2011-02-01 22:49:33 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2015-06-16 09:25:09 +02:00
|
|
|
from __future__ import print_function, unicode_literals
|
2013-01-11 02:57:43 +01:00
|
|
|
|
2012-08-29 12:17:59 -07:00
|
|
|
import copy
|
2012-08-01 13:36:47 -04:00
|
|
|
import inspect
|
2011-02-01 21:44:50 +00:00
|
|
|
import locale
|
2012-03-20 13:01:21 +00:00
|
|
|
import logging
|
2015-06-16 09:25:09 +02:00
|
|
|
import os
|
2018-08-07 17:35:16 +02:00
|
|
|
import re
|
2015-06-16 09:25:09 +02:00
|
|
|
from os.path import isabs
|
|
|
|
|
from posixpath import join as posix_join
|
|
|
|
|
|
|
|
|
|
import six
|
|
|
|
|
|
|
|
|
|
from pelican.log import LimitFilter
|
2012-03-20 13:01:21 +00:00
|
|
|
|
2019-09-23 17:48:56 +02:00
|
|
|
|
2013-04-13 16:36:05 -04:00
|
|
|
try:
|
2019-09-23 17:48:56 +02:00
|
|
|
# spec_from_file_location is the recommended way in Python 3.5+
|
|
|
|
|
import importlib.util
|
2015-06-16 09:25:09 +02:00
|
|
|
|
|
|
|
|
def load_source(name, path):
|
2019-09-23 17:48:56 +02:00
|
|
|
spec = importlib.util.spec_from_file_location(name, path)
|
|
|
|
|
mod = importlib.util.module_from_spec(spec)
|
|
|
|
|
spec.loader.exec_module(mod)
|
|
|
|
|
return mod
|
2013-04-13 16:36:05 -04:00
|
|
|
except ImportError:
|
2017-10-02 18:33:21 +03:00
|
|
|
# but it does not exist in Python 2.7, so fall back to imp
|
2013-04-13 16:36:05 -04:00
|
|
|
import imp
|
|
|
|
|
load_source = imp.load_source
|
|
|
|
|
|
2012-03-20 13:01:21 +00:00
|
|
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
2010-10-30 00:56:40 +01:00
|
|
|
|
2013-01-04 14:46:17 -05:00
|
|
|
DEFAULT_THEME = os.path.join(os.path.dirname(os.path.abspath(__file__)),
|
|
|
|
|
'themes', 'notmyidea')
|
2013-03-24 08:38:19 -04:00
|
|
|
DEFAULT_CONFIG = {
|
|
|
|
|
'PATH': os.curdir,
|
2014-04-21 11:36:17 +02:00
|
|
|
'ARTICLE_PATHS': [''],
|
2014-05-14 14:30:21 +02:00
|
|
|
'ARTICLE_EXCLUDES': [],
|
2014-04-21 11:36:17 +02:00
|
|
|
'PAGE_PATHS': ['pages'],
|
2014-05-14 14:30:21 +02:00
|
|
|
'PAGE_EXCLUDES': [],
|
2013-03-24 08:38:19 -04:00
|
|
|
'THEME': DEFAULT_THEME,
|
|
|
|
|
'OUTPUT_PATH': 'output',
|
2013-08-04 17:02:58 +02:00
|
|
|
'READERS': {},
|
2014-10-18 13:11:59 -07:00
|
|
|
'STATIC_PATHS': ['images'],
|
|
|
|
|
'STATIC_EXCLUDES': [],
|
|
|
|
|
'STATIC_EXCLUDE_SOURCES': True,
|
2013-07-18 10:36:44 +08:00
|
|
|
'THEME_STATIC_DIR': 'theme',
|
2013-03-24 08:38:19 -04:00
|
|
|
'THEME_STATIC_PATHS': ['static', ],
|
2015-01-02 23:45:44 -08:00
|
|
|
'FEED_ALL_ATOM': posix_join('feeds', 'all.atom.xml'),
|
2018-11-03 09:12:20 -06:00
|
|
|
'CATEGORY_FEED_ATOM': posix_join('feeds', '{slug}.atom.xml'),
|
|
|
|
|
'AUTHOR_FEED_ATOM': posix_join('feeds', '{slug}.atom.xml'),
|
|
|
|
|
'AUTHOR_FEED_RSS': posix_join('feeds', '{slug}.rss.xml'),
|
|
|
|
|
'TRANSLATION_FEED_ATOM': posix_join('feeds', 'all-{lang}.atom.xml'),
|
2013-03-24 08:38:19 -04:00
|
|
|
'FEED_MAX_ITEMS': '',
|
2016-11-16 02:18:46 +03:00
|
|
|
'RSS_FEED_SUMMARY_ONLY': True,
|
2013-03-24 08:38:19 -04:00
|
|
|
'SITEURL': '',
|
|
|
|
|
'SITENAME': 'A Pelican Blog',
|
|
|
|
|
'DISPLAY_PAGES_ON_MENU': True,
|
|
|
|
|
'DISPLAY_CATEGORIES_ON_MENU': True,
|
2014-07-31 18:04:35 -07:00
|
|
|
'DOCUTILS_SETTINGS': {},
|
2013-03-24 08:38:19 -04:00
|
|
|
'OUTPUT_SOURCES': False,
|
|
|
|
|
'OUTPUT_SOURCES_EXTENSION': '.text',
|
|
|
|
|
'USE_FOLDER_AS_CATEGORY': True,
|
|
|
|
|
'DEFAULT_CATEGORY': 'misc',
|
|
|
|
|
'WITH_FUTURE_DATES': True,
|
|
|
|
|
'CSS_FILE': 'main.css',
|
|
|
|
|
'NEWEST_FIRST_ARCHIVES': True,
|
|
|
|
|
'REVERSE_CATEGORY_ORDER': False,
|
|
|
|
|
'DELETE_OUTPUT_DIRECTORY': False,
|
2015-01-17 16:20:39 -08:00
|
|
|
'OUTPUT_RETENTION': [],
|
2015-09-15 02:24:21 +03:00
|
|
|
'INDEX_SAVE_AS': 'index.html',
|
2013-03-24 08:38:19 -04:00
|
|
|
'ARTICLE_URL': '{slug}.html',
|
|
|
|
|
'ARTICLE_SAVE_AS': '{slug}.html',
|
2015-06-12 17:15:19 -04:00
|
|
|
'ARTICLE_ORDER_BY': 'reversed-date',
|
2013-03-24 08:38:19 -04:00
|
|
|
'ARTICLE_LANG_URL': '{slug}-{lang}.html',
|
|
|
|
|
'ARTICLE_LANG_SAVE_AS': '{slug}-{lang}.html',
|
2013-12-26 19:30:55 +01:00
|
|
|
'DRAFT_URL': 'drafts/{slug}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'DRAFT_SAVE_AS': posix_join('drafts', '{slug}.html'),
|
2013-12-26 19:30:55 +01:00
|
|
|
'DRAFT_LANG_URL': 'drafts/{slug}-{lang}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'DRAFT_LANG_SAVE_AS': posix_join('drafts', '{slug}-{lang}.html'),
|
2013-03-24 08:38:19 -04:00
|
|
|
'PAGE_URL': 'pages/{slug}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'PAGE_SAVE_AS': posix_join('pages', '{slug}.html'),
|
2014-05-27 11:42:37 -07:00
|
|
|
'PAGE_ORDER_BY': 'basename',
|
2013-03-24 08:38:19 -04:00
|
|
|
'PAGE_LANG_URL': 'pages/{slug}-{lang}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'PAGE_LANG_SAVE_AS': posix_join('pages', '{slug}-{lang}.html'),
|
2018-07-03 12:08:27 +02:00
|
|
|
'DRAFT_PAGE_URL': 'drafts/pages/{slug}.html',
|
|
|
|
|
'DRAFT_PAGE_SAVE_AS': posix_join('drafts', 'pages', '{slug}.html'),
|
|
|
|
|
'DRAFT_PAGE_LANG_URL': 'drafts/pages/{slug}-{lang}.html',
|
|
|
|
|
'DRAFT_PAGE_LANG_SAVE_AS': posix_join('drafts', 'pages',
|
|
|
|
|
'{slug}-{lang}.html'),
|
2013-03-24 08:38:19 -04:00
|
|
|
'STATIC_URL': '{path}',
|
|
|
|
|
'STATIC_SAVE_AS': '{path}',
|
2016-07-23 03:04:04 -04:00
|
|
|
'STATIC_CREATE_LINKS': False,
|
|
|
|
|
'STATIC_CHECK_IF_MODIFIED': False,
|
2013-03-24 08:38:19 -04:00
|
|
|
'CATEGORY_URL': 'category/{slug}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'CATEGORY_SAVE_AS': posix_join('category', '{slug}.html'),
|
2013-03-24 08:38:19 -04:00
|
|
|
'TAG_URL': 'tag/{slug}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'TAG_SAVE_AS': posix_join('tag', '{slug}.html'),
|
2013-03-24 08:38:19 -04:00
|
|
|
'AUTHOR_URL': 'author/{slug}.html',
|
2015-01-02 23:45:44 -08:00
|
|
|
'AUTHOR_SAVE_AS': posix_join('author', '{slug}.html'),
|
2013-07-29 08:10:28 -04:00
|
|
|
'PAGINATION_PATTERNS': [
|
2018-07-05 13:55:51 +02:00
|
|
|
(1, '{name}{extension}', '{name}{extension}'),
|
|
|
|
|
(2, '{name}{number}{extension}', '{name}{number}{extension}'),
|
2013-07-29 08:10:28 -04:00
|
|
|
],
|
2017-10-26 18:23:17 +02:00
|
|
|
'YEAR_ARCHIVE_URL': '',
|
2014-03-31 19:38:49 +02:00
|
|
|
'YEAR_ARCHIVE_SAVE_AS': '',
|
2017-10-26 18:23:17 +02:00
|
|
|
'MONTH_ARCHIVE_URL': '',
|
2014-03-31 19:38:49 +02:00
|
|
|
'MONTH_ARCHIVE_SAVE_AS': '',
|
2017-10-26 18:23:17 +02:00
|
|
|
'DAY_ARCHIVE_URL': '',
|
2014-03-31 19:38:49 +02:00
|
|
|
'DAY_ARCHIVE_SAVE_AS': '',
|
2013-03-24 08:38:19 -04:00
|
|
|
'RELATIVE_URLS': False,
|
|
|
|
|
'DEFAULT_LANG': 'en',
|
2018-03-22 23:47:51 +01:00
|
|
|
'ARTICLE_TRANSLATION_ID': 'slug',
|
|
|
|
|
'PAGE_TRANSLATION_ID': 'slug',
|
2015-01-17 16:20:39 -08:00
|
|
|
'DIRECT_TEMPLATES': ['index', 'tags', 'categories', 'authors', 'archives'],
|
2016-10-16 15:47:22 +08:00
|
|
|
'THEME_TEMPLATES_OVERRIDES': [],
|
2018-07-12 13:41:05 +02:00
|
|
|
'PAGINATED_TEMPLATES': {'index': None, 'tag': None, 'category': None,
|
|
|
|
|
'author': None},
|
2013-03-24 08:38:19 -04:00
|
|
|
'PELICAN_CLASS': 'pelican.Pelican',
|
|
|
|
|
'DEFAULT_DATE_FORMAT': '%a %d %B %Y',
|
|
|
|
|
'DATE_FORMATS': {},
|
2016-03-14 20:37:27 +01:00
|
|
|
'MARKDOWN': {
|
|
|
|
|
'extension_configs': {
|
|
|
|
|
'markdown.extensions.codehilite': {'css_class': 'highlight'},
|
|
|
|
|
'markdown.extensions.extra': {},
|
|
|
|
|
'markdown.extensions.meta': {},
|
|
|
|
|
},
|
2016-11-02 21:00:04 +01:00
|
|
|
'output_format': 'html5',
|
2015-11-08 23:08:03 +01:00
|
|
|
},
|
2013-03-24 15:45:36 -04:00
|
|
|
'JINJA_FILTERS': {},
|
2016-08-29 11:19:29 -07:00
|
|
|
'JINJA_ENVIRONMENT': {
|
|
|
|
|
'trim_blocks': True,
|
|
|
|
|
'lstrip_blocks': True,
|
|
|
|
|
'extensions': [],
|
|
|
|
|
},
|
2014-04-01 20:44:09 +02:00
|
|
|
'LOG_FILTER': [],
|
2013-07-21 13:31:11 +08:00
|
|
|
'LOCALE': [''], # defaults to user locale
|
2013-03-24 08:38:19 -04:00
|
|
|
'DEFAULT_PAGINATION': False,
|
|
|
|
|
'DEFAULT_ORPHANS': 0,
|
2015-01-17 16:20:39 -08:00
|
|
|
'DEFAULT_METADATA': {},
|
2017-03-27 16:06:07 +02:00
|
|
|
'FILENAME_METADATA': r'(?P<date>\d{4}-\d{2}-\d{2}).*',
|
2013-03-24 08:38:19 -04:00
|
|
|
'PATH_METADATA': '',
|
2013-06-03 15:15:53 -04:00
|
|
|
'EXTRA_PATH_METADATA': {},
|
2013-03-24 08:38:19 -04:00
|
|
|
'ARTICLE_PERMALINK_STRUCTURE': '',
|
|
|
|
|
'TYPOGRIFY': False,
|
2014-07-19 15:07:44 -07:00
|
|
|
'TYPOGRIFY_IGNORE_TAGS': [],
|
2013-03-24 08:38:19 -04:00
|
|
|
'SUMMARY_MAX_LENGTH': 50,
|
2014-05-14 14:06:58 +02:00
|
|
|
'PLUGIN_PATHS': [],
|
2013-03-24 08:38:19 -04:00
|
|
|
'PLUGINS': [],
|
2013-09-15 22:43:24 -07:00
|
|
|
'PYGMENTS_RST_OPTIONS': {},
|
2013-03-24 08:38:19 -04:00
|
|
|
'TEMPLATE_PAGES': {},
|
2017-01-15 22:57:01 +00:00
|
|
|
'TEMPLATE_EXTENSIONS': ['.html'],
|
2013-03-24 08:38:19 -04:00
|
|
|
'IGNORE_FILES': ['.#*'],
|
2018-08-07 17:35:16 +02:00
|
|
|
'SLUG_REGEX_SUBSTITUTIONS': [
|
|
|
|
|
(r'[^\w\s-]', ''), # remove non-alphabetical/whitespace/'-' chars
|
|
|
|
|
(r'(?u)\A\s*', ''), # strip leading whitespace
|
|
|
|
|
(r'(?u)\s*\Z', ''), # strip trailing whitespace
|
|
|
|
|
(r'[-\s]+', '-'), # reduce multiple whitespace or '-' to single '-'
|
|
|
|
|
],
|
2013-09-01 00:35:13 +05:00
|
|
|
'INTRASITE_LINK_REGEX': '[{|](?P<what>.*?)[|}]',
|
2014-02-15 21:20:51 +01:00
|
|
|
'SLUGIFY_SOURCE': 'title',
|
2015-06-06 20:07:12 +02:00
|
|
|
'CACHE_CONTENT': False,
|
2014-04-20 14:34:52 +02:00
|
|
|
'CONTENT_CACHING_LAYER': 'reader',
|
2014-04-27 08:53:56 +02:00
|
|
|
'CACHE_PATH': 'cache',
|
2014-02-15 21:20:51 +01:00
|
|
|
'GZIP_CACHE': True,
|
|
|
|
|
'CHECK_MODIFIED_METHOD': 'mtime',
|
2015-06-06 20:07:12 +02:00
|
|
|
'LOAD_CONTENT_CACHE': False,
|
2014-04-17 16:28:22 +02:00
|
|
|
'WRITE_SELECTED': [],
|
2015-02-10 14:49:29 -05:00
|
|
|
'FORMATTED_FIELDS': ['summary'],
|
2017-07-10 16:59:35 +02:00
|
|
|
'PORT': 8000,
|
|
|
|
|
'BIND': '',
|
2015-06-16 09:25:09 +02:00
|
|
|
}
|
2012-03-09 16:21:38 +01:00
|
|
|
|
2013-09-15 22:43:24 -07:00
|
|
|
PYGMENTS_RST_OPTIONS = None
|
|
|
|
|
|
2013-08-04 17:02:58 +02:00
|
|
|
|
2013-01-04 10:50:09 -05:00
|
|
|
def read_settings(path=None, override=None):
|
2018-08-07 17:35:16 +02:00
|
|
|
settings = override or {}
|
|
|
|
|
|
|
|
|
|
if path:
|
|
|
|
|
settings = dict(get_settings_from_file(path), **settings)
|
|
|
|
|
|
|
|
|
|
if settings:
|
|
|
|
|
settings = handle_deprecated_settings(settings)
|
|
|
|
|
|
2013-01-04 10:50:09 -05:00
|
|
|
if path:
|
2018-08-07 17:35:16 +02:00
|
|
|
# Make relative paths absolute
|
|
|
|
|
def getabs(maybe_relative, base_path=path):
|
|
|
|
|
if isabs(maybe_relative):
|
|
|
|
|
return maybe_relative
|
|
|
|
|
return os.path.abspath(os.path.normpath(os.path.join(
|
|
|
|
|
os.path.dirname(base_path), maybe_relative)))
|
|
|
|
|
|
2014-04-27 08:53:56 +02:00
|
|
|
for p in ['PATH', 'OUTPUT_PATH', 'THEME', 'CACHE_PATH']:
|
2018-08-07 17:35:16 +02:00
|
|
|
if settings.get(p) is not None:
|
|
|
|
|
absp = getabs(settings[p])
|
|
|
|
|
# THEME may be a name rather than a path
|
2016-05-04 20:28:03 +02:00
|
|
|
if p != 'THEME' or os.path.exists(absp):
|
2018-08-07 17:35:16 +02:00
|
|
|
settings[p] = absp
|
2012-10-16 01:35:35 +02:00
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
if settings.get('PLUGIN_PATHS') is not None:
|
|
|
|
|
settings['PLUGIN_PATHS'] = [getabs(pluginpath)
|
|
|
|
|
for pluginpath
|
|
|
|
|
in settings['PLUGIN_PATHS']]
|
|
|
|
|
|
|
|
|
|
settings = dict(copy.deepcopy(DEFAULT_CONFIG), **settings)
|
|
|
|
|
settings = configure_settings(settings)
|
2012-10-16 01:35:35 +02:00
|
|
|
|
2013-09-15 22:43:24 -07:00
|
|
|
# This is because there doesn't seem to be a way to pass extra
|
|
|
|
|
# parameters to docutils directive handlers, so we have to have a
|
|
|
|
|
# variable here that we'll import from within Pygments.run (see
|
|
|
|
|
# rstdirectives.py) to see what the user defaults were.
|
|
|
|
|
global PYGMENTS_RST_OPTIONS
|
2018-08-07 17:35:16 +02:00
|
|
|
PYGMENTS_RST_OPTIONS = settings.get('PYGMENTS_RST_OPTIONS', None)
|
|
|
|
|
return settings
|
2012-03-22 07:58:04 -07:00
|
|
|
|
|
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
def get_settings_from_module(module=None):
|
2013-03-10 20:11:36 -07:00
|
|
|
"""Loads settings from a module, returns a dictionary."""
|
2012-08-01 13:36:47 -04:00
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
context = {}
|
2012-08-01 13:36:47 -04:00
|
|
|
if module is not None:
|
2012-10-16 01:35:35 +02:00
|
|
|
context.update(
|
2013-08-04 17:02:58 +02:00
|
|
|
(k, v) for k, v in inspect.getmembers(module) if k.isupper())
|
2012-03-22 07:58:04 -07:00
|
|
|
return context
|
|
|
|
|
|
2011-02-01 21:44:50 +00:00
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
def get_settings_from_file(path):
|
2013-03-10 20:11:36 -07:00
|
|
|
"""Loads settings from a file path, returning a dict."""
|
2012-08-01 13:36:47 -04:00
|
|
|
|
2013-01-04 15:09:47 -05:00
|
|
|
name, ext = os.path.splitext(os.path.basename(path))
|
2013-04-13 16:36:05 -04:00
|
|
|
module = load_source(name, path)
|
2018-08-07 17:35:16 +02:00
|
|
|
return get_settings_from_module(module)
|
2012-08-01 13:36:47 -04:00
|
|
|
|
|
|
|
|
|
2016-08-29 11:19:29 -07:00
|
|
|
def get_jinja_environment(settings):
|
|
|
|
|
"""Sets the environment for Jinja"""
|
|
|
|
|
|
|
|
|
|
jinja_env = settings.setdefault('JINJA_ENVIRONMENT',
|
|
|
|
|
DEFAULT_CONFIG['JINJA_ENVIRONMENT'])
|
|
|
|
|
|
|
|
|
|
# Make sure we include the defaults if the user has set env variables
|
|
|
|
|
for key, value in DEFAULT_CONFIG['JINJA_ENVIRONMENT'].items():
|
|
|
|
|
if key not in jinja_env:
|
|
|
|
|
jinja_env[key] = value
|
|
|
|
|
|
|
|
|
|
return settings
|
|
|
|
|
|
|
|
|
|
|
2018-11-09 10:33:36 -08:00
|
|
|
def _printf_s_to_format_field(printf_string, format_field):
|
|
|
|
|
"""Tries to replace %s with {format_field} in the provided printf_string.
|
|
|
|
|
Raises ValueError in case of failure.
|
|
|
|
|
"""
|
|
|
|
|
TEST_STRING = 'PELICAN_PRINTF_S_DEPRECATION'
|
|
|
|
|
expected = printf_string % TEST_STRING
|
|
|
|
|
|
|
|
|
|
result = printf_string.replace('{', '{{').replace('}', '}}') \
|
|
|
|
|
% '{{{}}}'.format(format_field)
|
|
|
|
|
if result.format(**{format_field: TEST_STRING}) != expected:
|
|
|
|
|
raise ValueError('Failed to safely replace %s with {{{}}}'.format(
|
|
|
|
|
format_field))
|
|
|
|
|
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
def handle_deprecated_settings(settings):
|
|
|
|
|
"""Converts deprecated settings and issues warnings. Issues an exception
|
|
|
|
|
if both old and new setting is specified.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
# PLUGIN_PATH -> PLUGIN_PATHS
|
|
|
|
|
if 'PLUGIN_PATH' in settings:
|
|
|
|
|
logger.warning('PLUGIN_PATH setting has been replaced by '
|
|
|
|
|
'PLUGIN_PATHS, moving it to the new setting name.')
|
|
|
|
|
settings['PLUGIN_PATHS'] = settings['PLUGIN_PATH']
|
|
|
|
|
del settings['PLUGIN_PATH']
|
|
|
|
|
|
|
|
|
|
# PLUGIN_PATHS: str -> [str]
|
|
|
|
|
if isinstance(settings.get('PLUGIN_PATHS'), six.string_types):
|
|
|
|
|
logger.warning("Defining PLUGIN_PATHS setting as string "
|
|
|
|
|
"has been deprecated (should be a list)")
|
|
|
|
|
settings['PLUGIN_PATHS'] = [settings['PLUGIN_PATHS']]
|
|
|
|
|
|
|
|
|
|
# JINJA_EXTENSIONS -> JINJA_ENVIRONMENT > extensions
|
|
|
|
|
if 'JINJA_EXTENSIONS' in settings:
|
|
|
|
|
logger.warning('JINJA_EXTENSIONS setting has been deprecated, '
|
|
|
|
|
'moving it to JINJA_ENVIRONMENT setting.')
|
|
|
|
|
settings['JINJA_ENVIRONMENT']['extensions'] = \
|
|
|
|
|
settings['JINJA_EXTENSIONS']
|
|
|
|
|
del settings['JINJA_EXTENSIONS']
|
|
|
|
|
|
|
|
|
|
# {ARTICLE,PAGE}_DIR -> {ARTICLE,PAGE}_PATHS
|
|
|
|
|
for key in ['ARTICLE', 'PAGE']:
|
|
|
|
|
old_key = key + '_DIR'
|
|
|
|
|
new_key = key + '_PATHS'
|
|
|
|
|
if old_key in settings:
|
|
|
|
|
logger.warning(
|
|
|
|
|
'Deprecated setting %s, moving it to %s list',
|
|
|
|
|
old_key, new_key)
|
|
|
|
|
settings[new_key] = [settings[old_key]] # also make a list
|
|
|
|
|
del settings[old_key]
|
|
|
|
|
|
|
|
|
|
# EXTRA_TEMPLATES_PATHS -> THEME_TEMPLATES_OVERRIDES
|
|
|
|
|
if 'EXTRA_TEMPLATES_PATHS' in settings:
|
|
|
|
|
logger.warning('EXTRA_TEMPLATES_PATHS is deprecated use '
|
|
|
|
|
'THEME_TEMPLATES_OVERRIDES instead.')
|
|
|
|
|
if ('THEME_TEMPLATES_OVERRIDES' in settings and
|
|
|
|
|
settings['THEME_TEMPLATES_OVERRIDES']):
|
|
|
|
|
raise Exception(
|
|
|
|
|
'Setting both EXTRA_TEMPLATES_PATHS and '
|
|
|
|
|
'THEME_TEMPLATES_OVERRIDES is not permitted. Please move to '
|
|
|
|
|
'only setting THEME_TEMPLATES_OVERRIDES.')
|
|
|
|
|
settings['THEME_TEMPLATES_OVERRIDES'] = \
|
|
|
|
|
settings['EXTRA_TEMPLATES_PATHS']
|
|
|
|
|
del settings['EXTRA_TEMPLATES_PATHS']
|
|
|
|
|
|
|
|
|
|
# MD_EXTENSIONS -> MARKDOWN
|
|
|
|
|
if 'MD_EXTENSIONS' in settings:
|
|
|
|
|
logger.warning('MD_EXTENSIONS is deprecated use MARKDOWN '
|
|
|
|
|
'instead. Falling back to the default.')
|
|
|
|
|
settings['MARKDOWN'] = DEFAULT_CONFIG['MARKDOWN']
|
|
|
|
|
|
|
|
|
|
# LESS_GENERATOR -> Webassets plugin
|
|
|
|
|
# FILES_TO_COPY -> STATIC_PATHS, EXTRA_PATH_METADATA
|
|
|
|
|
for old, new, doc in [
|
|
|
|
|
('LESS_GENERATOR', 'the Webassets plugin', None),
|
|
|
|
|
('FILES_TO_COPY', 'STATIC_PATHS and EXTRA_PATH_METADATA',
|
|
|
|
|
'https://github.com/getpelican/pelican/'
|
|
|
|
|
'blob/master/docs/settings.rst#path-metadata'),
|
|
|
|
|
]:
|
|
|
|
|
if old in settings:
|
|
|
|
|
message = 'The {} setting has been removed in favor of {}'.format(
|
|
|
|
|
old, new)
|
|
|
|
|
if doc:
|
|
|
|
|
message += ', see {} for details'.format(doc)
|
|
|
|
|
logger.warning(message)
|
|
|
|
|
|
|
|
|
|
# PAGINATED_DIRECT_TEMPLATES -> PAGINATED_TEMPLATES
|
|
|
|
|
if 'PAGINATED_DIRECT_TEMPLATES' in settings:
|
|
|
|
|
message = 'The {} setting has been removed in favor of {}'.format(
|
|
|
|
|
'PAGINATED_DIRECT_TEMPLATES', 'PAGINATED_TEMPLATES')
|
|
|
|
|
logger.warning(message)
|
|
|
|
|
|
2018-11-11 13:57:13 +01:00
|
|
|
# set PAGINATED_TEMPLATES
|
|
|
|
|
if 'PAGINATED_TEMPLATES' not in settings:
|
|
|
|
|
settings['PAGINATED_TEMPLATES'] = {
|
|
|
|
|
'tag': None, 'category': None, 'author': None}
|
|
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
for t in settings['PAGINATED_DIRECT_TEMPLATES']:
|
|
|
|
|
if t not in settings['PAGINATED_TEMPLATES']:
|
|
|
|
|
settings['PAGINATED_TEMPLATES'][t] = None
|
|
|
|
|
del settings['PAGINATED_DIRECT_TEMPLATES']
|
|
|
|
|
|
|
|
|
|
# {SLUG,CATEGORY,TAG,AUTHOR}_SUBSTITUTIONS ->
|
|
|
|
|
# {SLUG,CATEGORY,TAG,AUTHOR}_REGEX_SUBSTITUTIONS
|
|
|
|
|
url_settings_url = \
|
|
|
|
|
'http://docs.getpelican.com/en/latest/settings.html#url-settings'
|
|
|
|
|
flavours = {'SLUG', 'CATEGORY', 'TAG', 'AUTHOR'}
|
|
|
|
|
old_values = {f: settings[f + '_SUBSTITUTIONS']
|
|
|
|
|
for f in flavours if f + '_SUBSTITUTIONS' in settings}
|
|
|
|
|
new_values = {f: settings[f + '_REGEX_SUBSTITUTIONS']
|
|
|
|
|
for f in flavours if f + '_REGEX_SUBSTITUTIONS' in settings}
|
|
|
|
|
if old_values and new_values:
|
|
|
|
|
raise Exception(
|
|
|
|
|
'Setting both {new_key} and {old_key} (or variants thereof) is '
|
|
|
|
|
'not permitted. Please move to only setting {new_key}.'
|
|
|
|
|
.format(old_key='SLUG_SUBSTITUTIONS',
|
|
|
|
|
new_key='SLUG_REGEX_SUBSTITUTIONS'))
|
|
|
|
|
if old_values:
|
|
|
|
|
message = ('{} and variants thereof are deprecated and will be '
|
|
|
|
|
'removed in the future. Please use {} and variants thereof '
|
|
|
|
|
'instead. Check {}.'
|
|
|
|
|
.format('SLUG_SUBSTITUTIONS', 'SLUG_REGEX_SUBSTITUTIONS',
|
|
|
|
|
url_settings_url))
|
|
|
|
|
logger.warning(message)
|
|
|
|
|
if old_values.get('SLUG'):
|
|
|
|
|
for f in {'CATEGORY', 'TAG'}:
|
|
|
|
|
if old_values.get(f):
|
|
|
|
|
old_values[f] = old_values['SLUG'] + old_values[f]
|
|
|
|
|
old_values['AUTHOR'] = old_values.get('AUTHOR', [])
|
|
|
|
|
for f in flavours:
|
|
|
|
|
if old_values.get(f) is not None:
|
|
|
|
|
regex_subs = []
|
|
|
|
|
# by default will replace non-alphanum characters
|
|
|
|
|
replace = True
|
|
|
|
|
for tpl in old_values[f]:
|
|
|
|
|
try:
|
|
|
|
|
src, dst, skip = tpl
|
|
|
|
|
if skip:
|
|
|
|
|
replace = False
|
|
|
|
|
except ValueError:
|
|
|
|
|
src, dst = tpl
|
|
|
|
|
regex_subs.append(
|
|
|
|
|
(re.escape(src), dst.replace('\\', r'\\')))
|
|
|
|
|
|
|
|
|
|
if replace:
|
|
|
|
|
regex_subs += [
|
|
|
|
|
(r'[^\w\s-]', ''),
|
|
|
|
|
(r'(?u)\A\s*', ''),
|
|
|
|
|
(r'(?u)\s*\Z', ''),
|
|
|
|
|
(r'[-\s]+', '-'),
|
|
|
|
|
]
|
|
|
|
|
else:
|
|
|
|
|
regex_subs += [
|
|
|
|
|
(r'(?u)\A\s*', ''),
|
|
|
|
|
(r'(?u)\s*\Z', ''),
|
|
|
|
|
]
|
|
|
|
|
settings[f + '_REGEX_SUBSTITUTIONS'] = regex_subs
|
|
|
|
|
settings.pop(f + '_SUBSTITUTIONS', None)
|
|
|
|
|
|
2018-11-03 09:12:20 -06:00
|
|
|
# `%s` -> '{slug}` or `{lang}` in FEED settings
|
2018-11-03 11:09:17 -06:00
|
|
|
for key in ['TRANSLATION_FEED_ATOM',
|
|
|
|
|
'TRANSLATION_FEED_RSS'
|
|
|
|
|
]:
|
2018-11-09 10:33:36 -08:00
|
|
|
if settings.get(key) and '%s' in settings[key]:
|
2018-11-03 11:09:17 -06:00
|
|
|
logger.warning('%%s usage in %s is deprecated, use {lang} '
|
2018-11-09 10:33:36 -08:00
|
|
|
'instead.', key)
|
|
|
|
|
try:
|
|
|
|
|
settings[key] = _printf_s_to_format_field(
|
|
|
|
|
settings[key], 'lang')
|
|
|
|
|
except ValueError:
|
|
|
|
|
logger.warning('Failed to convert %%s to {lang} for %s. '
|
|
|
|
|
'Falling back to default.', key)
|
|
|
|
|
settings[key] = DEFAULT_CONFIG[key]
|
2018-11-03 11:09:17 -06:00
|
|
|
for key in ['AUTHOR_FEED_ATOM',
|
|
|
|
|
'AUTHOR_FEED_RSS',
|
|
|
|
|
'CATEGORY_FEED_ATOM',
|
|
|
|
|
'CATEGORY_FEED_RSS',
|
|
|
|
|
'TAG_FEED_ATOM',
|
|
|
|
|
'TAG_FEED_RSS',
|
|
|
|
|
]:
|
2018-11-09 10:33:36 -08:00
|
|
|
if settings.get(key) and '%s' in settings[key]:
|
2018-11-03 11:09:17 -06:00
|
|
|
logger.warning('%%s usage in %s is deprecated, use {slug} '
|
2018-11-09 10:33:36 -08:00
|
|
|
'instead.', key)
|
|
|
|
|
try:
|
|
|
|
|
settings[key] = _printf_s_to_format_field(
|
|
|
|
|
settings[key], 'slug')
|
|
|
|
|
except ValueError:
|
|
|
|
|
logger.warning('Failed to convert %%s to {slug} for %s. '
|
|
|
|
|
'Falling back to default.', key)
|
|
|
|
|
settings[key] = DEFAULT_CONFIG[key]
|
2018-11-03 09:12:20 -06:00
|
|
|
|
2018-08-07 17:35:16 +02:00
|
|
|
return settings
|
|
|
|
|
|
|
|
|
|
|
2012-10-16 01:35:35 +02:00
|
|
|
def configure_settings(settings):
|
2014-04-14 16:18:07 -04:00
|
|
|
"""Provide optimizations, error checking, and warnings for the given
|
2013-03-10 20:11:36 -07:00
|
|
|
settings.
|
2014-04-14 16:18:07 -04:00
|
|
|
Also, specify the log messages to be ignored.
|
2012-10-16 01:35:35 +02:00
|
|
|
"""
|
2015-06-16 09:25:09 +02:00
|
|
|
if 'PATH' not in settings or not os.path.isdir(settings['PATH']):
|
2012-10-16 01:35:35 +02:00
|
|
|
raise Exception('You need to specify a path containing the content'
|
2012-10-24 23:34:38 +02:00
|
|
|
' (see pelican --help for more information)')
|
2012-10-16 01:35:35 +02:00
|
|
|
|
2014-04-14 16:18:07 -04:00
|
|
|
# specify the log messages to be ignored
|
2015-06-16 09:25:09 +02:00
|
|
|
log_filter = settings.get('LOG_FILTER', DEFAULT_CONFIG['LOG_FILTER'])
|
|
|
|
|
LimitFilter._ignore.update(set(log_filter))
|
2014-04-01 20:44:09 +02:00
|
|
|
|
2013-03-10 20:11:36 -07:00
|
|
|
# lookup the theme in "pelican/themes" if the given one doesn't exist
|
2012-10-16 01:35:35 +02:00
|
|
|
if not os.path.isdir(settings['THEME']):
|
2013-01-04 14:46:17 -05:00
|
|
|
theme_path = os.path.join(
|
|
|
|
|
os.path.dirname(os.path.abspath(__file__)),
|
|
|
|
|
'themes',
|
|
|
|
|
settings['THEME'])
|
2012-10-16 01:35:35 +02:00
|
|
|
if os.path.exists(theme_path):
|
|
|
|
|
settings['THEME'] = theme_path
|
|
|
|
|
else:
|
2013-04-20 08:08:31 -07:00
|
|
|
raise Exception("Could not find the theme %s"
|
2012-10-24 23:34:38 +02:00
|
|
|
% settings['THEME'])
|
2011-07-02 15:15:21 -05:00
|
|
|
|
2014-04-17 16:28:22 +02:00
|
|
|
# make paths selected for writing absolute if necessary
|
|
|
|
|
settings['WRITE_SELECTED'] = [
|
|
|
|
|
os.path.abspath(path) for path in
|
|
|
|
|
settings.get('WRITE_SELECTED', DEFAULT_CONFIG['WRITE_SELECTED'])
|
2015-06-16 09:25:09 +02:00
|
|
|
]
|
2014-04-17 16:28:22 +02:00
|
|
|
|
2013-03-24 14:01:54 -04:00
|
|
|
# standardize strings to lowercase strings
|
2015-06-16 09:25:09 +02:00
|
|
|
for key in ['DEFAULT_LANG']:
|
2013-03-24 14:01:54 -04:00
|
|
|
if key in settings:
|
|
|
|
|
settings[key] = settings[key].lower()
|
|
|
|
|
|
2016-08-29 11:19:29 -07:00
|
|
|
# set defaults for Jinja environment
|
|
|
|
|
settings = get_jinja_environment(settings)
|
|
|
|
|
|
2013-03-24 14:01:54 -04:00
|
|
|
# standardize strings to lists
|
2015-06-16 09:25:09 +02:00
|
|
|
for key in ['LOCALE']:
|
2013-03-24 14:01:54 -04:00
|
|
|
if key in settings and isinstance(settings[key], six.string_types):
|
|
|
|
|
settings[key] = [settings[key]]
|
|
|
|
|
|
|
|
|
|
# check settings that must be a particular type
|
|
|
|
|
for key, types in [
|
|
|
|
|
('OUTPUT_SOURCES_EXTENSION', six.string_types),
|
|
|
|
|
('FILENAME_METADATA', six.string_types),
|
2015-06-16 09:25:09 +02:00
|
|
|
]:
|
2013-03-24 14:01:54 -04:00
|
|
|
if key in settings and not isinstance(settings[key], types):
|
|
|
|
|
value = settings.pop(key)
|
2015-06-16 09:25:09 +02:00
|
|
|
logger.warn(
|
|
|
|
|
'Detected misconfigured %s (%s), '
|
|
|
|
|
'falling back to the default (%s)',
|
|
|
|
|
key, value, DEFAULT_CONFIG[key])
|
2011-05-19 17:28:45 +01:00
|
|
|
|
|
|
|
|
# try to set the different locales, fallback on the default.
|
2013-03-24 14:01:54 -04:00
|
|
|
locales = settings.get('LOCALE', DEFAULT_CONFIG['LOCALE'])
|
2011-05-31 12:44:40 +02:00
|
|
|
|
2011-05-19 18:10:21 +01:00
|
|
|
for locale_ in locales:
|
2011-05-19 17:28:45 +01:00
|
|
|
try:
|
2013-01-11 02:57:43 +01:00
|
|
|
locale.setlocale(locale.LC_ALL, str(locale_))
|
2012-08-29 12:17:59 -07:00
|
|
|
break # break if it is successful
|
2011-05-19 17:28:45 +01:00
|
|
|
except locale.Error:
|
|
|
|
|
pass
|
2011-05-19 18:10:21 +01:00
|
|
|
else:
|
2016-10-22 15:35:01 -06:00
|
|
|
logger.warning(
|
|
|
|
|
"Locale could not be set. Check the LOCALE setting, ensuring it "
|
|
|
|
|
"is valid and available on your system.")
|
2011-05-19 17:28:45 +01:00
|
|
|
|
2012-03-23 07:16:23 -07:00
|
|
|
if ('SITEURL' in settings):
|
|
|
|
|
# If SITEURL has a trailing slash, remove it and provide a warning
|
|
|
|
|
siteurl = settings['SITEURL']
|
2012-04-18 07:16:51 -07:00
|
|
|
if (siteurl.endswith('/')):
|
2012-03-23 07:16:23 -07:00
|
|
|
settings['SITEURL'] = siteurl[:-1]
|
2013-04-13 16:36:05 -04:00
|
|
|
logger.warning("Removed extraneous trailing slash from SITEURL.")
|
2013-03-03 20:12:31 -08:00
|
|
|
# If SITEURL is defined but FEED_DOMAIN isn't,
|
|
|
|
|
# set FEED_DOMAIN to SITEURL
|
2015-06-16 09:25:09 +02:00
|
|
|
if 'FEED_DOMAIN' not in settings:
|
2012-03-23 07:16:23 -07:00
|
|
|
settings['FEED_DOMAIN'] = settings['SITEURL']
|
2012-03-22 07:58:04 -07:00
|
|
|
|
2014-04-20 14:34:52 +02:00
|
|
|
# check content caching layer and warn of incompatibilities
|
2015-06-16 09:25:09 +02:00
|
|
|
if settings.get('CACHE_CONTENT', False) and \
|
2019-02-06 10:22:57 -04:00
|
|
|
settings.get('CONTENT_CACHING_LAYER', '') == 'generator' and \
|
|
|
|
|
settings.get('WITH_FUTURE_DATES', False):
|
|
|
|
|
logger.warning(
|
|
|
|
|
"WITH_FUTURE_DATES conflicts with CONTENT_CACHING_LAYER "
|
|
|
|
|
"set to 'generator', use 'reader' layer instead")
|
2014-04-20 14:34:52 +02:00
|
|
|
|
2012-03-22 07:58:04 -07:00
|
|
|
# Warn if feeds are generated with both SITEURL & FEED_DOMAIN undefined
|
2013-08-04 17:02:58 +02:00
|
|
|
feed_keys = [
|
|
|
|
|
'FEED_ATOM', 'FEED_RSS',
|
|
|
|
|
'FEED_ALL_ATOM', 'FEED_ALL_RSS',
|
|
|
|
|
'CATEGORY_FEED_ATOM', 'CATEGORY_FEED_RSS',
|
2014-04-05 15:27:03 -04:00
|
|
|
'AUTHOR_FEED_ATOM', 'AUTHOR_FEED_RSS',
|
2013-08-04 17:02:58 +02:00
|
|
|
'TAG_FEED_ATOM', 'TAG_FEED_RSS',
|
|
|
|
|
'TRANSLATION_FEED_ATOM', 'TRANSLATION_FEED_RSS',
|
|
|
|
|
]
|
2012-10-25 16:50:27 +02:00
|
|
|
|
2012-11-07 20:52:59 +01:00
|
|
|
if any(settings.get(k) for k in feed_keys):
|
|
|
|
|
if not settings.get('SITEURL'):
|
2013-08-04 17:02:58 +02:00
|
|
|
logger.warning('Feeds generated without SITEURL set properly may'
|
|
|
|
|
' not be valid')
|
2012-03-22 07:58:04 -07:00
|
|
|
|
2015-06-16 09:25:09 +02:00
|
|
|
if 'TIMEZONE' not in settings:
|
2013-04-13 16:36:05 -04:00
|
|
|
logger.warning(
|
2013-03-03 20:12:31 -08:00
|
|
|
'No timezone information specified in the settings. Assuming'
|
|
|
|
|
' your timezone is UTC for feed generation. Check '
|
2013-04-19 11:12:20 -07:00
|
|
|
'http://docs.getpelican.com/en/latest/settings.html#timezone '
|
2013-03-03 20:12:31 -08:00
|
|
|
'for more information')
|
2011-08-18 13:58:04 +02:00
|
|
|
|
2013-07-29 08:10:28 -04:00
|
|
|
# fix up pagination rules
|
|
|
|
|
from pelican.paginator import PaginationRule
|
|
|
|
|
pagination_rules = [
|
2013-08-03 14:04:58 -07:00
|
|
|
PaginationRule(*r) for r in settings.get(
|
|
|
|
|
'PAGINATION_PATTERNS',
|
|
|
|
|
DEFAULT_CONFIG['PAGINATION_PATTERNS'],
|
|
|
|
|
)
|
2013-07-29 08:10:28 -04:00
|
|
|
]
|
|
|
|
|
settings['PAGINATION_PATTERNS'] = sorted(
|
|
|
|
|
pagination_rules,
|
|
|
|
|
key=lambda r: r[0],
|
|
|
|
|
)
|
|
|
|
|
|
2013-03-23 19:56:45 -07:00
|
|
|
# Save people from accidentally setting a string rather than a list
|
|
|
|
|
path_keys = (
|
2013-08-04 17:02:58 +02:00
|
|
|
'ARTICLE_EXCLUDES',
|
|
|
|
|
'DEFAULT_METADATA',
|
|
|
|
|
'DIRECT_TEMPLATES',
|
2016-10-16 15:47:22 +08:00
|
|
|
'THEME_TEMPLATES_OVERRIDES',
|
2013-08-04 17:02:58 +02:00
|
|
|
'FILES_TO_COPY',
|
|
|
|
|
'IGNORE_FILES',
|
|
|
|
|
'PAGINATED_DIRECT_TEMPLATES',
|
|
|
|
|
'PLUGINS',
|
2014-10-18 13:11:59 -07:00
|
|
|
'STATIC_EXCLUDES',
|
2013-08-04 17:02:58 +02:00
|
|
|
'STATIC_PATHS',
|
|
|
|
|
'THEME_STATIC_PATHS',
|
2014-04-21 11:36:17 +02:00
|
|
|
'ARTICLE_PATHS',
|
|
|
|
|
'PAGE_PATHS',
|
2013-08-04 17:02:58 +02:00
|
|
|
)
|
2013-01-12 19:08:24 +00:00
|
|
|
for PATH_KEY in filter(lambda k: k in settings, path_keys):
|
2014-04-21 11:36:17 +02:00
|
|
|
if isinstance(settings[PATH_KEY], six.string_types):
|
|
|
|
|
logger.warning("Detected misconfiguration with %s setting "
|
2014-07-22 11:48:15 -04:00
|
|
|
"(must be a list), falling back to the default",
|
|
|
|
|
PATH_KEY)
|
2014-04-21 11:36:17 +02:00
|
|
|
settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY]
|
2013-01-12 19:08:24 +00:00
|
|
|
|
2014-05-14 14:30:21 +02:00
|
|
|
# Add {PAGE,ARTICLE}_PATHS to {ARTICLE,PAGE}_EXCLUDES
|
|
|
|
|
mutually_exclusive = ('ARTICLE', 'PAGE')
|
|
|
|
|
for type_1, type_2 in [mutually_exclusive, mutually_exclusive[::-1]]:
|
|
|
|
|
try:
|
|
|
|
|
includes = settings[type_1 + '_PATHS']
|
|
|
|
|
excludes = settings[type_2 + '_EXCLUDES']
|
|
|
|
|
for path in includes:
|
|
|
|
|
if path not in excludes:
|
|
|
|
|
excludes.append(path)
|
|
|
|
|
except KeyError:
|
|
|
|
|
continue # setting not specified, nothing to do
|
2013-01-12 19:08:24 +00:00
|
|
|
|
2012-03-22 07:58:04 -07:00
|
|
|
return settings
|