Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ship a non-alpha release after Datasette 1.0 stable #5

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 53 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,36 @@ 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
```

## 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 +50,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.2"


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