Varia's website https://varia.zone
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
13 KiB

import copy
import locale
import os
from os.path import abspath, dirname, join
from sys import platform
from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME,
_printf_s_to_format_field,
coerce_overrides, configure_settings,
handle_deprecated_settings, read_settings)
from pelican.tests.support import unittest
class TestSettingsConfiguration(unittest.TestCase):
"""Provided a file, it should read it, replace the default values,
append new values to the settings (if any), and apply basic settings
optimizations.
"""
def setUp(self):
self.old_locale = locale.setlocale(locale.LC_ALL)
locale.setlocale(locale.LC_ALL, 'C')
self.PATH = abspath(dirname(__file__))
default_conf = join(self.PATH, 'default_conf.py')
self.settings = read_settings(default_conf)
def tearDown(self):
locale.setlocale(locale.LC_ALL, self.old_locale)
def test_overwrite_existing_settings(self):
self.assertEqual(self.settings.get('SITENAME'), "Alexis' log")
self.assertEqual(
self.settings.get('SITEURL'),
'http://blog.notmyidea.org')
def test_keep_default_settings(self):
# Keep default settings if not defined.
self.assertEqual(
self.settings.get('DEFAULT_CATEGORY'),
DEFAULT_CONFIG['DEFAULT_CATEGORY'])
def test_dont_copy_small_keys(self):
# Do not copy keys not in caps.
self.assertNotIn('foobar', self.settings)
def test_read_empty_settings(self):
# Ensure an empty settings file results in default settings.
settings = read_settings(None)
expected = copy.deepcopy(DEFAULT_CONFIG)
# Added by configure settings
expected['FEED_DOMAIN'] = ''
expected['ARTICLE_EXCLUDES'] = ['pages']
expected['PAGE_EXCLUDES'] = ['']
self.maxDiff = None
self.assertDictEqual(settings, expected)
def test_settings_return_independent(self):
# Make sure that the results from one settings call doesn't
# effect past or future instances.
self.PATH = abspath(dirname(__file__))
default_conf = join(self.PATH, 'default_conf.py')
settings = read_settings(default_conf)
settings['SITEURL'] = 'new-value'
new_settings = read_settings(default_conf)
self.assertNotEqual(new_settings['SITEURL'], settings['SITEURL'])
def test_defaults_not_overwritten(self):
# This assumes 'SITENAME': 'A Pelican Blog'
settings = read_settings(None)
settings['SITENAME'] = 'Not a Pelican Blog'
self.assertNotEqual(settings['SITENAME'], DEFAULT_CONFIG['SITENAME'])
def test_static_path_settings_safety(self):
# Disallow static paths from being strings
settings = {
'STATIC_PATHS': 'foo/bar',
'THEME_STATIC_PATHS': 'bar/baz',
# These 4 settings are required to run configure_settings
'PATH': '.',
'THEME': DEFAULT_THEME,
'SITEURL': 'http://blog.notmyidea.org/',
'LOCALE': '',
}
configure_settings(settings)
self.assertEqual(
settings['STATIC_PATHS'],
DEFAULT_CONFIG['STATIC_PATHS'])
self.assertEqual(
settings['THEME_STATIC_PATHS'],
DEFAULT_CONFIG['THEME_STATIC_PATHS'])
def test_configure_settings(self):
# Manipulations to settings should be applied correctly.
settings = {
'SITEURL': 'http://blog.notmyidea.org/',
'LOCALE': '',
'PATH': os.curdir,
'THEME': DEFAULT_THEME,
}
configure_settings(settings)
# SITEURL should not have a trailing slash
self.assertEqual(settings['SITEURL'], 'http://blog.notmyidea.org')
# FEED_DOMAIN, if undefined, should default to SITEURL
self.assertEqual(settings['FEED_DOMAIN'], 'http://blog.notmyidea.org')
settings['FEED_DOMAIN'] = 'http://feeds.example.com'
configure_settings(settings)
self.assertEqual(settings['FEED_DOMAIN'], 'http://feeds.example.com')
def test_theme_settings_exceptions(self):
settings = self.settings
# Check that theme lookup in "pelican/themes" functions as expected
settings['THEME'] = os.path.split(settings['THEME'])[1]
configure_settings(settings)
self.assertEqual(settings['THEME'], DEFAULT_THEME)
# Check that non-existent theme raises exception
settings['THEME'] = 'foo'
self.assertRaises(Exception, configure_settings, settings)
def test_deprecated_dir_setting(self):
settings = self.settings
settings['ARTICLE_DIR'] = 'foo'
settings['PAGE_DIR'] = 'bar'
settings = handle_deprecated_settings(settings)
self.assertEqual(settings['ARTICLE_PATHS'], ['foo'])
self.assertEqual(settings['PAGE_PATHS'], ['bar'])
with self.assertRaises(KeyError):
settings['ARTICLE_DIR']
settings['PAGE_DIR']
# locale.getdefaultlocale() is broken on Windows
# See: https://bugs.python.org/issue37945
@unittest.skipIf(platform == 'win32', "Doesn't work on Windows")
def test_default_encoding(self):
# Test that the default locale is set if not specified in settings
# Reset locale to Python's default locale
locale.setlocale(locale.LC_ALL, 'C')
self.assertEqual(self.settings['LOCALE'], DEFAULT_CONFIG['LOCALE'])
configure_settings(self.settings)
self.assertEqual(locale.getlocale(), locale.getdefaultlocale())
def test_invalid_settings_throw_exception(self):
# Test that the path name is valid
# test that 'PATH' is set
settings = {
}
self.assertRaises(Exception, configure_settings, settings)
# Test that 'PATH' is valid
settings['PATH'] = ''
self.assertRaises(Exception, configure_settings, settings)
# Test nonexistent THEME
settings['PATH'] = os.curdir
settings['THEME'] = 'foo'
self.assertRaises(Exception, configure_settings, settings)
def test__printf_s_to_format_field(self):
for s in ('%s', '{%s}', '{%s'):
option = 'foo/{}/bar.baz'.format(s)
result = _printf_s_to_format_field(option, 'slug')
expected = option % 'qux'
found = result.format(slug='qux')
self.assertEqual(expected, found)
def test_deprecated_extra_templates_paths(self):
settings = self.settings
settings['EXTRA_TEMPLATES_PATHS'] = ['/foo/bar', '/ha']
settings = handle_deprecated_settings(settings)
self.assertEqual(settings['THEME_TEMPLATES_OVERRIDES'],
['/foo/bar', '/ha'])
self.assertNotIn('EXTRA_TEMPLATES_PATHS', settings)
def test_deprecated_paginated_direct_templates(self):
settings = self.settings
settings['PAGINATED_DIRECT_TEMPLATES'] = ['index', 'archives']
settings['PAGINATED_TEMPLATES'] = {'index': 10, 'category': None}
settings = handle_deprecated_settings(settings)
self.assertEqual(settings['PAGINATED_TEMPLATES'],
{'index': 10, 'category': None, 'archives': None})
self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)
def test_deprecated_paginated_direct_templates_from_file(self):
# This is equivalent to reading a settings file that has
# PAGINATED_DIRECT_TEMPLATES defined but no PAGINATED_TEMPLATES.
settings = read_settings(None, override={
'PAGINATED_DIRECT_TEMPLATES': ['index', 'archives']
})
self.assertEqual(settings['PAGINATED_TEMPLATES'], {
'archives': None,
'author': None,
'index': None,
'category': None,
'tag': None})
self.assertNotIn('PAGINATED_DIRECT_TEMPLATES', settings)
def test_theme_and_extra_templates_exception(self):
settings = self.settings
settings['EXTRA_TEMPLATES_PATHS'] = ['/ha']
settings['THEME_TEMPLATES_OVERRIDES'] = ['/foo/bar']
self.assertRaises(Exception, handle_deprecated_settings, settings)
def test_slug_and_slug_regex_substitutions_exception(self):
settings = {}
settings['SLUG_REGEX_SUBSTITUTIONS'] = [('C++', 'cpp')]
settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
self.assertRaises(Exception, handle_deprecated_settings, settings)
def test_deprecated_slug_substitutions(self):
default_slug_regex_subs = self.settings['SLUG_REGEX_SUBSTITUTIONS']
# If no deprecated setting is set, don't set new ones
settings = {}
settings = handle_deprecated_settings(settings)
self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
self.assertNotIn('AUTHOR_REGEX_SUBSTITUTIONS', settings)
# If SLUG_SUBSTITUTIONS is set, set {SLUG, AUTHOR}_REGEX_SUBSTITUTIONS
# correctly, don't set {CATEGORY, TAG}_REGEX_SUBSTITUTIONS
settings = {}
settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
settings = handle_deprecated_settings(settings)
self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
[(r'C\+\+', 'cpp')] + default_slug_regex_subs)
self.assertNotIn('TAG_REGEX_SUBSTITUTIONS', settings)
self.assertNotIn('CATEGORY_REGEX_SUBSTITUTIONS', settings)
self.assertEqual(settings.get('AUTHOR_REGEX_SUBSTITUTIONS'),
default_slug_regex_subs)
# If {CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
# {CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly, don't set
# SLUG_REGEX_SUBSTITUTIONS
settings = {}
settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
settings = handle_deprecated_settings(settings)
self.assertNotIn('SLUG_REGEX_SUBSTITUTIONS', settings)
self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
[(r'C\#', 'csharp')] + default_slug_regex_subs)
self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
[(r'C\#', 'csharp')] + default_slug_regex_subs)
self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
[(r'Alexander\ Todorov', 'atodorov')] +
default_slug_regex_subs)
# If {SLUG, CATEGORY, TAG, AUTHOR}_SUBSTITUTIONS are set, set
# {SLUG, CATEGORY, TAG, AUTHOR}_REGEX_SUBSTITUTIONS correctly
settings = {}
settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp')]
settings['TAG_SUBSTITUTIONS'] = [('C#', 'csharp')]
settings['CATEGORY_SUBSTITUTIONS'] = [('C#', 'csharp')]
settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov')]
settings = handle_deprecated_settings(settings)
self.assertEqual(settings['TAG_REGEX_SUBSTITUTIONS'],
[(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
default_slug_regex_subs)
self.assertEqual(settings['CATEGORY_REGEX_SUBSTITUTIONS'],
[(r'C\+\+', 'cpp')] + [(r'C\#', 'csharp')] +
default_slug_regex_subs)
self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
[(r'Alexander\ Todorov', 'atodorov')] +
default_slug_regex_subs)
# Handle old 'skip' flags correctly
settings = {}
settings['SLUG_SUBSTITUTIONS'] = [('C++', 'cpp', True)]
settings['AUTHOR_SUBSTITUTIONS'] = [('Alexander Todorov', 'atodorov',
False)]
settings = handle_deprecated_settings(settings)
self.assertEqual(settings.get('SLUG_REGEX_SUBSTITUTIONS'),
[(r'C\+\+', 'cpp')] +
[(r'(?u)\A\s*', ''), (r'(?u)\s*\Z', '')])
self.assertEqual(settings['AUTHOR_REGEX_SUBSTITUTIONS'],
[(r'Alexander\ Todorov', 'atodorov')] +
default_slug_regex_subs)
def test_deprecated_slug_substitutions_from_file(self):
# This is equivalent to reading a settings file that has
# SLUG_SUBSTITUTIONS defined but no SLUG_REGEX_SUBSTITUTIONS.
settings = read_settings(None, override={
'SLUG_SUBSTITUTIONS': [('C++', 'cpp')]
})
self.assertEqual(settings['SLUG_REGEX_SUBSTITUTIONS'],
[(r'C\+\+', 'cpp')] +
self.settings['SLUG_REGEX_SUBSTITUTIONS'])
self.assertNotIn('SLUG_SUBSTITUTIONS', settings)
def test_coerce_overrides(self):
overrides = coerce_overrides({
'ARTICLE_EXCLUDES': '["testexcl"]',
'READERS': '{"foo": "bar"}',
'STATIC_EXCLUDE_SOURCES': 'true',
'THEME_STATIC_DIR': 'theme',
})
expected = {
'ARTICLE_EXCLUDES': ["testexcl"],
'READERS': {"foo": "bar"},
'STATIC_EXCLUDE_SOURCES': True,
'THEME_STATIC_DIR': 'theme',
}
self.assertDictEqual(overrides, expected)