view piecrust/data/paginationdata.py @ 852:4850f8c21b6e

core: Start of the big refactor for PieCrust 3.0. * Everything is a `ContentSource`, including assets directories. * Most content sources are subclasses of the base file-system source. * A source is processed by a "pipeline", and there are 2 built-in pipelines, one for assets and one for pages. The asset pipeline is vaguely functional, but the page pipeline is completely broken right now. * Rewrite the baking process as just running appropriate pipelines on each content item. This should allow for better parallelization.
author Ludovic Chabant <ludovic@chabant.com>
date Wed, 17 May 2017 00:11:48 -0700
parents a12ad254176e
children f070a4fc033c
line wrap: on
line source

import time
import logging
from piecrust.data.pagedata import LazyPageConfigData


logger = logging.getLogger(__name__)


class PaginationData(LazyPageConfigData):
    def __init__(self, qualified_page):
        super(PaginationData, self).__init__(qualified_page.page)
        self._qualified_page = qualified_page

    def _load(self):
        from piecrust.uriutil import split_uri

        page = self._page
        dt = page.datetime
        page_url = self._qualified_page.uri
        _, slug = split_uri(page.app, page_url)
        self._setValue('url', page_url)
        self._setValue('slug', slug)
        self._setValue(
            'timestamp',
            time.mktime(page.datetime.timetuple()))
        self._setValue('datetime', {
            'year': dt.year, 'month': dt.month, 'day': dt.day,
            'hour': dt.hour, 'minute': dt.minute, 'second': dt.second})
        date_format = page.app.config.get('site/date_format')
        if date_format:
            self._setValue('date', page.datetime.strftime(date_format))
        self._setValue('mtime', page.path_mtime)

        assetor = page.source.buildAssetor(page, page_url)
        self._setValue('assets', assetor)

        segment_names = page.config.get('segments')
        for name in segment_names:
            self._mapLoader(name, self._load_rendered_segment)

    def _load_rendered_segment(self, data, name):
        do_render = True
        stack = self._page.app.env.render_ctx_stack
        if stack.hasPage(self._page):
            # This is the pagination data for the page that is currently
            # being rendered! Inception! But this is possible... so just
            # prevent infinite recursion.
            do_render = False

        assert self is data

        if do_render:
            uri = self._qualified_page.uri
            try:
                from piecrust.rendering import (
                    RenderingContext, render_page_segments)
                ctx = RenderingContext(self._qualified_page)
                render_result = render_page_segments(ctx)
                segs = render_result.segments
            except Exception as ex:
                logger.exception(ex)
                raise Exception(
                    "Error rendering segments for '%s'" % uri) from ex
        else:
            segs = {}
            for name in self._page.config.get('segments'):
                segs[name] = "<unavailable: current page>"

        for k, v in segs.items():
            self._unmapLoader(k)
            self._setValue(k, v)

        if 'content.abstract' in segs:
            self._setValue('content', segs['content.abstract'])
            self._setValue('has_more', True)
            if name == 'content':
                return segs['content.abstract']

        return segs[name]