From 04701e5bcab830af0e09ba548310fca0a46622fc Mon Sep 17 00:00:00 2001 From: Ignazio De Santis Date: Wed, 10 Jun 2026 14:55:58 +0800 Subject: [PATCH] Raise ValueError instead of assert for conflicting insert_all() options insert_all() validated the pk=/hash_id= and ignore=/replace= argument conflicts with bare assert statements. Asserts are stripped under `python -O`, so the validation silently disappears in optimized deployments, and when they do fire they raise AssertionError rather than the ValueError used for the neighbouring pk validation. Replace both with explicit ValueError raises and add regression tests. --- sqlite_utils/db.py | 8 ++++---- tests/test_create.py | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index ed3fc7af2..183aeb668 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -3464,15 +3464,15 @@ def insert_all( if upsert and (not pk and not hash_id): raise PrimaryKeyRequired("upsert() requires a pk") - assert not (hash_id and pk), "Use either pk= or hash_id=" + if hash_id and pk: + raise ValueError("Use either pk= or hash_id=") if hash_id_columns and (hash_id is None): hash_id = "id" if hash_id: pk = hash_id - assert not ( - ignore and replace - ), "Use either ignore=True or replace=True, not both" + if ignore and replace: + raise ValueError("Use either ignore=True or replace=True, not both") all_columns = [] first = True num_records_processed = 0 diff --git a/tests/test_create.py b/tests/test_create.py index b1a6ad1f8..f899ed732 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -950,6 +950,26 @@ def test_insert_hash_id(fresh_db): assert dogs.count == 1 +def test_insert_all_pk_and_hash_id_raises_value_error(fresh_db): + # pk= and hash_id= are mutually exclusive. This must raise a ValueError + # rather than a bare AssertionError, which is silently stripped under + # python -O and so would let the contradictory call through. + with pytest.raises(ValueError, match="Use either pk= or hash_id="): + fresh_db["dogs"].insert_all( + [{"id": 1, "name": "Cleo"}], pk="id", hash_id="hash" + ) + + +def test_insert_all_ignore_and_replace_raises_value_error(fresh_db): + # ignore=True and replace=True are mutually exclusive. + with pytest.raises( + ValueError, match="Use either ignore=True or replace=True, not both" + ): + fresh_db["dogs"].insert_all( + [{"id": 1, "name": "Cleo"}], ignore=True, replace=True + ) + + @pytest.mark.parametrize("use_table_factory", [True, False]) def test_insert_hash_id_columns(fresh_db, use_table_factory): if use_table_factory: