Mercurial > piecrust2
diff piecrust/serving.py @ 371:c2ca72fb7f0b 2.0.0a8
caching: Use separate caches for config variants and other contexts.
* The `_cache` directory is now organized in multiple "sub-caches" for
different contexts.
* A new context is created when config variants or overrides are applied.
* `serve` context uses a different context that the other commends, to prevent
the `bake` command's output from messing up the preview server (e.g. with
how asset URLs are generated differently between the two).
* Fix a few places where the cache directory was referenced directly.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Sun, 03 May 2015 23:59:46 -0700 |
parents | 4b1019bb2533 |
children |
line wrap: on
line diff
--- a/piecrust/serving.py Sun May 03 23:45:32 2015 -0700 +++ b/piecrust/serving.py Sun May 03 23:59:46 2015 -0700 @@ -66,9 +66,11 @@ class Server(object): def __init__(self, root_dir, - debug=False, use_reloader=False, static_preview=True): + debug=False, sub_cache_dir=None, + use_reloader=False, static_preview=True): self.root_dir = root_dir self.debug = debug + self.sub_cache_dir = sub_cache_dir self.use_reloader = use_reloader self.static_preview = static_preview self._out_dir = None @@ -80,7 +82,8 @@ # Bake all the assets so we know what we have, and so we can serve # them to the client. We need a temp app for this. app = PieCrust(root_dir=self.root_dir, debug=self.debug) - self._out_dir = os.path.join(app.cache_dir, 'server') + app._useSubCacheDir(self.sub_cache_dir) + self._out_dir = os.path.join(app.sub_cache_dir, 'server') self._page_record = ServeRecord() if (not self.use_reloader or @@ -129,6 +132,7 @@ # Create the app for this request. app = PieCrust(root_dir=self.root_dir, debug=self.debug) + app._useSubCacheDir(self.sub_cache_dir) app.config.set('site/root', '/') app.config.set('server/is_serving', True) if (app.config.get('site/enable_debug_info') and @@ -226,67 +230,35 @@ if len(routes) == 0: raise RouteNotFoundError("Can't find route for: %s" % req_path) - taxonomy = None - tax_terms = None + rendered_page = None + first_not_found = None for route, route_metadata in routes: - source = app.getSource(route.source_name) - if route.taxonomy_name is None: - factory = source.findPageFactory(route_metadata, MODE_PARSING) - if factory is not None: + try: + logger.debug("Trying to render match from source '%s'." % + route.source_name) + rendered_page = self._try_render_page( + app, route, route_metadata, page_num, req_path) + if rendered_page is not None: break - else: - taxonomy = app.getTaxonomy(route.taxonomy_name) - route_terms = route_metadata.get(taxonomy.term_name) - if route_terms is not None: - tax_page_ref = taxonomy.getPageRef(source.name) - factory = tax_page_ref.getFactory() - tax_terms = route.unslugifyTaxonomyTerm(route_terms) - factory.metadata[taxonomy.term_name] = tax_terms - break + except NotFound as nfe: + if first_not_found is None: + first_not_found = nfe else: raise SourceNotFoundError( "Can't find path for: %s (looked in: %s)" % (req_path, [r.source_name for r, _ in routes])) - # Build the page. - page = factory.buildPage() - # We force the rendering of the page because it could not have - # changed, but include pages that did change. - qp = QualifiedPage(page, route, route_metadata) - render_ctx = PageRenderingContext(qp, - page_num=page_num, - force_render=True) - if taxonomy is not None: - render_ctx.setTaxonomyFilter(taxonomy, tax_terms) + # If we haven't found any good match, raise whatever exception we + # first got. Otherwise, raise a generic exception. + if rendered_page is None: + first_not_found = first_not_found or NotFound( + "This page couldn't be found.") + raise first_not_found - # See if this page is known to use sources. If that's the case, - # just don't use cached rendered segments for that page (but still - # use them for pages that are included in it). - entry = self._page_record.getEntry(req_path, page_num) - if (taxonomy is not None or entry is None or - entry.used_source_names): - cache_key = '%s:%s' % (req_path, page_num) - app.env.rendered_segments_repository.invalidate(cache_key) - - # Render the page. - rendered_page = render_page(render_ctx) + # Start doing stuff. + page = rendered_page.page rp_content = rendered_page.content - if taxonomy is not None: - paginator = rendered_page.data.get('pagination') - if (paginator and paginator.is_loaded and - len(paginator.items) == 0): - message = ("This URL matched a route for taxonomy '%s' but " - "no pages have been found to have it. This page " - "won't be generated by a bake." % taxonomy.name) - raise NotFound(message) - - if entry is None: - entry = ServeRecordPageEntry(req_path, page_num) - self._page_record.addEntry(entry) - for p, pinfo in render_ctx.render_passes.items(): - entry.used_source_names |= pinfo.used_source_names - # Profiling. if app.config.get('site/show_debug_info'): now_time = time.clock() @@ -341,6 +313,74 @@ return response + def _try_render_page(self, app, route, route_metadata, page_num, req_path): + # Match the route to an actual factory. + taxonomy_info = None + source = app.getSource(route.source_name) + if route.taxonomy_name is None: + factory = source.findPageFactory(route_metadata, MODE_PARSING) + if factory is None: + return None + else: + taxonomy = app.getTaxonomy(route.taxonomy_name) + route_terms = route_metadata.get(taxonomy.term_name) + if route_terms is None: + return None + + tax_page_ref = taxonomy.getPageRef(source.name) + factory = tax_page_ref.getFactory() + tax_terms = route.unslugifyTaxonomyTerm(route_terms) + route_metadata[taxonomy.term_name] = tax_terms + taxonomy_info = (taxonomy, tax_terms) + + # Build the page. + page = factory.buildPage() + # We force the rendering of the page because it could not have + # changed, but include pages that did change. + qp = QualifiedPage(page, route, route_metadata) + render_ctx = PageRenderingContext(qp, + page_num=page_num, + force_render=True) + if taxonomy_info is not None: + taxonomy, tax_terms = taxonomy_info + render_ctx.setTaxonomyFilter(taxonomy, tax_terms) + + # See if this page is known to use sources. If that's the case, + # just don't use cached rendered segments for that page (but still + # use them for pages that are included in it). + uri = qp.getUri() + assert uri == req_path + entry = self._page_record.getEntry(uri, page_num) + if (taxonomy_info is not None or entry is None or + entry.used_source_names): + cache_key = '%s:%s' % (uri, page_num) + app.env.rendered_segments_repository.invalidate(cache_key) + + # Render the page. + rendered_page = render_page(render_ctx) + + # Check if this page is a taxonomy page that actually doesn't match + # anything. + if taxonomy_info is not None: + paginator = rendered_page.data.get('pagination') + if (paginator and paginator.is_loaded and + len(paginator.items) == 0): + taxonomy = taxonomy_info[0] + message = ("This URL matched a route for taxonomy '%s' but " + "no pages have been found to have it. This page " + "won't be generated by a bake." % taxonomy.name) + raise NotFound(message) + + # Remember stuff for next time. + if entry is None: + entry = ServeRecordPageEntry(req_path, page_num) + self._page_record.addEntry(entry) + for p, pinfo in render_ctx.render_passes.items(): + entry.used_source_names |= pinfo.used_source_names + + # Ok all good. + return rendered_page + def _make_wrapped_file_response(self, environ, request, path): logger.debug("Serving %s" % path)