mirror of
https://github.com/getpelican/pelican.git
synced 2025-10-15 20:28:56 +02:00
Merge branch 'master' into switch-to-pytest
This commit is contained in:
commit
26f68e4749
13 changed files with 240 additions and 83 deletions
22
.travis.yml
22
.travis.yml
|
|
@ -9,21 +9,17 @@ addons:
|
|||
apt_packages:
|
||||
- pandoc
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo locale-gen fr_FR.UTF-8 tr_TR.UTF-8
|
||||
- sudo apt-get update -qq
|
||||
- sudo locale-gen fr_FR.UTF-8 tr_TR.UTF-8
|
||||
install:
|
||||
- pip install python-coveralls
|
||||
- pip install -U virtualenv py
|
||||
- pip install -e . -r dev_requirements.txt tox
|
||||
- pip install coveralls -U virtualenv py -e . -r dev_requirements.txt tox
|
||||
script:
|
||||
- tox
|
||||
- py.test --cov=pelican --cov-report=term-missing tests
|
||||
- tox -e $TESTENV --sitepackages
|
||||
after_success:
|
||||
# Report coverage results to coveralls.io
|
||||
- pip install coveralls
|
||||
- py.test --cov=pelican --cov-report=term-missing tests
|
||||
- coveralls
|
||||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#pelican"
|
||||
on_success: change
|
||||
irc:
|
||||
channels:
|
||||
- "irc.freenode.org#pelican"
|
||||
on_success: change
|
||||
|
|
|
|||
59
README.rst
59
README.rst
|
|
@ -3,57 +3,58 @@ Pelican |build-status| |coverage-status|
|
|||
|
||||
Pelican is a static site generator, written in Python_.
|
||||
|
||||
* Write your weblog entries directly with your editor of choice (vim!)
|
||||
in reStructuredText_ or Markdown_
|
||||
* Includes a simple CLI tool to (re)generate the weblog
|
||||
* Easy to interface with DVCSes and web hooks
|
||||
* Completely static output is easy to host anywhere
|
||||
* Write content in reStructuredText_ or Markdown_ using your editor of choice
|
||||
* Includes a simple command line tool to (re)generate site files
|
||||
* Easy to interface with version control systems and web hooks
|
||||
* Completely static output is simple to host anywhere
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
Pelican currently supports:
|
||||
|
||||
* Blog articles and pages
|
||||
* Comments, via an external service (Disqus). (Please note that while
|
||||
useful, Disqus is an external service, and thus the comment data will be
|
||||
somewhat outside of your control and potentially subject to data loss.)
|
||||
* Theming support (themes are created using Jinja2_ templates)
|
||||
* PDF generation of the articles/pages (optional)
|
||||
* Chronological content (e.g., articles, blog posts) as well as static pages
|
||||
* Integration with external services (e.g., Google Analytics and Disqus)
|
||||
* Site themes (created using Jinja2_ templates)
|
||||
* Publication of articles in multiple languages
|
||||
* Atom/RSS feeds
|
||||
* Code syntax highlighting
|
||||
* Import from WordPress, Dotclear, or RSS feeds
|
||||
* Integration with external tools: Twitter, Google Analytics, etc. (optional)
|
||||
* Fast rebuild times thanks to content caching and selective output writing.
|
||||
* Generation of Atom and RSS feeds
|
||||
* Syntax highlighting via Pygments_
|
||||
* Importing existing content from WordPress, Dotclear, and other services
|
||||
* Fast rebuild times due to content caching and selective output writing
|
||||
|
||||
Have a look at the `Pelican documentation`_ for more information.
|
||||
Check out `Pelican's documentation`_ for further information.
|
||||
|
||||
Why the name "Pelican"?
|
||||
-----------------------
|
||||
|
||||
"Pelican" is an anagram for *calepin*, which means "notebook" in French. ;)
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
You can access the source code at: https://github.com/getpelican/pelican
|
||||
|
||||
If you feel hackish, have a look at the explanation of `Pelican's internals`_.
|
||||
|
||||
How to get help, contribute, or provide feedback
|
||||
------------------------------------------------
|
||||
|
||||
See our `contribution submission and feedback guidelines <CONTRIBUTING.rst>`_.
|
||||
|
||||
|
||||
Source code
|
||||
-----------
|
||||
|
||||
Pelican's source code is `hosted on GitHub`_. If you feel like hacking,
|
||||
take a look at `Pelican's internals`_.
|
||||
|
||||
|
||||
Why the name "Pelican"?
|
||||
-----------------------
|
||||
|
||||
"Pelican" is an anagram of *calepin*, which means "notebook" in French.
|
||||
|
||||
|
||||
.. Links
|
||||
|
||||
.. _Python: http://www.python.org/
|
||||
.. _reStructuredText: http://docutils.sourceforge.net/rst.html
|
||||
.. _Markdown: http://daringfireball.net/projects/markdown/
|
||||
.. _Jinja2: http://jinja.pocoo.org/
|
||||
.. _`Pelican documentation`: http://docs.getpelican.com/
|
||||
.. _Pygments: http://pygments.org/
|
||||
.. _`Pelican's documentation`: http://docs.getpelican.com/
|
||||
.. _`Pelican's internals`: http://docs.getpelican.com/en/latest/internals.html
|
||||
.. _`hosted on GitHub`: https://github.com/getpelican/pelican
|
||||
|
||||
.. |build-status| image:: https://img.shields.io/travis/getpelican/pelican/master.svg
|
||||
:target: https://travis-ci.org/getpelican/pelican
|
||||
|
|
|
|||
|
|
@ -847,13 +847,11 @@ can be invoked by passing the ``--archive`` flag).
|
|||
|
||||
The cache files are Python pickles, so they may not be readable by
|
||||
different versions of Python as the pickle format often changes. If
|
||||
such an error is encountered, the cache files have to be rebuilt by
|
||||
removing them and re-running Pelican, or by using the Pelican
|
||||
command-line option ``--ignore-cache``. The cache files also have to
|
||||
be rebuilt when changing the ``GZIP_CACHE`` setting for cache file
|
||||
reading to work properly.
|
||||
such an error is encountered, it is caught and the cache file is
|
||||
rebuilt automatically in the new format. The cache files will also be
|
||||
rebuilt after the ``GZIP_CACHE`` setting has been changed.
|
||||
|
||||
The ``--ignore-cache`` command-line option is also useful when the
|
||||
The ``--ignore-cache`` command-line option is useful when the
|
||||
whole cache needs to be regenerated, such as when making modifications
|
||||
to the settings file that will affect the cached content, or just for
|
||||
debugging purposes. When Pelican runs in autoreload mode, modification
|
||||
|
|
|
|||
102
docs/themes.rst
102
docs/themes.rst
|
|
@ -329,6 +329,108 @@ period_archives.html template
|
|||
<https://github.com/getpelican/pelican/blob/master/pelican/themes/simple/templates/period_archives.html>`_.
|
||||
|
||||
|
||||
Objects
|
||||
=======
|
||||
|
||||
Detail objects attributes that are available and useful in templates. Not all
|
||||
attributes are listed here, this is a selection of attributes considered useful
|
||||
in a template.
|
||||
|
||||
.. _object-article:
|
||||
|
||||
Article
|
||||
-------
|
||||
|
||||
The string representation of an Article is the `source_path` attribute.
|
||||
|
||||
=================== ===================================================
|
||||
Attribute Description
|
||||
=================== ===================================================
|
||||
author The :ref:`Author <object-author_cat_tag>` of
|
||||
this article.
|
||||
authors A list of :ref:`Authors <object-author_cat_tag>`
|
||||
of this article.
|
||||
category The :ref:`Category <object-author_cat_tag>`
|
||||
of this article.
|
||||
content The rendered content of the article.
|
||||
date Datetime object representing the article date.
|
||||
date_format Either default date format or locale date format.
|
||||
default_template Default template name.
|
||||
in_default_lang Boolean representing if the article is written
|
||||
in the default language.
|
||||
lang Language of the article.
|
||||
locale_date Date formated by the `date_format`.
|
||||
metadata Article header metadata `dict`.
|
||||
save_as Location to save the article page.
|
||||
slug Page slug.
|
||||
source_path Full system path of the article source file.
|
||||
status The article status, can be any of 'published' or
|
||||
'draft'.
|
||||
summary Rendered summary content.
|
||||
tags List of :ref:`Tag <object-author_cat_tab>`
|
||||
objects.
|
||||
template Template name to use for rendering.
|
||||
title Title of the article.
|
||||
translations List of translations
|
||||
:ref:`Article <object-article>` objects.
|
||||
url URL to the article page.
|
||||
=================== ===================================================
|
||||
|
||||
.. _object-author_cat_tag:
|
||||
|
||||
Author / Category / Tag
|
||||
-----------------------
|
||||
|
||||
The string representation of those objects is the `name` attribute.
|
||||
|
||||
=================== ===================================================
|
||||
Attribute Description
|
||||
=================== ===================================================
|
||||
name Name of this object [1]_.
|
||||
page_name Author page name.
|
||||
save_as Location to save the author page.
|
||||
slug Page slug.
|
||||
url URL to the author page.
|
||||
=================== ===================================================
|
||||
|
||||
.. [1] for Author object, coming from `:authors:` or `AUTHOR`.
|
||||
|
||||
.. _object-page:
|
||||
|
||||
Page
|
||||
----
|
||||
|
||||
The string representation of a Page is the `source_path` attribute.
|
||||
|
||||
=================== ===================================================
|
||||
Attribute Description
|
||||
=================== ===================================================
|
||||
author The :ref:`Author <object-author_cat_tag>` of
|
||||
this page.
|
||||
content The rendered content of the page.
|
||||
date Datetime object representing the page date.
|
||||
date_format Either default date format or locale date format.
|
||||
default_template Default template name.
|
||||
in_default_lang Boolean representing if the article is written
|
||||
in the default language.
|
||||
lang Language of the article.
|
||||
locale_date Date formated by the `date_format`.
|
||||
metadata Page header metadata `dict`.
|
||||
save_as Location to save the page.
|
||||
slug Page slug.
|
||||
source_path Full system path of the page source file.
|
||||
status The page status, can be any of 'published' or
|
||||
'draft'.
|
||||
summary Rendered summary content.
|
||||
tags List of :ref:`Tag <object-author_cat_tab>`
|
||||
objects.
|
||||
template Template name to use for rendering.
|
||||
title Title of the page.
|
||||
translations List of translations
|
||||
:ref:`Article <object-article>` objects.
|
||||
url URL to the page.
|
||||
=================== ===================================================
|
||||
|
||||
Feeds
|
||||
=====
|
||||
|
||||
|
|
|
|||
|
|
@ -321,7 +321,8 @@ def get_config(args):
|
|||
config['CACHE_PATH'] = args.cache_path
|
||||
if args.selected_paths:
|
||||
config['WRITE_SELECTED'] = args.selected_paths.split(',')
|
||||
config['RELATIVE_URLS'] = args.relative_paths
|
||||
if args.relative_paths:
|
||||
config['RELATIVE_URLS'] = args.relative_paths
|
||||
config['DEBUG'] = args.verbosity == logging.DEBUG
|
||||
|
||||
# argparse returns bytes in Py2. There is no definite answer as to which
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals, print_function
|
||||
import six
|
||||
from six.moves.urllib.parse import (unquote, urlparse, urlunparse)
|
||||
from six.moves.urllib.parse import urlparse, urlunparse
|
||||
|
||||
import copy
|
||||
import locale
|
||||
|
|
@ -53,7 +53,7 @@ class Content(object):
|
|||
self._context = context
|
||||
self.translations = []
|
||||
|
||||
local_metadata = dict(settings['DEFAULT_METADATA'])
|
||||
local_metadata = dict()
|
||||
local_metadata.update(metadata)
|
||||
|
||||
# set metadata as attributes
|
||||
|
|
@ -90,7 +90,7 @@ class Content(object):
|
|||
|
||||
self.in_default_lang = (self.lang == default_lang)
|
||||
|
||||
# create the slug if not existing, generate slug according to
|
||||
# create the slug if not existing, generate slug according to
|
||||
# setting of SLUG_ATTRIBUTE
|
||||
if not hasattr(self, 'slug'):
|
||||
if settings['SLUGIFY_SOURCE'] == 'title' and hasattr(self, 'title'):
|
||||
|
|
@ -166,21 +166,13 @@ class Content(object):
|
|||
"""Returns the URL, formatted with the proper values"""
|
||||
metadata = copy.copy(self.metadata)
|
||||
path = self.metadata.get('path', self.get_relative_source_path())
|
||||
default_category = self.settings['DEFAULT_CATEGORY']
|
||||
slug_substitutions = self.settings.get('SLUG_SUBSTITUTIONS', ())
|
||||
metadata.update({
|
||||
'path': path_to_url(path),
|
||||
'slug': getattr(self, 'slug', ''),
|
||||
'lang': getattr(self, 'lang', 'en'),
|
||||
'date': getattr(self, 'date', SafeDatetime.now()),
|
||||
'author': slugify(
|
||||
getattr(self, 'author', ''),
|
||||
slug_substitutions
|
||||
),
|
||||
'category': slugify(
|
||||
getattr(self, 'category', default_category),
|
||||
slug_substitutions
|
||||
)
|
||||
'author': self.author.slug if hasattr(self, 'author') else '',
|
||||
'category': self.category.slug if hasattr(self, 'category') else ''
|
||||
})
|
||||
return metadata
|
||||
|
||||
|
|
@ -316,8 +308,13 @@ class Content(object):
|
|||
"""Dummy function"""
|
||||
pass
|
||||
|
||||
url = property(functools.partial(get_url_setting, key='url'))
|
||||
save_as = property(functools.partial(get_url_setting, key='save_as'))
|
||||
@property
|
||||
def url(self):
|
||||
return self.get_url_setting('url')
|
||||
|
||||
@property
|
||||
def save_as(self):
|
||||
return self.get_url_setting('save_as')
|
||||
|
||||
def _get_template(self):
|
||||
if hasattr(self, 'template') and self.template is not None:
|
||||
|
|
|
|||
|
|
@ -544,10 +544,8 @@ class ArticlesGenerator(CachingGenerator):
|
|||
if hasattr(article, 'tags'):
|
||||
for tag in article.tags:
|
||||
self.tags[tag].append(article)
|
||||
# ignore blank authors as well as undefined
|
||||
for author in getattr(article, 'authors', []):
|
||||
if author.name != '':
|
||||
self.authors[author].append(article)
|
||||
self.authors[author].append(article)
|
||||
# sort the articles by date
|
||||
self.articles.sort(key=attrgetter('date'), reverse=True)
|
||||
self.dates = list(self.articles)
|
||||
|
|
|
|||
|
|
@ -28,16 +28,44 @@ from pelican.contents import Page, Category, Tag, Author
|
|||
from pelican.utils import get_date, pelican_open, FileStampDataCacher, SafeDatetime, posixize_path
|
||||
|
||||
|
||||
def strip_split(text, sep=','):
|
||||
"""Return a list of stripped, non-empty substrings, delimited by sep."""
|
||||
items = [x.strip() for x in text.split(sep)]
|
||||
return [x for x in items if x]
|
||||
|
||||
|
||||
# Metadata processors have no way to discard an unwanted value, so we have
|
||||
# them return this value instead to signal that it should be discarded later.
|
||||
# This means that _filter_discardable_metadata() must be called on processed
|
||||
# metadata dicts before use, to remove the items with the special value.
|
||||
_DISCARD = object()
|
||||
|
||||
|
||||
def _process_if_nonempty(processor, name, settings):
|
||||
"""Removes extra whitespace from name and applies a metadata processor.
|
||||
If name is empty or all whitespace, returns _DISCARD instead.
|
||||
"""
|
||||
name = name.strip()
|
||||
return processor(name, settings) if name else _DISCARD
|
||||
|
||||
|
||||
METADATA_PROCESSORS = {
|
||||
'tags': lambda x, y: [Tag(tag, y) for tag in x.split(',')],
|
||||
'tags': lambda x, y: [Tag(tag, y) for tag in strip_split(x)] or _DISCARD,
|
||||
'date': lambda x, y: get_date(x.replace('_', ' ')),
|
||||
'modified': lambda x, y: get_date(x),
|
||||
'status': lambda x, y: x.strip(),
|
||||
'category': Category,
|
||||
'author': Author,
|
||||
'authors': lambda x, y: [Author(author.strip(), y) for author in x.split(',')],
|
||||
'status': lambda x, y: x.strip() or _DISCARD,
|
||||
'category': lambda x, y: _process_if_nonempty(Category, x, y),
|
||||
'author': lambda x, y: _process_if_nonempty(Author, x, y),
|
||||
'authors': lambda x, y: [Author(a, y) for a in strip_split(x)] or _DISCARD,
|
||||
'slug': lambda x, y: x.strip() or _DISCARD,
|
||||
}
|
||||
|
||||
|
||||
def _filter_discardable_metadata(metadata):
|
||||
"""Return a copy of a dict, minus any items marked as discardable."""
|
||||
return {name: val for name, val in metadata.items() if val is not _DISCARD}
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class BaseReader(object):
|
||||
|
|
@ -447,14 +475,14 @@ class Readers(FileStampDataCacher):
|
|||
|
||||
reader = self.readers[fmt]
|
||||
|
||||
metadata = default_metadata(
|
||||
settings=self.settings, process=reader.process_metadata)
|
||||
metadata = _filter_discardable_metadata(default_metadata(
|
||||
settings=self.settings, process=reader.process_metadata))
|
||||
metadata.update(path_metadata(
|
||||
full_path=path, source_path=source_path,
|
||||
settings=self.settings))
|
||||
metadata.update(parse_path_metadata(
|
||||
metadata.update(_filter_discardable_metadata(parse_path_metadata(
|
||||
source_path=source_path, settings=self.settings,
|
||||
process=reader.process_metadata))
|
||||
process=reader.process_metadata)))
|
||||
reader_name = reader.__class__.__name__
|
||||
metadata['reader'] = reader_name.replace('Reader', '').lower()
|
||||
|
||||
|
|
@ -462,7 +490,7 @@ class Readers(FileStampDataCacher):
|
|||
if content is None:
|
||||
content, reader_metadata = reader.read(path)
|
||||
self.cache_data(path, (content, reader_metadata))
|
||||
metadata.update(reader_metadata)
|
||||
metadata.update(_filter_discardable_metadata(reader_metadata))
|
||||
|
||||
if content:
|
||||
# find images with empty alt
|
||||
|
|
@ -537,6 +565,10 @@ def find_empty_alt(content, path):
|
|||
def default_metadata(settings=None, process=None):
|
||||
metadata = {}
|
||||
if settings:
|
||||
for name, value in dict(settings.get('DEFAULT_METADATA', {})).items():
|
||||
if process:
|
||||
value = process(name, value)
|
||||
metadata[name] = value
|
||||
if 'DEFAULT_CATEGORY' in settings:
|
||||
value = settings['DEFAULT_CATEGORY']
|
||||
if process:
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
{% endif %}
|
||||
{# other items #}
|
||||
{% else %}
|
||||
{% if loop.first and articles_page.has_previous %}
|
||||
{% if loop.first %}
|
||||
<section id="content" class="body">
|
||||
<ol id="posts-list" class="hfeed" start="{{ articles_paginator.per_page -1 }}">
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ from __future__ import with_statement, unicode_literals, print_function
|
|||
import six
|
||||
|
||||
import os
|
||||
import locale
|
||||
import logging
|
||||
|
||||
if not six.PY3:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import os.path
|
|||
|
||||
from tests.support import unittest, get_settings
|
||||
|
||||
from pelican.contents import Page, Article, Static, URLWrapper
|
||||
from pelican.contents import Page, Article, Static, URLWrapper, Author, Category
|
||||
from pelican.settings import DEFAULT_CONFIG
|
||||
from pelican.utils import path_to_url, truncate_html_words, SafeDatetime, posix_join
|
||||
from pelican.signals import content_object_init
|
||||
|
|
@ -33,7 +33,7 @@ class TestPage(unittest.TestCase):
|
|||
'metadata': {
|
||||
'summary': TEST_SUMMARY,
|
||||
'title': 'foo bar',
|
||||
'author': 'Blogger',
|
||||
'author': Author('Blogger', DEFAULT_CONFIG),
|
||||
},
|
||||
'source_path': '/path/to/file/foo.ext'
|
||||
}
|
||||
|
|
@ -374,7 +374,8 @@ class TestPage(unittest.TestCase):
|
|||
content = Page(**args)
|
||||
assert content.authors == [content.author]
|
||||
args['metadata'].pop('author')
|
||||
args['metadata']['authors'] = ['First Author', 'Second Author']
|
||||
args['metadata']['authors'] = [Author('First Author', DEFAULT_CONFIG),
|
||||
Author('Second Author', DEFAULT_CONFIG)]
|
||||
content = Page(**args)
|
||||
assert content.authors
|
||||
assert content.author == content.authors[0]
|
||||
|
|
@ -396,8 +397,8 @@ class TestArticle(TestPage):
|
|||
settings['ARTICLE_URL'] = '{author}/{category}/{slug}/'
|
||||
settings['ARTICLE_SAVE_AS'] = '{author}/{category}/{slug}/index.html'
|
||||
article_kwargs = self._copy_page_kwargs()
|
||||
article_kwargs['metadata']['author'] = "O'Brien"
|
||||
article_kwargs['metadata']['category'] = 'C# & stuff'
|
||||
article_kwargs['metadata']['author'] = Author("O'Brien", settings)
|
||||
article_kwargs['metadata']['category'] = Category('C# & stuff', settings)
|
||||
article_kwargs['metadata']['title'] = 'fnord'
|
||||
article_kwargs['settings'] = settings
|
||||
article = Article(**article_kwargs)
|
||||
|
|
|
|||
|
|
@ -413,6 +413,38 @@ class TestArticlesGenerator(unittest.TestCase):
|
|||
generator.generate_context()
|
||||
generator.readers.read_file.assert_called_count == orig_call_count
|
||||
|
||||
def test_standard_metadata_in_default_metadata(self):
|
||||
settings = get_settings(filenames={})
|
||||
settings['CACHE_CONTENT'] = False
|
||||
settings['DEFAULT_CATEGORY'] = 'Default'
|
||||
settings['DEFAULT_DATE'] = (1970, 1, 1)
|
||||
settings['DEFAULT_METADATA'] = (('author', 'Blogger'),
|
||||
# category will be ignored in favor of
|
||||
# DEFAULT_CATEGORY
|
||||
('category', 'Random'),
|
||||
('tags', 'general, untagged'))
|
||||
generator = ArticlesGenerator(
|
||||
context=settings.copy(), settings=settings,
|
||||
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
|
||||
generator.generate_context()
|
||||
|
||||
authors = sorted([author.name for author, _ in generator.authors])
|
||||
authors_expected = sorted(['Alexis Métaireau', 'Blogger',
|
||||
'First Author', 'Second Author'])
|
||||
self.assertEqual(authors, authors_expected)
|
||||
|
||||
categories = sorted([category.name
|
||||
for category, _ in generator.categories])
|
||||
categories_expected = [
|
||||
sorted(['Default', 'TestCategory', 'yeah', 'test', '指導書']),
|
||||
sorted(['Default', 'TestCategory', 'Yeah', 'test', '指導書'])]
|
||||
self.assertIn(categories, categories_expected)
|
||||
|
||||
tags = sorted([tag.name for tag in generator.tags])
|
||||
tags_expected = sorted(['bar', 'foo', 'foobar', 'general', 'untagged',
|
||||
'パイソン', 'マック'])
|
||||
self.assertEqual(tags, tags_expected)
|
||||
|
||||
|
||||
class TestPageGenerator(unittest.TestCase):
|
||||
# Note: Every time you want to test for a new field; Make sure the test
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import locale
|
|||
from tests.support import unittest, get_settings
|
||||
|
||||
from pelican.paginator import Paginator
|
||||
from pelican.contents import Article
|
||||
from pelican.contents import Article, Author
|
||||
from pelican.settings import DEFAULT_CONFIG
|
||||
from jinja2.utils import generate_lorem_ipsum
|
||||
|
||||
|
|
@ -26,7 +26,6 @@ class TestPage(unittest.TestCase):
|
|||
'metadata': {
|
||||
'summary': TEST_SUMMARY,
|
||||
'title': 'foo bar',
|
||||
'author': 'Blogger',
|
||||
},
|
||||
'source_path': '/path/to/file/foo.ext'
|
||||
}
|
||||
|
|
@ -49,6 +48,7 @@ class TestPage(unittest.TestCase):
|
|||
key=lambda r: r[0],
|
||||
)
|
||||
|
||||
self.page_kwargs['metadata']['author'] = Author('Blogger', settings)
|
||||
object_list = [Article(**self.page_kwargs), Article(**self.page_kwargs)]
|
||||
paginator = Paginator('foobar.foo', object_list, settings)
|
||||
page = paginator.page(1)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue