forked from github/pelican
control slug substitutions from settings with regex
This commit is contained in:
parent
6af825eae6
commit
5199fa51ea
12 changed files with 409 additions and 235 deletions
|
|
@ -6,6 +6,7 @@ import inspect
|
|||
import locale
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
from os.path import isabs
|
||||
from posixpath import join as posix_join
|
||||
|
||||
|
|
@ -145,7 +146,12 @@ DEFAULT_CONFIG = {
|
|||
'TEMPLATE_PAGES': {},
|
||||
'TEMPLATE_EXTENSIONS': ['.html'],
|
||||
'IGNORE_FILES': ['.#*'],
|
||||
'SLUG_SUBSTITUTIONS': (),
|
||||
'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 '-'
|
||||
],
|
||||
'INTRASITE_LINK_REGEX': '[{|](?P<what>.*?)[|}]',
|
||||
'SLUGIFY_SOURCE': 'title',
|
||||
'CACHE_CONTENT': False,
|
||||
|
|
@ -164,79 +170,62 @@ PYGMENTS_RST_OPTIONS = None
|
|||
|
||||
|
||||
def read_settings(path=None, override=None):
|
||||
settings = override or {}
|
||||
|
||||
if path:
|
||||
local_settings = get_settings_from_file(path)
|
||||
# Make the paths relative to the settings file
|
||||
settings = dict(get_settings_from_file(path), **settings)
|
||||
|
||||
if settings:
|
||||
settings = handle_deprecated_settings(settings)
|
||||
|
||||
if path:
|
||||
# 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)))
|
||||
|
||||
for p in ['PATH', 'OUTPUT_PATH', 'THEME', 'CACHE_PATH']:
|
||||
if p in local_settings and local_settings[p] is not None \
|
||||
and not isabs(local_settings[p]):
|
||||
absp = os.path.abspath(os.path.normpath(os.path.join(
|
||||
os.path.dirname(path), local_settings[p])))
|
||||
if settings.get(p) is not None:
|
||||
absp = getabs(settings[p])
|
||||
# THEME may be a name rather than a path
|
||||
if p != 'THEME' or os.path.exists(absp):
|
||||
local_settings[p] = absp
|
||||
settings[p] = absp
|
||||
|
||||
if 'PLUGIN_PATH' in local_settings:
|
||||
logger.warning('PLUGIN_PATH setting has been replaced by '
|
||||
'PLUGIN_PATHS, moving it to the new setting name.')
|
||||
local_settings['PLUGIN_PATHS'] = local_settings['PLUGIN_PATH']
|
||||
del local_settings['PLUGIN_PATH']
|
||||
if 'JINJA_EXTENSIONS' in local_settings:
|
||||
logger.warning('JINJA_EXTENSIONS setting has been deprecated, '
|
||||
'moving it to JINJA_ENVIRONMENT setting.')
|
||||
local_settings['JINJA_ENVIRONMENT']['extensions'] = \
|
||||
local_settings['JINJA_EXTENSIONS']
|
||||
del local_settings['JINJA_EXTENSIONS']
|
||||
if isinstance(local_settings['PLUGIN_PATHS'], six.string_types):
|
||||
logger.warning("Defining PLUGIN_PATHS setting as string "
|
||||
"has been deprecated (should be a list)")
|
||||
local_settings['PLUGIN_PATHS'] = [local_settings['PLUGIN_PATHS']]
|
||||
elif local_settings['PLUGIN_PATHS'] is not None:
|
||||
def getabs(path, pluginpath):
|
||||
if isabs(pluginpath):
|
||||
return pluginpath
|
||||
else:
|
||||
path_dirname = os.path.dirname(path)
|
||||
path_joined = os.path.join(path_dirname, pluginpath)
|
||||
path_normed = os.path.normpath(path_joined)
|
||||
path_absolute = os.path.abspath(path_normed)
|
||||
return path_absolute
|
||||
if settings.get('PLUGIN_PATHS') is not None:
|
||||
settings['PLUGIN_PATHS'] = [getabs(pluginpath)
|
||||
for pluginpath
|
||||
in settings['PLUGIN_PATHS']]
|
||||
|
||||
pluginpath_list = [getabs(path, pluginpath)
|
||||
for pluginpath
|
||||
in local_settings['PLUGIN_PATHS']]
|
||||
local_settings['PLUGIN_PATHS'] = pluginpath_list
|
||||
else:
|
||||
local_settings = copy.deepcopy(DEFAULT_CONFIG)
|
||||
settings = dict(copy.deepcopy(DEFAULT_CONFIG), **settings)
|
||||
settings = configure_settings(settings)
|
||||
|
||||
if override:
|
||||
local_settings.update(override)
|
||||
|
||||
parsed_settings = configure_settings(local_settings)
|
||||
# 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
|
||||
PYGMENTS_RST_OPTIONS = parsed_settings.get('PYGMENTS_RST_OPTIONS', None)
|
||||
return parsed_settings
|
||||
PYGMENTS_RST_OPTIONS = settings.get('PYGMENTS_RST_OPTIONS', None)
|
||||
return settings
|
||||
|
||||
|
||||
def get_settings_from_module(module=None, default_settings=DEFAULT_CONFIG):
|
||||
def get_settings_from_module(module=None):
|
||||
"""Loads settings from a module, returns a dictionary."""
|
||||
|
||||
context = copy.deepcopy(default_settings)
|
||||
context = {}
|
||||
if module is not None:
|
||||
context.update(
|
||||
(k, v) for k, v in inspect.getmembers(module) if k.isupper())
|
||||
return context
|
||||
|
||||
|
||||
def get_settings_from_file(path, default_settings=DEFAULT_CONFIG):
|
||||
def get_settings_from_file(path):
|
||||
"""Loads settings from a file path, returning a dict."""
|
||||
|
||||
name, ext = os.path.splitext(os.path.basename(path))
|
||||
module = load_source(name, path)
|
||||
return get_settings_from_module(module, default_settings=default_settings)
|
||||
return get_settings_from_module(module)
|
||||
|
||||
|
||||
def get_jinja_environment(settings):
|
||||
|
|
@ -253,6 +242,149 @@ def get_jinja_environment(settings):
|
|||
return settings
|
||||
|
||||
|
||||
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)
|
||||
|
||||
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)
|
||||
|
||||
return settings
|
||||
|
||||
|
||||
def configure_settings(settings):
|
||||
"""Provide optimizations, error checking, and warnings for the given
|
||||
settings.
|
||||
|
|
@ -377,31 +509,6 @@ def configure_settings(settings):
|
|||
key=lambda r: r[0],
|
||||
)
|
||||
|
||||
# move {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]
|
||||
|
||||
# Deprecated warning of EXTRA_TEMPLATES_PATHS
|
||||
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']
|
||||
|
||||
# Save people from accidentally setting a string rather than a list
|
||||
path_keys = (
|
||||
'ARTICLE_EXCLUDES',
|
||||
|
|
@ -425,12 +532,6 @@ def configure_settings(settings):
|
|||
PATH_KEY)
|
||||
settings[PATH_KEY] = DEFAULT_CONFIG[PATH_KEY]
|
||||
|
||||
# Deprecated warning of MD_EXTENSIONS
|
||||
if 'MD_EXTENSIONS' in settings:
|
||||
logger.warning('MD_EXTENSIONS is deprecated use MARKDOWN '
|
||||
'instead. Falling back to the default.')
|
||||
settings['MARKDOWN'] = DEFAULT_CONFIG['MARKDOWN']
|
||||
|
||||
# Add {PAGE,ARTICLE}_PATHS to {ARTICLE,PAGE}_EXCLUDES
|
||||
mutually_exclusive = ('ARTICLE', 'PAGE')
|
||||
for type_1, type_2 in [mutually_exclusive, mutually_exclusive[::-1]]:
|
||||
|
|
@ -443,27 +544,4 @@ def configure_settings(settings):
|
|||
except KeyError:
|
||||
continue # setting not specified, nothing to do
|
||||
|
||||
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)
|
||||
|
||||
if 'PAGINATED_DIRECT_TEMPLATES' in settings:
|
||||
message = 'The {} setting has been removed in favor of {}'.format(
|
||||
'PAGINATED_DIRECT_TEMPLATES', 'PAGINATED_TEMPLATES')
|
||||
logger.warning(message)
|
||||
|
||||
for t in settings['PAGINATED_DIRECT_TEMPLATES']:
|
||||
if t not in settings['PAGINATED_TEMPLATES']:
|
||||
settings['PAGINATED_TEMPLATES'][t] = None
|
||||
del settings['PAGINATED_DIRECT_TEMPLATES']
|
||||
|
||||
return settings
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue