1
0
Fork 0
forked from github/pelican
pelican-theme/pelican/tests/test_generators.py

658 lines
28 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
from __future__ import unicode_literals
import os
from codecs import open
2013-10-06 15:30:14 +02:00
try:
from unittest.mock import MagicMock
except ImportError:
from mock import MagicMock
2013-11-14 12:37:22 -08:00
from operator import itemgetter
from shutil import rmtree
from tempfile import mkdtemp
from pelican.generators import (Generator, ArticlesGenerator, PagesGenerator,
Make StaticGenerator skip content sources. Refs #1019. This change partially addresses issue #1019, by teaching Pelican to distinguish between static files and content source files. A user can now safely add the same directory to both STATIC_PATHS and PAGE_PATHS (or ARTICLE_PATHS). Pelican will then process the content source files in that directory normally, and treat the remaining files as static, without copying the raw content source files to the output directory. (The OUTPUT_SOURCES setting still works.) In other words, images and markdown/reST files can now safely live together. To keep those files together in the generated site, STATIC_SAVE_AS and PAGE_SAVE_AS (or ARTICLE_SAVE_AS) should point to the same output directory. There are two new configuration settings: STATIC_EXCLUDES=[] # This works just like PAGE_EXCLUDES and ARTICLE_EXCLUDES. STATIC_EXCLUDE_SOURCES=True # Set this to False to get the old behavior. Two small but noteworthy internal changes: StaticGenerator now runs after all the other generators. This allows it to see which files are meant to be processed by other generators, and avoid them. Generators now include files that they fail to process (e.g. those with missing mandatory metadata) along with all the other paths in context['filenames']. This allows such files to be excluded from StaticGenerator's file list, so they won't end up accidentally published. Since these files have no Content object, their value in context['filenames'] is None. The code that uses that dict has been updated accordingly.
2014-10-18 13:11:59 -07:00
StaticGenerator, TemplatePagesGenerator)
2012-10-30 02:33:22 +01:00
from pelican.writers import Writer
2013-03-06 00:41:27 -08:00
from pelican.tests.support import unittest, get_settings
import locale
CUR_DIR = os.path.dirname(__file__)
CONTENT_DIR = os.path.join(CUR_DIR, 'content')
2012-05-06 02:43:13 +02:00
class TestGenerator(unittest.TestCase):
def setUp(self):
self.old_locale = locale.setlocale(locale.LC_ALL)
locale.setlocale(locale.LC_ALL, str('C'))
self.settings = get_settings()
2013-08-04 21:17:15 +02:00
self.settings['READERS'] = {'asc': None}
self.generator = Generator(self.settings.copy(), self.settings,
CUR_DIR, self.settings['THEME'], None)
def tearDown(self):
locale.setlocale(locale.LC_ALL, self.old_locale)
def test_include_path(self):
filename = os.path.join(CUR_DIR, 'content', 'article.rst')
include_path = self.generator._include_path
self.assertTrue(include_path(filename))
self.assertTrue(include_path(filename, extensions=('rst',)))
self.assertFalse(include_path(filename, extensions=('md',)))
def test_get_files_exclude(self):
"""Test that Generator.get_files() properly excludes directories.
"""
# We use our own Generator so we can give it our own content path
generator = Generator(context=self.settings.copy(),
settings=self.settings,
path=os.path.join(CUR_DIR, 'nested_content'),
theme=self.settings['THEME'], output_path=None)
filepaths = generator.get_files(paths=['maindir'])
found_files = {os.path.basename(f) for f in filepaths}
expected_files = {'maindir.md', 'subdir.md'}
self.assertFalse(expected_files - found_files,
"get_files() failed to find one or more files")
filepaths = generator.get_files(paths=[''], exclude=['maindir'])
found_files = {os.path.basename(f) for f in filepaths}
self.assertNotIn('maindir.md', found_files,
"get_files() failed to exclude a top-level directory")
self.assertNotIn('subdir.md', found_files,
"get_files() failed to exclude a subdir of an excluded directory")
filepaths = generator.get_files(paths=[''],
exclude=[os.path.join('maindir', 'subdir')])
found_files = {os.path.basename(f) for f in filepaths}
self.assertNotIn('subdir.md', found_files,
"get_files() failed to exclude a subdirectory")
filepaths = generator.get_files(paths=[''], exclude=['subdir'])
found_files = {os.path.basename(f) for f in filepaths}
self.assertIn('subdir.md', found_files,
"get_files() excluded a subdirectory by name, ignoring its path")
class TestArticlesGenerator(unittest.TestCase):
@classmethod
def setUpClass(cls):
settings = get_settings(filenames={})
settings['DEFAULT_CATEGORY'] = 'Default'
settings['DEFAULT_DATE'] = (1970, 1, 1)
2013-08-04 21:17:15 +02:00
settings['READERS'] = {'asc': None}
settings['CACHE_CONTENT'] = False # cache not needed for this logic tests
cls.generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
cls.generator.generate_context()
2013-11-14 12:37:22 -08:00
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)
2013-11-14 12:37:22 -08:00
@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()
settings['CACHE_PATH'] = self.temp_cache
generator = ArticlesGenerator(
context=settings, settings=settings,
path=None, theme=settings['THEME'], output_path=None)
writer = MagicMock()
generator.generate_feeds(writer)
2013-03-03 19:44:57 -08:00
writer.write_feed.assert_called_with([], settings,
'feeds/all.atom.xml')
generator = ArticlesGenerator(
context=settings, settings=get_settings(FEED_ALL_ATOM=None),
path=None, theme=settings['THEME'], output_path=None)
writer = MagicMock()
generator.generate_feeds(writer)
self.assertFalse(writer.write_feed.called)
def test_generate_context(self):
articles_expected = [
['Article title', 'published', 'Default', 'article'],
['Article with markdown and summary metadata multi', 'published',
'Default', 'article'],
2013-03-03 19:44:57 -08:00
['Article with markdown and summary metadata single', 'published',
'Default', 'article'],
['Article with markdown containing footnotes', 'published',
2013-03-03 19:44:57 -08:00
'Default', 'article'],
['Article with template', 'published', 'Default', 'custom'],
['Rst with filename metadata', 'published', 'yeah', 'article'],
['Test Markdown extensions', 'published', 'Default', 'article'],
['Test markdown File', 'published', 'test', 'article'],
['Test md File', 'published', 'test', 'article'],
['Test mdown File', 'published', 'test', 'article'],
['Test mkd File', 'published', 'test', 'article'],
['This is a super article !', 'published', 'Yeah', 'article'],
['This is a super article !', 'published', 'Yeah', 'article'],
['Article with Nonconformant HTML meta tags', 'published', 'Default', 'article'],
['This is a super article !', 'published', 'yeah', 'article'],
['This is a super article !', 'published', 'yeah', 'article'],
['This is a super article !', 'published', 'yeah', 'article'],
['This is a super article !', 'published', 'Default', 'article'],
2013-03-03 19:44:57 -08:00
['This is an article with category !', 'published', 'yeah',
'article'],
2013-07-05 01:08:45 +02:00
['This is an article with multiple authors!', 'published', 'Default', 'article'],
['This is an article with multiple authors!', 'published', 'Default', 'article'],
2013-03-03 19:44:57 -08:00
['This is an article without category !', 'published', 'Default',
'article'],
['This is an article without category !', 'published',
'TestCategory', 'article'],
['An Article With Code Block To Test Typogrify Ignore',
'published', 'Default', 'article'],
['マックOS X 10.8でパイソンとVirtualenvをインストールと設定', 'published',
'指導書', 'article'],
]
self.assertEqual(sorted(articles_expected), sorted(self.articles))
def test_generate_categories(self):
# test for name
# categories are grouped by slug; if two categories have the same slug
# but different names they will be grouped together, the first one in
# terms of process order will define the name for that category
categories = [cat.name for cat, _ in self.generator.categories]
categories_alternatives = (
sorted(['Default', 'TestCategory', 'Yeah', 'test', '指導書']),
sorted(['Default', 'TestCategory', 'yeah', 'test', '指導書']),
)
self.assertIn(sorted(categories), categories_alternatives)
# test for slug
categories = [cat.slug for cat, _ in self.generator.categories]
categories_expected = ['default', 'testcategory', 'yeah', 'test',
'zhi-dao-shu']
self.assertEqual(sorted(categories), sorted(categories_expected))
2012-05-06 02:43:13 +02:00
def test_do_not_use_folder_as_category(self):
settings = get_settings(filenames={})
settings['DEFAULT_CATEGORY'] = 'Default'
settings['DEFAULT_DATE'] = (1970, 1, 1)
settings['USE_FOLDER_AS_CATEGORY'] = False
settings['CACHE_PATH'] = self.temp_cache
2013-08-04 21:17:15 +02:00
settings['READERS'] = {'asc': None}
settings['filenames'] = {}
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
# test for name
# categories are grouped by slug; if two categories have the same slug
# but different names they will be grouped together, the first one in
# terms of process order will define the name for that category
categories = [cat.name for cat, _ in generator.categories]
categories_alternatives = (
sorted(['Default', 'Yeah', 'test', '指導書']),
sorted(['Default', 'yeah', 'test', '指導書']),
)
self.assertIn(sorted(categories), categories_alternatives)
# test for slug
categories = [cat.slug for cat, _ in generator.categories]
categories_expected = ['default', 'yeah', 'test', 'zhi-dao-shu']
self.assertEqual(sorted(categories), sorted(categories_expected))
def test_direct_templates_save_as_default(self):
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
generator = ArticlesGenerator(
context=settings, settings=settings,
path=None, theme=settings['THEME'], output_path=None)
write = MagicMock()
generator.generate_direct_templates(write)
write.assert_called_with("archives.html",
generator.get_template("archives"), settings,
blog=True, paginated={}, page_name='archives')
def test_direct_templates_save_as_modified(self):
settings = get_settings()
settings['DIRECT_TEMPLATES'] = ['archives']
settings['ARCHIVES_SAVE_AS'] = 'archives/index.html'
settings['CACHE_PATH'] = self.temp_cache
generator = ArticlesGenerator(
context=settings, settings=settings,
path=None, theme=settings['THEME'], output_path=None)
write = MagicMock()
generator.generate_direct_templates(write)
write.assert_called_with("archives/index.html",
generator.get_template("archives"), settings,
blog=True, paginated={},
page_name='archives/index')
def test_direct_templates_save_as_false(self):
settings = get_settings()
settings['DIRECT_TEMPLATES'] = ['archives']
settings['ARCHIVES_SAVE_AS'] = False
settings['CACHE_PATH'] = self.temp_cache
generator = ArticlesGenerator(
context=settings, settings=settings,
path=None, theme=settings['THEME'], output_path=None)
write = MagicMock()
generator.generate_direct_templates(write)
self.assertEqual(write.call_count, 0)
def test_per_article_template(self):
"""
Custom template articles get the field but standard/unset are None
"""
2013-03-03 19:44:57 -08:00
custom_template = ['Article with template', 'published', 'Default',
'custom']
standard_template = ['This is a super article !', 'published', 'Yeah',
'article']
self.assertIn(custom_template, self.articles)
self.assertIn(standard_template, self.articles)
def test_period_in_timeperiod_archive(self):
"""
Test that the context of a generated period_archive is passed
'period' : a tuple of year, month, day according to the time period
"""
settings = get_settings(filenames={})
settings['YEAR_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/index.html'
settings['CACHE_PATH'] = self.temp_cache
generator = ArticlesGenerator(
context=settings, settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
write = MagicMock()
generator.generate_period_archives(write)
dates = [d for d in generator.dates if d.date.year == 1970]
self.assertEqual(len(dates), 1)
#among other things it must have at least been called with this
settings["period"] = (1970,)
write.assert_called_with("posts/1970/index.html",
generator.get_template("period_archives"),
settings,
blog=True, dates=dates)
del settings["period"]
settings['MONTH_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/{date:%b}/index.html'
generator = ArticlesGenerator(
context=settings, settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
write = MagicMock()
generator.generate_period_archives(write)
dates = [d for d in generator.dates if d.date.year == 1970
and d.date.month == 1]
self.assertEqual(len(dates), 1)
settings["period"] = (1970, "January")
#among other things it must have at least been called with this
write.assert_called_with("posts/1970/Jan/index.html",
generator.get_template("period_archives"),
settings,
blog=True, dates=dates)
del settings["period"]
settings['DAY_ARCHIVE_SAVE_AS'] = 'posts/{date:%Y}/{date:%b}/{date:%d}/index.html'
generator = ArticlesGenerator(
context=settings, settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
write = MagicMock()
generator.generate_period_archives(write)
dates = [d for d in generator.dates if d.date.year == 1970
and d.date.month == 1
and d.date.day == 1]
self.assertEqual(len(dates), 1)
settings["period"] = (1970, "January", 1)
#among other things it must have at least been called with this
write.assert_called_with("posts/1970/Jan/01/index.html",
generator.get_template("period_archives"),
settings,
blog=True, dates=dates)
2013-07-05 01:08:45 +02:00
def test_generate_authors(self):
"""Check authors generation."""
authors = [author.name for author, _ in self.generator.authors]
authors_expected = sorted(['Alexis Métaireau', 'First Author', 'Second Author'])
self.assertEqual(sorted(authors), authors_expected)
# test for slug
authors = [author.slug for author, _ in self.generator.authors]
authors_expected = ['alexis-metaireau', 'first-author', 'second-author']
self.assertEqual(sorted(authors), sorted(authors_expected))
2012-04-28 03:03:53 +03:00
def test_article_object_caching(self):
"""Test Article objects caching at the generator level"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['CONTENT_CACHING_LAYER'] = 'generator'
settings['READERS'] = {'asc': None}
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
self.assertTrue(hasattr(generator, '_cache'))
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
generator.readers.read_file.assert_called_count == 0
def test_reader_content_caching(self):
"""Test raw content caching at the reader level"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['READERS'] = {'asc': None}
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
self.assertTrue(hasattr(generator.readers, '_cache'))
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
readers = generator.readers.readers
for reader in readers.values():
reader.read = MagicMock()
generator.generate_context()
for reader in readers.values():
reader.read.assert_called_count == 0
def test_ignore_cache(self):
"""Test that all the articles are read again when not loading cache
used in --ignore-cache or autoreload mode"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['READERS'] = {'asc': None}
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
self.assertTrue(hasattr(generator, '_cache_open'))
orig_call_count = generator.readers.read_file.call_count
settings['LOAD_CONTENT_CACHE'] = False
generator = ArticlesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
generator.readers.read_file.assert_called_count == orig_call_count
2013-03-03 19:44:57 -08:00
class TestPageGenerator(unittest.TestCase):
2013-03-03 19:44:57 -08:00
# Note: Every time you want to test for a new field; Make sure the test
# pages in "TestPages" have all the fields Add it to distilled in
# distill_pages Then update the assertEqual in test_generate_context
2013-03-03 19:44:57 -08:00
# to match expected
def setUp(self):
self.temp_cache = mkdtemp(prefix='pelican_cache.')
def tearDown(self):
rmtree(self.temp_cache)
def distill_pages(self, pages):
return [[page.title, page.status, page.template] for page in pages]
def test_generate_context(self):
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR
settings['DEFAULT_DATE'] = (1970, 1, 1)
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)
hidden_pages = self.distill_pages(generator.hidden_pages)
pages_expected = [
['This is a test page', 'published', 'page'],
['This is a markdown test page', 'published', 'page'],
2013-03-03 19:44:57 -08:00
['This is a test page with a preset template', 'published',
2013-11-14 12:37:22 -08:00
'custom'],
['A Page (Test) for sorting', 'published', 'page'],
]
hidden_pages_expected = [
['This is a test hidden page', 'hidden', 'page'],
['This is a markdown test hidden page', 'hidden', 'page'],
2013-03-03 19:44:57 -08:00
['This is a test hidden page with a custom template', 'hidden',
'custom']
]
self.assertEqual(sorted(pages_expected), sorted(pages))
self.assertEqual(sorted(hidden_pages_expected), sorted(hidden_pages))
def test_page_object_caching(self):
"""Test Page objects caching at the generator level"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['CONTENT_CACHING_LAYER'] = 'generator'
settings['READERS'] = {'asc': None}
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
self.assertTrue(hasattr(generator, '_cache'))
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
generator.readers.read_file.assert_called_count == 0
def test_reader_content_caching(self):
"""Test raw content caching at the reader level"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['READERS'] = {'asc': None}
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.generate_context()
self.assertTrue(hasattr(generator.readers, '_cache'))
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
readers = generator.readers.readers
for reader in readers.values():
reader.read = MagicMock()
generator.generate_context()
for reader in readers.values():
reader.read.assert_called_count == 0
def test_ignore_cache(self):
"""Test that all the pages are read again when not loading cache
used in --ignore_cache or autoreload mode"""
settings = get_settings(filenames={})
settings['CACHE_PATH'] = self.temp_cache
settings['READERS'] = {'asc': None}
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
self.assertTrue(hasattr(generator, '_cache_open'))
orig_call_count = generator.readers.read_file.call_count
settings['LOAD_CONTENT_CACHE'] = False
generator = PagesGenerator(
context=settings.copy(), settings=settings,
path=CONTENT_DIR, theme=settings['THEME'], output_path=None)
generator.readers.read_file = MagicMock()
generator.generate_context()
generator.readers.read_file.assert_called_count == orig_call_count
2013-11-14 12:37:22 -08:00
def test_generate_sorted(self):
settings = get_settings(filenames={})
2014-09-18 20:09:12 -04:00
settings['PAGE_PATHS'] = ['TestPages'] # relative to CUR_DIR
settings['CACHE_PATH'] = self.temp_cache
2013-11-14 12:37:22 -08:00
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)
2012-10-30 02:33:22 +01:00
class TestTemplatePagesGenerator(unittest.TestCase):
TEMPLATE_CONTENT = "foo: {{ foo }}"
def setUp(self):
self.temp_content = mkdtemp(prefix='pelicantests.')
self.temp_output = mkdtemp(prefix='pelicantests.')
self.old_locale = locale.setlocale(locale.LC_ALL)
locale.setlocale(locale.LC_ALL, str('C'))
2012-10-30 02:33:22 +01:00
def tearDown(self):
rmtree(self.temp_content)
rmtree(self.temp_output)
locale.setlocale(locale.LC_ALL, self.old_locale)
2012-10-30 02:33:22 +01:00
def test_generate_output(self):
settings = get_settings()
2012-10-30 02:33:22 +01:00
settings['STATIC_PATHS'] = ['static']
settings['TEMPLATE_PAGES'] = {
'template/source.html': 'generated/file.html'
}
2012-10-30 02:33:22 +01:00
generator = TemplatePagesGenerator(
context={'foo': 'bar'}, settings=settings,
path=self.temp_content, theme='', output_path=self.temp_output)
2012-10-30 02:33:22 +01:00
# create a dummy template file
template_dir = os.path.join(self.temp_content, 'template')
template_path = os.path.join(template_dir, 'source.html')
2012-10-30 02:33:22 +01:00
os.makedirs(template_dir)
with open(template_path, 'w') as template_file:
2012-10-30 02:33:22 +01:00
template_file.write(self.TEMPLATE_CONTENT)
writer = Writer(self.temp_output, settings=settings)
generator.generate_output(writer)
output_path = os.path.join(self.temp_output, 'generated', 'file.html')
2012-10-30 02:33:22 +01:00
# output file has been generated
self.assertTrue(os.path.exists(output_path))
2012-10-30 02:33:22 +01:00
# output content is correct
with open(output_path, 'r') as output_file:
self.assertEqual(output_file.read(), 'foo: bar')
Make StaticGenerator skip content sources. Refs #1019. This change partially addresses issue #1019, by teaching Pelican to distinguish between static files and content source files. A user can now safely add the same directory to both STATIC_PATHS and PAGE_PATHS (or ARTICLE_PATHS). Pelican will then process the content source files in that directory normally, and treat the remaining files as static, without copying the raw content source files to the output directory. (The OUTPUT_SOURCES setting still works.) In other words, images and markdown/reST files can now safely live together. To keep those files together in the generated site, STATIC_SAVE_AS and PAGE_SAVE_AS (or ARTICLE_SAVE_AS) should point to the same output directory. There are two new configuration settings: STATIC_EXCLUDES=[] # This works just like PAGE_EXCLUDES and ARTICLE_EXCLUDES. STATIC_EXCLUDE_SOURCES=True # Set this to False to get the old behavior. Two small but noteworthy internal changes: StaticGenerator now runs after all the other generators. This allows it to see which files are meant to be processed by other generators, and avoid them. Generators now include files that they fail to process (e.g. those with missing mandatory metadata) along with all the other paths in context['filenames']. This allows such files to be excluded from StaticGenerator's file list, so they won't end up accidentally published. Since these files have no Content object, their value in context['filenames'] is None. The code that uses that dict has been updated accordingly.
2014-10-18 13:11:59 -07:00
class TestStaticGenerator(unittest.TestCase):
def setUp(self):
self.content_path = os.path.join(CUR_DIR, 'mixed_content')
def test_static_excludes(self):
"""Test that StaticGenerator respects STATIC_EXCLUDES.
"""
settings = get_settings(STATIC_EXCLUDES=['subdir'],
PATH=self.content_path, STATIC_PATHS=[''])
context = settings.copy()
context['filenames'] = {}
StaticGenerator(context=context, settings=settings,
path=settings['PATH'], output_path=None,
theme=settings['THEME']).generate_context()
staticnames = [os.path.basename(c.source_path)
for c in context['staticfiles']]
self.assertNotIn('subdir_fake_image.jpg', staticnames,
"StaticGenerator processed a file in a STATIC_EXCLUDES directory")
self.assertIn('fake_image.jpg', staticnames,
"StaticGenerator skipped a file that it should have included")
def test_static_exclude_sources(self):
"""Test that StaticGenerator respects STATIC_EXCLUDE_SOURCES.
"""
# Test STATIC_EXCLUDE_SOURCES=True
settings = get_settings(STATIC_EXCLUDE_SOURCES=True,
PATH=self.content_path, PAGE_PATHS=[''], STATIC_PATHS=[''],
CACHE_CONTENT=False)
context = settings.copy()
context['filenames'] = {}
for generator_class in (PagesGenerator, StaticGenerator):
generator_class(context=context, settings=settings,
path=settings['PATH'], output_path=None,
theme=settings['THEME']).generate_context()
staticnames = [os.path.basename(c.source_path)
for c in context['staticfiles']]
self.assertFalse(any(name.endswith(".md") for name in staticnames),
"STATIC_EXCLUDE_SOURCES=True failed to exclude a markdown file")
# Test STATIC_EXCLUDE_SOURCES=False
settings.update(STATIC_EXCLUDE_SOURCES=False)
context = settings.copy()
context['filenames'] = {}
for generator_class in (PagesGenerator, StaticGenerator):
generator_class(context=context, settings=settings,
path=settings['PATH'], output_path=None,
theme=settings['THEME']).generate_context()
staticnames = [os.path.basename(c.source_path)
for c in context['staticfiles']]
self.assertTrue(any(name.endswith(".md") for name in staticnames),
"STATIC_EXCLUDE_SOURCES=False failed to include a markdown file")