9 import pngtile.tile |
9 import pngtile.tile |
10 from pngtile.application import BaseApplication |
10 from pngtile.application import BaseApplication |
11 import pypngtile |
11 import pypngtile |
12 |
12 |
13 import json |
13 import json |
|
14 import os, os.path |
|
15 |
|
16 def dir_url (prefix, name, item): |
|
17 """ |
|
18 Join together an absolute URL prefix, an optional directory name, and a directory item |
|
19 """ |
|
20 |
|
21 url = prefix |
|
22 |
|
23 if name: |
|
24 url += '/' + name |
|
25 |
|
26 url += '/' + item |
|
27 |
|
28 return url |
|
29 |
|
30 def dir_list (root): |
|
31 """ |
|
32 Yield a series of directory items to show for the given dir |
|
33 """ |
|
34 |
|
35 for name in os.listdir(root): |
|
36 path = os.path.join(root, name) |
|
37 |
|
38 # skip dotfiles |
|
39 if name.startswith('.'): |
|
40 continue |
|
41 |
|
42 # show dirs |
|
43 if os.path.isdir(path): |
|
44 yield name |
|
45 |
|
46 # examine ext |
|
47 if '.' in name: |
|
48 name_base, name_type = name.rsplit('.', 1) |
|
49 else: |
|
50 name_base = name |
|
51 name_type = None |
|
52 |
|
53 # show .png files with a .cache file |
|
54 if name_type in ImageApplication.IMAGE_TYPES and os.path.exists(os.path.join(root, name_base + '.cache')): |
|
55 yield name |
14 |
56 |
15 class ImageApplication (BaseApplication): |
57 class ImageApplication (BaseApplication): |
16 |
58 |
17 STYLESHEETS = ( |
59 STYLESHEETS = ( |
18 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css', |
60 'https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css', |
28 '/static/pngtile/map.js', |
70 '/static/pngtile/map.js', |
29 ) |
71 ) |
30 |
72 |
31 def __init__ (self, **opts): |
73 def __init__ (self, **opts): |
32 BaseApplication.__init__(self, **opts) |
74 BaseApplication.__init__(self, **opts) |
|
75 |
|
76 def render_dir_breadcrumb (self, name): |
|
77 path = [] |
|
78 |
|
79 yield html.li(html.a(href='/', *[u"Index"])) |
|
80 |
|
81 if name: |
|
82 for part in name.split('/'): |
|
83 path.append(part) |
|
84 |
|
85 yield html.li(html.a(href='/'.join(path), *[part])) |
|
86 |
|
87 def render_dir (self, request, name, items): |
|
88 """ |
|
89 request: werkzeug.Request |
|
90 name: /.../... url to dir |
|
91 items: [...] items in dir |
|
92 """ |
|
93 |
|
94 if name: |
|
95 title = name |
|
96 else: |
|
97 title = "Index" |
|
98 |
|
99 return self.render_html( |
|
100 title = name, |
|
101 body = ( |
|
102 html.div(class_='container', *[ |
|
103 html.h1(title), |
|
104 html.div(*[ |
|
105 html.ol(class_='breadcrumb', *self.render_dir_breadcrumb(name)), |
|
106 ]), |
|
107 html.div(class_='list', *[ |
|
108 html.ul(class_='list-group', *[html.li(class_='list-group-item', *[ |
|
109 html.a(href=dir_url('', name, item), *[item]) |
|
110 ]) for item in items] |
|
111 ), |
|
112 ]), |
|
113 ]), |
|
114 ), |
|
115 ) |
33 |
116 |
34 def render_image (self, request, image, name): |
117 def render_image (self, request, image, name): |
35 """ |
118 """ |
36 request: werkzeug.Request |
119 request: werkzeug.Request |
37 image: pypngtile.Image |
120 image: pypngtile.Image |
63 end = ( |
146 end = ( |
64 html.script("""$(function() {{ map_init({map_config}); }});""".format(map_config=json.dumps(map_config))), |
147 html.script("""$(function() {{ map_init({map_config}); }});""".format(map_config=json.dumps(map_config))), |
65 ), |
148 ), |
66 ) |
149 ) |
67 |
150 |
68 def handle (self, request): |
151 def handle_dir (self, request, name, path): |
69 """ |
152 """ |
70 Handle request for an image |
153 Generate response for directory listing. |
71 """ |
154 """ |
72 |
155 |
|
156 items = sorted(dir_list(path)) |
|
157 |
|
158 html = self.render_dir(request, name, items) |
|
159 |
|
160 return Response(html, content_type="text/html") |
|
161 |
|
162 def handle_image (self, request, name, path): |
|
163 """ |
|
164 Generate Response for image request. |
|
165 """ |
|
166 |
73 try: |
167 try: |
74 image, name = self.get_image(request.path) |
168 image, name = self.get_image(request.path) |
75 except pypngtile.Error as error: |
169 except pypngtile.Error as error: |
76 raise exceptions.BadRequest(str(error)) |
170 raise exceptions.BadRequest(str(error)) |
77 |
171 |
78 html = self.render_image(request, image, name) |
172 html = self.render_image(request, image, name) |
79 |
173 |
80 return Response(html, content_type="text/html") |
174 return Response(html, content_type="text/html") |
81 |
175 |
82 |
176 def handle (self, request): |
|
177 """ |
|
178 Handle request for an image |
|
179 """ |
|
180 |
|
181 name, path = self.lookup_path(request.path) |
|
182 |
|
183 # determine type |
|
184 if '/' in name: |
|
185 _, name_base = name.rsplit('/', 1) |
|
186 else: |
|
187 name_base = name |
|
188 |
|
189 if '.' in name_base: |
|
190 name_base, name_type = name_base.rsplit('.', 1) |
|
191 else: |
|
192 name_type = None |
|
193 |
|
194 # determine handler |
|
195 if os.path.isdir(path): |
|
196 return self.handle_dir(request, name, path) |
|
197 |
|
198 elif name_type and name_type in self.IMAGE_TYPES: |
|
199 return self.handle_image(request, name, path) |
|
200 |
|
201 else: |
|
202 raise exceptions.NotFound(path) |
|
203 |