terom@1: #!/usr/bin/env python2.4
terom@1: #
terom@1: # DeGAL - A pretty simple web image gallery
terom@1: # Copyright (C) 2007 Tero Marttila
terom@1: # http://marttila.de/~terom/degal/
terom@1: #
terom@1: # This program is free software; you can redistribute it and/or modify
terom@1: # it under the terms of the GNU General Public License as published by
terom@1: # the Free Software Foundation; either version 2 of the License, or
terom@1: # (at your option) any later version.
terom@1: #
terom@1: # This program is distributed in the hope that it will be useful,
terom@1: # but WITHOUT ANY WARRANTY; without even the implied warranty of
terom@1: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
terom@1: # GNU General Public License for more details.
terom@1: #
terom@1: # You should have received a copy of the GNU General Public License
terom@1: # along with this program; if not, write to the
terom@1: # Free Software Foundation, Inc.,
terom@1: # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
terom@1: #
terom@1:
terom@1: import os.path, os
terom@1: import urllib
terom@1: import logging
terom@1: import string
terom@1: from datetime import datetime
terom@1: import struct
terom@1: import base64
terom@1: import shelve
terom@1:
terom@1: import PIL
terom@1: import PIL.Image
terom@1:
terom@1: import utils
terom@1:
terom@1: __version__ = '0.2'
terom@1:
terom@1: TEMPLATE_DIR='templates'
terom@1: TEMPLATE_EXT='html'
terom@1:
terom@1: logging.basicConfig(
terom@1: level=logging.INFO,
terom@1: format="%(name)8s %(levelname)8s %(lineno)3d %(message)s",
terom@1:
terom@1: )
terom@1:
terom@1: tpl = logging.getLogger('tpl')
terom@1: index = logging.getLogger('index')
terom@1: prepare = logging.getLogger('prepare')
terom@1: render = logging.getLogger('render')
terom@1:
terom@1: tpl.setLevel(logging.WARNING)
terom@1:
terom@1: #for l in (tpl, index, prepare, render) :
terom@1: # l.setLevel(logging.DEBUG)
terom@1:
terom@1: def readFile (path) :
terom@1: fo = open(path, 'r')
terom@1: data = fo.read()
terom@1: fo.close()
terom@1:
terom@1: return data
terom@1:
terom@1: class Template (object) :
terom@1: GLOBALS = dict(
terom@1: VERSION=__version__,
terom@1: )
terom@1:
terom@1: def __init__ (self, name) :
terom@1: self.name = name
terom@1: self.path = os.path.join(TEMPLATE_DIR, "%s.%s" % (name, TEMPLATE_EXT))
terom@1:
terom@1: tpl.debug("Template %s at %s", name, self.path)
terom@1:
terom@1: self.content = readFile(self.path)
terom@1:
terom@1: def render (self, **vars) :
terom@1: content = self.content
terom@1:
terom@1: vars.update(self.GLOBALS)
terom@1:
terom@1: for name, value in vars.iteritems() :
terom@1: content = content.replace('' % name, str(value))
terom@1:
terom@1: return content
terom@1:
terom@1: def renderTo (self, path, **vars) :
terom@1: tpl.info("Render %s to %s", self.name, path)
terom@1:
terom@1: fo = open(path, 'w')
terom@1: fo.write(self.render(**vars))
terom@1: fo.close()
terom@1:
terom@1: gallery_tpl = Template('gallery')
terom@1: image_tpl = Template('image')
terom@1:
terom@1: IMAGE_EXTS = ('jpg', 'jpeg', 'png', 'gif', 'bmp')
terom@1:
terom@1: THUMB_DIR = 'thumbs'
terom@1: PREVIEW_DIR = 'previews'
terom@1: TITLE_FILE = 'title.txt'
terom@1:
terom@1: THUMB_GEOM = (160, 120)
terom@1: PREVIEW_GEOM = (640, 480)
terom@1:
terom@1: DEFAULT_TITLE = 'Image gallery'
terom@1:
terom@5: # how many image/page
terom@5: IMAGE_COUNT = 50
terom@5:
terom@1: def isImage (fname) :
terom@1: """
terom@1: Is the given filename likely to be an image file?
terom@1: """
terom@1:
terom@1: fname = fname.lower()
terom@1: base, ext = os.path.splitext(fname)
terom@1: ext = ext.lstrip('.')
terom@1:
terom@1: return ext in IMAGE_EXTS
terom@1:
terom@1: def link (url, title) :
terom@1: """
terom@1: Returns an link tag with the given values
terom@1: """
terom@1:
terom@1: return "%s" % (urllib.quote(url), title)
terom@1:
terom@1: def dirUp (count=1) :
terom@1: """
terom@1: Returns a relative path to the directly count levels above the current one
terom@1: """
terom@1:
terom@1: if not count :
terom@1: return '.'
terom@1:
terom@1: return os.path.join(*(['..']*count))
terom@1:
terom@1: def readTitleDescr (path) :
terom@1: """
terom@1: Read a title.txt or .txt file
terom@1: """
terom@1:
terom@1: if os.path.exists(path) :
terom@1: content = readFile(path)
terom@1:
terom@1: if '---' in content :
terom@1: title, descr = content.split('---', 1)
terom@1: else :
terom@1: title, descr = content, ''
terom@1:
terom@1: return title.strip(), descr.strip()
terom@1:
terom@1: return None, None
terom@1:
terom@1: class Folder (object) :
terom@1: def __init__ (self, name='.', parent=None) :
terom@1: # the directory name
terom@1: self.name = name
terom@1:
terom@1: # our parent Folder, or None
terom@1: self.parent = parent
terom@1:
terom@1: # the path to this dir, as a relative path to the root of the image gallery, always starts with .
terom@1: if parent and name :
terom@1: self.path = parent.pathFor(name)
terom@1: else :
terom@1: self.path = name
terom@1:
terom@1: # the url-path to the index.html file
terom@1: self.html_path = self.path
terom@1:
terom@1: # dict of fname -> Folder
terom@1: self.subdirs = {}
terom@1:
terom@1: # dict of fname -> Image
terom@1: self.images = {}
terom@1:
terom@1: # our human-friendly title
terom@1: self.title = None
terom@1:
terom@1: # our long-winded description
terom@1: self.descr = ''
terom@1:
terom@1: # is this folder non-empty?
terom@1: self.alive = None
terom@1:
terom@1: # self.images.values(), but sorted by filename
terom@1: self.sorted_images = []
terom@1:
terom@1: # the ShortURL key to this dir
terom@1: self.shorturl_code = None
terom@1:
terom@1: # were we filtered out?
terom@1: self.filtered = False
terom@1:
terom@1: def pathFor (self, *fnames) :
terom@1: """
terom@1: Return a root-relative path to the given path inside this dir
terom@1: """
terom@1: return os.path.join(self.path, *fnames)
terom@1:
terom@1: def index (self, filters=None) :
terom@1: """
terom@1: Look for other dirs and images inside this dir. Filters must be either None,
terom@1: whereupon all files will be included, or a dict of {filename -> next_filter}.
terom@1: If given, only filenames that are present in the dict will be indexed, and in
terom@1: the case of dirs, the next_filter will be passed on to that Folder's index
terom@1: method.
terom@1: """
terom@1:
terom@1: index.info("Indexing %s", self.path)
terom@1:
terom@1: if filters :
terom@1: self.filtered = True
terom@1:
terom@1: # iterate through listdir
terom@1: for fname in os.listdir(self.path) :
terom@1: # the full filesystem path to it
terom@1: fpath = self.pathFor(fname)
terom@1:
terom@1: # ignore dotfiles
terom@1: if fname.startswith('.') :
terom@1: index.debug("Skipping dotfile %s", fname)
terom@1: continue
terom@1:
terom@1: # apply filters
terom@1: if filters :
terom@1: if fname in filters :
terom@1: next_filter = filters[fname]
terom@1: else :
terom@1: index.debug("Skip `%s' as we have a filter", fname)
terom@1: continue
terom@1: else :
terom@1: next_filter = None
terom@1:
terom@1: # recurse into subdirs, but not thumbs/previews
terom@1: if os.path.isdir(fpath) and fname not in (THUMB_DIR, PREVIEW_DIR) :
terom@1: index.debug("Found subdir %s", fpath)
terom@1: f = self.subdirs[fname] = Folder(fname, self)
terom@1: f.index(next_filter) # recursion
terom@1:
terom@1: # handle images
terom@1: elif os.path.isfile(fpath) and isImage(fname) :
terom@1: index.debug("Found image %s", fname)
terom@1: self.images[fname] = Image(self, fname)
terom@1:
terom@1: # ignore everything else
terom@1: else :
terom@1: index.debug("Ignoring file %s", fname)
terom@1:
terom@1: def prepare (self) :
terom@1: """
terom@1: Prepare the dir, i.e. sort+prepare the images, as well as recurse
terom@1: into subdirs
terom@1: """
terom@1:
terom@1: prepare.info("Preparing dir %s", self.path)
terom@1:
terom@1: # is this folder non-empty?
terom@1: alive = False
terom@1:
terom@1: # only create thumbs/previews dirs if we have images in here
terom@1: if self.images :
terom@1: # folder is non-empty
terom@1: alive = True
terom@1: prepare.info("Have %d images", len(self.images))
terom@1:
terom@1: # create the thumb/preview dirs if needed
terom@1: for dir in (THUMB_DIR, PREVIEW_DIR) :
terom@1: prepare.debug("Checking for existance of %s dir", dir)
terom@1: path = self.pathFor(dir)
terom@1:
terom@1: if not os.path.isdir(path) :
terom@1: prepare.info("Creating dir %s", path)
terom@1: os.mkdir(path)
terom@1:
terom@1: # sort the images
terom@1: fnames = self.images.keys()
terom@1: fnames.sort()
terom@1:
terom@1: prev = None
terom@1:
terom@1: # link them together and prepare them
terom@1: for fname in fnames :
terom@1: img = self.images[fname]
terom@1:
terom@1: prepare.debug("Linking %s <-> %s", prev, img)
terom@1:
terom@1: img.prev = prev
terom@1:
terom@1: if prev :
terom@1: prev.next = img
terom@1:
terom@1: prev = img
terom@1:
terom@1: img.prepare()
terom@1:
terom@1: # add to the sorted images list
terom@1: self.sorted_images.append(img)
terom@1:
terom@1: # prepare subdirs
terom@1: if self.subdirs :
terom@1: prepare.info("Have %d subdirs", len(self.subdirs))
terom@1:
terom@1: # just recurse into them, we're alive if one of them is
terom@1: for dir in self.subdirs.itervalues() :
terom@1: if dir.prepare() :
terom@1: alive = True
terom@1:
terom@1: # figure out our title
terom@1: title_path = self.pathFor(TITLE_FILE)
terom@1:
terom@1: title, descr = readTitleDescr(title_path)
terom@1:
terom@1: if title :
terom@1: prepare.info("Found title/descr")
terom@1: self.title = title
terom@1: self.descr = descr
terom@1: alive = True
terom@1:
terom@1: # default title for the root dir
terom@1: elif self.name == '.' :
terom@1: self.title = 'Index'
terom@1:
terom@1: else :
terom@1: self.title = self.name
terom@1:
terom@1: prepare.debug("Our title is '%s'", self.title)
terom@1:
terom@1: # lol ded
terom@1: if not alive :
terom@1: prepare.info("Dir %s is not alive", self.path)
terom@1:
terom@1: self.alive = alive
terom@1:
terom@1: return alive
terom@1:
terom@1: def getObjInfo (self) :
terom@1: """
terom@1: Metadata for shorturls2.db
terom@1: """
terom@5: return 'dir', self.path, 'index'
terom@1:
terom@1: def linkTag (self) :
terom@1: """
terom@1: A text-link to this dir
terom@1: """
terom@1:
terom@1: return link(self.path, self.title)
terom@1:
terom@1: def breadcrumb (self) :
terom@1: """
terom@1: Returns a [(fname, title)] list of this dir's parent dirs
terom@1: """
terom@1:
terom@1: f = self
terom@1: b = []
terom@1: d = 0
terom@1:
terom@1: while f :
terom@1: b.insert(0, (dirUp(d), f.title))
terom@1:
terom@1: d += 1
terom@1: f = f.parent
terom@1:
terom@1: return b
terom@1:
terom@1: def inRoot (self, *fnames) :
terom@1: """
terom@1: Return a relative URL from this dir to the given path in the root dir
terom@1: """
terom@1:
terom@1: c = len(self.path.split('/')) - 1
terom@1:
terom@1: return os.path.join(*((['..']*c) + list(fnames)))
terom@5:
terom@5: def _page_fname (self, page) :
terom@5: assert page >= 0
terom@5:
terom@5: if page > 0 :
terom@5: return 'index_%d.html' % page
terom@5: else :
terom@5: return 'index.html'
terom@1:
terom@1: def render (self) :
terom@1: """
terom@1: Render the index.html, Images, and recurse into subdirs
terom@1: """
terom@1:
terom@1: # ded folders are skipped
terom@1: if not self.alive :
terom@1: render.info("Skipping dir %s", self.path)
terom@1: return
terom@1:
terom@1: # 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
terom@1: if self.filtered :
terom@1: render.warning("Dir `%s' contents were filtered, so we won't render the gallery index again", self.path)
terom@1:
terom@1: else :
terom@1: # sort the subdirs
terom@1: subdirs = self.subdirs.items()
terom@1: subdirs.sort()
terom@1:
terom@1: # generate the 's for the subdirs
terom@1: subdir_linkTags = [link(f.name, f.title) for fname, f in subdirs if f.alive]
terom@1:
terom@1: # stick them into a list
terom@1: if subdir_linkTags :
terom@1: directories = "" % "\n\t".join(subdir_linkTags)
terom@1: else :
terom@1: directories = ''
terom@1:
terom@1: render.info("Rendering %s", self.path)
terom@5:
terom@5: # paginate!
terom@5: images = self.sorted_images
terom@5: image_count = len(images)
terom@5: pages = []
terom@1:
terom@5: while images :
terom@5: pages.append(images[:IMAGE_COUNT])
terom@5: images = images[IMAGE_COUNT:]
terom@5:
terom@5: pagination_required = len(pages) > 1
terom@5:
terom@5: if pagination_required :
terom@5: render.info("Index split into %d pages of %d images each", len(pages), IMAGE_COUNT)
terom@5:
terom@5: for cur_page, page in enumerate(pages) :
terom@5: if pagination_required :
terom@5: pagination = "" # - Showing Images %d - %d of %d
" % (cur_page*IMAGE_COUNT, cur_page*IMAGE_COUNT+len(page), image_count)
terom@5:
terom@5: if cur_page > 0 :
terom@5: pagination += '- « Prev
' % (self._page_fname(cur_page - 1))
terom@5: else :
terom@5: pagination += '- « Prev
'
terom@5:
terom@5: for x in xrange(0, len(pages)) :
terom@5: if x == cur_page :
terom@5: pagination += '- %s
' % (x + 1)
terom@5: else :
terom@5: pagination += '- %s
' % (self._page_fname(x), x+1)
terom@5:
terom@5: if cur_page < len(pages) - 1 :
terom@5: pagination += '- Next »
' % (self._page_fname(cur_page + 1))
terom@5: else :
terom@5: pagination += '- Next »
'
terom@5:
terom@5: pagination += "
"
terom@6: shorturl = "%s/%s" % (self.shorturl_code, cur_page+1)
terom@5: else :
terom@5: pagination = ''
terom@6: shorturl = self.shorturl_code
terom@5:
terom@5: # render to index.html
terom@5: gallery_tpl.renderTo(self.pathFor(self._page_fname(cur_page)),
terom@5: STYLE_URL=self.inRoot('style.css'),
terom@5: BREADCRUMB=" » ".join([link(u, t) for (u, t) in self.breadcrumb()]),
terom@5: TITLE=self.title,
terom@5: DIRECTORIES=directories,
terom@5: PAGINATION=pagination,
terom@5: CONTENT="".join([i.thumbImgTag() for i in page]),
terom@5: DESCR=self.descr,
terom@6: SHORTURL=self.inRoot('s', shorturl),
terom@6: SHORTURL_CODE=shorturl,
terom@5: )
terom@1:
terom@1: # render images
terom@1: for img in self.images.itervalues() :
terom@1: img.render()
terom@1:
terom@1: # recurse into subdirs
terom@1: for dir in self.subdirs.itervalues() :
terom@1: dir.render()
terom@1:
terom@1: class Image (object) :
terom@1: def __init__ (self, dir, name) :
terom@1: # the image filename, e.g. DSC3948.JPG
terom@1: self.name = name
terom@1:
terom@1: # the Folder object that we are in
terom@1: self.dir = dir
terom@1:
terom@1: # the relative path from the root to us
terom@1: self.path = dir.pathFor(name)
terom@1:
terom@1: # the basename+ext, e.g. DSCR3948, .JPG
terom@1: self.base_name, self.ext = os.path.splitext(name)
terom@1:
terom@1: # the root-relative paths to the thumb and preview images
terom@1: self.thumb_path = self.dir.pathFor(THUMB_DIR, self.name)
terom@1: self.preview_path = self.dir.pathFor(PREVIEW_DIR, self.name)
terom@1:
terom@1: # our user-friendly title
terom@1: self.title = name
terom@1:
terom@1: # our long-winded description
terom@1: self.descr = ''
terom@1:
terom@1: # the image before and after us, both may be None
terom@1: self.prev = self.next = None
terom@1:
terom@1: # the name of the .html gallery view thing for this image, *always* self.name + ".html"
terom@1: self.html_name = self.name + ".html"
terom@1:
terom@1: # the root-relative path to the gallery view
terom@1: self.html_path = self.dir.pathFor(self.html_name)
terom@1:
terom@1: #
terom@1: # Figured out after prepare
terom@1: #
terom@1:
terom@1: # (w, h) tuple
terom@1: self.img_size = None
terom@1:
terom@1: # the ShortURL code for this image
terom@1: self.shorturl_code = None
terom@1:
terom@1: # what to use in the rendered templates, intended to be overridden by subclasses
terom@1: self.series_act = "add"
terom@1: self.series_verb = "Add to"
terom@1:
terom@1: def prepare (self) :
terom@1: """
terom@1: Generate the thumbnail/preview views if needed, get the image info, and look for the title
terom@1: """
terom@1:
terom@1: prepare.info("Preparing image %s", self.path)
terom@1:
terom@1: # stat the image file to get the filesize and mtime
terom@1: st = os.stat(self.path)
terom@1:
terom@1: self.filesize = st.st_size
terom@1: self.timestamp = st.st_mtime
terom@1:
terom@1: # open the image in PIL to get image attributes + generate thumbnails
terom@1: img = PIL.Image.open(self.path)
terom@1:
terom@1: self.img_size = img.size
terom@1:
terom@1: for out_path, geom in ((self.thumb_path, THUMB_GEOM), (self.preview_path, PREVIEW_GEOM)) :
terom@1: # if it doesn't exist, or it's older than the image itself, generate
terom@1: if not (os.path.exists(out_path) and os.stat(out_path).st_mtime > self.timestamp) :
terom@1: prepare.info("Create thumbnailed image at %s with geom %s", out_path, geom)
terom@1:
terom@1: # XXX: is this the most efficient way to do this?
terom@1: out_img = img.copy()
terom@1: out_img.thumbnail(geom, resample=True)
terom@1: out_img.save(out_path)
terom@1:
terom@1: # look for the metadata file
terom@1: title_path = self.dir.pathFor(self.base_name + '.txt')
terom@1: prepare.debug("Looking for title at %s", title_path)
terom@1:
terom@1: title, descr = readTitleDescr(title_path)
terom@1:
terom@1: if title :
terom@1: self.title = title
terom@1: self.descr = descr
terom@1:
terom@1: prepare.info("Found title `%s'", self.title)
terom@1:
terom@1: def getObjInfo (self) :
terom@1: """
terom@1: Metadata for shorturl2.db
terom@1: """
terom@1: return 'img', self.dir.path, self.name
terom@1:
terom@1: def thumbImgTag (self) :
terom@1: """
terom@1: a of this image's thumbnail. Path relative to directory we are in
terom@1: """
terom@5: return link(self.html_name, "" % (os.path.join(THUMB_DIR, self.name), self.descr, self.title))
terom@1:
terom@1: def previewImgTag (self) :
terom@1: """
terom@1: a of this image's preview. Path relative to directory we are in
terom@1: """
terom@5: return link(self.name, "" % (os.path.join(PREVIEW_DIR, self.name), self.descr, self.title))
terom@1:
terom@1: def linkTag (self) :
terom@1: """
terom@1: a text-link to this image
terom@1: """
terom@1: return link(self.html_name, self.title)
terom@1:
terom@1: def breadcrumb (self) :
terom@1: """
terom@1: Returns a [(fname, title)] list of this image's parents
terom@1: """
terom@1:
terom@1: f = self.dir
terom@1: b = [(self.html_name, self.title)]
terom@1: d = 0
terom@1:
terom@1: while f :
terom@1: b.insert(0, (dirUp(d), f.title))
terom@1:
terom@1: d += 1
terom@1: f = f.parent
terom@1:
terom@1: return b
terom@1:
terom@1: def render (self) :
terom@1: """
terom@1: Write out the .html file
terom@1: """
terom@1:
terom@1: render.info("Rendering image %s", self.path)
terom@1:
terom@1: image_tpl.renderTo(self.html_path,
terom@1: STYLE_URL=self.dir.inRoot('style.css'),
terom@1: UP_URL=('.'),
terom@1: PREV_URL=(self.prev and self.prev.html_name or ''),
terom@1: NEXT_URL=(self.next and self.next.html_name or ''),
terom@1: FILE=self.name,
terom@1: BREADCRUMB=" » ".join([link(u, t) for u, t in self.breadcrumb()]),
terom@1: TITLE=self.title,
terom@1: PREVIOUS_THUMB=(self.prev and self.prev.thumbImgTag() or ''),
terom@1: IMAGE=self.previewImgTag(),
terom@1: NEXT_THUMB=(self.next and self.next.thumbImgTag() or ''),
terom@1: DESCRIPTION=self.descr,
terom@1: IMGSIZE="%dx%d" % self.img_size,
terom@1: FILESIZE=fmtFilesize(self.filesize),
terom@1: TIMESTAMP=fmtTimestamp(self.timestamp),
terom@1: SHORTURL=self.dir.inRoot('s', self.shorturl_code),
terom@1: SHORTURL_CODE=self.shorturl_code,
terom@1: SERIES_URL=self.dir.inRoot('series/%s/%s' % (self.series_act, self.shorturl_code)),
terom@1: SERIES_VERB=self.series_verb,
terom@1: )
terom@1:
terom@1: def __str__ (self) :
terom@1: return "Image `%s' in `%s'" % (self.name, self.dir.path)
terom@1:
terom@1: def int2key (id) :
terom@1: """
terom@1: Turn an integer into a short-as-possible url-safe string
terom@1: """
terom@1: for type in ('B', 'H', 'I') :
terom@1: try :
terom@1: return base64.b64encode(struct.pack(type, id), '-_').rstrip('=')
terom@1: except struct.error :
terom@1: continue
terom@1:
terom@1: raise Exception("ID overflow: %s" % id)
terom@1:
terom@1: def updateShorturlDb (root) :
terom@1: """
terom@1: DeGAL <= 0.2 used a simple key => path mapping, but now we use
terom@1: something more structured, key => (type, dirpath, fname), where
terom@1:
terom@1: type - one of 'img', 'dir'
terom@1: dirpath - the path to the directory, e.g. '.', './foobar', './foobar/quux'
terom@1: fname - the filename, one of '', 'DSC9839.JPG', 'this.png', etc.
terom@1: """
terom@1:
terom@5: db = shelve.open('shorturls2', 'c', writeback=True)
terom@1:
terom@1: id = db.get('_id', 1)
terom@1:
terom@1: dirqueue = [root]
terom@1:
terom@1: # dict of path -> obj
terom@1: paths = {}
terom@1:
terom@5: index.info("Processing ShortURLs...")
terom@5:
terom@1: while dirqueue :
terom@1: dir = dirqueue.pop(0)
terom@1:
terom@1: dirqueue.extend(dir.subdirs.itervalues())
terom@1:
terom@1: if dir.alive :
terom@1: paths[dir.path] = dir
terom@1:
terom@1: for img in dir.images.itervalues() :
terom@5: paths[img.path] = img
terom@1:
terom@1: for key in db.keys() :
terom@1: if key.startswith('_') :
terom@1: continue
terom@1:
terom@1: type, dirpath, fname = db[key]
terom@1:
terom@5: path = os.path.join(dirpath, fname).rstrip('/')
terom@1:
terom@1: try :
terom@1: paths.pop(path).shorturl_code = key
terom@1: index.debug("Code for `%s' is %s", path, key)
terom@1:
terom@1: except KeyError :
terom@1: index.debug("Path `%s' in DB does not exist?", path)
terom@1:
terom@1: for obj in paths.itervalues() :
terom@1: key = int2key(id)
terom@1: id += 1
terom@1:
terom@1: index.info("Alloc code `%s' for `%s'", key, obj.html_path)
terom@1:
terom@1: obj.shorturl_code = key
terom@1:
terom@1: db[key] = obj.getObjInfo()
terom@1:
terom@1: db['_id'] = id
terom@1: db.close()
terom@1:
terom@1: def main (targets=()) :
terom@1: root_filter = {}
terom@1:
terom@1: for target in targets :
terom@1: f = root_filter
terom@1: for path_part in target.split('/') :
terom@1: if path_part :
terom@1: if path_part not in f :
terom@1: f[path_part] = {}
terom@1: f = f[path_part]
terom@1:
terom@1: index.debug('Filter: %s', root_filter)
terom@1:
terom@1: root = Folder()
terom@1: root.index(root_filter)
terom@1: root.prepare()
terom@1: updateShorturlDb(root)
terom@1: root.render()
terom@1:
terom@1: def fmtFilesize (size) :
terom@1: return utils.formatbytes(size, forcekb=False, largestonly=True, kiloname='K', meganame='M', bytename='B', nospace=True)
terom@1:
terom@1: def fmtTimestamp (ts) :
terom@1: return datetime.fromtimestamp(ts).strftime("%Y/%m/%d %H:%M")
terom@1:
terom@1: if __name__ == '__main__' :
terom@1: from sys import argv
terom@1: argv.pop(0)
terom@1:
terom@1: main(argv)
terom@1: