예제 #1
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        page = feed_source.parent

        feed = AtomFeed(
            title=page.record_label + u' — Pallets Project',
            feed_url=url_to(feed_source, external=True),
            url=url_to('/blog', external=True),
            id=get_id(ctx.env.project.id)
        )

        for item in page.children.order_by(
            '-pub_date', '-pub_order', 'title'
        ).limit(10):
            item_author = item['author']

            feed.add(
                item['title'],
                text_type(item['body']),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%s/%s' % (
                    ctx.env.project.id,
                    item['_path'].encode('utf-8'))),
                author=item_author,
                updated=datetime(*item['pub_date'].timetuple()[:3]))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
    def generate_feed(artifact):
        feed = AtomFeed(
            title=title or 'Feed',
            subtitle=unicode(subtitle or ''),
            subtitle_type=hasattr(subtitle, '__html__') and 'html' or 'text',
            feed_url=feed_url,
            url=embed_url,
            id=get_id(ctx.env.project.id + 'lektor')
        )

        for item in items:
            feed.add(
                get_item_title(item, item_title_field),
                get_item_body(item, item_body_field),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%slektor/%s' % (
                    ctx.env.project.id,
                    item['_path'].encode('utf-8'),
                )),
                author=get_item_author(item, item_author_field),
                updated=get_item_updated(item, item_date_field))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8') + '\n')
예제 #3
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        blog = feed_source.parent

        summary = get(blog, feed_source.blog_summary_field) or ''
        subtitle_type = ('html' if hasattr(summary, '__html__') else 'text')
        blog_author = unicode(get(blog, feed_source.blog_author_field) or '')
        generator = ('Lektor Atom Plugin',
                     'https://github.com/ajdavis/lektor-atom',
                     pkg_resources.get_distribution('lektor-atom').version)

        project_id = ctx.env.load_config().base_url
        if not project_id:
            project_id = ctx.env.project.id
        feed = AtomFeed(
            title=feed_source.feed_name,
            subtitle=unicode(summary),
            subtitle_type=subtitle_type,
            author=blog_author,
            feed_url=url_to(feed_source, external=True),
            url=url_to(blog, external=True),
            id=get_id(project_id),
            generator=generator)

        if feed_source.items:
            # "feed_source.items" is a string like "site.query('/blog')".
            expr = Expression(ctx.env, feed_source.items)
            items = expr.evaluate(ctx.pad)
        else:
            items = blog.children

        if feed_source.item_model:
            items = items.filter(F._model == feed_source.item_model)

        order_by = '-' + feed_source.item_date_field
        items = items.order_by(order_by).limit(int(feed_source.limit))

        for item in items:
            item_author_field = feed_source.item_author_field
            item_author = get(item, item_author_field) or blog_author

            feed.add(
                get_item_title(item, feed_source.item_title_field),
                get_item_body(item, feed_source.item_body_field),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%s/%s' % (
                    project_id,
                    item['_path'].encode('utf-8'))),
                author=item_author,
                updated=get_item_updated(item, feed_source.item_date_field))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))
예제 #4
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=["jinja2.ext.autoescape", "jinja2.ext.with_"],
            loader=jinja2.FileSystemLoader(os.path.join(self.root_path, "templates")),
        )

        from lektor.db import F

        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types

        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers

        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []

        if load_plugins:
            self.load_plugins()
예제 #5
0
    def __init__(self, project):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                os.path.join(self.root_path, 'templates'))
        )

        from lektor.db import F
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(get_asset_url(*a, **kw))),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
예제 #6
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        source = self.source

        appcast = AppCast(
            title=source.cast_name,
            link=url_to(source, external=True),
        )

        try:
            expr = Expression(ctx.env, source.items)
        except AttributeError:
            items = source.parent.children
        else:
            items = expr.evaluate(ctx.pad)

        if source.item_model:
            items = items.filter(F._model == source.item_model)
        items = items.order_by('-build_number')

        for item in items:
            with ctx.changed_base_url(item.url_path):
                description = six.text_type(markupsafe.escape(item['note']))

            try:
                offset = int(source.timezone)
            except ValueError:
                tzinfo = pytz.timezone(source.timezone)
            else:
                tzinfo = pytz.FixedOffset(offset)
            pub_date = item['pub_datetime'].replace(tzinfo=tzinfo)

            try:
                build_number = str(item['build_number'])
                if '.' in build_number:
                    build_number = build_number.rstrip('0').rstrip('.')
                appcast.add(
                    title='Version {}'.format(item['version']),
                    description=description,
                    pub_date=pub_date,
                    url=item['download_url'],
                    build=build_number,
                    version=item['version'],
                    length=item['length'],
                    dsasign=item['dsa_signature'],
                    minsysver=item['min_sysver'],
                )
            except Exception as e:
                msg = '{}: {}'.format(item.id, e)
                click.echo(click.style('E', fg='red') + ' ' + msg)

        with artifact.open('wb') as f:
            f.write(appcast.to_string().encode('utf-8'))
