diff --git a/.github/workflows/test-sqlite-support.yml b/.github/workflows/test-sqlite-support.yml new file mode 100644 index 000000000..256a2ce8c --- /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.9"] + 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 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 diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index ef8c40e67..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): @@ -3203,7 +3196,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. @@ -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)) diff --git a/tests/test_plugins.py b/tests/test_plugins.py index e82ed313d..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() == [] @@ -54,7 +68,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() ]