Mercurial > hg > index.fcgi > www > www-1
comparison pics2/pics_app.py @ 54:496714f2fd8c
first live version of pics2
author | paulo |
---|---|
date | Mon, 03 Jun 2013 00:30:24 -0700 |
parents | 0482bffd7d7f |
children | 0249782e231e |
comparison
equal
deleted
inserted
replaced
1:6a94c3b87174 | 2:33cc05f1f73b |
---|---|
1 import os | 1 import os |
2 import re | 2 import re |
3 import glob | 3 import glob |
4 import traceback | 4 import traceback |
5 import datetime | |
6 import random | |
7 import urlparse | |
5 | 8 |
6 import html | 9 import html |
7 | 10 |
8 import logging | 11 import logging |
9 logging.basicConfig( | 12 logging.basicConfig( |
12 format="%(asctime)s %(levelname)-8s %(message)s", | 15 format="%(asctime)s %(levelname)-8s %(message)s", |
13 ) | 16 ) |
14 | 17 |
15 | 18 |
16 | 19 |
17 def _get_pics_url(environ, dirpath): | 20 def _is_pics_dir(dirpath): |
18 script_name = environ.get("SCRIPT_NAME", '') | 21 return os.path.exists(os.path.join(dirpath, "_picsroot")) |
19 return os.path.normpath(os.path.join(os.path.dirname(script_name), dirpath)) | 22 |
20 | 23 |
21 | 24 def _get_dir_dt(dirpath): |
22 def _get_app_url(environ, dirpath): | 25 if _is_pics_dir(dirpath): |
23 script_name = environ.get("SCRIPT_NAME", '') | 26 dirpath = os.path.join(dirpath, "_picsroot") |
24 return os.path.normpath(os.path.join(script_name, dirpath)) | 27 |
28 return datetime.datetime.fromtimestamp(os.stat(dirpath).st_mtime) | |
29 | |
30 | |
31 def _format_dt(dt): | |
32 return dt.strftime("%Y-%m-%d") | |
25 | 33 |
26 | 34 |
27 def _parse_path_info(path_info): | 35 def _parse_path_info(path_info): |
28 ppi = path_info.split(os.sep) | 36 ppi = path_info.split(os.sep) |
29 if len(ppi) > 1 and ppi[-1] == '': | 37 if len(ppi) > 1 and ppi[-1] == '': |
30 del ppi[-1] | 38 del ppi[-1] |
31 | 39 |
32 return ppi | 40 return ppi |
33 | 41 |
34 | 42 |
35 def _get_standard_html_doc(title): | |
36 root = html.HTML("html") | |
37 | |
38 header = root.header | |
39 header.title(title) | |
40 | |
41 body = root.body | |
42 body.h1(title) | |
43 | |
44 return (root, header, body) | |
45 | |
46 | |
47 def _numeric_pad_basename(path, maxdigits=20): | 43 def _numeric_pad_basename(path, maxdigits=20): |
48 return os.path.basename(path).zfill(maxdigits) | 44 return os.path.basename(path).zfill(maxdigits) |
49 | 45 |
50 | 46 |
51 def _get_images(d): | 47 def _get_images(d): |
55 | 51 |
56 browse_fns = [os.path.join(d, "browse", os.path.basename(i)) for i in thumb_fns] | 52 browse_fns = [os.path.join(d, "browse", os.path.basename(i)) for i in thumb_fns] |
57 logging.debug("browse_fns = %s" % browse_fns) | 53 logging.debug("browse_fns = %s" % browse_fns) |
58 | 54 |
59 return zip(thumb_fns, browse_fns) | 55 return zip(thumb_fns, browse_fns) |
60 | 56 |
61 | 57 |
62 def _go_thumbnail_links_to_browse_imgs_html_body(environ, body, t, b): | 58 class Main: |
63 thumb_img_url = _get_pics_url(environ, t) | 59 def _get_pics_url(self, dirpath): |
64 browse_url = _get_app_url(environ, b) | 60 script_name = self._environ.get("SCRIPT_NAME", '') |
65 body.a(href=browse_url).img(src=thumb_img_url) | 61 return os.path.normpath(os.path.join(os.path.dirname(script_name), dirpath)) |
66 | 62 |
67 | 63 |
68 def main(environ): | 64 def _get_app_url(self, dirpath): |
69 page_func = None | 65 script_name = self._environ.get("SCRIPT_NAME", '') |
70 | 66 return os.path.normpath(os.path.join(script_name, dirpath)) |
71 logging.debug("environ['PATH_INFO'] = %s" % environ["PATH_INFO"]) | 67 |
72 logging.debug("environ['SCRIPT_NAME'] = %s" % environ["SCRIPT_NAME"]) | 68 |
73 | 69 def _get_standard_html_doc(self, title): |
74 pi = environ["PATH_INFO"] | 70 root = html.HTML("html") |
75 ppi = _parse_path_info(pi) | 71 |
76 logging.debug("ppi = %s" % ppi) | 72 header = root.header |
77 | 73 header.link(rel="stylesheet", type="text/css", href=self._get_pics_url("index.css")) |
78 if len(ppi) < 1 or ppi[0] != '': | 74 header.title(title) |
79 raise AssertionError("Parsed path length must start empty: " + pi) | 75 |
80 | 76 body = root.body |
81 if len(ppi) >= 2 and os.path.exists(os.path.join(ppi[1], "_picsroot")): | 77 body.h1(title) |
82 if len(ppi) == 2: | 78 |
83 page_func = page_thumbs | 79 return (root, header, body) |
84 elif len(ppi) >= 4 and ppi[2] == "browse" and os.path.exists(os.path.join(*ppi)): | 80 |
85 page_func = page_browse | 81 |
86 elif len(ppi) == 1: | 82 def _go_thumbnail_links_to_browse_imgs_html_body(self, body, t, b, selclass=None): |
87 page_func = page_index | 83 thumb_img_url = self._get_pics_url(t) |
88 | 84 browse_url = self._get_app_url(b) |
89 if page_func is None: | 85 |
90 raise RuntimeError("Cannot find path: " + pi) | 86 a = body.a(href=browse_url) |
91 | 87 |
92 return unicode(page_func(environ)).encode("utf-8") | 88 if selclass is not None: |
93 | 89 a.img(src=thumb_img_url, klass=selclass) |
94 | 90 else: |
95 def page_index(environ): | 91 a.img(src=thumb_img_url) |
96 (html_root, html_header, html_body) = _get_standard_html_doc("pics index") | 92 |
97 | 93 body.text(' ') |
98 return html_root | 94 |
99 | 95 |
100 | 96 def __init__(self, environ): |
101 def page_thumbs(environ): | 97 self._environ = environ |
102 ppi = _parse_path_info(environ["PATH_INFO"]) | 98 self._page_func = None |
103 d = os.path.join(*ppi) | 99 |
104 (html_root, html_header, html_body) = _get_standard_html_doc(d) | 100 #logging.debug("environ = %s" % (sorted(self._environ.items(), key=lambda x: x[0]),)) |
105 | 101 logging.debug("environ['PATH_INFO'] = %s" % self._environ["PATH_INFO"]) |
106 html_p = html_body.p | 102 logging.debug("environ['SCRIPT_NAME'] = %s" % self._environ["SCRIPT_NAME"]) |
107 for (t, b) in _get_images(d): | 103 logging.debug("environ['QUERY_STRING'] = %s" % self._environ["QUERY_STRING"]) |
108 _go_thumbnail_links_to_browse_imgs_html_body(environ, html_p, t, b) | 104 |
109 | 105 pi = self._environ["PATH_INFO"] |
110 return html_root | 106 ppi = _parse_path_info(pi) |
111 | 107 logging.debug("ppi = %s" % ppi) |
112 | 108 |
113 def page_browse(environ): | 109 if len(ppi) < 1 or ppi[0] != '': |
114 ppi = _parse_path_info(environ["PATH_INFO"]) | 110 raise AssertionError("Parsed path length must start empty: " + pi) |
115 d = os.path.join(*ppi[:2]) | 111 |
116 imgs = _get_images(d) | 112 if len(ppi) >= 2 and _is_pics_dir(ppi[1]): |
117 img = os.path.join(*ppi) | 113 if len(ppi) == 2: |
118 | 114 self._page_func = self.page_thumbs |
119 # thumbnail preview ribbon | 115 elif len(ppi) >= 4 and ppi[2] == "browse" and os.path.exists(os.path.join(*ppi)): |
120 w = 7 # must be odd | 116 self._page_func = self.page_browse |
121 v = w/2 | 117 elif len(ppi) == 1: |
122 imgs_circ = [None] * w | 118 self._page_func = self.page_index |
123 x = None | 119 |
124 n = len(imgs) | 120 if self._page_func is None: |
125 for (i, (t, b)) in enumerate(imgs): | 121 raise RuntimeError("Cannot find path: " + pi) |
126 if b == img: | 122 |
127 x = i + 1 | 123 |
128 imgs_circ[v] = (t, b) | 124 def page(self): |
129 for j in range(1, v + 1): | 125 return unicode(self._page_func()).encode("utf-8") |
130 if (i + j) < n: imgs_circ[v + j] = imgs[i + j] | 126 |
131 if (i - j) >= 0: imgs_circ[v - j] = imgs[i - j] | 127 |
132 | 128 def page_index(self): |
133 break | 129 n = 5 # number of thumbnails to display |
134 | 130 |
135 if x is None: | 131 (html_root, html_header, html_body) = self._get_standard_html_doc("Pictures") |
136 raise AssertionError | 132 |
137 | 133 pics_dirs = [] |
138 (html_root, html_header, html_body) = _get_standard_html_doc(u"%s \u2014 %s of %s" % (d, x, len(imgs))) | 134 for i in os.listdir('.'): |
139 | 135 if _is_pics_dir(i): |
140 browse_img_url = _get_pics_url(environ, img) | 136 pics_dirs.append((i, _get_dir_dt(i))) |
141 html_body.p.img(src=browse_img_url) | 137 |
142 | 138 pics_dirs.sort(key=lambda x: x[1], reverse=True) |
143 logging.debug("imgs_circ = %s" % imgs_circ) | 139 |
144 | 140 for (d, dt) in pics_dirs: |
145 html_p_ribbon = html_body.p | 141 html_body.h2.a(d, href=self._get_app_url(d)) |
146 for i in imgs_circ: | 142 html_body.h3(_format_dt(dt)) |
147 if i is not None: | 143 |
148 (t, b) = i | 144 imgs = _get_images(d) |
149 _go_thumbnail_links_to_browse_imgs_html_body(environ, html_p_ribbon, t, b) | 145 imgs_idx = [(i, img) for (i, img) in enumerate(imgs)] |
150 | 146 |
151 return html_root | 147 sampled_imgs_idx = random.sample(imgs_idx, min(len(imgs_idx), n)) |
148 sampled_imgs_idx.sort(key=lambda x: x[0]) | |
149 | |
150 html_p = html_body.p | |
151 for (i, (t, b)) in sampled_imgs_idx: | |
152 self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b) | |
153 | |
154 return html_root | |
155 | |
156 | |
157 def page_thumbs(self): | |
158 ppi = _parse_path_info(self._environ["PATH_INFO"]) | |
159 d = os.path.join(*ppi) | |
160 (html_root, html_header, html_body) = self._get_standard_html_doc(d) | |
161 | |
162 qs = urlparse.parse_qs(self._environ["QUERY_STRING"]) | |
163 from_img = None | |
164 if "from" in qs: | |
165 from_img = qs["from"][0] | |
166 | |
167 html_p = html_body.p | |
168 for (t, b) in _get_images(d): | |
169 if from_img is not None and b == from_img: | |
170 self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b, "sel2") | |
171 else: | |
172 self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b) | |
173 | |
174 html_body.a("(Other pictures)", href=self._get_app_url('')) | |
175 return html_root | |
176 | |
177 | |
178 def page_browse(self): | |
179 ppi = _parse_path_info(self._environ["PATH_INFO"]) | |
180 d = os.path.join(*ppi[:2]) | |
181 imgs = _get_images(d) | |
182 img = os.path.join(*ppi) | |
183 | |
184 # thumbnail preview ribbon | |
185 w = 7 # must be odd | |
186 v = w/2 | |
187 imgs_circ = [None] * w | |
188 x = None | |
189 n = len(imgs) | |
190 for (i, (t, b)) in enumerate(imgs): | |
191 if b == img: | |
192 x = i + 1 | |
193 imgs_circ[v] = (t, b) | |
194 for j in range(1, v + 1): | |
195 if (i + j) < n: imgs_circ[v + j] = imgs[i + j] | |
196 if (i - j) >= 0: imgs_circ[v - j] = imgs[i - j] | |
197 | |
198 break | |
199 | |
200 if x is None: | |
201 raise AssertionError | |
202 | |
203 (html_root, html_header, html_body) = self._get_standard_html_doc(u"%s \u2014 %s of %s" % (d, x, len(imgs))) | |
204 | |
205 browse_img_url = self._get_pics_url(img) | |
206 html_body.p.img(src=browse_img_url) | |
207 | |
208 logging.debug("imgs_circ = %s" % imgs_circ) | |
209 | |
210 html_p = html_body.p | |
211 for i in imgs_circ: | |
212 if i is not None: | |
213 (t, b) = i | |
214 if b == img: | |
215 self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, d + "?from=" + img, "sel") | |
216 else: | |
217 self._go_thumbnail_links_to_browse_imgs_html_body(html_p, t, b) | |
218 | |
219 return html_root | |
152 | 220 |
153 | 221 |
154 def app(environ, start_response): | 222 def app(environ, start_response): |
155 response_code = "500 Internal Server Error" | 223 response_code = "500 Internal Server Error" |
156 response_type = "text/plain; charset=UTF-8" | 224 response_type = "text/plain; charset=UTF-8" |
157 | 225 |
158 try: | 226 try: |
159 response_body = main(environ) | 227 response_body = Main(environ).page() |
160 response_code = "200 OK" | 228 response_code = "200 OK" |
161 response_type = "text/html; charset=UTF-8" | 229 response_type = "text/html; charset=UTF-8" |
162 except: | 230 except: |
163 response_body = traceback.format_exc() | 231 response_body = traceback.format_exc() |
164 | 232 |