From f5dbe61a4568c0915ec6be820095c2960cf0857c Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 25 Oct 2020 22:06:20 -0700 Subject: [PATCH] -o now opens to most relevant page, closes #976 --- datasette/cli.py | 10 ++++++++-- datasette/utils/__init__.py | 15 +++++++++++++++ tests/test_utils.py | 26 ++++++++++++++++++++++++-- 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/datasette/cli.py b/datasette/cli.py index f0752b7c..ece03636 100644 --- a/datasette/cli.py +++ b/datasette/cli.py @@ -17,6 +17,7 @@ from .utils import ( parse_metadata, ConnectionProblem, SpatialiteConnectionProblem, + initial_path_for_datasette, temporary_docker_directory, value_as_boolean, SpatialiteNotFound, @@ -456,14 +457,19 @@ def serve( return # Start the server + url = None if root: url = "http://{}:{}{}?token={}".format( host, port, ds.urls.path("-/auth-token"), ds._root_token ) print(url) - else: - url = "http://{}:{}{}".format(host, port, ds.urls.instance()) if open_browser: + if url is None: + # Figure out most convenient URL - to table, database or homepage + path = asyncio.get_event_loop().run_until_complete( + initial_path_for_datasette(ds) + ) + url = "http://{}:{}{}".format(host, port, path) webbrowser.open(url) uvicorn.run( ds.app(), host=host, port=port, log_level="info", lifespan="on", workers=1 diff --git a/datasette/utils/__init__.py b/datasette/utils/__init__.py index dea50861..f819aa82 100644 --- a/datasette/utils/__init__.py +++ b/datasette/utils/__init__.py @@ -991,3 +991,18 @@ def find_spatialite(): if os.path.exists(path): return path raise SpatialiteNotFound + + +async def initial_path_for_datasette(datasette): + "Return suggested path for opening this Datasette, based on number of DBs and tables" + if len(datasette.databases) == 1: + db_name = next(iter(datasette.databases.keys())) + path = datasette.urls.database(db_name) + # Does this DB only have one table? + db = next(iter(datasette.databases.values())) + tables = await db.table_names() + if len(tables) == 1: + path = datasette.urls.table(db_name, tables[0]) + else: + path = datasette.urls.instance() + return path diff --git a/tests/test_utils.py b/tests/test_utils.py index c244a6f4..0e2af098 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,10 +1,9 @@ """ Tests for various datasette helper functions. """ - +from datasette.app import Datasette from datasette import utils from datasette.utils.asgi import Request -from datasette.filters import Filters import json import os import pathlib @@ -554,3 +553,26 @@ def test_resolve_env_secrets(config, expected): ) def test_display_actor(actor, expected): assert expected == utils.display_actor(actor) + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "dbs,expected_path", + [ + (["one_table"], "/one/one"), + (["two_tables"], "/two"), + (["one_table", "two_tables"], "/"), + ], +) +async def test_initial_path_for_datasette(tmp_path_factory, dbs, expected_path): + db_dir = tmp_path_factory.mktemp("dbs") + one_table = str(db_dir / "one.db") + sqlite3.connect(one_table).execute("create table one (id integer primary key)") + two_tables = str(db_dir / "two.db") + sqlite3.connect(two_tables).execute("create table two (id integer primary key)") + sqlite3.connect(two_tables).execute("create table three (id integer primary key)") + datasette = Datasette( + [{"one_table": one_table, "two_tables": two_tables}[db] for db in dbs] + ) + path = await utils.initial_path_for_datasette(datasette) + assert path == expected_path