예제 #7
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.theme_paths = [os.path.join(self.root_path, 'themes', theme)
                            for theme in self.project.themes]

        if not self.theme_paths:
            # load the directories in the themes directory as the themes
            try:
                for fname in os.listdir(os.path.join(self.root_path, 'themes')):
                    f = os.path.join(self.root_path, 'themes', fname)
                    if os.path.isdir(f):
                        self.theme_paths.append(f)
            except OSError:
                pass

        template_paths = [os.path.join(path, 'templates')
                          for path in [self.root_path] + self.theme_paths]

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                template_paths)
        )

        from lektor.db import F, get_alts
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(
                lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_alts=get_alts,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers
        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []
        self.virtual_sources = {}

        if load_plugins:
            self.load_plugins()

        from lektor.db import siblings_resolver
        self.virtualpathresolver('siblings')(siblings_resolver)
def create_atom_feed(filename='atom.xml',
                     title=None, subtitle=None,
                     link=None, items=None, item_title_field='title',
                     item_body_field='body', item_author_field='author',
                     item_date_field='pub_date'):
    ctx = get_ctx()
    if ctx is None:
        raise RuntimeError('A context is required')
    source = ctx.source
    if source is None:
        raise RuntimeError('Can only generate feeds out of sources.')
    if items is None:
        raise RuntimeError('An item expression is required')

    artifact_name = posixpath.join(source.url_path, filename)
    config_hash = get_structure_hash({
        'filename': filename,
        'title': title,
        'subtitle': subtitle,
        'link': link,
        'items': items,
        'item_title_field': item_title_field,
        'item_body_field': item_body_field,
        'item_author_field': item_author_field,
        'item_date_field': item_date_field,
    })

    # Iterating over the items will resolve dependencies.  As we are very
    # interested in those, we need to capture tem,
    dependencies = set()
    with ctx.gather_dependencies(dependencies.add):
        items = list(items)

    here = posixpath.join(source.url_path, filename)
    feed_url = url_to(here, external=True)
    embed_url = url_to(source, external=True)

    @ctx.sub_artifact(artifact_name, source_obj=ctx.source,
                      sources=list(dependencies),
                      config_hash=config_hash)
    def generate_feed(artifact):
        feed = AtomFeed(
            title=title or 'Feed',
            subtitle=unicode(subtitle or ''),
            subtitle_type=hasattr(subtitle, '__html__') and 'html' or 'text',
            feed_url=feed_url,
            url=embed_url,
            id=get_id(ctx.env.project.id + 'lektor')
        )

        for item in items:
            feed.add(
                get_item_title(item, item_title_field),
                get_item_body(item, item_body_field),
                xml_base=url_to(item, external=True),
                url=url_to(item, external=True),
                content_type='html',
                id=get_id(u'%slektor/%s' % (
                    ctx.env.project.id,
                    item['_path'].encode('utf-8'),
                )),
                author=get_item_author(item, item_author_field),
                updated=get_item_updated(item, item_date_field))

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8') + '\n')

    return artifact_name
예제 #9
0
    def __init__(self, project, load_plugins=True):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=['jinja2.ext.autoescape', 'jinja2.ext.with_'],
            loader=jinja2.FileSystemLoader(
                os.path.join(self.root_path, 'templates')))

        from lektor.db import F
        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types
        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers
        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []
        self.virtual_sources = {}

        if load_plugins:
            self.load_plugins()

        from lektor.db import siblings_resolver
        self.virtualpathresolver('siblings')(siblings_resolver)
