39 TEMPLATE_DIR='templates' |
39 TEMPLATE_DIR='templates' |
40 TEMPLATE_EXT='html' |
40 TEMPLATE_EXT='html' |
41 |
41 |
42 logging.basicConfig( |
42 logging.basicConfig( |
43 level=logging.INFO, |
43 level=logging.INFO, |
44 format="%(name)8s %(levelname)8s %(lineno)3d %(message)s", |
44 format="%(message)s", |
|
45 # format="%(name)8s %(levelname)8s %(lineno)3d %(message)s", |
45 |
46 |
46 ) |
47 ) |
47 |
48 |
48 tpl = logging.getLogger('tpl') |
49 tpl = logging.getLogger('tpl') |
49 index = logging.getLogger('index') |
50 index = logging.getLogger('index') |
50 prepare = logging.getLogger('prepare') |
|
51 render = logging.getLogger('render') |
51 render = logging.getLogger('render') |
52 |
52 |
53 tpl.setLevel(logging.WARNING) |
53 tpl.setLevel(logging.WARNING) |
54 |
54 |
55 #for l in (tpl, index, prepare, render) : |
55 #for l in (tpl, index, prepare, render) : |
237 |
237 |
238 # recurse into subdirs, but not thumbs/previews |
238 # recurse into subdirs, but not thumbs/previews |
239 if os.path.isdir(fpath) and fname not in (THUMB_DIR, PREVIEW_DIR) : |
239 if os.path.isdir(fpath) and fname not in (THUMB_DIR, PREVIEW_DIR) : |
240 index.debug("Found subdir %s", fpath) |
240 index.debug("Found subdir %s", fpath) |
241 f = self.subdirs[fname] = Folder(fname, self) |
241 f = self.subdirs[fname] = Folder(fname, self) |
242 f.index(next_filter) # recursion |
242 if f.index(next_filter) : # recursion |
|
243 # if a subdir is alive, we are alive as well |
|
244 self.alive = True |
243 |
245 |
244 # handle images |
246 # handle images |
245 elif os.path.isfile(fpath) and isImage(fname) : |
247 elif os.path.isfile(fpath) and isImage(fname) : |
246 index.debug("Found image %s", fname) |
248 index.debug("Found image %s", fname) |
247 self.images[fname] = Image(self, fname) |
249 self.images[fname] = Image(self, fname) |
248 |
250 |
249 # ignore everything else |
251 # ignore everything else |
250 else : |
252 else : |
251 index.debug("Ignoring file %s", fname) |
253 index.debug("Ignoring file %s", fname) |
252 |
254 |
253 def prepare (self) : |
255 # sort and link the images |
254 """ |
|
255 Prepare the dir, i.e. sort+prepare the images, as well as recurse |
|
256 into subdirs |
|
257 """ |
|
258 |
|
259 prepare.info("Preparing dir %s", self.path) |
|
260 |
|
261 # is this folder non-empty? |
|
262 alive = False |
|
263 |
|
264 # only create thumbs/previews dirs if we have images in here |
|
265 if self.images : |
256 if self.images : |
266 # folder is non-empty |
257 self.alive = True |
267 alive = True |
258 |
268 prepare.info("Have %d images", len(self.images)) |
|
269 |
|
270 # create the thumb/preview dirs if needed |
|
271 for dir in (THUMB_DIR, PREVIEW_DIR) : |
|
272 prepare.debug("Checking for existance of %s dir", dir) |
|
273 path = self.pathFor(dir) |
|
274 |
|
275 if not os.path.isdir(path) : |
|
276 prepare.info("Creating dir %s", path) |
|
277 os.mkdir(path) |
|
278 |
|
279 # sort the images |
259 # sort the images |
280 fnames = self.images.keys() |
260 fnames = self.images.keys() |
281 fnames.sort() |
261 fnames.sort() |
282 |
262 |
283 prev = None |
263 prev = None |
284 |
264 |
285 # link them together and prepare them |
265 # link |
286 for fname in fnames : |
266 for fname in fnames : |
287 img = self.images[fname] |
267 img = self.images[fname] |
288 |
268 |
289 prepare.debug("Linking %s <-> %s", prev, img) |
|
290 |
|
291 img.prev = prev |
269 img.prev = prev |
292 |
270 |
293 if prev : |
271 if prev : |
294 prev.next = img |
272 prev.next = img |
295 |
273 |
296 prev = img |
274 prev = img |
297 |
|
298 img.prepare() |
|
299 |
275 |
300 # add to the sorted images list |
276 # add to the sorted images list |
301 self.sorted_images.append(img) |
277 self.sorted_images.append(img) |
302 |
278 |
303 # prepare subdirs |
279 return self.alive |
304 if self.subdirs : |
|
305 prepare.info("Have %d subdirs", len(self.subdirs)) |
|
306 |
|
307 # just recurse into them, we're alive if one of them is |
|
308 for dir in self.subdirs.itervalues() : |
|
309 if dir.prepare() : |
|
310 alive = True |
|
311 |
|
312 # figure out our title |
|
313 title_path = self.pathFor(TITLE_FILE) |
|
314 |
|
315 title, descr = readTitleDescr(title_path) |
|
316 |
|
317 if title : |
|
318 prepare.info("Found title/descr") |
|
319 self.title = title |
|
320 self.descr = descr |
|
321 alive = True |
|
322 |
|
323 # default title for the root dir |
|
324 elif self.name == '.' : |
|
325 self.title = 'Index' |
|
326 |
|
327 else : |
|
328 self.title = self.name |
|
329 |
|
330 prepare.debug("Our title is '%s'", self.title) |
|
331 |
|
332 # lol ded |
|
333 if not alive : |
|
334 prepare.info("Dir %s is not alive", self.path) |
|
335 |
|
336 self.alive = alive |
|
337 |
|
338 return alive |
|
339 |
280 |
340 def getObjInfo (self) : |
281 def getObjInfo (self) : |
341 """ |
282 """ |
342 Metadata for shorturls2.db |
283 Metadata for shorturls2.db |
343 """ |
284 """ |
396 |
337 |
397 # if this dir's contents were filtered out, then we can't render the index.html, as we aren't aware of all the images in here |
338 # if this dir's contents were filtered out, then we can't render the index.html, as we aren't aware of all the images in here |
398 if self.filtered : |
339 if self.filtered : |
399 render.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path) |
340 render.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path) |
400 |
341 |
401 else : |
342 else : |
|
343 # create the thumb/preview dirs if needed |
|
344 for dir in (THUMB_DIR, PREVIEW_DIR) : |
|
345 path = self.pathFor(dir) |
|
346 |
|
347 if not os.path.isdir(path) : |
|
348 render.info("Creating dir %s", path) |
|
349 os.mkdir(path) |
|
350 |
|
351 # figure out our title |
|
352 title_path = self.pathFor(TITLE_FILE) |
|
353 |
|
354 title, descr = readTitleDescr(title_path) |
|
355 |
|
356 if title : |
|
357 self.title = title |
|
358 self.descr = descr |
|
359 |
|
360 # default title for the root dir |
|
361 elif self.name == '.' : |
|
362 self.title = 'Index' |
|
363 |
|
364 else : |
|
365 self.title = self.name |
|
366 |
402 # sort the subdirs |
367 # sort the subdirs |
403 subdirs = self.subdirs.items() |
368 subdirs = self.subdirs.items() |
404 subdirs.sort() |
369 subdirs.sort() |
405 |
370 |
406 # generate the <a href=""></a>'s for the subdirs |
371 # generate the <a href=""></a>'s for the subdirs |
520 |
485 |
521 # what to use in the rendered templates, intended to be overridden by subclasses |
486 # what to use in the rendered templates, intended to be overridden by subclasses |
522 self.series_act = "add" |
487 self.series_act = "add" |
523 self.series_verb = "Add to" |
488 self.series_verb = "Add to" |
524 |
489 |
525 def prepare (self) : |
490 def getObjInfo (self) : |
526 """ |
491 """ |
527 Generate the thumbnail/preview views if needed, get the image info, and look for the title |
492 Metadata for shorturl2.db |
528 """ |
493 """ |
529 |
494 return 'img', self.dir.path, self.name |
530 prepare.info("Preparing image %s", self.path) |
495 |
|
496 def thumbImgTag (self) : |
|
497 """ |
|
498 a <a><img /></a> of this image's thumbnail. Path relative to directory we are in |
|
499 """ |
|
500 return link(self.html_name, "<img src='%s' alt='%s' title='%s' />" % (os.path.join(THUMB_DIR, self.name), self.descr, self.title)) |
|
501 |
|
502 def previewImgTag (self) : |
|
503 """ |
|
504 a <a><img /></a> of this image's preview. Path relative to directory we are in |
|
505 """ |
|
506 return link(self.name, "<img src='%s' alt='%s' title='%s' />" % (os.path.join(PREVIEW_DIR, self.name), self.descr, self.title)) |
|
507 |
|
508 def linkTag (self) : |
|
509 """ |
|
510 a <a></a> text-link to this image |
|
511 """ |
|
512 return link(self.html_name, self.title) |
|
513 |
|
514 def breadcrumb (self) : |
|
515 """ |
|
516 Returns a [(fname, title)] list of this image's parents |
|
517 """ |
|
518 |
|
519 f = self.dir |
|
520 b = [(self.html_name, self.title)] |
|
521 d = 0 |
|
522 |
|
523 while f : |
|
524 b.insert(0, (dirUp(d), f.title)) |
|
525 |
|
526 d += 1 |
|
527 f = f.parent |
|
528 |
|
529 return b |
|
530 |
|
531 def render (self) : |
|
532 """ |
|
533 Write out the .html file |
|
534 """ |
531 |
535 |
532 # stat the image file to get the filesize and mtime |
536 # stat the image file to get the filesize and mtime |
533 st = os.stat(self.path) |
537 st = os.stat(self.path) |
534 |
538 |
535 self.filesize = st.st_size |
539 self.filesize = st.st_size |
541 self.img_size = img.size |
545 self.img_size = img.size |
542 |
546 |
543 for out_path, geom in ((self.thumb_path, THUMB_GEOM), (self.preview_path, PREVIEW_GEOM)) : |
547 for out_path, geom in ((self.thumb_path, THUMB_GEOM), (self.preview_path, PREVIEW_GEOM)) : |
544 # if it doesn't exist, or it's older than the image itself, generate |
548 # if it doesn't exist, or it's older than the image itself, generate |
545 if not (os.path.exists(out_path) and os.stat(out_path).st_mtime > self.timestamp) : |
549 if not (os.path.exists(out_path) and os.stat(out_path).st_mtime > self.timestamp) : |
546 prepare.info("Create thumbnailed image at %s with geom %s", out_path, geom) |
550 render.info("Create thumbnailed image at %s with geom %s", out_path, geom) |
547 |
551 |
548 # XXX: is this the most efficient way to do this? |
552 # XXX: is this the most efficient way to do this? |
549 out_img = img.copy() |
553 out_img = img.copy() |
550 out_img.thumbnail(geom, resample=True) |
554 out_img.thumbnail(geom, resample=True) |
551 out_img.save(out_path) |
555 out_img.save(out_path) |
552 |
556 |
553 # look for the metadata file |
557 # look for the metadata file |
554 title_path = self.dir.pathFor(self.base_name + '.txt') |
558 title_path = self.dir.pathFor(self.base_name + '.txt') |
555 prepare.debug("Looking for title at %s", title_path) |
|
556 |
559 |
557 title, descr = readTitleDescr(title_path) |
560 title, descr = readTitleDescr(title_path) |
558 |
561 |
559 if title : |
562 if title : |
560 self.title = title |
563 self.title = title |
561 self.descr = descr |
564 self.descr = descr |
562 |
|
563 prepare.info("Found title `%s'", self.title) |
|
564 |
|
565 def getObjInfo (self) : |
|
566 """ |
|
567 Metadata for shorturl2.db |
|
568 """ |
|
569 return 'img', self.dir.path, self.name |
|
570 |
|
571 def thumbImgTag (self) : |
|
572 """ |
|
573 a <a><img /></a> of this image's thumbnail. Path relative to directory we are in |
|
574 """ |
|
575 return link(self.html_name, "<img src='%s' alt='%s' title='%s' />" % (os.path.join(THUMB_DIR, self.name), self.descr, self.title)) |
|
576 |
|
577 def previewImgTag (self) : |
|
578 """ |
|
579 a <a><img /></a> of this image's preview. Path relative to directory we are in |
|
580 """ |
|
581 return link(self.name, "<img src='%s' alt='%s' title='%s' />" % (os.path.join(PREVIEW_DIR, self.name), self.descr, self.title)) |
|
582 |
|
583 def linkTag (self) : |
|
584 """ |
|
585 a <a></a> text-link to this image |
|
586 """ |
|
587 return link(self.html_name, self.title) |
|
588 |
|
589 def breadcrumb (self) : |
|
590 """ |
|
591 Returns a [(fname, title)] list of this image's parents |
|
592 """ |
|
593 |
|
594 f = self.dir |
|
595 b = [(self.html_name, self.title)] |
|
596 d = 0 |
|
597 |
|
598 while f : |
|
599 b.insert(0, (dirUp(d), f.title)) |
|
600 |
|
601 d += 1 |
|
602 f = f.parent |
|
603 |
|
604 return b |
|
605 |
|
606 def render (self) : |
|
607 """ |
|
608 Write out the .html file |
|
609 """ |
|
610 |
565 |
611 render.info("Rendering image %s", self.path) |
566 render.info("Rendering image %s", self.path) |
612 |
567 |
613 image_tpl.renderTo(self.html_path, |
568 image_tpl.renderTo(self.html_path, |
614 STYLE_URL=self.dir.inRoot('style.css'), |
569 STYLE_URL=self.dir.inRoot('style.css'), |
719 |
674 |
720 index.debug('Filter: %s', root_filter) |
675 index.debug('Filter: %s', root_filter) |
721 |
676 |
722 root = Folder() |
677 root = Folder() |
723 root.index(root_filter) |
678 root.index(root_filter) |
724 root.prepare() |
|
725 updateShorturlDb(root) |
679 updateShorturlDb(root) |
726 root.render() |
680 root.render() |
727 |
681 |
728 def fmtFilesize (size) : |
682 def fmtFilesize (size) : |
729 return utils.formatbytes(size, forcekb=False, largestonly=True, kiloname='KiB', meganame='MiB', bytename='B', nospace=False) |
683 return utils.formatbytes(size, forcekb=False, largestonly=True, kiloname='KiB', meganame='MiB', bytename='B', nospace=False) |