emin

Mon, 09 May 2011 15:15:59 +0100

author
Andy Buckley <andy@insectnation.org>
date
Mon, 09 May 2011 15:15:59 +0100
changeset 20
1c024e55880c
parent 17
d1377fc46e5d
child 21
71e18d3b1685
permissions
-rwxr-xr-x

Added tag emin-0.3.2 for changeset 14161f1492a4

andy@1 1 #! /usr/bin/env python
andy@1 2 # -*- python -*-
andy@1 3
andy@14 4 """%prog [opts] dir [outdir]
andy@3 5
andy@14 6 emin - a static web gallery builder
andy@3 7
andy@3 8 by Andy Buckley
andy@3 9 http://www.insectnation.org
andy@3 10
andy@14 11 This is a weeny script for making static sets of Web pages for presenting lots
andy@14 12 of imagey things: photos, PDFs, graphs...
andy@3 13
andy@14 14 As for the name, this is a program to make pretty crappy galleries, so it's
andy@14 15 named after a pretty crappy artist. And, thankfully, e-m-i-n is not many
andy@14 16 characters to type (and they're all close together on the Colemak keyboard
andy@14 17 layout) --- trebles all round!
andy@3 18
andy@3 19 TODO:
andy@4 20 * Try to import BeautifulSoup for validating/pretty-printing the output
andy@14 21 * Add all on one page option
andy@11 22 * Resize option
andy@11 23 * Rename option
andy@13 24 * Crop-to-thumb option
andy@16 25 * Auto-rotate by EXIF orientation
andy@13 26 * Copy Lightbox stuff into place
andy@6 27 * Allow complete rollback if any failure (or on demand?)
andy@3 28 """
andy@2 29
andy@17 30 __version__ = "0.3.1"
andy@14 31
andy@3 32
andy@5 33 import logging
andy@2 34 from optparse import OptionParser, OptionGroup
andy@14 35 parser = OptionParser(usage=__doc__, version="%prog " + __version__)
andy@14 36 parser.add_option("-t", "--title", dest="TITLE", default="",
andy@5 37 help="title of this gallery")
andy@14 38 parser.add_option("--template", dest="TEMPLATE", default=None,
andy@5 39 help="specify the template file to be used for the index pages")
andy@14 40 parser.add_option("--zipfile", dest="ZIPFILE", default=None,
andy@5 41 help="name of zip archive file. Default is based on the title.")
andy@6 42 parser.add_option("--no-zipfile", action="store_false",
andy@14 43 dest="WRITE_ZIPFILE", default=True,
andy@5 44 help="disable writing out of a zipped archive of photos from this gallery")
andy@14 45 ## TODO: Add all on one page option
andy@5 46 parser.add_option("-c", "--num-cols", dest="NUM_COLS", default=5, type=int,
andy@5 47 help="max number of thumbnail columns on one page (default: 5)")
andy@5 48 parser.add_option("-r", "--num-rows", dest="NUM_ROWS", default=6, type=int,
andy@5 49 help="max number of thumbnail rows on one page (default: 6). Set < 1 for unlimited (i.e. all on one page)")
andy@5 50 parser.add_option("--thumb-height", dest="THUMB_HEIGHT", default=150, type=int,
andy@5 51 help="thumbnail height, in pixels (default: 100)")
andy@5 52 parser.add_option("--max-imgsize", dest="MAX_IMGSIZE", default=800, type=int,
andy@5 53 help="max large image dimension in pixels (default: 800)")
andy@14 54 parser.add_option("--no-js", dest="USE_JS", action="store_false", default=True,
andy@5 55 help="disable use of funky JavaScript display stuff")
andy@14 56 parser.add_option("--force", dest="FORCE", action="store_true", default=False,
andy@5 57 help="force creation of gallery: regen thumbnails etc.")
andy@14 58 parser.add_option("--no-table", dest="USE_TABLE", action="store_false", default=True,
andy@5 59 help="don't use an HTML table for thumbnail presentation: just let the thumbs flow into the browser window")
andy@5 60 verbgroup = OptionGroup(parser, "Verbosity control")
andy@16 61 verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
andy@5 62 default=logging.INFO, help="print debug (very verbose) messages")
andy@16 63 verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
andy@5 64 default=logging.INFO, help="be very quiet")
andy@5 65 parser.add_option_group(verbgroup)
andy@3 66 opts, args = parser.parse_args()
andy@5 67 logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
andy@1 68
andy@1 69
andy@3 70 ## More stdlib imports
andy@5 71 import sys, os, glob, re, commands, math, shutil
andy@5 72 import traceback
andy@3 73
andy@3 74
andy@5 75 ## TODO: These should be options...
andy@5 76 opts.RENAME = False
andy@5 77 opts.CONVERT = False
andy@5 78
andy@5 79
andy@5 80 ## Set processing/output dir
andy@9 81 if len(args) < 1 or len(args) > 2:
andy@9 82 print parser.show_usage()
andy@9 83 exit(1)
andy@9 84 if len(args) >= 1:
andy@9 85 opts.SRCDIR = os.path.normpath(args[0])
andy@9 86 opts.OUTDIR = os.path.normpath(args[0])
andy@9 87 if len(args) == 2:
andy@9 88 opts.OUTDIR = os.path.normpath(args[1])
andy@5 89
andy@5 90
andy@5 91 ## Try to import Cheetah templating
andy@5 92 try:
andy@8 93 from Cheetah.Template import Template
andy@5 94 except Exception, e:
andy@9 95 logging.error("Couldn't import required Cheetah package")
andy@9 96 exit(1)
andy@5 97
andy@2 98 ## Try to import Python Imaging Library
andy@2 99 try:
andy@5 100 import PIL.Image as PILI
andy@2 101 except Exception, e:
andy@5 102 logging.error("Couldn't import required Python Imaging Library package")
andy@9 103 exit(1)
andy@2 104
andy@2 105
andy@3 106 def safeencode(s):
andy@2 107 """Encode a string for use as a filename."""
andy@3 108 newstr = s.replace(" ", "-").replace(",", "").replace("/", "").replace(".", "")
andy@3 109 return newstr
andy@1 110
andy@5 111 logging.debug("Title: %s" % opts.TITLE)
andy@5 112 logging.debug("Thumb height: %d" % opts.THUMB_HEIGHT)
andy@5 113
andy@1 114
andy@9 115 class ImageInfo(object):
andy@6 116 def __init__(self):
andy@9 117 self.name = None
andy@6 118 self.path = None
andy@9 119 self.thumbname = None
andy@9 120 self.thumbpath = None
andy@9 121 self.thumbx = None
andy@9 122 self.thumby = None
andy@9 123
andy@9 124 def setsize(self, sizetuple):
andy@9 125 self.thumbx = sizetuple[0]
andy@9 126 self.thumby = sizetuple[1]
andy@9 127
andy@7 128 def _getsize(self):
andy@9 129 return self.thumbx, self.thumby
andy@9 130
andy@9 131 thumbsize = property(_getsize, setsize)
andy@6 132
andy@6 133
andy@2 134 ## Go to the gallery directory and test if it's writeable
andy@2 135 if not os.access(opts.OUTDIR, os.W_OK):
andy@9 136 try:
andy@9 137 logging.info("Making output dir in %s" % opts.OUTDIR)
andy@9 138 os.makedirs(opts.OUTDIR)
andy@9 139 except Exception, e:
andy@9 140 logging.error("Problem when making output dir %s... exiting" % opts.OUTDIR)
andy@9 141 #traceback.print_exc()
andy@9 142 exit(1)
andy@1 143
andy@14 144
andy@9 145 ## Make thumbnail directory if needed
andy@9 146 opts.THUMBDIR = "thumbs"
andy@9 147 THUMBDIR = os.path.join(opts.OUTDIR, opts.THUMBDIR)
andy@5 148 try:
andy@9 149 if not os.path.isdir(THUMBDIR):
andy@9 150 logging.info("Making thumbs dir in %s" % THUMBDIR)
andy@9 151 os.makedirs(THUMBDIR)
andy@5 152 except Exception, e:
andy@5 153 logging.error("Problem when making thumbnails dir... exiting")
andy@5 154 #traceback.print_exc()
andy@9 155 exit(1)
andy@5 156
andy@2 157
andy@9 158 ## Build the list of pictures to display
andy@9 159 ## TODO: types: PNG/GIF, JPEG, PDF
andy@9 160 ## TODO: match formats & store thumb filenames
andy@9 161 EXTENSIONS = \
andy@9 162 ["*.jpg", "*.jpeg"] + \
andy@9 163 ["*.png", "*.gif"] + \
andy@9 164 ["*.tif", "*.tiff"] + \
andy@9 165 ["*.eps", "*.pdf"]
andy@9 166 imgs = []
andy@9 167 import fnmatch
andy@9 168 for img in os.listdir(opts.SRCDIR):
andy@9 169 for e in EXTENSIONS:
andy@12 170 if fnmatch.fnmatch(img.lower(), e):
andy@9 171 imgpath = os.path.join(opts.SRCDIR, img)
andy@9 172 imgs.append(imgpath)
andy@9 173 break
andy@9 174
andy@3 175 ## Count the pictures
andy@9 176 logging.debug("Number of pictures = %d" % len(imgs))
andy@9 177 if len(imgs) == 0:
andy@2 178 logging.debug("No pictures from which to build a gallery...")
andy@9 179 exit(2)
andy@9 180 logging.debug("Images: " + str(sorted(imgs)))
andy@2 181
andy@5 182
andy@9 183 ## Rename/move if needed
andy@9 184 outimgs = []
andy@9 185 for n, imgpath in enumerate(imgs):
andy@9 186 imgname = os.path.basename(imgpath)
andy@9 187 imgnameparts = os.path.splitext(imgname)
andy@9 188 targetname = imgname
andy@9 189 if opts.RENAME:
andy@9 190 targetname = "%s-%03d%s" % (safename(opts.OUTDIR), n, imgnameparts[1])
andy@9 191 targetpath = os.path.join(opts.OUTDIR, targetname)
andy@9 192 outimgs.append(targetpath)
andy@9 193 if imgpath != targetpath:
andy@9 194 logging.debug("Copying %s -> %s" % (imgpath, targetpath))
andy@9 195 import shutil
andy@9 196 shutil.copy(imgpath, targetpath)
andy@9 197
andy@9 198
andy@9 199 ## Store some image info
andy@9 200 imgsinfo = {}
andy@9 201 for picpath in outimgs:
andy@9 202 picname = os.path.basename(picpath)
andy@9 203 picbase = os.path.splitext(picname)[0]
andy@9 204
andy@9 205 ## Convert EPS, PDF, TIFF to Web-viewable formats
andy@9 206 picversions = {}
andy@9 207 picpathparts = os.path.splitext(picpath)
andy@9 208 picnameparts = os.path.splitext(picname)
andy@9 209 extn = picnameparts[1].lower()
andy@9 210 convcmd = None
andy@9 211 if extn in [".tif", ".tiff"]:
andy@9 212 picversions["TIFF"] = picname
andy@9 213 newpicname = picname + ".jpg"
andy@9 214 newpicpath = picpath + ".jpg"
andy@9 215 picversions["JPG"] = newpicname
andy@9 216 convcmd = ["convert", picpath, newpicpath]
andy@9 217 picname = newpicname
andy@9 218 picpath = newpicpath
andy@9 219 elif extn in [".eps", ".pdf"]:
andy@9 220 picversions[extn[1:].upper()] = picname
andy@9 221 newpicname = picname + ".png"
andy@9 222 newpicpath = picpath + ".png"
andy@9 223 picversions["PNG"] = newpicname
andy@10 224 convcmd = ["convert", "-density", "200", "-resize", "800x700", picpath, newpicpath]
andy@9 225 picname = newpicname
andy@9 226 picpath = newpicpath
andy@9 227 else:
andy@9 228 picversions[extn[1:].upper()] = picname
andy@9 229
andy@9 230 ## Do the conversion
andy@9 231 if convcmd:
andy@9 232 try:
andy@9 233 import subprocess
andy@9 234 subprocess.check_call(convcmd)
andy@9 235 except:
andy@9 236 raise
andy@9 237
andy@9 238 ## Main pic info
andy@9 239 info = ImageInfo()
andy@9 240 info.name = picname
andy@9 241 info.path = picpath
andy@9 242 info.versions = picversions
andy@9 243
andy@9 244 ## Thumb info
andy@9 245 ## TODO: Un-hard-code PNG thumb format
andy@9 246 thumbname = picname + ".png"
andy@9 247 thumbpath = os.path.join(THUMBDIR, thumbname)
andy@9 248 info.thumbname = thumbname
andy@9 249 info.thumbpath = thumbpath
andy@9 250
andy@9 251 ## Make thumbnail
andy@9 252 ## TODO: Be lazy!
andy@9 253 #if opts.FORCE or not os.access(thumbpath, os.R_OK) or os.stat(thumbpath).st_mtime > os.stat(pic).st_mtime:
andy@9 254 try:
andy@9 255 logging.debug("Making new thumbnail %s for %s (max height %d)" % \
andy@9 256 (thumbpath, picname, opts.THUMB_HEIGHT))
andy@9 257 thumbimg = PILI.open(picpath, "r")
andy@9 258 thumbimg.thumbnail((100000000, opts.THUMB_HEIGHT), resample=PILI.ANTIALIAS)
andy@9 259 thumbimg.save(thumbpath)
andy@9 260 info.thumbsize = thumbimg.size
andy@9 261 except Exception, e:
andy@9 262 logging.warning("Problem when making thumbnail from %s... exiting" % picpath)
andy@9 263 #traceback.print_exc()
andy@9 264 exit(1)
andy@9 265
andy@9 266 ## Store info
andy@9 267 imgsinfo[picname] = info
andy@9 268
andy@9 269
andy@9 270 #####################
andy@9 271
andy@5 272
andy@3 273 ## Calculate how many pages will be needed
andy@3 274 ## TODO: allow all on one page
andy@6 275 NUM_PER_PAGE = opts.NUM_ROWS * opts.NUM_COLS
andy@9 276 NUM_PAGES = int(math.ceil( len(imgs)/float(NUM_PER_PAGE) ))
andy@1 277
andy@1 278
andy@14 279 ## TODO: Move HTML extension-setting to option parser
andy@6 280 ## (or take from template name, e.g. page.html.template -> html)
andy@6 281 opts.EXTN = "html"
andy@6 282
andy@6 283
andy@3 284 def getPageFilename(pagenum):
andy@9 285 if pagenum == 1:
andy@3 286 pagefile = "index.%s" % opts.EXTN
andy@3 287 else:
andy@3 288 pagefile = "index%02d.%s" % (pagenum, opts.EXTN)
andy@8 289 return pagefile
andy@3 290
andy@3 291
andy@3 292 def mkPageLinkStr(pagenum):
andy@14 293 "Write the linked page list"
andy@3 294 global NUM_PAGES
andy@14 295 out = ''
andy@3 296 if NUM_PAGES > 1:
andy@6 297 out += ""
andy@3 298 ## Previous
andy@3 299 prev = pagenum - 1
andy@3 300 if prev > 0:
andy@14 301 out += '<a href="%s">prev</a>' % getPageFilename(prev)
andy@3 302 else:
andy@14 303 out += 'prev'
andy@14 304 out += '&nbsp;'
andy@3 305 ## Numbers
andy@14 306 for n in range(1, NUM_PAGES+1):
andy@3 307 if n != pagenum:
andy@14 308 out += '<a href="%s">%d</a>' % (getPageFilename(n), n)
andy@14 309 else:
andy@14 310 out += "%d" % n
andy@14 311 out += '&nbsp;'
andy@3 312 ## Next
andy@3 313 next = pagenum + 1
andy@3 314 if next <= NUM_PAGES:
andy@14 315 out += '<a href="%s">next</a>' % getPageFilename(next)
andy@3 316 else:
andy@14 317 out += 'next'
andy@3 318 return out
andy@3 319
andy@3 320
andy@9 321 ## Make a zip archive
andy@9 322 ZIPFILE = "photo-album.zip"
andy@9 323 if True: #opts.WRITE_ZIPFILE:
andy@3 324 logging.debug("Making zipped picture archive")
andy@6 325 if opts.ZIPFILE is not None:
andy@6 326 ZIPFILE = opts.ZIPFILE
andy@6 327 elif opts.TITLE is not None or len(opts.TITLE) > 0:
andy@3 328 ZIPFILE = safeencode(opts.TITLE)
andy@8 329 #ZIPFILE = safename(opts.OUTDIR)
andy@9 330 if not "." in ZIPFILE or os.path.splitextn(ZIPFILE)[1] != ".zip":
andy@6 331 ZIPFILE += ".zip"
andy@9 332 ## Do the zipping
andy@13 333 if ZIPFILE:
andy@13 334 from zipfile import ZipFile
andy@13 335 zf = ZipFile(os.path.join(opts.OUTDIR, ZIPFILE), "w")
andy@13 336 for img in imgs:
andy@13 337 zf.write(img, os.path.basename(img))
andy@13 338 zf.close()
andy@13 339 else:
andy@13 340 logging.warning("No zip file made because zip filename is empty")
andy@3 341
andy@3 342
andy@9 343 ## Copy Lightbox stuff into place
andy@9 344 #if opts.USE_JS:
andy@9 345 # from zipfile import ZipFile
andy@9 346 # zf = ZipFile(os.path.join(opts.OUTDIR, "lightbox.zip"), "r")
andy@9 347 # for img in imgs:
andy@9 348 # zf.write(img, os.path.basename(img))
andy@9 349 # zf.close()
andy@14 350
andy@9 351
andy@9 352 ## Default template
andy@9 353 tmplstr = \
andy@9 354 """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
andy@9 355 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
andy@9 356 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
andy@9 357 <head>
andy@13 358 #set title = $PAGETITLE
andy@13 359 #if $NUM_PAGES > 1
andy@13 360 #set title = $title + " (page %s)" % $PAGENUM
andy@13 361 #end if
andy@9 362 <title>$title</title>
andy@9 363 <style>
andy@13 364 img { border:0; padding:10 10 0 0; }
andy@9 365 body { padding:1em; background:white; font-family:sans-serif; }
andy@9 366 h1 { font-family:sans-serif; }
andy@13 367 a.format { text-decoration:none; font-variant:small-caps; color:grey; font-size:small; }
andy@13 368 a.format:hover { color:deeppink; }
andy@13 369 a.format:active { color:deeppink; }
andy@14 370 .pagelinks { text-decoration:none; font-variant:small-caps; color:grey; margin-top:1em; margin-bottom:1em; }
andy@14 371 .pagelinks a:link { color:#22c; text-decoration:none; }
andy@14 372 .pagelinks a:hover { color:#55c; text-decoration:none; }
andy@14 373 .pagelinks a:active { color:#55c; text-decoration:none; }
andy@9 374 </style>
andy@9 375 #if $OPTS.USE_JS:
andy@14 376 <link rel="stylesheet" href="lightbox/css/lightbox.css" type="text/css" media="screen" />
andy@9 377 <script src="lightbox/js/prototype.js" type="text/javascript"></script>
andy@9 378 <script src="lightbox/js/scriptaculous.js?load=effects,builder" type="text/javascript"></script>
andy@9 379 <script src="lightbox/js/lightbox.js" type="text/javascript"></script>
andy@9 380 #end if
andy@9 381 </head>
andy@9 382 <body>
andy@9 383 <h1>$PAGETITLE</h1>
andy@9 384 #if $NUM_PAGES > 1
andy@9 385 <div class="pagelinks">Pages: $LINKSTR</div>
andy@9 386 #end if
andy@9 387
andy@9 388 <table>
andy@9 389 <tr>
andy@9 390 #set jsrel = ''
andy@9 391 #if $OPTS.USE_JS:
andy@9 392 #set jsrel = 'rel="lightbox[emin]"'
andy@9 393 #end if
andy@9 394 #for n, thumb in enumerate($PAGEPICS)
andy@9 395 #if $n % $NUM_COLS == 0 and $n not in (0, len($PAGEPICS)-1)
andy@9 396 <tr/><tr>
andy@9 397 #end if
andy@9 398 #set info = $PICINFO[$thumb]
andy@9 399 <td>
andy@9 400 <a href="$info.relpath" $jsrel>
andy@9 401 <img alt="$thumb" src="$info.relthumbpath" style="border:0;" width="$info.thumbx" height="$info.thumby" />
andy@9 402 </a><br/>
andy@9 403 #for fmt, name in $info.versions.iteritems()
andy@13 404 <a class="format" href="$name">$fmt.lower()</a>
andy@9 405 #end for
andy@9 406 </td>
andy@9 407 #end for
andy@9 408 </tr>
andy@9 409 </table>
andy@9 410
andy@9 411 #if $NUM_PAGES > 1
andy@9 412 <div class="pagelinks">Pages: $LINKSTR</div>
andy@9 413 #end if
andy@9 414
andy@13 415 #if $OPTS.WRITE_ZIPFILE and $ZIPFILE:
andy@9 416 <p>All zipped up: <a href="$ZIPFILE">$ZIPFILE</a></p>
andy@9 417 #end if
andy@9 418 </body>
andy@9 419 </html>
andy@9 420 """
andy@9 421
andy@9 422
andy@9 423 ## Override default template with a template file
andy@9 424 if opts.TEMPLATE is not None:
andy@9 425 logging.info("Using index template file %s" % opts.TEMPLATE)
andy@9 426 tf = open(opts.TEMPLATE, "r")
andy@9 427 tmplstr = tf.read()
andy@9 428 tf.close()
andy@8 429
andy@8 430
andy@3 431 ## Make each index page
andy@3 432 for n in range(NUM_PAGES):
andy@6 433 PAGENUM = n + 1
andy@3 434
andy@3 435 ## Choose and open page file
andy@14 436 PAGEFILE = getPageFilename(PAGENUM)
andy@9 437 PAGEPATH = os.path.join(opts.OUTDIR, PAGEFILE)
andy@8 438
andy@3 439 ## Write the title
andy@9 440 PAGETITLE = opts.TITLE or os.path.basename(opts.SRCDIR)
andy@14 441
andy@3 442 ## Write the linked page list
andy@8 443 LINKSTR = mkPageLinkStr(PAGENUM)
andy@14 444
andy@9 445 ## Work out the picture offsets for this page
andy@3 446 pics_start = n * NUM_PER_PAGE
andy@3 447 pics_end = (n+1) * NUM_PER_PAGE - 1
andy@9 448 if pics_end >= len(imgs):
andy@9 449 pics_end = len(imgs) - 1
andy@1 450
andy@16 451 PAGEPICS = sorted(imgsinfo.keys())[pics_start: pics_end+1]
andy@9 452 PAGEPICNUMS = range(len(PAGEPICS))
andy@9 453 relthumbdir = opts.THUMBDIR
andy@9 454 #relthumbdir = os.path.relpath(THUMBDIR, OUTDIR)
andy@9 455 reloutdir = "."
andy@9 456 for k in imgsinfo.keys():
andy@9 457 imgsinfo[k].relthumbpath = os.path.normpath(os.path.join(relthumbdir, imgsinfo[k].thumbname))
andy@9 458 imgsinfo[k].relpath = os.path.normpath(os.path.join(reloutdir, imgsinfo[k].name))
andy@9 459 PICINFO = imgsinfo
andy@9 460 # THUMBNAMES = [t.name for t in thumbsinfo.values()[pics_start : pics_end]]
andy@9 461 # print THUMBNAMES
andy@9 462 # THUMBPATHS = [os.path.join(relthumbdir, name) for name in THUMBNAMES]
andy@9 463 # print THUMBPATHS
andy@9 464 # THUMBDIMS = [t.size for t in thumbsinfo.values()[pics_start : pics_end]]
andy@1 465
andy@9 466 logging.info("Writing to index file %s" % PAGEPATH)
andy@9 467 f = open(PAGEPATH, "w")
andy@16 468 logging.debug("Images on page: %s" % PAGEPICS)
andy@8 469 tdict = {}
andy@8 470 tdict["NUM_PAGES"] = NUM_PAGES
andy@9 471 tdict["NUM_PER_PAGE"] = NUM_PER_PAGE
andy@9 472 tdict["NUM_ROWS"] = opts.NUM_ROWS
andy@9 473 tdict["NUM_COLS"] = opts.NUM_COLS
andy@8 474 tdict["PAGEPICS"] = PAGEPICS
andy@8 475 tdict["PAGENUM"] = PAGENUM
andy@8 476 tdict["PAGETITLE"] = PAGETITLE
andy@8 477 tdict["LINKSTR"] = LINKSTR
andy@8 478 tdict["PAGEPICNUMS"] = PAGEPICNUMS
andy@9 479 tdict["PICINFO"] = imgsinfo
andy@9 480 # tdict["THUMBS"] = thumbsinfo
andy@9 481 # tdict["THUMBNAMES"] = THUMBNAMES
andy@9 482 # tdict["THUMBPATHS"] = THUMBPATHS
andy@9 483 # tdict["THUMBDIMS"] = THUMBDIMS
andy@8 484 tdict["ZIPFILE"] = ZIPFILE
andy@8 485 tdict["OPTS"] = opts
andy@8 486 indexstr = Template(tmplstr, searchList=[tdict])
andy@9 487 #print indexstr
andy@8 488 f.write(str(indexstr))
andy@3 489 f.close()
andy@3 490
andy@3 491 ## It's over. Nothing to see here.
andy@3 492 logging.debug("All done!")

mercurial