예제 #10
0
    def __init__(self, project, load_plugins=True, extra_flags=None):
        self.project = project
        self.root_path = os.path.abspath(project.tree)

        self.theme_paths = [
            os.path.join(self.root_path, "themes", theme)
            for theme in self.project.themes
        ]

        if not self.theme_paths:
            # load the directories in the themes directory as the themes
            try:
                for fname in os.listdir(os.path.join(self.root_path,
                                                     "themes")):
                    f = os.path.join(self.root_path, "themes", fname)
                    if os.path.isdir(f):
                        self.theme_paths.append(f)
            except OSError:
                pass

        template_paths = [
            os.path.join(path, "templates")
            for path in [self.root_path] + self.theme_paths
        ]

        self.jinja_env = CustomJinjaEnvironment(
            autoescape=self.select_jinja_autoescape,
            extensions=[
                "jinja2.ext.autoescape", "jinja2.ext.with_", "jinja2.ext.do"
            ],
            loader=jinja2.FileSystemLoader(template_paths),
        )

        from lektor.db import F, get_alts

        self.jinja_env.filters.update(
            tojson=tojson_filter,
            latformat=lambda x, secs=True: format_lat_long(lat=x, secs=secs),
            longformat=lambda x, secs=True: format_lat_long(long=x, secs=secs),
            latlongformat=lambda x, secs=True: format_lat_long(secs=secs, *x),
            # By default filters need to be side-effect free.  This is not
            # the case for this one, so we need to make it as a dummy
            # context filter so that jinja2 will not inline it.
            url=jinja2.contextfilter(lambda ctx, *a, **kw: url_to(*a, **kw)),
            asseturl=jinja2.contextfilter(
                lambda ctx, *a, **kw: get_asset_url(*a, **kw)),
            markdown=jinja2.contextfilter(
                lambda ctx, *a, **kw: Markdown(*a, **kw)),
        )
        self.jinja_env.globals.update(
            F=F,
            url_to=url_to,
            site=site_proxy,
            config=config_proxy,
            bag=lookup_from_bag,
            get_alts=get_alts,
            get_random_id=lambda: uuid.uuid4().hex,
        )
        self.jinja_env.filters.update(
            datetimeformat=_pass_locale(dates.format_datetime),
            dateformat=_pass_locale(dates.format_date),
            timeformat=_pass_locale(dates.format_time),
        )

        from lektor.types import builtin_types

        self.types = builtin_types.copy()

        from lektor.publisher import builtin_publishers

        self.publishers = builtin_publishers.copy()

        # The plugins that are loaded for this environment.  This is
        # modified by the plugin controller and registry methods on the
        # environment.
        self.plugin_controller = PluginController(self, extra_flags)
        self.plugins = {}
        self.plugin_ids_by_class = {}
        self.build_programs = []
        self.special_file_assets = {}
        self.special_file_suffixes = {}
        self.custom_url_resolvers = []
        self.custom_generators = []
        self.virtual_sources = {}

        if load_plugins:
            self.load_plugins()

        from lektor.db import siblings_resolver

        self.virtualpathresolver("siblings")(siblings_resolver)
예제 #11
0
    def build_artifact(self, artifact):
        ctx = get_ctx()
        feed_source = self.source
        blog = feed_source.parent

        summary = get(blog, feed_source.blog_summary_field) or ''
        if hasattr(summary, '__html__'):
            subtitle_type = 'html'
            summary = text_type(summary.__html__())
        else:
            subtitle_type = 'text'
        blog_author = text_type(get(blog, feed_source.blog_author_field) or '')
        generator = ('Lektor Atom Plugin',
                     'https://github.com/ajdavis/lektor-atom',
                     pkg_resources.get_distribution('lektor-atom').version)

        feed = AtomFeed(title=feed_source.feed_name,
                        subtitle=summary,
                        subtitle_type=subtitle_type,
                        author=blog_author,
                        feed_url=url_to(feed_source, external=True),
                        url=url_to(blog, external=True),
                        id=get_id(ctx.env.project.id),
                        generator=generator)

        if feed_source.items:
            # "feed_source.items" is a string like "site.query('/blog')".
            expr = Expression(ctx.env, feed_source.items)
            items = expr.evaluate(ctx.pad)
        else:
            items = blog.children

        if feed_source.item_model:
            items = items.filter(F._model == feed_source.item_model)

        order_by = '-' + feed_source.item_date_field
        items = items.order_by(order_by).limit(int(feed_source.limit))

        for item in items:
            try:
                item_author_field = feed_source.item_author_field
                item_author = get(item, item_author_field) or blog_author

                feed.add(
                    get_item_title(item, feed_source.item_title_field),
                    get_item_body(item, feed_source.item_body_field),
                    xml_base=url_to(item, external=True),
                    url=url_to(item, external=True),
                    content_type='html',
                    id=get_id(
                        u'%s/%s' %
                        (ctx.env.project.id, item['_path'].encode('utf-8'))),
                    author=item_author,
                    updated=get_item_updated(item,
                                             feed_source.item_date_field))
            except Exception as exc:
                msg = '%s: %s' % (item.id, exc)
                click.echo(click.style('E', fg='red') + ' ' + msg)

        with artifact.open('wb') as f:
            f.write(feed.to_string().encode('utf-8'))