Mercurial > piecrust2
comparison piecrust/sources/taxonomy.py @ 989:8adc27285d93
bake: Big pass on bake performance.
- Reduce the amount of data passed between processes.
- Make inter-process data simple objects to make it easier to test with
alternatives to pickle.
- Make sources have the basic requirement to be able to find a content item
from an item spec (path).
- Make Hoedown the default Markdown formatter.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 19 Nov 2017 14:29:17 -0800 |
parents | 45ad976712ec |
children | 1857dbd4580f |
comparison
equal
deleted
inserted
replaced
988:f83ae0a5d793 | 989:8adc27285d93 |
---|---|
5 from piecrust.configuration import ConfigurationError | 5 from piecrust.configuration import ConfigurationError |
6 from piecrust.data.filters import ( | 6 from piecrust.data.filters import ( |
7 PaginationFilter, SettingFilterClause) | 7 PaginationFilter, SettingFilterClause) |
8 from piecrust.page import Page | 8 from piecrust.page import Page |
9 from piecrust.pipelines._pagebaker import PageBaker | 9 from piecrust.pipelines._pagebaker import PageBaker |
10 from piecrust.pipelines._pagerecords import PagePipelineRecordEntry | 10 from piecrust.pipelines._pagerecords import ( |
11 PagePipelineRecordEntry, | |
12 add_page_job_result, merge_job_result_into_record_entry) | |
11 from piecrust.pipelines.base import ( | 13 from piecrust.pipelines.base import ( |
12 ContentPipeline, get_record_name_for_source) | 14 ContentPipeline, get_record_name_for_source, |
15 create_job, content_item_from_job) | |
13 from piecrust.pipelines.records import RecordHistory | 16 from piecrust.pipelines.records import RecordHistory |
14 from piecrust.routing import RouteParameter | 17 from piecrust.routing import RouteParameter |
15 from piecrust.sources.base import ContentItem | 18 from piecrust.sources.base import ContentItem |
16 from piecrust.sources.generator import GeneratorSourceBase | 19 from piecrust.sources.generator import GeneratorSourceBase |
17 | 20 |
81 param_type = (RouteParameter.TYPE_PATH if self.taxonomy.is_multiple | 84 param_type = (RouteParameter.TYPE_PATH if self.taxonomy.is_multiple |
82 else RouteParameter.TYPE_STRING) | 85 else RouteParameter.TYPE_STRING) |
83 return [RouteParameter(name, param_type, | 86 return [RouteParameter(name, param_type, |
84 variadic=self.taxonomy.is_multiple)] | 87 variadic=self.taxonomy.is_multiple)] |
85 | 88 |
86 def findContent(self, route_params): | 89 def findContentFromRoute(self, route_params): |
87 slugified_term = route_params[self.taxonomy.term_name] | 90 slugified_term = route_params[self.taxonomy.term_name] |
88 spec = '_index' | 91 spec = '_index' |
89 metadata = {'term': slugified_term, | 92 metadata = {'term': slugified_term, |
90 'record_entry_spec': '_index[%s]' % slugified_term, | |
91 'route_params': { | 93 'route_params': { |
92 self.taxonomy.term_name: slugified_term} | 94 self.taxonomy.term_name: slugified_term} |
93 } | 95 } |
94 return ContentItem(spec, metadata) | 96 return ContentItem(spec, metadata) |
95 | 97 |
172 slugified_values = self.slugify(str(values)) | 174 slugified_values = self.slugify(str(values)) |
173 route_val = slugified_values | 175 route_val = slugified_values |
174 | 176 |
175 # We need to register this use of a taxonomy term. | 177 # We need to register this use of a taxonomy term. |
176 rcs = self.app.env.render_ctx_stack | 178 rcs = self.app.env.render_ctx_stack |
177 cpi = rcs.current_ctx.current_pass_info | 179 ri = rcs.current_ctx.render_info |
178 if cpi: | 180 utt = ri.get('used_taxonomy_terms') |
179 utt = cpi.getCustomInfo('used_taxonomy_terms') | 181 if utt is None: |
180 if utt is None: | 182 utt = set() |
181 utt = set() | 183 utt.add(slugified_values) |
182 utt.add(slugified_values) | 184 ri['used_taxonomy_terms'] = utt |
183 cpi.setCustomInfo('used_taxonomy_terms', utt) | 185 else: |
184 else: | 186 utt.add(slugified_values) |
185 utt.add(slugified_values) | |
186 | 187 |
187 # Put the slugified values in the route metadata so they're used to | 188 # Put the slugified values in the route metadata so they're used to |
188 # generate the URL. | 189 # generate the URL. |
189 route_params[self.taxonomy.term_name] = route_val | 190 route_params[self.taxonomy.term_name] = route_val |
190 | 191 |
285 | 286 |
286 logger.debug("Queuing %d '%s' jobs." % | 287 logger.debug("Queuing %d '%s' jobs." % |
287 (len(self._analyzer.dirty_slugified_terms), | 288 (len(self._analyzer.dirty_slugified_terms), |
288 self.taxonomy.name)) | 289 self.taxonomy.name)) |
289 jobs = [] | 290 jobs = [] |
291 rec_fac = self.createRecordEntry | |
292 current_record = ctx.current_record | |
293 | |
290 for slugified_term in self._analyzer.dirty_slugified_terms: | 294 for slugified_term in self._analyzer.dirty_slugified_terms: |
291 item = ContentItem( | 295 item_spec = '_index' |
292 '_index', | 296 record_entry_spec = '_index[%s]' % slugified_term |
293 {'term': slugified_term, | 297 |
294 'record_entry_spec': '_index[%s]' % slugified_term, | 298 jobs.append(create_job(self, item_spec, |
295 'route_params': { | 299 term=slugified_term, |
296 self.taxonomy.term_name: slugified_term} | 300 record_entry_spec=record_entry_spec)) |
297 }) | 301 |
298 jobs.append(self.createJob(item)) | 302 entry = rec_fac(record_entry_spec) |
303 current_record.addEntry(entry) | |
304 | |
299 if len(jobs) > 0: | 305 if len(jobs) > 0: |
300 return jobs | 306 return jobs |
301 return None | 307 return None |
302 | 308 |
303 def run(self, job, ctx, result): | 309 def run(self, job, ctx, result): |
304 content_item = job.content_item | 310 term = job['term'] |
311 content_item = ContentItem('_index', | |
312 {'term': term, | |
313 'route_params': { | |
314 self.taxonomy.term_name: term} | |
315 }) | |
316 page = Page(self.source, content_item) | |
317 | |
305 logger.debug("Rendering '%s' page: %s" % | 318 logger.debug("Rendering '%s' page: %s" % |
306 (self.taxonomy.name, content_item.metadata['term'])) | 319 (self.taxonomy.name, page.source_metadata['term'])) |
307 | |
308 page = Page(self.source, job.content_item) | |
309 prev_entry = ctx.previous_entry | 320 prev_entry = ctx.previous_entry |
310 cur_entry = result.record_entry | 321 rdr_subs = self._pagebaker.bake(page, prev_entry) |
311 cur_entry.term = content_item.metadata['term'] | 322 |
312 self._pagebaker.bake(page, prev_entry, cur_entry) | 323 add_page_job_result(result) |
324 result['subs'] = rdr_subs | |
325 result['term'] = page.source_metadata['term'] | |
326 | |
327 def handleJobResult(self, result, ctx): | |
328 existing = ctx.record_entry | |
329 merge_job_result_into_record_entry(existing, result) | |
330 existing.term = result['term'] | |
313 | 331 |
314 def postJobRun(self, ctx): | 332 def postJobRun(self, ctx): |
315 # We create bake entries for all the terms that were *not* dirty. | 333 # We create bake entries for all the terms that were *not* dirty. |
316 # This is because otherwise, on the next incremental bake, we wouldn't | 334 # This is because otherwise, on the next incremental bake, we wouldn't |
317 # find any entry for those things, and figure that we need to delete | 335 # find any entry for those things, and figure that we need to delete |
379 self._addTerms( | 397 self._addTerms( |
380 slugifier, cur_entry.item_spec, cur_terms) | 398 slugifier, cur_entry.item_spec, cur_terms) |
381 | 399 |
382 # Re-bake all taxonomy terms that include new or changed pages, by | 400 # Re-bake all taxonomy terms that include new or changed pages, by |
383 # marking them as 'dirty'. | 401 # marking them as 'dirty'. |
384 previous_records = self.record_histories.previous | 402 history = self.record_histories.getHistory(record_name).copy() |
385 prev_rec = previous_records.getRecord(record_name) | |
386 history = RecordHistory(prev_rec, cur_rec) | |
387 history.build() | 403 history.build() |
388 for prev_entry, cur_entry in history.diffs: | 404 for prev_entry, cur_entry in history.diffs: |
389 entries = [cur_entry] | 405 entries = [cur_entry] |
390 if prev_entry: | 406 if prev_entry: |
391 entries.append(prev_entry) | 407 entries.append(prev_entry) |
460 | 476 |
461 | 477 |
462 def _get_all_entry_taxonomy_terms(entry): | 478 def _get_all_entry_taxonomy_terms(entry): |
463 res = set() | 479 res = set() |
464 for o in entry.subs: | 480 for o in entry.subs: |
465 for pinfo in o.render_info: | 481 pinfo = o['render_info'] |
466 if pinfo: | 482 terms = pinfo.get('used_taxonomy_terms') |
467 terms = pinfo.getCustomInfo('used_taxonomy_terms') | 483 if terms: |
468 if terms: | 484 res |= set(terms) |
469 res |= set(terms) | |
470 return res | 485 return res |
471 | 486 |
472 | 487 |
473 class _Slugifier(object): | 488 class _Slugifier(object): |
474 def __init__(self, taxonomy, mode): | 489 def __init__(self, taxonomy, mode): |