paulo@52: import os paulo@52: import re paulo@52: import glob paulo@52: import traceback paulo@52: paulo@52: import html paulo@52: paulo@53: import logging paulo@53: logging.basicConfig( paulo@53: level=logging.DEBUG, paulo@53: filename="_LOG", paulo@53: format="%(asctime)s %(levelname)-8s %(message)s", paulo@53: ) paulo@52: paulo@52: paulo@52: paulo@52: def _get_pics_url(environ, dirpath): paulo@52: script_name = environ.get("SCRIPT_NAME", '') paulo@52: return os.path.normpath(os.path.join(os.path.dirname(script_name), dirpath)) paulo@52: paulo@52: paulo@53: def _get_app_url(environ, dirpath): paulo@53: script_name = environ.get("SCRIPT_NAME", '') paulo@53: return os.path.normpath(os.path.join(script_name, dirpath)) paulo@53: paulo@53: paulo@53: def _parse_path_info(path_info): paulo@53: ppi = path_info.split(os.sep) paulo@53: if len(ppi) > 1 and ppi[-1] == '': paulo@53: del ppi[-1] paulo@53: paulo@53: return ppi paulo@53: paulo@53: paulo@53: def _get_standard_html_doc(title): paulo@53: root = html.HTML("html") paulo@53: paulo@53: header = root.header paulo@53: header.title(title) paulo@53: paulo@53: body = root.body paulo@53: body.h1(title) paulo@53: paulo@53: return (root, header, body) paulo@53: paulo@53: paulo@53: def _numeric_pad_basename(path, maxdigits=20): paulo@53: return os.path.basename(path).zfill(maxdigits) paulo@53: paulo@53: paulo@53: def _get_images(d): paulo@53: thumb_fns = glob.glob(os.path.join(d, "thumbs", "*.jpg")) paulo@53: thumb_fns = sorted(thumb_fns, key=_numeric_pad_basename) paulo@53: logging.debug("thumb_fns = %s" % thumb_fns) paulo@53: paulo@53: browse_fns = [os.path.join(d, "browse", os.path.basename(i)) for i in thumb_fns] paulo@53: logging.debug("browse_fns = %s" % browse_fns) paulo@53: paulo@53: return zip(thumb_fns, browse_fns) paulo@53: paulo@53: paulo@53: def _go_thumbnail_links_to_browse_imgs_html_body(environ, body, t, b): paulo@53: thumb_img_url = _get_pics_url(environ, t) paulo@53: browse_url = _get_app_url(environ, b) paulo@53: body.a(href=browse_url).img(src=thumb_img_url) paulo@53: paulo@53: paulo@52: def main(environ): paulo@53: page_func = None paulo@52: paulo@53: logging.debug("environ['PATH_INFO'] = %s" % environ["PATH_INFO"]) paulo@53: logging.debug("environ['SCRIPT_NAME'] = %s" % environ["SCRIPT_NAME"]) paulo@52: paulo@53: pi = environ["PATH_INFO"] paulo@53: ppi = _parse_path_info(pi) paulo@53: logging.debug("ppi = %s" % ppi) paulo@53: paulo@53: if len(ppi) < 1 or ppi[0] != '': paulo@53: raise AssertionError("Parsed path length must start empty: " + pi) paulo@53: paulo@53: if len(ppi) >= 2 and os.path.exists(os.path.join(ppi[1], "_picsroot")): paulo@53: if len(ppi) == 2: paulo@53: page_func = page_thumbs paulo@53: elif len(ppi) >= 4 and ppi[2] == "browse" and os.path.exists(os.path.join(*ppi)): paulo@53: page_func = page_browse paulo@53: elif len(ppi) == 1: paulo@53: page_func = page_index paulo@53: paulo@53: if page_func is None: paulo@53: raise RuntimeError("Cannot find path: " + pi) paulo@52: paulo@53: return unicode(page_func(environ)).encode("utf-8") paulo@53: paulo@52: paulo@53: def page_index(environ): paulo@53: (html_root, html_header, html_body) = _get_standard_html_doc("pics index") paulo@52: paulo@53: return html_root paulo@52: paulo@52: paulo@53: def page_thumbs(environ): paulo@53: ppi = _parse_path_info(environ["PATH_INFO"]) paulo@53: d = os.path.join(*ppi) paulo@53: (html_root, html_header, html_body) = _get_standard_html_doc(d) paulo@53: paulo@53: html_p = html_body.p paulo@53: for (t, b) in _get_images(d): paulo@53: _go_thumbnail_links_to_browse_imgs_html_body(environ, html_p, t, b) paulo@53: paulo@53: return html_root paulo@53: paulo@53: paulo@53: def page_browse(environ): paulo@53: ppi = _parse_path_info(environ["PATH_INFO"]) paulo@53: d = os.path.join(*ppi[:2]) paulo@53: imgs = _get_images(d) paulo@53: img = os.path.join(*ppi) paulo@53: paulo@53: # thumbnail preview ribbon paulo@53: w = 7 # must be odd paulo@53: v = w/2 paulo@53: imgs_circ = [None] * w paulo@53: x = None paulo@53: n = len(imgs) paulo@53: for (i, (t, b)) in enumerate(imgs): paulo@53: if b == img: paulo@53: x = i + 1 paulo@53: imgs_circ[v] = (t, b) paulo@53: for j in range(1, v + 1): paulo@53: if (i + j) < n: imgs_circ[v + j] = imgs[i + j] paulo@53: if (i - j) >= 0: imgs_circ[v - j] = imgs[i - j] paulo@53: paulo@53: break paulo@53: paulo@53: if x is None: paulo@53: raise AssertionError paulo@53: paulo@53: (html_root, html_header, html_body) = _get_standard_html_doc(u"%s \u2014 %s of %s" % (d, x, len(imgs))) paulo@53: paulo@53: browse_img_url = _get_pics_url(environ, img) paulo@53: html_body.p.img(src=browse_img_url) paulo@53: paulo@53: logging.debug("imgs_circ = %s" % imgs_circ) paulo@53: paulo@53: html_p_ribbon = html_body.p paulo@53: for i in imgs_circ: paulo@53: if i is not None: paulo@53: (t, b) = i paulo@53: _go_thumbnail_links_to_browse_imgs_html_body(environ, html_p_ribbon, t, b) paulo@53: paulo@53: return html_root paulo@53: paulo@52: paulo@52: def app(environ, start_response): paulo@52: response_code = "500 Internal Server Error" paulo@52: response_type = "text/plain; charset=UTF-8" paulo@52: paulo@52: try: paulo@52: response_body = main(environ) paulo@52: response_code = "200 OK" paulo@52: response_type = "text/html; charset=UTF-8" paulo@52: except: paulo@52: response_body = traceback.format_exc() paulo@52: paulo@52: response_headers = [ paulo@52: ("Content-Type", response_type), paulo@52: ("Content-Length", str(len(response_body))), paulo@52: ] paulo@52: paulo@52: start_response(response_code, response_headers) paulo@52: paulo@52: return [response_body]