From 0123fc112c78ae8c884fe893c04e8633684214cb Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Tue, 6 May 2025 10:20:26 -0700 Subject: [PATCH 1/7] Test against pre-upsert SQLite 3.23.1 Borrowed from https://github.com/simonw/datasette/commit/8f86d2af6 --- .github/workflows/test-sqlite-support.yml | 41 +++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .github/workflows/test-sqlite-support.yml diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml new file mode 100644 index 000000000..33569f1c9 --- /dev/null +++ b/.github/workflows/test-sqlite-support.yml @@ -0,0 +1,41 @@ +name: Test SQLite versions + +on: [push, pull_request] + +permissions: + contents: read + +jobs: + test: + runs-on: ${{ matrix.platform }} + continue-on-error: true + strategy: + matrix: + platform: [ubuntu-latest] + python-version: ["3.13"] + sqlite-version: [ + "3.46", + "3.23.1", # 2018-04-10, before UPSERT + ] + steps: + - uses: actions/checkout@v4 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + allow-prereleases: true + cache: pip + cache-dependency-path: setup.py + - name: Set up SQLite ${{ matrix.sqlite-version }} + uses: asg017/sqlite-versions@71ea0de37ae739c33e447af91ba71dda8fcf22e6 + with: + version: ${{ matrix.sqlite-version }} + cflags: "-DSQLITE_ENABLE_DESERIALIZE -DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_FTS3_PARENTHESIS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_JSON1" + - run: python3 -c "import sqlite3; print(sqlite3.sqlite_version)" + - name: Install dependencies + run: | + pip install -e '.[test]' + pip freeze + - name: Run tests + run: | + python -m pytest From ba7419445f802c469d1ab0dbd9c5e80086eb1179 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:13:50 -0700 Subject: [PATCH 2/7] Try this on Python 3.9 --- .github/workflows/test-sqlite-support.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml index 33569f1c9..256a2ce8c 100644 --- a/.github/workflows/test-sqlite-support.yml +++ b/.github/workflows/test-sqlite-support.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: platform: [ubuntu-latest] - python-version: ["3.13"] + python-version: ["3.9"] sqlite-version: [ "3.46", "3.23.1", # 2018-04-10, before UPSERT From acdbd8c42bbba478732f7f98c37c84195b4c942a Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:23:29 -0700 Subject: [PATCH 3/7] select ... from pragma_function_list() Refs https://github.com/simonw/sqlite-utils/pull/654#issuecomment-2860898278 --- tests/test_plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e82ed313d..c3962ea07 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -54,7 +54,7 @@ def _functions(db): return [ row[0] for row in db.execute( - "select distinct name from pragma_function_list order by 1" + "select distinct name from pragma_function_list() order by 1" ).fetchall() ] From 753a53eede74413810a4f0b3191be753adb541fd Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:24:51 -0700 Subject: [PATCH 4/7] Fix spelling error --- sqlite_utils/db.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index ef8c40e67..5c1cc9938 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -3203,7 +3203,7 @@ def insert( :param not_null: Set of strings specifying columns that should be ``NOT NULL``. :param defaults: Dictionary specifying default values for specific columns. :param hash_id: Name of a column to create and use as a primary key, where the - value of thet primary key will be derived as a SHA1 hash of the other column values + value of that primary key will be derived as a SHA1 hash of the other column values in the record. ``hash_id="id"`` is a common column name used for this. :param alter: Boolean, should any missing columns be added automatically? :param ignore: Boolean, if a record already exists with this primary key, ignore this insert. From b3942fb34f6b37e8c91d2edd24d10701e8b21e17 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:25:57 -0700 Subject: [PATCH 5/7] Compatible with latest black --- sqlite_utils/db.py | 9 +-------- tests/test_cli.py | 4 ++-- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 5c1cc9938..144330a1b 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -237,37 +237,30 @@ class Default: class AlterError(Exception): "Error altering table" - pass class NoObviousTable(Exception): "Could not tell which table this operation refers to" - pass class NoTable(Exception): "Specified table does not exist" - pass class BadPrimaryKey(Exception): "Table does not have a single obvious primary key" - pass class NotFoundError(Exception): "Record not found" - pass class PrimaryKeyRequired(Exception): "Primary key needs to be specified" - pass class InvalidColumns(Exception): "Specified columns do not exist" - pass class DescIndex(str): @@ -3852,7 +3845,7 @@ def jsonify_if_needed(value): def resolve_extracts( - extracts: Optional[Union[Dict[str, str], List[str], Tuple[str]]] + extracts: Optional[Union[Dict[str, str], List[str], Tuple[str]]], ) -> dict: if extracts is None: extracts = {} diff --git a/tests/test_cli.py b/tests/test_cli.py index 4e564f13f..4033af641 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -916,7 +916,7 @@ def test_query_json_with_json_cols(db_path): @pytest.mark.parametrize( "content,is_binary", - [(b"\x00\x0Fbinary", True), ("this is text", False), (1, False), (1.5, False)], + [(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}) @@ -931,7 +931,7 @@ def test_query_raw(db_path, content, is_binary): @pytest.mark.parametrize( "content,is_binary", - [(b"\x00\x0Fbinary", True), ("this is text", False), (1, False), (1.5, False)], + [(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)) From 0d1d9aef484ecef6dced7c50f8018067c308611d Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:33:31 -0700 Subject: [PATCH 6/7] Skip plugin test that needs pragma_function_list Refs https://github.com/simonw/sqlite-utils/pull/654#issuecomment-2860924225 --- tests/test_plugins.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index c3962ea07..c6c805944 100644 --- a/tests/test_plugins.py +++ b/tests/test_plugins.py @@ -1,9 +1,19 @@ from click.testing import CliRunner import click import importlib +import pytest from sqlite_utils import cli, Database, hookimpl, plugins +def _supports_pragma_function_list(): + db = Database(memory=True) + try: + db.execute("select * from pragma_function_list()") + except Exception: + return False + return True + + def test_register_commands(): importlib.reload(cli) assert plugins.get_plugins() == [] @@ -37,6 +47,10 @@ def hello_world(): assert plugins.get_plugins() == [] +@pytest.mark.skipif( + not _supports_pragma_function_list(), + reason="Needs SQLite version that supports pragma_function_list()", +) def test_prepare_connection(): importlib.reload(cli) assert plugins.get_plugins() == [] From d83d7a054131c2bf3af24675b10637948bea231b Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 7 May 2025 17:36:51 -0700 Subject: [PATCH 7/7] Ran cog --- docs/cli-reference.rst | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/docs/cli-reference.rst b/docs/cli-reference.rst index b0572642f..668461cdb 100644 --- a/docs/cli-reference.rst +++ b/docs/cli-reference.rst @@ -1045,23 +1045,6 @@ disable-fts -h, --help Show this message and exit. -.. _cli_ref_tui: - -tui -=== - -See :ref:`cli_tui`. - -:: - - Usage: sqlite-utils tui [OPTIONS] - - Open Textual TUI. - - Options: - -h, --help Show this message and exit. - - .. _cli_ref_optimize: optimize