Mercurial > piecrust2
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 |