comparison piecrust/routing.py @ 334:b034f6f15e22

bake: Several bug taxonomy-related fixes for incorrect incremental bakes. * Improve how the baker processes taxonomy terms and figures out what needs to be re-baked or not. * Create bake entries for clean taxnomy terms so they're not deleted by an incremental bake. * Add more information to bake records. * Slugify taxonomy terms is now done by the route in one place. * Fix a bug where the cache key for invalidating rendered segments was not computed the same way as when the caching was done. * Fix how term combinations are passed around, rendered, printed, parsed, etc. (TODO: more word needed in the routing functions) * Expose to the template whether a taxonomy term is a combination or not. * Display term combinations better in the built-in theme. * Rename `route.taxonomy` to `route.taxonomy_name` to prevent confusion. * Add options to show bake records for previous bakes.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 03 Apr 2015 10:59:50 -0700
parents 422052d2e978
children 49408002798e
comparison
equal deleted inserted replaced
333:91b07f9efdc1 334:b034f6f15e22
24 Each route defines the "shape" of an URL and how it maps to 24 Each route defines the "shape" of an URL and how it maps to
25 sources and taxonomies. 25 sources and taxonomies.
26 """ 26 """
27 def __init__(self, app, cfg): 27 def __init__(self, app, cfg):
28 self.app = app 28 self.app = app
29
30 self.source_name = cfg['source']
31 self.taxonomy_name = cfg.get('taxonomy')
29 32
30 self.pretty_urls = app.config.get('site/pretty_urls') 33 self.pretty_urls = app.config.get('site/pretty_urls')
31 self.trailing_slash = app.config.get('site/trailing_slash') 34 self.trailing_slash = app.config.get('site/trailing_slash')
32 self.pagination_suffix_format = app.config.get( 35 self.pagination_suffix_format = app.config.get(
33 '__cache/pagination_suffix_format') 36 '__cache/pagination_suffix_format')
64 67
65 self.required_source_metadata = set() 68 self.required_source_metadata = set()
66 for m in route_re.finditer(self.uri_pattern): 69 for m in route_re.finditer(self.uri_pattern):
67 self.required_source_metadata.add(m.group('name')) 70 self.required_source_metadata.add(m.group('name'))
68 71
69 self.source_name = cfg['source']
70 self.taxonomy = cfg.get('taxonomy')
71 self.template_func = None 72 self.template_func = None
72 self.template_func_name = None 73 self.template_func_name = None
73 self.template_func_args = [] 74 self.template_func_args = []
74 self._createTemplateFunc(cfg.get('func')) 75 self._createTemplateFunc(cfg.get('func'))
75 76
155 uri = base_uri + ext 156 uri = base_uri + ext
156 157
157 uri = self.uri_root + uri 158 uri = self.uri_root + uri
158 return uri 159 return uri
159 160
161 def slugifyTaxonomyTerm(self, term):
162 #TODO: add options for transliterating and combining terms.
163 if isinstance(term, tuple):
164 return '/'.join(term)
165 return term
166
167 def unslugifyTaxonomyTerm(self, term):
168 #TODO: same as above.
169 split_terms = term.split('/')
170 if len(split_terms) == 1:
171 return term
172 return tuple(split_terms)
173
160 def _uriFormatRepl(self, m): 174 def _uriFormatRepl(self, m):
161 name = m.group('name') 175 name = m.group('name')
162 #TODO: fix this hard-coded shit 176 #TODO: fix this hard-coded shit
163 if name == 'year': 177 if name == 'year':
164 return '%(year)04d' 178 return '%(year)04d'
169 return '%(' + name + ')s' 183 return '%(' + name + ')s'
170 184
171 def _uriPatternRepl(self, m): 185 def _uriPatternRepl(self, m):
172 name = m.group('name') 186 name = m.group('name')
173 qualifier = m.group('qual') 187 qualifier = m.group('qual')
174 if qualifier == 'path': 188 if qualifier == 'path' or self.taxonomy_name:
175 return r'(?P<%s>[^\?]*)' % name 189 return r'(?P<%s>[^\?]*)' % name
176 return r'(?P<%s>[^/\?]+)' % name 190 return r'(?P<%s>[^/\?]+)' % name
177 191
178 def _uriNoPathRepl(self, m): 192 def _uriNoPathRepl(self, m):
179 name = m.group('name') 193 name = m.group('name')
196 self.template_func_args.append(m.group('first_arg')) 210 self.template_func_args.append(m.group('first_arg'))
197 arg_list = m.group('other_args') 211 arg_list = m.group('other_args')
198 if arg_list: 212 if arg_list:
199 self.template_func_args += template_func_arg_re.findall(arg_list) 213 self.template_func_args += template_func_arg_re.findall(arg_list)
200 214
201 if self.taxonomy: 215 if self.taxonomy_name:
202 # This will be a taxonomy route function... this means we can 216 # This will be a taxonomy route function... this means we can
203 # have a variable number of parameters, but only one parameter 217 # have a variable number of parameters, but only one parameter
204 # definition, which is the value. 218 # definition, which is the value.
205 if len(self.template_func_args) != 1: 219 if len(self.template_func_args) != 1:
206 raise Exception("Route '%s' is a taxonomy route and must have " 220 raise Exception("Route '%s' is a taxonomy route and must have "
224 registered_values = values[0] 238 registered_values = values[0]
225 else: 239 else:
226 registered_values = tuple(values) 240 registered_values = tuple(values)
227 eis = self.app.env.exec_info_stack 241 eis = self.app.env.exec_info_stack
228 eis.current_page_info.render_ctx.used_taxonomy_terms.add( 242 eis.current_page_info.render_ctx.used_taxonomy_terms.add(
229 (self.source_name, self.taxonomy, registered_values)) 243 (self.source_name, self.taxonomy_name,
230 244 registered_values))
231 if len(values) == 1: 245
232 str_values = values[0] 246 str_values = self.slugifyTaxonomyTerm(registered_values)
233 else:
234 str_values = '/'.join(values)
235 term_name = self.template_func_args[0] 247 term_name = self.template_func_args[0]
236 metadata = {term_name: str_values} 248 metadata = {term_name: str_values}
237 249
238 return self.getUri(metadata) 250 return self.getUri(metadata)
239 251
268 "with route function with arguments '%s'." % 280 "with route function with arguments '%s'." %
269 (route.template_func_args, self._arg_names)) 281 (route.template_func_args, self._arg_names))
270 self._funcs.append((route, route.template_func)) 282 self._funcs.append((route, route.template_func))
271 283
272 def __call__(self, *args, **kwargs): 284 def __call__(self, *args, **kwargs):
273 if len(args) == len(self._arg_names): 285 if len(self._funcs) == 1 or len(args) == len(self._arg_names):
274 f = self._funcs[0][1] 286 f = self._funcs[0][1]
275 return f(*args, **kwargs) 287 return f(*args, **kwargs)
276 288
277 if len(args) == len(self._arg_names) + 1: 289 if len(args) == len(self._arg_names) + 1:
278 f_args = args[:-1] 290 f_args = args[:-1]