mirror of
https://github.com/simonw/datasette.git
synced 2026-05-27 12:34:37 +02:00
From 409 warnings down to 52 warnings.
By closing unclosed database connections. Refs #2614
This commit is contained in:
parent
9c164572d3
commit
f02484c3de
14 changed files with 75 additions and 27 deletions
|
|
@ -1819,6 +1819,7 @@ class Datasette:
|
|||
break
|
||||
except importlib.metadata.PackageNotFoundError:
|
||||
pass
|
||||
conn.close()
|
||||
return info
|
||||
|
||||
def _plugins(self, request=None, all=False):
|
||||
|
|
|
|||
|
|
@ -615,7 +615,9 @@ def serve(
|
|||
for file in file_paths:
|
||||
if not pathlib.Path(file).exists():
|
||||
if create:
|
||||
sqlite3.connect(file).execute("vacuum")
|
||||
conn = sqlite3.connect(file)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
else:
|
||||
raise click.ClickException(
|
||||
"Invalid value for '[FILES]...': Path '{}' does not exist.".format(
|
||||
|
|
|
|||
|
|
@ -681,13 +681,18 @@ def detect_fts_sql(table):
|
|||
|
||||
|
||||
def detect_json1(conn=None):
|
||||
close_conn = False
|
||||
if conn is None:
|
||||
conn = sqlite3.connect(":memory:")
|
||||
close_conn = True
|
||||
try:
|
||||
conn.execute("SELECT json('{}')")
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
finally:
|
||||
if close_conn:
|
||||
conn.close()
|
||||
|
||||
|
||||
def table_columns(conn, table):
|
||||
|
|
|
|||
|
|
@ -20,15 +20,16 @@ def sqlite_version():
|
|||
|
||||
|
||||
def _sqlite_version():
|
||||
return tuple(
|
||||
map(
|
||||
int,
|
||||
sqlite3.connect(":memory:")
|
||||
.execute("select sqlite_version()")
|
||||
.fetchone()[0]
|
||||
.split("."),
|
||||
conn = sqlite3.connect(":memory:")
|
||||
try:
|
||||
return tuple(
|
||||
map(
|
||||
int,
|
||||
conn.execute("select sqlite_version()").fetchone()[0].split("."),
|
||||
)
|
||||
)
|
||||
)
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
|
||||
def supports_table_xinfo():
|
||||
|
|
|
|||
|
|
@ -100,9 +100,10 @@ async def ds_client():
|
|||
|
||||
|
||||
def pytest_report_header(config):
|
||||
return "SQLite: {}".format(
|
||||
sqlite3.connect(":memory:").execute("select sqlite_version()").fetchone()[0]
|
||||
)
|
||||
conn = sqlite3.connect(":memory:")
|
||||
version = conn.execute("select sqlite_version()").fetchone()[0]
|
||||
conn.close()
|
||||
return "SQLite: {}".format(version)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
|
|
|
|||
|
|
@ -187,6 +187,8 @@ def app_client():
|
|||
def app_client_no_files():
|
||||
ds = Datasette([])
|
||||
yield TestClient(ds)
|
||||
for db in ds.databases.values():
|
||||
db.close()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
|
@ -822,6 +824,7 @@ def cli(db_filename, config, metadata, plugins_path, recreate, extra_db_filename
|
|||
for sql, params in TABLE_PARAMETERIZED_SQL:
|
||||
with conn:
|
||||
conn.execute(sql, params)
|
||||
conn.close()
|
||||
print(f"Test tables written to {db_filename}")
|
||||
if metadata:
|
||||
with open(metadata, "w") as fp:
|
||||
|
|
@ -850,6 +853,7 @@ def cli(db_filename, config, metadata, plugins_path, recreate, extra_db_filename
|
|||
pathlib.Path(extra_db_filename).unlink()
|
||||
conn = sqlite3.connect(extra_db_filename)
|
||||
conn.executescript(EXTRA_DATABASE_SQL)
|
||||
conn.close()
|
||||
print(f"Test tables written to {extra_db_filename}")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ def ds_write(tmp_path_factory):
|
|||
db.execute(
|
||||
"create table docs (id integer primary key, title text, score float, age integer)"
|
||||
)
|
||||
db1.close()
|
||||
db2.close()
|
||||
ds = Datasette([db_path], immutables=[db_path_immutable])
|
||||
ds.root_enabled = True
|
||||
yield ds
|
||||
|
|
|
|||
|
|
@ -472,7 +472,9 @@ def test_serve_duplicate_database_names(tmpdir):
|
|||
nested.mkdir()
|
||||
db_2_path = str(tmpdir / "nested" / "db.db")
|
||||
for path in (db_1_path, db_2_path):
|
||||
sqlite3.connect(path).execute("vacuum")
|
||||
conn = sqlite3.connect(path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
result = runner.invoke(cli, [db_1_path, db_2_path, "--get", "/-/databases.json"])
|
||||
assert result.exit_code == 0, result.output
|
||||
databases = json.loads(result.output)
|
||||
|
|
@ -486,7 +488,9 @@ def test_weird_database_names(tmpdir, filename):
|
|||
# https://github.com/simonw/datasette/issues/1181
|
||||
runner = CliRunner()
|
||||
db_path = str(tmpdir / filename)
|
||||
sqlite3.connect(db_path).execute("vacuum")
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
result1 = runner.invoke(cli, [db_path, "--get", "/"])
|
||||
assert result1.exit_code == 0, result1.output
|
||||
filename_no_stem = filename.rsplit(".", 1)[0]
|
||||
|
|
@ -523,7 +527,9 @@ def test_duplicate_database_files_error(tmpdir):
|
|||
"""Test that passing the same database file multiple times raises an error"""
|
||||
runner = CliRunner()
|
||||
db_path = str(tmpdir / "test.db")
|
||||
sqlite3.connect(db_path).execute("vacuum")
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
|
||||
# Test with exact duplicate
|
||||
result = runner.invoke(cli, ["serve", db_path, db_path, "--get", "/"])
|
||||
|
|
@ -542,7 +548,9 @@ def test_duplicate_database_files_error(tmpdir):
|
|||
config_dir = tmpdir / "config"
|
||||
config_dir.mkdir()
|
||||
config_db_path = str(config_dir / "data.db")
|
||||
sqlite3.connect(config_db_path).execute("vacuum")
|
||||
conn = sqlite3.connect(config_db_path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
|
||||
result3 = runner.invoke(
|
||||
cli, ["serve", config_db_path, str(config_dir), "--get", "/"]
|
||||
|
|
@ -553,7 +561,9 @@ def test_duplicate_database_files_error(tmpdir):
|
|||
|
||||
# Test that mixing a file NOT in the directory with a directory works fine
|
||||
other_db_path = str(tmpdir / "other.db")
|
||||
sqlite3.connect(other_db_path).execute("vacuum")
|
||||
conn = sqlite3.connect(other_db_path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
|
||||
result4 = runner.invoke(
|
||||
cli, ["serve", other_db_path, str(config_dir), "--get", "/-/databases.json"]
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ def config_dir(tmp_path_factory):
|
|||
(1, 'San Francisco')
|
||||
;
|
||||
""")
|
||||
db.close()
|
||||
|
||||
# Mark "immutable.db" as immutable
|
||||
(config_dir / "inspect-data.json").write_text(
|
||||
|
|
@ -95,6 +96,8 @@ def test_invalid_settings(config_dir):
|
|||
def config_dir_client(config_dir):
|
||||
ds = Datasette([], config_dir=config_dir)
|
||||
yield _TestClient(ds)
|
||||
for db in ds.databases.values():
|
||||
db.close()
|
||||
|
||||
|
||||
def test_settings(config_dir_client):
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ def test_crossdb_warning_if_too_many_databases(tmp_path_factory):
|
|||
path = str(db_dir / "db_{}.db".format(i))
|
||||
conn = sqlite3.connect(path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
dbs.append(path)
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
|
|
|
|||
|
|
@ -543,7 +543,9 @@ async def test_execute_write_fn_exception(db):
|
|||
@pytest.mark.timeout(1)
|
||||
async def test_execute_write_fn_connection_exception(tmpdir, app_client):
|
||||
path = str(tmpdir / "immutable.db")
|
||||
sqlite3.connect(path).execute("vacuum")
|
||||
conn = sqlite3.connect(path)
|
||||
conn.execute("vacuum")
|
||||
conn.close()
|
||||
db = Database(app_client.ds, path=path, is_mutable=False)
|
||||
app_client.ds.add_database(db, name="immutable-db")
|
||||
|
||||
|
|
@ -747,15 +749,19 @@ async def test_replace_database(tmpdir):
|
|||
path1 = str(tmpdir / "data1.db")
|
||||
(tmpdir / "two").mkdir()
|
||||
path2 = str(tmpdir / "two" / "data1.db")
|
||||
sqlite3.connect(path1).executescript("""
|
||||
conn1 = sqlite3.connect(path1)
|
||||
conn1.executescript("""
|
||||
create table t (id integer primary key);
|
||||
insert into t (id) values (1);
|
||||
insert into t (id) values (2);
|
||||
""")
|
||||
sqlite3.connect(path2).executescript("""
|
||||
conn1.close()
|
||||
conn2 = sqlite3.connect(path2)
|
||||
conn2.executescript("""
|
||||
create table t (id integer primary key);
|
||||
insert into t (id) values (1);
|
||||
""")
|
||||
conn2.close()
|
||||
datasette = Datasette([path1])
|
||||
db = datasette.get_database("data1")
|
||||
count = (await db.execute("select count(*) from t")).first()[0]
|
||||
|
|
|
|||
|
|
@ -422,9 +422,9 @@ def test_plugins_async_template_function(restore_working_directory):
|
|||
.select("pre.extra_from_awaitable_function")[0]
|
||||
.text
|
||||
)
|
||||
expected = (
|
||||
sqlite3.connect(":memory:").execute("select sqlite_version()").fetchone()[0]
|
||||
)
|
||||
conn = sqlite3.connect(":memory:")
|
||||
expected = conn.execute("select sqlite_version()").fetchone()[0]
|
||||
conn.close()
|
||||
assert expected == extra_from_awaitable_function
|
||||
|
||||
|
||||
|
|
@ -466,6 +466,7 @@ def view_names_client(tmp_path_factory):
|
|||
db_path = str(tmpdir / "fixtures.db")
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.executescript(TABLES)
|
||||
conn.close()
|
||||
return _TestClient(
|
||||
Datasette([db_path], template_dir=str(templates), plugins_dir=str(plugins))
|
||||
)
|
||||
|
|
|
|||
|
|
@ -208,6 +208,7 @@ def test_detect_fts(open_quote, close_quote):
|
|||
assert None is utils.detect_fts(conn, "Test_View")
|
||||
assert None is utils.detect_fts(conn, "r")
|
||||
assert "Street_Tree_List_fts" == utils.detect_fts(conn, "Street_Tree_List")
|
||||
conn.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("table", ("regular", "has'single quote"))
|
||||
|
|
@ -222,6 +223,7 @@ def test_detect_fts_different_table_names(table):
|
|||
conn = utils.sqlite3.connect(":memory:")
|
||||
conn.executescript(sql)
|
||||
assert "{table}_fts".format(table=table) == utils.detect_fts(conn, table)
|
||||
conn.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -359,6 +361,7 @@ def test_table_columns():
|
|||
create table places (id integer primary key, name text, bob integer)
|
||||
""")
|
||||
assert ["id", "name", "bob"] == utils.table_columns(conn, "places")
|
||||
conn.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
|
|
@ -433,11 +436,13 @@ def test_check_connection_spatialite_raises():
|
|||
conn = sqlite3.connect(path)
|
||||
with pytest.raises(utils.SpatialiteConnectionProblem):
|
||||
utils.check_connection(conn)
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_check_connection_passes():
|
||||
conn = sqlite3.connect(":memory:")
|
||||
utils.check_connection(conn)
|
||||
conn.close()
|
||||
|
||||
|
||||
def test_call_with_supported_arguments():
|
||||
|
|
@ -564,10 +569,14 @@ def test_display_actor(actor, expected):
|
|||
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)")
|
||||
conn1 = sqlite3.connect(one_table)
|
||||
conn1.execute("create table one (id integer primary key)")
|
||||
conn1.close()
|
||||
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)")
|
||||
conn2 = sqlite3.connect(two_tables)
|
||||
conn2.execute("create table two (id integer primary key)")
|
||||
conn2.execute("create table three (id integer primary key)")
|
||||
conn2.close()
|
||||
datasette = Datasette(
|
||||
[{"one_table": one_table, "two_tables": two_tables}[db] for db in dbs]
|
||||
)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ def inner_html(soup):
|
|||
|
||||
def has_load_extension():
|
||||
conn = sqlite3.connect(":memory:")
|
||||
return hasattr(conn, "enable_load_extension")
|
||||
result = hasattr(conn, "enable_load_extension")
|
||||
conn.close()
|
||||
return result
|
||||
|
||||
|
||||
def cookie_was_deleted(response, cookie):
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue