diff --git a/datasette/app.py b/datasette/app.py index 70704eeb..d4aa7d55 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -549,6 +549,19 @@ class Datasette: for unit in self.metadata("custom_units") or []: ureg.define(unit) + def connected_databases(self): + return [ + { + "name": d.name, + "path": d.path, + "size": d.size, + "is_mutable": d.is_mutable, + "is_memory": d.is_memory, + "hash": d.hash, + } + for d in self.databases.values() + ] + def versions(self): conn = sqlite3.connect(":memory:") self.prepare_connection(conn) @@ -810,6 +823,10 @@ class Datasette: JsonDataView.as_view(self, "config.json", lambda: self._config), r"/-/config", ) + app.add_route( + JsonDataView.as_view(self, "databases.json", self.connected_databases), + r"/-/databases", + ) app.add_route( DatabaseDownload.as_view(self), r"/" ) diff --git a/docs/introspection.rst b/docs/introspection.rst index 9162ac34..e514ddf5 100644 --- a/docs/introspection.rst +++ b/docs/introspection.rst @@ -89,3 +89,19 @@ Shows the :ref:`config` options for this instance of Datasette. `Config example "max_returned_rows": 1000, "sql_time_limit_ms": 1000 } + +/-/databases +------------ + +Shows currently attached databases. `Databases example `_:: + + [ + { + "hash": null, + "is_memory": false, + "is_mutable": true, + "name": "fixtures", + "path": "fixtures.db", + "size": 225280 + } + ] diff --git a/tests/fixtures.py b/tests/fixtures.py index d85aef95..4667ba89 100644 --- a/tests/fixtures.py +++ b/tests/fixtures.py @@ -100,6 +100,13 @@ def app_client_two_attached_databases(): ) +@pytest.fixture(scope="session") +def app_client_two_attached_databases_one_immutable(): + yield from make_app_client( + is_immutable=True, extra_databases={"extra_database.db": EXTRA_DATABASE_SQL} + ) + + @pytest.fixture(scope="session") def app_client_with_memory(): yield from make_app_client(memory=True) diff --git a/tests/test_api.py b/tests/test_api.py index f7ce4bb9..693fe0a1 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -6,6 +6,7 @@ from .fixtures import ( # noqa app_client_shorter_time_limit, app_client_larger_cache_size, app_client_returned_rows_matches_page_size, + app_client_two_attached_databases_one_immutable, app_client_with_cors, app_client_with_dot, generate_compound_rows, @@ -1058,6 +1059,22 @@ def test_unit_filters(app_client): assert data["rows"][0][0] == 2 +def test_databases_json(app_client_two_attached_databases_one_immutable): + response = app_client_two_attached_databases_one_immutable.get("/-/databases.json") + databases = response.json + assert 2 == len(databases) + extra_database, fixtures_database = databases + assert "extra_database" == extra_database["name"] + assert None == extra_database["hash"] + assert True == extra_database["is_mutable"] + assert False == extra_database["is_memory"] + + assert "fixtures" == fixtures_database["name"] + assert fixtures_database["hash"] is not None + assert False == fixtures_database["is_mutable"] + assert False == fixtures_database["is_memory"] + + def test_metadata_json(app_client): response = app_client.get("/-/metadata.json") assert METADATA == response.json