Skip to content

Commit

Permalink
Release 0.2a0, compatible with Datasette 1.0a14
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Aug 5, 2024
1 parent 25c3c3b commit 9d1d38e
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 49 deletions.
95 changes: 54 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,37 @@ Periodically refresh Datasette metadata from a remote URL

Install this plugin in the same environment as Datasette.

$ datasette install datasette-remote-metadata
```bash
datasette install datasette-remote-metadata
```
The alpha version of this plugin requires [Datasette 1.0a14](https://docs.datasette.io/en/1.0a14/changelog.html#a14-2024-08-05) or higher.

## Usage

Add the following to your `metadata.json`:
Add the following to your `datasette.yml`:

```json
{
"plugins": {
"datasette-remote-metadata": {
"url": "https://example.com/remote-metadata.yml"
}
}
}
```yaml
plugins:
datasette-remote-metadata:
url: "https://example.com/remote-metadata.yml"
```
Then start Datasette like this:
```bash
datasette mydatabase.db -c datasette.yml
```

The plugin will fetch the specified metadata from that URL at startup and combine it with any existing metadata. You can use a URL to either a JSON file or a YAML file.

It will periodically refresh that metadata - by default every 30 seconds, unless you specify an alternative `"ttl"` value in the plugin configuration.

You can also use the `datasette -s` option to configure the plugin without a configuration file:
```bash
datasette \
-s plugins.datasette-remote-metadata.url 'https://example.com/remote-metadata.yml' \
-s plugins.datasette-remote-metadata.ttl 2 \
mydatabase.db
```
## Configuration

Available configuration options are as follows:
Expand All @@ -39,49 +51,50 @@ Available configuration options are as follows:
- `"headers"` - a dictionary of additional request headers to send.
- `"cachebust"` - if true, a random `?0.29508` value will be added to the query string of the remote metadata to bust any intermediary caches.

This example `metadata.json` configuration refreshes every 10 seconds, uses cache busting and sends an `Authorization: Bearer xyz` header with the request:
This example `datasette.yml` configuration refreshes every 10 seconds, uses cache busting and sends an `Authorization: Bearer xyz` header with the request:

```json
{
"plugins": {
"datasette-remote-metadata": {
"url": "https://example.com/remote-metadata.yml",
"ttl": 10,
"cachebust": true,
"headers": {
"Authorization": "Bearer xyz"
}
}
}
}
```
This example if you are using `metadata.yaml` for configuration:
```yaml
plugins:
datasette-remote-metadata:
url: https://example.com/remote-metadata.yml
url: "https://example.com/remote-metadata.yml"
ttl: 10
cachebust: true
headers:
Authorization: Bearer xyz
Authorization: "Bearer xyz"
```
This example if you are using `datasette.json` for configuration:
```json
{
"plugins": {
"datasette-remote-metadata": {
"url": "https://example.com/remote-metadata.yml",
"ttl": 10,
"cachebust": true,
"headers": {
"Authorization": "Bearer xyz"
}
}
}
}
```

## Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:
cd datasette-remote-metadata
python3 -mvenv venv
source venv/bin/activate
```bash
cd datasette-remote-metadata
python3 -mvenv venv
source venv/bin/activate
```
Or if you are using `pipenv`:

pipenv shell

```bash
pipenv shell
```
Now install the dependencies and test dependencies:

pip install -e '.[test]'

```bash
pip install -e '.[test]'
```
To run the tests:

pytest
```bash
pytest
```
36 changes: 30 additions & 6 deletions datasette_remote_metadata/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def update_remote():
)
response.raise_for_status()
metadata = parse_metadata(response.content)
datasette._remote_metadata = metadata
await apply_metadata(datasette, metadata)
datasette._remote_metadata_last_updated = time.monotonic()

if timelimit is not None:
Expand All @@ -45,16 +45,12 @@ async def update_remote():
@hookimpl
def startup(datasette):
async def inner():
await datasette.refresh_schemas()
await update_remote_with_time_limit(datasette)

return inner


@hookimpl
def get_metadata(datasette):
return getattr(datasette, "_remote_metadata", None) or {}


@hookimpl
def asgi_wrapper(datasette):
# Refresh stale (over X seconds old) remote metadata on every request
Expand All @@ -72,3 +68,31 @@ async def add_refresh(scope, recieve, send):
return add_refresh

return wrap_with_refresh


# Imitating https://github.com/simonw/datasette/blob/f6bd2bf8/datasette/app.py#L446-L472
async def apply_metadata(datasette, metadata_dict):
for key in metadata_dict or {}:
if key == "databases":
continue
await datasette.set_instance_metadata(key, metadata_dict[key])

# database-level
for dbname, db in metadata_dict.get("databases", {}).items():
for key, value in db.items():
if key == "tables":
continue
await datasette.set_database_metadata(dbname, key, value)

# table-level
for tablename, table in db.get("tables", {}).items():
for key, value in table.items():
if key == "columns":
continue
await datasette.set_resource_metadata(dbname, tablename, key, value)

# column-level
for columnname, column_description in table.get("columns", {}).items():
await datasette.set_column_metadata(
dbname, tablename, columnname, "description", column_description
)
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from setuptools import setup
import os

VERSION = "0.1"
VERSION = "0.2a0"


def get_long_description():
Expand All @@ -28,7 +28,7 @@ def get_long_description():
version=VERSION,
packages=["datasette_remote_metadata"],
entry_points={"datasette": ["remote_metadata = datasette_remote_metadata"]},
install_requires=["datasette"],
install_requires=["datasette>=1.0a14"],
extras_require={"test": ["pytest", "pytest-asyncio", "pytest-httpx"]},
tests_require=["datasette-remote-metadata[test]"],
python_requires=">=3.6",
Expand Down
1 change: 1 addition & 0 deletions tests/test_remote_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ async def test_remote_metadata(httpx_mock):
memory=True,
metadata={"plugins": {"datasette-remote-metadata": {"url": TEST_URL}}},
)
await datasette.invoke_startup()
response = await datasette.client.get("/")
assert response.status_code == 200
assert ">This is the remote metadata title<" in response.text
Expand Down

0 comments on commit 9d1d38e

Please sign in to comment.