mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
This change updates the `-s/--setting` option to `datasette serve` to allow it to be used to set arbitrarily complex nested settings in a way that is compatible with the new `-c datasette.yml` work happening in: - #2143 It will enable things like this: ``` datasette data.db --setting plugins.datasette-ripgrep.path "/home/simon/code" ``` For the moment though it just affects [settings](https://docs.datasette.io/en/1.0a4/settings.html) - so you can do this: ``` datasette data.db --setting settings.sql_time_limit_ms 3500 ``` I've also implemented a backwards compatibility mechanism, so if you use it this way (the old way): ``` datasette data.db --setting sql_time_limit_ms 3500 ``` It will notice that the setting you passed is one of Datasette's core settings, and will treat that as if you said `settings.sql_time_limit_ms` instead.
This commit is contained in:
parent
527cec66b0
commit
d9aad1fd04
3 changed files with 46 additions and 47 deletions
|
|
@ -31,6 +31,7 @@ from .utils import (
|
|||
ConnectionProblem,
|
||||
SpatialiteConnectionProblem,
|
||||
initial_path_for_datasette,
|
||||
pairs_to_nested_config,
|
||||
temporary_docker_directory,
|
||||
value_as_boolean,
|
||||
SpatialiteNotFound,
|
||||
|
|
@ -56,35 +57,27 @@ class Setting(CompositeParamType):
|
|||
|
||||
def convert(self, config, param, ctx):
|
||||
name, value = config
|
||||
if name not in DEFAULT_SETTINGS:
|
||||
msg = (
|
||||
OBSOLETE_SETTINGS.get(name)
|
||||
or f"{name} is not a valid option (--help-settings to see all)"
|
||||
)
|
||||
self.fail(
|
||||
msg,
|
||||
param,
|
||||
ctx,
|
||||
)
|
||||
return
|
||||
# Type checking
|
||||
default = DEFAULT_SETTINGS[name]
|
||||
if isinstance(default, bool):
|
||||
try:
|
||||
return name, value_as_boolean(value)
|
||||
except ValueAsBooleanError:
|
||||
self.fail(f'"{name}" should be on/off/true/false/1/0', param, ctx)
|
||||
return
|
||||
elif isinstance(default, int):
|
||||
if not value.isdigit():
|
||||
self.fail(f'"{name}" should be an integer', param, ctx)
|
||||
return
|
||||
return name, int(value)
|
||||
elif isinstance(default, str):
|
||||
return name, value
|
||||
else:
|
||||
# Should never happen:
|
||||
self.fail("Invalid option")
|
||||
if name in DEFAULT_SETTINGS:
|
||||
# For backwards compatibility with how this worked prior to
|
||||
# Datasette 1.0, we turn bare setting names into setting.name
|
||||
# Type checking for those older settings
|
||||
default = DEFAULT_SETTINGS[name]
|
||||
name = "settings.{}".format(name)
|
||||
if isinstance(default, bool):
|
||||
try:
|
||||
return name, "true" if value_as_boolean(value) else "false"
|
||||
except ValueAsBooleanError:
|
||||
self.fail(f'"{name}" should be on/off/true/false/1/0', param, ctx)
|
||||
elif isinstance(default, int):
|
||||
if not value.isdigit():
|
||||
self.fail(f'"{name}" should be an integer', param, ctx)
|
||||
return name, value
|
||||
elif isinstance(default, str):
|
||||
return name, value
|
||||
else:
|
||||
# Should never happen:
|
||||
self.fail("Invalid option")
|
||||
return name, value
|
||||
|
||||
|
||||
def sqlite_extensions(fn):
|
||||
|
|
@ -425,7 +418,7 @@ def uninstall(packages, yes):
|
|||
"--setting",
|
||||
"settings",
|
||||
type=Setting(),
|
||||
help="Setting, see docs.datasette.io/en/stable/settings.html",
|
||||
help="nested.key, value setting to use in Datasette configuration",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option(
|
||||
|
|
@ -547,6 +540,13 @@ def serve(
|
|||
if config:
|
||||
config_data = parse_metadata(config.read())
|
||||
|
||||
config_data = config_data or {}
|
||||
|
||||
# Merge in settings from -s/--setting
|
||||
if settings:
|
||||
settings_updates = pairs_to_nested_config(settings)
|
||||
config_data.update(settings_updates)
|
||||
|
||||
kwargs = dict(
|
||||
immutables=immutable,
|
||||
cache_headers=not reload,
|
||||
|
|
@ -558,7 +558,7 @@ def serve(
|
|||
template_dir=template_dir,
|
||||
plugins_dir=plugins_dir,
|
||||
static_mounts=static,
|
||||
settings=dict(settings),
|
||||
settings=None, # These are passed in config= now
|
||||
memory=memory,
|
||||
secret=secret,
|
||||
version_note=version_note,
|
||||
|
|
|
|||
|
|
@ -113,8 +113,8 @@ Once started you can access it at ``http://localhost:8001``
|
|||
/MOUNT/...
|
||||
--memory Make /_memory database available
|
||||
-c, --config FILENAME Path to JSON/YAML Datasette configuration file
|
||||
--setting SETTING... Setting, see
|
||||
docs.datasette.io/en/stable/settings.html
|
||||
-s, --setting SETTING... nested.key, value setting to use in Datasette
|
||||
configuration
|
||||
--secret TEXT Secret used for signing secure values, such as
|
||||
signed cookies
|
||||
--root Output URL that sets a cookie authenticating
|
||||
|
|
|
|||
|
|
@ -220,20 +220,27 @@ def test_serve_invalid_ports(invalid_port):
|
|||
assert "Invalid value for '-p'" in result.stderr
|
||||
|
||||
|
||||
def test_setting():
|
||||
@pytest.mark.parametrize(
|
||||
"args",
|
||||
(
|
||||
["--setting", "default_page_size", "5"],
|
||||
["--setting", "settings.default_page_size", "5"],
|
||||
["-s", "settings.default_page_size", "5"],
|
||||
),
|
||||
)
|
||||
def test_setting(args):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli, ["--setting", "default_page_size", "5", "--get", "/-/settings.json"]
|
||||
)
|
||||
result = runner.invoke(cli, ["--get", "/-/settings.json"] + args)
|
||||
assert result.exit_code == 0, result.output
|
||||
assert json.loads(result.output)["default_page_size"] == 5
|
||||
settings = json.loads(result.output)
|
||||
assert settings["default_page_size"] == 5
|
||||
|
||||
|
||||
def test_setting_type_validation():
|
||||
runner = CliRunner(mix_stderr=False)
|
||||
result = runner.invoke(cli, ["--setting", "default_page_size", "dog"])
|
||||
assert result.exit_code == 2
|
||||
assert '"default_page_size" should be an integer' in result.stderr
|
||||
assert '"settings.default_page_size" should be an integer' in result.stderr
|
||||
|
||||
|
||||
@pytest.mark.parametrize("default_allow_sql", (True, False))
|
||||
|
|
@ -360,11 +367,3 @@ def test_help_settings():
|
|||
result = runner.invoke(cli, ["--help-settings"])
|
||||
for setting in SETTINGS:
|
||||
assert setting.name in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize("setting", ("hash_urls", "default_cache_ttl_hashed"))
|
||||
def test_help_error_on_hash_urls_setting(setting):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["--setting", setting, 1])
|
||||
assert result.exit_code == 2
|
||||
assert "The hash_urls setting has been removed" in result.output
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue