kopia lustrzana https://github.com/simonw/datasette
New --setting to replace --config, closes #992
rodzic
4bac9f18f9
commit
3159263f05
|
@ -2,6 +2,7 @@ import asyncio
|
|||
import uvicorn
|
||||
import click
|
||||
from click import formatting
|
||||
from click.types import CompositeParamType
|
||||
from click_default_group import DefaultGroup
|
||||
import json
|
||||
import os
|
||||
|
@ -29,6 +30,7 @@ from .version import __version__
|
|||
|
||||
|
||||
class Config(click.ParamType):
|
||||
# This will be removed in Datasette 1.0 in favour of class Setting
|
||||
name = "config"
|
||||
|
||||
def convert(self, config, param, ctx):
|
||||
|
@ -63,6 +65,39 @@ class Config(click.ParamType):
|
|||
self.fail("Invalid option")
|
||||
|
||||
|
||||
class Setting(CompositeParamType):
|
||||
name = "setting"
|
||||
arity = 2
|
||||
|
||||
def convert(self, config, param, ctx):
|
||||
name, value = config
|
||||
if name not in DEFAULT_CONFIG:
|
||||
self.fail(
|
||||
f"{name} is not a valid option (--help-config to see all)",
|
||||
param,
|
||||
ctx,
|
||||
)
|
||||
return
|
||||
# Type checking
|
||||
default = DEFAULT_CONFIG[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")
|
||||
|
||||
|
||||
@click.group(cls=DefaultGroup, default="serve", default_if_no_args=True)
|
||||
@click.version_option(version=__version__)
|
||||
def cli():
|
||||
|
@ -330,7 +365,14 @@ def uninstall(packages, yes):
|
|||
@click.option(
|
||||
"--config",
|
||||
type=Config(),
|
||||
help="Set config option using configname:value docs.datasette.io/en/stable/config.html",
|
||||
help="Deprecated: set config option using configname:value. Use --setting instead.",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option(
|
||||
"--setting",
|
||||
"settings",
|
||||
type=Setting(),
|
||||
help="Setting, see docs.datasette.io/en/stable/config.html",
|
||||
multiple=True,
|
||||
)
|
||||
@click.option(
|
||||
|
@ -372,6 +414,7 @@ def serve(
|
|||
static,
|
||||
memory,
|
||||
config,
|
||||
settings,
|
||||
secret,
|
||||
root,
|
||||
get,
|
||||
|
@ -410,6 +453,15 @@ def serve(
|
|||
if metadata:
|
||||
metadata_data = parse_metadata(metadata.read())
|
||||
|
||||
combined_config = {}
|
||||
if config:
|
||||
click.echo(
|
||||
"--config name:value will be deprecated in Datasette 1.0, use --setting name value instead",
|
||||
err=True,
|
||||
)
|
||||
combined_config.update(config)
|
||||
combined_config.update(settings)
|
||||
|
||||
kwargs = dict(
|
||||
immutables=immutable,
|
||||
cache_headers=not reload,
|
||||
|
@ -420,7 +472,7 @@ def serve(
|
|||
template_dir=template_dir,
|
||||
plugins_dir=plugins_dir,
|
||||
static_mounts=static,
|
||||
config=dict(config),
|
||||
config=combined_config,
|
||||
memory=memory,
|
||||
secret=secret,
|
||||
version_note=version_note,
|
||||
|
|
|
@ -25,9 +25,10 @@ Options:
|
|||
--plugins-dir DIRECTORY Path to directory containing custom plugins
|
||||
--static MOUNT:DIRECTORY Serve static files from this directory at /MOUNT/...
|
||||
--memory Make :memory: database available
|
||||
--config CONFIG Set config option using configname:value
|
||||
docs.datasette.io/en/stable/config.html
|
||||
--config CONFIG Deprecated: set config option using configname:value. Use
|
||||
--setting instead.
|
||||
|
||||
--setting SETTING... Setting, see docs.datasette.io/en/stable/config.html
|
||||
--secret TEXT Secret used for signing secure values, such as signed
|
||||
cookies
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from .fixtures import (
|
|||
TestClient as _TestClient,
|
||||
EXPECTED_PLUGINS,
|
||||
)
|
||||
import asyncio
|
||||
from datasette.plugins import DEFAULT_PLUGINS
|
||||
from datasette.cli import cli, serve
|
||||
from datasette.version import __version__
|
||||
|
@ -17,6 +18,13 @@ import textwrap
|
|||
from unittest import mock
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ensure_eventloop():
|
||||
# Workaround for "Event loop is closed" error
|
||||
if asyncio.get_event_loop().is_closed():
|
||||
asyncio.set_event_loop(asyncio.new_event_loop())
|
||||
|
||||
|
||||
def test_inspect_cli(app_client):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["inspect", "fixtures.db"])
|
||||
|
@ -115,6 +123,7 @@ def test_metadata_yaml():
|
|||
static=[],
|
||||
memory=False,
|
||||
config=[],
|
||||
settings=[],
|
||||
secret=None,
|
||||
root=False,
|
||||
version_note=None,
|
||||
|
@ -163,3 +172,30 @@ def test_version():
|
|||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["--version"])
|
||||
assert result.output == f"cli, version {__version__}\n"
|
||||
|
||||
|
||||
def test_setting(ensure_eventloop):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli, ["--setting", "default_page_size", "5", "--get", "/-/config.json"]
|
||||
)
|
||||
assert result.exit_code == 0, result.output
|
||||
assert json.loads(result.output)["default_page_size"] == 5
|
||||
|
||||
|
||||
def test_setting_type_validation(ensure_eventloop):
|
||||
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
|
||||
|
||||
|
||||
def test_config_deprecated(ensure_eventloop):
|
||||
# The --config option should show a deprecation message
|
||||
runner = CliRunner(mix_stderr=False)
|
||||
result = runner.invoke(
|
||||
cli, ["--config", "allow_download:off", "--get", "/-/config.json"]
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert not json.loads(result.output)["allow_download"]
|
||||
assert "will be deprecated in" in result.stderr
|
||||
|
|
Ładowanie…
Reference in New Issue