# HG changeset patch # User Tero Marttila # Date 1410733381 -10800 # Node ID 77330e43c855a91e060853bed19d69ca329265db # Parent 0f2a918eb90abfd7c46cba4365b4299d8c3f8f78 pngtile.image: handle dir indexes diff -r 0f2a918eb90a -r 77330e43c855 pngtile/image.py --- a/pngtile/image.py Mon Sep 15 01:22:46 2014 +0300 +++ b/pngtile/image.py Mon Sep 15 01:23:01 2014 +0300 @@ -11,6 +11,48 @@ import pypngtile import json +import os, os.path + +def dir_url (prefix, name, item): + """ + Join together an absolute URL prefix, an optional directory name, and a directory item + """ + + url = prefix + + if name: + url += '/' + name + + url += '/' + item + + return url + +def dir_list (root): + """ + Yield a series of directory items to show for the given dir + """ + + for name in os.listdir(root): + path = os.path.join(root, name) + + # skip dotfiles + if name.startswith('.'): + continue + + # show dirs + if os.path.isdir(path): + yield name + + # examine ext + if '.' in name: + name_base, name_type = name.rsplit('.', 1) + else: + name_base = name + name_type = None + + # show .png files with a .cache file + if name_type in ImageApplication.IMAGE_TYPES and os.path.exists(os.path.join(root, name_base + '.cache')): + yield name class ImageApplication (BaseApplication): @@ -31,6 +73,47 @@ def __init__ (self, **opts): BaseApplication.__init__(self, **opts) + def render_dir_breadcrumb (self, name): + path = [] + + yield html.li(html.a(href='/', *[u"Index"])) + + if name: + for part in name.split('/'): + path.append(part) + + yield html.li(html.a(href='/'.join(path), *[part])) + + def render_dir (self, request, name, items): + """ + request: werkzeug.Request + name: /.../... url to dir + items: [...] items in dir + """ + + if name: + title = name + else: + title = "Index" + + return self.render_html( + title = name, + body = ( + html.div(class_='container', *[ + html.h1(title), + html.div(*[ + html.ol(class_='breadcrumb', *self.render_dir_breadcrumb(name)), + ]), + html.div(class_='list', *[ + html.ul(class_='list-group', *[html.li(class_='list-group-item', *[ + html.a(href=dir_url('', name, item), *[item]) + ]) for item in items] + ), + ]), + ]), + ), + ) + def render_image (self, request, image, name): """ request: werkzeug.Request @@ -65,11 +148,22 @@ ), ) - def handle (self, request): + def handle_dir (self, request, name, path): """ - Handle request for an image + Generate response for directory listing. """ - + + items = sorted(dir_list(path)) + + html = self.render_dir(request, name, items) + + return Response(html, content_type="text/html") + + def handle_image (self, request, name, path): + """ + Generate Response for image request. + """ + try: image, name = self.get_image(request.path) except pypngtile.Error as error: @@ -79,4 +173,31 @@ return Response(html, content_type="text/html") + def handle (self, request): + """ + Handle request for an image + """ + name, path = self.lookup_path(request.path) + + # determine type + if '/' in name: + _, name_base = name.rsplit('/', 1) + else: + name_base = name + + if '.' in name_base: + name_base, name_type = name_base.rsplit('.', 1) + else: + name_type = None + + # determine handler + if os.path.isdir(path): + return self.handle_dir(request, name, path) + + elif name_type and name_type in self.IMAGE_TYPES: + return self.handle_image(request, name, path) + + else: + raise exceptions.NotFound(path) +