comparison piecrust/generation/base.py @ 711:ab5c6a8ae90a

bake: Replace hard-coded taxonomy support with "generator" system. * Taxonomies are now implemented one or more `TaxonomyGenerator`s. * A `BlogArchivesGenerator` stub is there but non-functional.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 26 May 2016 19:52:47 -0700
parents
children 606f6d57b5df
comparison
equal deleted inserted replaced
710:e85f29b28b84 711:ab5c6a8ae90a
1 from werkzeug.utils import cached_property
2 from piecrust.baking.records import BakeRecordEntry
3 from piecrust.baking.worker import save_factory, JOB_BAKE
4 from piecrust.configuration import ConfigurationError
5 from piecrust.routing import create_route_metadata
6 from piecrust.sources.pageref import PageRef
7
8
9 class InvalidRecordExtraKey(Exception):
10 pass
11
12
13 class PageGeneratorBakeContext(object):
14 def __init__(self, app, record, pool, generator):
15 self._app = app
16 self._record = record
17 self._pool = pool
18 self._generator = generator
19 self._job_queue = []
20 self._is_running = False
21
22 def getRecordExtraKey(self, seed):
23 return '%s:%s' % (self._generator.name, seed)
24
25 def matchesRecordExtraKey(self, extra_key):
26 return (extra_key is not None and
27 extra_key.startswith(self._generator.name + ':'))
28
29 def getSeedFromRecordExtraKey(self, extra_key):
30 if not self.matchesRecordExtraKey(extra_key):
31 raise InvalidRecordExtraKey("Invalid extra key: %s" % extra_key)
32 return extra_key[len(self._generator.name) + 1:]
33
34 def getAllPageRecords(self):
35 return self._record.transitions.values()
36
37 def getBakedPageRecords(self):
38 for prev, cur in self.getAllPageRecords():
39 if cur and cur.was_any_sub_baked:
40 yield (prev, cur)
41
42 def collapseRecord(self, entry):
43 self._record.collapseEntry(entry)
44
45 def queueBakeJob(self, page_fac, route, extra_route_metadata, seed):
46 if self._is_running:
47 raise Exception("The job queue is running.")
48
49 extra_key = self.getRecordExtraKey(seed)
50 entry = BakeRecordEntry(
51 page_fac.source.name,
52 page_fac.path,
53 extra_key)
54 self._record.addEntry(entry)
55
56 page = page_fac.buildPage()
57 route_metadata = create_route_metadata(page)
58 route_metadata.update(extra_route_metadata)
59 uri = route.getUri(route_metadata)
60 override_entry = self._record.getOverrideEntry(page.path, uri)
61 if override_entry is not None:
62 override_source = self.app.getSource(
63 override_entry.source_name)
64 if override_source.realm == fac.source.realm:
65 cur_entry.errors.append(
66 "Page '%s' maps to URL '%s' but is overriden "
67 "by page '%s'." %
68 (fac.ref_spec, uri, override_entry.path))
69 logger.error(cur_entry.errors[-1])
70 cur_entry.flags |= BakeRecordEntry.FLAG_OVERRIDEN
71 return
72
73 route_index = self._app.routes.index(route)
74 job = {
75 'type': JOB_BAKE,
76 'job': {
77 'factory_info': save_factory(page_fac),
78 'generator_name': self._generator.name,
79 'generator_record_key': extra_key,
80 'route_index': route_index,
81 'route_metadata': route_metadata,
82 'dirty_source_names': self._record.dirty_source_names,
83 'needs_config': True
84 }
85 }
86 self._job_queue.append(job)
87
88 def runJobQueue(self):
89 def _handler(res):
90 entry = self._record.getCurrentEntry(
91 res['path'], res['generator_record_key'])
92 entry.config = res['config']
93 entry.subs = res['sub_entries']
94 if res['errors']:
95 entry.errors += res['errors']
96 if entry.has_any_error:
97 self._record.current.success = False
98
99 self._is_running = True
100 try:
101 ar = self._pool.queueJobs(self._job_queue, handler=_handler)
102 ar.wait()
103 finally:
104 self._is_running = False
105
106
107 class PageGenerator(object):
108 def __init__(self, app, name, config):
109 self.app = app
110 self.name = name
111 self.config = config or {}
112
113 self.source_name = config.get('source')
114 if self.source_name is None:
115 raise ConfigurationError(
116 "Generator '%s' requires a source name" % name)
117
118 page_ref = config.get('page')
119 if page_ref is None:
120 raise ConfigurationError(
121 "Generator '%s' requires a listing page ref." % name)
122 self.page_ref = PageRef(app, page_ref)
123
124 @cached_property
125 def source(self):
126 for src in self.app.sources:
127 if src.name == self.source_name:
128 return src
129 raise Exception("Can't find source '%s' for generator '%s'." % (
130 self.source_name, self.name))
131
132 def bake(self, ctx):
133 raise NotImplementedError()
134
135 def onRouteFunctionUsed(self, route, route_metadata):
136 pass
137