1
0
Fork 0
forked from github/pelican

Override settings from the command line

Add a --setting-overrides KEY=VAL command line option to override
default settings or those defined in settings files. This adds
flexibility in running Pelican and helps reduce sprawl of settings
files. Cast int and str setting overrides to their respective types.
Support other setting types by treating them as JSON. Fall back to JSON
when an override typecast errors. This should make it possible to set
int values to None, resp. to JSON 'none'
This commit is contained in:
Peter Sabaini 2020-05-09 18:15:16 +02:00 committed by Justin Mayer
commit 1c50a18d0a
3 changed files with 64 additions and 3 deletions

View file

@ -23,7 +23,7 @@ from pelican.plugins import signals
from pelican.plugins._utils import load_plugins
from pelican.readers import Readers
from pelican.server import ComplexHTTPRequestHandler, RootedHTTPServer
from pelican.settings import read_settings
from pelican.settings import coerce_overrides, read_settings
from pelican.utils import (FileSystemWatcher, clean_output_dir, maybe_pluralize)
from pelican.writers import Writer
@ -230,6 +230,18 @@ class PrintSettings(argparse.Action):
parser.exit()
class ParseDict(argparse.Action):
def __call__(self, parser, namespace, values, option_string=None):
d = {}
if values:
for item in values:
split_items = item.split("=", 1)
key = split_items[0].strip()
value = split_items[1].strip()
d[key] = value
setattr(namespace, self.dest, d)
def parse_arguments(argv=None):
parser = argparse.ArgumentParser(
description='A tool to generate a static blog, '
@ -323,6 +335,18 @@ def parse_arguments(argv=None):
help='IP to bind to when serving files via HTTP '
'(default: 127.0.0.1)')
parser.add_argument('-c', '--setting-overrides', dest='overrides',
help='Specify one ore more SETTING=VALUE pairs '
'(without spaces around =) to override '
'settings files. If VALUE contains spaces, add quotes: '
'SETTING="VALUE". '
'Integers and strings are autoconverted, other values '
'can be passed in in json notation, '
'e.g. SETTING=none',
nargs='*',
action=ParseDict
)
args = parser.parse_args(argv)
if args.port is not None and not args.listen:
@ -358,6 +382,7 @@ def get_config(args):
if args.bind is not None:
config['BIND'] = args.bind
config['DEBUG'] = args.verbosity == logging.DEBUG
config.update(coerce_overrides(args.overrides))
return config

View file

@ -1,6 +1,7 @@
import copy
import importlib.util
import inspect
import json
import locale
import logging
import os
@ -658,3 +659,23 @@ def configure_settings(settings):
continue # setting not specified, nothing to do
return settings
def coerce_overrides(overrides):
coerced = {}
types_to_cast = {int, str}
for k, v in overrides.items():
if k not in overrides:
logger.warning('Override for unknown setting %s, ignoring', k)
continue
setting_type = type(DEFAULT_CONFIG[k])
if setting_type not in types_to_cast:
coerced[k] = json.loads(v)
else:
try:
coerced[k] = setting_type(v)
except ValueError:
logger.debug('ValueError for %s override with %s, try to '
'load as json', k, v)
coerced[k] = json.loads(v)
return coerced

View file

@ -7,8 +7,8 @@ from sys import platform
from pelican.settings import (DEFAULT_CONFIG, DEFAULT_THEME,
_printf_s_to_format_field,
configure_settings, handle_deprecated_settings,
read_settings)
coerce_overrides, configure_settings,
handle_deprecated_settings, read_settings)
from pelican.tests.support import unittest
@ -304,3 +304,18 @@ class TestSettingsConfiguration(unittest.TestCase):
[(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)