Merge remote-tracking branch 'remotes/malept/davidmarble-page-order-by' into davidmarble-page-order-by

Conflicts:
	docs/settings.rst
	pelican/generators.py
	pelican/tests/test_generators.py
This commit is contained in:
Vincent Jousse 2014-05-14 10:48:41 +02:00
commit ebf0da0f7b
6 changed files with 94 additions and 11 deletions

View file

@ -265,6 +265,11 @@ Setting name (followed by default value, if any) What does it do?
====================================================== ========================================================
``ARTICLE_URL = '{slug}.html'`` The URL to refer to an article.
``ARTICLE_SAVE_AS = '{slug}.html'`` The place where we will save an article.
``ARTICLE_ORDER_BY = 'slug'`` The metadata attribute used to sort articles. By default
the articles_page.object_list template variable is
ordered by slug. If you modify this, make sure all
articles contain the attribute you specify. You can
also specify a sorting function.
``ARTICLE_LANG_URL = '{slug}-{lang}.html'`` The URL to refer to an article which doesn't use the
default language.
``ARTICLE_LANG_SAVE_AS = '{slug}-{lang}.html'`` The place where we will save an article which
@ -279,6 +284,14 @@ Setting name (followed by default value, if any) What does it do?
``PAGE_SAVE_AS = 'pages/{slug}.html'`` The location we will save the page. This value has to be
the same as PAGE_URL or you need to use a rewrite in
your server config.
``PAGE_ORDER_BY = 'filename'`` The metadata attribute used to sort pages. By default
the PAGES template variable is ordered by filename
(path not included). Note that the option 'filename'
is a special option supported in the source code. If
you modify this settings, make sure all pages contain
the attribute you specify. You can also specify a
sorting function.
``PAGE_LANG_URL = 'pages/{slug}-{lang}.html'`` The URL we will use to link to a page which doesn't
use the default language.
``PAGE_LANG_SAVE_AS = 'pages/{slug}-{lang}.html'`` The location we will save the page which doesn't

View file

@ -501,7 +501,8 @@ class ArticlesGenerator(CachingGenerator):
(repr(article.status),
repr(f)))
self.articles, self.translations = process_translations(all_articles)
self.articles, self.translations = process_translations(all_articles,
order_by=self.settings['ARTICLE_ORDER_BY'])
self.drafts, self.drafts_translations = \
process_translations(all_drafts)
@ -618,7 +619,8 @@ class PagesGenerator(CachingGenerator):
(repr(page.status),
repr(f)))
self.pages, self.translations = process_translations(all_pages)
self.pages, self.translations = process_translations(all_pages,
order_by=self.settings['PAGE_ORDER_BY'])
self.hidden_pages, self.hidden_translations = (
process_translations(hidden_pages))

View file

