diff --git a/tests/test_analyze.py b/tests/test_analyze.py index a4cd8a2..edd5174 100644 --- a/tests/test_analyze.py +++ b/tests/test_analyze.py @@ -3,11 +3,13 @@ import pytest @pytest.fixture def db(fresh_db): - fresh_db["one_index"].insert({"id": 1, "name": "Cleo"}, pk="id") - fresh_db["one_index"].create_index(["name"]) - fresh_db["two_indexes"].insert({"id": 1, "name": "Cleo", "species": "dog"}, pk="id") - fresh_db["two_indexes"].create_index(["name"]) - fresh_db["two_indexes"].create_index(["species"]) + fresh_db.table("one_index").insert({"id": 1, "name": "Cleo"}, pk="id") + fresh_db.table("one_index").create_index(["name"]) + fresh_db.table("two_indexes").insert( + {"id": 1, "name": "Cleo", "species": "dog"}, pk="id" + ) + fresh_db.table("two_indexes").create_index(["name"]) + fresh_db.table("two_indexes").create_index(["species"]) return fresh_db @@ -17,7 +19,7 @@ def test_analyze_whole_database(db): assert set(db.table_names()).issuperset( {"one_index", "two_indexes", "sqlite_stat1"} ) - assert list(db["sqlite_stat1"].rows) == [ + assert list(db.table("sqlite_stat1").rows) == [ {"tbl": "two_indexes", "idx": "idx_two_indexes_species", "stat": "1 1"}, {"tbl": "two_indexes", "idx": "idx_two_indexes_name", "stat": "1 1"}, {"tbl": "one_index", "idx": "idx_one_index_name", "stat": "1 1"}, @@ -30,12 +32,12 @@ def test_analyze_one_table(db, method): if method == "db_method_with_name": db.analyze("one_index") elif method == "table_method": - db["one_index"].analyze() + db.table("one_index").analyze() assert set(db.table_names()).issuperset( {"one_index", "two_indexes", "sqlite_stat1"} ) - assert list(db["sqlite_stat1"].rows) == [ + assert list(db.table("sqlite_stat1").rows) == [ {"tbl": "one_index", "idx": "idx_one_index_name", "stat": "1 1"} ] @@ -46,6 +48,6 @@ def test_analyze_index_by_name(db): assert set(db.table_names()).issuperset( {"one_index", "two_indexes", "sqlite_stat1"} ) - assert list(db["sqlite_stat1"].rows) == [ + assert list(db.table("sqlite_stat1").rows) == [ {"tbl": "two_indexes", "idx": "idx_two_indexes_species", "stat": "1 1"}, ] diff --git a/tests/test_analyze_tables.py b/tests/test_analyze_tables.py index a51bba6..9e4799c 100644 --- a/tests/test_analyze_tables.py +++ b/tests/test_analyze_tables.py @@ -9,7 +9,7 @@ from sqlite_utils.db import ColumnDetails, Database @pytest.fixture def db_to_analyze(fresh_db): - stuff = fresh_db["stuff"] + stuff = fresh_db.table("stuff") stuff.insert_all( [ {"id": 1, "owner": "Terryterryterry", "size": 5}, @@ -45,7 +45,7 @@ def big_db_to_analyze_path(tmpdir): "all_null": None, } ) - db["stuff"].insert_all(to_insert) + db.table("stuff").insert_all(to_insert) return path @@ -126,7 +126,7 @@ def big_db_to_analyze_path(tmpdir): ) def test_analyze_column(db_to_analyze, column, extra_kwargs, expected): assert ( - db_to_analyze["stuff"].analyze_column( + db_to_analyze.table("stuff").analyze_column( column, common_limit=2, value_truncate=5, **extra_kwargs ) == expected @@ -186,7 +186,7 @@ def test_analyze_table_save(db_to_analyze_path): cli.cli, ["analyze-tables", db_to_analyze_path, "--save"] ) assert result.exit_code == 0 - rows = list(Database(db_to_analyze_path)["_analyze_tables_"].rows) + rows = list(Database(db_to_analyze_path).table("_analyze_tables_").rows) assert rows == [ { "table": "stuff", @@ -248,7 +248,7 @@ def test_analyze_table_save_no_most_no_least_options( args.append("--no-least") result = CliRunner().invoke(cli.cli, args) assert result.exit_code == 0 - rows = list(Database(big_db_to_analyze_path)["_analyze_tables_"].rows) + rows = list(Database(big_db_to_analyze_path).table("_analyze_tables_").rows) expected = { "table": "stuff", "column": "category", @@ -297,13 +297,13 @@ def test_analyze_table_column_all_nulls(big_db_to_analyze_path): def test_analyze_table_validate_columns(tmpdir, args, expected_error): path = str(tmpdir / "test_validate_columns.db") db = Database(path) - db["one"].insert( + db.table("one").insert( { "id": 1, "name": "one", } ) - db["two"].insert( + db.table("two").insert( { "id": 1, "age": 5, diff --git a/tests/test_atomic.py b/tests/test_atomic.py index ba16ca5..89a318a 100644 --- a/tests/test_atomic.py +++ b/tests/test_atomic.py @@ -45,30 +45,30 @@ def test_iter_complete_sql_statements(sql, expected): def test_atomic_commits(fresh_db): with fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 1, "name": "Cleo"}, pk="id") + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id") - assert list(fresh_db["dogs"].rows) == [{"id": 1, "name": "Cleo"}] + assert list(fresh_db.table("dogs").rows) == [{"id": 1, "name": "Cleo"}] def test_atomic_rolls_back(fresh_db): with pytest.raises(RuntimeError), fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 1, "name": "Cleo"}, pk="id") + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id") raise RuntimeError("boom") - assert not fresh_db["dogs"].exists() + assert not fresh_db.table("dogs").exists() def test_nested_atomic_rolls_back_to_savepoint(fresh_db): - fresh_db["dogs"].create({"id": int, "name": str}, pk="id") + fresh_db.table("dogs").create({"id": int, "name": str}, pk="id") with fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 1, "name": "Cleo"}) + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo"}) with pytest.raises(RuntimeError), fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 2, "name": "Pancakes"}) + fresh_db.table("dogs").insert({"id": 2, "name": "Pancakes"}) raise RuntimeError("boom") - fresh_db["dogs"].insert({"id": 3, "name": "Marnie"}) + fresh_db.table("dogs").insert({"id": 3, "name": "Marnie"}) - assert list(fresh_db["dogs"].rows) == [ + assert list(fresh_db.table("dogs").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 3, "name": "Marnie"}, ] @@ -76,12 +76,12 @@ def test_nested_atomic_rolls_back_to_savepoint(fresh_db): def test_outer_atomic_rolls_back_released_savepoint(fresh_db): with pytest.raises(RuntimeError), fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 1, "name": "Cleo"}, pk="id") + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id") with fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 2, "name": "Pancakes"}) + fresh_db.table("dogs").insert({"id": 2, "name": "Pancakes"}) raise RuntimeError("boom") - assert not fresh_db["dogs"].exists() + assert not fresh_db.table("dogs").exists() def test_executescript_does_not_commit_open_atomic_block(fresh_db): @@ -97,41 +97,41 @@ def test_executescript_does_not_commit_open_atomic_block(fresh_db): """) raise RuntimeError("boom") - assert not fresh_db["dogs"].exists() + assert not fresh_db.table("dogs").exists() def test_transform_does_not_commit_open_atomic_block(fresh_db): - fresh_db["dogs"].insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") with pytest.raises(RuntimeError), fresh_db.atomic(): - fresh_db["dogs"].insert({"id": 2, "name": "Pancakes", "age": "6"}) - fresh_db["dogs"].transform(rename={"age": "dog_age"}) + fresh_db.table("dogs").insert({"id": 2, "name": "Pancakes", "age": "6"}) + fresh_db.table("dogs").transform(rename={"age": "dog_age"}) raise RuntimeError("boom") assert ( - fresh_db["dogs"].schema + fresh_db.table("dogs").schema == 'CREATE TABLE "dogs" (\n "id" INTEGER PRIMARY KEY,\n "name" TEXT,\n "age" TEXT\n)' ) - assert list(fresh_db["dogs"].rows) == [ + assert list(fresh_db.table("dogs").rows) == [ {"id": 1, "name": "Cleo", "age": "5"}, ] def test_transform_parent_table_with_foreign_keys_in_atomic(fresh_db): fresh_db.conn.execute("PRAGMA foreign_keys=ON") - fresh_db["authors"].insert({"id": 1, "name": "Tina"}, pk="id") - fresh_db["books"].insert( + fresh_db.table("authors").insert({"id": 1, "name": "Tina"}, pk="id") + fresh_db.table("books").insert( {"id": 1, "title": "Book", "author_id": 1}, pk="id", foreign_keys={"author_id"}, ) with fresh_db.atomic(): - fresh_db["authors"].transform(rename={"name": "full_name"}) + fresh_db.table("authors").transform(rename={"name": "full_name"}) assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] assert ( - fresh_db["authors"].schema + fresh_db.table("authors").schema == 'CREATE TABLE "authors" (\n "id" INTEGER PRIMARY KEY,\n "full_name" TEXT\n)' ) assert fresh_db.execute("PRAGMA foreign_key_check").fetchall() == [] @@ -139,19 +139,19 @@ def test_transform_parent_table_with_foreign_keys_in_atomic(fresh_db): def test_transform_parent_table_with_foreign_keys_rolls_back(fresh_db): fresh_db.conn.execute("PRAGMA foreign_keys=ON") - fresh_db["authors"].insert({"id": 1, "name": "Tina"}, pk="id") - fresh_db["books"].insert( + fresh_db.table("authors").insert({"id": 1, "name": "Tina"}, pk="id") + fresh_db.table("books").insert( {"id": 1, "title": "Book", "author_id": 1}, pk="id", foreign_keys={"author_id"}, ) with pytest.raises(RuntimeError), fresh_db.atomic(): - fresh_db["authors"].transform(rename={"name": "full_name"}) + fresh_db.table("authors").transform(rename={"name": "full_name"}) raise RuntimeError("boom") assert ( - fresh_db["authors"].schema + fresh_db.table("authors").schema == 'CREATE TABLE "authors" (\n "id" INTEGER PRIMARY KEY,\n "name" TEXT\n)' ) assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] @@ -160,49 +160,51 @@ def test_transform_parent_table_with_foreign_keys_rolls_back(fresh_db): def test_transform_detects_foreign_key_check_violations(fresh_db): fresh_db.conn.execute("PRAGMA foreign_keys=ON") - fresh_db["authors"].insert({"id": 1, "name": "Tina"}, pk="id") - fresh_db["books"].insert({"id": 1, "author_id": 2}, pk="id") + fresh_db.table("authors").insert({"id": 1, "name": "Tina"}, pk="id") + fresh_db.table("books").insert({"id": 1, "author_id": 2}, pk="id") with pytest.raises(sqlite3.IntegrityError): - fresh_db["books"].transform(add_foreign_keys=(("author_id", "authors", "id"),)) + fresh_db.table("books").transform( + add_foreign_keys=(("author_id", "authors", "id"),) + ) - assert fresh_db["books"].foreign_keys == [] + assert fresh_db.table("books").foreign_keys == [] assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] def test_atomic_inside_manual_transaction_uses_savepoint(fresh_db): - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") fresh_db.execute("begin") with fresh_db.atomic(): - fresh_db["t"].insert({"id": 2}, pk="id") + fresh_db.table("t").insert({"id": 2}, pk="id") # Nothing is committed until the user's own transaction commits assert fresh_db.conn.in_transaction fresh_db.rollback() - assert [r["id"] for r in fresh_db["t"].rows] == [1] + assert [r["id"] for r in fresh_db.table("t").rows] == [1] # And with a commit instead, the atomic block's writes persist fresh_db.execute("begin") with fresh_db.atomic(): - fresh_db["t"].insert({"id": 3}, pk="id") + fresh_db.table("t").insert({"id": 3}, pk="id") fresh_db.commit() - assert [r["id"] for r in fresh_db["t"].rows] == [1, 3] + assert [r["id"] for r in fresh_db.table("t").rows] == [1, 3] def test_begin_commit_rollback(tmpdir): path = str(tmpdir / "test.db") db = Database(path) - db["t"].insert({"id": 1}, pk="id") + db.table("t").insert({"id": 1}, pk="id") db.begin() - db["t"].insert({"id": 2}, pk="id") + db.table("t").insert({"id": 2}, pk="id") assert db.conn.in_transaction db.rollback() assert not db.conn.in_transaction - assert [r["id"] for r in db["t"].rows] == [1] + assert [r["id"] for r in db.table("t").rows] == [1] db.begin() - db["t"].insert({"id": 3}, pk="id") + db.table("t").insert({"id": 3}, pk="id") db.commit() db.close() db2 = Database(path) - assert [r["id"] for r in db2["t"].rows] == [1, 3] + assert [r["id"] for r in db2.table("t").rows] == [1, 3] db2.close() @@ -222,7 +224,7 @@ def test_commit_and_rollback_without_transaction_are_noops(fresh_db): def test_execute_write_commits_immediately(tmpdir): path = str(tmpdir / "test.db") db = Database(path) - db["t"].insert({"id": 1}, pk="id") + db.table("t").insert({"id": 1}, pk="id") db.execute("insert into t (id) values (2)") # No implicit transaction is left open assert not db.conn.in_transaction @@ -234,24 +236,24 @@ def test_execute_write_commits_immediately(tmpdir): def test_execute_write_respects_explicit_transaction(fresh_db): - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") fresh_db.begin() fresh_db.execute("insert into t (id) values (2)") # Still inside the explicit transaction - not committed assert fresh_db.conn.in_transaction fresh_db.rollback() - assert [r["id"] for r in fresh_db["t"].rows] == [1] + assert [r["id"] for r in fresh_db.table("t").rows] == [1] def test_execute_comment_prefixed_begin_leaves_transaction_open(fresh_db): # A BEGIN hidden behind a leading comment must not be auto-committed # out from under the caller - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") fresh_db.execute("-- start a transaction\nbegin") assert fresh_db.conn.in_transaction fresh_db.execute("insert into t (id) values (2)") fresh_db.rollback() - assert [r["id"] for r in fresh_db["t"].rows] == [1] + assert [r["id"] for r in fresh_db.table("t").rows] == [1] def _sqlite_accepts_bom(): @@ -269,12 +271,12 @@ def test_execute_prefixed_begin_leaves_transaction_open(fresh_db, begin_sql): # out from under the caller if begin_sql.startswith("\ufeff") and not _sqlite_accepts_bom(): pytest.skip("This SQLite version rejects a leading byte order mark") - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") fresh_db.execute(begin_sql) assert fresh_db.conn.in_transaction fresh_db.execute("insert into t (id) values (2)") fresh_db.rollback() - assert [r["id"] for r in fresh_db["t"].rows] == [1] + assert [r["id"] for r in fresh_db.table("t").rows] == [1] def test_execute_failed_write_rolls_back_implicit_transaction(tmpdir): @@ -282,40 +284,40 @@ def test_execute_failed_write_rolls_back_implicit_transaction(tmpdir): # that would silently disable auto-commit for every subsequent write path = str(tmpdir / "test.db") db = Database(path) - db["t"].insert({"id": 1}, pk="id") + db.table("t").insert({"id": 1}, pk="id") with pytest.raises(sqlite3.IntegrityError): db.execute("insert into t (id) values (1)") assert not db.conn.in_transaction # Subsequent writes commit as normal and survive closing the connection - db["other"].insert({"id": 2}) + db.table("other").insert({"id": 2}) db.close() db2 = Database(path) - assert db2["other"].exists() + assert db2.table("other").exists() db2.close() def test_execute_failed_write_preserves_explicit_transaction(fresh_db): # A failed write inside an explicit transaction must not roll back # the caller's earlier work - only the caller decides that - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") fresh_db.begin() fresh_db.execute("insert into t (id) values (2)") with pytest.raises(sqlite3.IntegrityError): fresh_db.execute("insert into t (id) values (1)") assert fresh_db.conn.in_transaction fresh_db.commit() - assert [r["id"] for r in fresh_db["t"].rows] == [1, 2] + assert [r["id"] for r in fresh_db.table("t").rows] == [1, 2] def test_execute_failed_write_inside_atomic_preserves_block(fresh_db): # A caught failure inside an atomic() block must leave the block's # transaction open so its other work still commits - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") with fresh_db.atomic(): fresh_db.execute("insert into t (id) values (2)") with pytest.raises(sqlite3.IntegrityError): fresh_db.execute("insert into t (id) values (1)") - assert [r["id"] for r in fresh_db["t"].rows] == [1, 2] + assert [r["id"] for r in fresh_db.table("t").rows] == [1, 2] def test_query_returning_commits_after_iteration(tmpdir): @@ -325,7 +327,7 @@ def test_query_returning_commits_after_iteration(tmpdir): _pytest.skip("RETURNING requires SQLite 3.35.0 or higher") path = str(tmpdir / "test.db") db = Database(path) - db["t"].insert({"id": 1}, pk="id") + db.table("t").insert({"id": 1}, pk="id") rows = list(db.query("insert into t (id) values (2) returning id")) assert rows == [{"id": 2}] assert not db.conn.in_transaction @@ -375,7 +377,7 @@ def test_nested_atomic_preserves_error_from_transaction_destroying_trigger( def test_atomic_preserves_error_from_insert_or_rollback(fresh_db): - fresh_db["t"].insert({"id": 1}, pk="id") + fresh_db.table("t").insert({"id": 1}, pk="id") with pytest.raises(sqlite3.IntegrityError), fresh_db.atomic(): fresh_db.execute("insert or rollback into t (id) values (1)") assert not fresh_db.conn.in_transaction diff --git a/tests/test_attach.py b/tests/test_attach.py index b594b3b..2b11e36 100644 --- a/tests/test_attach.py +++ b/tests/test_attach.py @@ -6,10 +6,10 @@ def test_attach(tmpdir): bar_path = str(tmpdir / "bar.db") db = Database(foo_path) with db.conn: - db["foo"].insert({"id": 1, "text": "foo"}) + db.table("foo").insert({"id": 1, "text": "foo"}) db2 = Database(bar_path) with db2.conn: - db2["bar"].insert({"id": 1, "text": "bar"}) + db2.table("bar").insert({"id": 1, "text": "bar"}) db.attach("bar", bar_path) assert db.execute( "select * from foo union all select * from bar.bar" diff --git a/tests/test_cli.py b/tests/test_cli.py index d3ad228..012900c 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -72,13 +72,13 @@ def test_views(db_path): def test_tables_fts4(db_path): - Database(db_path)["Gosh"].enable_fts(["c2"], fts_version="FTS4") + Database(db_path).table("Gosh").enable_fts(["c2"], fts_version="FTS4") result = CliRunner().invoke(cli.cli, ["tables", "--fts4", db_path]) assert '[{"table": "Gosh_fts"}]' == result.output.strip() def test_tables_fts5(db_path): - Database(db_path)["Gosh"].enable_fts(["c2"], fts_version="FTS5") + Database(db_path).table("Gosh").enable_fts(["c2"], fts_version="FTS5") result = CliRunner().invoke(cli.cli, ["tables", "--fts5", db_path]) assert '[{"table": "Gosh_fts"}]' == result.output.strip() @@ -86,7 +86,7 @@ def test_tables_fts5(db_path): def test_tables_counts_and_columns(db_path): db = Database(db_path) with db.conn: - db["lots"].insert_all([{"id": i, "age": i + 1} for i in range(30)]) + db.table("lots").insert_all([{"id": i, "age": i + 1} for i in range(30)]) result = CliRunner().invoke(cli.cli, ["tables", "--counts", "--columns", db_path]) assert ( '[{"table": "Gosh", "count": 0, "columns": ["c1", "c2", "c3"]},\n' @@ -121,7 +121,7 @@ def test_tables_counts_and_columns(db_path): def test_tables_counts_and_columns_csv(db_path, format, expected): db = Database(db_path) with db.conn: - db["lots"].insert_all([{"id": i, "age": i + 1} for i in range(30)]) + db.table("lots").insert_all([{"id": i, "age": i + 1} for i in range(30)]) result = CliRunner().invoke( cli.cli, ["tables", "--counts", "--columns", format, db_path] ) @@ -131,7 +131,7 @@ def test_tables_counts_and_columns_csv(db_path, format, expected): def test_tables_schema(db_path): db = Database(db_path) with db.conn: - db["lots"].insert_all([{"id": i, "age": i + 1} for i in range(30)]) + db.table("lots").insert_all([{"id": i, "age": i + 1} for i in range(30)]) result = CliRunner().invoke(cli.cli, ["tables", "--schema", db_path]) assert ( '[{"table": "Gosh", "schema": "CREATE TABLE Gosh (c1 text, c2 text, c3 text)"},\n' @@ -183,7 +183,7 @@ def test_tables_schema(db_path): def test_output_table(db_path, options, expected): db = Database(db_path) with db.conn: - db["rows"].insert_all( + db.table("rows").insert_all( [ { "c1": f"verb{i}", @@ -207,7 +207,7 @@ def test_output_table_no_headers(db_path, fmt_option): # tabulate formats and the column names were always printed. db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "name": "Cleo", "age": 4}, {"id": 2, "name": "Pancakes", "age": 2}, @@ -244,14 +244,14 @@ def test_output_table_no_headers(db_path, fmt_option): def test_create_index(db_path): db = Database(db_path) - assert [] == db["Gosh"].indexes + assert [] == db.table("Gosh").indexes result = CliRunner().invoke(cli.cli, ["create-index", db_path, "Gosh", "c1"]) assert result.exit_code == 0 assert [ Index( seq=0, name="idx_Gosh_c1", unique=0, origin="c", partial=0, columns=["c1"] ) - ] == db["Gosh"].indexes + ] == db.table("Gosh").indexes # Try with a custom name result = CliRunner().invoke( cli.cli, ["create-index", db_path, "Gosh", "c2", "--name", "blah"] @@ -262,7 +262,7 @@ def test_create_index(db_path): Index( seq=1, name="idx_Gosh_c1", unique=0, origin="c", partial=0, columns=["c1"] ), - ] == db["Gosh"].indexes + ] == db.table("Gosh").indexes # Try a two-column unique index create_index_unique_args = [ "create-index", @@ -283,7 +283,7 @@ def test_create_index(db_path): partial=0, columns=["c1", "c2"], ) - ] == db["Gosh2"].indexes + ] == db.table("Gosh2").indexes # Trying to create the same index should fail assert CliRunner().invoke(cli.cli, create_index_unique_args).exit_code != 0 # ... unless we use --if-not-exists or --ignore @@ -296,11 +296,11 @@ def test_create_index(db_path): def test_drop_index(db_path): db = Database(db_path) - db["Gosh"].create_index(["c1"]) - assert [index.name for index in db["Gosh"].indexes] == ["idx_Gosh_c1"] + db.table("Gosh").create_index(["c1"]) + assert [index.name for index in db.table("Gosh").indexes] == ["idx_Gosh_c1"] result = CliRunner().invoke(cli.cli, ["drop-index", db_path, "Gosh", "idx_Gosh_c1"]) assert result.exit_code == 0 - assert db["Gosh"].indexes == [] + assert db.table("Gosh").indexes == [] result = CliRunner().invoke(cli.cli, ["drop-index", db_path, "Gosh", "idx_Gosh_c1"]) assert result.exit_code == 1 @@ -315,7 +315,7 @@ def test_drop_index(db_path): def test_create_index_analyze(db_path): db = Database(db_path) assert "sqlite_stat1" not in db.table_names() - assert [] == db["Gosh"].indexes + assert [] == db.table("Gosh").indexes result = CliRunner().invoke( cli.cli, ["create-index", db_path, "Gosh", "c1", "--analyze"] ) @@ -325,7 +325,7 @@ def test_create_index_analyze(db_path): def test_create_index_desc(db_path): db = Database(db_path) - assert [] == db["Gosh"].indexes + assert [] == db.table("Gosh").indexes result = CliRunner().invoke(cli.cli, ["create-index", db_path, "Gosh", "--", "-c1"]) assert result.exit_code == 0 assert ( @@ -361,12 +361,12 @@ def test_create_index_desc(db_path): def test_add_column(db_path, col_name, col_type, expected_schema): db = Database(db_path) db.create_table("dogs", {"name": str}) - assert db["dogs"].schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' + assert db.table("dogs").schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' args = ["add-column", db_path, "dogs", col_name] if col_type is not None: args.append(col_type) assert CliRunner().invoke(cli.cli, args).exit_code == 0 - assert db["dogs"].schema == expected_schema + assert db.table("dogs").schema == expected_schema @pytest.mark.parametrize("ignore", (True, False)) @@ -385,7 +385,7 @@ def test_add_column_ignore(db_path, ignore): def test_add_column_not_null_default(db_path): db = Database(db_path) db.create_table("dogs", {"name": str}) - assert db["dogs"].schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' + assert db.table("dogs").schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' args = [ "add-column", db_path, @@ -395,7 +395,7 @@ def test_add_column_not_null_default(db_path): "dogs'dawg", ] assert CliRunner().invoke(cli.cli, args).exit_code == 0 - assert db["dogs"].schema == ( + assert db.table("dogs").schema == ( 'CREATE TABLE "dogs" (\n' ' "name" TEXT\n' ", \"nickname\" TEXT NOT NULL DEFAULT 'dogs''dawg')" @@ -415,10 +415,10 @@ def test_add_column_not_null_default(db_path): ) def test_add_foreign_key(db_path, args, assert_message): db = Database(db_path) - db["authors"].insert_all( + db.table("authors").insert_all( [{"id": 1, "name": "Sally"}, {"id": 2, "name": "Asheesh"}], pk="id" ) - db["books"].insert_all( + db.table("books").insert_all( [ {"title": "Hedgehogs of the world", "author_id": 1}, {"title": "How to train your wolf", "author_id": 2}, @@ -431,7 +431,7 @@ def test_add_foreign_key(db_path, args, assert_message): ForeignKey( table="books", column="author_id", other_table="authors", other_column="id" ) - ] == db["books"].foreign_keys + ] == db.table("books").foreign_keys # Error if we try to add it twice: result = CliRunner().invoke( @@ -460,14 +460,14 @@ def test_add_foreign_key(db_path, args, assert_message): def test_add_column_foreign_key(db_path): db = Database(db_path) - db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - db["books"].insert({"title": "Hedgehogs of the world"}) + db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + db.table("books").insert({"title": "Hedgehogs of the world"}) # Add an author_id foreign key column to the books table result = CliRunner().invoke( cli.cli, ["add-column", db_path, "books", "author_id", "--fk", "authors"] ) assert result.exit_code == 0, result.output - assert db["books"].schema == ( + assert db.table("books").schema == ( 'CREATE TABLE "books" (\n' ' "title" TEXT,\n' ' "author_id" INTEGER REFERENCES "authors"("id")\n' @@ -488,7 +488,7 @@ def test_add_column_foreign_key(db_path): ], ) assert result.exit_code == 0, result.output - assert db["books"].schema == ( + assert db.table("books").schema == ( 'CREATE TABLE "books" (\n' ' "title" TEXT,\n' ' "author_id" INTEGER REFERENCES "authors"("id"),\n' @@ -505,7 +505,7 @@ def test_add_column_foreign_key(db_path): def test_suggest_alter_if_column_missing(db_path): db = Database(db_path) - db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") + db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") result = CliRunner().invoke( cli.cli, ["insert", db_path, "authors", "-"], @@ -521,27 +521,27 @@ def test_suggest_alter_if_column_missing(db_path): def test_index_foreign_keys(db_path): test_add_column_foreign_key(db_path) db = Database(db_path) - assert [] == db["books"].indexes + assert [] == db.table("books").indexes result = CliRunner().invoke(cli.cli, ["index-foreign-keys", db_path]) assert result.exit_code == 0 assert [["author_id"], ["author_name_ref"]] == [ - i.columns for i in db["books"].indexes + i.columns for i in db.table("books").indexes ] def test_enable_fts(db_path): db = Database(db_path) - assert db["Gosh"].detect_fts() is None + assert db.table("Gosh").detect_fts() is None result = CliRunner().invoke( cli.cli, ["enable-fts", db_path, "Gosh", "c1", "--fts4"] ) assert result.exit_code == 0 - assert "Gosh_fts" == db["Gosh"].detect_fts() + assert "Gosh_fts" == db.table("Gosh").detect_fts() # Table names with restricted chars are handled correctly. # colons and dots are restricted characters for table names. - db["http://example.com"].create({"c1": str, "c2": str, "c3": str}) - assert db["http://example.com"].detect_fts() is None + db.table("http://example.com").create({"c1": str, "c2": str, "c3": str}) + assert db.table("http://example.com").detect_fts() is None result = CliRunner().invoke( cli.cli, [ @@ -555,7 +555,7 @@ def test_enable_fts(db_path): ], ) assert result.exit_code == 0 - assert "http://example.com_fts" == db["http://example.com"].detect_fts() + assert "http://example.com_fts" == db.table("http://example.com").detect_fts() # Check tokenize was set to porter assert ( 'CREATE VIRTUAL TABLE "http://example.com_fts" USING FTS4 (\n' @@ -563,19 +563,19 @@ def test_enable_fts(db_path): " tokenize='porter',\n" ' content="http://example.com"' "\n)" - ) == db["http://example.com_fts"].schema - db["http://example.com"].drop() + ) == db.table("http://example.com_fts").schema + db.table("http://example.com").drop() def test_enable_fts_replace(db_path): db = Database(db_path) - assert db["Gosh"].detect_fts() is None + assert db.table("Gosh").detect_fts() is None result = CliRunner().invoke( cli.cli, ["enable-fts", db_path, "Gosh", "c1", "--fts4"] ) assert result.exit_code == 0 - assert "Gosh_fts" == db["Gosh"].detect_fts() - assert db["Gosh_fts"].columns_dict == {"c1": str} + assert "Gosh_fts" == db.table("Gosh").detect_fts() + assert db.table("Gosh_fts").columns_dict == {"c1": str} # This should throw an error result2 = CliRunner().invoke( @@ -589,11 +589,11 @@ def test_enable_fts_replace(db_path): cli.cli, ["enable-fts", db_path, "Gosh", "c2", "--fts4", "--replace"] ) assert result3.exit_code == 0 - assert db["Gosh_fts"].columns_dict == {"c2": str} + assert db.table("Gosh_fts").columns_dict == {"c2": str} def test_enable_fts_with_triggers(db_path): - Database(db_path)["Gosh"].insert_all([{"c1": "baz"}]) + Database(db_path).table("Gosh").insert_all([{"c1": "baz"}]) exit_code = ( CliRunner() .invoke( @@ -612,12 +612,12 @@ def test_enable_fts_with_triggers(db_path): ) assert [("baz",)] == search("baz") - Database(db_path)["Gosh"].insert_all([{"c1": "martha"}]) + Database(db_path).table("Gosh").insert_all([{"c1": "martha"}]) assert [("martha",)] == search("martha") def test_populate_fts(db_path): - Database(db_path)["Gosh"].insert_all([{"c1": "baz"}]) + Database(db_path).table("Gosh").insert_all([{"c1": "baz"}]) exit_code = ( CliRunner() .invoke(cli.cli, ["enable-fts", db_path, "Gosh", "c1", "--fts4"]) @@ -633,7 +633,7 @@ def test_populate_fts(db_path): ) assert [("baz",)] == search("baz") - Database(db_path)["Gosh"].insert_all([{"c1": "martha"}]) + Database(db_path).table("Gosh").insert_all([{"c1": "martha"}]) assert [] == search("martha") exit_code = ( CliRunner().invoke(cli.cli, ["populate-fts", db_path, "Gosh", "c1"]).exit_code @@ -645,7 +645,7 @@ def test_populate_fts(db_path): def test_disable_fts(db_path): db = Database(db_path) assert {"Gosh", "Gosh2"} == set(db.table_names()) - db["Gosh"].enable_fts(["c1"], create_triggers=True) + db.table("Gosh").enable_fts(["c1"], create_triggers=True) assert { "Gosh_fts", "Gosh_fts_idx", @@ -677,7 +677,7 @@ def test_optimize(db_path, tables): db = Database(db_path) with db.conn: for table in ("Gosh", "Gosh2"): - db[table].insert_all( + db.table(table).insert_all( [ { "c1": f"verb{i}", @@ -687,8 +687,8 @@ def test_optimize(db_path, tables): for i in range(10000) ] ) - db["Gosh"].enable_fts(["c1", "c2", "c3"], fts_version="FTS4") - db["Gosh2"].enable_fts(["c1", "c2", "c3"], fts_version="FTS5") + db.table("Gosh").enable_fts(["c1", "c2", "c3"], fts_version="FTS4") + db.table("Gosh2").enable_fts(["c1", "c2", "c3"], fts_version="FTS5") size_before_optimize = os.stat(db_path).st_size result = CliRunner().invoke(cli.cli, ["optimize", db_path] + tables) assert result.exit_code == 0 @@ -713,22 +713,22 @@ def test_rebuild_fts_fixes_docsize_error(db_path): for i in range(10000) ] with db.conn: - db["fts5_table"].insert_all(records, pk="c1") - db["fts5_table"].enable_fts( + db.table("fts5_table").insert_all(records, pk="c1") + db.table("fts5_table").enable_fts( ["c1", "c2", "c3"], fts_version="FTS5", create_triggers=True ) # Search should work - assert list(db["fts5_table"].search("verb1")) + assert list(db.table("fts5_table").search("verb1")) # Replicate docsize error from this issue for FTS5 # https://github.com/simonw/sqlite-utils/issues/149 - assert db["fts5_table_fts_docsize"].count == 10000 - db["fts5_table"].insert_all(records, replace=True) - assert db["fts5_table"].count == 10000 - assert db["fts5_table_fts_docsize"].count == 20000 + assert db.table("fts5_table_fts_docsize").count == 10000 + db.table("fts5_table").insert_all(records, replace=True) + assert db.table("fts5_table").count == 10000 + assert db.table("fts5_table_fts_docsize").count == 20000 # Running rebuild-fts should fix this result = CliRunner().invoke(cli.cli, ["rebuild-fts", db_path, "fts5_table"]) assert result.exit_code == 0 - assert db["fts5_table_fts_docsize"].count == 10000 + assert db.table("fts5_table_fts_docsize").count == 10000 @pytest.mark.parametrize( @@ -741,7 +741,7 @@ def test_rebuild_fts_fixes_docsize_error(db_path): def test_query_csv(db_path, format, expected): db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "age": 4, "name": "Cleo"}, {"id": 2, "age": 2, "name": "Pancakes"}, @@ -793,7 +793,7 @@ _one_query = "select id, name, age from dogs where id = 1" def test_query_json(db_path, sql, args, expected): db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "age": 4, "name": "Cleo"}, {"id": 2, "age": 2, "name": "Pancakes"}, @@ -807,7 +807,7 @@ def test_query_sql_from_stdin(db_path): # https://github.com/simonw/sqlite-utils/issues/765 db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "age": 4, "name": "Cleo"}, {"id": 2, "age": 2, "name": "Pancakes"}, @@ -1004,7 +1004,7 @@ LOREM_IPSUM_COMPRESSED = ( def test_query_json_binary(db_path): db = Database(db_path) with db.conn: - db["files"].insert( + db.table("files").insert( { "name": "lorem.txt", "sz": 16984, @@ -1059,7 +1059,7 @@ def test_query_params(db_path, sql, params, expected): def test_query_json_with_json_cols(db_path): db = Database(db_path) with db.conn: - db["dogs"].insert( + db.table("dogs").insert( { "id": 1, "name": "Cleo", @@ -1088,7 +1088,7 @@ def test_query_json_with_json_cols(db_path): def test_query_json_unicode_not_escaped_by_default(db_path): db = Database(db_path) with db.conn: - db["text"].insert({"id": 1, "text": "Japanese 日本語"}, pk="id") + db.table("text").insert({"id": 1, "text": "Japanese 日本語"}, pk="id") result = CliRunner().invoke(cli.cli, [db_path, "select id, text from text"]) assert result.exit_code == 0 assert result.output.strip() == '[{"id": 1, "text": "Japanese 日本語"}]' @@ -1102,7 +1102,7 @@ def test_query_json_unicode_not_escaped_by_default(db_path): def test_query_json_ascii_option(db_path, command): db = Database(db_path) with db.conn: - db["text"].insert({"id": 1, "text": "Japanese 日本語"}, pk="id") + db.table("text").insert({"id": 1, "text": "Japanese 日本語"}, pk="id") if command == "query": args = [db_path, "select id, text from text", "--ascii"] else: @@ -1118,7 +1118,7 @@ def test_query_json_ascii_option(db_path, command): [(b"\x00\x0fbinary", True), ("this is text", False), (1, False), (1.5, False)], ) def test_query_raw(db_path, content, is_binary): - Database(db_path)["files"].insert({"content": content}) + Database(db_path).table("files").insert({"content": content}) result = CliRunner().invoke( cli.cli, [db_path, "select content from files", "--raw"] ) @@ -1133,7 +1133,7 @@ def test_query_raw(db_path, content, is_binary): [(b"\x00\x0fbinary", True), ("this is text", False), (1, False), (1.5, False)], ) def test_query_raw_lines(db_path, content, is_binary): - Database(db_path)["files"].insert_all({"content": content} for _ in range(3)) + Database(db_path).table("files").insert_all({"content": content} for _ in range(3)) result = CliRunner().invoke( cli.cli, [db_path, "select content from files", "--raw-lines"] ) @@ -1215,7 +1215,7 @@ def test_query_memory_does_not_create_file(tmpdir): def test_rows(db_path, args, expected): db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "age": 4, "name": "Cleo"}, {"id": 2, "age": 2, "name": "Pancakes"}, @@ -1240,7 +1240,7 @@ def test_upsert(db_path, tmpdir): catch_exceptions=False, ) assert result.exit_code == 0, result.output - assert 2 == db["dogs"].count + assert 2 == db.table("dogs").count # Now run the upsert to update just their ages upsert_dogs = [ {"id": 1, "age": 5}, @@ -1295,8 +1295,8 @@ def test_upsert_pk_inferred_from_existing_table(db_path, tmpdir): def test_upsert_analyze(db_path, tmpdir): db = Database(db_path) - db["rows"].insert({"id": 1, "foo": "x", "n": 3}, pk="id") - db["rows"].create_index(["n"]) + db.table("rows").insert({"id": 1, "foo": "x", "n": 3}, pk="id") + db.table("rows").create_index(["n"]) assert "sqlite_stat1" not in db.table_names() result = CliRunner().invoke( cli.cli, @@ -1310,7 +1310,7 @@ def test_upsert_analyze(db_path, tmpdir): def test_upsert_flatten(tmpdir): db_path = str(tmpdir / "flat.db") db = Database(db_path) - db["upsert_me"].insert({"id": 1, "name": "Example"}, pk="id") + db.table("upsert_me").insert({"id": 1, "name": "Example"}, pk="id") result = CliRunner().invoke( cli.cli, ["upsert", db_path, "upsert_me", "-", "--flatten", "--pk", "id", "--alter"], @@ -1424,7 +1424,7 @@ def test_create_table(args, schema): ) assert result.exit_code == 0 db = Database("test.db") - assert schema == db["t"].schema + assert schema == db.table("t").schema def test_create_table_foreign_key(): @@ -1459,21 +1459,21 @@ def test_create_table_foreign_key(): ' "id" INTEGER PRIMARY KEY,\n' ' "name" TEXT\n' ")" - ) == db["authors"].schema + ) == db.table("authors").schema assert ( 'CREATE TABLE "books" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "title" TEXT,\n' ' "author_id" INTEGER REFERENCES "authors"("id")\n' ")" - ) == db["books"].schema + ) == db.table("books").schema def test_create_table_error_if_table_exists(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) result = runner.invoke( cli.cli, ["create-table", "test.db", "dogs", "id", "integer"] ) @@ -1488,24 +1488,24 @@ def test_create_table_ignore(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) result = runner.invoke( cli.cli, ["create-table", "test.db", "dogs", "id", "integer", "--ignore"] ) assert result.exit_code == 0 - assert 'CREATE TABLE "dogs" (\n "name" TEXT\n)' == db["dogs"].schema + assert 'CREATE TABLE "dogs" (\n "name" TEXT\n)' == db.table("dogs").schema def test_create_table_replace(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) result = runner.invoke( cli.cli, ["create-table", "test.db", "dogs", "id", "integer", "--replace"] ) assert result.exit_code == 0 - assert 'CREATE TABLE "dogs" (\n "id" INTEGER\n)' == db["dogs"].schema + assert 'CREATE TABLE "dogs" (\n "id" INTEGER\n)' == db.table("dogs").schema def test_create_view(): @@ -1517,7 +1517,8 @@ def test_create_view(): ) assert result.exit_code == 0 assert ( - 'CREATE VIEW "version" AS select sqlite_version()' == db["version"].schema + 'CREATE VIEW "version" AS select sqlite_version()' + == db.view("version").schema ) @@ -1554,7 +1555,7 @@ def test_create_view_ignore(): assert result.exit_code == 0 assert ( 'CREATE VIEW "version" AS select sqlite_version() + 1' - == db["version"].schema + == db.view("version").schema ) @@ -1575,7 +1576,8 @@ def test_create_view_replace(): ) assert result.exit_code == 0 assert ( - 'CREATE VIEW "version" AS select sqlite_version()' == db["version"].schema + 'CREATE VIEW "version" AS select sqlite_version()' + == db.view("version").schema ) @@ -1583,7 +1585,7 @@ def test_drop_table(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["t"].create({"pk": int}, pk="pk") + db.table("t").create({"pk": int}, pk="pk") assert "t" in db.table_names() result = runner.invoke( cli.cli, @@ -1601,7 +1603,7 @@ def test_drop_table_error(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["t"].create({"pk": int}, pk="pk") + db.table("t").create({"pk": int}, pk="pk") result = runner.invoke( cli.cli, [ @@ -1624,7 +1626,7 @@ def test_drop_table_on_view_errors(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["t"].insert({"id": 1}) + db.table("t").insert({"id": 1}) db.create_view("v", "select * from t") result = runner.invoke(cli.cli, ["drop-table", "test.db", "v"]) assert result.exit_code == 1 @@ -1660,7 +1662,7 @@ def test_drop_view_on_table_errors(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["t"].insert({"id": 1}) + db.table("t").insert({"id": 1}) result = runner.invoke(cli.cli, ["drop-view", "test.db", "t"]) assert result.exit_code == 1 assert 'Error: "t" is a table, not a view - use drop-table to drop it' == ( @@ -1677,7 +1679,7 @@ def test_drop_view_error(): runner = CliRunner() with runner.isolated_filesystem(): db = Database("test.db") - db["t"].create({"pk": int}, pk="pk") + db.table("t").create({"pk": int}, pk="pk") result = runner.invoke( cli.cli, [ @@ -1702,7 +1704,7 @@ def test_enable_wal(): with runner.isolated_filesystem(): for dbname in dbs: db = Database(dbname) - db["t"].create({"pk": int}, pk="pk") + db.table("t").create({"pk": int}, pk="pk") assert db.journal_mode == "delete" result = runner.invoke(cli.cli, ["enable-wal"] + dbs, catch_exceptions=False) assert result.exit_code == 0 @@ -1717,7 +1719,7 @@ def test_disable_wal(): with runner.isolated_filesystem(): for dbname in dbs: db = Database(dbname) - db["t"].create({"pk": int}, pk="pk") + db.table("t").create({"pk": int}, pk="pk") db.enable_wal() assert db.journal_mode == "wal" result = runner.invoke(cli.cli, ["disable-wal"] + dbs) @@ -1740,7 +1742,7 @@ def test_disable_wal(): def test_query_update(db_path, args, expected): db = Database(db_path) with db.conn: - db["dogs"].insert_all( + db.table("dogs").insert_all( [ {"id": 1, "age": 4, "name": "Cleo"}, ] @@ -1756,11 +1758,13 @@ def test_query_update(db_path, args, expected): def test_add_foreign_keys(db_path): db = Database(db_path) - db["countries"].insert({"id": 7, "name": "Panama"}, pk="id") - db["authors"].insert({"id": 3, "name": "Matilda", "country_id": 7}, pk="id") - db["books"].insert({"id": 2, "title": "Wolf anatomy", "author_id": 3}, pk="id") - assert db["authors"].foreign_keys == [] - assert db["books"].foreign_keys == [] + db.table("countries").insert({"id": 7, "name": "Panama"}, pk="id") + db.table("authors").insert({"id": 3, "name": "Matilda", "country_id": 7}, pk="id") + db.table("books").insert( + {"id": 2, "title": "Wolf anatomy", "author_id": 3}, pk="id" + ) + assert db.table("authors").foreign_keys == [] + assert db.table("books").foreign_keys == [] result = CliRunner().invoke( cli.cli, [ @@ -1777,7 +1781,7 @@ def test_add_foreign_keys(db_path): ], ) assert result.exit_code == 0 - assert db["authors"].foreign_keys == [ + assert db.table("authors").foreign_keys == [ ForeignKey( table="authors", column="country_id", @@ -1785,7 +1789,7 @@ def test_add_foreign_keys(db_path): other_column="id", ) ] - assert db["books"].foreign_keys == [ + assert db.table("books").foreign_keys == [ ForeignKey( table="books", column="author_id", other_table="authors", other_column="id" ) @@ -1909,7 +1913,7 @@ def test_add_foreign_keys(db_path): def test_transform(db_path, args, expected_schema): db = Database(db_path) with db.conn: - db["dogs"].insert( + db.table("dogs").insert( {"id": 1, "age": 4, "name": "Cleo"}, not_null={"age"}, defaults={"age": 1}, @@ -1918,20 +1922,20 @@ def test_transform(db_path, args, expected_schema): result = CliRunner().invoke(cli.cli, ["transform", db_path, "dogs"] + args) print(result.output) assert result.exit_code == 0 - schema = db["dogs"].schema + schema = db.table("dogs").schema assert schema == expected_schema def test_transform_sql(db_path): db = Database(db_path) with db.conn: - db["dogs"].insert( + db.table("dogs").insert( {"id": 1, "age": 4, "name": "Cleo"}, not_null={"age"}, defaults={"age": 1}, pk="id", ) - original_schema = db["dogs"].schema + original_schema = db.table("dogs").schema result = CliRunner().invoke( cli.cli, ["transform", db_path, "dogs", "--drop", "name", "--sql"] @@ -1942,7 +1946,7 @@ def test_transform_sql(db_path): assert '"age" INTEGER NOT NULL DEFAULT' in result.output assert 'DROP TABLE "dogs";' in result.output assert 'ALTER TABLE "dogs_new_' in result.output - assert db["dogs"].schema == original_schema + assert db.table("dogs").schema == original_schema @pytest.mark.parametrize( @@ -1958,12 +1962,12 @@ def test_transform_strict_option(db_path, initial_strict, args, expected_strict) db = Database(db_path) if not db.supports_strict: pytest.skip("SQLite version does not support strict tables") - db["dogs"].create({"id": int}, strict=initial_strict) + db.table("dogs").create({"id": int}, strict=initial_strict) result = CliRunner().invoke(cli.cli, ["transform", db_path, "dogs"] + args) assert result.exit_code == 0, result.output - assert db["dogs"].strict is expected_strict + assert db.table("dogs").strict is expected_strict @pytest.mark.parametrize( @@ -1977,20 +1981,20 @@ def test_transform_strict_option_sql(db_path, initial_strict, flag, sql_is_stric db = Database(db_path) if not db.supports_strict: pytest.skip("SQLite version does not support strict tables") - db["dogs"].create({"id": int}, strict=initial_strict) + db.table("dogs").create({"id": int}, strict=initial_strict) result = CliRunner().invoke(cli.cli, ["transform", db_path, "dogs", flag, "--sql"]) assert result.exit_code == 0, result.output assert (") STRICT;" in result.output) is sql_is_strict - assert db["dogs"].strict is initial_strict + assert db.table("dogs").strict is initial_strict def test_transform_strict_option_with_invalid_data(db_path): db = Database(db_path) if not db.supports_strict: pytest.skip("SQLite version does not support strict tables") - dogs = db["dogs"] + dogs = db.table("dogs") dogs.create({"id": int}) dogs.insert({"id": "not-an-integer"}) @@ -2048,10 +2052,10 @@ def test_transform_add_or_drop_foreign_key(db_path, extra_args, expected_schema) db = Database(db_path) with db.conn: # Create table with three foreign keys so we can drop two of them - db["continent"].insert({"id": 1, "name": "Europe"}, pk="id") - db["country"].insert({"id": 1, "name": "France"}, pk="id") - db["city"].insert({"id": 24, "name": "Paris"}, pk="id") - db["places"].insert( + db.table("continent").insert({"id": 1, "name": "Europe"}, pk="id") + db.table("country").insert({"id": 1, "name": "France"}, pk="id") + db.table("city").insert({"id": 24, "name": "Paris"}, pk="id") + db.table("places").insert( { "id": 32, "name": "Caveau de la Huchette", @@ -2072,7 +2076,7 @@ def test_transform_add_or_drop_foreign_key(db_path, extra_args, expected_schema) + extra_args, ) assert result.exit_code == 0 - schema = db["places"].schema + schema = db.table("places").schema assert schema == expected_schema @@ -2133,7 +2137,7 @@ _common_other_schema = ( def test_extract(db_path, args, expected_table_schema, expected_other_schema): db = Database(db_path) with db.conn: - db["trees"].insert( + db.table("trees").insert( {"id": 1, "address": "4 Park Ave", "species": "Palm"}, pk="id", ) @@ -2142,7 +2146,7 @@ def test_extract(db_path, args, expected_table_schema, expected_other_schema): ) print(result.output) assert result.exit_code == 0 - schema = db["trees"].schema + schema = db.table("trees").schema assert schema == expected_table_schema other_schema = next( t for t in db.tables if t.name not in ("trees", "Gosh", "Gosh2") @@ -2190,7 +2194,7 @@ def test_insert_encoding(tmpdir): ) assert good_result.exit_code == 0 db = Database(db_path) - assert list(db["places"].rows) == [ + assert list(db.table("places").rows) == [ { "date": "2020-01-01", "name": "Barra da Lagoa", @@ -2226,7 +2230,7 @@ def test_insert_encoding(tmpdir): def test_search(tmpdir, fts, extra_arg, expected): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["articles"].insert_all( + db.table("articles").insert_all( [ {"id": 1, "title": "Title the first"}, {"id": 2, "title": "Title the second"}, @@ -2234,7 +2238,7 @@ def test_search(tmpdir, fts, extra_arg, expected): ], pk="id", ) - db["articles"].enable_fts(["title"], fts_version=fts) + db.table("articles").enable_fts(["title"], fts_version=fts) result = CliRunner().invoke( cli.cli, ["search", db_path, "articles", "second"] + ([extra_arg] if extra_arg else []), @@ -2247,7 +2251,7 @@ def test_search(tmpdir, fts, extra_arg, expected): def test_search_quote(tmpdir): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["creatures"].insert({"name": "dog."}).enable_fts(["name"]) + db.table("creatures").insert({"name": "dog."}).enable_fts(["name"]) # Without --quote should return an error error_result = CliRunner().invoke(cli.cli, ["search", db_path, "creatures", 'dog"']) assert error_result.exit_code == 1 @@ -2355,11 +2359,11 @@ _TRIGGERS_EXPECTED = ( def test_triggers(tmpdir, extra_args, expected): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["articles"].insert( + db.table("articles").insert( {"id": 1, "title": "Title the first"}, pk="id", ) - db["counter"].insert({"count": 1}) + db.table("counter").insert({"count": 1}) db.conn.execute(textwrap.dedent(""" CREATE TRIGGER blah AFTER INSERT ON articles BEGIN @@ -2420,9 +2424,9 @@ def test_triggers(tmpdir, extra_args, expected): def test_schema(tmpdir, options, expected): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["dogs"].create({"id": int, "name": str}) - db["chickens"].create({"id": int, "name": str, "breed": str}) - db["chickens"].create_index(["breed"]) + db.table("dogs").create({"id": int, "name": str}) + db.table("chickens").create({"id": int, "name": str, "breed": str}) + db.table("chickens").create_index(["breed"]) result = CliRunner().invoke( cli.cli, ["schema", db_path] + options, @@ -2446,7 +2450,7 @@ def test_long_csv_column_value(tmpdir): ) assert result.exit_code == 0 db = Database(db_path) - rows = list(db["bigtable"].rows) + rows = list(db.table("bigtable").rows) assert len(rows) == 1 assert rows[0]["text"] == long_string @@ -2473,7 +2477,7 @@ def test_import_no_headers(tmpdir, args, tsv): ) assert result.exit_code == 0, result.output db = Database(db_path) - schema = db["creatures"].schema + schema = db.table("creatures").schema assert schema == ( 'CREATE TABLE "creatures" (\n' ' "untitled_1" TEXT,\n' @@ -2481,7 +2485,7 @@ def test_import_no_headers(tmpdir, args, tsv): ' "untitled_3" TEXT\n' ")" ) - rows = list(db["creatures"].rows) + rows = list(db.table("creatures").rows) assert rows == [ {"untitled_1": "Cleo", "untitled_2": "Dog", "untitled_3": "5"}, {"untitled_1": "Tracy", "untitled_2": "Spider", "untitled_3": "7"}, @@ -2493,10 +2497,10 @@ def test_attach(tmpdir): bar_path = str(tmpdir / "bar.db") db = Database(foo_path) with db.conn: - db["foo"].insert({"id": 1, "text": "foo"}) + db.table("foo").insert({"id": 1, "text": "foo"}) db2 = Database(bar_path) with db2.conn: - db2["bar"].insert({"id": 1, "text": "bar"}) + db2.table("bar").insert({"id": 1, "text": "bar"}) db.attach("bar", bar_path) sql = "select * from foo union all select * from bar.bar" result = CliRunner().invoke( @@ -2557,7 +2561,7 @@ def test_insert_detect_types(tmpdir): ) assert result.exit_code == 0 db = Database(db_path) - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"name": "Cleo", "age": 6, "weight": 45.5}, {"name": "Dori", "age": 1, "weight": 3.5}, ] @@ -2589,7 +2593,7 @@ def test_upsert_detect_types(tmpdir): ) assert result.exit_code == 0 db = Database(db_path) - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"id": 1, "name": "Cleo", "age": 6, "weight": 45.5}, {"id": 2, "name": "Dori", "age": 1, "weight": 3.5}, ] @@ -2608,7 +2612,7 @@ def test_csv_detect_types_creates_real_columns(tmpdir): assert result.exit_code == 0 db = Database(db_path) # Check that the schema uses REAL for the weight column - assert db["creatures"].schema == ( + assert db.table("creatures").schema == ( 'CREATE TABLE "creatures" (\n' ' "name" TEXT,\n' ' "age" INTEGER,\n' @@ -2630,11 +2634,11 @@ def test_insert_no_detect_types(tmpdir): assert result.exit_code == 0 db = Database(db_path) # All columns should be TEXT when --no-detect-types is used - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"name": "Cleo", "age": "6", "weight": "45.5"}, {"name": "Dori", "age": "1", "weight": "3.5"}, ] - assert db["creatures"].schema == ( + assert db.table("creatures").schema == ( 'CREATE TABLE "creatures" (\n' ' "name" TEXT,\n' ' "age" TEXT,\n' @@ -2665,11 +2669,11 @@ def test_upsert_no_detect_types(tmpdir): assert result.exit_code == 0 db = Database(db_path) # All columns should be TEXT when --no-detect-types is used - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"id": "1", "name": "Cleo", "age": "6", "weight": "45.5"}, {"id": "2", "name": "Dori", "age": "1", "weight": "3.5"}, ] - assert db["creatures"].schema == ( + assert db.table("creatures").schema == ( 'CREATE TABLE "creatures" (\n' ' "id" TEXT PRIMARY KEY,\n' ' "name" TEXT,\n' @@ -2751,20 +2755,20 @@ def test_create_database(tmpdir, enable_wal): def test_analyze(tmpdir, options, expected): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["one_index"].insert({"id": 1, "name": "Cleo"}, pk="id") - db["one_index"].create_index(["name"]) - db["two_indexes"].insert({"id": 1, "name": "Cleo", "species": "dog"}, pk="id") - db["two_indexes"].create_index(["name"]) - db["two_indexes"].create_index(["species"]) + db.table("one_index").insert({"id": 1, "name": "Cleo"}, pk="id") + db.table("one_index").create_index(["name"]) + db.table("two_indexes").insert({"id": 1, "name": "Cleo", "species": "dog"}, pk="id") + db.table("two_indexes").create_index(["name"]) + db.table("two_indexes").create_index(["species"]) result = CliRunner().invoke(cli.cli, ["analyze", db_path] + options) assert result.exit_code == 0 - assert list(db["sqlite_stat1"].rows) == expected + assert list(db.table("sqlite_stat1").rows) == expected def test_rename_table(tmpdir): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["one"].insert({"id": 1, "name": "Cleo"}, pk="id") + db.table("one").insert({"id": 1, "name": "Cleo"}, pk="id") # First try a non-existent table result_error = CliRunner().invoke( cli.cli, @@ -2782,7 +2786,7 @@ def test_rename_table(tmpdir): catch_exceptions=False, ) assert result_error2.exit_code == 0 - previous_columns = db["one"].columns_dict + previous_columns = db.table("one").columns_dict # Now try for a table that exists result = CliRunner().invoke( cli.cli, @@ -2790,13 +2794,13 @@ def test_rename_table(tmpdir): catch_exceptions=False, ) assert result.exit_code == 0 - assert db["two"].columns_dict == previous_columns + assert db.table("two").columns_dict == previous_columns def test_duplicate_table(tmpdir): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["one"].insert({"id": 1, "name": "Cleo"}, pk="id") + db.table("one").insert({"id": 1, "name": "Cleo"}, pk="id") # First try a non-existent table result_error = CliRunner().invoke( cli.cli, @@ -2819,8 +2823,8 @@ def test_duplicate_table(tmpdir): catch_exceptions=False, ) assert result.exit_code == 0 - assert db["one"].columns_dict == db["two"].columns_dict - assert list(db["one"].rows) == list(db["two"].rows) + assert db.table("one").columns_dict == db.table("two").columns_dict + assert list(db.table("one").rows) == list(db.table("two").rows) @pytest.mark.skipif(not _has_compiled_ext(), reason="Requires compiled ext.c") @@ -2863,9 +2867,9 @@ def test_create_table_strict(strict): + (["--strict"] if strict else []), ) assert result.exit_code == 0 - assert db["items"].strict == strict or not db.supports_strict + assert db.table("items").strict == strict or not db.supports_strict # Should have a floating point column - assert db["items"].columns_dict == {"id": int, "w": float} + assert db.table("items").columns_dict == {"id": int, "w": float} @pytest.mark.parametrize("method", ("insert", "upsert")) @@ -2880,12 +2884,12 @@ def test_insert_upsert_strict(tmpdir, method, strict): ) assert result.exit_code == 0 db = Database(db_path) - assert db["items"].strict == strict or not db.supports_strict + assert db.table("items").strict == strict or not db.supports_strict def test_extract_bad_column_clean_error(db_path): db = Database(db_path) - db["trees"].insert({"id": 1, "species": "Palm"}, pk="id") + db.table("trees").insert({"id": 1, "species": "Palm"}, pk="id") result = CliRunner().invoke(cli.cli, ["extract", db_path, "trees", "nope"]) assert result.exit_code == 1 assert result.exception is None or isinstance(result.exception, SystemExit) @@ -2894,7 +2898,7 @@ def test_extract_bad_column_clean_error(db_path): def test_extract_view_clean_error(db_path): db = Database(db_path) - db["trees"].insert({"id": 1, "species": "Palm"}, pk="id") + db.table("trees").insert({"id": 1, "species": "Palm"}, pk="id") db.create_view("v", "select * from trees") result = CliRunner().invoke(cli.cli, ["extract", db_path, "v", "species"]) assert result.exit_code == 1 diff --git a/tests/test_cli_bulk.py b/tests/test_cli_bulk.py index 932269b..24889b3 100644 --- a/tests/test_cli_bulk.py +++ b/tests/test_cli_bulk.py @@ -13,7 +13,7 @@ from sqlite_utils import Database, cli def test_db_and_path(tmpdir): db_path = str(pathlib.Path(tmpdir) / "data.db") db = Database(db_path) - db["example"].insert_all( + db.table("example").insert_all( [ {"id": 1, "name": "One"}, {"id": 2, "name": "Two"}, @@ -44,7 +44,7 @@ def test_cli_bulk(test_db_and_path): {"id": 2, "name": "Two"}, {"id": 3, "name": "THREE"}, {"id": 4, "name": "FOUR"}, - ] == list(db["example"].rows) + ] == list(db.table("example").rows) def test_cli_bulk_multiple_functions(test_db_and_path): @@ -70,7 +70,7 @@ def test_cli_bulk_multiple_functions(test_db_and_path): {"id": 2, "name": "Two"}, {"id": 3, "name": "THREE"}, {"id": 4, "name": "FOUR"}, - ] == list(db["example"].rows) + ] == list(db.table("example").rows) def test_cli_bulk_batch_size(test_db_and_path): @@ -95,13 +95,13 @@ def test_cli_bulk_batch_size(test_db_and_path): proc.stdin.write(b'{"id": 3, "name": "Three"}\n\n') proc.stdin.flush() time.sleep(1) - assert db["example"].count == 2 + assert db.table("example").count == 2 # Writing another should trigger a commit: proc.stdin.write(b'{"id": 4, "name": "Four"}\n\n') proc.stdin.flush() time.sleep(1) - assert db["example"].count == 4 + assert db.table("example").count == 4 proc.stdin.close() proc.wait() diff --git a/tests/test_cli_convert.py b/tests/test_cli_convert.py index 65543b1..1101f0f 100644 --- a/tests/test_cli_convert.py +++ b/tests/test_cli_convert.py @@ -12,7 +12,7 @@ from sqlite_utils import cli @pytest.fixture def test_db_and_path(fresh_db_and_path): db, db_path = fresh_db_and_path - db["example"].insert_all( + db.table("example").insert_all( [ {"id": 1, "dt": "5th October 2019 12:04"}, {"id": 2, "dt": "6th October 2019 00:05:06"}, @@ -47,12 +47,12 @@ def fresh_db_and_path(tmpdir): ) def test_convert_code(fresh_db_and_path, code): db, db_path = fresh_db_and_path - db["t"].insert({"text": "October"}) + db.table("t").insert({"text": "October"}) result = CliRunner().invoke( cli.cli, ["convert", db_path, "t", "text", code], catch_exceptions=False ) assert result.exit_code == 0, result.output - value = next(iter(db["t"].rows))["text"] + value = next(iter(db.table("t").rows))["text"] assert value == "Spooktober" @@ -65,7 +65,7 @@ def test_convert_code(fresh_db_and_path, code): ) def test_convert_code_errors(fresh_db_and_path, bad_code): db, db_path = fresh_db_and_path - db["t"].insert({"text": "October"}) + db.table("t").insert({"text": "October"}) result = CliRunner().invoke( cli.cli, ["convert", db_path, "t", "text", bad_code], catch_exceptions=False ) @@ -93,12 +93,12 @@ def test_convert_import(test_db_and_path): {"id": 2, "dt": "6th OXXober 2019 00:05:06"}, {"id": 3, "dt": ""}, {"id": 4, "dt": None}, - ] == list(db["example"].rows) + ] == list(db.table("example").rows) def test_convert_import_nested(fresh_db_and_path): db, db_path = fresh_db_and_path - db["example"].insert({"xml": ''}) + db.table("example").insert({"xml": ''}) result = CliRunner().invoke( cli.cli, [ @@ -114,7 +114,7 @@ def test_convert_import_nested(fresh_db_and_path): assert result.exit_code == 0, result.output assert [ {"xml": "Cleo"}, - ] == list(db["example"].rows) + ] == list(db.table("example").rows) def test_convert_dryrun(test_db_and_path): @@ -152,7 +152,7 @@ def test_convert_dryrun(test_db_and_path): "Would affect 4 rows" ) # But it should not have actually modified the table data - assert list(db["example"].rows) == [ + assert list(db.table("example").rows) == [ {"id": 1, "dt": "5th October 2019 12:04"}, {"id": 2, "dt": "6th October 2019 00:05:06"}, {"id": 3, "dt": ""}, @@ -269,7 +269,7 @@ def test_convert_output_column(test_db_and_path, drop): if drop: for row in expected: del row["dt"] - assert list(db["example"].rows) == expected + assert list(db.table("example").rows) == expected @pytest.mark.parametrize( @@ -352,7 +352,7 @@ def test_convert_output_error(test_db_and_path, options, expected_error): @pytest.mark.parametrize("drop", (True, False)) def test_convert_multi(fresh_db_and_path, drop): db, db_path = fresh_db_and_path - db["creatures"].insert_all( + db.table("creatures").insert_all( [ {"id": 1, "name": "Simon"}, {"id": 2, "name": "Cleo"}, @@ -378,12 +378,12 @@ def test_convert_multi(fresh_db_and_path, drop): if drop: for row in expected: del row["name"] - assert list(db["creatures"].rows) == expected + assert list(db.table("creatures").rows) == expected def test_convert_multi_complex_column_types(fresh_db_and_path): db, db_path = fresh_db_and_path - db["rows"].insert_all( + db.table("rows").insert_all( [ {"id": 1}, {"id": 2}, @@ -412,7 +412,7 @@ def test_convert_multi_complex_column_types(fresh_db_and_path): ], ) assert result.exit_code == 0, result.output - assert list(db["rows"].rows) == [ + assert list(db.table("rows").rows) == [ {"id": 1, "is_str": "", "is_float": 1.2, "is_int": None, "is_bytes": None}, {"id": 2, "is_str": None, "is_float": 1.0, "is_int": 12, "is_bytes": None}, { @@ -424,7 +424,7 @@ def test_convert_multi_complex_column_types(fresh_db_and_path): }, {"id": 4, "is_str": None, "is_float": None, "is_int": None, "is_bytes": None}, ] - assert db["rows"].schema == ( + assert db.table("rows").schema == ( 'CREATE TABLE "rows" (\n' ' "id" INTEGER PRIMARY KEY\n' ', "is_str" TEXT, "is_float" REAL, "is_int" INTEGER, "is_bytes" BLOB)' @@ -435,7 +435,7 @@ def test_convert_multi_complex_column_types(fresh_db_and_path): def test_recipe_jsonsplit(tmpdir, delimiter): db_path = str(pathlib.Path(tmpdir) / "data.db") db = sqlite_utils.Database(db_path) - db["example"].insert_all( + db.table("example").insert_all( [ {"id": 1, "tags": (delimiter or ",").join(["foo", "bar"])}, {"id": 2, "tags": (delimiter or ",").join(["bar", "baz"])}, @@ -448,7 +448,7 @@ def test_recipe_jsonsplit(tmpdir, delimiter): args = ["convert", db_path, "example", "tags", code] result = CliRunner().invoke(cli.cli, args) assert result.exit_code == 0, result.output - assert list(db["example"].rows) == [ + assert list(db.table("example").rows) == [ {"id": 1, "tags": '["foo", "bar"]'}, {"id": 2, "tags": '["bar", "baz"]'}, ] @@ -464,7 +464,7 @@ def test_recipe_jsonsplit(tmpdir, delimiter): ) def test_recipe_jsonsplit_type(fresh_db_and_path, type, expected_array): db, db_path = fresh_db_and_path - db["example"].insert_all( + db.table("example").insert_all( [ {"id": 1, "records": "1,2,3"}, ], @@ -476,13 +476,13 @@ def test_recipe_jsonsplit_type(fresh_db_and_path, type, expected_array): args = ["convert", db_path, "example", "records", code] result = CliRunner().invoke(cli.cli, args) assert result.exit_code == 0, result.output - assert json.loads(db["example"].get(1)["records"]) == expected_array + assert json.loads(db.table("example").get(1)["records"]) == expected_array @pytest.mark.parametrize("drop", (True, False)) def test_recipe_jsonsplit_output(fresh_db_and_path, drop): db, db_path = fresh_db_and_path - db["example"].insert_all( + db.table("example").insert_all( [ {"id": 1, "records": "1,2,3"}, ], @@ -501,7 +501,7 @@ def test_recipe_jsonsplit_output(fresh_db_and_path, drop): } if drop: del expected["records"] - assert db["example"].get(1) == expected + assert db.table("example").get(1) == expected def test_cannot_use_drop_without_multi_or_output(fresh_db_and_path): @@ -558,7 +558,7 @@ def test_convert_where(test_db_and_path): ], ) assert result.exit_code == 0, result.output - assert list(db["example"].rows) == [ + assert list(db.table("example").rows) == [ {"id": 1, "dt": "5th October 2019 12:04"}, {"id": 2, "dt": "6TH OCTOBER 2019 00:05:06"}, {"id": 3, "dt": ""}, @@ -568,7 +568,7 @@ def test_convert_where(test_db_and_path): def test_convert_where_multi(fresh_db_and_path): db, db_path = fresh_db_and_path - db["names"].insert_all( + db.table("names").insert_all( [{"id": 1, "name": "Cleo"}, {"id": 2, "name": "Bants"}], pk="id" ) result = CliRunner().invoke( @@ -588,7 +588,7 @@ def test_convert_where_multi(fresh_db_and_path): ], ) assert result.exit_code == 0, result.output - assert list(db["names"].rows) == [ + assert list(db.table("names").rows) == [ {"id": 1, "name": "Cleo", "upper": None}, {"id": 2, "name": "Bants", "upper": "BANTS"}, ] @@ -596,7 +596,7 @@ def test_convert_where_multi(fresh_db_and_path): def test_convert_code_standard_input(fresh_db_and_path): db, db_path = fresh_db_and_path - db["names"].insert_all([{"id": 1, "name": "Cleo"}], pk="id") + db.table("names").insert_all([{"id": 1, "name": "Cleo"}], pk="id") result = CliRunner().invoke( cli.cli, [ @@ -609,27 +609,27 @@ def test_convert_code_standard_input(fresh_db_and_path): input="value.upper()", ) assert result.exit_code == 0, result.output - assert list(db["names"].rows) == [ + assert list(db.table("names").rows) == [ {"id": 1, "name": "CLEO"}, ] def test_convert_hyphen_workaround(fresh_db_and_path): db, db_path = fresh_db_and_path - db["names"].insert_all([{"id": 1, "name": "Cleo"}], pk="id") + db.table("names").insert_all([{"id": 1, "name": "Cleo"}], pk="id") result = CliRunner().invoke( cli.cli, ["convert", db_path, "names", "name", '"-"'], ) assert result.exit_code == 0, result.output - assert list(db["names"].rows) == [ + assert list(db.table("names").rows) == [ {"id": 1, "name": "-"}, ] def test_convert_initialization_pattern(fresh_db_and_path): db, db_path = fresh_db_and_path - db["names"].insert_all([{"id": 1, "name": "Cleo"}], pk="id") + db.table("names").insert_all([{"id": 1, "name": "Cleo"}], pk="id") result = CliRunner().invoke( cli.cli, [ @@ -642,7 +642,7 @@ def test_convert_initialization_pattern(fresh_db_and_path): input="import random\nrandom.seed(1)\ndef convert(value): return random.randint(0, 100)", ) assert result.exit_code == 0, result.output - assert list(db["names"].rows) == [ + assert list(db.table("names").rows) == [ {"id": 1, "name": "17"}, ] @@ -657,13 +657,13 @@ def test_convert_handles_falsey_values(fresh_db_and_path): "x", "-", ] - db["t"].insert_all([{"x": 0}, {"x": 1}]) - assert db["t"].get(1)["x"] == 0 - assert db["t"].get(2)["x"] == 1 + db.table("t").insert_all([{"x": 0}, {"x": 1}]) + assert db.table("t").get(1)["x"] == 0 + assert db.table("t").get(2)["x"] == 1 result = CliRunner().invoke(cli.cli, args, input="value + 1") assert result.exit_code == 0, result.output - assert db["t"].get(1)["x"] == 1 - assert db["t"].get(2)["x"] == 2 + assert db.table("t").get(1)["x"] == 1 + assert db.table("t").get(2)["x"] == 2 @pytest.mark.parametrize( @@ -684,7 +684,7 @@ def test_convert_callable_reference(test_db_and_path, code): cli.cli, ["convert", db_path, "example", "dt", code], catch_exceptions=False ) assert result.exit_code == 0, result.output - rows = list(db["example"].rows) + rows = list(db.table("example").rows) assert rows[0]["dt"] == "2019-10-05" assert rows[1]["dt"] == "2019-10-06" assert rows[2]["dt"] == "" @@ -694,7 +694,7 @@ def test_convert_callable_reference(test_db_and_path, code): def test_convert_callable_reference_with_import(fresh_db_and_path): """Test callable reference from an imported module""" db, db_path = fresh_db_and_path - db["example"].insert({"id": 1, "data": '{"name": "test"}'}) + db.table("example").insert({"id": 1, "data": '{"name": "test"}'}) result = CliRunner().invoke( cli.cli, [ @@ -710,5 +710,5 @@ def test_convert_callable_reference_with_import(fresh_db_and_path): ) assert result.exit_code == 0, result.output # json.loads returns a dict, which sqlite stores as JSON string - row = db["example"].get(1) + row = db.table("example").get(1) assert row["data"] == '{"name": "test"}' diff --git a/tests/test_cli_insert.py b/tests/test_cli_insert.py index eefb3fa..01e7e94 100644 --- a/tests/test_cli_insert.py +++ b/tests/test_cli_insert.py @@ -21,7 +21,7 @@ def test_insert_simple(tmpdir): ) db = Database(db_path) assert ["dogs"] == db.table_names() - assert [] == db["dogs"].indexes + assert [] == db.table("dogs").indexes def test_insert_from_stdin(tmpdir): @@ -96,7 +96,7 @@ def test_insert_with_primary_keys(db_path, tmpdir, args, expected_pks): Database(db_path).query("select * from dogs") ) db = Database(db_path) - assert db["dogs"].pks == expected_pks + assert db.table("dogs").pks == expected_pks def test_insert_multiple_with_primary_key(db_path, tmpdir): @@ -110,7 +110,7 @@ def test_insert_multiple_with_primary_key(db_path, tmpdir): assert result.exit_code == 0 db = Database(db_path) assert dogs == list(db.query("select * from dogs order by id")) - assert ["id"] == db["dogs"].pks + assert ["id"] == db.table("dogs").pks def test_insert_multiple_with_compound_primary_key(db_path, tmpdir): @@ -127,7 +127,7 @@ def test_insert_multiple_with_compound_primary_key(db_path, tmpdir): assert result.exit_code == 0 db = Database(db_path) assert dogs == list(db.query("select * from dogs order by breed, id")) - assert {"breed", "id"} == set(db["dogs"].pks) + assert {"breed", "id"} == set(db.table("dogs").pks) assert ( 'CREATE TABLE "dogs" (\n' ' "breed" TEXT,\n' @@ -136,7 +136,7 @@ def test_insert_multiple_with_compound_primary_key(db_path, tmpdir): ' "age" INTEGER,\n' ' PRIMARY KEY ("id", "breed")\n' ")" - ) == db["dogs"].schema + ) == db.table("dogs").schema def test_insert_not_null_default(db_path, tmpdir): @@ -160,7 +160,7 @@ def test_insert_not_null_default(db_path, tmpdir): ' "name" TEXT NOT NULL,\n' " \"age\" INTEGER NOT NULL DEFAULT '1',\n" " \"score\" INTEGER DEFAULT '5'\n)" - ) == db["dogs"].schema + ) == db.table("dogs").schema def test_insert_binary_base64(db_path): @@ -191,7 +191,7 @@ def test_insert_newline_delimited(db_path): def test_insert_ignore(db_path, tmpdir): db = Database(db_path) - db["dogs"].insert({"id": 1, "name": "Cleo"}, pk="id") + db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id") json_path = str(tmpdir / "dogs.json") with open(json_path, "w") as fp: fp.write(json.dumps([{"id": 1, "name": "Bailey"}])) @@ -232,7 +232,7 @@ def test_insert_csv_tsv(content, options, db_path, tmpdir): catch_exceptions=False, ) assert result.exit_code == 0 - assert [{"foo": "1", "bar": "2", "baz": "cat,dog"}] == list(db["data"].rows) + assert [{"foo": "1", "bar": "2", "baz": "cat,dog"}] == list(db.table("data").rows) @pytest.mark.parametrize("empty_null", (True, False)) @@ -248,7 +248,7 @@ def test_insert_csv_empty_null(db_path, empty_null): ) assert result.exit_code == 0 db = Database(db_path) - assert [r for r in db["data"].rows] == [ + assert [r for r in db.table("data").rows] == [ {"foo": "1", "bar": None if empty_null else "", "baz": "cat"} ] @@ -302,7 +302,7 @@ def test_insert_replace(db_path, tmpdir): test_insert_multiple_with_primary_key(db_path, tmpdir) json_path = str(tmpdir / "insert-replace.json") db = Database(db_path) - assert db["dogs"].count == 20 + assert db.table("dogs").count == 20 insert_replace_dogs = [ {"id": 1, "name": "Insert replaced 1", "age": 4}, {"id": 2, "name": "Insert replaced 2", "age": 4}, @@ -314,7 +314,7 @@ def test_insert_replace(db_path, tmpdir): cli.cli, ["insert", db_path, "dogs", json_path, "--pk", "id", "--replace"] ) assert result.exit_code == 0, result.output - assert db["dogs"].count == 21 + assert db.table("dogs").count == 21 assert ( list(db.query("select * from dogs where id in (1, 2, 21) order by id")) == insert_replace_dogs @@ -377,7 +377,7 @@ def test_insert_alter(db_path, tmpdir): assert result.exit_code == 0, result.output # Soundness check the database itself db = Database(db_path) - assert {"foo": str, "n": int, "baz": int} == db["from_json_nl"].columns_dict + assert {"foo": str, "n": int, "baz": int} == db.table("from_json_nl").columns_dict assert [ {"foo": "bar", "n": 1, "baz": None}, {"foo": "baz", "n": 2, "baz": None}, @@ -387,8 +387,8 @@ def test_insert_alter(db_path, tmpdir): def test_insert_analyze(db_path): db = Database(db_path) - db["rows"].insert({"foo": "x", "n": 3}) - db["rows"].create_index(["n"]) + db.table("rows").insert({"foo": "x", "n": 3}) + db.table("rows").create_index(["n"]) assert "sqlite_stat1" not in db.table_names() result = CliRunner().invoke( cli.cli, @@ -583,7 +583,7 @@ def test_insert_streaming_batch_size_1(db_path): def try_until(expected): tries = 0 while True: - rows = list(Database(db_path)["rows"].rows) + rows = list(Database(db_path).table("rows").rows) if rows == expected: return tries += 1 @@ -615,13 +615,13 @@ def test_insert_csv_headers_only(tmpdir): assert result.exit_code == 0 # Table should not exist since there were no data rows db = Database(db_path) - assert not db["data"].exists() + assert not db.table("data").exists() def test_insert_into_view_errors(tmpdir): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["t"].insert({"id": 1}) + db.table("t").insert({"id": 1}) db.create_view("v", "select * from t") db.close() result = CliRunner().invoke( @@ -637,7 +637,7 @@ def test_insert_csv_detect_types_leaves_existing_table_alone(db_path): # table would rewrite its column types and corrupt data such as # TEXT zip codes with leading zeros db = Database(db_path) - db["places"].insert({"name": "Boston", "zip": "01234"}) + db.table("places").insert({"name": "Boston", "zip": "01234"}) result = CliRunner().invoke( cli.cli, ["insert", db_path, "places", "-", "--csv"], @@ -645,8 +645,8 @@ def test_insert_csv_detect_types_leaves_existing_table_alone(db_path): input="name,zip\nSF,94107", ) assert result.exit_code == 0, result.output - assert db["places"].columns_dict["zip"] is str - assert list(db["places"].rows) == [ + assert db.table("places").columns_dict["zip"] is str + assert list(db.table("places").rows) == [ {"name": "Boston", "zip": "01234"}, {"name": "SF", "zip": "94107"}, ] @@ -662,7 +662,7 @@ def test_insert_csv_detect_types_new_table(db_path): ) assert result.exit_code == 0, result.output db = Database(db_path) - assert db["data"].columns_dict == {"name": str, "age": int, "weight": float} + assert db.table("data").columns_dict == {"name": str, "age": int, "weight": float} @pytest.mark.parametrize( @@ -708,13 +708,13 @@ def test_insert_upsert_csv_type_overrides_detected_types( expected_columns = {"zipcode": str, "score": float} if command == "upsert": expected_columns = {"id": int, **expected_columns} - assert db["places"].columns_dict == expected_columns - assert list(db["places"].rows) == [expected_row] + assert db.table("places").columns_dict == expected_columns + assert list(db.table("places").rows) == [expected_row] def test_upsert_csv_detect_types_leaves_existing_table_alone(db_path): db = Database(db_path) - db["places"].insert({"id": 1, "name": "Boston", "zip": "01234"}, pk="id") + db.table("places").insert({"id": 1, "name": "Boston", "zip": "01234"}, pk="id") result = CliRunner().invoke( cli.cli, ["upsert", db_path, "places", "-", "--csv", "--pk", "id"], @@ -722,15 +722,15 @@ def test_upsert_csv_detect_types_leaves_existing_table_alone(db_path): input="id,name,zip\n2,SF,94107", ) assert result.exit_code == 0, result.output - assert db["places"].columns_dict["zip"] is str - assert db["places"].get(1)["zip"] == "01234" + assert db.table("places").columns_dict["zip"] is str + assert db.table("places").get(1)["zip"] == "01234" def test_insert_invalid_pk_clean_error(db_path): # An invalid --pk against an existing table should be a clean CLI # error, not a raw InvalidColumns traceback db = Database(db_path) - db["t"].insert({"a": 1}) + db.table("t").insert({"a": 1}) result = CliRunner().invoke( cli.cli, ["insert", db_path, "t", "-", "--pk", "badcol"], @@ -765,8 +765,8 @@ def test_insert_code(tmpdir, code): ) assert result.exit_code == 0, result.output db = Database(db_path) - assert db["creatures"].pks == ["id"] - assert list(db["creatures"].rows) == [ + assert db.table("creatures").pks == ["id"] + assert list(db.table("creatures").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 2, "name": "Suna"}, ] @@ -782,7 +782,7 @@ def test_insert_code_from_file(tmpdir): ["insert", db_path, "creatures", "--code", code_path], ) assert result.exit_code == 0, result.output - assert list(Database(db_path)["creatures"].rows) == [ + assert list(Database(db_path).table("creatures").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 2, "name": "Suna"}, ] @@ -791,7 +791,7 @@ def test_insert_code_from_file(tmpdir): def test_upsert_code(tmpdir): db_path = str(tmpdir / "dogs.db") db = Database(db_path) - db["creatures"].insert_all( + db.table("creatures").insert_all( [{"id": 1, "name": "old"}, {"id": 2, "name": "Suna"}], pk="id" ) result = CliRunner().invoke( @@ -799,7 +799,7 @@ def test_upsert_code(tmpdir): ["upsert", db_path, "creatures", "--code", CODE_ROWS_FUNCTION, "--pk", "id"], ) assert result.exit_code == 0, result.output - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 2, "name": "Suna"}, ] @@ -858,7 +858,9 @@ def test_insert_code_single_dict(tmpdir): ], ) assert result.exit_code == 0, result.output - assert list(Database(db_path)["creatures"].rows) == [{"id": 1, "name": "Cleo"}] + assert list(Database(db_path).table("creatures").rows) == [ + {"id": 1, "name": "Cleo"} + ] def test_insert_code_not_iterable(tmpdir): diff --git a/tests/test_cli_memory.py b/tests/test_cli_memory.py index 4fb4fb3..445f50b 100644 --- a/tests/test_cli_memory.py +++ b/tests/test_cli_memory.py @@ -228,7 +228,7 @@ def test_memory_save(tmpdir, extra_args): ) assert result.exit_code == 0 db = Database(save_to) - assert list(db["stdin"].rows) == [ + assert list(db.table("stdin").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 2, "name": "Bants"}, ] diff --git a/tests/test_cli_migrate.py b/tests/test_cli_migrate.py index f49ef10..7439887 100644 --- a/tests/test_cli_migrate.py +++ b/tests/test_cli_migrate.py @@ -13,11 +13,11 @@ m = Migrations("hello") @m() def foo(db): - db["foo"].insert({"hello": "world"}) + db.table("foo").insert({"hello": "world"}) @m() def bar(db): - db["bar"].insert({"hello": "world"}) + db.table("bar").insert({"hello": "world"}) """ @@ -42,21 +42,21 @@ creatures = Migrations("creatures") @creatures() def create_table(db): - db["creatures"].insert({"name": "Cleo"}) + db.table("creatures").insert({"name": "Cleo"}) @creatures() def add_weight(db): - db["creature_weights"].insert({"weight": 4.2}) + db.table("creature_weights").insert({"weight": 4.2}) sales = Migrations("sales") @sales() def create_table(db): - db["sales"].insert({"id": 1}) + db.table("sales").insert({"id": 1}) @sales() def add_weight(db): - db["sales_weights"].insert({"weight": 10}) + db.table("sales_weights").insert({"weight": 10}) """, "utf-8", ) @@ -99,10 +99,10 @@ def test_basic(two_migrations, arg): assert " Pending:\n (none)" in list_output db = sqlite_utils.Database(db_path) - assert db["foo"].exists() - assert db["bar"].exists() - assert db["_sqlite_migrations"].exists() - rows = list(db["_sqlite_migrations"].rows) + assert db.table("foo").exists() + assert db.table("bar").exists() + assert db.table("_sqlite_migrations").exists() + rows = list(db.table("_sqlite_migrations").rows) assert len(rows) == 2 assert rows[0]["name"] == "foo" assert rows[1]["name"] == "bar" @@ -113,13 +113,13 @@ def test_list_same_migration_names_in_different_sets(capsys): @applied(name="foo") def applied_foo(db): - db["applied"].insert({"hello": "world"}) + db.table("applied").insert({"hello": "world"}) pending = sqlite_utils.Migrations("pending") @pending(name="foo") def pending_foo(db): - db["pending"].insert({"hello": "world"}) + db.table("pending").insert({"hello": "world"}) db = sqlite_utils.Database(memory=True) applied.apply(db) @@ -144,7 +144,7 @@ m = Migrations("hello") @m() def foo(db): - db["dogs"].insert({"id": 1, "name": "Cleo"}) + db.table("dogs").insert({"id": 1, "name": "Cleo"}) """, "utf-8", ) @@ -184,9 +184,9 @@ Schema after: new_migration = """ @m() def bar(db): - db["dogs"].add_column("age", int) - db["dogs"].add_column("weight", float) - db["dogs"].transform() + db.table("dogs").add_column("age", int) + db.table("dogs").add_column("weight", float) + db.table("dogs").transform() """ migrations_py.write_text(migrations_py.read_text("utf-8") + new_migration) @@ -224,8 +224,8 @@ def test_stop_before(two_migrations): ) assert result.exit_code == 0 db = sqlite_utils.Database(db_path) - assert db["foo"].exists() - assert not db["bar"].exists() + assert db.table("foo").exists() + assert not db.table("bar").exists() def test_stop_before_multiple_sets_unqualified(two_migrations): @@ -239,7 +239,7 @@ m = Migrations("hello2") @m() def foo(db): - db["foo"].insert({"hello": "world"}) + db.table("foo").insert({"hello": "world"}) """, "utf-8", ) @@ -257,7 +257,7 @@ def foo(db): assert result.exit_code == 0, result.output db = sqlite_utils.Database(db_path) assert db.table_names() == ["_sqlite_migrations"] - assert list(db["_sqlite_migrations"].rows) == [] + assert list(db.table("_sqlite_migrations").rows) == [] def test_stop_before_qualified_only_affects_named_set(two_sets_same_migration_name): @@ -275,10 +275,10 @@ def test_stop_before_qualified_only_affects_named_set(two_sets_same_migration_na ) assert result.exit_code == 0, result.output db = sqlite_utils.Database(db_path) - assert db["creatures"].exists() - assert not db["creature_weights"].exists() - assert db["sales"].exists() - assert db["sales_weights"].exists() + assert db.table("creatures").exists() + assert not db.table("creature_weights").exists() + assert db.table("sales").exists() + assert db.table("sales_weights").exists() def test_stop_before_multiple_qualified(two_sets_same_migration_name): @@ -298,10 +298,10 @@ def test_stop_before_multiple_qualified(two_sets_same_migration_name): ) assert result.exit_code == 0, result.output db = sqlite_utils.Database(db_path) - assert db["creatures"].exists() - assert not db["creature_weights"].exists() - assert db["sales"].exists() - assert not db["sales_weights"].exists() + assert db.table("creatures").exists() + assert not db.table("creature_weights").exists() + assert db.table("sales").exists() + assert not db.table("sales_weights").exists() LEGACY_MIGRATIONS = """ @@ -331,7 +331,7 @@ class LegacyMigrations: return fn def ensure_migrations_table(self, db): - db[self.migrations_table].create( + db.table(self.migrations_table).create( {"migration_set": str, "name": str, "applied_at": str}, pk=("migration_set", "name"), if_not_exists=True, @@ -341,7 +341,7 @@ class LegacyMigrations: self.ensure_migrations_table(db) return [ _Applied(row["name"], row["applied_at"]) - for row in db[self.migrations_table].rows_where( + for row in db.table(self.migrations_table).rows_where( "migration_set = ?", [self.name] ) ] @@ -355,7 +355,7 @@ class LegacyMigrations: if migration.name == stop_before: return migration.fn(db) - db[self.migrations_table].insert( + db.table(self.migrations_table).insert( { "migration_set": self.name, "name": migration.name, @@ -369,11 +369,11 @@ legacy = LegacyMigrations("legacy_set") @legacy def first(db): - db["first"].insert({"hello": "world"}) + db.table("first").insert({"hello": "world"}) @legacy def second(db): - db["second"].insert({"hello": "world"}) + db.table("second").insert({"hello": "world"}) """ @@ -446,11 +446,11 @@ def test_list_does_not_upgrade_legacy_migrations_table(two_migrations): path, _ = two_migrations db_path = str(path / "test.db") db = sqlite_utils.Database(db_path) - db["_sqlite_migrations"].create( + db.table("_sqlite_migrations").create( {"migration_set": str, "name": str, "applied_at": str}, pk=("migration_set", "name"), ) - db["_sqlite_migrations"].insert( + db.table("_sqlite_migrations").insert( {"migration_set": "hello", "name": "foo", "applied_at": "x"} ) db.close() @@ -462,7 +462,7 @@ def test_list_does_not_upgrade_legacy_migrations_table(two_migrations): assert "foo - x" in result.output # --list must not perform the one-way legacy schema upgrade db2 = sqlite_utils.Database(db_path) - assert db2["_sqlite_migrations"].pks == ["migration_set", "name"] + assert db2.table("_sqlite_migrations").pks == ["migration_set", "name"] db2.close() @@ -485,7 +485,7 @@ def test_stop_before_applied_migration_errors(two_migrations): assert result.exit_code != 0 assert "already been applied" in result.output db = sqlite_utils.Database(db_path) - assert not db["bar"].exists() + assert not db.table("bar").exists() def test_list_with_legacy_class_is_read_only(tmpdir): @@ -496,7 +496,7 @@ def test_list_with_legacy_class_is_read_only(tmpdir): (path / "migrations.py").write_text(LEGACY_MIGRATIONS, "utf-8") db_path = str(path / "test.db") db = sqlite_utils.Database(db_path) - db["existing"].insert({"id": 1}) + db.table("existing").insert({"id": 1}) db.close() result = CliRunner().invoke( sqlite_utils.cli.cli, ["migrate", db_path, str(path), "--list"] diff --git a/tests/test_column_affinity.py b/tests/test_column_affinity.py index fa23345..8c619e1 100644 --- a/tests/test_column_affinity.py +++ b/tests/test_column_affinity.py @@ -43,4 +43,4 @@ def test_column_affinity(column_def, expected_type): @pytest.mark.parametrize("column_def,expected_type", EXAMPLES) def test_columns_dict(fresh_db, column_def, expected_type): fresh_db.execute(f"create table foo (col {column_def})") - assert {"col": expected_type} == fresh_db["foo"].columns_dict + assert {"col": expected_type} == fresh_db.table("foo").columns_dict diff --git a/tests/test_column_casing.py b/tests/test_column_casing.py index ce11345..b3f03c9 100644 --- a/tests/test_column_casing.py +++ b/tests/test_column_casing.py @@ -13,14 +13,14 @@ from sqlite_utils.db import ForeignKey def test_insert_populates_last_pk_case_insensitively(fresh_db): - books = fresh_db["books"] + books = fresh_db.table("books") books.create({"Id": int, "Title": str}, pk="Id") books.insert({"Id": 1, "Title": "One"}, pk="id") assert books.last_pk == 1 def test_insert_populates_last_pk_compound_pk_case_insensitively(fresh_db): - books = fresh_db["books"] + books = fresh_db.table("books") books.create({"Author": str, "Position": int, "Title": str}) books.insert( {"Author": "Sue", "Position": 1, "Title": "One"}, pk=("author", "position") @@ -31,7 +31,7 @@ def test_insert_populates_last_pk_compound_pk_case_insensitively(fresh_db): @pytest.mark.parametrize("use_old_upsert", (False, True)) def test_upsert_pk_case_differs_from_schema(use_old_upsert): db = Database(memory=True, use_old_upsert=use_old_upsert) - books = db["books"] + books = db.table("books") books.create({"Id": int, "Title": str}, pk="Id") books.insert({"Id": 1, "Title": "One"}) books.upsert({"id": 1, "title": "Won"}, pk="id") @@ -43,7 +43,7 @@ def test_upsert_pk_case_differs_from_schema(use_old_upsert): def test_upsert_record_key_case_differs_from_pk(use_old_upsert): # all_columns comes from the record keys, pk= from the caller db = Database(memory=True, use_old_upsert=use_old_upsert) - books = db["books"] + books = db.table("books") books.create({"Id": int, "Title": str}, pk="Id") books.upsert({"ID": 1, "Title": "One"}, pk="id") assert list(books.rows) == [{"Id": 1, "Title": "One"}] @@ -52,7 +52,7 @@ def test_upsert_record_key_case_differs_from_pk(use_old_upsert): def test_upsert_inferred_pk_case_differs_from_record_keys(fresh_db): # pk is inferred from the existing schema as "Id", records use "id" - books = fresh_db["books"] + books = fresh_db.table("books") books.create({"Id": int, "Title": str}, pk="Id") books.upsert({"id": 1, "title": "One"}) assert list(books.rows) == [{"Id": 1, "Title": "One"}] @@ -60,7 +60,7 @@ def test_upsert_inferred_pk_case_differs_from_record_keys(fresh_db): def test_upsert_list_mode_pk_case_insensitive(fresh_db): - books = fresh_db["books"] + books = fresh_db.table("books") books.create({"Id": int, "Title": str}, pk="Id") books.upsert_all([["id", "title"], [1, "One"]], pk="Id") assert list(books.rows) == [{"Id": 1, "Title": "One"}] @@ -68,84 +68,84 @@ def test_upsert_list_mode_pk_case_insensitive(fresh_db): def test_lookup_pk_case_insensitive(fresh_db): - fresh_db["species"].create({"ID": int, "Name": str}, pk="ID") - fresh_db["species"].insert({"ID": 5, "Name": "Palm"}) - fresh_db["species"].create_index(["Name"], unique=True) - assert fresh_db["species"].lookup({"Name": "Palm"}, pk="id") == 5 + fresh_db.table("species").create({"ID": int, "Name": str}, pk="ID") + fresh_db.table("species").insert({"ID": 5, "Name": "Palm"}) + fresh_db.table("species").create_index(["Name"], unique=True) + assert fresh_db.table("species").lookup({"Name": "Palm"}, pk="id") == 5 def test_lookup_does_not_create_redundant_index(fresh_db): - fresh_db["species"].create({"id": int, "Name": str}, pk="id") - fresh_db["species"].create_index(["Name"], unique=True) - fresh_db["species"].lookup({"name": "Palm"}) - assert len(fresh_db["species"].indexes) == 1 + fresh_db.table("species").create({"id": int, "Name": str}, pk="id") + fresh_db.table("species").create_index(["Name"], unique=True) + fresh_db.table("species").lookup({"name": "Palm"}) + assert len(fresh_db.table("species").indexes) == 1 def test_create_table_transform_same_columns_different_case(fresh_db): - fresh_db["t"].create({"Name": str, "Age": int}) - fresh_db["t"].insert({"Name": "Cleo", "Age": 5}) + fresh_db.table("t").create({"Name": str, "Age": int}) + fresh_db.table("t").insert({"Name": "Cleo", "Age": 5}) fresh_db.create_table("t", {"name": str, "age": int}, transform=True) # Schema casing is preserved - SQLite considers these the same columns - assert fresh_db["t"].columns_dict == {"Name": str, "Age": int} - assert list(fresh_db["t"].rows) == [{"Name": "Cleo", "Age": 5}] + assert fresh_db.table("t").columns_dict == {"Name": str, "Age": int} + assert list(fresh_db.table("t").rows) == [{"Name": "Cleo", "Age": 5}] def test_create_table_transform_case_insensitive_with_changes(fresh_db): - fresh_db["t"].create({"Name": str, "Age": int}) + fresh_db.table("t").create({"Name": str, "Age": int}) fresh_db.create_table("t", {"name": str, "age": str, "size": int}, transform=True) # age changed type, size added, Name untouched - assert fresh_db["t"].columns_dict == {"Name": str, "Age": str, "size": int} + assert fresh_db.table("t").columns_dict == {"Name": str, "Age": str, "size": int} def test_transform_types_case_insensitive(fresh_db): - fresh_db["t"].create({"Name": str, "Age": str}) - fresh_db["t"].transform(types={"age": int}) - assert fresh_db["t"].columns_dict == {"Name": str, "Age": int} + fresh_db.table("t").create({"Name": str, "Age": str}) + fresh_db.table("t").transform(types={"age": int}) + assert fresh_db.table("t").columns_dict == {"Name": str, "Age": int} def test_transform_rename_case_insensitive(fresh_db): - fresh_db["t"].create({"Name": str}) - fresh_db["t"].transform(rename={"name": "title"}) - assert fresh_db["t"].columns_dict == {"title": str} + fresh_db.table("t").create({"Name": str}) + fresh_db.table("t").transform(rename={"name": "title"}) + assert fresh_db.table("t").columns_dict == {"title": str} def test_transform_drop_case_insensitive(fresh_db): - fresh_db["t"].create({"Name": str, "Age": int}) - fresh_db["t"].transform(drop=["name"]) - assert fresh_db["t"].columns_dict == {"Age": int} + fresh_db.table("t").create({"Name": str, "Age": int}) + fresh_db.table("t").transform(drop=["name"]) + assert fresh_db.table("t").columns_dict == {"Age": int} def test_transform_not_null_and_defaults_case_insensitive(fresh_db): - fresh_db["t"].create({"Name": str, "Age": int}) - fresh_db["t"].transform(not_null={"name"}, defaults={"age": 3}) - columns = {c.name: c for c in fresh_db["t"].columns} + fresh_db.table("t").create({"Name": str, "Age": int}) + fresh_db.table("t").transform(not_null={"name"}, defaults={"age": 3}) + columns = {c.name: c for c in fresh_db.table("t").columns} assert columns["Name"].notnull - assert fresh_db["t"].default_values == {"Age": 3} + assert fresh_db.table("t").default_values == {"Age": 3} def test_transform_pk_case_insensitive(fresh_db): - fresh_db["t"].create({"Id": int, "Name": str}) - fresh_db["t"].transform(pk="id") - assert fresh_db["t"].pks == ["Id"] - assert fresh_db["t"].columns_dict == {"Id": int, "Name": str} + fresh_db.table("t").create({"Id": int, "Name": str}) + fresh_db.table("t").transform(pk="id") + assert fresh_db.table("t").pks == ["Id"] + assert fresh_db.table("t").columns_dict == {"Id": int, "Name": str} def test_transform_drop_foreign_keys_case_insensitive(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create( + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create( {"id": int, "Parent_ID": int}, pk="id", foreign_keys=[("Parent_ID", "parent", "Id")], ) - fresh_db["child"].transform(drop_foreign_keys=["parent_id"]) - assert fresh_db["child"].foreign_keys == [] + fresh_db.table("child").transform(drop_foreign_keys=["parent_id"]) + assert fresh_db.table("child").foreign_keys == [] def test_add_foreign_key_case_insensitive(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create({"id": int, "Parent_ID": int}, pk="id") - fresh_db["child"].add_foreign_key("parent_id", "parent", "id") - fks = fresh_db["child"].foreign_keys + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create({"id": int, "Parent_ID": int}, pk="id") + fresh_db.table("child").add_foreign_key("parent_id", "parent", "id") + fks = fresh_db.table("child").foreign_keys assert len(fks) == 1 # The foreign key should use the schema casing of the columns assert fks[0].column == "Parent_ID" @@ -153,79 +153,83 @@ def test_add_foreign_key_case_insensitive(fresh_db): def test_add_foreign_keys_case_insensitive(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create({"id": int, "Parent_ID": int}, pk="id") + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create({"id": int, "Parent_ID": int}, pk="id") fresh_db.add_foreign_keys([("child", "parent_id", "parent", "id")]) - fks = fresh_db["child"].foreign_keys + fks = fresh_db.table("child").foreign_keys assert len(fks) == 1 assert fks[0].column == "Parent_ID" assert fks[0].other_column == "Id" def test_add_foreign_key_detects_existing_case_insensitively(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create( + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create( {"id": int, "Parent_ID": int}, pk="id", foreign_keys=[("Parent_ID", "parent", "Id")], ) # ignore=True should treat this as already existing, not add a duplicate - fresh_db["child"].add_foreign_key("parent_id", "parent", "id", ignore=True) - assert len(fresh_db["child"].foreign_keys) == 1 + fresh_db.table("child").add_foreign_key("parent_id", "parent", "id", ignore=True) + assert len(fresh_db.table("child").foreign_keys) == 1 def test_add_column_fk_col_case_insensitive(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create({"id": int}, pk="id") - fresh_db["child"].add_column("parent_id", int, fk="parent", fk_col="id") - fks = fresh_db["child"].foreign_keys + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create({"id": int}, pk="id") + fresh_db.table("child").add_column("parent_id", int, fk="parent", fk_col="id") + fks = fresh_db.table("child").foreign_keys assert len(fks) == 1 assert fks[0].other_column == "Id" def test_extract_case_insensitive(fresh_db): - fresh_db["trees"].insert({"id": 1, "Species": "Palm"}, pk="id") - fresh_db["trees"].extract("species") - assert fresh_db["trees"].columns_dict == {"id": int, "Species_id": int} - assert list(fresh_db["Species"].rows) == [{"id": 1, "Species": "Palm"}] + fresh_db.table("trees").insert({"id": 1, "Species": "Palm"}, pk="id") + fresh_db.table("trees").extract("species") + assert fresh_db.table("trees").columns_dict == {"id": int, "Species_id": int} + assert list(fresh_db.table("Species").rows) == [{"id": 1, "Species": "Palm"}] def test_convert_multi_case_insensitive(fresh_db): - fresh_db["t"].insert({"id": 1, "Name": "Cleo"}, pk="id") - fresh_db["t"].convert("name", lambda v: {"upper": v.upper()}, multi=True) - assert list(fresh_db["t"].rows) == [{"id": 1, "Name": "Cleo", "upper": "CLEO"}] + fresh_db.table("t").insert({"id": 1, "Name": "Cleo"}, pk="id") + fresh_db.table("t").convert("name", lambda v: {"upper": v.upper()}, multi=True) + assert list(fresh_db.table("t").rows) == [ + {"id": 1, "Name": "Cleo", "upper": "CLEO"} + ] def test_convert_output_case_insensitive(fresh_db): - fresh_db["t"].insert({"id": 1, "Name": "Cleo", "Upper": None}, pk="id") - fresh_db["t"].convert("name", lambda v: v.upper(), output="upper") - assert list(fresh_db["t"].rows) == [{"id": 1, "Name": "Cleo", "Upper": "CLEO"}] + fresh_db.table("t").insert({"id": 1, "Name": "Cleo", "Upper": None}, pk="id") + fresh_db.table("t").convert("name", lambda v: v.upper(), output="upper") + assert list(fresh_db.table("t").rows) == [ + {"id": 1, "Name": "Cleo", "Upper": "CLEO"} + ] def test_create_table_sql_pk_case_insensitive(fresh_db): - fresh_db["t"].create({"Id": int, "Name": str}, pk="id") + fresh_db.table("t").create({"Id": int, "Name": str}, pk="id") # Should not have created an extra lowercase "id" column - assert fresh_db["t"].columns_dict == {"Id": int, "Name": str} - assert fresh_db["t"].pks == ["Id"] + assert fresh_db.table("t").columns_dict == {"Id": int, "Name": str} + assert fresh_db.table("t").pks == ["Id"] def test_create_table_not_null_and_defaults_case_insensitive(fresh_db): - fresh_db["t"].create( + fresh_db.table("t").create( {"Name": str, "Age": int}, not_null={"name"}, defaults={"age": 1} ) - columns = {c.name: c for c in fresh_db["t"].columns} + columns = {c.name: c for c in fresh_db.table("t").columns} assert columns["Name"].notnull - assert fresh_db["t"].default_values == {"Age": 1} + assert fresh_db.table("t").default_values == {"Age": 1} def test_create_table_foreign_keys_case_insensitive(fresh_db): - fresh_db["parent"].create({"Id": int}, pk="Id") - fresh_db["child"].create( + fresh_db.table("parent").create({"Id": int}, pk="Id") + fresh_db.table("child").create( {"id": int, "Parent_ID": int}, pk="id", foreign_keys=[("parent_id", "parent", "id")], ) - fks = fresh_db["child"].foreign_keys + fks = fresh_db.table("child").foreign_keys assert fks == [ ForeignKey( table="child", column="Parent_ID", other_table="parent", other_column="Id" diff --git a/tests/test_constructor.py b/tests/test_constructor.py index 4282969..2d0a298 100644 --- a/tests/test_constructor.py +++ b/tests/test_constructor.py @@ -20,8 +20,8 @@ def test_recursive_triggers_off(): def test_memory_name(): db1 = Database(memory_name="shared") db2 = Database(memory_name="shared") - db1["dogs"].insert({"name": "Cleo"}) - assert list(db2["dogs"].rows) == [{"name": "Cleo"}] + db1.table("dogs").insert({"name": "Cleo"}) + assert list(db2.table("dogs").rows) == [{"name": "Cleo"}] def test_sqlite_version(): @@ -36,7 +36,7 @@ def test_sqlite_version(): def test_database_context_manager(tmpdir): path = str(tmpdir / "test.db") with Database(path) as db: - db["t"].insert({"id": 1}) + db.table("t").insert({"id": 1}) # Raw writes commit automatically too db.execute("insert into t (id) values (2)") # An explicitly opened transaction left uncommitted on purpose: @@ -47,7 +47,7 @@ def test_database_context_manager(tmpdir): db.execute("select 1") # ... and the open explicit transaction was rolled back, not committed db2 = Database(path) - assert [r["id"] for r in db2["t"].rows] == [1, 2] + assert [r["id"] for r in db2.table("t").rows] == [1, 2] db2.close() @@ -86,8 +86,8 @@ def test_legacy_transaction_control_connection_is_accepted(tmpdir): str(tmpdir / "test.db"), autocommit=sqlite3.LEGACY_TRANSACTION_CONTROL ) db = Database(conn) - db["t"].insert({"id": 1}, pk="id") - assert [r["id"] for r in db["t"].rows] == [1] + db.table("t").insert({"id": 1}, pk="id") + assert [r["id"] for r in db.table("t").rows] == [1] db.close() diff --git a/tests/test_conversions.py b/tests/test_conversions.py index d70f5c8..bb58df4 100644 --- a/tests/test_conversions.py +++ b/tests/test_conversions.py @@ -1,17 +1,17 @@ def test_insert_conversion(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"foo": "bar"}, conversions={"foo": "upper(?)"}) assert [{"foo": "BAR"}] == list(table.rows) def test_insert_all_conversion(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all([{"foo": "bar"}], conversions={"foo": "upper(?)"}) assert [{"foo": "BAR"}] == list(table.rows) def test_upsert_conversion(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert({"id": 1, "foo": "bar"}, pk="id", conversions={"foo": "upper(?)"}) assert [{"id": 1, "foo": "BAR"}] == list(table.rows) table.upsert( @@ -21,7 +21,7 @@ def test_upsert_conversion(fresh_db): def test_upsert_all_conversion(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert_all( [{"id": 1, "foo": "bar"}], pk="id", conversions={"foo": "upper(?)"} ) @@ -29,7 +29,7 @@ def test_upsert_all_conversion(fresh_db): def test_update_conversion(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"id": 5, "foo": "bar"}, pk="id") table.update(5, {"foo": "baz"}, conversions={"foo": "upper(?)"}) assert [{"id": 5, "foo": "BAZ"}] == list(table.rows) diff --git a/tests/test_convert.py b/tests/test_convert.py index 879267a..1f9e9ed 100644 --- a/tests/test_convert.py +++ b/tests/test_convert.py @@ -27,7 +27,7 @@ from sqlite_utils.db import BadMultiValues ), ) def test_convert(fresh_db, columns, fn, expected): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"title": "Mixed Case", "abstract": "Abstract"}) table.convert(columns, fn) assert list(table.rows) == [expected] @@ -37,7 +37,7 @@ def test_convert(fresh_db, columns, fn, expected): "where,where_args", (("id > 1", None), ("id > :id", {"id": 1}), ("id > ?", [1])) ) def test_convert_where(fresh_db, where, where_args): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all( [ {"id": 1, "title": "One"}, @@ -53,7 +53,7 @@ def test_convert_where(fresh_db, where, where_args): def test_convert_handles_falsey_values(fresh_db): # Falsey values like 0 should be converted (issue #527) - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all([{"x": 0}, {"x": 1}]) assert table.get(1)["x"] == 0 assert table.get(2)["x"] == 1 @@ -70,14 +70,14 @@ def test_convert_handles_falsey_values(fresh_db): ), ) def test_convert_output(fresh_db, drop, expected): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"title": "Mixed Case"}) table.convert("title", lambda v: v.upper(), output="other", drop=drop) assert list(table.rows) == [expected] def test_convert_output_multiple_column_error(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") with pytest.raises(ValueError) as excinfo: table.convert(["title", "other"], lambda v: v, output="out") assert "output= can only be used with a single column" in str(excinfo.value) @@ -91,14 +91,14 @@ def test_convert_output_multiple_column_error(fresh_db): ), ) def test_convert_output_type(fresh_db, type, expected): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"number": "123"}) table.convert("number", lambda v: v, output="other", output_type=type, drop=True) assert list(table.rows) == [expected] def test_convert_multi(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"title": "Mixed Case"}) table.convert( "title", @@ -123,7 +123,7 @@ def test_convert_multi(fresh_db): def test_convert_multi_where(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all( [ {"id": 1, "title": "One"}, @@ -145,14 +145,14 @@ def test_convert_multi_where(fresh_db): def test_convert_multi_exception(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"title": "Mixed Case"}) with pytest.raises(BadMultiValues): table.convert("title", lambda v: v.upper(), multi=True) def test_convert_repeated(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") col = "num" table.insert({col: 1}) table.convert(col, lambda x: x * 2) diff --git a/tests/test_create.py b/tests/test_create.py index 40746bf..0af68a6 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -80,9 +80,10 @@ def test_create_table_compound_primary_key(fresh_db): @pytest.mark.parametrize("pk", ("id", ["id"])) def test_create_table_with_single_primary_key(fresh_db, pk): - fresh_db["foo"].insert({"id": 1}, pk=pk) + fresh_db.table("foo").insert({"id": 1}, pk=pk) assert ( - fresh_db["foo"].schema == 'CREATE TABLE "foo" (\n "id" INTEGER PRIMARY KEY\n)' + fresh_db.table("foo").schema + == 'CREATE TABLE "foo" (\n "id" INTEGER PRIMARY KEY\n)' ) @@ -159,7 +160,7 @@ def test_create_table_with_not_null(fresh_db): ), ) def test_create_table_from_example(fresh_db, example, expected_columns): - people_table = fresh_db["people"] + people_table = fresh_db.table("people") assert people_table.last_rowid is None assert people_table.last_pk is None people_table.insert(example) @@ -167,13 +168,13 @@ def test_create_table_from_example(fresh_db, example, expected_columns): assert people_table.last_pk == 1 assert ["people"] == fresh_db.table_names() assert expected_columns == [ - {"name": col.name, "type": col.type} for col in fresh_db["people"].columns + {"name": col.name, "type": col.type} for col in fresh_db.table("people").columns ] def test_create_table_from_example_with_compound_primary_keys(fresh_db): record = {"name": "Zhang", "group": "staff", "employee_id": 2} - table = fresh_db["people"].insert(record, pk=("group", "employee_id")) + table = fresh_db.table("people").insert(record, pk=("group", "employee_id")) assert ["group", "employee_id"] == table.pks assert record == table.get(("staff", 2)) @@ -184,7 +185,7 @@ def test_create_table_from_example_with_compound_primary_keys(fresh_db): @pytest.mark.parametrize("use_old_upsert", (False, True)) def test_create_table_with_custom_columns(method_name, use_old_upsert): db = Database(memory=True, use_old_upsert=use_old_upsert) - table = db["dogs"] + table = db.table("dogs") method = getattr(table, method_name) record = {"id": 1, "name": "Cleo", "age": "5"} if method_name.endswith("_all"): @@ -218,14 +219,16 @@ def test_create_table_column_order(fresh_db, use_table_factory): if use_table_factory: fresh_db.table("table", column_order=column_order).insert(row) else: - fresh_db["table"].insert(row, column_order=column_order) + fresh_db.table("table").insert(row, column_order=column_order) assert [ {"name": "abc", "type": "TEXT"}, {"name": "ccc", "type": "TEXT"}, {"name": "zzz", "type": "TEXT"}, {"name": "bbb", "type": "TEXT"}, {"name": "aaa", "type": "TEXT"}, - ] == [{"name": col.name, "type": col.type} for col in fresh_db["table"].columns] + ] == [ + {"name": col.name, "type": col.type} for col in fresh_db.table("table").columns + ] @pytest.mark.parametrize( @@ -261,8 +264,8 @@ def test_create_table_works_for_m2m_with_only_foreign_keys( fresh_db.table("one", pk="id").insert({"id": 1}) fresh_db.table("two", pk="id").insert({"id": 1}) else: - fresh_db["one"].insert({"id": 1}, pk="id") - fresh_db["two"].insert({"id": 1}, pk="id") + fresh_db.table("one").insert({"id": 1}, pk="id") + fresh_db.table("two").insert({"id": 1}, pk="id") row = {"one_id": 1, "two_id": 1} @@ -270,7 +273,7 @@ def test_create_table_works_for_m2m_with_only_foreign_keys( if use_table_factory: fresh_db.table("m2m", foreign_keys=foreign_key_specification).insert(row) else: - fresh_db["m2m"].insert(row, foreign_keys=foreign_key_specification) + fresh_db.table("m2m").insert(row, foreign_keys=foreign_key_specification) if expected_exception: with pytest.raises(expected_exception): @@ -281,7 +284,7 @@ def test_create_table_works_for_m2m_with_only_foreign_keys( assert [ {"name": "one_id", "type": "INTEGER"}, {"name": "two_id", "type": "INTEGER"}, - ] == [{"name": col.name, "type": col.type} for col in fresh_db["m2m"].columns] + ] == [{"name": col.name, "type": col.type} for col in fresh_db.table("m2m").columns] assert sorted( [ {"column": "one_id", "other_table": "one", "other_column": "id"}, @@ -295,7 +298,7 @@ def test_create_table_works_for_m2m_with_only_foreign_keys( "other_table": fk.other_table, "other_column": fk.other_column, } - for fk in fresh_db["m2m"].foreign_keys + for fk in fresh_db.table("m2m").foreign_keys ], key=lambda s: repr(s), ) @@ -322,7 +325,7 @@ def test_self_referential_foreign_key(fresh_db): def test_create_error_if_invalid_foreign_keys(fresh_db): with pytest.raises(AlterError): - fresh_db["one"].insert( + fresh_db.table("one").insert( {"id": 1, "ref_id": 3}, pk="id", foreign_keys=(("ref_id", "bad_table", "bad_column"),), @@ -331,7 +334,7 @@ def test_create_error_if_invalid_foreign_keys(fresh_db): def test_create_error_if_invalid_self_referential_foreign_keys(fresh_db): with pytest.raises(AlterError) as ex: - fresh_db["one"].insert( + fresh_db.table("one").insert( {"id": 1, "ref_id": 3}, pk="id", foreign_keys=(("ref_id", "one", "bad_column"),), @@ -397,41 +400,43 @@ def test_create_error_if_invalid_self_referential_foreign_keys(fresh_db): ) def test_add_column(fresh_db, col_name, col_type, not_null_default, expected_schema): fresh_db.create_table("dogs", {"name": str}) - assert fresh_db["dogs"].schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' - fresh_db["dogs"].add_column(col_name, col_type, not_null_default=not_null_default) - assert fresh_db["dogs"].schema == expected_schema + assert fresh_db.table("dogs").schema == 'CREATE TABLE "dogs" (\n "name" TEXT\n)' + fresh_db.table("dogs").add_column( + col_name, col_type, not_null_default=not_null_default + ) + assert fresh_db.table("dogs").schema == expected_schema def test_add_foreign_key(fresh_db): - fresh_db["authors"].insert_all( + fresh_db.table("authors").insert_all( [{"id": 1, "name": "Sally"}, {"id": 2, "name": "Asheesh"}], pk="id" ) - fresh_db["books"].insert_all( + fresh_db.table("books").insert_all( [ {"title": "Hedgehogs of the world", "author_id": 1}, {"title": "How to train your wolf", "author_id": 2}, ] ) - assert [] == fresh_db["books"].foreign_keys - t = fresh_db["books"].add_foreign_key("author_id", "authors", "id") + assert [] == fresh_db.table("books").foreign_keys + t = fresh_db.table("books").add_foreign_key("author_id", "authors", "id") # Ensure it returned self: assert isinstance(t, Table) and t.name == "books" assert [ ForeignKey( table="books", column="author_id", other_table="authors", other_column="id" ) - ] == fresh_db["books"].foreign_keys + ] == fresh_db.table("books").foreign_keys def test_add_foreign_key_if_column_contains_space(fresh_db): - fresh_db["authors"].insert_all([{"id": 1, "name": "Sally"}], pk="id") - fresh_db["books"].insert_all( + fresh_db.table("authors").insert_all([{"id": 1, "name": "Sally"}], pk="id") + fresh_db.table("books").insert_all( [ {"title": "Hedgehogs of the world", "author id": 1}, ] ) - fresh_db["books"].add_foreign_key("author id", "authors", "id") - assert fresh_db["books"].foreign_keys == [ + fresh_db.table("books").add_foreign_key("author id", "authors", "id") + assert fresh_db.table("books").foreign_keys == [ ForeignKey( table="books", column="author id", other_table="authors", other_column="id" ) @@ -439,44 +444,44 @@ def test_add_foreign_key_if_column_contains_space(fresh_db): def test_add_foreign_key_error_if_column_does_not_exist(fresh_db): - fresh_db["books"].insert( + fresh_db.table("books").insert( {"id": 1, "title": "Hedgehogs of the world", "author_id": 1} ) with pytest.raises(AlterError): - fresh_db["books"].add_foreign_key("author2_id", "books", "id") + fresh_db.table("books").add_foreign_key("author2_id", "books", "id") def test_add_foreign_key_error_if_other_table_does_not_exist(fresh_db): - fresh_db["books"].insert({"title": "Hedgehogs of the world", "author_id": 1}) + fresh_db.table("books").insert({"title": "Hedgehogs of the world", "author_id": 1}) with pytest.raises(AlterError): - fresh_db["books"].add_foreign_key("author_id", "authors", "id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") def test_add_foreign_key_error_if_already_exists(fresh_db): - fresh_db["books"].insert({"title": "Hedgehogs of the world", "author_id": 1}) - fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - fresh_db["books"].add_foreign_key("author_id", "authors", "id") + fresh_db.table("books").insert({"title": "Hedgehogs of the world", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") with pytest.raises(AlterError) as ex: - fresh_db["books"].add_foreign_key("author_id", "authors", "id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") assert "Foreign key already exists for author_id => authors.id" == ex.value.args[0] def test_add_foreign_key_no_error_if_exists_and_ignore_true(fresh_db): - fresh_db["books"].insert({"title": "Hedgehogs of the world", "author_id": 1}) - fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - fresh_db["books"].add_foreign_key("author_id", "authors", "id") - fresh_db["books"].add_foreign_key("author_id", "authors", "id", ignore=True) + fresh_db.table("books").insert({"title": "Hedgehogs of the world", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id", ignore=True) def test_add_foreign_keys(fresh_db): - fresh_db["authors"].insert_all( + fresh_db.table("authors").insert_all( [{"id": 1, "name": "Sally"}, {"id": 2, "name": "Asheesh"}], pk="id" ) - fresh_db["categories"].insert_all([{"id": 1, "name": "Wildlife"}], pk="id") - fresh_db["books"].insert_all( + fresh_db.table("categories").insert_all([{"id": 1, "name": "Wildlife"}], pk="id") + fresh_db.table("books").insert_all( [{"title": "Hedgehogs of the world", "author_id": 1, "category_id": 1}] ) - assert [] == fresh_db["books"].foreign_keys + assert [] == fresh_db.table("books").foreign_keys fresh_db.add_foreign_keys( [ ("books", "author_id", "authors", "id"), @@ -493,14 +498,14 @@ def test_add_foreign_keys(fresh_db): other_table="categories", other_column="id", ), - ] == sorted(fresh_db["books"].foreign_keys) + ] == sorted(fresh_db.table("books").foreign_keys) def test_add_column_foreign_key(fresh_db): fresh_db.create_table("dogs", {"name": str}) fresh_db.create_table("breeds", {"name": str}) - fresh_db["dogs"].add_column("breed_id", fk="breeds") - assert fresh_db["dogs"].schema == ( + fresh_db.table("dogs").add_column("breed_id", fk="breeds") + assert fresh_db.table("dogs").schema == ( 'CREATE TABLE "dogs" (\n' ' "name" TEXT,\n' ' "breed_id" INTEGER REFERENCES "breeds"("rowid")\n' @@ -508,8 +513,8 @@ def test_add_column_foreign_key(fresh_db): ) # And again with an explicit primary key column fresh_db.create_table("subbreeds", {"name": str, "primkey": str}, pk="primkey") - fresh_db["dogs"].add_column("subbreed_id", fk="subbreeds") - assert fresh_db["dogs"].schema == ( + fresh_db.table("dogs").add_column("subbreed_id", fk="subbreeds") + assert fresh_db.table("dogs").schema == ( 'CREATE TABLE "dogs" (\n' ' "name" TEXT,\n' ' "breed_id" INTEGER REFERENCES "breeds"("rowid"),\n' @@ -521,9 +526,9 @@ def test_add_column_foreign_key(fresh_db): def test_add_foreign_key_guess_table(fresh_db): fresh_db.create_table("dogs", {"name": str}) fresh_db.create_table("breeds", {"name": str, "id": int}, pk="id") - fresh_db["dogs"].add_column("breed_id", int) - fresh_db["dogs"].add_foreign_key("breed_id") - assert fresh_db["dogs"].schema == ( + fresh_db.table("dogs").add_column("breed_id", int) + fresh_db.table("dogs").add_foreign_key("breed_id") + assert fresh_db.table("dogs").schema == ( 'CREATE TABLE "dogs" (\n' ' "name" TEXT,\n' ' "breed_id" INTEGER REFERENCES "breeds"("id")\n' @@ -533,21 +538,23 @@ def test_add_foreign_key_guess_table(fresh_db): def test_index_foreign_keys(fresh_db): test_add_foreign_key_guess_table(fresh_db) - assert [] == fresh_db["dogs"].indexes + assert [] == fresh_db.table("dogs").indexes fresh_db.index_foreign_keys() - assert [["breed_id"]] == [i.columns for i in fresh_db["dogs"].indexes] + assert [["breed_id"]] == [i.columns for i in fresh_db.table("dogs").indexes] # Calling it a second time should do nothing fresh_db.index_foreign_keys() - assert [["breed_id"]] == [i.columns for i in fresh_db["dogs"].indexes] + assert [["breed_id"]] == [i.columns for i in fresh_db.table("dogs").indexes] def test_index_foreign_keys_if_index_name_is_already_used(fresh_db): # https://github.com/simonw/sqlite-utils/issues/335 test_add_foreign_key_guess_table(fresh_db) # Add index with a name that will conflict with index_foreign_keys() - fresh_db["dogs"].create_index(["name"], index_name="idx_dogs_breed_id") + fresh_db.table("dogs").create_index(["name"], index_name="idx_dogs_breed_id") fresh_db.index_foreign_keys() - assert {(idx.name, tuple(idx.columns)) for idx in fresh_db["dogs"].indexes} == { + assert { + (idx.name, tuple(idx.columns)) for idx in fresh_db.table("dogs").indexes + } == { ("idx_dogs_breed_id_2", ("breed_id",)), ("idx_dogs_breed_id", ("name",)), } @@ -571,7 +578,7 @@ def test_index_foreign_keys_if_index_name_is_already_used(fresh_db): def test_insert_row_alter_table( fresh_db, extra_data, expected_new_columns, use_table_factory ): - table = fresh_db["books"] + table = fresh_db.table("books") table.insert({"title": "Hedgehogs of the world", "author_id": 1}) assert [ {"name": "title", "type": "TEXT"}, @@ -582,7 +589,7 @@ def test_insert_row_alter_table( if use_table_factory: fresh_db.table("books", alter=True).insert(record) else: - fresh_db["books"].insert(record, alter=True) + fresh_db.table("books").insert(record, alter=True) assert [ {"name": "title", "type": "TEXT"}, {"name": "author_id", "type": "INTEGER"}, @@ -592,7 +599,7 @@ def test_insert_row_alter_table( def test_add_missing_columns_case_insensitive(fresh_db): - table = fresh_db["foo"] + table = fresh_db.table("foo") table.insert({"id": 1, "name": "Cleo"}, pk="id") table.add_missing_columns([{"Name": ".", "age": 4}]) assert ( @@ -618,7 +625,7 @@ def test_insert_replace_rows_alter_table(fresh_db, use_table_factory): table.insert(first_row) table.insert_all(next_rows, replace=True) else: - table = fresh_db["books"] + table = fresh_db.table("books") table.insert(first_row, pk="id") table.insert_all(next_rows, alter=True, replace=True) assert { @@ -664,8 +671,8 @@ def test_insert_all_with_extra_columns_in_later_chunks(fresh_db): {"record": "Record 3"}, {"record": "Record 4", "extra": 1}, ] - fresh_db["t"].insert_all(chunk, batch_size=2, alter=True) - assert list(fresh_db["t"].rows) == [ + fresh_db.table("t").insert_all(chunk, batch_size=2, alter=True) + assert list(fresh_db.table("t").rows) == [ {"record": "Record 1", "extra": None}, {"record": "Record 2", "extra": None}, {"record": "Record 3", "extra": None}, @@ -675,7 +682,7 @@ def test_insert_all_with_extra_columns_in_later_chunks(fresh_db): def test_bulk_insert_more_than_999_values(fresh_db): "Inserting 100 items with 11 columns should work" - fresh_db["big"].insert_all( + fresh_db.table("big").insert_all( ( { "id": i + 1, @@ -694,7 +701,7 @@ def test_bulk_insert_more_than_999_values(fresh_db): ), pk="id", ) - assert fresh_db["big"].count == 100 + assert fresh_db.table("big").count == 100 @pytest.mark.parametrize( @@ -704,9 +711,9 @@ def test_error_if_more_than_999_columns(fresh_db, num_columns, should_error): record = {f"c{i}": i for i in range(num_columns)} if should_error: with pytest.raises(ValueError): - fresh_db["big"].insert(record) + fresh_db.table("big").insert(record) else: - fresh_db["big"].insert(record) + fresh_db.table("big").insert(record) def test_columns_not_in_first_record_should_not_cause_batch_to_be_too_large(fresh_db): @@ -722,7 +729,9 @@ def test_columns_not_in_first_record_should_not_cause_batch_to_be_too_large(fres # fill out the batch with 99 records with enough columns to exceed THRESHOLD *[{f"c{i}": j for i in range(extra_columns)} for j in range(batch_size - 1)], ] - fresh_db["too_many_columns"].insert_all(records, alter=True, batch_size=batch_size) + fresh_db.table("too_many_columns").insert_all( + records, alter=True, batch_size=batch_size + ) @pytest.mark.parametrize( @@ -767,7 +776,7 @@ def test_columns_not_in_first_record_should_not_cause_batch_to_be_too_large(fres ), ) def test_create_index(fresh_db, columns, index_name, expected_index): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is good dog": True}) assert [] == dogs.indexes dogs.create_index(columns, index_name) @@ -775,7 +784,7 @@ def test_create_index(fresh_db, columns, index_name, expected_index): def test_create_index_unique(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is_good_dog": True}) assert [] == dogs.indexes dogs.create_index(["name"], unique=True) @@ -793,7 +802,7 @@ def test_create_index_unique(fresh_db): def test_create_index_if_not_exists(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is_good_dog": True}) assert [] == dogs.indexes dogs.create_index(["name"]) @@ -804,7 +813,7 @@ def test_create_index_if_not_exists(fresh_db): def test_drop_index(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is_good_dog": True}) dogs.create_index(["name"]) assert [index.name for index in dogs.indexes] == ["idx_dogs_name"] @@ -813,7 +822,7 @@ def test_drop_index(fresh_db): def test_drop_index_ignore(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo"}) with pytest.raises(OperationalError, match="No index named idx_dogs_name"): dogs.drop_index("idx_dogs_name") @@ -821,8 +830,8 @@ def test_drop_index_ignore(fresh_db): def test_drop_index_wrong_table(fresh_db): - dogs = fresh_db["dogs"] - cats = fresh_db["cats"] + dogs = fresh_db.table("dogs") + cats = fresh_db.table("cats") dogs.insert({"name": "Cleo"}) cats.insert({"name": "Misty"}) dogs.create_index(["name"]) @@ -832,7 +841,7 @@ def test_drop_index_wrong_table(fresh_db): def test_create_index_desc(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"name": "Cleo", "twitter": "cleopaws", "age": 3, "is good dog": True}) assert [] == dogs.indexes dogs.create_index([DescIndex("age"), "name"]) @@ -845,7 +854,7 @@ def test_create_index_desc(fresh_db): def test_create_index_find_unique_name(fresh_db): - table = fresh_db["t"] + table = fresh_db.table("t") table.insert({"id": 1}) table.create_index(["id"]) # Without find_unique_name should error @@ -860,12 +869,12 @@ def test_create_index_find_unique_name(fresh_db): def test_create_index_analyze(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") assert "sqlite_stat1" not in fresh_db.table_names() dogs.insert({"name": "Cleo", "twitter": "cleopaws"}) dogs.create_index(["name"], analyze=True) assert "sqlite_stat1" in fresh_db.table_names() - assert list(fresh_db["sqlite_stat1"].rows) == [ + assert list(fresh_db.table("sqlite_stat1").rows) == [ {"tbl": "dogs", "idx": "idx_dogs_name", "stat": "1 1"} ] @@ -887,14 +896,14 @@ def test_create_index_analyze(fresh_db): ), ) def test_insert_dictionaries_and_lists_as_json(fresh_db, data_structure): - fresh_db["test"].insert({"id": 1, "data": data_structure}, pk="id") + fresh_db.table("test").insert({"id": 1, "data": data_structure}, pk="id") row = fresh_db.execute("select id, data from test").fetchone() assert row[0] == 1 assert data_structure == json.loads(row[1]) def test_insert_list_nested_unicode(fresh_db): - fresh_db["test"].insert( + fresh_db.table("test").insert( {"id": 1, "data": {"key1": {"nested": ["cømplex"]}}}, pk="id" ) row = fresh_db.execute("select id, data from test").fetchone() @@ -903,33 +912,35 @@ def test_insert_list_nested_unicode(fresh_db): def test_insert_uuid(fresh_db): uuid4 = uuid.uuid4() - fresh_db["test"].insert({"uuid": uuid4}) - row = next(iter(fresh_db["test"].rows)) + fresh_db.table("test").insert({"uuid": uuid4}) + row = next(iter(fresh_db.table("test").rows)) assert {"uuid"} == row.keys() assert isinstance(row["uuid"], str) assert row["uuid"] == str(uuid4) def test_insert_memoryview(fresh_db): - fresh_db["test"].insert({"data": memoryview(b"hello")}) - row = next(iter(fresh_db["test"].rows)) + fresh_db.table("test").insert({"data": memoryview(b"hello")}) + row = next(iter(fresh_db.table("test").rows)) assert {"data"} == row.keys() assert isinstance(row["data"], bytes) assert row["data"] == b"hello" def test_insert_thousands_using_generator(fresh_db): - fresh_db["test"].insert_all({"i": i, "word": f"word_{i}"} for i in range(10000)) + fresh_db.table("test").insert_all( + {"i": i, "word": f"word_{i}"} for i in range(10000) + ) assert [{"name": "i", "type": "INTEGER"}, {"name": "word", "type": "TEXT"}] == [ - {"name": col.name, "type": col.type} for col in fresh_db["test"].columns + {"name": col.name, "type": col.type} for col in fresh_db.table("test").columns ] - assert fresh_db["test"].count == 10000 + assert fresh_db.table("test").count == 10000 def test_insert_thousands_raises_exception_with_extra_columns_after_first_100(fresh_db): # https://github.com/simonw/sqlite-utils/issues/139 with pytest.raises(Exception, match="table test has no column named extra"): - fresh_db["test"].insert_all( + fresh_db.table("test").insert_all( [{"i": i, "word": f"word_{i}"} for i in range(100)] + [{"i": 101, "extra": "This extra column should cause an exception"}], ) @@ -937,7 +948,7 @@ def test_insert_thousands_raises_exception_with_extra_columns_after_first_100(fr def test_insert_thousands_adds_extra_columns_after_first_100_with_alter(fresh_db): # https://github.com/simonw/sqlite-utils/issues/139 - fresh_db["test"].insert_all( + fresh_db.table("test").insert_all( [{"i": i, "word": f"word_{i}"} for i in range(100)] + [{"i": 101, "extra": "Should trigger ALTER"}], alter=True, @@ -953,12 +964,12 @@ def test_insert_all_pk_not_in_records_raises(fresh_db, num_rows): rows = [{"a": f"x{i}", "b": i} for i in range(num_rows)] with pytest.raises(InvalidColumns) as ex: - fresh_db["t"].insert_all(rows, pk="not_a_column") + fresh_db.table("t").insert_all(rows, pk="not_a_column") assert ex.value.args == ( "Invalid primary key column ['not_a_column'] for table t with columns ['a', 'b']", ) - assert fresh_db["t"].count == 0 + assert fresh_db.table("t").count == 0 @pytest.mark.parametrize("num_rows", (1, 2, 3, 10)) @@ -970,20 +981,20 @@ def test_insert_all_pk_not_in_records_alter_raises(fresh_db, num_rows): rows = [{"a": f"x{i}", "b": i} for i in range(num_rows)] with pytest.raises(InvalidColumns) as ex: - fresh_db["t"].insert_all(rows, pk="not_a_column", alter=True) + fresh_db.table("t").insert_all(rows, pk="not_a_column", alter=True) assert ex.value.args == ( "Invalid primary key column ['not_a_column'] for table t with columns ['a', 'b']", ) - assert fresh_db["t"].count == 0 + assert fresh_db.table("t").count == 0 def test_insert_pk_in_records_with_alter_adds_column(fresh_db): # 3.x allowed insert(pk=..., alter=True) to add the pk column from the # records - the InvalidColumns check must not fire in that case - fresh_db["t"].insert({"a": 1}) - fresh_db["t"].insert({"id": 5, "a": 2}, pk="id", alter=True) - assert fresh_db["t"].columns_dict.keys() == {"a", "id"} + fresh_db.table("t").insert({"a": 1}) + fresh_db.table("t").insert({"id": 5, "a": 2}, pk="id", alter=True) + assert fresh_db.table("t").columns_dict.keys() == {"a", "id"} assert list(fresh_db.query("select * from t order by a")) == [ {"a": 1, "id": None}, {"a": 2, "id": 5}, @@ -994,17 +1005,17 @@ def test_insert_all_invalid_pk_alter_empty_records_is_noop(fresh_db): # With alter=True the pk check needs record keys, so an empty iterator # returns without error - matching the 3.x no-op for empty inserts fresh_db.conn.execute("CREATE TABLE t (a TEXT)") - fresh_db["t"].insert_all([], pk="not_a_column", alter=True) - assert fresh_db["t"].count == 0 + fresh_db.table("t").insert_all([], pk="not_a_column", alter=True) + assert fresh_db.table("t").count == 0 def test_insert_ignore(fresh_db): - fresh_db["test"].insert({"id": 1, "bar": 2}, pk="id") + fresh_db.table("test").insert({"id": 1, "bar": 2}, pk="id") # Should raise an error if we try this again with pytest.raises(Exception, match="UNIQUE constraint failed"): - fresh_db["test"].insert({"id": 1, "bar": 2}, pk="id") + fresh_db.table("test").insert({"id": 1, "bar": 2}, pk="id") # Using ignore=True should cause our insert to be silently ignored - fresh_db["test"].insert({"id": 1, "bar": 3}, pk="id", ignore=True) + fresh_db.table("test").insert({"id": 1, "bar": 3}, pk="id", ignore=True) # Only one row, and it should be bar=2, not bar=3 rows = list(fresh_db.query("select * from test")) assert rows == [{"id": 1, "bar": 2}] @@ -1013,12 +1024,12 @@ def test_insert_ignore(fresh_db): def test_insert_ignore_reports_existing_row(fresh_db): # An ignored insert (row already exists) should point last_rowid and # last_pk at the existing conflicting row - see the Datasette insert API - fresh_db["docs"].insert({"id": 1, "title": "Exists"}, pk="id") + fresh_db.table("docs").insert({"id": 1, "title": "Exists"}, pk="id") # Insert a conflicting row with ignore=True and no explicit pk= - table = fresh_db["docs"].insert({"id": 1, "title": "One"}, ignore=True) + table = fresh_db.table("docs").insert({"id": 1, "title": "One"}, ignore=True) assert table.last_rowid == 1 assert table.last_pk == 1 - assert list(fresh_db["docs"].rows_where("rowid = ?", [table.last_rowid])) == [ + assert list(fresh_db.table("docs").rows_where("rowid = ?", [table.last_rowid])) == [ {"id": 1, "title": "Exists"} ] @@ -1029,51 +1040,51 @@ def test_pk_rowid_alias_on_rowid_table(fresh_db, rowid_alias, method): # rowid and its aliases are valid primary keys for a rowid table even # though they are not listed among the table's columns - see the Datasette # upsert API against tables without an explicit primary key - fresh_db["t"].insert({"title": "Hello"}) - assert fresh_db["t"].pks == ["rowid"] + fresh_db.table("t").insert({"title": "Hello"}) + assert fresh_db.table("t").pks == ["rowid"] record = {rowid_alias: 1, "title": "Updated"} if method == "upsert": - table = fresh_db["t"].upsert(record, pk=rowid_alias) + table = fresh_db.table("t").upsert(record, pk=rowid_alias) elif method == "insert_replace": - table = fresh_db["t"].insert(record, pk=rowid_alias, replace=True) + table = fresh_db.table("t").insert(record, pk=rowid_alias, replace=True) else: - table = fresh_db["t"].insert(record, pk=rowid_alias, ignore=True) + table = fresh_db.table("t").insert(record, pk=rowid_alias, ignore=True) assert table.last_pk == 1 expected_title = "Hello" if method == "insert_ignore" else "Updated" - assert list(fresh_db["t"].rows) == [{"title": expected_title}] + assert list(fresh_db.table("t").rows) == [{"title": expected_title}] def test_insert_ignore_reports_existing_row_compound_pk(fresh_db): # Compound primary key variant of the ignored-insert lookup - fresh_db["t"].insert_all([{"a": 1, "b": 2, "note": "first"}], pk=("a", "b")) - table = fresh_db["t"].insert( + fresh_db.table("t").insert_all([{"a": 1, "b": 2, "note": "first"}], pk=("a", "b")) + table = fresh_db.table("t").insert( {"a": 1, "b": 2, "note": "second"}, pk=("a", "b"), ignore=True ) assert table.last_pk == (1, 2) - assert list(fresh_db["t"].rows_where("rowid = ?", [table.last_rowid])) == [ + assert list(fresh_db.table("t").rows_where("rowid = ?", [table.last_rowid])) == [ {"a": 1, "b": 2, "note": "first"} ] def test_insert_ignore_reports_existing_row_list_mode(fresh_db): # List-based iteration variant of the ignored-insert lookup - fresh_db["t"].insert_all([["id", "title"], [1, "first"]], pk="id") - table = fresh_db["t"].insert_all( + fresh_db.table("t").insert_all([["id", "title"], [1, "first"]], pk="id") + table = fresh_db.table("t").insert_all( [["id", "title"], [1, "second"]], pk="id", ignore=True ) assert table.last_pk == 1 assert table.last_rowid == 1 - assert list(fresh_db["t"].rows) == [{"id": 1, "title": "first"}] + assert list(fresh_db.table("t").rows) == [{"id": 1, "title": "first"}] def test_insert_ignore_hash_id_reports_pk(fresh_db): # With hash_id the pk is the computed hash; the original record has no id # column to look up so last_rowid is left unset - first = fresh_db["dogs"].insert({"name": "Cleo"}, hash_id="id") - table = fresh_db["dogs"].insert({"name": "Cleo"}, hash_id="id", ignore=True) + first = fresh_db.table("dogs").insert({"name": "Cleo"}, hash_id="id") + table = fresh_db.table("dogs").insert({"name": "Cleo"}, hash_id="id", ignore=True) assert table.last_pk == first.last_pk assert table.last_rowid is None - assert fresh_db["dogs"].count == 1 + assert fresh_db.table("dogs").count == 1 def test_insert_ignore_unresolvable_conflict_leaves_pk_unset(fresh_db): @@ -1081,45 +1092,45 @@ def test_insert_ignore_unresolvable_conflict_leaves_pk_unset(fresh_db): # last_rowid are left unset rather than reporting a misleading value # rowid table with a UNIQUE column and no primary key: no pk to look up - fresh_db["u"].db.execute("create table u (title text unique)") - fresh_db["u"].insert({"title": "x"}) - table = fresh_db["u"].insert({"title": "x"}, ignore=True) + fresh_db.table("u").db.execute("create table u (title text unique)") + fresh_db.table("u").insert({"title": "x"}) + table = fresh_db.table("u").insert({"title": "x"}, ignore=True) assert table.last_pk is None assert table.last_rowid is None - assert fresh_db["u"].count == 1 + assert fresh_db.table("u").count == 1 # Conflict on a UNIQUE column other than the primary key: the pk value from # the record does not match the existing row, so the lookup finds nothing - fresh_db["docs"].db.execute( + fresh_db.table("docs").db.execute( "create table docs (id integer primary key, email text unique)" ) - fresh_db["docs"].insert({"id": 1, "email": "a"}, pk="id") - table = fresh_db["docs"].insert({"id": 2, "email": "a"}, ignore=True) + fresh_db.table("docs").insert({"id": 1, "email": "a"}, pk="id") + table = fresh_db.table("docs").insert({"id": 2, "email": "a"}, ignore=True) assert table.last_pk is None assert table.last_rowid is None - assert fresh_db["docs"].count == 1 + assert fresh_db.table("docs").count == 1 def test_insert_ignore_with_pk_after_other_table_insert(fresh_db): # https://github.com/simonw/sqlite-utils/issues/554 user = {"id": "abc", "name": "david"} - fresh_db["users"].insert(user, pk="id") - fresh_db["comments"].insert_all( + fresh_db.table("users").insert(user, pk="id") + fresh_db.table("comments").insert_all( [ {"id": "def", "text": "ok"}, {"id": "ghi", "text": "great"}, ], ) - table = fresh_db["users"].insert(user, pk="id", ignore=True) + table = fresh_db.table("users").insert(user, pk="id", ignore=True) assert table.last_pk == "abc" - assert list(fresh_db["users"].rows) == [user] + assert list(fresh_db.table("users").rows) == [user] def test_insert_hash_id(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") id = dogs.insert({"name": "Cleo", "twitter": "cleopaws"}, hash_id="id").last_pk assert "f501265970505d9825d8d9f590bfab3519fb20b1" == id assert dogs.count == 1 @@ -1137,7 +1148,7 @@ def test_insert_hash_id_columns(fresh_db, use_table_factory): dogs = fresh_db.table("dogs", hash_id_columns=("name", "twitter")) insert_kwargs = {} else: - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") insert_kwargs = {"hash_id_columns": ("name", "twitter")} id = dogs.insert( @@ -1158,26 +1169,26 @@ def test_insert_hash_id_columns(fresh_db, use_table_factory): def test_vacuum(fresh_db): - fresh_db["data"].insert({"foo": "foo", "bar": "bar"}) + fresh_db.table("data").insert({"foo": "foo", "bar": "bar"}) fresh_db.vacuum() def test_works_with_pathlib_path(tmpdir): path = pathlib.Path(tmpdir / "test.db") db = Database(path) - db["demo"].insert_all([{"foo": 1}]) - assert db["demo"].count == 1 + db.table("demo").insert_all([{"foo": 1}]) + assert db.table("demo").count == 1 @pytest.mark.skipif(pd is None, reason="pandas and numpy are not installed") def test_create_table_numpy(fresh_db): df = pd.DataFrame({"col 1": range(3), "col 2": range(3)}) - fresh_db["pandas"].insert_all(df.to_dict(orient="records")) + fresh_db.table("pandas").insert_all(df.to_dict(orient="records")) assert [ {"col 1": 0, "col 2": 0}, {"col 1": 1, "col 2": 1}, {"col 1": 2, "col 2": 2}, - ] == list(fresh_db["pandas"].rows) + ] == list(fresh_db.table("pandas").rows) # Now try all the different types df = pd.DataFrame( { @@ -1222,7 +1233,7 @@ def test_create_table_numpy(fresh_db): "float32", "float64", ] == [str(t) for t in df.dtypes] - fresh_db["types"].insert_all(df.to_dict(orient="records")) + fresh_db.table("types").insert_all(df.to_dict(orient="records")) assert [ { "np.float16": 16.5, @@ -1237,7 +1248,7 @@ def test_create_table_numpy(fresh_db): "np.uint64": 64, "np.uint8": 8, } - ] == list(fresh_db["types"].rows) + ] == list(fresh_db.table("types").rows) def test_cannot_provide_both_filename_and_memory(): @@ -1249,31 +1260,31 @@ def test_cannot_provide_both_filename_and_memory(): def test_creates_id_column(fresh_db): last_pk = fresh_db.table("cats", pk="id").insert({"name": "barry"}).last_pk - assert [{"name": "barry", "id": last_pk}] == list(fresh_db["cats"].rows) + assert [{"name": "barry", "id": last_pk}] == list(fresh_db.table("cats").rows) def test_drop(fresh_db): - fresh_db["t"].insert({"foo": 1}) + fresh_db.table("t").insert({"foo": 1}) assert ["t"] == fresh_db.table_names() - assert None is fresh_db["t"].drop() + assert None is fresh_db.table("t").drop() assert [] == fresh_db.table_names() def test_drop_view(fresh_db): fresh_db.create_view("foo_view", "select 1") assert ["foo_view"] == fresh_db.view_names() - assert None is fresh_db["foo_view"].drop() + assert None is fresh_db.view("foo_view").drop() assert [] == fresh_db.view_names() def test_drop_ignore(fresh_db): with pytest.raises(sqlite3.OperationalError): - fresh_db["does_not_exist"].drop() - fresh_db["does_not_exist"].drop(ignore=True) + fresh_db.table("does_not_exist").drop() + fresh_db.table("does_not_exist").drop(ignore=True) # Testing view is harder, we need to create it in order # to get a View object, then drop it twice fresh_db.create_view("foo_view", "select 1") - view = fresh_db["foo_view"] + view = fresh_db.view("foo_view") assert isinstance(view, View) view.drop() with pytest.raises(sqlite3.OperationalError): @@ -1282,16 +1293,16 @@ def test_drop_ignore(fresh_db): def test_insert_all_empty_list(fresh_db): - fresh_db["t"].insert({"foo": 1}) - assert fresh_db["t"].count == 1 - fresh_db["t"].insert_all([]) - assert fresh_db["t"].count == 1 - fresh_db["t"].insert_all([], replace=True) - assert fresh_db["t"].count == 1 + fresh_db.table("t").insert({"foo": 1}) + assert fresh_db.table("t").count == 1 + fresh_db.table("t").insert_all([]) + assert fresh_db.table("t").count == 1 + fresh_db.table("t").insert_all([], replace=True) + assert fresh_db.table("t").count == 1 def test_insert_all_single_column(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all([{"name": "Cleo"}], pk="name") assert [{"name": "Cleo"}] == list(table.rows) assert table.pks == ["name"] @@ -1299,31 +1310,33 @@ def test_insert_all_single_column(fresh_db): @pytest.mark.parametrize("method_name", ("insert_all", "upsert_all")) def test_insert_all_analyze(fresh_db, method_name): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all([{"id": 1, "name": "Cleo"}], pk="id") assert "sqlite_stat1" not in fresh_db.table_names() table.create_index(["name"], analyze=True) - assert list(fresh_db["sqlite_stat1"].rows) == [ + assert list(fresh_db.table("sqlite_stat1").rows) == [ {"tbl": "table", "idx": "idx_table_name", "stat": "1 1"} ] method = getattr(table, method_name) method([{"id": 2, "name": "Suna"}], pk="id", analyze=True) assert "sqlite_stat1" in fresh_db.table_names() - assert list(fresh_db["sqlite_stat1"].rows) == [ + assert list(fresh_db.table("sqlite_stat1").rows) == [ {"tbl": "table", "idx": "idx_table_name", "stat": "2 1"} ] def test_create_with_a_null_column(fresh_db): record = {"name": "Name", "description": None} - fresh_db["t"].insert(record) - assert [record] == list(fresh_db["t"].rows) + fresh_db.table("t").insert(record) + assert [record] == list(fresh_db.table("t").rows) def test_create_with_nested_bytes(fresh_db): record = {"id": 1, "data": {"foo": b"bytes"}} - fresh_db["t"].insert(record) - assert [{"id": 1, "data": '{"foo": "b\'bytes\'"}'}] == list(fresh_db["t"].rows) + fresh_db.table("t").insert(record) + assert [{"id": 1, "data": '{"foo": "b\'bytes\'"}'}] == list( + fresh_db.table("t").rows + ) @pytest.mark.parametrize( @@ -1361,7 +1374,7 @@ def test_create_table_sql(fresh_db, columns, expected_sql_middle): def test_create(fresh_db): - fresh_db["t"].create( + fresh_db.table("t").create( { "id": int, "text": str, @@ -1374,7 +1387,7 @@ def test_create(fresh_db): not_null=("float", "integer"), defaults={"integer": 0}, ) - assert fresh_db["t"].schema == ( + assert fresh_db.table("t").schema == ( 'CREATE TABLE "t" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "float" REAL NOT NULL,\n' @@ -1386,37 +1399,37 @@ def test_create(fresh_db): def test_create_if_not_exists(fresh_db): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should error with pytest.raises(sqlite3.OperationalError): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should not - fresh_db["t"].create({"id": int}, if_not_exists=True) + fresh_db.table("t").create({"id": int}, if_not_exists=True) def test_create_if_no_columns(fresh_db): with pytest.raises(ValueError) as error: - fresh_db["t"].create({}) + fresh_db.table("t").create({}) assert error.value.args[0] == "Tables must have at least one column" def test_create_ignore(fresh_db): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should error with pytest.raises(sqlite3.OperationalError): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should not - fresh_db["t"].create({"id": int}, ignore=True) + fresh_db.table("t").create({"id": int}, ignore=True) def test_create_replace(fresh_db): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should error with pytest.raises(sqlite3.OperationalError): - fresh_db["t"].create({"id": int}) + fresh_db.table("t").create({"id": int}) # This should not - fresh_db["t"].create({"name": str}, replace=True) - assert fresh_db["t"].schema == ('CREATE TABLE "t" (\n' ' "name" TEXT\n' ")") + fresh_db.table("t").create({"name": str}, replace=True) + assert fresh_db.table("t").schema == ('CREATE TABLE "t" (\n' ' "name" TEXT\n' ")") @pytest.mark.parametrize( @@ -1484,23 +1497,23 @@ def test_create_replace(fresh_db): ) def test_create_transform(fresh_db, cols, kwargs, expected_schema, should_transform): fresh_db.create_table("demo", {"id": int, "name": str}, pk="id") - fresh_db["demo"].insert({"id": 1, "name": "Cleo"}) + fresh_db.table("demo").insert({"id": 1, "name": "Cleo"}) traces = [] with fresh_db.tracer(lambda sql, parameters: traces.append((sql, parameters))): - fresh_db["demo"].create(cols, **kwargs, transform=True) + fresh_db.table("demo").create(cols, **kwargs, transform=True) at_least_one_create_table = any(sql.startswith("CREATE TABLE") for sql, _ in traces) assert should_transform == at_least_one_create_table - new_schema = fresh_db["demo"].schema + new_schema = fresh_db.table("demo").schema assert new_schema == expected_schema, repr(new_schema) - assert fresh_db["demo"].count == 1 + assert fresh_db.table("demo").count == 1 def test_rename_table(fresh_db): - fresh_db["t"].insert({"foo": "bar"}) + fresh_db.table("t").insert({"foo": "bar"}) assert ["t"] == fresh_db.table_names() fresh_db.rename_table("t", "renamed") assert ["renamed"] == fresh_db.table_names() - assert [{"foo": "bar"}] == list(fresh_db["renamed"].rows) + assert [{"foo": "bar"}] == list(fresh_db.table("renamed").rows) # Should error if table does not exist: with pytest.raises(sqlite3.OperationalError): fresh_db.rename_table("does_not_exist", "renamed") @@ -1527,7 +1540,7 @@ def test_database_strict_override(strict): ) @pytest.mark.parametrize("strict", (False, True)) def test_insert_upsert_strict(fresh_db, method_name, strict): - table = fresh_db["t"] + table = fresh_db.table("t") method = getattr(table, method_name) record = {"id": 1} if method_name.endswith("_all"): @@ -1550,7 +1563,7 @@ def test_create_table_strict(fresh_db, strict): @pytest.mark.parametrize("strict", (False, True)) def test_create_strict(fresh_db, strict): - table = fresh_db["t"] + table = fresh_db.table("t") table.create({"id": int}, strict=strict) assert table.strict == strict or not fresh_db.supports_strict @@ -1575,7 +1588,7 @@ def test_bad_table_and_view_exceptions(fresh_db): def test_pk_persists_after_insert_655(fresh_db): """When pk is passed to insert(), subsequent inserts should use it.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.insert({"id": 1, "name": "Alice"}, pk="id") # Second insert should use pk="id" from _defaults table.insert({"id": 2, "name": "Bob"}) @@ -1586,7 +1599,7 @@ def test_pk_persists_after_insert_655(fresh_db): def test_pk_persists_after_insert_all_655(fresh_db): """When pk is passed to insert_all(), subsequent inserts should use it.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.insert_all([{"id": 1, "name": "Alice"}], pk="id") # Second insert_all should use pk="id" from _defaults table.insert_all([{"id": 2, "name": "Bob"}]) @@ -1596,7 +1609,7 @@ def test_pk_persists_after_insert_all_655(fresh_db): def test_pk_persists_after_create_655(fresh_db): """When pk is passed to create(), it should be stored in _defaults.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.create({"id": int, "name": str}, pk="id") assert table._defaults["pk"] == "id" # Subsequent insert should use the pk @@ -1607,8 +1620,8 @@ def test_pk_persists_after_create_655(fresh_db): def test_foreign_keys_persist_after_create_655(fresh_db): """When foreign_keys is passed to create(), it should be stored in _defaults.""" - fresh_db["authors"].insert({"id": 1, "name": "Alice"}, pk="id") - table = fresh_db["books"] + fresh_db.table("authors").insert({"id": 1, "name": "Alice"}, pk="id") + table = fresh_db.table("books") table.create( {"id": int, "title": str, "author_id": int}, pk="id", @@ -1620,28 +1633,28 @@ def test_foreign_keys_persist_after_create_655(fresh_db): def test_not_null_persists_after_create_655(fresh_db): """When not_null is passed to create(), it should be stored in _defaults.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.create({"id": int, "name": str}, pk="id", not_null=["name"]) assert table._defaults["not_null"] == ["name"] def test_defaults_persist_after_create_655(fresh_db): """When defaults is passed to create(), it should be stored in _defaults.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.create({"id": int, "score": int}, pk="id", defaults={"score": 0}) assert table._defaults["defaults"] == {"score": 0} def test_strict_persists_after_create_655(fresh_db): """When strict is passed to create(), it should be stored in _defaults.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.create({"id": int, "name": str}, pk="id", strict=True) assert table._defaults["strict"] is True def test_upsert_uses_pk_from_prior_insert_655(fresh_db): """After insert with pk, upsert should use the same pk.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.insert({"id": 1, "name": "Alice"}, pk="id") # Upsert should work without specifying pk again table.upsert({"id": 1, "name": "Alice Updated"}) @@ -1651,7 +1664,7 @@ def test_upsert_uses_pk_from_prior_insert_655(fresh_db): def test_upsert_all_uses_pk_from_prior_insert_655(fresh_db): """After insert with pk, upsert_all should use the same pk.""" - table = fresh_db["users"] + table = fresh_db.table("users") table.insert({"id": 1, "name": "Alice"}, pk="id") # Upsert_all should work without specifying pk again table.upsert_all([{"id": 1, "name": "Alice Updated"}, {"id": 2, "name": "Bob"}]) diff --git a/tests/test_default_value.py b/tests/test_default_value.py index 2815180..02b28c3 100644 --- a/tests/test_default_value.py +++ b/tests/test_default_value.py @@ -32,9 +32,9 @@ EXAMPLES = [ @pytest.mark.parametrize("column_def,initial_value,expected_value", EXAMPLES) def test_quote_default_value(fresh_db, column_def, initial_value, expected_value): fresh_db.execute(f"create table foo (col {column_def})") - assert initial_value == fresh_db["foo"].columns[0].default_value + assert initial_value == fresh_db.table("foo").columns[0].default_value assert expected_value == fresh_db.quote_default_value( - fresh_db["foo"].columns[0].default_value + fresh_db.table("foo").columns[0].default_value ) @@ -48,7 +48,7 @@ def test_insert_empty_record_uses_default_values(fresh_db): ) """) - table = fresh_db["has_defaults"] + table = fresh_db.table("has_defaults") table.insert({}) rows = list(table.rows) diff --git a/tests/test_delete.py b/tests/test_delete.py index dffb6bb..a9341b8 100644 --- a/tests/test_delete.py +++ b/tests/test_delete.py @@ -2,7 +2,7 @@ import sqlite_utils def test_delete_rowid_table(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"foo": 1}) rowid = table.insert({"foo": 2}).last_pk table.delete(rowid) @@ -10,7 +10,7 @@ def test_delete_rowid_table(fresh_db): def test_delete_pk_table(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"id": 1}, pk="id") table.insert({"id": 2}, pk="id") table.delete(1) @@ -18,7 +18,7 @@ def test_delete_pk_table(fresh_db): def test_delete_where(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") for i in range(1, 11): table.insert({"id": i}, pk="id") assert table.count == 10 @@ -27,7 +27,7 @@ def test_delete_where(fresh_db): def test_delete_where_all(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") for i in range(1, 11): table.insert({"id": i}, pk="id") assert table.count == 10 @@ -38,27 +38,27 @@ def test_delete_where_all(fresh_db): def test_delete_where_commits(tmpdir): path = str(tmpdir / "test.db") db = sqlite_utils.Database(path) - db["table"].insert_all([{"id": i} for i in range(5)], pk="id") - db["table"].delete_where("id > ?", [2]) + db.table("table").insert_all([{"id": i} for i in range(5)], pk="id") + db.table("table").delete_where("id > ?", [2]) # The connection must not be left inside an open transaction, # otherwise subsequent atomic() blocks never commit either assert not db.conn.in_transaction - db["table"].insert({"id": 100}) + db.table("table").insert({"id": 100}) db.close() db2 = sqlite_utils.Database(path) - assert [r["id"] for r in db2["table"].rows] == [0, 1, 2, 100] + assert [r["id"] for r in db2.table("table").rows] == [0, 1, 2, 100] db2.close() def test_delete_where_analyze(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert_all(({"id": i, "i": i} for i in range(10)), pk="id") table.create_index(["i"], analyze=True) assert "sqlite_stat1" in fresh_db.table_names() - assert list(fresh_db["sqlite_stat1"].rows) == [ + assert list(fresh_db.table("sqlite_stat1").rows) == [ {"tbl": "table", "idx": "idx_table_i", "stat": "10 1"} ] table.delete_where("id > ?", [5], analyze=True) - assert list(fresh_db["sqlite_stat1"].rows) == [ + assert list(fresh_db.table("sqlite_stat1").rows) == [ {"tbl": "table", "idx": "idx_table_i", "stat": "6 1"} ] diff --git a/tests/test_duplicate.py b/tests/test_duplicate.py index ad853a5..c7a5612 100644 --- a/tests/test_duplicate.py +++ b/tests/test_duplicate.py @@ -22,7 +22,7 @@ def test_duplicate(fresh_db): "bool_col": True, "datetime_col": str(dt), } - table1 = fresh_db["table1"] + table1 = fresh_db.table("table1") row_id = table1.insert(data).last_rowid # Duplicate table: table2 = table1.duplicate("table2") @@ -40,4 +40,4 @@ def test_duplicate(fresh_db): def test_duplicate_fails_if_table_does_not_exist(fresh_db): with pytest.raises(NoTable): - fresh_db["not_a_table"].duplicate("duplicated") + fresh_db.table("not_a_table").duplicate("duplicated") diff --git a/tests/test_enable_counts.py b/tests/test_enable_counts.py index 71a8936..1230b6c 100644 --- a/tests/test_enable_counts.py +++ b/tests/test_enable_counts.py @@ -5,7 +5,7 @@ from sqlite_utils import Database, cli def test_enable_counts_specific_table(fresh_db): - foo = fresh_db["foo"] + foo = fresh_db.table("foo") assert fresh_db.table_names() == [] for i in range(10): foo.insert({"name": f"item {i}"}) @@ -41,24 +41,24 @@ def test_enable_counts_specific_table(fresh_db): ), } assert fresh_db.table_names() == ["foo", "_counts"] - assert list(fresh_db["_counts"].rows) == [{"count": 10, "table": "foo"}] + assert list(fresh_db.table("_counts").rows) == [{"count": 10, "table": "foo"}] # Add some items to test the triggers for i in range(5): foo.insert({"name": f"item {10 + i}"}) assert foo.count == 15 - assert list(fresh_db["_counts"].rows) == [{"count": 15, "table": "foo"}] + assert list(fresh_db.table("_counts").rows) == [{"count": 15, "table": "foo"}] # Delete some items foo.delete_where("rowid < 7") assert foo.count == 9 - assert list(fresh_db["_counts"].rows) == [{"count": 9, "table": "foo"}] + assert list(fresh_db.table("_counts").rows) == [{"count": 9, "table": "foo"}] foo.delete_where() assert foo.count == 0 - assert list(fresh_db["_counts"].rows) == [{"count": 0, "table": "foo"}] + assert list(fresh_db.table("_counts").rows) == [{"count": 0, "table": "foo"}] def test_enable_counts_all_tables(fresh_db): - foo = fresh_db["foo"] - bar = fresh_db["bar"] + foo = fresh_db.table("foo") + bar = fresh_db.table("bar") foo.insert({"name": "Cleo"}) bar.insert({"name": "Cleo"}) foo.enable_fts(["name"]) @@ -73,7 +73,7 @@ def test_enable_counts_all_tables(fresh_db): "foo_fts_config", "_counts", } - assert list(fresh_db["_counts"].rows) == [ + assert list(fresh_db.table("_counts").rows) == [ {"count": 1, "table": "foo"}, {"count": 1, "table": "bar"}, {"count": 3, "table": "foo_fts_data"}, @@ -87,10 +87,10 @@ def test_enable_counts_all_tables(fresh_db): def counts_db_path(tmpdir): path = str(tmpdir / "test.db") db = Database(path) - db["foo"].insert({"name": "bar"}) - db["bar"].insert({"name": "bar"}) - db["bar"].insert({"name": "bar"}) - db["baz"].insert({"name": "bar"}) + db.table("foo").insert({"name": "bar"}) + db.table("bar").insert({"name": "bar"}) + db.table("bar").insert({"name": "bar"}) + db.table("baz").insert({"name": "bar"}) return path @@ -163,25 +163,25 @@ def test_uses_counts_after_enable_counts(counts_db_path): def test_reset_counts(counts_db_path): db = Database(counts_db_path) - db["foo"].enable_counts() - db["bar"].enable_counts() + db.table("foo").enable_counts() + db.table("bar").enable_counts() assert db.cached_counts() == {"foo": 1, "bar": 2} # Corrupt the value - db["_counts"].update("foo", {"count": 3}) + db.table("_counts").update("foo", {"count": 3}) assert db.cached_counts() == {"foo": 3, "bar": 2} - assert db["foo"].count == 3 + assert db.table("foo").count == 3 # Reset them db.reset_counts() assert db.cached_counts() == {"foo": 1, "bar": 2} - assert db["foo"].count == 1 + assert db.table("foo").count == 1 def test_reset_counts_cli(counts_db_path): db = Database(counts_db_path) - db["foo"].enable_counts() - db["bar"].enable_counts() + db.table("foo").enable_counts() + db.table("bar").enable_counts() assert db.cached_counts() == {"foo": 1, "bar": 2} - db["_counts"].update("foo", {"count": 3}) + db.table("_counts").update("foo", {"count": 3}) result = CliRunner().invoke(cli.cli, ["reset-counts", counts_db_path]) assert result.exit_code == 0 assert db.cached_counts() == {"foo": 1, "bar": 2} diff --git a/tests/test_extract.py b/tests/test_extract.py index 915e6e1..72579c4 100644 --- a/tests/test_extract.py +++ b/tests/test_extract.py @@ -11,7 +11,7 @@ def test_extract_single_column(fresh_db, table, fk_column): expected_table = table or "species" expected_fk = fk_column or f"{expected_table}_id" iter_species = itertools.cycle(["Palm", "Spruce", "Mangrove", "Oak"]) - fresh_db["tree"].insert_all( + fresh_db.table("tree").insert_all( ( { "id": i, @@ -23,8 +23,8 @@ def test_extract_single_column(fresh_db, table, fk_column): ), pk="id", ) - fresh_db["tree"].extract("species", table=table, fk_column=fk_column) - assert fresh_db["tree"].schema == ( + fresh_db.table("tree").extract("species", table=table, fk_column=fk_column) + assert fresh_db.table("tree").schema == ( 'CREATE TABLE "tree" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "name" TEXT,\n' @@ -32,18 +32,18 @@ def test_extract_single_column(fresh_db, table, fk_column): + ' "end" INTEGER\n' + ")" ) - assert fresh_db[expected_table].schema == ( + assert fresh_db.table(expected_table).schema == ( f'CREATE TABLE "{expected_table}" (\n' + ' "id" INTEGER PRIMARY KEY,\n' ' "species" TEXT\n' ")" ) - assert list(fresh_db[expected_table].rows) == [ + assert list(fresh_db.table(expected_table).rows) == [ {"id": 1, "species": "Palm"}, {"id": 2, "species": "Spruce"}, {"id": 3, "species": "Mangrove"}, {"id": 4, "species": "Oak"}, ] - assert list(itertools.islice(fresh_db["tree"].rows, 0, 4)) == [ + assert list(itertools.islice(fresh_db.table("tree").rows, 0, 4)) == [ {"id": 1, "name": "Tree 1", expected_fk: 1, "end": 1}, {"id": 2, "name": "Tree 2", expected_fk: 2, "end": 1}, {"id": 3, "name": "Tree 3", expected_fk: 3, "end": 1}, @@ -54,7 +54,7 @@ def test_extract_single_column(fresh_db, table, fk_column): def test_extract_multiple_columns_with_rename(fresh_db): iter_common = itertools.cycle(["Palm", "Spruce", "Mangrove", "Oak"]) iter_latin = itertools.cycle(["Arecaceae", "Picea", "Rhizophora", "Quercus"]) - fresh_db["tree"].insert_all( + fresh_db.table("tree").insert_all( ( { "id": i, @@ -67,30 +67,30 @@ def test_extract_multiple_columns_with_rename(fresh_db): pk="id", ) - fresh_db["tree"].extract( + fresh_db.table("tree").extract( ["common_name", "latin_name"], rename={"common_name": "name"} ) - assert fresh_db["tree"].schema == ( + assert fresh_db.table("tree").schema == ( 'CREATE TABLE "tree" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "name" TEXT,\n' ' "common_name_latin_name_id" INTEGER REFERENCES "common_name_latin_name"("id")\n' ")" ) - assert fresh_db["common_name_latin_name"].schema == ( + assert fresh_db.table("common_name_latin_name").schema == ( 'CREATE TABLE "common_name_latin_name" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "name" TEXT,\n' ' "latin_name" TEXT\n' ")" ) - assert list(fresh_db["common_name_latin_name"].rows) == [ + assert list(fresh_db.table("common_name_latin_name").rows) == [ {"name": "Palm", "id": 1, "latin_name": "Arecaceae"}, {"name": "Spruce", "id": 2, "latin_name": "Picea"}, {"name": "Mangrove", "id": 3, "latin_name": "Rhizophora"}, {"name": "Oak", "id": 4, "latin_name": "Quercus"}, ] - assert list(itertools.islice(fresh_db["tree"].rows, 0, 4)) == [ + assert list(itertools.islice(fresh_db.table("tree").rows, 0, 4)) == [ {"id": 1, "name": "Tree 1", "common_name_latin_name_id": 1}, {"id": 2, "name": "Tree 2", "common_name_latin_name_id": 2}, {"id": 3, "name": "Tree 3", "common_name_latin_name_id": 3}, @@ -99,7 +99,7 @@ def test_extract_multiple_columns_with_rename(fresh_db): def test_extract_invalid_columns(fresh_db): - fresh_db["tree"].insert( + fresh_db.table("tree").insert( { "id": 1, "name": "Tree 1", @@ -109,19 +109,19 @@ def test_extract_invalid_columns(fresh_db): pk="id", ) with pytest.raises(InvalidColumns): - fresh_db["tree"].extract(["bad_column"]) + fresh_db.table("tree").extract(["bad_column"]) def test_extract_rowid_table(fresh_db): - fresh_db["tree"].insert( + fresh_db.table("tree").insert( { "name": "Tree 1", "common_name": "Palm", "latin_name": "Arecaceae", } ) - fresh_db["tree"].extract(["common_name", "latin_name"]) - assert fresh_db["tree"].schema == ( + fresh_db.table("tree").extract(["common_name", "latin_name"]) + assert fresh_db.table("tree").schema == ( 'CREATE TABLE "tree" (\n' ' "name" TEXT,\n' ' "common_name_latin_name_id" INTEGER REFERENCES "common_name_latin_name"("id")\n' @@ -139,68 +139,68 @@ def test_extract_rowid_table(fresh_db): def test_reuse_lookup_table(fresh_db): - fresh_db["species"].insert({"id": 1, "name": "Wolf"}, pk="id") - fresh_db["sightings"].insert({"id": 10, "species": "Wolf"}, pk="id") - fresh_db["individuals"].insert( + fresh_db.table("species").insert({"id": 1, "name": "Wolf"}, pk="id") + fresh_db.table("sightings").insert({"id": 10, "species": "Wolf"}, pk="id") + fresh_db.table("individuals").insert( {"id": 10, "name": "Terriana", "species": "Fox"}, pk="id" ) - fresh_db["sightings"].extract("species", rename={"species": "name"}) - fresh_db["individuals"].extract("species", rename={"species": "name"}) - assert fresh_db["sightings"].schema == ( + fresh_db.table("sightings").extract("species", rename={"species": "name"}) + fresh_db.table("individuals").extract("species", rename={"species": "name"}) + assert fresh_db.table("sightings").schema == ( 'CREATE TABLE "sightings" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "species_id" INTEGER REFERENCES "species"("id")\n' ")" ) - assert fresh_db["individuals"].schema == ( + assert fresh_db.table("individuals").schema == ( 'CREATE TABLE "individuals" (\n' ' "id" INTEGER PRIMARY KEY,\n' ' "name" TEXT,\n' ' "species_id" INTEGER REFERENCES "species"("id")\n' ")" ) - assert list(fresh_db["species"].rows) == [ + assert list(fresh_db.table("species").rows) == [ {"id": 1, "name": "Wolf"}, {"id": 2, "name": "Fox"}, ] def test_extract_error_on_incompatible_existing_lookup_table(fresh_db): - fresh_db["species"].insert({"id": 1}) - fresh_db["tree"].insert({"name": "Tree 1", "common_name": "Palm"}) + fresh_db.table("species").insert({"id": 1}) + fresh_db.table("tree").insert({"name": "Tree 1", "common_name": "Palm"}) with pytest.raises(InvalidColumns): - fresh_db["tree"].extract("common_name", table="species") + fresh_db.table("tree").extract("common_name", table="species") # Try again with incompatible existing column type - fresh_db["species2"].insert({"id": 1, "common_name": 3.5}) + fresh_db.table("species2").insert({"id": 1, "common_name": 3.5}) with pytest.raises(InvalidColumns): - fresh_db["tree"].extract("common_name", table="species2") + fresh_db.table("tree").extract("common_name", table="species2") def test_extract_works_with_null_values(fresh_db): - fresh_db["listens"].insert_all( + fresh_db.table("listens").insert_all( [ {"id": 1, "track_title": "foo", "album_title": "bar"}, {"id": 2, "track_title": "baz", "album_title": None}, ], pk="id", ) - fresh_db["listens"].extract( + fresh_db.table("listens").extract( columns=["album_title"], table="albums", fk_column="album_id" ) - assert list(fresh_db["listens"].rows) == [ + assert list(fresh_db.table("listens").rows) == [ {"id": 1, "track_title": "foo", "album_id": 1}, {"id": 2, "track_title": "baz", "album_id": None}, ] - assert list(fresh_db["albums"].rows) == [ + assert list(fresh_db.table("albums").rows) == [ {"id": 1, "album_title": "bar"}, ] def test_extract_null_values_single_column(fresh_db): # https://github.com/simonw/sqlite-utils/issues/186 - fresh_db["species"].insert({"id": 1, "species": "Wolf"}, pk="id") - fresh_db["individuals"].insert_all( + fresh_db.table("species").insert({"id": 1, "species": "Wolf"}, pk="id") + fresh_db.table("individuals").insert_all( [ {"id": 10, "name": "Terriana", "species": "Fox"}, {"id": 11, "name": "Spenidorm", "species": None}, @@ -210,13 +210,13 @@ def test_extract_null_values_single_column(fresh_db): ], pk="id", ) - fresh_db["individuals"].extract("species") + fresh_db.table("individuals").extract("species") # No null row should have been added to species - assert list(fresh_db["species"].rows) == [ + assert list(fresh_db.table("species").rows) == [ {"id": 1, "species": "Wolf"}, {"id": 2, "species": "Fox"}, ] - assert list(fresh_db["individuals"].rows) == [ + assert list(fresh_db.table("individuals").rows) == [ {"id": 10, "name": "Terriana", "species_id": 2}, {"id": 11, "name": "Spenidorm", "species_id": None}, {"id": 12, "name": "Grantheim", "species_id": 1}, @@ -228,7 +228,7 @@ def test_extract_null_values_single_column(fresh_db): def test_extract_null_values_multiple_columns(fresh_db): # A row should be extracted if at least one column is not null - # only rows where ALL extracted columns are null are left alone - fresh_db["circulation"].insert_all( + fresh_db.table("circulation").insert_all( [ {"id": 1, "title": "title one", "creator": "creator one", "year": 2018}, {"id": 2, "title": "title two", "creator": None, "year": 2019}, @@ -237,14 +237,14 @@ def test_extract_null_values_multiple_columns(fresh_db): ], pk="id", ) - fresh_db["circulation"].extract( + fresh_db.table("circulation").extract( ["title", "creator"], table="books", fk_column="book_id" ) - assert list(fresh_db["books"].rows) == [ + assert list(fresh_db.table("books").rows) == [ {"id": 1, "title": "title one", "creator": "creator one"}, {"id": 2, "title": "title two", "creator": None}, ] - assert list(fresh_db["circulation"].rows) == [ + assert list(fresh_db.table("circulation").rows) == [ {"id": 1, "book_id": 1, "year": 2018}, {"id": 2, "book_id": 2, "year": 2019}, {"id": 3, "book_id": None, "year": 2020}, @@ -255,20 +255,20 @@ def test_extract_null_values_multiple_columns(fresh_db): def test_extract_null_values_existing_lookup_table_with_null_row(fresh_db): # Even if the lookup table already contains an all-null row, rows where # every extracted column is null should keep a null foreign key - fresh_db["species"].insert({"id": 1, "species": None}, pk="id") - fresh_db["individuals"].insert_all( + fresh_db.table("species").insert({"id": 1, "species": None}, pk="id") + fresh_db.table("individuals").insert_all( [ {"id": 10, "name": "Terriana", "species": "Fox"}, {"id": 11, "name": "Spenidorm", "species": None}, ], pk="id", ) - fresh_db["individuals"].extract("species") - assert list(fresh_db["species"].rows) == [ + fresh_db.table("individuals").extract("species") + assert list(fresh_db.table("species").rows) == [ {"id": 1, "species": None}, {"id": 2, "species": "Fox"}, ] - assert list(fresh_db["individuals"].rows) == [ + assert list(fresh_db.table("individuals").rows) == [ {"id": 10, "name": "Terriana", "species_id": 2}, {"id": 11, "name": "Spenidorm", "species_id": None}, ] @@ -279,17 +279,19 @@ def test_extract_repeated_into_shared_lookup_with_nulls(fresh_db): # cannot dedupe NULL-containing rows against the existing lookup # table - extracting a second table into the same lookup previously # inserted duplicate rows that nothing pointed to - fresh_db["t1"].insert_all( + fresh_db.table("t1").insert_all( [ {"id": 1, "species": None, "common": "X"}, {"id": 2, "species": "Oak", "common": "Oak"}, ], pk="id", ) - fresh_db["t2"].insert_all([{"id": 1, "species": None, "common": "X"}], pk="id") - fresh_db["t1"].extract(["species", "common"], table="lk") - fresh_db["t2"].extract(["species", "common"], table="lk") - assert fresh_db["lk"].count == 2 + fresh_db.table("t2").insert_all( + [{"id": 1, "species": None, "common": "X"}], pk="id" + ) + fresh_db.table("t1").extract(["species", "common"], table="lk") + fresh_db.table("t2").extract(["species", "common"], table="lk") + assert fresh_db.table("lk").count == 2 # Both tables point at the same lookup row t1_fk = fresh_db.execute("select lk_id from t1 where id = 1").fetchone()[0] t2_fk = fresh_db.execute("select lk_id from t2 where id = 1").fetchone()[0] @@ -298,8 +300,8 @@ def test_extract_repeated_into_shared_lookup_with_nulls(fresh_db): def test_extract_repeated_into_shared_lookup_no_nulls(fresh_db): # Non-NULL rows were already deduped by the unique index - keep it so - fresh_db["t1"].insert_all([{"id": 1, "species": "Oak"}], pk="id") - fresh_db["t2"].insert_all([{"id": 1, "species": "Oak"}], pk="id") - fresh_db["t1"].extract(["species"], table="lk") - fresh_db["t2"].extract(["species"], table="lk") - assert fresh_db["lk"].count == 1 + fresh_db.table("t1").insert_all([{"id": 1, "species": "Oak"}], pk="id") + fresh_db.table("t2").insert_all([{"id": 1, "species": "Oak"}], pk="id") + fresh_db.table("t1").extract(["species"], table="lk") + fresh_db.table("t2").extract(["species"], table="lk") + assert fresh_db.table("lk").count == 1 diff --git a/tests/test_extracts.py b/tests/test_extracts.py index 9519b91..4e7cf39 100644 --- a/tests/test_extracts.py +++ b/tests/test_extracts.py @@ -32,15 +32,15 @@ def test_extracts(fresh_db, kwargs, expected_table, use_table_factory): assert {expected_table, "Trees"} == set(fresh_db.table_names()) assert ( f'CREATE TABLE "{expected_table}" (\n "id" INTEGER PRIMARY KEY,\n "value" TEXT\n)' - == fresh_db[expected_table].schema + == fresh_db.table(expected_table).schema ) assert ( f'CREATE TABLE "Trees" (\n "id" INTEGER,\n "species_id" INTEGER REFERENCES "{expected_table}"("id")\n)' - == fresh_db["Trees"].schema + == fresh_db.table("Trees").schema ) # Should have a foreign key reference - assert len(fresh_db["Trees"].foreign_keys) == 1 - fk = fresh_db["Trees"].foreign_keys[0] + assert len(fresh_db.table("Trees").foreign_keys) == 1 + fk = fresh_db.table("Trees").foreign_keys[0] assert fk.table == "Trees" assert fk.column == "species_id" @@ -54,22 +54,22 @@ def test_extracts(fresh_db, kwargs, expected_table, use_table_factory): partial=0, columns=["value"], ) - ] == fresh_db[expected_table].indexes + ] == fresh_db.table(expected_table).indexes # Finally, check the rows assert [{"id": 1, "value": "Oak"}, {"id": 2, "value": "Palm"}] == list( - fresh_db[expected_table].rows + fresh_db.table(expected_table).rows ) assert [ {"id": 1, "species_id": 1}, {"id": 2, "species_id": 1}, {"id": 3, "species_id": 2}, - ] == list(fresh_db["Trees"].rows) + ] == list(fresh_db.table("Trees").rows) def test_extracts_null_values(fresh_db): # https://github.com/simonw/sqlite-utils/issues/186 # Null values should stay null, not be extracted into the lookup table - fresh_db["Trees"].insert_all( + fresh_db.table("Trees").insert_all( [ {"id": 1, "species_id": "Oak"}, {"id": 2, "species_id": None}, @@ -78,11 +78,11 @@ def test_extracts_null_values(fresh_db): ], extracts={"species_id": "Species"}, ) - assert list(fresh_db["Species"].rows) == [ + assert list(fresh_db.table("Species").rows) == [ {"id": 1, "value": "Oak"}, {"id": 2, "value": "Palm"}, ] - assert list(fresh_db["Trees"].rows) == [ + assert list(fresh_db.table("Trees").rows) == [ {"id": 1, "species_id": 1}, {"id": 2, "species_id": None}, {"id": 3, "species_id": 2}, @@ -92,7 +92,7 @@ def test_extracts_null_values(fresh_db): def test_extracts_null_values_list_mode(fresh_db): # Same as test_extracts_null_values but for list-based records - fresh_db["Trees"].insert_all( + fresh_db.table("Trees").insert_all( [ ["id", "species_id"], [1, "Oak"], @@ -102,11 +102,11 @@ def test_extracts_null_values_list_mode(fresh_db): ], extracts={"species_id": "Species"}, ) - assert list(fresh_db["Species"].rows) == [ + assert list(fresh_db.table("Species").rows) == [ {"id": 1, "value": "Oak"}, {"id": 2, "value": "Palm"}, ] - assert list(fresh_db["Trees"].rows) == [ + assert list(fresh_db.table("Trees").rows) == [ {"id": 1, "species_id": 1}, {"id": 2, "species_id": None}, {"id": 3, "species_id": 2}, diff --git a/tests/test_foreign_keys.py b/tests/test_foreign_keys.py index 45f4f35..271125c 100644 --- a/tests/test_foreign_keys.py +++ b/tests/test_foreign_keys.py @@ -32,7 +32,7 @@ def compound_db(): def test_compound_foreign_key(compound_db): - fks = compound_db["courses"].foreign_keys + fks = compound_db.table("courses").foreign_keys assert len(fks) == 1 fk = fks[0] assert fk.is_compound is True @@ -46,10 +46,10 @@ def test_compound_foreign_key(compound_db): def test_single_foreign_key_gets_columns_fields(fresh_db): - fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - fresh_db["books"].insert({"title": "Hedgehogs", "author_id": 1}) - fresh_db["books"].add_foreign_key("author_id", "authors", "id") - fk = fresh_db["books"].foreign_keys[0] + fresh_db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + fresh_db.table("books").insert({"title": "Hedgehogs", "author_id": 1}) + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") + fk = fresh_db.table("books").foreign_keys[0] assert fk.is_compound is False assert fk.column == "author_id" assert fk.other_column == "id" @@ -60,10 +60,10 @@ def test_single_foreign_key_gets_columns_fields(fresh_db): def test_foreign_key_no_longer_unpacks_as_tuple(fresh_db): # Clean break in 4.0: ForeignKey is a dataclass, not a namedtuple, so the # old tuple unpacking and indexing patterns now fail hard. - fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - fresh_db["books"].insert({"title": "Hedgehogs", "author_id": 1}) - fresh_db["books"].add_foreign_key("author_id", "authors", "id") - fk = fresh_db["books"].foreign_keys[0] + fresh_db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + fresh_db.table("books").insert({"title": "Hedgehogs", "author_id": 1}) + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") + fk = fresh_db.table("books").foreign_keys[0] with pytest.raises(TypeError): _table, _column, _other_table, _other_column = fk with pytest.raises(TypeError): @@ -71,16 +71,18 @@ def test_foreign_key_no_longer_unpacks_as_tuple(fresh_db): def test_foreign_keys_are_sortable(fresh_db): - fresh_db["authors"].insert({"id": 1, "name": "Sally"}, pk="id") - fresh_db["categories"].insert({"id": 1, "name": "Wildlife"}, pk="id") - fresh_db["books"].insert({"title": "Hedgehogs", "author_id": 1, "category_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Sally"}, pk="id") + fresh_db.table("categories").insert({"id": 1, "name": "Wildlife"}, pk="id") + fresh_db.table("books").insert( + {"title": "Hedgehogs", "author_id": 1, "category_id": 1} + ) fresh_db.add_foreign_keys( [ ("books", "author_id", "authors", "id"), ("books", "category_id", "categories", "id"), ] ) - fks = sorted(fresh_db["books"].foreign_keys) + fks = sorted(fresh_db.table("books").foreign_keys) assert fks[0].column == "author_id" assert fks[1].column == "category_id" @@ -105,7 +107,7 @@ def test_mixed_compound_and_single_foreign_keys_are_sortable(): REFERENCES departments(campus_name, dept_code) ); """) - fks = db["courses"].foreign_keys + fks = db.table("courses").foreign_keys assert len(fks) == 2 assert {fk.is_compound for fk in fks} == {True, False} fks_sorted = sorted(fks) @@ -163,8 +165,8 @@ def test_create_table_with_compound_foreign_key(departments_db, foreign_keys): pk="course_code", foreign_keys=foreign_keys, ) - assert departments_db["courses"].schema == EXPECTED_COURSES_SCHEMA - fks = departments_db["courses"].foreign_keys + assert departments_db.table("courses").schema == EXPECTED_COURSES_SCHEMA + fks = departments_db.table("courses").foreign_keys assert len(fks) == 1 fk = fks[0] assert fk.is_compound is True @@ -181,10 +183,10 @@ def test_create_table_compound_foreign_key_enforced(departments_db): pk="course_code", foreign_keys=[(("campus_name", "dept_code"), "departments")], ) - departments_db["departments"].insert( + departments_db.table("departments").insert( {"campus_name": "Berkeley", "dept_code": "CS", "dept_name": "Computer Science"} ) - departments_db["courses"].insert( + departments_db.table("courses").insert( {"course_code": "CS101", "campus_name": "Berkeley", "dept_code": "CS"} ) with pytest.raises(sqlite3.IntegrityError): @@ -207,8 +209,8 @@ def test_create_table_compound_foreign_key_missing_other_column(departments_db): def test_transform_preserves_compound_foreign_key(compound_db): - compound_db["courses"].transform(rename={"course_name": "title"}) - fks = compound_db["courses"].foreign_keys + compound_db.table("courses").transform(rename={"course_name": "title"}) + fks = compound_db.table("courses").foreign_keys assert len(fks) == 1 fk = fks[0] assert fk.is_compound is True @@ -218,8 +220,8 @@ def test_transform_preserves_compound_foreign_key(compound_db): def test_transform_rename_member_column_updates_compound_foreign_key(compound_db): - compound_db["courses"].transform(rename={"campus_name": "campus"}) - fks = compound_db["courses"].foreign_keys + compound_db.table("courses").transform(rename={"campus_name": "campus"}) + fks = compound_db.table("courses").foreign_keys assert len(fks) == 1 fk = fks[0] assert fk.is_compound is True @@ -231,9 +233,9 @@ def test_transform_rename_member_column_updates_compound_foreign_key(compound_db def test_transform_drop_member_column_drops_compound_foreign_key(compound_db): # Matches single-column behavior: dropping the column silently # drops the foreign key that used it - compound_db["courses"].transform(drop={"dept_code"}) - assert compound_db["courses"].foreign_keys == [] - assert "FOREIGN KEY" not in compound_db["courses"].schema + compound_db.table("courses").transform(drop={"dept_code"}) + assert compound_db.table("courses").foreign_keys == [] + assert "FOREIGN KEY" not in compound_db.table("courses").schema @pytest.mark.parametrize( @@ -246,11 +248,11 @@ def test_transform_drop_member_column_drops_compound_foreign_key(compound_db): ), ) def test_transform_drop_compound_foreign_key(compound_db, drop_foreign_keys): - compound_db["courses"].transform(drop_foreign_keys=drop_foreign_keys) - assert compound_db["courses"].foreign_keys == [] + compound_db.table("courses").transform(drop_foreign_keys=drop_foreign_keys) + assert compound_db.table("courses").foreign_keys == [] # The columns themselves survive assert {"campus_name", "dept_code"} <= set( - compound_db["courses"].columns_dict.keys() + compound_db.table("courses").columns_dict.keys() ) @@ -265,12 +267,12 @@ def courses_db(departments_db): def test_add_compound_foreign_key(courses_db): - t = courses_db["courses"].add_foreign_key( + t = courses_db.table("courses").add_foreign_key( ("campus_name", "dept_code"), "departments", ("campus_name", "dept_code") ) # Returns self assert t.name == "courses" - fks = courses_db["courses"].foreign_keys + fks = courses_db.table("courses").foreign_keys assert len(fks) == 1 fk = fks[0] assert fk.is_compound is True @@ -281,27 +283,33 @@ def test_add_compound_foreign_key(courses_db): def test_add_compound_foreign_key_guesses_other_columns(courses_db): # Lists work here too, though tuples are the documented form - courses_db["courses"].add_foreign_key(["campus_name", "dept_code"], "departments") - fk = courses_db["courses"].foreign_keys[0] + courses_db.table("courses").add_foreign_key( + ["campus_name", "dept_code"], "departments" + ) + fk = courses_db.table("courses").foreign_keys[0] assert fk.other_columns == ("campus_name", "dept_code") def test_add_compound_foreign_key_error_if_already_exists(courses_db): - courses_db["courses"].add_foreign_key(("campus_name", "dept_code"), "departments") + courses_db.table("courses").add_foreign_key( + ("campus_name", "dept_code"), "departments" + ) with pytest.raises(AlterError) as ex: - courses_db["courses"].add_foreign_key( + courses_db.table("courses").add_foreign_key( ("campus_name", "dept_code"), "departments" ) assert "already exists" in ex.value.args[0] # ignore=True should not raise - courses_db["courses"].add_foreign_key( + courses_db.table("courses").add_foreign_key( ("campus_name", "dept_code"), "departments", ignore=True ) def test_add_compound_foreign_key_error_if_column_missing(courses_db): with pytest.raises(AlterError): - courses_db["courses"].add_foreign_key(("campus_name", "nope"), "departments") + courses_db.table("courses").add_foreign_key( + ("campus_name", "nope"), "departments" + ) def test_db_add_foreign_keys_compound(courses_db): @@ -315,14 +323,14 @@ def test_db_add_foreign_keys_compound(courses_db): ) ] ) - fk = courses_db["courses"].foreign_keys[0] + fk = courses_db.table("courses").foreign_keys[0] assert fk.is_compound is True assert fk.columns == ("campus_name", "dept_code") def test_index_foreign_keys_compound_creates_composite_index(compound_db): compound_db.index_foreign_keys() - index_columns = [i.columns for i in compound_db["courses"].indexes] + index_columns = [i.columns for i in compound_db.table("courses").indexes] assert ["campus_name", "dept_code"] in index_columns # No separate single-column indexes for the members assert ["campus_name"] not in index_columns @@ -339,22 +347,22 @@ def test_foreign_key_captures_on_delete_and_on_update(): ON DELETE CASCADE ON UPDATE RESTRICT ); """) - fk = db["books"].foreign_keys[0] + fk = db.table("books").foreign_keys[0] assert fk.on_delete == "CASCADE" assert fk.on_update == "RESTRICT" def test_foreign_key_on_delete_defaults_to_no_action(fresh_db): - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["books"].insert({"id": 1, "author_id": 1}, pk="id") - fresh_db["books"].add_foreign_key("author_id", "authors", "id") - fk = fresh_db["books"].foreign_keys[0] + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("books").insert({"id": 1, "author_id": 1}, pk="id") + fresh_db.table("books").add_foreign_key("author_id", "authors", "id") + fk = fresh_db.table("books").foreign_keys[0] assert fk.on_delete == "NO ACTION" assert fk.on_update == "NO ACTION" def test_create_table_foreign_key_with_on_delete(fresh_db): - fresh_db["authors"].insert({"id": 1}, pk="id") + fresh_db.table("authors").insert({"id": 1}, pk="id") fresh_db.create_table( "books", {"id": int, "author_id": int}, @@ -369,8 +377,8 @@ def test_create_table_foreign_key_with_on_delete(fresh_db): ) ], ) - assert "ON DELETE CASCADE" in fresh_db["books"].schema - assert fresh_db["books"].foreign_keys[0].on_delete == "CASCADE" + assert "ON DELETE CASCADE" in fresh_db.table("books").schema + assert fresh_db.table("books").foreign_keys[0].on_delete == "CASCADE" def test_transform_preserves_on_delete_cascade(): @@ -383,11 +391,11 @@ def test_transform_preserves_on_delete_cascade(): author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE ); """) - db["books"].transform(rename={"title": "book_title"}) - fk = db["books"].foreign_keys[0] + db.table("books").transform(rename={"title": "book_title"}) + fk = db.table("books").foreign_keys[0] assert fk.on_delete == "CASCADE" assert fk.on_update == "NO ACTION" - assert "ON DELETE CASCADE" in db["books"].schema + assert "ON DELETE CASCADE" in db.table("books").schema def test_transform_preserves_compound_foreign_key_on_delete(): @@ -406,11 +414,11 @@ def test_transform_preserves_compound_foreign_key_on_delete(): REFERENCES departments(campus_name, dept_code) ON DELETE CASCADE ); """) - db["courses"].transform(rename={"course_code": "code"}) - fk = db["courses"].foreign_keys[0] + db.table("courses").transform(rename={"course_code": "code"}) + fk = db.table("courses").foreign_keys[0] assert fk.is_compound is True assert fk.on_delete == "CASCADE" - assert "ON DELETE CASCADE" in db["courses"].schema + assert "ON DELETE CASCADE" in db.table("courses").schema def test_implicit_primary_key_reference_is_resolved(): @@ -424,7 +432,7 @@ def test_implicit_primary_key_reference_is_resolved(): author_id INTEGER REFERENCES authors ); """) - fk = db["books"].foreign_keys[0] + fk = db.table("books").foreign_keys[0] assert fk.is_compound is False assert fk.other_column == "author_id" assert fk.other_columns == ("author_id",) @@ -445,7 +453,7 @@ def test_implicit_compound_primary_key_reference_is_resolved(): FOREIGN KEY (campus_name, dept_code) REFERENCES departments ); """) - fk = db["courses"].foreign_keys[0] + fk = db.table("courses").foreign_keys[0] assert fk.is_compound is True assert fk.other_columns == ("campus_name", "dept_code") @@ -470,14 +478,14 @@ def test_add_foreign_keys_preserves_actions(fresh_db): # https://github.com/simonw/sqlite-utils/issues/594 review finding: # ForeignKey objects passed to db.add_foreign_keys() were flattened # to plain tuples, losing on_delete/on_update - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["books"].insert({"id": 1, "author_id": 1}, pk="id") + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("books").insert({"id": 1, "author_id": 1}, pk="id") fresh_db.add_foreign_keys( [ForeignKey("books", "author_id", "authors", "id", on_delete="CASCADE")] ) - fk = fresh_db["books"].foreign_keys[0] + fk = fresh_db.table("books").foreign_keys[0] assert fk.on_delete == "CASCADE" - assert "ON DELETE CASCADE" in fresh_db["books"].schema + assert "ON DELETE CASCADE" in fresh_db.table("books").schema def test_add_foreign_keys_preserves_actions_compound(courses_db): @@ -495,36 +503,36 @@ def test_add_foreign_keys_preserves_actions_compound(courses_db): ) ] ) - fk = courses_db["courses"].foreign_keys[0] + fk = courses_db.table("courses").foreign_keys[0] assert fk.is_compound is True assert fk.on_delete == "CASCADE" - assert "ON DELETE CASCADE" in courses_db["courses"].schema + assert "ON DELETE CASCADE" in courses_db.table("courses").schema def test_add_foreign_key_on_delete_on_update(fresh_db): - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["books"].insert({"id": 1, "author_id": 1}, pk="id") - fresh_db["books"].add_foreign_key( + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("books").insert({"id": 1, "author_id": 1}, pk="id") + fresh_db.table("books").add_foreign_key( "author_id", "authors", "id", on_delete="CASCADE", on_update="RESTRICT" ) - fk = fresh_db["books"].foreign_keys[0] + fk = fresh_db.table("books").foreign_keys[0] assert fk.on_delete == "CASCADE" assert fk.on_update == "RESTRICT" - assert "ON UPDATE RESTRICT ON DELETE CASCADE" in fresh_db["books"].schema + assert "ON UPDATE RESTRICT ON DELETE CASCADE" in fresh_db.table("books").schema # The cascade should actually fire fresh_db.execute("PRAGMA foreign_keys = ON") fresh_db.execute("delete from authors where id = 1") - assert fresh_db["books"].count == 0 + assert fresh_db.table("books").count == 0 def test_add_compound_foreign_key_on_delete(courses_db): - courses_db["courses"].add_foreign_key( + courses_db.table("courses").add_foreign_key( ("campus_name", "dept_code"), "departments", on_delete="SET NULL" ) - fk = courses_db["courses"].foreign_keys[0] + fk = courses_db.table("courses").foreign_keys[0] assert fk.is_compound is True assert fk.on_delete == "SET NULL" - assert "ON DELETE SET NULL" in courses_db["courses"].schema + assert "ON DELETE SET NULL" in courses_db.table("courses").schema def test_implicit_compound_foreign_key_resolves_pk_declaration_order(fresh_db): @@ -536,7 +544,7 @@ def test_implicit_compound_foreign_key_resolves_pk_declaration_order(fresh_db): fresh_db.execute( "create table child (x text, y text, foreign key (x, y) references other)" ) - fk = fresh_db["child"].foreign_keys[0] + fk = fresh_db.table("child").foreign_keys[0] assert fk.other_columns == ("a", "b") @@ -549,46 +557,46 @@ def test_transform_implicit_compound_foreign_key_stays_valid(fresh_db): "create table child (x text, y text, foreign key (x, y) references other)" ) fresh_db.execute("PRAGMA foreign_keys = ON") - fresh_db["other"].insert({"a": "A", "b": "B"}) - fresh_db["child"].insert({"x": "A", "y": "B"}) - fresh_db["child"].transform(types={"x": str}) - assert fresh_db["child"].foreign_keys[0].other_columns == ("a", "b") + fresh_db.table("other").insert({"a": "A", "b": "B"}) + fresh_db.table("child").insert({"x": "A", "y": "B"}) + fresh_db.table("child").transform(types={"x": str}) + assert fresh_db.table("child").foreign_keys[0].other_columns == ("a", "b") # The constraint still points the right way around - fresh_db["child"].insert({"x": "A", "y": "B"}) + fresh_db.table("child").insert({"x": "A", "y": "B"}) with pytest.raises(sqlite3.IntegrityError): - fresh_db["child"].insert({"x": "B", "y": "A"}) + fresh_db.table("child").insert({"x": "B", "y": "A"}) def test_create_compound_foreign_key_guesses_pk_declaration_order(fresh_db): fresh_db.execute("create table other (b text, a text, primary key (a, b))") - fresh_db["other"].insert({"a": "A", "b": "B"}) - fresh_db["child"].create( + fresh_db.table("other").insert({"a": "A", "b": "B"}) + fresh_db.table("child").create( {"id": int, "x": str, "y": str}, pk="id", foreign_keys=[(("x", "y"), "other")], ) - assert fresh_db["child"].foreign_keys[0].other_columns == ("a", "b") + assert fresh_db.table("child").foreign_keys[0].other_columns == ("a", "b") fresh_db.execute("PRAGMA foreign_keys = ON") - fresh_db["child"].insert({"id": 1, "x": "A", "y": "B"}) + fresh_db.table("child").insert({"id": 1, "x": "A", "y": "B"}) with pytest.raises(sqlite3.IntegrityError): - fresh_db["child"].insert({"id": 2, "x": "B", "y": "A"}) + fresh_db.table("child").insert({"id": 2, "x": "B", "y": "A"}) def test_add_compound_foreign_key_guesses_pk_declaration_order(fresh_db): fresh_db.execute("create table other (b text, a text, primary key (a, b))") - fresh_db["child"].insert({"id": 1, "x": "A", "y": "B"}, pk="id") - fresh_db["child"].add_foreign_key(("x", "y"), "other") - assert fresh_db["child"].foreign_keys[0].other_columns == ("a", "b") + fresh_db.table("child").insert({"id": 1, "x": "A", "y": "B"}, pk="id") + fresh_db.table("child").add_foreign_key(("x", "y"), "other") + assert fresh_db.table("child").foreign_keys[0].other_columns == ("a", "b") def test_foreign_keys_are_hashable(fresh_db): # set() over foreign_keys worked with the 3.x namedtuple and must # keep working with the dataclass - fresh_db["p"].insert({"id": 1}, pk="id") - fresh_db["c"].insert( + fresh_db.table("p").insert({"id": 1}, pk="id") + fresh_db.table("c").insert( {"id": 1, "pid": 1}, pk="id", foreign_keys=[("pid", "p", "id")] ) - fks = set(fresh_db["c"].foreign_keys) + fks = set(fresh_db.table("c").foreign_keys) assert len(fks) == 1 assert ForeignKey("c", "pid", "p", "id") in fks # Usable as dict keys too @@ -617,9 +625,9 @@ def test_create_table_mixed_foreign_keys_list(fresh_db): # 3.x accepted a mix of ForeignKey objects, tuples and bare column # strings in foreign_keys= (ForeignKey was a namedtuple, so it passed # the tuple check) - keep accepting the mix - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["publishers"].insert({"id": 1}, pk="id") - fresh_db["books"].create( + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("publishers").insert({"id": 1}, pk="id") + fresh_db.table("books").create( {"id": int, "author_id": int, "publisher_id": int}, pk="id", foreign_keys=[ @@ -627,14 +635,14 @@ def test_create_table_mixed_foreign_keys_list(fresh_db): ("publisher_id", "publishers", "id"), ], ) - fks = {fk.column: fk.other_table for fk in fresh_db["books"].foreign_keys} + fks = {fk.column: fk.other_table for fk in fresh_db.table("books").foreign_keys} assert fks == {"author_id": "authors", "publisher_id": "publishers"} def test_create_table_mixed_foreign_keys_with_string(fresh_db): - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["publishers"].insert({"id": 1}, pk="id") - fresh_db["books"].create( + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("publishers").insert({"id": 1}, pk="id") + fresh_db.table("books").create( {"id": int, "author_id": int, "publisher_id": int}, pk="id", foreign_keys=[ @@ -642,15 +650,15 @@ def test_create_table_mixed_foreign_keys_with_string(fresh_db): ("publisher_id", "publishers", "id"), ], ) - fks = {fk.column: fk.other_table for fk in fresh_db["books"].foreign_keys} + fks = {fk.column: fk.other_table for fk in fresh_db.table("books").foreign_keys} assert fks == {"author_id": "authors", "publisher_id": "publishers"} def test_add_foreign_keys_existing_with_different_actions_errors(fresh_db): # Requesting an existing foreign key with different ON DELETE/ON UPDATE # actions was silently skipped, dropping the requested change - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["books"].insert( + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("books").insert( {"id": 1, "author_id": 1}, pk="id", foreign_keys=[("author_id", "authors", "id")], @@ -660,19 +668,21 @@ def test_add_foreign_keys_existing_with_different_actions_errors(fresh_db): [ForeignKey("books", "author_id", "authors", "id", on_delete="CASCADE")] ) assert "ON DELETE" in str(ex.value) - assert fresh_db["books"].foreign_keys[0].on_delete == "NO ACTION" + assert fresh_db.table("books").foreign_keys[0].on_delete == "NO ACTION" def test_add_foreign_keys_identical_existing_is_noop(fresh_db): # An exact match, including actions, is silently skipped so repeated # calls stay idempotent - fresh_db["authors"].insert({"id": 1}, pk="id") - fresh_db["books"].insert({"id": 1, "author_id": 1}, pk="id") - fresh_db["books"].add_foreign_key("author_id", "authors", "id", on_delete="CASCADE") + fresh_db.table("authors").insert({"id": 1}, pk="id") + fresh_db.table("books").insert({"id": 1, "author_id": 1}, pk="id") + fresh_db.table("books").add_foreign_key( + "author_id", "authors", "id", on_delete="CASCADE" + ) fresh_db.add_foreign_keys( [ForeignKey("books", "author_id", "authors", "id", on_delete="CASCADE")] ) - fks = fresh_db["books"].foreign_keys + fks = fresh_db.table("books").foreign_keys assert len(fks) == 1 assert fks[0].on_delete == "CASCADE" @@ -680,13 +690,13 @@ def test_add_foreign_keys_identical_existing_is_noop(fresh_db): def test_add_foreign_keys_compound_column_count_mismatch_errors(fresh_db): # Previously the extra other-column was silently discarded, creating # a single-column foreign key to just ("id") - fresh_db["departments"].insert( + fresh_db.table("departments").insert( {"campus": "north", "code": "cs"}, pk=("campus", "code") ) - fresh_db["courses"].insert({"id": 1, "campus": "north"}, pk="id") + fresh_db.table("courses").insert({"id": 1, "campus": "north"}, pk="id") with pytest.raises(ValueError) as ex: fresh_db.add_foreign_keys( [("courses", ("campus",), "departments", ("campus", "code"))] ) assert "same number of columns" in str(ex.value) - assert fresh_db["courses"].foreign_keys == [] + assert fresh_db.table("courses").foreign_keys == [] diff --git a/tests/test_fts.py b/tests/test_fts.py index 79af042..312b032 100644 --- a/tests/test_fts.py +++ b/tests/test_fts.py @@ -20,7 +20,7 @@ search_records = [ def test_enable_fts(fresh_db): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert_all(search_records) assert ["searchable"] == fresh_db.table_names() table.enable_fts(["text", "country"], fts_version="FTS4") @@ -54,7 +54,7 @@ def test_enable_fts(fresh_db): def test_enable_fts_escape_table_names(fresh_db): # Table names with restricted chars are handled correctly. # colons and dots are restricted characters for table names. - table = fresh_db["http://example.com"] + table = fresh_db.table("http://example.com") table.insert_all(search_records) assert ["http://example.com"] == fresh_db.table_names() table.enable_fts(["text", "country"], fts_version="FTS4") @@ -87,7 +87,7 @@ def test_enable_fts_escape_table_names(fresh_db): def test_search_duplicate_columns_are_deduped(fresh_db): # https://github.com/simonw/sqlite-utils/issues/624 - table = fresh_db["t"] + table = fresh_db.table("t") table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version="FTS4") rows = list(table.search("tanuki", columns=["text", "text"])) @@ -100,7 +100,7 @@ def test_search_duplicate_columns_are_deduped(fresh_db): def test_search_limit_offset(fresh_db): - table = fresh_db["t"] + table = fresh_db.table("t") table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version="FTS4") assert len(list(table.search("are"))) == 2 @@ -113,7 +113,7 @@ def test_search_limit_offset(fresh_db): def test_search_offset_without_limit(fresh_db): - table = fresh_db["t"] + table = fresh_db.table("t") table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version="FTS4") assert [row["rowid"] for row in table.search("are", order_by="rowid")] == [1, 2] @@ -125,7 +125,7 @@ def test_search_offset_without_limit(fresh_db): @pytest.mark.parametrize("fts_version", ("FTS4", "FTS5")) def test_search_where(fresh_db, fts_version): - table = fresh_db["t"] + table = fresh_db.table("t") table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version=fts_version) results = list( @@ -142,7 +142,7 @@ def test_search_where(fresh_db, fts_version): def test_search_where_args_disallows_query(fresh_db): - table = fresh_db["t"] + table = fresh_db.table("t") with pytest.raises(ValueError) as ex: list( table.search( @@ -156,7 +156,7 @@ def test_search_where_args_disallows_query(fresh_db): def test_search_include_rank(fresh_db): - table = fresh_db["t"] + table = fresh_db.table("t") table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version="FTS5") results = list(table.search("are", include_rank=True)) @@ -182,7 +182,7 @@ def test_search_include_rank(fresh_db): def test_enable_fts_table_names_containing_spaces(fresh_db): - table = fresh_db["test"] + table = fresh_db.table("test") table.insert({"column with spaces": "in its name"}) table.enable_fts(["column with spaces"]) assert [ @@ -196,7 +196,7 @@ def test_enable_fts_table_names_containing_spaces(fresh_db): def test_populate_fts(fresh_db): - table = fresh_db["populatable"] + table = fresh_db.table("populatable") table.insert(search_records[0]) table.enable_fts(["text", "country"], fts_version="FTS4") assert [] == list(table.search("trash pandas")) @@ -217,7 +217,7 @@ def test_populate_fts(fresh_db): def test_populate_fts_escape_table_names(fresh_db): # Restricted characters such as colon and dots should be escaped. - table = fresh_db["http://example.com"] + table = fresh_db.table("http://example.com") table.insert(search_records[0]) table.enable_fts(["text", "country"], fts_version="FTS4") assert [] == list(table.search("trash pandas")) @@ -238,7 +238,7 @@ def test_populate_fts_escape_table_names(fresh_db): @pytest.mark.parametrize("fts_version", ("4", "5")) def test_fts_tokenize(fresh_db, fts_version): table_name = f"searchable_{fts_version}" - table = fresh_db[table_name] + table = fresh_db.table(table_name) table.insert_all(search_records) # Test without porter stemming table.enable_fts( @@ -266,7 +266,7 @@ def test_fts_tokenize(fresh_db, fts_version): def test_fts_tokenize_escaped(fresh_db): # A malicious tokenize value must not be able to break out of the # string literal in the CREATE VIRTUAL TABLE statement. - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert_all(search_records) malicious = "porter'); CREATE TABLE injected(x); --" with pytest.raises(Exception): @@ -278,7 +278,7 @@ def test_fts_tokenize_escaped(fresh_db): def test_optimize_fts(fresh_db): for fts_version in ("4", "5"): table_name = f"searchable_{fts_version}" - table = fresh_db[table_name] + table = fresh_db.table(table_name) table.insert_all(search_records) table.enable_fts(["text", "country"], fts_version=f"FTS{fts_version}") # You can call optimize successfully against the tables OR their _fts equivalents: @@ -288,11 +288,11 @@ def test_optimize_fts(fresh_db): "searchable_4_fts", "searchable_5_fts", ): - fresh_db[table_name].optimize() + fresh_db.table(table_name).optimize() def test_enable_fts_with_triggers(fresh_db): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert(search_records[0]) table.enable_fts(["text", "country"], fts_version="FTS4", create_triggers=True) rows1 = list(table.search("tanuki")) @@ -321,7 +321,7 @@ def test_enable_fts_with_triggers(fresh_db): @pytest.mark.parametrize("create_triggers", [True, False]) def test_disable_fts(fresh_db, create_triggers): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert(search_records[0]) table.enable_fts(["text", "country"], create_triggers=create_triggers) assert { @@ -354,7 +354,7 @@ def test_disable_fts(fresh_db, create_triggers): def test_rebuild_fts(fresh_db): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert(search_records[0]) table.enable_fts(["text", "country"]) # Run a search @@ -380,7 +380,7 @@ def test_rebuild_fts(fresh_db): def test_optimize_and_rebuild_fts_commit(tmpdir, method): path = str(tmpdir / "test.db") db = Database(path) - table = db["searchable"] + table = db.table("searchable") table.insert(search_records[0]) table.enable_fts(["text", "country"]) getattr(table, method)() @@ -390,16 +390,16 @@ def test_optimize_and_rebuild_fts_commit(tmpdir, method): table.insert(search_records[1]) db.close() db2 = Database(path) - assert db2["searchable"].count == 2 + assert db2.table("searchable").count == 2 db2.close() @pytest.mark.parametrize("invalid_table", ["does_not_exist", "not_searchable"]) def test_rebuild_fts_invalid(fresh_db, invalid_table): - fresh_db["not_searchable"].insert({"foo": "bar"}) + fresh_db.table("not_searchable").insert({"foo": "bar"}) # Raise OperationalError on invalid table with pytest.raises(sqlite3.OperationalError): - fresh_db[invalid_table].rebuild_fts() + fresh_db.table(invalid_table).rebuild_fts() @pytest.mark.parametrize("fts_version", ["FTS4", "FTS5"]) @@ -408,15 +408,17 @@ def test_rebuild_removes_junk_docsize_rows(tmpdir, fts_version): path = tmpdir / "test.db" db = Database(str(path), recursive_triggers=False) licenses = [{"key": "apache2", "name": "Apache 2"}, {"key": "bsd", "name": "BSD"}] - db["licenses"].insert_all(licenses, pk="key", replace=True) - db["licenses"].enable_fts(["name"], create_triggers=True, fts_version=fts_version) - assert db["licenses_fts_docsize"].count == 2 + db.table("licenses").insert_all(licenses, pk="key", replace=True) + db.table("licenses").enable_fts( + ["name"], create_triggers=True, fts_version=fts_version + ) + assert db.table("licenses_fts_docsize").count == 2 # Bug: insert with replace increases the number of rows in _docsize: - db["licenses"].insert_all(licenses, pk="key", replace=True) - assert db["licenses_fts_docsize"].count == 4 + db.table("licenses").insert_all(licenses, pk="key", replace=True) + assert db.table("licenses_fts_docsize").count == 4 # rebuild should fix this: - db["licenses_fts"].rebuild_fts() - assert db["licenses_fts_docsize"].count == 2 + db.table("licenses_fts").rebuild_fts() + assert db.table("licenses_fts_docsize").count == 2 @pytest.mark.parametrize( @@ -430,7 +432,7 @@ def test_rebuild_removes_junk_docsize_rows(tmpdir, fts_version): ) def test_enable_fts_replace(kwargs): db = Database(memory=True) - db["books"].insert( + db.table("books").insert( { "id": 1, "title": "Habits of Australian Marsupials", @@ -438,31 +440,31 @@ def test_enable_fts_replace(kwargs): }, pk="id", ) - db["books"].enable_fts(["title", "author"]) - assert not db["books"].triggers - assert db["books_fts"].columns_dict.keys() == {"title", "author"} - assert "FTS5" in db["books_fts"].schema - assert "porter" not in db["books_fts"].schema + db.table("books").enable_fts(["title", "author"]) + assert not db.table("books").triggers + assert db.table("books_fts").columns_dict.keys() == {"title", "author"} + assert "FTS5" in db.table("books_fts").schema + assert "porter" not in db.table("books_fts").schema # Now modify the FTS configuration should_have_changed_columns = "columns" in kwargs if "columns" not in kwargs: kwargs["columns"] = ["title", "author"] - db["books"].enable_fts(**kwargs, replace=True) + db.table("books").enable_fts(**kwargs, replace=True) # Check that the new configuration is correct if should_have_changed_columns: - assert db["books_fts"].columns_dict.keys() == {"title"} + assert db.table("books_fts").columns_dict.keys() == {"title"} if "create_triggers" in kwargs: - assert db["books"].triggers + assert db.table("books").triggers if "fts_version" in kwargs: - assert "FTS4" in db["books_fts"].schema + assert "FTS4" in db.table("books_fts").schema if "tokenize" in kwargs: - assert "porter" in db["books_fts"].schema + assert "porter" in db.table("books_fts").schema def test_enable_fts_replace_does_nothing_if_args_the_same(): queries = [] db = Database(memory=True, tracer=lambda sql, params: queries.append((sql, params))) - db["books"].insert( + db.table("books").insert( { "id": 1, "title": "Habits of Australian Marsupials", @@ -470,17 +472,19 @@ def test_enable_fts_replace_does_nothing_if_args_the_same(): }, pk="id", ) - db["books"].enable_fts(["title", "author"], create_triggers=True) + db.table("books").enable_fts(["title", "author"], create_triggers=True) queries.clear() # Running that again shouldn't run much SQL: - db["books"].enable_fts(["title", "author"], create_triggers=True, replace=True) + db.table("books").enable_fts( + ["title", "author"], create_triggers=True, replace=True + ) # The only SQL that executed should be select statements assert all(q[0].startswith("select ") for q in queries) def test_enable_fts_replace_handles_legacy_bracket_quoted_content_table(): db = Database(memory=True) - db["books"].insert( + db.table("books").insert( { "id": 1, "title": "Habits of Australian Marsupials", @@ -495,10 +499,10 @@ def test_enable_fts_replace_handles_legacy_bracket_quoted_content_table(): ); """) - db["books"].enable_fts(["title", "author"], replace=True) + db.table("books").enable_fts(["title", "author"], replace=True) - assert db["books_fts"].columns_dict.keys() == {"title", "author"} - assert 'content="books"' in db["books_fts"].schema + assert db.table("books_fts").columns_dict.keys() == {"title", "author"} + assert 'content="books"' in db.table("books_fts").schema def test_view_has_no_enable_fts(): @@ -506,7 +510,7 @@ def test_view_has_no_enable_fts(): db.create_view("hello", "select 1 + 1") # Views deliberately do not have an enable_fts() method with pytest.raises(AttributeError): - db["hello"].enable_fts() # type: ignore[union-attr] + db.view("hello").enable_fts() # type: ignore[union-attr] @pytest.mark.parametrize( @@ -712,14 +716,14 @@ def test_view_has_no_enable_fts(): ) def test_search_sql(kwargs, fts, expected): db = Database(memory=True) - db["books"].insert( + db.table("books").insert( { "title": "Habits of Australian Marsupials", "author": "Marlee Hawkins", } ) - db["books"].enable_fts(["title", "author"], fts_version=fts) - sql = db["books"].search_sql(**kwargs) + db.table("books").enable_fts(["title", "author"], fts_version=fts) + sql = db.table("books").search_sql(**kwargs) assert sql == expected @@ -740,7 +744,7 @@ def test_search_sql(kwargs, fts, expected): ), ) def test_quote_fts_query(fresh_db, input, expected): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert_all(search_records) table.enable_fts(["text", "country"]) quoted = fresh_db.quote_fts(input) @@ -750,7 +754,7 @@ def test_quote_fts_query(fresh_db, input, expected): def test_search_quote(fresh_db): - table = fresh_db["searchable"] + table = fresh_db.table("searchable") table.insert_all(search_records) table.enable_fts(["text", "country"]) query = "cat's" @@ -763,7 +767,7 @@ def test_search_quote(fresh_db): def test_enable_fts_cli_on_view_errors(tmpdir): db_path = str(tmpdir / "test.db") db = Database(db_path) - db["t"].insert({"text": "hello"}) + db.table("t").insert({"text": "hello"}) db.create_view("v", "select * from t") db.close() from click.testing import CliRunner diff --git a/tests/test_get.py b/tests/test_get.py index 3cdaed8..5e29506 100644 --- a/tests/test_get.py +++ b/tests/test_get.py @@ -4,14 +4,14 @@ from sqlite_utils.db import NotFoundError def test_get_rowid(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") cleo = {"name": "Cleo", "age": 4} row_id = dogs.insert(cleo).last_rowid assert cleo == dogs.get(row_id) def test_get_primary_key(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") cleo = {"name": "Cleo", "age": 4, "id": 5} last_pk = dogs.insert(cleo, pk="id").last_pk assert 5 == last_pk @@ -23,10 +23,10 @@ def test_get_primary_key(fresh_db): [(100, None), (None, None), ((1, 2), "Need 1 primary key value"), ("2", None)], ) def test_get_not_found(argument, expected_msg, fresh_db): - fresh_db["dogs"].insert( + fresh_db.table("dogs").insert( {"id": 1, "name": "Cleo", "age": 4, "is_good": True}, pk="id" ) with pytest.raises(NotFoundError) as excinfo: - fresh_db["dogs"].get(argument) + fresh_db.table("dogs").get(argument) if expected_msg is not None: assert expected_msg == excinfo.value.args[0] diff --git a/tests/test_gis.py b/tests/test_gis.py index 8b41d22..592af4c 100644 --- a/tests/test_gis.py +++ b/tests/test_gis.py @@ -45,7 +45,7 @@ def test_add_geometry_column(): coord_dimension="XY", ) - assert db["geometry_columns"].get(["locations", "geometry"]) == { + assert db.table("geometry_columns").get(["locations", "geometry"]) == { "f_table_name": "locations", "f_geometry_column": "geometry", "geometry_type": 1, # point @@ -133,7 +133,7 @@ def test_cli_add_geometry_column(tmpdir): db = Database(str(db_path)) db.init_spatialite() - table = db["locations"].create({"name": str}) + table = db.table("locations").create({"name": str}) result = CliRunner().invoke( cli, @@ -149,7 +149,7 @@ def test_cli_add_geometry_column(tmpdir): assert result.exit_code == 0 - assert db["geometry_columns"].get(["locations", "geometry"]) == { + assert db.table("geometry_columns").get(["locations", "geometry"]) == { "f_table_name": "locations", "f_geometry_column": "geometry", "geometry_type": 1, # point @@ -164,7 +164,7 @@ def test_cli_add_geometry_column_options(tmpdir): db_path = tmpdir / "spatial.db" db = Database(str(db_path)) db.init_spatialite() - table = db["locations"].create({"name": str}) + table = db.table("locations").create({"name": str}) result = CliRunner().invoke( cli, @@ -183,7 +183,7 @@ def test_cli_add_geometry_column_options(tmpdir): assert result.exit_code == 0 - assert db["geometry_columns"].get(["locations", "geometry"]) == { + assert db.table("geometry_columns").get(["locations", "geometry"]) == { "f_table_name": "locations", "f_geometry_column": "geometry", "geometry_type": 3, # polygon @@ -202,7 +202,7 @@ def test_cli_add_geometry_column_invalid_type(tmpdir): db = Database(str(db_path)) db.init_spatialite() - table = db["locations"].create({"name": str}) + table = db.table("locations").create({"name": str}) result = CliRunner().invoke( cli, @@ -225,7 +225,7 @@ def test_cli_create_spatial_index(tmpdir): db = Database(str(db_path)) db.init_spatialite() - table = db["locations"].create({"name": str}) + table = db.table("locations").create({"name": str}) table.add_geometry_column("geometry", "POINT") result = CliRunner().invoke( diff --git a/tests/test_hypothesis.py b/tests/test_hypothesis.py index ab652c7..d017f1f 100644 --- a/tests/test_hypothesis.py +++ b/tests/test_hypothesis.py @@ -11,8 +11,8 @@ def test_roundtrip_integers(integer): row = { "integer": integer, } - db["test"].insert(row) - assert list(db["test"].rows) == [row] + db.table("test").insert(row) + assert list(db.table("test").rows) == [row] @given(st.text()) @@ -21,8 +21,8 @@ def test_roundtrip_text(text): row = { "text": text, } - db["test"].insert(row) - assert list(db["test"].rows) == [row] + db.table("test").insert(row) + assert list(db.table("test").rows) == [row] @given(st.binary(max_size=1024 * 1024)) @@ -31,8 +31,8 @@ def test_roundtrip_binary(binary): row = { "binary": binary, } - db["test"].insert(row) - assert list(db["test"].rows) == [row] + db.table("test").insert(row) + assert list(db.table("test").rows) == [row] @given(st.floats(allow_nan=False)) @@ -41,5 +41,5 @@ def test_roundtrip_floats(floats): row = { "floats": floats, } - db["test"].insert(row) - assert list(db["test"].rows) == [row] + db.table("test").insert(row) + assert list(db.table("test").rows) == [row] diff --git a/tests/test_insert_files.py b/tests/test_insert_files.py index 1724d2d..93c4daf 100644 --- a/tests/test_insert_files.py +++ b/tests/test_insert_files.py @@ -57,7 +57,7 @@ def test_insert_files(silent, pk_args, expected_pks): ) assert result.exit_code == 0, result.stdout db = Database(db_path) - rows_by_path = {r["path"]: r for r in db["files"].rows} + rows_by_path = {r["path"]: r for r in db.table("files").rows} one, two, three = ( rows_by_path["one.txt"], rows_by_path["two.txt"], @@ -114,7 +114,7 @@ def test_insert_files(silent, pk_args, expected_pks): for colname, expected_type in expected_types.items(): for row in (one, two, three): assert isinstance(row[colname], expected_type) - assert set(db["files"].pks) == set(expected_pks) + assert set(db.table("files").pks) == set(expected_pks) @pytest.mark.parametrize( @@ -144,7 +144,7 @@ def test_insert_files_stdin(use_text, encoding, input, expected): ) assert result.exit_code == 0, result.stdout db = Database(db_path) - row = next(iter(db["files"].rows)) + row = next(iter(db.table("files").rows)) key = "content" if use_text: key = "content_text" diff --git a/tests/test_introspect.py b/tests/test_introspect.py index 2a8d579..b0953f1 100644 --- a/tests/test_introspect.py +++ b/tests/test_introspect.py @@ -1,6 +1,6 @@ import pytest -from sqlite_utils.db import Check, Database, Index, View, XIndex, XIndexColumn +from sqlite_utils.db import Check, Database, Index, Table, View, XIndex, XIndexColumn def _check_supports_strict(): @@ -21,10 +21,10 @@ def test_view_names(fresh_db): def test_table_names_fts4(existing_db): - existing_db["woo"].insert({"title": "Hello"}).enable_fts( + existing_db.table("woo").insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS4" ) - existing_db["woo2"].insert({"title": "Hello"}).enable_fts( + existing_db.table("woo2").insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS5" ) assert ["woo_fts"] == existing_db.table_names(fts4=True) @@ -32,17 +32,17 @@ def test_table_names_fts4(existing_db): def test_detect_fts(existing_db): - existing_db["woo"].insert({"title": "Hello"}).enable_fts( + existing_db.table("woo").insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS4" ) - existing_db["woo2"].insert({"title": "Hello"}).enable_fts( + existing_db.table("woo2").insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS5" ) - assert "woo_fts" == existing_db["woo"].detect_fts() - assert "woo_fts" == existing_db["woo_fts"].detect_fts() - assert "woo2_fts" == existing_db["woo2"].detect_fts() - assert "woo2_fts" == existing_db["woo2_fts"].detect_fts() - assert existing_db["foo"].detect_fts() is None + assert "woo_fts" == existing_db.table("woo").detect_fts() + assert "woo_fts" == existing_db.table("woo_fts").detect_fts() + assert "woo2_fts" == existing_db.table("woo2").detect_fts() + assert "woo2_fts" == existing_db.table("woo2_fts").detect_fts() + assert existing_db.table("foo").detect_fts() is None @pytest.mark.parametrize("reverse_order", (True, False)) @@ -52,14 +52,14 @@ def test_detect_fts_similar_tables(fresh_db, reverse_order): if reverse_order: table1, table2 = table2, table1 - fresh_db[table1].insert({"title": "Hello"}).enable_fts( + fresh_db.table(table1).insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS4" ) - fresh_db[table2].insert({"title": "Hello"}).enable_fts( + fresh_db.table(table2).insert({"title": "Hello"}).enable_fts( ["title"], fts_version="FTS4" ) - assert fresh_db[table1].detect_fts() == f"{table1}_fts" - assert fresh_db[table2].detect_fts() == f"{table2}_fts" + assert fresh_db.table(table1).detect_fts() == f"{table1}_fts" + assert fresh_db.table(table2).detect_fts() == f"{table2}_fts" def test_tables(existing_db): @@ -77,26 +77,34 @@ def test_views(fresh_db): assert view.columns_dict == {"1": str} +def test_getitem_returns_table_or_view(fresh_db): + fresh_db.table("items").insert({"id": 1}, pk="id") + fresh_db.create_view("item_ids", "select id from items") + + assert isinstance(fresh_db["items"], Table) + assert isinstance(fresh_db["item_ids"], View) + + def test_count(existing_db): - assert existing_db["foo"].count == 3 - assert existing_db["foo"].count_where() == 3 - assert existing_db["foo"].execute_count() == 3 + assert existing_db.table("foo").count == 3 + assert existing_db.table("foo").count_where() == 3 + assert existing_db.table("foo").execute_count() == 3 def test_count_where(existing_db): - assert existing_db["foo"].count_where("text != ?", ["two"]) == 2 - assert existing_db["foo"].count_where("text != :t", {"t": "two"}) == 2 + assert existing_db.table("foo").count_where("text != ?", ["two"]) == 2 + assert existing_db.table("foo").count_where("text != :t", {"t": "two"}) == 2 def test_columns(existing_db): - table = existing_db["foo"] + table = existing_db.table("foo") assert [{"name": "text", "type": "TEXT"}] == [ {"name": col.name, "type": col.type} for col in table.columns ] def test_table_schema(existing_db): - assert existing_db["foo"].schema == "CREATE TABLE foo (text TEXT)" + assert existing_db.table("foo").schema == "CREATE TABLE foo (text TEXT)" def test_database_schema(existing_db): @@ -104,9 +112,9 @@ def test_database_schema(existing_db): def test_table_repr(fresh_db): - table = fresh_db["dogs"].insert({"name": "Cleo", "age": 4}) + table = fresh_db.table("dogs").insert({"name": "Cleo", "age": 4}) assert "" == repr(table) - assert "
" == repr(fresh_db["cats"]) + assert "
" == repr(fresh_db.table("cats")) def test_indexes(fresh_db): @@ -125,7 +133,7 @@ def test_indexes(fresh_db): columns=["c2", "c3"], ), Index(seq=1, name="Gosh_c1", unique=0, origin="c", partial=0, columns=["c1"]), - ] == fresh_db["Gosh"].indexes + ] == fresh_db.table("Gosh").indexes def test_xindexes(fresh_db): @@ -134,7 +142,7 @@ def test_xindexes(fresh_db): create index Gosh_c1 on Gosh(c1); create index Gosh_c2c3 on Gosh(c2, c3 desc); """) - assert fresh_db["Gosh"].xindexes == [ + assert fresh_db.table("Gosh").xindexes == [ XIndex( name="Gosh_c2c3", columns=[ @@ -166,15 +174,15 @@ def test_xindexes(fresh_db): def test_guess_foreign_table(fresh_db, column, expected_table_guess): fresh_db.create_table("authors", {"name": str}) fresh_db.create_table("genre", {"name": str}) - assert expected_table_guess == fresh_db["books"].guess_foreign_table(column) + assert expected_table_guess == fresh_db.table("books").guess_foreign_table(column) @pytest.mark.parametrize( "pk,expected", ((None, ["rowid"]), ("id", ["id"]), (["id", "id2"], ["id", "id2"])) ) def test_pks(fresh_db, pk, expected): - fresh_db["foo"].insert_all([{"id": 1, "id2": 2}], pk=pk) - assert expected == fresh_db["foo"].pks + fresh_db.table("foo").insert_all([{"id": 1, "id2": 2}], pk=pk) + assert expected == fresh_db.table("foo").pks def test_checks(fresh_db): @@ -185,7 +193,7 @@ def test_checks(fresh_db): CONSTRAINT within_maximum CHECK(score <= maximum) ) """) - scores = fresh_db["scores"] + scores = fresh_db.table("scores") expected_column = Check("score > 0", name="positive", column="score") expected_table = Check("score <= maximum", name="within_maximum") assert scores.checks == [expected_column, expected_table] @@ -195,26 +203,26 @@ def test_checks(fresh_db): def test_checks_nonexistent_and_virtual_tables(fresh_db): - assert fresh_db["does_not_exist"].checks == [] - fresh_db["searchable"].insert({"text": "hello"}).enable_fts( + assert fresh_db.table("does_not_exist").checks == [] + fresh_db.table("searchable").insert({"text": "hello"}).enable_fts( ["text"], fts_version="FTS5" ) - assert fresh_db["searchable_fts"].checks == [] + assert fresh_db.table("searchable_fts").checks == [] def test_triggers_and_triggers_dict(fresh_db): assert [] == fresh_db.triggers - authors = fresh_db["authors"] + authors = fresh_db.table("authors") authors.insert_all( [ {"name": "Frank Herbert", "famous_works": "Dune"}, {"name": "Neal Stephenson", "famous_works": "Cryptonomicon"}, ] ) - fresh_db["other"].insert({"foo": "bar"}) + fresh_db.table("other").insert({"foo": "bar"}) assert authors.triggers == [] assert authors.triggers_dict == {} - assert fresh_db["other"].triggers == [] + assert fresh_db.table("other").triggers == [] assert fresh_db.triggers_dict == {} authors.enable_fts( ["name", "famous_works"], fts_version="FTS4", create_triggers=True @@ -226,7 +234,7 @@ def test_triggers_and_triggers_dict(fresh_db): } assert expected_triggers == {(t.name, t.table) for t in fresh_db.triggers} assert expected_triggers == { - (t.name, t.table) for t in fresh_db["authors"].triggers + (t.name, t.table) for t in fresh_db.table("authors").triggers } expected_triggers = { "authors_ai": ( @@ -246,13 +254,13 @@ def test_triggers_and_triggers_dict(fresh_db): ), } assert authors.triggers_dict == expected_triggers - assert fresh_db["other"].triggers == [] - assert fresh_db["other"].triggers_dict == {} + assert fresh_db.table("other").triggers == [] + assert fresh_db.table("other").triggers_dict == {} assert fresh_db.triggers_dict == expected_triggers def test_has_counts_triggers(fresh_db): - authors = fresh_db["authors"] + authors = fresh_db.table("authors") authors.insert({"name": "Frank Herbert"}) assert not authors.has_counts_triggers authors.enable_counts() @@ -301,14 +309,14 @@ def test_has_counts_triggers(fresh_db): ) def test_virtual_table_using(fresh_db, sql, expected_name, expected_using): fresh_db.execute(sql) - assert fresh_db[expected_name].virtual_table_using == expected_using + assert fresh_db.table(expected_name).virtual_table_using == expected_using def test_use_rowid(fresh_db): - fresh_db["rowid_table"].insert({"name": "Cleo"}) - fresh_db["regular_table"].insert({"id": 1, "name": "Cleo"}, pk="id") - assert fresh_db["rowid_table"].use_rowid - assert not fresh_db["regular_table"].use_rowid + fresh_db.table("rowid_table").insert({"name": "Cleo"}) + fresh_db.table("regular_table").insert({"id": 1, "name": "Cleo"}, pk="id") + assert fresh_db.table("rowid_table").use_rowid + assert not fresh_db.table("regular_table").use_rowid @pytest.mark.skipif( @@ -327,7 +335,7 @@ def test_use_rowid(fresh_db): ) def test_table_strict(fresh_db, create_table, expected_strict): fresh_db.execute(create_table) - table = fresh_db["t"] + table = fresh_db.table("t") assert table.strict == expected_strict @@ -343,10 +351,10 @@ def test_table_strict(fresh_db, create_table, expected_strict): ), ) def test_table_default_values(fresh_db, value): - fresh_db["default_values"].insert( + fresh_db.table("default_values").insert( {"nodefault": 1, "value": value}, defaults={"value": value} ) - default_values = fresh_db["default_values"].default_values + default_values = fresh_db.table("default_values").default_values assert default_values == {"value": value} @@ -356,8 +364,8 @@ def test_table_default_values_escaped_quotes(fresh_db): fresh_db.execute( "create table t (id integer primary key, name text default 'O''Brien')" ) - assert "default 'O''Brien'" in fresh_db["t"].schema - assert fresh_db["t"].default_values == {"name": "O'Brien"} + assert "default 'O''Brien'" in fresh_db.table("t").schema + assert fresh_db.table("t").default_values == {"name": "O'Brien"} def test_pks_use_primary_key_declaration_order(fresh_db): @@ -365,11 +373,11 @@ def test_pks_use_primary_key_declaration_order(fresh_db): # pks must follow the declaration order, which is what SQLite uses to # resolve implicit foreign key references and compound pk lookups fresh_db.execute("create table t (b text, a text, primary key (a, b))") - assert fresh_db["t"].pks == ["a", "b"] + assert fresh_db.table("t").pks == ["a", "b"] def test_transform_preserves_compound_pk_declaration_order(fresh_db): fresh_db.execute("create table t (a text, b text, c text, primary key (b, a))") - fresh_db["t"].transform(drop={"c"}) - assert fresh_db["t"].pks == ["b", "a"] - assert 'PRIMARY KEY ("b", "a")' in fresh_db["t"].schema + fresh_db.table("t").transform(drop={"c"}) + assert fresh_db.table("t").pks == ["b", "a"] + assert 'PRIMARY KEY ("b", "a")' in fresh_db.table("t").schema diff --git a/tests/test_list_mode.py b/tests/test_list_mode.py index 646098e..b9ab812 100644 --- a/tests/test_list_mode.py +++ b/tests/test_list_mode.py @@ -19,9 +19,9 @@ def test_insert_all_list_mode_basic(): yield [2, "Bob", 25] yield [3, "Charlie", 35] - db["people"].insert_all(data_generator()) + db.table("people").insert_all(data_generator()) - rows = list(db["people"].rows) + rows = list(db.table("people").rows) assert len(rows) == 3 assert rows[0] == {"id": 1, "name": "Alice", "age": 30} assert rows[1] == {"id": 2, "name": "Bob", "age": 25} @@ -37,10 +37,10 @@ def test_insert_all_list_mode_with_pk(): yield [1, "Alice", 95] yield [2, "Bob", 87] - db["scores"].insert_all(data_generator(), pk="id") + db.table("scores").insert_all(data_generator(), pk="id") - assert db["scores"].pks == ["id"] - rows = list(db["scores"].rows) + assert db.table("scores").pks == ["id"] + rows = list(db.table("scores").rows) assert len(rows) == 2 @@ -54,7 +54,7 @@ def test_upsert_all_list_mode(): yield [1, "Alice", 100] yield [2, "Bob", 200] - db["data"].insert_all(initial_data(), pk="id") + db.table("data").insert_all(initial_data(), pk="id") # Upsert with some updates and new records def upsert_data(): @@ -62,9 +62,9 @@ def test_upsert_all_list_mode(): yield [1, "Alice", 150] # Update existing yield [3, "Charlie", 300] # Insert new - db["data"].upsert_all(upsert_data(), pk="id") + db.table("data").upsert_all(upsert_data(), pk="id") - rows = list(db["data"].rows_where(order_by="id")) + rows = list(db.table("data").rows_where(order_by="id")) assert len(rows) == 3 assert rows[0] == {"id": 1, "name": "Alice", "value": 150} assert rows[1] == {"id": 2, "name": "Bob", "value": 200} @@ -81,9 +81,9 @@ def test_list_mode_with_various_types(): yield [2, "Bob", 87.3, False] yield [3, "Charlie", None, True] - db["mixed"].insert_all(data_generator()) + db.table("mixed").insert_all(data_generator()) - rows = list(db["mixed"].rows) + rows = list(db.table("mixed").rows) assert len(rows) == 3 assert rows[0]["score"] == 95.5 assert rows[1]["active"] == 0 # SQLite stores boolean as int @@ -99,7 +99,7 @@ def test_list_mode_error_non_string_columns(): yield ["a", "b", "c"] with pytest.raises(ValueError, match="must be a list of column name strings"): - db["bad"].insert_all(bad_data()) + db.table("bad").insert_all(bad_data()) def test_list_mode_error_mixed_types(): @@ -111,7 +111,7 @@ def test_list_mode_error_mixed_types(): yield {"id": 1, "name": "Alice"} # Should be a list, not dict with pytest.raises(ValueError, match="must also be lists"): - db["bad"].insert_all(bad_data()) + db.table("bad").insert_all(bad_data()) def test_list_mode_empty_after_headers(): @@ -122,9 +122,9 @@ def test_list_mode_empty_after_headers(): yield ["id", "name", "age"] # No data rows - result = db["people"].insert_all(data_generator()) + result = db.table("people").insert_all(data_generator()) assert result is not None - assert not db["people"].exists() + assert not db.table("people").exists() def test_list_mode_batch_processing(): @@ -136,7 +136,7 @@ def test_list_mode_batch_processing(): for i in range(1000): yield [i, f"value_{i}"] - db["large"].insert_all(large_data(), batch_size=100) + db.table("large").insert_all(large_data(), batch_size=100) count = db.execute("SELECT COUNT(*) as c FROM large").fetchone()[0] assert count == 1000 @@ -152,9 +152,9 @@ def test_list_mode_shorter_rows(): yield [2, "Bob"] # Missing age and city yield [3, "Charlie", 35] # Missing city - db["people"].insert_all(data_generator()) + db.table("people").insert_all(data_generator()) - rows = list(db["people"].rows_where(order_by="id")) + rows = list(db.table("people").rows_where(order_by="id")) assert rows[0] == {"id": 1, "name": "Alice", "age": 30, "city": "NYC"} assert rows[1] == {"id": 2, "name": "Bob", "age": None, "city": None} assert rows[2] == {"id": 3, "name": "Charlie", "age": 35, "city": None} @@ -170,9 +170,9 @@ def test_backwards_compatibility_dict_mode(): {"id": 2, "name": "Bob", "age": 25}, ] - db["people"].insert_all(data) + db.table("people").insert_all(data) - rows = list(db["people"].rows) + rows = list(db.table("people").rows) assert len(rows) == 2 assert rows[0] == {"id": 1, "name": "Alice", "age": 30} @@ -189,9 +189,9 @@ def test_insert_all_tuple_mode_basic(): yield (2, "Bob", 25) yield (3, "Charlie", 35) - db["people"].insert_all(data_generator()) + db.table("people").insert_all(data_generator()) - rows = list(db["people"].rows) + rows = list(db.table("people").rows) assert len(rows) == 3 assert rows[0] == {"id": 1, "name": "Alice", "age": 30} assert rows[1] == {"id": 2, "name": "Bob", "age": 25} @@ -211,9 +211,9 @@ def test_insert_all_mixed_list_tuple(): yield [3, "Charlie", 35] yield (4, "Diana", 40) - db["people"].insert_all(data_generator()) + db.table("people").insert_all(data_generator()) - rows = list(db["people"].rows) + rows = list(db.table("people").rows) assert len(rows) == 4 assert rows[0] == {"id": 1, "name": "Alice", "age": 30} assert rows[1] == {"id": 2, "name": "Bob", "age": 25} @@ -231,7 +231,7 @@ def test_upsert_all_tuple_mode(): yield (1, "Alice", 100) yield (2, "Bob", 200) - db["data"].insert_all(initial_data(), pk="id") + db.table("data").insert_all(initial_data(), pk="id") # Upsert with tuples def upsert_data(): @@ -239,9 +239,9 @@ def test_upsert_all_tuple_mode(): yield (1, "Alice", 150) # Update existing yield (3, "Charlie", 300) # Insert new - db["data"].upsert_all(upsert_data(), pk="id") + db.table("data").upsert_all(upsert_data(), pk="id") - rows = list(db["data"].rows_where(order_by="id")) + rows = list(db.table("data").rows_where(order_by="id")) assert len(rows) == 3 assert rows[0] == {"id": 1, "name": "Alice", "value": 150} assert rows[1] == {"id": 2, "name": "Bob", "value": 200} @@ -258,9 +258,9 @@ def test_tuple_mode_shorter_rows(): yield 2, "Bob" # Missing age and city yield 3, "Charlie", 35 # Missing city - db["people"].insert_all(data_generator()) + db.table("people").insert_all(data_generator()) - rows = list(db["people"].rows_where(order_by="id")) + rows = list(db.table("people").rows_where(order_by="id")) assert rows[0] == {"id": 1, "name": "Alice", "age": 30, "city": "NYC"} assert rows[1] == {"id": 2, "name": "Bob", "age": None, "city": None} assert rows[2] == {"id": 3, "name": "Charlie", "age": 35, "city": None} @@ -271,18 +271,18 @@ def test_list_mode_single_record_upsert_last_pk(): db = Database(memory=True) # Create table first - db["data"].insert({"id": 1, "name": "Alice", "value": 100}, pk="id") + db.table("data").insert({"id": 1, "name": "Alice", "value": 100}, pk="id") # Now upsert a single record using list mode def upsert_data(): yield ["id", "name", "value"] yield [1, "Alice", 150] # Update existing - table = db["data"] + table = db.table("data") table.upsert_all(upsert_data(), pk="id") # Verify the data was updated - rows = list(db["data"].rows) + rows = list(db.table("data").rows) assert rows == [{"id": 1, "name": "Alice", "value": 150}] # Verify last_pk is populated correctly diff --git a/tests/test_lookup.py b/tests/test_lookup.py index c93d1ed..f96cfef 100644 --- a/tests/test_lookup.py +++ b/tests/test_lookup.py @@ -4,7 +4,7 @@ from sqlite_utils.db import Index def test_lookup_new_table(fresh_db): - species = fresh_db["species"] + species = fresh_db.table("species") palm_id = species.lookup({"name": "Palm"}) oak_id = species.lookup({"name": "Oak"}) cherry_id = species.lookup({"name": "Cherry"}) @@ -26,7 +26,7 @@ def test_lookup_new_table(fresh_db): def test_lookup_new_table_compound_key(fresh_db): - species = fresh_db["species"] + species = fresh_db.table("species") palm_id = species.lookup({"name": "Palm", "type": "Tree"}) oak_id = species.lookup({"name": "Oak", "type": "Tree"}) assert palm_id == species.lookup({"name": "Palm", "type": "Tree"}) @@ -70,7 +70,7 @@ def test_lookup_fails_if_constraint_cannot_be_added(fresh_db): def test_lookup_with_extra_values(fresh_db): - species = fresh_db["species"] + species = fresh_db.table("species") id = species.lookup({"name": "Palm", "type": "Tree"}, {"first_seen": "2020-01-01"}) assert species.get(id) == { "id": 1, @@ -90,9 +90,9 @@ def test_lookup_with_extra_values(fresh_db): def test_lookup_with_extra_insert_parameters(fresh_db): - other_table = fresh_db["other_table"] + other_table = fresh_db.table("other_table") other_table.insert({"id": 1, "name": "Name"}, pk="id") - species = fresh_db["species"] + species = fresh_db.table("species") id = species.lookup( {"name": "Palm", "type": "Tree"}, { @@ -156,15 +156,15 @@ def test_lookup_with_extra_insert_parameters(fresh_db): @pytest.mark.parametrize("strict", (False, True)) def test_lookup_new_table_strict(fresh_db, strict): - fresh_db["species"].lookup({"name": "Palm"}, strict=strict) - assert fresh_db["species"].strict == strict or not fresh_db.supports_strict + fresh_db.table("species").lookup({"name": "Palm"}, strict=strict) + assert fresh_db.table("species").strict == strict or not fresh_db.supports_strict def test_lookup_null_value_idempotent(fresh_db): # https://github.com/simonw/sqlite-utils/issues/186 # Repeated lookups of a null value should return the same row, # not insert a duplicate row each time - species = fresh_db["species"] + species = fresh_db.table("species") first_id = species.lookup({"name": None}) second_id = species.lookup({"name": None}) assert first_id == second_id @@ -172,7 +172,7 @@ def test_lookup_null_value_idempotent(fresh_db): def test_lookup_compound_key_with_null_idempotent(fresh_db): - species = fresh_db["species"] + species = fresh_db.table("species") palm_id = species.lookup({"name": "Palm", "type": None}) oak_id = species.lookup({"name": "Oak", "type": "Tree"}) assert palm_id == species.lookup({"name": "Palm", "type": None}) diff --git a/tests/test_m2m.py b/tests/test_m2m.py index 4fca918..4dde7e4 100644 --- a/tests/test_m2m.py +++ b/tests/test_m2m.py @@ -4,45 +4,45 @@ from sqlite_utils.db import ForeignKey, NoObviousTable def test_insert_m2m_single(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id").m2m( "humans", {"id": 1, "name": "Natalie D"}, pk="id" ) assert {"dogs_humans", "humans", "dogs"} == set(fresh_db.table_names()) - humans = fresh_db["humans"] - dogs_humans = fresh_db["dogs_humans"] + humans = fresh_db.table("humans") + dogs_humans = fresh_db.table("dogs_humans") assert [{"id": 1, "name": "Natalie D"}] == list(humans.rows) assert [{"humans_id": 1, "dogs_id": 1}] == list(dogs_humans.rows) def test_insert_m2m_alter(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id").m2m( "humans", {"id": 1, "name": "Natalie D"}, pk="id" ) dogs.update(1).m2m( "humans", {"id": 2, "name": "Simon W", "nerd": True}, pk="id", alter=True ) - assert list(fresh_db["humans"].rows) == [ + assert list(fresh_db.table("humans").rows) == [ {"id": 1, "name": "Natalie D", "nerd": None}, {"id": 2, "name": "Simon W", "nerd": 1}, ] - assert list(fresh_db["dogs_humans"].rows) == [ + assert list(fresh_db.table("dogs_humans").rows) == [ {"humans_id": 1, "dogs_id": 1}, {"humans_id": 2, "dogs_id": 1}, ] def test_insert_m2m_list(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id").m2m( "humans", [{"id": 1, "name": "Natalie D"}, {"id": 2, "name": "Simon W"}], pk="id", ) assert {"dogs", "humans", "dogs_humans"} == set(fresh_db.table_names()) - humans = fresh_db["humans"] - dogs_humans = fresh_db["dogs_humans"] + humans = fresh_db.table("humans") + dogs_humans = fresh_db.table("dogs_humans") assert [{"humans_id": 1, "dogs_id": 1}, {"humans_id": 2, "dogs_id": 1}] == list( dogs_humans.rows ) @@ -68,7 +68,7 @@ def test_insert_m2m_iterable(fresh_db): def iterable(): yield from iterable_records - platypuses = fresh_db["platypuses"] + platypuses = fresh_db.table("platypuses") platypuses.insert({"id": 1, "name": "Perry"}, pk="id").m2m( "humans", iterable(), @@ -76,8 +76,8 @@ def test_insert_m2m_iterable(fresh_db): ) assert {"platypuses", "humans", "humans_platypuses"} == set(fresh_db.table_names()) - humans = fresh_db["humans"] - humans_platypuses = fresh_db["humans_platypuses"] + humans = fresh_db.table("humans") + humans_platypuses = fresh_db.table("humans_platypuses") assert [ {"humans_id": 1, "platypuses_id": 1}, {"humans_id": 2, "platypuses_id": 1}, @@ -111,14 +111,14 @@ def test_m2m_with_table_objects(fresh_db): assert expected_tables == set(fresh_db.table_names()) assert dogs.count == 1 assert humans.count == 2 - assert fresh_db["dogs_humans"].count == 2 + assert fresh_db.table("dogs_humans").count == 2 def test_m2m_lookup(fresh_db): people = fresh_db.table("people", pk="id") people.insert({"name": "Wahyu"}).m2m("tags", lookup={"tag": "Coworker"}) - people_tags = fresh_db["people_tags"] - tags = fresh_db["tags"] + people_tags = fresh_db.table("people_tags") + tags = fresh_db.table("tags") assert people_tags.exists() assert tags.exists() assert [ @@ -150,9 +150,9 @@ def test_m2m_explicit_table_name_argument(fresh_db): people.insert({"name": "Wahyu"}).m2m( "tags", lookup={"tag": "Coworker"}, m2m_table="tagged" ) - assert fresh_db["tags"].exists - assert fresh_db["tagged"].exists - assert not fresh_db["people_tags"].exists() + assert fresh_db.table("tags").exists + assert fresh_db.table("tagged").exists + assert not fresh_db.table("people_tags").exists() def test_m2m_table_candidates(fresh_db): @@ -181,25 +181,25 @@ def test_uses_existing_m2m_table_if_exists(fresh_db): # Code should look for an existing table with fks to both tables # and use that if it exists. people = fresh_db.create_table("people", {"id": int, "name": str}, pk="id") - fresh_db["tags"].lookup({"tag": "Coworker"}) + fresh_db.table("tags").lookup({"tag": "Coworker"}) fresh_db.create_table( "tagged", {"people_id": int, "tags_id": int}, foreign_keys=["people_id", "tags_id"], ) people.insert({"name": "Wahyu"}).m2m("tags", lookup={"tag": "Coworker"}) - assert fresh_db["tags"].exists() - assert fresh_db["tagged"].exists() - assert not fresh_db["people_tags"].exists() - assert not fresh_db["tags_people"].exists() - assert [{"people_id": 1, "tags_id": 1}] == list(fresh_db["tagged"].rows) + assert fresh_db.table("tags").exists() + assert fresh_db.table("tagged").exists() + assert not fresh_db.table("people_tags").exists() + assert not fresh_db.table("tags_people").exists() + assert [{"people_id": 1, "tags_id": 1}] == list(fresh_db.table("tagged").rows) def test_requires_explicit_m2m_table_if_multiple_options(fresh_db): # If the code scans for m2m tables and finds more than one candidate # it should require that the m2m_table=x argument is used people = fresh_db.create_table("people", {"id": int, "name": str}, pk="id") - fresh_db["tags"].lookup({"tag": "Coworker"}) + fresh_db.table("tags").lookup({"tag": "Coworker"}) fresh_db.create_table( "tagged", {"people_id": int, "tags_id": int}, diff --git a/tests/test_migrations.py b/tests/test_migrations.py index 3f3dfea..fa419ec 100644 --- a/tests/test_migrations.py +++ b/tests/test_migrations.py @@ -10,11 +10,11 @@ def migrations(): @migrations() def m001(db): - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) @migrations() def m002(db): - db["cats"].create({"name": str}) + db.table("cats").create({"name": str}) db.execute("insert into dogs (name) values ('Pancakes')") return migrations @@ -28,11 +28,11 @@ def migrations_not_ordered_alphabetically(): @migrations() def m002(db): - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) @migrations() def m001(db): - db["cats"].create({"name": str}) + db.table("cats").create({"name": str}) db.execute("insert into dogs (name) values ('Pancakes')") return migrations @@ -44,7 +44,7 @@ def migrations2(): @migrations() def m001(db): - db["dogs2"].insert({"name": "Cleo"}) + db.table("dogs2").insert({"name": "Cleo"}) return migrations @@ -96,7 +96,7 @@ def test_applied_at_is_a_string(migrations): def test_failing_migration_rolls_back(migrations): @migrations() def m003(db): - db["birds"].create({"name": str}) + db.table("birds").create({"name": str}) db.execute("insert into dogs (name) values ('Dozer')") raise ValueError("boom") @@ -105,7 +105,7 @@ def test_failing_migration_rolls_back(migrations): migrations.apply(db) # m001 and m002 committed before the failure and stay applied assert set(db.table_names()) == {"_sqlite_migrations", "dogs", "cats"} - assert [r["name"] for r in db["dogs"].rows] == ["Cleo", "Pancakes"] + assert [r["name"] for r in db.table("dogs").rows] == ["Cleo", "Pancakes"] assert [m.name for m in migrations.applied(db)] == ["m001", "m002"] # Everything m003 did was rolled back and it is still pending assert [m.name for m in migrations.pending(db)] == ["m003"] @@ -117,11 +117,11 @@ def test_rerun_after_failure_applies_each_migration_once(): @migrations() def m001(db): - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) @migrations() def m002(db): - db["dogs"].insert({"name": "Pancakes"}) + db.table("dogs").insert({"name": "Pancakes"}) if state["fail"]: raise ValueError("boom") @@ -131,7 +131,7 @@ def test_rerun_after_failure_applies_each_migration_once(): state["fail"] = False migrations.apply(db) # m001 must not have been re-applied, m002 applied exactly once - assert [r["name"] for r in db["dogs"].rows] == ["Cleo", "Pancakes"] + assert [r["name"] for r in db.table("dogs").rows] == ["Cleo", "Pancakes"] assert [m.name for m in migrations.applied(db)] == ["m001", "m002"] @@ -142,7 +142,7 @@ def test_non_transactional_migration_allows_vacuum(tmpdir): @migrations() def m001(db): - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) @migrations(transactional=False) def m002(db): @@ -185,11 +185,13 @@ def test_apply_composes_inside_outer_transaction(migrations): ) def test_upgrades_sqlite_migrations(migrations, create_table, pk): db = sqlite_utils.Database(memory=True) - db["_sqlite_migrations"].create(create_table, pk=pk) + db.table("_sqlite_migrations").create(create_table, pk=pk) assert db.table_names() == ["_sqlite_migrations"] - assert db["_sqlite_migrations"].pks == ([pk] if isinstance(pk, str) else list(pk)) + assert db.table("_sqlite_migrations").pks == ( + [pk] if isinstance(pk, str) else list(pk) + ) migrations.apply(db) - assert db["_sqlite_migrations"].pks == ["id"] + assert db.table("_sqlite_migrations").pks == ["id"] def test_pending_and_applied_are_read_only(migrations): @@ -227,7 +229,7 @@ def test_stop_before_applied_migration_errors(migrations): assert "m001" in str(ex.value) assert "already been applied" in str(ex.value) # Nothing else was applied - assert not db["cats"].exists() + assert not db.table("cats").exists() def test_stop_before_applied_migration_errors_before_any_apply(migrations): @@ -238,9 +240,9 @@ def test_stop_before_applied_migration_errors_before_any_apply(migrations): @only_second() def m002(db): - db["cats"].create({"name": str}) + db.table("cats").create({"name": str}) only_second.apply(db) # m002 applied, m001 still pending with pytest.raises(ValueError): migrations.apply(db, stop_before="m002") - assert not db["dogs"].exists() + assert not db.table("dogs").exists() diff --git a/tests/test_mutator_transactions.py b/tests/test_mutator_transactions.py index 37ae1b6..3f13c6b 100644 --- a/tests/test_mutator_transactions.py +++ b/tests/test_mutator_transactions.py @@ -112,7 +112,7 @@ def test_mutator_commits_by_default(tmp_path, mutate, expected_rows): db = seed_database(path) assert not db.conn.in_transaction - mutate(db["items"]) + mutate(db.table("items")) assert current_rows(db) == expected_rows assert not db.conn.in_transaction @@ -127,7 +127,7 @@ def test_mutator_commits_with_outer_atomic(tmp_path, mutate, expected_rows): with db.atomic(): assert db.conn.in_transaction - mutate(db["items"]) + mutate(db.table("items")) assert current_rows(db) == expected_rows assert db.conn.in_transaction @@ -143,7 +143,7 @@ def test_mutator_rolls_back_outer_atomic(tmp_path, mutate, expected_rows): db = seed_database(path) with pytest.raises(RollbackTest), db.atomic(): - mutate(db["items"]) + mutate(db.table("items")) assert current_rows(db) == expected_rows assert db.conn.in_transaction raise RollbackTest diff --git a/tests/test_query.py b/tests/test_query.py index 9d79755..ac0d924 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -6,7 +6,7 @@ from sqlite_utils.utils import sqlite3 def test_query(fresh_db): - fresh_db["dogs"].insert_all([{"name": "Cleo"}, {"name": "Pancakes"}]) + fresh_db.table("dogs").insert_all([{"name": "Cleo"}, {"name": "Pancakes"}]) results = fresh_db.query("select * from dogs order by name desc") assert isinstance(results, types.GeneratorType) assert list(results) == [{"name": "Pancakes"}, {"name": "Cleo"}] @@ -20,13 +20,13 @@ def test_query_executes_eagerly(fresh_db): def test_query_rejects_statements_that_return_no_rows(fresh_db): - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) with pytest.raises(ValueError) as ex: fresh_db.query("update dogs set name = 'Cleopaws'") assert "execute()" in str(ex.value) # The rejected update was rolled back, and no transaction is left open assert not fresh_db.conn.in_transaction - assert [row["name"] for row in fresh_db["dogs"].rows] == ["Cleo"] + assert [row["name"] for row in fresh_db.table("dogs").rows] == ["Cleo"] def test_query_rejected_ddl_is_rolled_back(fresh_db): @@ -37,7 +37,7 @@ def test_query_rejected_ddl_is_rolled_back(fresh_db): def test_query_rejected_write_inside_transaction_is_rolled_back(fresh_db): - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) fresh_db.begin() fresh_db.execute("insert into dogs (name) values ('Pancakes')") with pytest.raises(ValueError): @@ -45,7 +45,7 @@ def test_query_rejected_write_inside_transaction_is_rolled_back(fresh_db): # The transaction is still open and the earlier insert is intact assert fresh_db.conn.in_transaction fresh_db.commit() - assert [row["name"] for row in fresh_db["dogs"].rows] == ["Cleo", "Pancakes"] + assert [row["name"] for row in fresh_db.table("dogs").rows] == ["Cleo", "Pancakes"] @pytest.mark.parametrize( @@ -77,7 +77,7 @@ def test_query_comment_prefixed_commit_does_not_commit_transaction(fresh_db): # A COMMIT hidden behind a leading comment must not slip past the # keyword check - previously it committed the caller's open # transaction before the ValueError was raised - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) fresh_db.begin() fresh_db.execute("insert into dogs (name) values ('Pancakes')") with pytest.raises(ValueError): @@ -85,7 +85,7 @@ def test_query_comment_prefixed_commit_does_not_commit_transaction(fresh_db): # The explicit transaction is still open and can still be rolled back assert fresh_db.conn.in_transaction fresh_db.rollback() - assert [row["name"] for row in fresh_db["dogs"].rows] == ["Cleo"] + assert [row["name"] for row in fresh_db.table("dogs").rows] == ["Cleo"] @pytest.mark.parametrize("sql", ["; COMMIT", "\ufeffCOMMIT"]) @@ -94,7 +94,7 @@ def test_query_prefixed_commit_does_not_commit_transaction(fresh_db, sql): # real token, so the keyword scanner must skip them too - previously # '; COMMIT' slipped past the check and committed the caller's open # transaction before raising OperationalError - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) fresh_db.begin() fresh_db.execute("insert into dogs (name) values ('Pancakes')") with pytest.raises(ValueError): @@ -102,7 +102,7 @@ def test_query_prefixed_commit_does_not_commit_transaction(fresh_db, sql): # The explicit transaction is still open and can still be rolled back assert fresh_db.conn.in_transaction fresh_db.rollback() - assert [row["name"] for row in fresh_db["dogs"].rows] == ["Cleo"] + assert [row["name"] for row in fresh_db.table("dogs").rows] == ["Cleo"] def test_query_error_leaves_no_transaction_open(fresh_db): @@ -190,12 +190,12 @@ def test_first_keyword(sql, expected): reason="RETURNING requires SQLite 3.35.0 or higher", ) def test_query_insert_returning(fresh_db): - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) rows = list( fresh_db.query("insert into dogs (name) values ('Pancakes') returning name") ) assert rows == [{"name": "Pancakes"}] - assert fresh_db["dogs"].count == 2 + assert fresh_db.table("dogs").count == 2 @pytest.mark.skipif( @@ -207,7 +207,7 @@ def test_query_insert_returning_commits_without_iteration(tmpdir): path = str(tmpdir / "test.db") db = Database(path) - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) # Never iterate over the results db.query("insert into dogs (name) values ('Pancakes') returning name") assert not db.conn.in_transaction @@ -227,7 +227,7 @@ def test_query_insert_returning_partial_iteration_still_commits(tmpdir): path = str(tmpdir / "test.db") db = Database(path) - db["dogs"].insert({"name": "Cleo"}) + db.table("dogs").insert({"name": "Cleo"}) row = next( db.query( "insert into dogs (name) values ('Pancakes'), ('Marnie') returning name" @@ -246,7 +246,7 @@ def test_query_insert_returning_partial_iteration_still_commits(tmpdir): reason="RETURNING requires SQLite 3.35.0 or higher", ) def test_query_insert_returning_respects_explicit_transaction(fresh_db): - fresh_db["dogs"].insert({"name": "Cleo"}) + fresh_db.table("dogs").insert({"name": "Cleo"}) fresh_db.begin() rows = list( fresh_db.query("insert into dogs (name) values ('Pancakes') returning name") @@ -255,13 +255,13 @@ def test_query_insert_returning_respects_explicit_transaction(fresh_db): # Still inside the explicit transaction - not committed assert fresh_db.conn.in_transaction fresh_db.rollback() - assert [row["name"] for row in fresh_db["dogs"].rows] == ["Cleo"] + assert [row["name"] for row in fresh_db.table("dogs").rows] == ["Cleo"] def test_query_duplicate_column_names_are_deduped(fresh_db): # https://github.com/simonw/sqlite-utils/issues/624 - fresh_db["one"].insert({"id": 1, "value": "left"}) - fresh_db["two"].insert({"id": 2, "value": "right"}) + fresh_db.table("one").insert({"id": 1, "value": "left"}) + fresh_db.table("two").insert({"id": 2, "value": "right"}) rows = list( fresh_db.query("select one.id, two.id, one.value, two.value from one, two") ) @@ -277,7 +277,7 @@ def test_query_deduped_column_avoids_existing_names(fresh_db): def test_execute_returning_dicts(fresh_db): # Like db.query() but returns a list, included for backwards compatibility # see https://github.com/simonw/sqlite-utils/issues/290 - fresh_db["test"].insert({"id": 1, "bar": 2}, pk="id") + fresh_db.table("test").insert({"id": 1, "bar": 2}, pk="id") assert fresh_db.execute_returning_dicts("select * from test") == [ {"id": 1, "bar": 2} ] diff --git a/tests/test_recipes.py b/tests/test_recipes.py index c6222a3..c6a548c 100644 --- a/tests/test_recipes.py +++ b/tests/test_recipes.py @@ -8,7 +8,7 @@ from sqlite_utils.utils import sqlite3 @pytest.fixture def dates_db(fresh_db): - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "dt": "5th October 2019 12:04"}, {"id": 2, "dt": "6th October 2019 00:05:06"}, @@ -21,8 +21,8 @@ def dates_db(fresh_db): def test_parsedate(dates_db): - dates_db["example"].convert("dt", recipes.parsedate) - assert list(dates_db["example"].rows) == [ + dates_db.table("example").convert("dt", recipes.parsedate) + assert list(dates_db.table("example").rows) == [ {"id": 1, "dt": "2019-10-05"}, {"id": 2, "dt": "2019-10-06"}, {"id": 3, "dt": ""}, @@ -31,8 +31,8 @@ def test_parsedate(dates_db): def test_parsedatetime(dates_db): - dates_db["example"].convert("dt", recipes.parsedatetime) - assert list(dates_db["example"].rows) == [ + dates_db.table("example").convert("dt", recipes.parsedatetime) + assert list(dates_db.table("example").rows) == [ {"id": 1, "dt": "2019-10-05T12:04:00"}, {"id": 2, "dt": "2019-10-06T00:05:06"}, {"id": 3, "dt": ""}, @@ -50,16 +50,16 @@ def test_parsedatetime(dates_db): ), ) def test_dayfirst_yearfirst(fresh_db, recipe, kwargs, expected): - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "dt": "03/04/05"}, ], pk="id", ) - fresh_db["example"].convert( + fresh_db.table("example").convert( "dt", lambda value: getattr(recipes, recipe)(value, **kwargs) ) - assert list(fresh_db["example"].rows) == [ + assert list(fresh_db.table("example").rows) == [ {"id": 1, "dt": expected}, ] @@ -68,7 +68,7 @@ def test_dayfirst_yearfirst(fresh_db, recipe, kwargs, expected): @pytest.mark.parametrize("fn", ("parsedate", "parsedatetime")) def test_dateparse_errors_raises(fresh_db, fn): """Test that invalid dates raise errors when errors=None""" - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "dt": "invalid"}, ], @@ -76,30 +76,32 @@ def test_dateparse_errors_raises(fresh_db, fn): ) # Exception in SQLite callback surfaces as OperationalError with pytest.raises(sqlite3.OperationalError): - fresh_db["example"].convert("dt", lambda value: getattr(recipes, fn)(value)) + fresh_db.table("example").convert( + "dt", lambda value: getattr(recipes, fn)(value) + ) @pytest.mark.parametrize("fn", ("parsedate", "parsedatetime")) @pytest.mark.parametrize("errors", (recipes.SET_NULL, recipes.IGNORE)) def test_dateparse_errors_handled(fresh_db, fn, errors): """Test error handling modes for invalid dates""" - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "dt": "invalid"}, ], pk="id", ) - fresh_db["example"].convert( + fresh_db.table("example").convert( "dt", lambda value: getattr(recipes, fn)(value, errors=errors) ) - rows = list(fresh_db["example"].rows) + rows = list(fresh_db.table("example").rows) expected = [{"id": 1, "dt": None if errors is recipes.SET_NULL else "invalid"}] assert rows == expected @pytest.mark.parametrize("delimiter", [None, ";", "-"]) def test_jsonsplit(fresh_db, delimiter): - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "tags": (delimiter or ",").join(["foo", "bar"])}, {"id": 2, "tags": (delimiter or ",").join(["bar", "baz"])}, @@ -114,8 +116,8 @@ def test_jsonsplit(fresh_db, delimiter): else: fn = recipes.jsonsplit - fresh_db["example"].convert("tags", fn) - assert list(fresh_db["example"].rows) == [ + fresh_db.table("example").convert("tags", fn) + assert list(fresh_db.table("example").rows) == [ {"id": 1, "tags": '["foo", "bar"]'}, {"id": 2, "tags": '["bar", "baz"]'}, ] @@ -130,7 +132,7 @@ def test_jsonsplit(fresh_db, delimiter): ), ) def test_jsonsplit_type(fresh_db, type, expected): - fresh_db["example"].insert_all( + fresh_db.table("example").insert_all( [ {"id": 1, "records": "1,2,3"}, ], @@ -144,5 +146,5 @@ def test_jsonsplit_type(fresh_db, type, expected): else: fn = recipes.jsonsplit - fresh_db["example"].convert("records", fn) - assert json.loads(fresh_db["example"].get(1)["records"]) == expected + fresh_db.table("example").convert("records", fn) + assert json.loads(fresh_db.table("example").get(1)["records"]) == expected diff --git a/tests/test_recreate.py b/tests/test_recreate.py index 09e237e..d8b846e 100644 --- a/tests/test_recreate.py +++ b/tests/test_recreate.py @@ -33,8 +33,8 @@ def test_recreate(tmp_path, use_path, create_file_first): filepath = pathlib.Path(filepath) if create_file_first: db = Database(filepath) - db["t1"].insert({"foo": "bar"}) + db.table("t1").insert({"foo": "bar"}) assert ["t1"] == db.table_names() db.close() - Database(filepath, recreate=True)["t2"].insert({"foo": "bar"}) + Database(filepath, recreate=True).table("t2").insert({"foo": "bar"}) assert ["t2"] == Database(filepath).table_names() diff --git a/tests/test_rows.py b/tests/test_rows.py index dccb6ad..476569e 100644 --- a/tests/test_rows.py +++ b/tests/test_rows.py @@ -3,7 +3,7 @@ import pytest def test_rows(existing_db): assert [{"text": "one"}, {"text": "two"}, {"text": "three"}] == list( - existing_db["foo"].rows + existing_db.table("foo").rows ) @@ -18,7 +18,7 @@ def test_rows(existing_db): ], ) def test_rows_where(where, where_args, expected_ids, fresh_db): - table = fresh_db["dogs"] + table = fresh_db.table("dogs") table.insert_all( [ {"id": 1, "name": "Cleo", "age": 4, "is_good": True}, @@ -41,7 +41,7 @@ def test_rows_where(where, where_args, expected_ids, fresh_db): ], ) def test_rows_where_order_by(where, order_by, expected_ids, fresh_db): - table = fresh_db["dogs"] + table = fresh_db.table("dogs") table.insert_all( [ {"id": 1, "name": "Cleo", "age": 4}, @@ -65,7 +65,7 @@ def test_rows_where_order_by(where, order_by, expected_ids, fresh_db): ], ) def test_rows_where_offset_limit(fresh_db, offset, limit, expected): - table = fresh_db["rows"] + table = fresh_db.table("rows") table.insert_all([{"id": id} for id in range(1, 101)], pk="id") assert table.count == 100 assert expected == [ @@ -74,13 +74,13 @@ def test_rows_where_offset_limit(fresh_db, offset, limit, expected): def test_pks_and_rows_where_offset_without_limit(fresh_db): - table = fresh_db["rows"] + table = fresh_db.table("rows") table.insert_all([{"id": id} for id in range(1, 6)], pk="id") assert [pk for pk, _ in table.pks_and_rows_where(offset=3, order_by="id")] == [4, 5] def test_pks_and_rows_where_rowid(fresh_db): - table = fresh_db["rowid_table"] + table = fresh_db.table("rowid_table") table.insert_all({"number": i + 10} for i in range(3)) pks_and_rows = list(table.pks_and_rows_where()) assert pks_and_rows == [ @@ -91,7 +91,7 @@ def test_pks_and_rows_where_rowid(fresh_db): def test_pks_and_rows_where_simple_pk(fresh_db): - table = fresh_db["simple_pk_table"] + table = fresh_db.table("simple_pk_table") table.insert_all(({"id": i + 10} for i in range(3)), pk="id") pks_and_rows = list(table.pks_and_rows_where()) assert pks_and_rows == [ @@ -102,7 +102,7 @@ def test_pks_and_rows_where_simple_pk(fresh_db): def test_pks_and_rows_where_compound_pk(fresh_db): - table = fresh_db["compound_pk_table"] + table = fresh_db.table("compound_pk_table") table.insert_all( ({"type": "number", "number": i, "plusone": i + 1} for i in range(3)), pk=("type", "number"), @@ -117,8 +117,8 @@ def test_pks_and_rows_where_compound_pk(fresh_db): def test_rows_where_duplicate_select_columns_are_deduped(fresh_db): # https://github.com/simonw/sqlite-utils/issues/624 - fresh_db["t"].insert({"id": 1, "name": "Cleo"}) - rows = list(fresh_db["t"].rows_where(select="id, id, name")) + fresh_db.table("t").insert({"id": 1, "name": "Cleo"}) + rows = list(fresh_db.table("t").rows_where(select="id, id, name")) assert rows == [{"id": 1, "id_2": 1, "name": "Cleo"}] @@ -130,10 +130,10 @@ def test_pks_and_rows_where_view(fresh_db): # an AttributeError from View lacking Table-only properties from sqlite_utils.utils import sqlite3 - fresh_db["dogs"].insert({"id": 1, "name": "Cleo"}, pk="id") + fresh_db.table("dogs").insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.create_view("dog_names", "select name from dogs") try: - result = list(fresh_db["dog_names"].pks_and_rows_where()) + result = list(fresh_db.view("dog_names").pks_and_rows_where()) except sqlite3.OperationalError: pass # SQLite 3.36+: no such column: rowid else: @@ -144,6 +144,6 @@ def test_pks_and_rows_where_view(fresh_db): def test_pks_and_rows_where_compound_pk_declaration_order(fresh_db): # Compound pks are returned in PRIMARY KEY declaration order fresh_db.execute("create table t (b text, a text, primary key (a, b))") - fresh_db["t"].insert({"a": "A", "b": "B"}) - pks_and_rows = list(fresh_db["t"].pks_and_rows_where()) + fresh_db.table("t").insert({"a": "A", "b": "B"}) + pks_and_rows = list(fresh_db.table("t").pks_and_rows_where()) assert pks_and_rows == [(("A", "B"), {"b": "B", "a": "A"})] diff --git a/tests/test_sniff.py b/tests/test_sniff.py index 7149978..029a7fc 100644 --- a/tests/test_sniff.py +++ b/tests/test_sniff.py @@ -19,7 +19,7 @@ def test_sniff(tmpdir, filepath): ) assert result.exit_code == 0, result.stdout db = Database(db_path) - assert list(db["creatures"].rows) == [ + assert list(db.table("creatures").rows) == [ {"id": "1", "species": "dog", "name": "Cleo", "age": "5"}, {"id": "2", "species": "dog", "name": "Pancakes", "age": "4"}, {"id": "3", "species": "cat", "name": "Mozie", "age": "8"}, diff --git a/tests/test_transform.py b/tests/test_transform.py index 980ee9d..28fa4d7 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -128,7 +128,7 @@ def test_transform_sql_table_with_primary_key( def tracer(sql, params): return captured.append((sql, params)) - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") if use_pragma_foreign_keys: fresh_db.conn.execute("PRAGMA foreign_keys=ON") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") @@ -209,7 +209,7 @@ def test_transform_sql_table_with_no_primary_key( def tracer(sql, params): return captured.append((sql, params)) - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") if use_pragma_foreign_keys: fresh_db.conn.execute("PRAGMA foreign_keys=ON") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}) @@ -229,7 +229,7 @@ def test_transform_sql_table_with_no_primary_key( def test_transform_sql_with_no_primary_key_to_primary_key_of_id(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}) assert ( dogs.schema @@ -244,7 +244,7 @@ def test_transform_sql_with_no_primary_key_to_primary_key_of_id(fresh_db): def test_transform_rename_pk(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") dogs.transform(rename={"id": "pk"}) assert ( @@ -265,7 +265,7 @@ def test_transform_preserves_keyword_literal_defaults(fresh_db): " note TEXT DEFAULT NULL" ")" ) - table = fresh_db["t"] + table = fresh_db.table("t") table.insert({"id": 1}) before = fresh_db.execute("SELECT is_active, flag, note FROM t").fetchone() assert before == (1, 0, None) @@ -288,7 +288,7 @@ def test_transform_preserves_keyword_literal_defaults(fresh_db): def test_transform_not_null(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") dogs.transform(not_null={"name"}) assert ( @@ -298,7 +298,7 @@ def test_transform_not_null(fresh_db): def test_transform_remove_a_not_null(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}, not_null={"age"}, pk="id") dogs.transform(not_null={"name": True, "age": False}) assert ( @@ -309,7 +309,7 @@ def test_transform_remove_a_not_null(fresh_db): @pytest.mark.parametrize("not_null", [{"age"}, {"age": True}]) def test_transform_add_not_null_with_rename(fresh_db, not_null): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": "5"}, pk="id") dogs.transform(not_null=not_null, rename={"age": "dog_age"}) assert ( @@ -319,7 +319,7 @@ def test_transform_add_not_null_with_rename(fresh_db, not_null): def test_transform_defaults(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id") dogs.transform(defaults={"age": 1}) assert ( @@ -329,7 +329,7 @@ def test_transform_defaults(fresh_db): def test_transform_defaults_and_rename_column(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id") dogs.transform(rename={"age": "dog_age"}, defaults={"age": 1}) assert ( @@ -339,7 +339,7 @@ def test_transform_defaults_and_rename_column(fresh_db): def test_remove_defaults(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": 5}, defaults={"age": 1}, pk="id") dogs.transform(defaults={"age": None}) assert ( @@ -350,8 +350,8 @@ def test_remove_defaults(fresh_db): @pytest.fixture def authors_db(fresh_db): - books = fresh_db["books"] - authors = fresh_db["authors"] + books = fresh_db.table("books") + authors = fresh_db.table("authors") authors.insert({"id": 5, "name": "Jane McGonical"}, pk="id") books.insert( {"id": 2, "title": "Reality is Broken", "author_id": 5}, @@ -362,13 +362,13 @@ def authors_db(fresh_db): def test_transform_foreign_keys_persist(authors_db): - assert authors_db["books"].foreign_keys == [ + assert authors_db.table("books").foreign_keys == [ ForeignKey( table="books", column="author_id", other_table="authors", other_column="id" ) ] - authors_db["books"].transform(rename={"title": "book_title"}) - assert authors_db["books"].foreign_keys == [ + authors_db.table("books").transform(rename={"title": "book_title"}) + assert authors_db.table("books").foreign_keys == [ ForeignKey( table="books", column="author_id", other_table="authors", other_column="id" ) @@ -381,8 +381,8 @@ def test_transform_foreign_keys_survive_renamed_column( ): if use_pragma_foreign_keys: authors_db.conn.execute("PRAGMA foreign_keys=ON") - authors_db["books"].transform(rename={"author_id": "author_id_2"}) - assert authors_db["books"].foreign_keys == [ + authors_db.table("books").transform(rename={"author_id": "author_id_2"}) + assert authors_db.table("books").foreign_keys == [ ForeignKey( table="books", column="author_id_2", @@ -393,9 +393,9 @@ def test_transform_foreign_keys_survive_renamed_column( def _add_country_city_continent(db): - db["country"].insert({"id": 1, "name": "France"}, pk="id") - db["continent"].insert({"id": 2, "name": "Europe"}, pk="id") - db["city"].insert({"id": 24, "name": "Paris"}, pk="id") + db.table("country").insert({"id": 1, "name": "France"}, pk="id") + db.table("continent").insert({"id": 2, "name": "Europe"}, pk="id") + db.table("city").insert({"id": 24, "name": "Paris"}, pk="id") _CAVEAU = { @@ -413,11 +413,11 @@ def test_transform_drop_foreign_keys(fresh_db, use_pragma_foreign_keys): fresh_db.conn.execute("PRAGMA foreign_keys=ON") # Create table with three foreign keys so we can drop two of them _add_country_city_continent(fresh_db) - fresh_db["places"].insert( + fresh_db.table("places").insert( _CAVEAU, foreign_keys=("country", "continent", "city"), ) - assert fresh_db["places"].foreign_keys == [ + assert fresh_db.table("places").foreign_keys == [ ForeignKey( table="places", column="city", other_table="city", other_column="id" ), @@ -432,9 +432,9 @@ def test_transform_drop_foreign_keys(fresh_db, use_pragma_foreign_keys): ), ] # Drop two of those foreign keys - fresh_db["places"].transform(drop_foreign_keys=("country", "continent")) + fresh_db.table("places").transform(drop_foreign_keys=("country", "continent")) # Should be only one foreign key now - assert fresh_db["places"].foreign_keys == [ + assert fresh_db.table("places").foreign_keys == [ ForeignKey(table="places", column="city", other_table="city", other_column="id") ] if use_pragma_foreign_keys: @@ -443,17 +443,17 @@ def test_transform_drop_foreign_keys(fresh_db, use_pragma_foreign_keys): def test_transform_verify_foreign_keys(fresh_db): fresh_db.conn.execute("PRAGMA foreign_keys=ON") - fresh_db["authors"].insert({"id": 3, "name": "Tina"}, pk="id") - fresh_db["books"].insert( + fresh_db.table("authors").insert({"id": 3, "name": "Tina"}, pk="id") + fresh_db.table("books").insert( {"id": 1, "title": "Book", "author_id": 3}, pk="id", foreign_keys={"author_id"} ) # Renaming the id column on authors should break everything with pytest.raises(OperationalError) as e: - fresh_db["authors"].transform(rename={"id": "id2"}) + fresh_db.table("authors").transform(rename={"id": "id2"}) assert e.value.args[0] == 'foreign key mismatch - "books" referencing "authors"' # This should have rolled us back assert ( - fresh_db["authors"].schema + fresh_db.table("authors").schema == 'CREATE TABLE "authors" (\n "id" INTEGER PRIMARY KEY,\n "name" TEXT\n)' ) assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] @@ -476,20 +476,22 @@ def test_transform_on_delete_cascade_does_not_delete_records( author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE ); """) - fresh_db["authors"].insert({"id": 1, "name": "Ursula K. Le Guin"}) - fresh_db["books"].insert({"id": 1, "title": "The Dispossessed", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Ursula K. Le Guin"}) + fresh_db.table("books").insert( + {"id": 1, "title": "The Dispossessed", "author_id": 1} + ) # Transform the table on the other end of the cascading foreign key - fresh_db["authors"].transform(rename={"name": "author_name"}) - assert list(fresh_db["authors"].rows) == [ + fresh_db.table("authors").transform(rename={"name": "author_name"}) + assert list(fresh_db.table("authors").rows) == [ {"id": 1, "author_name": "Ursula K. Le Guin"} ] - assert list(fresh_db["books"].rows) == [ + assert list(fresh_db.table("books").rows) == [ {"id": 1, "title": "The Dispossessed", "author_id": 1} ] # Transforming the table with the cascading foreign key should not # delete its records either - fresh_db["books"].transform(rename={"title": "book_title"}) - assert list(fresh_db["books"].rows) == [ + fresh_db.table("books").transform(rename={"title": "book_title"}) + assert list(fresh_db.table("books").rows) == [ {"id": 1, "book_title": "The Dispossessed", "author_id": 1} ] if use_pragma_foreign_keys: @@ -511,17 +513,19 @@ def test_transform_in_transaction_refuses_destructive_on_delete(fresh_db, on_del author_id INTEGER REFERENCES authors(id) ON DELETE {on_delete} ); """) - fresh_db["authors"].insert({"id": 1, "name": "Ursula K. Le Guin"}) - fresh_db["books"].insert({"id": 1, "title": "The Dispossessed", "author_id": 1}) - previous_schema = fresh_db["authors"].schema + fresh_db.table("authors").insert({"id": 1, "name": "Ursula K. Le Guin"}) + fresh_db.table("books").insert( + {"id": 1, "title": "The Dispossessed", "author_id": 1} + ) + previous_schema = fresh_db.table("authors").schema with fresh_db.atomic(), pytest.raises(TransactionError) as excinfo: - fresh_db["authors"].transform(rename={"name": "author_name"}) + fresh_db.table("authors").transform(rename={"name": "author_name"}) message = str(excinfo.value) assert "books" in message assert f"ON DELETE {on_delete.upper()}" in message # Nothing should have changed - assert fresh_db["authors"].schema == previous_schema - assert list(fresh_db["books"].rows) == [ + assert fresh_db.table("authors").schema == previous_schema + assert list(fresh_db.table("books").rows) == [ {"id": 1, "title": "The Dispossessed", "author_id": 1} ] assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] @@ -538,16 +542,16 @@ def test_transform_in_transaction_refuses_self_referential_cascade(fresh_db): parent_id INTEGER REFERENCES categories(id) ON DELETE CASCADE ); """) - fresh_db["categories"].insert_all( + fresh_db.table("categories").insert_all( [ {"id": 1, "name": "Fiction", "parent_id": None}, {"id": 2, "name": "Science Fiction", "parent_id": 1}, ] ) with fresh_db.atomic(), pytest.raises(TransactionError) as excinfo: - fresh_db["categories"].transform(rename={"name": "title"}) + fresh_db.table("categories").transform(rename={"name": "title"}) assert "categories" in str(excinfo.value) - assert fresh_db["categories"].count == 2 + assert fresh_db.table("categories").count == 2 def test_transform_in_transaction_allowed_with_no_action_foreign_key(fresh_db): @@ -562,14 +566,16 @@ def test_transform_in_transaction_allowed_with_no_action_foreign_key(fresh_db): author_id INTEGER REFERENCES authors(id) ); """) - fresh_db["authors"].insert({"id": 1, "name": "Ursula K. Le Guin"}) - fresh_db["books"].insert({"id": 1, "title": "The Dispossessed", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Ursula K. Le Guin"}) + fresh_db.table("books").insert( + {"id": 1, "title": "The Dispossessed", "author_id": 1} + ) with fresh_db.atomic(): - fresh_db["authors"].transform(rename={"name": "author_name"}) - assert list(fresh_db["authors"].rows) == [ + fresh_db.table("authors").transform(rename={"name": "author_name"}) + assert list(fresh_db.table("authors").rows) == [ {"id": 1, "author_name": "Ursula K. Le Guin"} ] - assert list(fresh_db["books"].rows) == [ + assert list(fresh_db.table("books").rows) == [ {"id": 1, "title": "The Dispossessed", "author_id": 1} ] assert fresh_db.conn.execute("PRAGMA foreign_keys").fetchone()[0] @@ -587,11 +593,13 @@ def test_transform_in_transaction_allowed_for_child_table(fresh_db): author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE ); """) - fresh_db["authors"].insert({"id": 1, "name": "Ursula K. Le Guin"}) - fresh_db["books"].insert({"id": 1, "title": "The Dispossessed", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Ursula K. Le Guin"}) + fresh_db.table("books").insert( + {"id": 1, "title": "The Dispossessed", "author_id": 1} + ) with fresh_db.atomic(): - fresh_db["books"].transform(rename={"title": "book_title"}) - assert list(fresh_db["books"].rows) == [ + fresh_db.table("books").transform(rename={"title": "book_title"}) + assert list(fresh_db.table("books").rows) == [ {"id": 1, "book_title": "The Dispossessed", "author_id": 1} ] @@ -607,24 +615,28 @@ def test_transform_in_transaction_allowed_with_foreign_keys_off(fresh_db): author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE ); """) - fresh_db["authors"].insert({"id": 1, "name": "Ursula K. Le Guin"}) - fresh_db["books"].insert({"id": 1, "title": "The Dispossessed", "author_id": 1}) + fresh_db.table("authors").insert({"id": 1, "name": "Ursula K. Le Guin"}) + fresh_db.table("books").insert( + {"id": 1, "title": "The Dispossessed", "author_id": 1} + ) with fresh_db.atomic(): - fresh_db["authors"].transform(rename={"name": "author_name"}) - assert list(fresh_db["books"].rows) == [ + fresh_db.table("authors").transform(rename={"name": "author_name"}) + assert list(fresh_db.table("books").rows) == [ {"id": 1, "title": "The Dispossessed", "author_id": 1} ] def test_transform_add_foreign_keys_from_scratch(fresh_db): _add_country_city_continent(fresh_db) - fresh_db["places"].insert(_CAVEAU) + fresh_db.table("places").insert(_CAVEAU) # Should have no foreign keys - assert fresh_db["places"].foreign_keys == [] + assert fresh_db.table("places").foreign_keys == [] # Now add them using .transform() - fresh_db["places"].transform(add_foreign_keys=("country", "continent", "city")) + fresh_db.table("places").transform( + add_foreign_keys=("country", "continent", "city") + ) # Should now have all three: - assert fresh_db["places"].foreign_keys == [ + assert fresh_db.table("places").foreign_keys == [ ForeignKey( table="places", column="city", other_table="city", other_column="id" ), @@ -638,7 +650,7 @@ def test_transform_add_foreign_keys_from_scratch(fresh_db): table="places", column="country", other_table="country", other_column="id" ), ] - assert fresh_db["places"].schema == ( + assert fresh_db.table("places").schema == ( 'CREATE TABLE "places" (\n' ' "id" INTEGER,\n' ' "name" TEXT,\n' @@ -662,18 +674,18 @@ def test_transform_add_foreign_keys_from_scratch(fresh_db): ) def test_transform_add_foreign_keys_from_partial(fresh_db, add_foreign_keys): _add_country_city_continent(fresh_db) - fresh_db["places"].insert( + fresh_db.table("places").insert( _CAVEAU, foreign_keys=("city",), ) # Should have one foreign keys - assert fresh_db["places"].foreign_keys == [ + assert fresh_db.table("places").foreign_keys == [ ForeignKey(table="places", column="city", other_table="city", other_column="id") ] # Now add three more using .transform() - fresh_db["places"].transform(add_foreign_keys=add_foreign_keys) + fresh_db.table("places").transform(add_foreign_keys=add_foreign_keys) # Should now have all three: - assert fresh_db["places"].foreign_keys == [ + assert fresh_db.table("places").foreign_keys == [ ForeignKey( table="places", column="city", other_table="city", other_column="id" ), @@ -702,14 +714,14 @@ def test_transform_add_foreign_keys_from_partial(fresh_db, add_foreign_keys): ) def test_transform_replace_foreign_keys(fresh_db, foreign_keys): _add_country_city_continent(fresh_db) - fresh_db["places"].insert( + fresh_db.table("places").insert( _CAVEAU, foreign_keys=("city",), ) - assert len(fresh_db["places"].foreign_keys) == 1 + assert len(fresh_db.table("places").foreign_keys) == 1 # Replace with two different ones - fresh_db["places"].transform(foreign_keys=foreign_keys) - assert fresh_db["places"].schema == ( + fresh_db.table("places").transform(foreign_keys=foreign_keys) + assert fresh_db.table("places").schema == ( 'CREATE TABLE "places" (\n' ' "id" INTEGER,\n' ' "name" TEXT,\n' @@ -729,7 +741,7 @@ def test_transform_preserves_rowids(fresh_db, table_type): pk = ("id", "name") elif table_type == "rowid": pk = None - fresh_db["places"].insert_all( + fresh_db.table("places").insert_all( [ {"id": "1", "name": "Paris", "country": "France"}, {"id": "2", "name": "London", "country": "UK"}, @@ -738,13 +750,13 @@ def test_transform_preserves_rowids(fresh_db, table_type): pk=pk, ) # Now delete and insert a row to mix up the `rowid` sequence - fresh_db["places"].delete_where("id = ?", ["2"]) - fresh_db["places"].insert({"id": "4", "name": "London", "country": "UK"}) + fresh_db.table("places").delete_where("id = ?", ["2"]) + fresh_db.table("places").insert({"id": "4", "name": "London", "country": "UK"}) previous_rows = [ tuple(row) for row in fresh_db.execute("select rowid, id, name from places") ] # Transform it - fresh_db["places"].transform(column_order=("country", "name")) + fresh_db.table("places").transform(column_order=("country", "name")) # Should be the same next_rows = [ tuple(row) for row in fresh_db.execute("select rowid, id, name from places") @@ -774,7 +786,7 @@ def test_transform_strict(fresh_db, initial_strict, transform_strict, expected_s def test_transform_to_strict_with_invalid_data(fresh_db): if not fresh_db.supports_strict: pytest.skip("SQLite version does not support strict tables") - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.create({"id": int}) dogs.insert({"id": "not-an-integer"}) @@ -801,7 +813,7 @@ def test_transform_strict_updates_default(fresh_db): @pytest.mark.parametrize("method_name", ("transform", "transform_sql")) def test_transform_to_strict_not_supported(fresh_db, method_name): - table = fresh_db["items"] + table = fresh_db.table("items") table.create({"id": int}) fresh_db._supports_strict = False @@ -823,7 +835,7 @@ def test_transform_to_strict_not_supported(fresh_db, method_name): def test_transform_indexes(fresh_db, indexes, transform_params): # https://github.com/simonw/sqlite-utils/issues/633 # New table should have same indexes as old table after transformation - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": 5, "breed": "Labrador"}, pk="id") for index in indexes: @@ -849,13 +861,13 @@ def test_transform_indexes(fresh_db, indexes, transform_params): if "keep_table" in transform_params: assert all( index.origin == "pk" - for index in fresh_db[transform_params["keep_table"]].indexes + for index in fresh_db.table(transform_params["keep_table"]).indexes ) def test_transform_retains_indexes_with_foreign_keys(fresh_db): - dogs = fresh_db["dogs"] - owners = fresh_db["owners"] + dogs = fresh_db.table("dogs") + owners = fresh_db.table("owners") dogs.insert({"id": 1, "name": "Cleo", "owner_id": 1}, pk="id") owners.insert({"id": 1, "name": "Alice"}, pk="id") @@ -890,7 +902,7 @@ def test_transform_retains_indexes_with_foreign_keys(fresh_db): ) def test_transform_with_indexes_errors(fresh_db, transform_params): # Should error with a compound (name, age) index if age is renamed or dropped - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id") dogs.create_index(["name", "age"]) @@ -906,7 +918,7 @@ def test_transform_with_indexes_errors(fresh_db, transform_params): def test_transform_with_unique_constraint_implicit_index(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") # Create a table with a UNIQUE constraint on 'name', which creates an implicit index fresh_db.execute(""" CREATE TABLE dogs ( @@ -933,7 +945,7 @@ def test_transform_with_unique_constraint_implicit_index(fresh_db): def test_transform_preserves_view(fresh_db): # https://github.com/simonw/sqlite-utils/issues/831 - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view dogs_view as select id, name from dogs") view_sql_before = fresh_db.execute( @@ -958,8 +970,8 @@ def test_transform_preserves_view(fresh_db): def test_transform_variants_preserve_view(fresh_db, transform_params): # Covers retyping, changing primary key and foreign key modifications, # with a view whose columns are untouched by the transform - fresh_db["other"].insert({"id": 1}, pk="id") - dogs = fresh_db["dogs"] + fresh_db.table("other").insert({"id": 1}, pk="id") + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo", "other_id": 1}, pk="id") if "drop_foreign_keys" in transform_params: dogs.transform(add_foreign_keys=[("other_id", "other", "id")]) @@ -972,13 +984,13 @@ def test_transform_variants_preserve_view(fresh_db, transform_params): "select sql from sqlite_master where name = 'dogs_view'" ).fetchone()[0] assert view_sql_before == view_sql_after - assert list(fresh_db["dogs_view"].rows) == [{"id": 1, "name": "Cleo"}] + assert list(fresh_db.view("dogs_view").rows) == [{"id": 1, "name": "Cleo"}] def test_transform_view_referencing_renamed_column(fresh_db): # The view survives but querying it raises "no such column" - inherent # to SQLite views, whose SQL is stored as text - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view dogs_view as select id, name from dogs") dogs.transform(rename={"name": "title"}) @@ -987,7 +999,7 @@ def test_transform_view_referencing_renamed_column(fresh_db): def test_transform_view_on_view(fresh_db): - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view v1 as select id, name from dogs") fresh_db.execute("create view v2 as select name from v1") @@ -999,13 +1011,13 @@ def test_transform_view_on_view(fresh_db): "select sql from sqlite_master where type = 'view' order by name" ).fetchall() assert sqls_before == sqls_after - assert list(fresh_db["v2"].rows) == [{"name": "Cleo"}] + assert list(fresh_db.view("v2").rows) == [{"name": "Cleo"}] def test_transform_keep_table_does_not_repoint_view(fresh_db): # Without legacy_alter_table the ALTER TABLE dogs RENAME TO dogs_backup # step would rewrite the view to select from "dogs_backup" - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view dogs_view as select id, name from dogs") dogs.transform(types={"name": str}, keep_table="dogs_backup") @@ -1015,7 +1027,7 @@ def test_transform_keep_table_does_not_repoint_view(fresh_db): assert "dogs_backup" not in view_sql # View reads from the live table, not the frozen backup dogs.insert({"id": 2, "name": "Pancakes"}) - assert list(fresh_db["dogs_view"].rows) == [ + assert list(fresh_db.view("dogs_view").rows) == [ {"id": 1, "name": "Cleo"}, {"id": 2, "name": "Pancakes"}, ] @@ -1024,7 +1036,7 @@ def test_transform_keep_table_does_not_repoint_view(fresh_db): def test_transform_sql_standalone_statements_work_with_view(fresh_db): # The documented "run these statements yourself" workflow should be # standalone-correct, so the pragmas must come from transform_sql() - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view dogs_view as select id, name from dogs") sqls = dogs.transform_sql(types={"name": str}, tmp_suffix="suffix") @@ -1033,12 +1045,12 @@ def test_transform_sql_standalone_statements_work_with_view(fresh_db): assert sqls[-1] == "PRAGMA legacy_alter_table=OFF;" for sql in sqls: fresh_db.execute(sql) - assert list(fresh_db["dogs_view"].rows) == [{"id": 1, "name": "Cleo"}] + assert list(fresh_db.view("dogs_view").rows) == [{"id": 1, "name": "Cleo"}] def test_transform_with_view_in_open_transaction(fresh_db): fresh_db.conn.execute("PRAGMA foreign_keys=ON") - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") fresh_db.execute("create view dogs_view as select id, name from dogs") with fresh_db.conn: @@ -1054,7 +1066,7 @@ def test_transform_with_view_in_open_transaction(fresh_db): def test_transform_restores_legacy_alter_table_setting(fresh_db): if sqlite3.sqlite_version_info < (3, 25, 0): pytest.skip("legacy_alter_table pragma requires SQLite 3.25 or higher") - dogs = fresh_db["dogs"] + dogs = fresh_db.table("dogs") dogs.insert({"id": 1, "name": "Cleo"}, pk="id") # Default is OFF, reset to OFF afterwards dogs.transform(types={"name": str}) @@ -1075,7 +1087,7 @@ def test_transform_preserves_check_constraints(fresh_db): CONSTRAINT nonzero_id CHECK(id != 0) ) """) - scores = fresh_db["scores"] + scores = fresh_db.table("scores") scores.insert({"id": 1, "score": 50}) scores.transform() assert scores.checks == [ @@ -1095,7 +1107,7 @@ def test_transform_preserves_check_ending_in_line_comment(fresh_db): ) ) """) - inventory = fresh_db["inventory"] + inventory = fresh_db.table("inventory") inventory.transform(types={"quantity": float}) assert inventory.checks == [Check("quantity >= 0 -- Quantity cannot be negative")] with pytest.raises(sqlite3.IntegrityError, match="CHECK constraint failed"): @@ -1113,7 +1125,7 @@ def test_transform_preserves_comments_owned_by_columns(fresh_db): age INTEGER -- May be NULL ) """) - people = fresh_db["people"] + people = fresh_db.table("people") people.insert({"id": 1, "name": "Cleo", "age": 5}) people.transform( rename={"name": "display_name"}, @@ -1143,8 +1155,8 @@ def test_transform_drops_comments_owned_by_dropped_column(fresh_db): obsolete TEXT /* Drop this too */ ) """) - fresh_db["t"].transform(drop={"obsolete"}) - schema = fresh_db["t"].schema + fresh_db.table("t").transform(drop={"obsolete"}) + schema = fresh_db.table("t").schema assert "Keep this explanation" in schema assert "Drop this explanation" not in schema assert "Drop this too" not in schema @@ -1159,7 +1171,7 @@ def test_transform_renames_columns_inside_check_constraints(fresh_db): CONSTRAINT within_maximum CHECK(quantity <= maximum) ) """) - inventory = fresh_db["inventory"] + inventory = fresh_db.table("inventory") inventory.insert({"quantity": 2, "maximum": 3}) inventory.transform(rename={"quantity": "amount"}) assert inventory.checks == [ @@ -1182,7 +1194,7 @@ def test_transform_check_rewrite_preserves_functions_and_quotes(fresh_db): CHECK(length("old name") > 0 AND length != '') ) """) - items = fresh_db["items"] + items = fresh_db.table("items") items.insert({"length": "label", "old name": "hello"}) items.transform(rename={"length": "description", "old name": "new name"}) assert items.checks == [Check("length(\"new name\") > 0 AND description != ''")] @@ -1190,9 +1202,9 @@ def test_transform_check_rewrite_preserves_functions_and_quotes(fresh_db): def test_transform_check_rewrite_quotes_keyword_column(fresh_db): fresh_db.execute("CREATE TABLE t(old_name TEXT CHECK(old_name != ''))") - fresh_db["t"].insert({"old_name": "value"}) - fresh_db["t"].transform(rename={"old_name": "select"}) - assert fresh_db["t"].checks == [Check("\"select\" != ''", column="select")] + fresh_db.table("t").insert({"old_name": "value"}) + fresh_db.table("t").transform(rename={"old_name": "select"}) + assert fresh_db.table("t").checks == [Check("\"select\" != ''", column="select")] def test_transform_check_rewrite_does_not_rename_collations_or_cast_types(fresh_db): @@ -1209,9 +1221,9 @@ def test_transform_check_rewrite_does_not_rename_collations_or_cast_types(fresh_ ) ) """) - fresh_db["t"].insert({"nocase": "n", "kind": "k", "other": "o"}) - fresh_db["t"].transform(rename={"nocase": "label", "kind": "category"}) - check = fresh_db["t"].checks[0].check + fresh_db.table("t").insert({"nocase": "n", "kind": "k", "other": "o"}) + fresh_db.table("t").transform(rename={"nocase": "label", "kind": "category"}) + check = fresh_db.table("t").checks[0].check assert "COLLATE nocase" in check assert "AS kind" in check assert "AND label != ''" in check @@ -1226,9 +1238,9 @@ def test_transform_drops_check_owned_by_dropped_column(fresh_db): CHECK(id > 0) ) """) - fresh_db["t"].insert({"id": 1, "obsolete": 2}) - fresh_db["t"].transform(drop={"obsolete"}) - assert fresh_db["t"].checks == [Check("id > 0")] + fresh_db.table("t").insert({"id": 1, "obsolete": 2}) + fresh_db.table("t").transform(drop={"obsolete"}) + assert fresh_db.table("t").checks == [Check("id > 0")] def test_transform_refuses_to_drop_column_used_by_remaining_check(fresh_db): @@ -1239,7 +1251,7 @@ def test_transform_refuses_to_drop_column_used_by_remaining_check(fresh_db): CHECK(minimum <= maximum) ) """) - ranges = fresh_db["ranges"] + ranges = fresh_db.table("ranges") ranges.insert({"minimum": 1, "maximum": 2}) schema_before = ranges.schema with pytest.raises( diff --git a/tests/test_update.py b/tests/test_update.py index e6ae7d8..44cc098 100644 --- a/tests/test_update.py +++ b/tests/test_update.py @@ -7,14 +7,14 @@ from sqlite_utils.db import NotFoundError def test_update_rowid_table(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") rowid = table.insert({"foo": "bar"}).last_pk table.update(rowid, {"foo": "baz"}) assert [{"foo": "baz"}] == list(table.rows) def test_update_pk_table(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") pk = table.insert({"foo": "bar", "id": 5}, pk="id").last_pk assert 5 == pk table.update(pk, {"foo": "baz"}) @@ -22,7 +22,7 @@ def test_update_pk_table(fresh_db): def test_update_compound_pk_table(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") pk = table.insert({"id1": 5, "id2": 3, "v": 1}, pk=("id1", "id2")).last_pk assert (5, 3) == pk table.update(pk, {"v": 2}) @@ -42,14 +42,14 @@ def test_update_compound_pk_table(fresh_db): ), ) def test_update_invalid_pk(fresh_db, pk, update_pk): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"id1": 5, "id2": 3, "v": 1}, pk=pk) with pytest.raises(NotFoundError): table.update(update_pk, {"v": 2}) def test_update_alter(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") rowid = table.insert({"foo": "bar"}).last_pk table.update(rowid, {"new_col": 1.2}, alter=True) assert [{"foo": "bar", "new_col": 1.2}] == list(table.rows) @@ -72,7 +72,7 @@ def test_update_alter(fresh_db): def test_update_alter_with_special_column_characters(fresh_db): # With double-quote escaping, columns with special characters are now valid - table = fresh_db["table"] + table = fresh_db.table("table") rowid = table.insert({"foo": "bar"}).last_pk table.update(rowid, {"new_col[abc]": 1.2}, alter=True) assert list(table.rows) == [{"foo": "bar", "new_col[abc]": 1.2}] @@ -106,8 +106,8 @@ def test_update_with_no_values_sets_last_pk(fresh_db): ), ) def test_update_dictionaries_and_lists_as_json(fresh_db, data_structure): - fresh_db["test"].insert({"id": 1, "data": ""}, pk="id") - fresh_db["test"].update(1, {"data": data_structure}) + fresh_db.table("test").insert({"id": 1, "data": ""}, pk="id") + fresh_db.table("test").update(1, {"data": data_structure}) row = fresh_db.execute("select id, data from test").fetchone() assert row[0] == 1 assert data_structure == json.loads(row[1]) diff --git a/tests/test_upsert.py b/tests/test_upsert.py index 0eaae9b..0f44cc7 100644 --- a/tests/test_upsert.py +++ b/tests/test_upsert.py @@ -7,7 +7,7 @@ from sqlite_utils.db import PrimaryKeyRequired @pytest.mark.parametrize("use_old_upsert", (False, True)) def test_upsert(use_old_upsert): db = Database(memory=True, use_old_upsert=use_old_upsert) - table = db["table"] + table = db.table("table") table.insert({"id": 1, "name": "Cleo"}, pk="id") table.upsert({"id": 1, "age": 5}, pk="id", alter=True) assert list(table.rows) == [{"id": 1, "name": "Cleo", "age": 5}] @@ -15,7 +15,7 @@ def test_upsert(use_old_upsert): def test_upsert_all(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert_all([{"id": 1, "name": "Cleo"}, {"id": 2, "name": "Nixie"}], pk="id") table.upsert_all([{"id": 1, "age": 5}, {"id": 2, "age": 5}], pk="id", alter=True) assert list(table.rows) == [ @@ -26,7 +26,7 @@ def test_upsert_all(fresh_db): def test_upsert_all_single_column(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert_all([{"name": "Cleo"}], pk="name") assert list(table.rows) == [{"name": "Cleo"}] assert table.pks == ["name"] @@ -34,16 +34,16 @@ def test_upsert_all_single_column(fresh_db): def test_upsert_all_not_null(fresh_db): # https://github.com/simonw/sqlite-utils/issues/538 - fresh_db["comments"].upsert_all( + fresh_db.table("comments").upsert_all( [{"id": 1, "name": "Cleo"}], pk="id", not_null=["name"], ) - assert list(fresh_db["comments"].rows) == [{"id": 1, "name": "Cleo"}] + assert list(fresh_db.table("comments").rows) == [{"id": 1, "name": "Cleo"}] def test_upsert_error_if_no_pk(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") with pytest.raises(PrimaryKeyRequired): table.upsert_all([{"id": 1, "name": "Cleo"}]) with pytest.raises(PrimaryKeyRequired): @@ -53,7 +53,7 @@ def test_upsert_error_if_no_pk(fresh_db): @pytest.mark.parametrize("use_old_upsert", (False, True)) def test_upsert_empty_record_errors(use_old_upsert): db = Database(memory=True, use_old_upsert=use_old_upsert) - table = db["table"] + table = db.table("table") table.insert({"id": 1, "name": "Cleo"}, pk="id") with pytest.raises(PrimaryKeyRequired): table.upsert({}, pk="id") @@ -66,7 +66,7 @@ def test_upsert_empty_record_errors(use_old_upsert): @pytest.mark.parametrize("use_old_upsert", (False, True)) def test_upsert_missing_pk_value_errors(use_old_upsert): db = Database(memory=True, use_old_upsert=use_old_upsert) - table = db["table"] + table = db.table("table") table.insert({"id": 1, "name": "Cleo"}, pk="id") # Records that omit the pk column entirely with pytest.raises(PrimaryKeyRequired): @@ -78,7 +78,7 @@ def test_upsert_missing_pk_value_errors(use_old_upsert): def test_upsert_missing_compound_pk_value_errors(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.insert({"a": "x", "b": "y", "v": 1}, pk=("a", "b")) # Missing one component of the detected compound primary key with pytest.raises(PrimaryKeyRequired): @@ -105,7 +105,7 @@ def test_upsert_uses_compound_pk_from_existing_table(use_old_upsert): primary key (Source, Object, Category) ) """) - table = db["summary"] + table = db.table("summary") table.upsert( { "Source": "Client A", @@ -134,7 +134,7 @@ def test_upsert_uses_compound_pk_from_existing_table(use_old_upsert): def test_upsert_with_hash_id(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert({"foo": "bar"}, hash_id="pk") assert [{"pk": "a5e744d0164540d33b1d7ea616c28f2fa97e754a", "foo": "bar"}] == list( table.rows @@ -144,7 +144,7 @@ def test_upsert_with_hash_id(fresh_db): @pytest.mark.parametrize("hash_id", (None, "custom_id")) def test_upsert_with_hash_id_columns(fresh_db, hash_id): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert({"a": 1, "b": 2, "c": 3}, hash_id=hash_id, hash_id_columns=("a", "b")) assert list(table.rows) == [ { @@ -167,7 +167,7 @@ def test_upsert_with_hash_id_columns(fresh_db, hash_id): def test_upsert_compound_primary_key(fresh_db): - table = fresh_db["table"] + table = fresh_db.table("table") table.upsert_all( [ {"species": "dog", "id": 1, "name": "Cleo", "age": 4}, diff --git a/tests/test_wal.py b/tests/test_wal.py index 35318f8..0e8f332 100644 --- a/tests/test_wal.py +++ b/tests/test_wal.py @@ -18,7 +18,7 @@ def test_enable_disable_wal(db_path_tmpdir): assert "test.db-wal" not in [f.basename for f in tmpdir.listdir()] db.enable_wal() assert "wal" == db.journal_mode - db["test"].insert({"foo": "bar"}) + db.table("test").insert({"foo": "bar"}) assert "test.db-wal" in [f.basename for f in tmpdir.listdir()] db.disable_wal() assert "delete" == db.journal_mode @@ -27,25 +27,25 @@ def test_enable_disable_wal(db_path_tmpdir): def test_enable_wal_inside_transaction_raises(db_path_tmpdir): db, _path, _tmpdir = db_path_tmpdir - db["test"].insert({"id": 1}, pk="id") + db.table("test").insert({"id": 1}, pk="id") with pytest.raises(TransactionError), db.atomic(): - db["test"].insert({"id": 2}, pk="id") + db.table("test").insert({"id": 2}, pk="id") db.enable_wal() # The atomic() block must have rolled back cleanly and the # journal mode must be unchanged assert db.journal_mode == "delete" - assert [r["id"] for r in db["test"].rows] == [1] + assert [r["id"] for r in db.table("test").rows] == [1] def test_disable_wal_inside_transaction_raises(db_path_tmpdir): db, _path, _tmpdir = db_path_tmpdir db.enable_wal() - db["test"].insert({"id": 1}, pk="id") + db.table("test").insert({"id": 1}, pk="id") with pytest.raises(TransactionError), db.atomic(): - db["test"].insert({"id": 2}, pk="id") + db.table("test").insert({"id": 2}, pk="id") db.disable_wal() assert db.journal_mode == "wal" - assert [r["id"] for r in db["test"].rows] == [1] + assert [r["id"] for r in db.table("test").rows] == [1] def test_ensure_autocommit_on(db_path_tmpdir): @@ -65,9 +65,9 @@ def test_enable_wal_noop_inside_transaction_is_allowed(db_path_tmpdir): db, _path, _tmpdir = db_path_tmpdir db.enable_wal() with db.atomic(): - db["test"].insert({"id": 1}, pk="id") + db.table("test").insert({"id": 1}, pk="id") db.enable_wal() - assert [r["id"] for r in db["test"].rows] == [1] + assert [r["id"] for r in db.table("test").rows] == [1] def test_ensure_autocommit_on_inside_transaction_raises(db_path_tmpdir): @@ -75,7 +75,7 @@ def test_ensure_autocommit_on_inside_transaction_raises(db_path_tmpdir): # effect, silently breaking the caller's rollback guarantee - so # entering autocommit mode with a transaction open is an error db, _path, _tmpdir = db_path_tmpdir - db["test"].insert({"id": 1}, pk="id") + db.table("test").insert({"id": 1}, pk="id") db.begin() db.execute("insert into test (id) values (2)") with pytest.raises(TransactionError), db.ensure_autocommit_on(): @@ -83,4 +83,4 @@ def test_ensure_autocommit_on_inside_transaction_raises(db_path_tmpdir): # The transaction is still open and can still be rolled back assert db.conn.in_transaction db.rollback() - assert [r["id"] for r in db["test"].rows] == [1] + assert [r["id"] for r in db.table("test").rows] == [1]