comparison piecrust/sources/taxonomy.py @ 856:9bb22bbe093c

refactor: Make the blog archives functional again. The blog archives are using the same pattern as the taxonomy support.
author Ludovic Chabant <ludovic@chabant.com>
date Tue, 06 Jun 2017 01:23:25 -0700
parents 448710d84121
children 504ddb370df8
comparison
equal deleted inserted replaced
855:448710d84121 856:9bb22bbe093c
1 import io
2 import re 1 import re
3 import time
4 import logging 2 import logging
5 import unidecode 3 import unidecode
6 from werkzeug.utils import cached_property
7 from piecrust.configuration import ConfigurationError 4 from piecrust.configuration import ConfigurationError
8 from piecrust.data.filters import ( 5 from piecrust.data.filters import (
9 PaginationFilter, SettingFilterClause) 6 PaginationFilter, SettingFilterClause)
10 from piecrust.page import Page 7 from piecrust.page import Page
11 from piecrust.pipelines._pagebaker import PageBaker 8 from piecrust.pipelines._pagebaker import PageBaker
12 from piecrust.pipelines._pagerecords import PagePipelineRecordEntry 9 from piecrust.pipelines._pagerecords import PagePipelineRecordEntry
13 from piecrust.pipelines.base import ( 10 from piecrust.pipelines.base import (
14 ContentPipeline, get_record_name_for_source) 11 ContentPipeline, get_record_name_for_source)
15 from piecrust.pipelines.records import RecordHistory 12 from piecrust.pipelines.records import RecordHistory
16 from piecrust.routing import RouteParameter 13 from piecrust.routing import RouteParameter
17 from piecrust.sources.base import ( 14 from piecrust.sources.base import ContentItem
18 ContentItem, ContentSource, GeneratedContentException) 15 from piecrust.sources.generator import GeneratorSourceBase
19 16
20 17
21 logger = logging.getLogger(__name__) 18 logger = logging.getLogger(__name__)
22 19
23 20
55 layout: %(template)s 52 layout: %(template)s
56 --- 53 ---
57 """ 54 """
58 55
59 56
60 class TaxonomySource(ContentSource): 57 class TaxonomySource(GeneratorSourceBase):
61 """ A content source that generates taxonomy listing pages. 58 """ A content source that generates taxonomy listing pages.
62 """ 59 """
63 SOURCE_NAME = 'taxonomy' 60 SOURCE_NAME = 'taxonomy'
64 DEFAULT_PIPELINE_NAME = 'taxonomy' 61 DEFAULT_PIPELINE_NAME = 'taxonomy'
65 62
66 def __init__(self, app, name, config): 63 def __init__(self, app, name, config):
67 super().__init__(app, name, config) 64 super().__init__(app, name, config)
68
69 source_name = config.get('source')
70 if source_name is None:
71 raise ConfigurationError(
72 "Taxonomy source '%s' requires an inner source." % name)
73 self._inner_source_name = source_name
74 65
75 tax_name = config.get('taxonomy') 66 tax_name = config.get('taxonomy')
76 if tax_name is None: 67 if tax_name is None:
77 raise ConfigurationError( 68 raise ConfigurationError(
78 "Taxonomy source '%s' requires a taxonomy name." % name) 69 "Taxonomy source '%s' requires a taxonomy name." % name)
81 sm = config.get('slugify_mode') 72 sm = config.get('slugify_mode')
82 self.slugifier = _get_slugifier(app, self.taxonomy, sm) 73 self.slugifier = _get_slugifier(app, self.taxonomy, sm)
83 74
84 tpl_name = config.get('template', '_%s.html' % tax_name) 75 tpl_name = config.get('template', '_%s.html' % tax_name)
85 self._raw_item = _taxonomy_index % {'template': tpl_name} 76 self._raw_item = _taxonomy_index % {'template': tpl_name}
86
87 @cached_property
88 def inner_source(self):
89 return self.app.getSource(self._inner_source_name)
90
91 def openItem(self, item, mode='r', **kwargs):
92 return io.StringIO(self._raw_item)
93
94 def getItemMtime(self, item):
95 return time.time()
96
97 def getContents(self, group):
98 # Our content is procedurally generated from other content sources,
99 # so we really don't support listing anything here -- it would be
100 # quite costly.
101 #
102 # Instead, our pipeline (the `TaxonomyPipeline`) will generate
103 # content items for us when it is asked to produce bake jobs.
104 raise GeneratedContentException()
105 77
106 def getSupportedRouteParameters(self): 78 def getSupportedRouteParameters(self):
107 name = self.taxonomy.term_name 79 name = self.taxonomy.term_name
108 param_type = (RouteParameter.TYPE_PATH if self.taxonomy.is_multiple 80 param_type = (RouteParameter.TYPE_PATH if self.taxonomy.is_multiple
109 else RouteParameter.TYPE_STRING) 81 else RouteParameter.TYPE_STRING)
319 (self.taxonomy.name, content_item.metadata['term'])) 291 (self.taxonomy.name, content_item.metadata['term']))
320 292
321 page = Page(self.source, job.content_item) 293 page = Page(self.source, job.content_item)
322 prev_entry = ctx.previous_entry 294 prev_entry = ctx.previous_entry
323 cur_entry = result.record_entry 295 cur_entry = result.record_entry
296 cur_entry.term = content_item.metadata['term']
324 self._pagebaker.bake(page, prev_entry, cur_entry, []) 297 self._pagebaker.bake(page, prev_entry, cur_entry, [])
325 298
326 def postJobRun(self, ctx): 299 def postJobRun(self, ctx):
327 # We create bake entries for all the terms that were *not* dirty. 300 # We create bake entries for all the terms that were *not* dirty.
328 # This is because otherwise, on the next incremental bake, we wouldn't 301 # This is because otherwise, on the next incremental bake, we wouldn't