Added plugin_config() method

pull/363/head
Simon Willison 2018-08-28 01:35:21 -07:00
rodzic 1905c03364
commit 0a14a4846b
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 17E2DEA2588B7F52
6 zmienionych plików z 114 dodań i 6 usunięć

Wyświetl plik

@ -170,7 +170,7 @@ class Datasette:
def metadata(self, key=None, database=None, table=None, fallback=True):
"""
Looks up metadata, cascading backwards from specified level.
Returns None if metadata value is not foundself.
Returns None if metadata value is not found.
"""
assert not (database is None and table is not None), \
"Cannot call metadata() with table= specified but not database="
@ -199,6 +199,17 @@ class Datasette:
m.update(item)
return m
def plugin_config(
self, plugin_name, database=None, table=None, fallback=True
):
"Return config for plugin, falling back from specified database/table"
plugins = self.metadata(
"plugins", database=database, table=table, fallback=fallback
)
if plugins is None:
return None
return plugins.get(plugin_name)
def app_css_hash(self):
if not hasattr(self, "_app_css_hash"):
self._app_css_hash = hashlib.sha1(

Wyświetl plik

@ -1,8 +1,8 @@
from pluggy import HookimplMarker
from pluggy import HookspecMarker
hookspec = HookspecMarker('datasette')
hookimpl = HookimplMarker('datasette')
hookspec = HookspecMarker("datasette")
hookimpl = HookimplMarker("datasette")
@hookspec

Wyświetl plik

@ -149,6 +149,71 @@ The priority order for template loading is:
See :ref:`customization` for more details on how to write custom templates,
including which filenames to use to customize which parts of the Datasette UI.
Plugin configuration
--------------------
Plugins can have their own configuration, embedded in a :ref:`metadata` file. Configuration options for plugins live within a ``"plugins"`` key in that file, which can be included at the root, database or table level.
Here is an example of some plugin configuration for a specific table::
{
"databases: {
"sf-trees": {
"tables": {
"Street_Tree_List": {
"plugins": {
"datasette-cluster-map": {
"latitude_column": "lat",
"longitude_column": "lng"
}
}
}
}
}
}
}
This tells the ``datasette-cluster-map`` column which latitude and longitude columns should be used for a table called ``Street_Tree_List`` inside a database file called ``sf-trees.db``.
When you are writing plugins, you can access plugin configuration like this using the ``datasette.plugin_config()`` method. If you know you need plugin configuration for a specific table, you can access it like this::
plugin_config = datasette.plugin_config(
"datasette-cluster-map", database="sf-trees", table="Street_Tree_List"
)
This will return the ``{"latitude_column": "lat", "longitude_column": "lng"}`` in the above example.
If it cannot find the requested configuration at the table layer, it will fall back to the database layer and then the root layer. For example, a user may have set the plugin configuration option like so::
{
"databases: {
"sf-trees": {
"plugins": {
"datasette-cluster-map": {
"latitude_column": "xlat",
"longitude_column": "xlng"
}
}
}
}
}
In this case, the above code would return that configuration for ANY table within the ``sf-trees`` database.
The plugin configuration could also be set at the top level of ``metadata.json``::
{
"title": "This is the top-level title in metadata.json",
"plugins": {
"datasette-cluster-map": {
"latitude_column": "xlat",
"longitude_column": "xlng"
}
}
}
Now that ``datasette-cluster-map`` plugin configuration will apply to every table in every database.
Plugin hooks
------------

Wyświetl plik

@ -129,9 +129,19 @@ METADATA = {
'license_url': 'https://github.com/simonw/datasette/blob/master/LICENSE',
'source': 'tests/fixtures.py',
'source_url': 'https://github.com/simonw/datasette/blob/master/tests/fixtures.py',
"plugins": {
"name-of-plugin": {
"depth": "root"
}
},
'databases': {
'fixtures': {
'description': 'Test tables description',
"plugins": {
"name-of-plugin": {
"depth": "database"
}
},
'tables': {
'simple_primary_key': {
'description_html': 'Simple <em>primary</em> key',
@ -143,7 +153,12 @@ METADATA = {
'sortable_with_nulls',
'sortable_with_nulls_2',
'text',
]
],
"plugins": {
"name-of-plugin": {
"depth": "table"
}
}
},
'no_primary_key': {
'sortable_columns': [],

Wyświetl plik

@ -14,8 +14,8 @@ label_re = re.compile(r'\.\. _([^\s:]+):')
def get_headings(filename, underline="-"):
content = (docs_path / filename).open().read()
heading_re = re.compile(r'(\S+)\n\{}+\n'.format(underline))
return set(heading_re.findall(content))
heading_re = re.compile(r'(\w+)(\([^)]*\))?\n\{}+\n'.format(underline))
return set(h[0] for h in heading_re.findall(content))
def get_labels(filename):

Wyświetl plik

@ -85,3 +85,20 @@ def test_plugins_render_cell(app_client):
assert a is not None, str(a)
assert a.attrs["href"] == "http://example.com/"
assert a.text == "Example"
def test_plugin_config(app_client):
assert {"depth": "table"} == app_client.ds.plugin_config(
"name-of-plugin", database="fixtures", table="sortable"
)
assert {"depth": "database"} == app_client.ds.plugin_config(
"name-of-plugin", database="fixtures", table="unknown_table"
)
assert {"depth": "database"} == app_client.ds.plugin_config(
"name-of-plugin", database="fixtures"
)
assert {"depth": "root"} == app_client.ds.plugin_config(
"name-of-plugin", database="unknown_database"
)
assert {"depth": "root"} == app_client.ds.plugin_config("name-of-plugin")
assert None is app_client.ds.plugin_config("unknown-plugin")