kopia lustrzana https://github.com/simonw/datasette
Treat plugins in metadata as if they were in config, closes #2248
rodzic
d4bc2b2dfc
commit
be4f02335f
|
@ -74,6 +74,7 @@ from .utils import (
|
||||||
find_spatialite,
|
find_spatialite,
|
||||||
format_bytes,
|
format_bytes,
|
||||||
module_from_path,
|
module_from_path,
|
||||||
|
move_plugins,
|
||||||
parse_metadata,
|
parse_metadata,
|
||||||
resolve_env_secrets,
|
resolve_env_secrets,
|
||||||
resolve_routes,
|
resolve_routes,
|
||||||
|
@ -341,6 +342,11 @@ class Datasette:
|
||||||
with config_files[0].open() as fp:
|
with config_files[0].open() as fp:
|
||||||
config = parse_metadata(fp.read())
|
config = parse_metadata(fp.read())
|
||||||
|
|
||||||
|
# Move any "plugins" settings from metadata to config - updates them in place
|
||||||
|
metadata = metadata or {}
|
||||||
|
config = config or {}
|
||||||
|
move_plugins(metadata, config)
|
||||||
|
|
||||||
self._metadata_local = metadata or {}
|
self._metadata_local = metadata or {}
|
||||||
self.sqlite_extensions = []
|
self.sqlite_extensions = []
|
||||||
for extension in sqlite_extensions or []:
|
for extension in sqlite_extensions or []:
|
||||||
|
|
|
@ -1287,3 +1287,43 @@ def make_slot_function(name, datasette, request, **kwargs):
|
||||||
return markupsafe.Markup("".join(html_bits))
|
return markupsafe.Markup("".join(html_bits))
|
||||||
|
|
||||||
return inner
|
return inner
|
||||||
|
|
||||||
|
|
||||||
|
def move_plugins(source, destination):
|
||||||
|
"""
|
||||||
|
Move 'plugins' keys from source to destination dictionary. Creates hierarchy in destination if needed.
|
||||||
|
After moving, recursively remove any keys in the source that are left empty.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def recursive_move(src, dest, path=None):
|
||||||
|
if path is None:
|
||||||
|
path = []
|
||||||
|
for key, value in list(src.items()):
|
||||||
|
new_path = path + [key]
|
||||||
|
if key == "plugins":
|
||||||
|
# Navigate and create the hierarchy in destination if needed
|
||||||
|
d = dest
|
||||||
|
for step in path:
|
||||||
|
d = d.setdefault(step, {})
|
||||||
|
# Move the plugins
|
||||||
|
d[key] = value
|
||||||
|
# Remove the plugins from source
|
||||||
|
src.pop(key, None)
|
||||||
|
elif isinstance(value, dict):
|
||||||
|
recursive_move(value, dest, new_path)
|
||||||
|
# After moving, check if the current dictionary is empty and remove it if so
|
||||||
|
if not value:
|
||||||
|
src.pop(key, None)
|
||||||
|
|
||||||
|
def prune_empty_dicts(d):
|
||||||
|
"""
|
||||||
|
Recursively prune all empty dictionaries from a given dictionary.
|
||||||
|
"""
|
||||||
|
for key, value in list(d.items()):
|
||||||
|
if isinstance(value, dict):
|
||||||
|
prune_empty_dicts(value)
|
||||||
|
if value == {}:
|
||||||
|
d.pop(key, None)
|
||||||
|
|
||||||
|
recursive_move(source, destination)
|
||||||
|
prune_empty_dicts(source)
|
||||||
|
|
|
@ -1458,3 +1458,54 @@ async def test_hook_register_events():
|
||||||
datasette = Datasette(memory=True)
|
datasette = Datasette(memory=True)
|
||||||
await datasette.invoke_startup()
|
await datasette.invoke_startup()
|
||||||
assert any(k.__name__ == "OneEvent" for k in datasette.event_classes)
|
assert any(k.__name__ == "OneEvent" for k in datasette.event_classes)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"metadata,config,expected_metadata,expected_config",
|
||||||
|
(
|
||||||
|
(
|
||||||
|
# Instance level
|
||||||
|
{"plugins": {"datasette-foo": "bar"}},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{"plugins": {"datasette-foo": "bar"}},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Database level
|
||||||
|
{"databases": {"foo": {"plugins": {"datasette-foo": "bar"}}}},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{"databases": {"foo": {"plugins": {"datasette-foo": "bar"}}}},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Table level
|
||||||
|
{
|
||||||
|
"databases": {
|
||||||
|
"foo": {"tables": {"bar": {"plugins": {"datasette-foo": "bar"}}}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
"databases": {
|
||||||
|
"foo": {"tables": {"bar": {"plugins": {"datasette-foo": "bar"}}}}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
# Keep other keys
|
||||||
|
{"plugins": {"datasette-foo": "bar"}, "other": "key"},
|
||||||
|
{"original_config": "original"},
|
||||||
|
{"other": "key"},
|
||||||
|
{"original_config": "original", "plugins": {"datasette-foo": "bar"}},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
def test_metadata_plugin_config_treated_as_config(
|
||||||
|
metadata, config, expected_metadata, expected_config
|
||||||
|
):
|
||||||
|
ds = Datasette(metadata=metadata, config=config)
|
||||||
|
actual_metadata = ds.metadata()
|
||||||
|
assert "plugins" not in actual_metadata
|
||||||
|
assert actual_metadata == expected_metadata
|
||||||
|
assert ds.config == expected_config
|
||||||
|
|
Ładowanie…
Reference in New Issue