@ -61,6 +61,7 @@ DEFAULT_CONFIG = {
'OUTPUT_RETENTION': (),
'ARTICLE_URL': '{slug}.html',
'ARTICLE_SAVE_AS': '{slug}.html',
'ARTICLE_ORDER_BY': 'slug',
'ARTICLE_LANG_URL': '{slug}-{lang}.html',
'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',
'DRAFT_URL': 'drafts/{slug}.html',
@ -69,6 +70,7 @@ DEFAULT_CONFIG = {
'DRAFT_LANG_SAVE_AS': os.path.join('drafts', '{slug}-{lang}.html'),
'PAGE_URL': 'pages/{slug}.html',
'PAGE_SAVE_AS': os.path.join('pages', '{slug}.html'),
'PAGE_ORDER_BY': 'filename',
'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',
'PAGE_LANG_SAVE_AS': os.path.join('pages', '{slug}-{lang}.html'),
'STATIC_URL': '{path}',

View file

@ -0,0 +1,6 @@
A Page (Test) for sorting
#########################
:slug: zzzz
When using title, should be first. When using slug, should be last.

View file

@ -7,6 +7,7 @@ try:
from unittest.mock import MagicMock
except ImportError:
from mock import MagicMock
from operator import itemgetter
from shutil import rmtree
from tempfile import mkdtemp
@ -55,14 +56,12 @@ class TestArticlesGenerator(unittest.TestCase):
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
cls.generator.generate_context()
cls.articles = [[page.title, page.status, page.category.name,
page.template] for page in cls.generator.articles]
cls.articles = cls.distill_articles(cls.generator.articles)
def setUp(self):
self.temp_cache = mkdtemp(prefix='pelican_cache.')
def tearDown(self):
rmtree(self.temp_cache)
@staticmethod
def distill_articles(articles):
return [[article.title, article.status, article.category.name,
article.template] for article in articles]
def test_generate_feeds(self):
settings = get_settings()
@ -387,7 +386,8 @@ class TestPageGenerator(unittest.TestCase):
['This is a test page', 'published', 'page'],
['This is a markdown test page', 'published', 'page'],
['This is a test page with a preset template', 'published',
'custom']
'custom'],
['A Page (Test) for sorting', 'published', 'page'],
]
hidden_pages_expected = [
['This is a test hidden page', 'hidden', 'page'],
@ -465,6 +465,42 @@ class TestPageGenerator(unittest.TestCase):
generator.generate_context()
generator.readers.read_file.assert_called_count == orig_call_count
def test_generate_sorted(self):
settings = get_settings(filenames={})
settings['PAGE_DIR'] = 'TestPages' # relative to CUR_DIR
settings['DEFAULT_DATE'] = (1970, 1, 1)
# default sort (filename)
pages_expected_sorted_by_filename = [
['This is a test page', 'published', 'page'],
['This is a markdown test page', 'published', 'page'],
['A Page (Test) for sorting', 'published', 'page'],
['This is a test page with a preset template', 'published',
'custom'],
]
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CUR_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
pages = self.distill_pages(generator.pages)
self.assertEqual(pages_expected_sorted_by_filename, pages)
# sort by title
pages_expected_sorted_by_title = [
['A Page (Test) for sorting', 'published', 'page'],
['This is a markdown test page', 'published', 'page'],
['This is a test page', 'published', 'page'],
['This is a test page with a preset template', 'published',
'custom'],
]
settings['PAGE_ORDER_BY'] = 'title'
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CUR_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
pages = self.distill_pages(generator.pages)
self.assertEqual(pages_expected_sorted_by_title, pages)
class TestTemplatePagesGenerator(unittest.TestCase):

View file

@ -400,7 +400,7 @@ def truncate_html_words(s, num, end_text='...'):
return out
def process_translations(content_list):
def process_translations(content_list, order_by=None):
""" Finds translation and returns them.
Returns a tuple with two lists (index, translations). Index list includes
@ -410,6 +410,14 @@ def process_translations(content_list):
the same slug have that metadata.
For each content_list item, sets the 'translations' attribute.
order_by can be a string of an attribute or sorting function. If order_by
is defined, content will be ordered by that attribute or sorting function.
By default, content is ordered by slug.
Different content types can have default order_by attributes defined
in settings, e.g. PAGES_ORDER_BY='sort-order', in which case `sort-order`
should be a defined metadata attribute in each page.
"""
content_list.sort(key=attrgetter('slug'))
grouped_by_slugs = groupby(content_list, attrgetter('slug'))
@ -455,6 +463,22 @@ def process_translations(content_list):
translations.extend([x for x in items if x not in default_lang_items])
for a in items:
a.translations = [x for x in items if x != a]
if order_by:
if hasattr(order_by, '__call__'):
try:
index.sort(key=order_by)
except:
if hasattr(order_by, 'func_name'):
logger.error("Error sorting with function %s" % order_by.func_name)
else:
logger.error("Error sorting with function %r" % order_by)
elif order_by == 'filename':
index.sort(key=lambda x:os.path.basename(
x.source_path or ''))
elif order_by != 'slug':
index.sort(key=attrgetter(order_by))
return index, translations