--- a/degal.py Thu Jan 31 17:58:03 2008 +0000
+++ b/degal.py Thu Jan 31 19:13:00 2008 +0000
@@ -23,7 +23,7 @@
import os.path, os
from optparse import OptionParser
-from lib import folder, shorturl
+from lib import folder, shorturl, log
def main (dir='.', targets=()) :
root_filter = {}
@@ -36,11 +36,19 @@
f[path_part] = {}
f = f[path_part]
-
+
+ log.title("Indexing %s...", dir)
root = folder.Folder(dir)
root.index(root_filter)
+ log.up()
+
+ log.title("Syncing ShortURLs...")
shorturl.updateDB(root)
+ log.up()
+
+ log.title("Rendering updated dirs...")
root.render()
+ log.up()
if __name__ == '__main__' :
parser = OptionParser(usage="usage: %prog [options] ... [target ...]")
--- a/lib/folder.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/folder.py Thu Jan 31 19:13:00 2008 +0000
@@ -20,8 +20,7 @@
import os, os.path
-import settings, image, utils, helpers
-from log import index, render
+import settings, image, utils, helpers, log
from template import gallery as gallery_tpl
from helpers import url_for_page
@@ -91,8 +90,6 @@
method.
"""
- index.info("Indexing %s", self.path)
-
if filters :
self.filtered = True
@@ -103,7 +100,7 @@
# ignore dotfiles
if fname.startswith('.') :
- index.debug("Skipping dotfile %s", fname)
+ log.debug("Skipping dotfile %s", fname)
continue
# apply filters
@@ -111,7 +108,7 @@
if fname in filters :
next_filter = filters[fname]
else :
- index.debug("Skip `%s' as we have a filter", fname)
+ log.debug("Skip `%s' as we have a filter", fname)
continue
else :
next_filter = None
@@ -121,21 +118,25 @@
and (fname not in (settings.THUMB_DIR, settings.PREVIEW_DIR))
and (self.parent or fname not in settings.ROOT_IGNORE)
) :
- index.debug("Found subdir %s", fpath)
+ log.down(fname)
+
f = Folder(fname, self)
+
if f.index(next_filter) : # recursion
# if a subdir is alive, we are alive as well
self.subdirs[fname] = f
self.alive = True
+ log.up()
+
# handle images
elif os.path.isfile(fpath) and utils.isImage(fname) :
- index.debug("Found image %s", fname)
+ log.next(fname)
self.images[fname] = image.Image(self, fname)
# ignore everything else
else :
- index.debug("Ignoring file %s", fname)
+ log.debug("Ignoring file %s", fname)
# sort and link the images
if self.images :
@@ -178,7 +179,7 @@
self.title = self.name
if not self.alive :
- index.debug("Dir %s isn't alive" % self.path)
+ log.debug("Dir %s isn't alive" % self.path)
return self.alive
@@ -240,12 +241,19 @@
# ded folders are skipped
if not self.alive :
- render.info("Skipping dir %s (no images)", self.path)
+ # dead, skip, no output
return
+ index_mtime = utils.mtime(self.pathFor("index.html"))
+ dir_mtime = utils.mtime(self.path)
+
# 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
if self.filtered :
- render.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path)
+ log.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path)
+
+ elif index_mtime > dir_mtime :
+ # no changes, pass, ignored
+ pass
else :
# create the thumb/preview dirs if needed
@@ -253,15 +261,13 @@
path = self.pathFor(dir)
if not os.path.isdir(path) :
- render.info("Creating dir %s", path)
+ log.info("mkdir %s", dir)
os.mkdir(path)
# sort the subdirs
subdirs = self.subdirs.values()
subdirs.sort(key=lambda d: d.name)
- render.info("Rendering %s", self.path)
-
# paginate!
images = self.sorted_images
image_count = len(images)
@@ -274,9 +280,9 @@
pagination_required = len(pages) > 1
if pagination_required :
- render.info("Index split into %d pages of %d images each", len(pages), settings.IMAGE_COUNT)
+ log.info("%d pages @ %d images", len(pages), settings.IMAGE_COUNT)
elif not pages :
- render.info("Dir with no images, render for subdirs")
+ log.info("no images, render for subdirs")
pages = [[]]
for cur_page, images in enumerate(pages) :
@@ -302,12 +308,19 @@
shorturl = self.inRoot('s', shorturl),
shorturl_code = shorturl,
)
-
+
# render images
- for img in self.images.itervalues() :
+ image_count = len(self.sorted_images)
+ for i, img in enumerate(self.images.itervalues()) :
+ log.next("[%-4d/%4d] %s", i, image_count, img.name)
+
img.render()
# recurse into subdirs
for dir in self.subdirs.itervalues() :
+ log.down(dir.name)
+
dir.render()
-
+
+ log.up()
+
--- a/lib/image.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/image.py Thu Jan 31 19:13:00 2008 +0000
@@ -22,8 +22,7 @@
import PIL.Image
-import settings, utils
-from log import index, render
+import settings, utils, log
from template import image as image_tpl
class Image (object) :
@@ -104,13 +103,15 @@
for out_path, geom in ((self.thumb_path, settings.THUMB_GEOM), (self.preview_path, settings.PREVIEW_GEOM)) :
# if it doesn't exist, or it's older than the image itself, generate
- if not (os.path.exists(out_path) and os.stat(out_path).st_mtime > self.timestamp) :
- render.info("Create thumbnailed image at %s with geom %s", out_path, geom)
+ if utils.mtime(out_path) < self.timestamp :
+ log.info("render [%sx%s]", geom[0], geom[1], wait=True)
# XXX: is this the most efficient way to do this? It seems slow
out_img = img.copy()
out_img.thumbnail(geom, resample=True)
out_img.save(out_path)
+
+ log.done()
# look for the metadata file
title_path = self.dir.pathFor(self.base_name + '.txt')
@@ -119,31 +120,33 @@
if not self.title :
self.title = self.name
-
- render.info("Rendering image %s", self.path)
+
+ if utils.mtime(self.html_path) < self.timestamp :
+ log.info("render %s.html", self.name)
- image_tpl.render_to(self.html_path,
- stylesheet_url = self.dir.inRoot('style.css'),
- title = self.title,
- breadcrumb = self.breadcrumb(),
-
- prev = self.prev,
- next = self.next,
- img = self,
-
- description = self.descr,
-
- filename = self.name,
- img_size = self.img_size,
- file_size = self.filesize,
- timestamp = self.timestamp,
-
- shorturl = self.dir.inRoot('s', self.shorturl_code),
- shorturl_code = self.shorturl_code,
-
- series_url = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
- series_verb = self.series_verb,
- )
+ image_tpl.render_to(self.html_path,
+ stylesheet_url = self.dir.inRoot('style.css'),
+ title = self.title,
+ breadcrumb = self.breadcrumb(),
+
+ prev = self.prev,
+ next = self.next,
+ img = self,
+
+ description = self.descr,
+
+ filename = self.name,
+ img_size = self.img_size,
+ file_size = self.filesize,
+ timestamp = self.timestamp,
+
+ shorturl = self.dir.inRoot('s', self.shorturl_code),
+ shorturl_code = self.shorturl_code,
+
+ series_url = self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
+ series_verb = self.series_verb,
+ )
def __str__ (self) :
return "Image `%s' in `%s'" % (self.name, self.dir.path)
+
--- a/lib/log.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/log.py Thu Jan 31 19:13:00 2008 +0000
@@ -18,19 +18,64 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-import logging
-
-logging.basicConfig(
- level=logging.INFO,
- format="%(message)s",
-# format="%(name)8s %(levelname)8s %(lineno)3d %(message)s",
+import logging, sys
-)
+log_level = logging.INFO
+stack = []
-index = logging.getLogger('index')
-render = logging.getLogger('render')
-template = logging.getLogger('template')
+class g :
+ out_depth = 0
+ node = None
-misc = logging.getLogger('misc')
+def title (title, *args) :
+ stack.append(title)
-template.setLevel(logging.ERROR)
+ print "%s- %s" % (" "*g.out_depth, title % args)
+
+ g.out_depth += 1
+
+def down (dir_name, *args) :
+ stack.append(dir_name % args)
+ g.node = None
+
+def next (fname, *args) :
+ g.node = fname % args
+
+def up () :
+ stack.pop(-1)
+ g.node = None
+ g.out_depth = min(g.out_depth, len(stack))
+
+def done () :
+ print "done"
+
+def log (level, message, *args, **kwargs) :
+ wait = kwargs.get("wait", False)
+
+ if level >= log_level :
+ if g.out_depth != len(stack) :
+ for segment in stack[g.out_depth:] :
+ print "%sd %s" % (" "*g.out_depth, segment)
+ g.out_depth += 1
+
+ if g.node :
+ print "%sf %s" % (" "*g.out_depth, g.node)
+ g.node = None
+
+ if wait :
+ print "%s- %s..." % (" "*g.out_depth, message % args),
+ sys.stdout.flush()
+ else :
+ print "%s- %s" % (" "*g.out_depth, message % args)
+
+def _level (level) :
+ def _log_func (message, *args, **kwargs) :
+ log(level, message, *args, **kwargs)
+
+ return _log_func
+
+debug = _level(logging.DEBUG)
+info = _level(logging.INFO)
+warning = _level(logging.WARNING)
+error = _level(logging.ERROR)
+
--- a/lib/shorturl.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/shorturl.py Thu Jan 31 19:13:00 2008 +0000
@@ -23,9 +23,8 @@
import shelve
import os.path
-from log import index
-import utils, db, helpers, folder, image
+import utils, db, helpers, folder, image, log
def int2key (id) :
"""
@@ -146,7 +145,7 @@
else :
assert(False, "%r %r" % (obj, id))
- index.info("img %50s %15s = %d %s", dir, fname, id, key)
+ log.info("img %50s %15s = %d %s", dir, fname, id, key)
def updateDB (root) :
"""
@@ -162,8 +161,6 @@
# dict of (dir, fname) -> obj
paths = {}
- index.info("Processing ShortURLs...")
-
while dirqueue :
dir = dirqueue.pop(0)
@@ -172,18 +169,18 @@
if dir.alive :
pathtuple = (utils.strip_path(dir.path), '')
- index.debug("dir %50s", pathtuple[0])
+ log.debug("dir %50s", pathtuple[0])
paths[pathtuple] = dir
for img in dir.images.itervalues() :
pathtuple = (utils.strip_path(img.dir.path), img.name)
- index.debug("img %50s %15s", *pathtuple)
+ log.debug("img %50s %15s", *pathtuple)
paths[pathtuple] = img
- print "%d nodes:" % (len(paths))
+ log.info("we have %d nodes", len(paths))
for (id, dir, fname) in db.select("SELECT id, dirpath, filename FROM nodes") :
try :
@@ -192,17 +189,20 @@
obj.shorturl_code = key
- index.debug("%s %50s %15s -> %d %s", dir and "img" or "dir", dir, fname, id, key)
+ log.debug("%s %50s %15s -> %d %s", dir and "img" or "dir", dir, fname, id, key)
except KeyError :
pass
-# index.warning("non-existant node (%d, %s, %s) in db", id, dir, fname)
+# log.warning("non-existant node (%d, %s, %s) in db", id, dir, fname)
- print "%d NEW nodes:" % (len(paths))
+ if paths :
+ log.info("allocating shorturls for %d new nodes:", len(paths))
- db.insert_many(
- _got_obj_key,
- "INSERT INTO nodes (dirpath, filename) VALUES (?, ?)",
- ((obj, (path, fname)) for ((path, fname), obj) in paths.iteritems())
- )
+ db.insert_many(
+ _got_obj_key,
+ "INSERT INTO nodes (dirpath, filename) VALUES (?, ?)",
+ ((obj, (path, fname)) for ((path, fname), obj) in paths.iteritems())
+ )
+ else :
+ log.info("no new images")
--- a/lib/template.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/template.py Thu Jan 31 19:13:00 2008 +0000
@@ -46,11 +46,11 @@
data.update(TEMPLATE_GLOBALS)
try :
- log.template.debug("render %s with %s", self.name, data)
+ log.debug("render %s with %s", self.name, data)
return self.tpl.render(**data)
except :
data = exceptions.text_error_template().render()
- log.template.error(data)
+ log.error(data)
raise
--- a/lib/utils.py Thu Jan 31 17:58:03 2008 +0000
+++ b/lib/utils.py Thu Jan 31 19:13:00 2008 +0000
@@ -18,7 +18,7 @@
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
-import os.path
+import os, os.path
import settings
@@ -80,3 +80,10 @@
def strip_path (path) :
return path.lstrip('.').lstrip('/')
+def mtime (path) :
+ try :
+ return os.stat(path).st_mtime
+ except OSError :
+ # no such file or directory
+ return None
+