Mercurial > piecrust2
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/piecrust/generation/base.py Thu May 26 19:52:47 2016 -0700 @@ -0,0 +1,137 @@ +from werkzeug.utils import cached_property +from piecrust.baking.records import BakeRecordEntry +from piecrust.baking.worker import save_factory, JOB_BAKE +from piecrust.configuration import ConfigurationError +from piecrust.routing import create_route_metadata +from piecrust.sources.pageref import PageRef + + +class InvalidRecordExtraKey(Exception): + pass + + +class PageGeneratorBakeContext(object): + def __init__(self, app, record, pool, generator): + self._app = app + self._record = record + self._pool = pool + self._generator = generator + self._job_queue = [] + self._is_running = False + + def getRecordExtraKey(self, seed): + return '%s:%s' % (self._generator.name, seed) + + def matchesRecordExtraKey(self, extra_key): + return (extra_key is not None and + extra_key.startswith(self._generator.name + ':')) + + def getSeedFromRecordExtraKey(self, extra_key): + if not self.matchesRecordExtraKey(extra_key): + raise InvalidRecordExtraKey("Invalid extra key: %s" % extra_key) + return extra_key[len(self._generator.name) + 1:] + + def getAllPageRecords(self): + return self._record.transitions.values() + + def getBakedPageRecords(self): + for prev, cur in self.getAllPageRecords(): + if cur and cur.was_any_sub_baked: + yield (prev, cur) + + def collapseRecord(self, entry): + self._record.collapseEntry(entry) + + def queueBakeJob(self, page_fac, route, extra_route_metadata, seed): + if self._is_running: + raise Exception("The job queue is running.") + + extra_key = self.getRecordExtraKey(seed) + entry = BakeRecordEntry( + page_fac.source.name, + page_fac.path, + extra_key) + self._record.addEntry(entry) + + page = page_fac.buildPage() + route_metadata = create_route_metadata(page) + route_metadata.update(extra_route_metadata) + uri = route.getUri(route_metadata) + override_entry = self._record.getOverrideEntry(page.path, uri) + if override_entry is not None: + override_source = self.app.getSource( + override_entry.source_name) + if override_source.realm == fac.source.realm: + cur_entry.errors.append( + "Page '%s' maps to URL '%s' but is overriden " + "by page '%s'." % + (fac.ref_spec, uri, override_entry.path)) + logger.error(cur_entry.errors[-1]) + cur_entry.flags |= BakeRecordEntry.FLAG_OVERRIDEN + return + + route_index = self._app.routes.index(route) + job = { + 'type': JOB_BAKE, + 'job': { + 'factory_info': save_factory(page_fac), + 'generator_name': self._generator.name, + 'generator_record_key': extra_key, + 'route_index': route_index, + 'route_metadata': route_metadata, + 'dirty_source_names': self._record.dirty_source_names, + 'needs_config': True + } + } + self._job_queue.append(job) + + def runJobQueue(self): + def _handler(res): + entry = self._record.getCurrentEntry( + res['path'], res['generator_record_key']) + entry.config = res['config'] + entry.subs = res['sub_entries'] + if res['errors']: + entry.errors += res['errors'] + if entry.has_any_error: + self._record.current.success = False + + self._is_running = True + try: + ar = self._pool.queueJobs(self._job_queue, handler=_handler) + ar.wait() + finally: + self._is_running = False + + +class PageGenerator(object): + def __init__(self, app, name, config): + self.app = app + self.name = name + self.config = config or {} + + self.source_name = config.get('source') + if self.source_name is None: + raise ConfigurationError( + "Generator '%s' requires a source name" % name) + + page_ref = config.get('page') + if page_ref is None: + raise ConfigurationError( + "Generator '%s' requires a listing page ref." % name) + self.page_ref = PageRef(app, page_ref) + + @cached_property + def source(self): + for src in self.app.sources: + if src.name == self.source_name: + return src + raise Exception("Can't find source '%s' for generator '%s'." % ( + self.source_name, self.name)) + + def bake(self, ctx): + raise NotImplementedError() + + def onRouteFunctionUsed(self, route, route_metadata): + pass +