diff --git a/datasette/app.py b/datasette/app.py index 7bdf076c..8c5480cf 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -46,6 +46,7 @@ from .database import Database, QueryInterrupted from .utils import ( PrefixedUrlString, + SPATIALITE_FUNCTIONS, StartupError, add_cors_headers, async_call_with_supported_arguments, @@ -724,6 +725,17 @@ class Datasette: sqlite_extensions[extension] = None except Exception: pass + # More details on SpatiaLite + if "spatialite" in sqlite_extensions: + spatialite_details = {} + for fn in SPATIALITE_FUNCTIONS: + try: + result = conn.execute("select {}()".format(fn)) + spatialite_details[fn] = result.fetchone()[0] + except Exception as e: + spatialite_details[fn] = {"error": str(e)} + sqlite_extensions["spatialite"] = spatialite_details + # Figure out supported FTS versions fts_versions = [] for fts in ("FTS5", "FTS4", "FTS3"): diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index 610e916f..e17b4d7f 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -52,9 +52,41 @@ SPATIALITE_PATHS = ( "/usr/local/lib/mod_spatialite.dylib", "/usr/local/lib/mod_spatialite.so", ) +# Used to display /-/versions.json SpatiaLite information +SPATIALITE_FUNCTIONS = ( + "spatialite_version", + "spatialite_target_cpu", + "check_strict_sql_quoting", + "freexl_version", + "proj_version", + "geos_version", + "rttopo_version", + "libxml2_version", + "HasIconv", + "HasMathSQL", + "HasGeoCallbacks", + "HasProj", + "HasProj6", + "HasGeos", + "HasGeosAdvanced", + "HasGeosTrunk", + "HasGeosReentrant", + "HasGeosOnlyReentrant", + "HasMiniZip", + "HasRtTopo", + "HasLibXML2", + "HasEpsg", + "HasFreeXL", + "HasGeoPackage", + "HasGCP", + "HasTopology", + "HasKNN", + "HasRouting", +) # Length of hash subset used in hashed URLs: HASH_LENGTH = 7 + # Can replace this with Column from sqlite_utils when I add that dependency Column = namedtuple( "Column", ("cid", "name", "type", "notnull", "default_value", "is_pk", "hidden") diff --git a/tests/test_spatialite.py b/tests/test_spatialite.py new file mode 100644 index 00000000..8b98c5d6 --- /dev/null +++ b/tests/test_spatialite.py @@ -0,0 +1,21 @@ +from datasette.app import Datasette +from datasette.utils import find_spatialite, SpatialiteNotFound, SPATIALITE_FUNCTIONS +import pytest + + +def has_spatialite(): + try: + find_spatialite() + return True + except SpatialiteNotFound: + return False + + +@pytest.mark.asyncio +@pytest.mark.skipif(not has_spatialite(), reason="Requires SpatiaLite") +async def test_spatialite_version_info(): + ds = Datasette(sqlite_extensions=["spatialite"]) + response = await ds.client.get("/-/versions.json") + assert response.status_code == 200 + spatialite = response.json()["sqlite"]["extensions"]["spatialite"] + assert set(SPATIALITE_FUNCTIONS) == set(spatialite)