dqlite-dbapi 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/PKG-INFO +3 -3
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/pyproject.toml +3 -3
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/__init__.py +10 -1
- dqlite_dbapi-0.2.2/src/dqlitedbapi/_pragma_intercept.py +264 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/aio/__init__.py +26 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/aio/connection.py +142 -2
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/aio/cursor.py +82 -18
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/connection.py +219 -28
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/cursor.py +179 -48
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/exceptions.py +27 -0
- dqlite_dbapi-0.2.2/src/dqlitedbapi/row.py +93 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/types.py +169 -20
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_failure_resets_rowcount.py +11 -9
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_misc_coverage.py +23 -15
- dqlite_dbapi-0.2.2/tests/integration/test_session_mode_read_only.py +128 -0
- dqlite_dbapi-0.2.2/tests/test_aenter_cleanup_nulls_locks_under_concurrent_close.py +136 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aexit_commit_cancel_debug_log.py +8 -0
- dqlite_dbapi-0.2.2/tests/test_aexit_commit_cancel_force_closes_transport.py +137 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aexit_rollback_debug_log.py +8 -0
- dqlite_dbapi-0.2.2/tests/test_aio_execute_unlocked_silent_drop_scrubs_state.py +126 -0
- dqlite_dbapi-0.2.2/tests/test_aio_force_close_foreign_thread_cursor_closed_pre_cascade.py +123 -0
- dqlite_dbapi-0.2.2/tests/test_aio_transaction_recheck_after_ensure_connection.py +96 -0
- dqlite_dbapi-0.2.2/tests/test_async_commit_rollback_timeout_outer_scope_hint.py +131 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_audit_2026_05_coverage_gaps.py +15 -6
- dqlite_dbapi-0.2.2/tests/test_begin_rewrite_session_mode.py +210 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_bypass_path_releases_latched_op_lock.py +5 -1
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_signal_handler_reentry.py +7 -2
- dqlite_dbapi-0.2.2/tests/test_convert_params_conform_raise_propagates_unwrapped.py +81 -0
- dqlite_dbapi-0.2.2/tests/test_cursor_arraysize_row_factory_setter_thread.py +129 -0
- dqlite_dbapi-0.2.2/tests/test_dbapi_type_hash_consistency.py +87 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_description_null_first_row_resolves.py +9 -3
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_description_null_type_code_to_none.py +19 -10
- dqlite_dbapi-0.2.2/tests/test_description_type_code_unknown_sentinel.py +69 -0
- dqlite_dbapi-0.2.2/tests/test_exceptions_all_symmetry.py +43 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_cancel_restores_pre_batch_lastrowid.py +31 -26
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_cancellederror_restores_pre_batch_lastrowid.py +13 -12
- dqlite_dbapi-0.2.2/tests/test_executemany_lastrowid_docstring_modern_stdlib.py +41 -0
- dqlite_dbapi-0.2.2/tests/test_executemany_lastrowid_mid_batch_preserves_in_batch.py +167 -0
- dqlite_dbapi-0.2.2/tests/test_executemany_push_skips_cascade_zeroed_cursor.py +77 -0
- dqlite_dbapi-0.2.2/tests/test_format_utc_offset_non_timedelta_guard.py +62 -0
- dqlite_dbapi-0.2.2/tests/test_get_async_connection_force_close_race.py +148 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_module_attributes.py +3 -0
- dqlite_dbapi-0.2.2/tests/test_number_includes_boolean_documented.py +34 -0
- dqlite_dbapi-0.2.2/tests/test_register_adapter_positional_only_signature.py +38 -0
- dqlite_dbapi-0.2.2/tests/test_row_factory_sqlite3_equivalent.py +110 -0
- dqlite_dbapi-0.2.2/tests/test_rowcount_select_divergence_documented.py +47 -0
- dqlite_dbapi-0.2.2/tests/test_sync_close_op_lock_owner_aware_probe.py +100 -0
- dqlite_dbapi-0.2.2/tests/test_sync_commit_rollback_snapshot_inner_for_tier2.py +53 -0
- dqlite_dbapi-0.2.2/tests/test_sync_transaction_ctxmgr_owner_slot_busy_sentinel.py +55 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_transaction_owner_token_bookkeeping.py +11 -6
- dqlite_dbapi-0.2.2/tests/test_text_bind_nul_byte_rejected_with_blob_hint.py +92 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_transaction_ctxmgr_state_lock.py +10 -2
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_types_dbapi_compare.py +22 -21
- dqlite_dbapi-0.2.2/tests/test_unregister_adapter.py +93 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_validate_ticks_and_unixtime_reject_bool_and_non_numeric.py +28 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/uv.lock +3 -3
- dqlite_dbapi-0.2.1/src/dqlitedbapi/_pragma_intercept.py +0 -106
- dqlite_dbapi-0.2.1/tests/test_dbapi_type_hash_consistency.py +0 -77
- dqlite_dbapi-0.2.1/tests/test_unregister_adapter.py +0 -50
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/.github/workflows/publish-to-pypi.yml +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/.gitignore +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/DEVELOPMENT.md +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/LICENSE.md +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/README.md +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/_busy_retry.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/_constants.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/src/dqlitedbapi/py.typed +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/__init__.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_aio_version_final_annotated.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_async_close_underlying_close_failed_logged.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_async_connection_fork_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_async_iter_protocol_invariants.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_async_unclosed_warning_skips_in_fork_child.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_close_cancel_between_cursor_cascade_and_lock.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_fetchmany_cancel_atomic.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/aio/test_messages_clear_on_closed.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/conftest.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/__init__.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/conftest.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_concurrent_executemany_serialized.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_cursor_concurrent_execute_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_cursor_edge_branches.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_fetchmany_cancel.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_returning_zero_rows.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_async_transaction_ctxmgr_rejects_stray_commit.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_close_implicit_rollback_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_concurrent_cursors_visibility.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_constraint_extended_codes.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_context_manager.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_cursor_fetch_after_non_row_execute.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_cursor_misc_invariant_pins.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_cursor_row_index_after_fetchall.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_datetime_conversion.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_description_after_ddl_pragma.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_description_survives_empty_fetchall.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_cancel_mid_batch.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_completed_iterations_observability.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_cte_dml.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_generator.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_executemany_returning.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_integrity_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_lastrowid_autoincrement.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_lastrowid_cursor_scoped.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_lastrowid_returning.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_lastrowid_survives_cross_cursor_rollback.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_leader_redirect_live.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_multiline_returning_rows.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_nan_inf_float.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_negative_zero_and_subnormal_float.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_no_transaction_error_wording.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_null_vs_empty_text_blob_three_way.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_pragma_deny_list.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_query_detection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_returning.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_savepoint_dbapi.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_savepoint_failure_responses.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_sqlite_version_pin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/integration/test_sync_transaction_ctxmgr_rejects_stray_commit.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aconn_execute_with_parameters.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aconn_factory_getters.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aconnect_cleanup_close_shielded_against_outer_timeout.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aconnect_cleanup_on_connect_failure.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_adapter_exceptions_wrapped_as_data_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aenter_cleanup_preserves_original_under_outer_cancel.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aexit_behavioural_no_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aexit_rollback_cancel_body_context_pin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_commit_rollback_no_tx.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_commit_rollback_no_tx_code_matrix.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_commit_rollback_wrapping.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_connection_finalizer_detached_on_cancel_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_connection_finalizer_detached_on_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_cursor_drain_rows.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_cursor_row_factory_typeerror_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_description_tuple_exported.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_executemany_cursor_close_cascade.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_force_close_transport_cursor_cascade.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_init_reexports_diagnostic_prefixes.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_loop_affinity_exc_class.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_module_attributes.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_register_adapter_export.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_register_converter_stubs.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_row_factory_setter_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_aio_setters_clear_messages_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_arraysize_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_backup_not_async_def.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_check_loop_only_pid_before_loop.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_cancel_arm_cancels_inner_pending_drain.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_ensure_locks_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_finally_propagates_cancel.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_op_lock_bounded.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_outer_cancel_force_closes_transport.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_close_race.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_force_close_on_outer_cancel.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_in_transaction_under_lock.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_loop_binding_first.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_messages_under_lock.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_op_lock_bounded.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_phase_budget.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_retry_after_invalidate.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_commit_rollback_timeout_phase_aware.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connect_cross_loop_diagnostic_on_fast_path.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_close_during_connect.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_cursor_fork_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_ensure_connection_post_yield_close_shielded.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_race.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_setters_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_connection_transaction.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_aclose_alias.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_add_races_cascade_clear.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_aenter_cross_task_executing_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_aenter_gc_parent_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_aiter_aenter_pep249_pins.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_aiter_cross_loop_fail_fast.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_arraysize_row_factory_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_callproc_nextset_scroll_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_close_clears_executing_task.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_close_is_sync_and_race_safe.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_close_lock_free.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_closed_state_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_execute_executing_task_inside_try_frame.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_execute_messages_clear.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_executemany_validation_clears_executing_task.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_fetch_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_finally_clear_executing_task_unconditional.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_late_add_proxy_swap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_rownumber_closed_cross_loop.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_cursor_setinputsizes_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_executemany_atomic.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_executemany_close_race.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_executescript_stub_raises_on_call.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_fetch_does_not_lazy_bind_loop.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_fetchall_row_factory_happy_path.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_force_close_transport.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_in_transaction_closed_foreign_loop.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_in_transaction_loop_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_invalidated_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_lock_binding.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_resource_warning_gate.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_resource_warning_sanitize_parity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_secondary_methods_clear_messages_before_guards.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_transaction_owner_set_inside_try_frame.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_async_with_exit_does_not_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_audit_2026_05_dbapi_coverage.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_autocommit_doc_no_round_trip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_autocommit_legacy_transaction_control.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_autocommit_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_autocommit_setter_exact_int_gate.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_binary_typeerror_stdlib_parity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_bind_typeerror_as_dataerror.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_build_and_connect_base_exception_group_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_build_and_connect_resolve_leader_oserror_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_build_and_connect_wire_encode_error_translation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_busy_retry_async_wiring.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_busy_retry_classifier.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_busy_retry_curve.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_busy_retry_docstring_pins_cross_thread_caveat.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_busy_retry_sync_wiring.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_base_exception_group_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_baseexceptiongroup_cancel_split.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_docstring_mapping_table.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_mapping.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_typeerror_message_does_not_blame_bind.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_call_client_wire_encode_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_callproc_noreturn_annotation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_callproc_scroll_clear_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cascade_cursors_clears_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_check_same_thread_kwarg.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_classify_caller_sql.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_classify_caller_sql_hardening.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_classify_caller_sql_structural_reject_precedence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_classify_operational_code_zero.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cleanup_loop_thread_disarms_inner_and_reaps_drain.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cleanup_loop_thread_finalizer_fork_safe.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_resource_leak.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_surfaces_op_lock_contention.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_thread_join_uses_close_timeout.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_timeout_floor_enforcement.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_close_timeout_plumbing.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_closed_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cluster_policy_rejection_prefix_constant.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_code_to_exception_wire_ssot.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_collated_coverage_gaps.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_commit_after_external_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_commit_leader_flip_ambiguous_commit_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_commit_leader_flip_propagates.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_commit_no_spurious_connect.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_commit_rollback_shortcircuit_uses_in_transaction.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_conform_adapter_non_primitive_rejected_at_dbapi_layer.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_conftest_adapter_registry_isolation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_baseexceptiongroup_cancel_split.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_busy_timeout_kwarg.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_clears_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_closed_precedes_thread_affinity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_docstring_parity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_iso_autocommit_round_trip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_isolation_level_autocommit_kwargs_symmetric.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connect_preserves_code.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_after_fork_raises.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_autocommit_isolation_level_closed_state.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_close_cascades_cursors.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_close_cursor_cascade_atomicity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_close_idempotent_cross_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_closed_checks.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_cursor_class_attribute.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_cursor_closed_state_precedes_unknown_kwarg.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_database_empty_string_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_database_kwarg_isinstance.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_docstring_pins_check_same_thread_contract.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_eager_address_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_enter_eager.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_executemany_outer_shape_check.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_exit_commit_ki_breadcrumb.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_exit_short_circuits_on_closed.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_messages_cleared_by_cursor_methods.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_connection_row_factory_setter_closed_check.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_context_manager_exit.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_convert_bind_param_conform_exception_propagates.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cte_prefix_stripper_edges.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_after_external_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_close_clears_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_close_cross_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_close_preserves_body_exception_on_messages_strip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_close_releases_connection_pin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_closed_after_connection_gc_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_closed_state_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_completed_iterations_resets_on_single_execute.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_connection_partial_init_attributeerror.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_connection_property_after_gc_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_execute_non_str_operation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_execute_state_reset_on_failure.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_executemany_non_str_operation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_executemany_outer_shape_check.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_factory_kwarg_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_force_close_race.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_iter_clears_messages_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_iterator_reset.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_kwargs_rejection_precedence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_next_row_factory_raise_replays_row.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_per_row_types.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_post_close_property_reads.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_protocol_check.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_rejects_generator_params.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_repr_with_gced_parent_connection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_row_factory_rejecting_setter.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_row_factory_subclass_inheritance.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_row_index_reset.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_rowcount_after_ddl_stdlib_parity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_rownumber_affinity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_rownumber_post_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_scroll_mode_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_secondary_methods_positional_only.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_setinputsizes_affinity_precedes_shape.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_setinputsizes_setoutputsize_closed_state_precedes_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_setters_clear_messages_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_stop_iteration_contract.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursor_uses_run_protocol.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_cursors_weakset_state_lock.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_date_widens_to_datetime.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_datetime_from_iso8601_docstring_two_step_fallback.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_datetime_time_round_trip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_commit_deferred_fk.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_default_timeouts_use_client_constants.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_exception_message_arg_cap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_exception_raw_message_cap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_fork_guard_cluster.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dbapi_hardening.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_description_strict_type_codes.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_description_tuple_public_alias.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_diagnostic_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dial_attempt_timeout_propagation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dial_func_propagation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dial_func_propagation_to_leader_resolve.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_doc_class_and_description_drift.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_dqlite_namespace_error_classification.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_ensure_loop_fast_path_snapshot_dcl_defence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_ensure_loop_post_fork_pid_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_error_code_mapping.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_error_pickle_cause_either_or.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_error_pickle_preserves_raw_message.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exception_coded_mixin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exception_mapping.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exception_repr_code.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exception_wrapping.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exceptions.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_execute_caller_param_shape_preserves_prior_state.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_execute_executemany_positional_only.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_execute_multi_statement_rejection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_execute_reject_scrubs_prior_result_state.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_accumulator_semantics.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_basecaught_state_reset.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_classifier_resets_state_first.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_classify_caller_sql_hoisted.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_completed_iterations_snapshot_conditional_restore.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_dict_subclass_accepted.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_empty.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_empty_batch_preserves_lastrowid.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_none_seq_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_per_iter_structural_rejects.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_pragma_with_leading_comment.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_reject_scrubs_prior_result_state.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_rejects_pure_queries.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_rejects_transaction_verbs.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_executemany_returning_cap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_exit_logs_rollback_failure.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchall_row_factory_raise_replay.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_edges.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_negative_size_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_non_int_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_one_clear_per_call_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_row_factory_raise_replay.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fetchmany_zero_docstring_stdlib_divergence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_finalizer_strict_warnings.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_cancel_and_observe_narrow_suppress.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_observe_ast_pin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_observe_callback_coverage.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_cleanup_tail_unconditional.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_clears_messages.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_cross_thread_cancel_threadsafe.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_cursor_cascade_threadsafe.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_defensive_arms.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_disarms_inner_finalizer.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_pending_drain_resnapshot.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_force_close_transport_writer_cross_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fork_diagnostic_includes_pids.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_fromticks_tz_policy.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_gc_cleanup.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_get_resolve_leader_cluster_no_loop_raises_runtime_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_in_transaction_after_close.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_in_transaction_closed_divergence_doc.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_in_transaction_closed_foreign_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_in_transaction_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_in_transaction_property_under_check_same_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_init_docstring_fromticks_three_impls.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_is_multi_statement_walker.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_is_no_transaction_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_is_row_returning_multiline_whitespace.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_is_row_returning_sql_noise.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_aware_microseconds_round_trip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_decoder_leap_seconds_rejected.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_decoder_subsecond_truncation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_encoder.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_encoder_fold.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_encoder_utcoffset_exception_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_parse_error_truncation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iso8601_tzinfo_exception_classes_wrapped.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_isolation_level_stdlib_accept_set.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_iterdump_stub_signature_3_13_filter_kwarg.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_lastrowid_docstring_stdlib_parity_claim.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_lastrowid_insert_only.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_lastrowid_signed_int64_cast.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_leader_error_codes_identity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_leader_redirect_on_connect.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_legacy_transaction_control_constant.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_max_continuation_frames_upper_bound.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_max_message_size_round_trip.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_max_total_rows_plumbing.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_max_total_rows_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_messages_attribute.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_messages_clear_on_ctxmgr_entry.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_module_level_stubs.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_nextset_noreturn_annotation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_no_transaction_substrings_source_of_truth.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_no_tx_primary_codes_invariant.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_op_lock_bounded_acquire.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_operational_error_classification.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_operational_error_raw_message.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_param_conversion.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_param_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_paramstyle_qmark_only_pin.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_parse_decltypes_colnames_constants.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_database_error_routing.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_exception_aliases.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_messages_clearing.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_messages_independence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_misc_pins.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_stub_hasattr_divergence.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_type_constructors_vs_singletons.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_type_constructors_wrap_valueerror.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pep249_type_objects_final_annotated.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pickle_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pragma_busy_timeout_intercept.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pragma_write_description_none.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_prepare_protocol_in_types_all.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_property_round_trip_and_fork_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_property_setters_do_not_mirror_to_inner_async_conn.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_protocol_serialization.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_pyproject_dependency_graph.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_readme_truthfulness_pins.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_register_adapter_conform_fallback.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_register_adapter_global_sync_aio_symmetry.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_repr.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_repr_sanitizes_address.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_resolve_leader_cache_dial_func_id_recycle.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_resolve_leader_cache_lock_atfork_hook.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_resolve_leader_cluster_cache.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_resolve_leader_cross_loop_isolation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_row_factory_annotation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_row_factory_sqlite3_row_surfaces_dataerror.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_rowid_number_overlap_documented.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_rownumber_closed_cursor_returns_none_documented.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_ensure_loop_raise_closes_coroutine.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_keyboard_interrupt.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_keyboard_interrupt_cleanup_paths.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_ki_post_schedule_pre_await.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_ki_race_recovery.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_loop_closed_during_schedule.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_other_runtimeerror_propagates.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_timeout.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_run_sync_timeout_recovery_preserves_conn.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_secondary_methods_clear_messages_before_thread_check.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setinputsizes_accepts_none.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setinputsizes_clears_messages_per_pep249.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setinputsizes_non_sequence_iterable.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setinputsizes_sequence_acceptance.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setinputsizes_short_circuit_on_closed_connection.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setoutputsize_accepts_none.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_setter_closed_state_precedes_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sqlite_errorname_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sqlite_version_not_public_attribute.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_strip_leading_comments_bom.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_strip_leading_comments_parity.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_strip_sql_noise_backtick_identifier.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_stub_signatures_normalize_to_dbapi_error.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_submodule_all.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_commit_rollback_closed_precedes_thread.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_commit_rollback_inside_ctxmgr_guard.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_commit_rollback_messages_under_lock.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_commit_rollback_retry_after_invalidate.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_connection_execute_shortcut.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_connection_executemany_shortcut.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_cursor_post_add_closed_recheck.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_exit_signal_mid_rollback.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_fetchmany_cancel_atomic.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_force_close_transport.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_force_close_transport_pending_drain_reap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_invalidated_property.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_sync_run_sync_multiphase_timeout.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_thread_safety_enforcement.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_timeout_validation.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_top_level_logger_has_null_handler.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_total_changes_hasattr_safe.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_transitive_wire_import.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_type_coercion_documented_asymmetries.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_types_validator_branches.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_unregister_adapter_rejects_built_in_datetime_types.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_unsupported_method_stubs.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_validate_positive_int_pep249_wrap.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_validate_ticks.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_version.py +0 -0
- {dqlite_dbapi-0.2.1 → dqlite_dbapi-0.2.2}/tests/test_version_export.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dqlite-dbapi
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: PEP 249 (DB-API 2.0) compliant interface for dqlite
|
|
5
5
|
Project-URL: Homepage, https://github.com/letsdiscodev/python-dqlite-dbapi
|
|
6
6
|
Project-URL: Repository, https://github.com/letsdiscodev/python-dqlite-dbapi
|
|
@@ -22,8 +22,8 @@ Classifier: Topic :: Database :: Database Engines/Servers
|
|
|
22
22
|
Classifier: Topic :: Database :: Front-Ends
|
|
23
23
|
Classifier: Typing :: Typed
|
|
24
24
|
Requires-Python: >=3.13
|
|
25
|
-
Requires-Dist: dqlite-client<0.3.0,>=0.2.
|
|
26
|
-
Requires-Dist: dqlite-wire<0.3.0,>=0.2.
|
|
25
|
+
Requires-Dist: dqlite-client<0.3.0,>=0.2.2
|
|
26
|
+
Requires-Dist: dqlite-wire<0.3.0,>=0.2.2
|
|
27
27
|
Provides-Extra: dev
|
|
28
28
|
Requires-Dist: mypy>=1.0; extra == 'dev'
|
|
29
29
|
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "dqlite-dbapi"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "PEP 249 (DB-API 2.0) compliant interface for dqlite"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -26,8 +26,8 @@ classifiers = [
|
|
|
26
26
|
"Typing :: Typed",
|
|
27
27
|
]
|
|
28
28
|
dependencies = [
|
|
29
|
-
"dqlite-client>=0.2.
|
|
30
|
-
"dqlite-wire>=0.2.
|
|
29
|
+
"dqlite-client>=0.2.2,<0.3.0",
|
|
30
|
+
"dqlite-wire>=0.2.2,<0.3.0",
|
|
31
31
|
]
|
|
32
32
|
|
|
33
33
|
[tool.uv.sources]
|
|
@@ -71,6 +71,7 @@ from dqlitedbapi.connection import (
|
|
|
71
71
|
)
|
|
72
72
|
from dqlitedbapi.cursor import Cursor
|
|
73
73
|
from dqlitedbapi.exceptions import (
|
|
74
|
+
AdapterLookupError,
|
|
74
75
|
AmbiguousCommitError,
|
|
75
76
|
DatabaseError,
|
|
76
77
|
DataError,
|
|
@@ -83,12 +84,14 @@ from dqlitedbapi.exceptions import (
|
|
|
83
84
|
ProgrammingError,
|
|
84
85
|
Warning,
|
|
85
86
|
)
|
|
87
|
+
from dqlitedbapi.row import Row
|
|
86
88
|
from dqlitedbapi.types import (
|
|
87
89
|
BINARY,
|
|
88
90
|
DATETIME,
|
|
89
91
|
NUMBER,
|
|
90
92
|
ROWID,
|
|
91
93
|
STRING,
|
|
94
|
+
UNKNOWN,
|
|
92
95
|
Binary,
|
|
93
96
|
Date,
|
|
94
97
|
DateFromTicks,
|
|
@@ -171,7 +174,7 @@ LEGACY_TRANSACTION_CONTROL: _Final[int] = -1
|
|
|
171
174
|
PARSE_DECLTYPES: _Final[int] = 1
|
|
172
175
|
PARSE_COLNAMES: _Final[int] = 2
|
|
173
176
|
|
|
174
|
-
__version__: _Final[str] = "0.2.
|
|
177
|
+
__version__: _Final[str] = "0.2.2"
|
|
175
178
|
|
|
176
179
|
__all__ = [ # grouped by PEP 249 section, not alphabetical
|
|
177
180
|
# Module attributes
|
|
@@ -214,6 +217,7 @@ __all__ = [ # grouped by PEP 249 section, not alphabetical
|
|
|
214
217
|
"InternalError",
|
|
215
218
|
"ProgrammingError",
|
|
216
219
|
"NotSupportedError",
|
|
220
|
+
"AdapterLookupError",
|
|
217
221
|
# Type constructors
|
|
218
222
|
"Date",
|
|
219
223
|
"Time",
|
|
@@ -228,6 +232,9 @@ __all__ = [ # grouped by PEP 249 section, not alphabetical
|
|
|
228
232
|
"NUMBER",
|
|
229
233
|
"DATETIME",
|
|
230
234
|
"ROWID",
|
|
235
|
+
"UNKNOWN",
|
|
236
|
+
# Row factory (sqlite3.Row equivalent)
|
|
237
|
+
"Row",
|
|
231
238
|
# Type aliases
|
|
232
239
|
"DescriptionTuple",
|
|
233
240
|
]
|
|
@@ -248,6 +255,7 @@ def connect(
|
|
|
248
255
|
dial_func: DialFunc | None = None,
|
|
249
256
|
busy_timeout: float = 5.0,
|
|
250
257
|
check_same_thread: bool = True,
|
|
258
|
+
session_mode: str | None = None,
|
|
251
259
|
**unknown_kwargs: object,
|
|
252
260
|
) -> Connection:
|
|
253
261
|
"""Connect to a dqlite database.
|
|
@@ -406,6 +414,7 @@ def connect(
|
|
|
406
414
|
dial_func=dial_func,
|
|
407
415
|
busy_timeout=busy_timeout,
|
|
408
416
|
check_same_thread=check_same_thread,
|
|
417
|
+
session_mode=session_mode,
|
|
409
418
|
)
|
|
410
419
|
# Apply the validated ``isolation_level`` / ``autocommit`` kwargs
|
|
411
420
|
# via the setters on the freshly-constructed connection. Stdlib
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""Pre-wire SQL interception at the dbapi cursor layer.
|
|
2
|
+
|
|
3
|
+
This module hosts two interceptions that rewrite or short-circuit
|
|
4
|
+
caller SQL before it reaches the dqlite wire:
|
|
5
|
+
|
|
6
|
+
1. ``PRAGMA busy_timeout`` — see ``try_intercept_busy_timeout`` below
|
|
7
|
+
for the rationale (authorizer rejection of the canonical SQLite
|
|
8
|
+
knob).
|
|
9
|
+
|
|
10
|
+
2. Bare ``BEGIN`` (and ``BEGIN TRANSACTION``) — rewritten to
|
|
11
|
+
``BEGIN IMMEDIATE`` when the connection's ``session_mode`` is
|
|
12
|
+
``"immediate"`` (the default). The writer-lock is acquired at
|
|
13
|
+
BEGIN time so the SELECT-then-INSERT pattern cannot be overtaken
|
|
14
|
+
by a concurrent committer (the ``SQLITE_BUSY_SNAPSHOT`` race).
|
|
15
|
+
dqlite-server's own VFS recommends ``BEGIN IMMEDIATE`` for
|
|
16
|
+
write-bearing transactions. Pass-through for ``BEGIN DEFERRED``
|
|
17
|
+
/ ``BEGIN IMMEDIATE`` / ``BEGIN EXCLUSIVE`` (caller intent
|
|
18
|
+
already correct).
|
|
19
|
+
|
|
20
|
+
Other session modes (``"deferred"`` / ``"exclusive"`` /
|
|
21
|
+
``"read_only"``) leave bare ``BEGIN`` untouched — the SQLite
|
|
22
|
+
engine treats it as DEFERRED, which is the right semantic for
|
|
23
|
+
read-only sessions and for callers who explicitly want the
|
|
24
|
+
legacy DEFERRED behaviour. The ``"exclusive"`` mode is reached
|
|
25
|
+
via the SA dialect's ``do_begin`` emitting the explicit
|
|
26
|
+
``BEGIN EXCLUSIVE`` literal, which doesn't match the rewrite
|
|
27
|
+
regex anyway.
|
|
28
|
+
|
|
29
|
+
Configuration: ``Connection(session_mode="…")`` kwarg, URL
|
|
30
|
+
``?session_mode=…``, or ``DQLITE_SESSION_MODE`` env var.
|
|
31
|
+
|
|
32
|
+
The PRAGMA interception writes cursor result state directly:
|
|
33
|
+
|
|
34
|
+
- Setter (``PRAGMA busy_timeout = N`` or ``PRAGMA busy_timeout(N)``)
|
|
35
|
+
updates ``connection._busy_timeout`` in seconds (N is ms per
|
|
36
|
+
SQLite convention; we divide by 1000) and emits the new value as
|
|
37
|
+
a single-row result, matching stdlib's PRAGMA result-set shape.
|
|
38
|
+
- Getter (``PRAGMA busy_timeout``) emits the current value as a
|
|
39
|
+
single-row result.
|
|
40
|
+
|
|
41
|
+
Case-insensitive and whitespace-tolerant per SQLite parser
|
|
42
|
+
conventions. Multi-statement strings ARE rejected (only a SINGLE
|
|
43
|
+
``PRAGMA busy_timeout`` statement is intercepted; multi-statement
|
|
44
|
+
inputs surface to the wire where the existing multi-statement
|
|
45
|
+
classifier rejects them with ``ProgrammingError`` — that path is
|
|
46
|
+
unchanged).
|
|
47
|
+
|
|
48
|
+
The interception writes the cursor's result state directly:
|
|
49
|
+
|
|
50
|
+
- ``_description = (("busy_timeout", None, None, None, None, None, None),)``
|
|
51
|
+
- ``_rows = [(N_ms_clamped,)]``
|
|
52
|
+
- ``_rowcount = -1`` (PRAGMA does not have a meaningful row count)
|
|
53
|
+
- ``_row_index = 0``
|
|
54
|
+
|
|
55
|
+
Then returns True so the caller short-circuits before the wire
|
|
56
|
+
round-trip.
|
|
57
|
+
|
|
58
|
+
The BEGIN rewrite, by contrast, returns the rewritten SQL string
|
|
59
|
+
(or ``None`` to leave the caller's SQL unchanged) — there is no
|
|
60
|
+
cursor state to populate; the caller substitutes the SQL and lets
|
|
61
|
+
the rewritten ``BEGIN IMMEDIATE`` flow through the regular wire
|
|
62
|
+
round-trip.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
from __future__ import annotations
|
|
66
|
+
|
|
67
|
+
import os
|
|
68
|
+
import re
|
|
69
|
+
from typing import TYPE_CHECKING, Final
|
|
70
|
+
|
|
71
|
+
if TYPE_CHECKING:
|
|
72
|
+
from dqlitedbapi.cursor import Cursor
|
|
73
|
+
|
|
74
|
+
# Match ``PRAGMA busy_timeout`` with optional setter forms:
|
|
75
|
+
#
|
|
76
|
+
# PRAGMA busy_timeout
|
|
77
|
+
# PRAGMA busy_timeout = 5000
|
|
78
|
+
# PRAGMA busy_timeout=5000
|
|
79
|
+
# pragma BUSY_TIMEOUT = 5000
|
|
80
|
+
# PRAGMA busy_timeout(5000)
|
|
81
|
+
#
|
|
82
|
+
# The trailing ``;?`` accommodates the canonical single-statement
|
|
83
|
+
# terminator. A semicolon followed by additional content (multi-
|
|
84
|
+
# statement) does NOT match — those route to the wire where the
|
|
85
|
+
# existing multi-statement classifier rejects them.
|
|
86
|
+
_PRAGMA_BUSY_TIMEOUT_RE = re.compile(
|
|
87
|
+
r"^\s*PRAGMA\s+busy_timeout\s*"
|
|
88
|
+
r"(?:=\s*(?P<setter_eq>-?\d+)|\(\s*(?P<setter_paren>-?\d+)\s*\))?"
|
|
89
|
+
r"\s*;?\s*$",
|
|
90
|
+
re.IGNORECASE,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def try_intercept_busy_timeout(
|
|
95
|
+
cursor: Cursor,
|
|
96
|
+
statement: str,
|
|
97
|
+
parameters: object,
|
|
98
|
+
) -> bool:
|
|
99
|
+
"""Return True if the statement is ``PRAGMA busy_timeout`` (any
|
|
100
|
+
form) and the cursor's result state has been populated.
|
|
101
|
+
|
|
102
|
+
When True, the caller MUST short-circuit BEFORE the wire round-
|
|
103
|
+
trip (the server would reject the PRAGMA via the VFS authorizer
|
|
104
|
+
if it reached the wire, defeating the interception's purpose).
|
|
105
|
+
|
|
106
|
+
``parameters`` is accepted for caller-signature parity but
|
|
107
|
+
PRAGMA does not take parameters. If parameters are non-empty
|
|
108
|
+
we still match the PRAGMA and ignore them — the engine would
|
|
109
|
+
do the same. (A future refinement could raise a friendlier
|
|
110
|
+
error here, but stdlib silently accepts the same shape.)
|
|
111
|
+
"""
|
|
112
|
+
if not isinstance(statement, str):
|
|
113
|
+
return False
|
|
114
|
+
match = _PRAGMA_BUSY_TIMEOUT_RE.match(statement)
|
|
115
|
+
if match is None:
|
|
116
|
+
return False
|
|
117
|
+
setter_eq = match.group("setter_eq")
|
|
118
|
+
setter_paren = match.group("setter_paren")
|
|
119
|
+
setter_value = setter_eq if setter_eq is not None else setter_paren
|
|
120
|
+
connection = cursor._connection
|
|
121
|
+
if setter_value is not None:
|
|
122
|
+
# Setter form: update connection._busy_timeout.
|
|
123
|
+
# SQLite clamps negative values to 0 (no wait) — stdlib parity.
|
|
124
|
+
new_ms = max(0, int(setter_value))
|
|
125
|
+
connection._busy_timeout = new_ms / 1000.0
|
|
126
|
+
# Both setter AND getter forms emit the (possibly updated) value
|
|
127
|
+
# as a single-row result. Matches SQLite's PRAGMA convention:
|
|
128
|
+
# ``PRAGMA busy_timeout = 5000`` returns ``(5000,)``,
|
|
129
|
+
# ``PRAGMA busy_timeout`` (getter) also returns ``(5000,)``.
|
|
130
|
+
current_ms = int(connection._busy_timeout * 1000)
|
|
131
|
+
cursor._description = (("busy_timeout", None, None, None, None, None, None),)
|
|
132
|
+
cursor._rows = [(current_ms,)]
|
|
133
|
+
cursor._rowcount = -1
|
|
134
|
+
cursor._row_index = 0
|
|
135
|
+
# Match stdlib: PRAGMA does not set lastrowid.
|
|
136
|
+
return True
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# Match the BEGIN forms that should be upgraded to BEGIN IMMEDIATE:
|
|
140
|
+
#
|
|
141
|
+
# BEGIN
|
|
142
|
+
# BEGIN;
|
|
143
|
+
# BEGIN TRANSACTION
|
|
144
|
+
# BEGIN TRANSACTION;
|
|
145
|
+
#
|
|
146
|
+
# Explicit ``BEGIN DEFERRED`` / ``BEGIN IMMEDIATE`` / ``BEGIN
|
|
147
|
+
# EXCLUSIVE`` MUST NOT match — the caller (or the SA dialect's
|
|
148
|
+
# per-session ``dqlite_session_mode`` opt-out) has stated explicit
|
|
149
|
+
# intent. The bare ``BEGIN`` form is what SA emits by default
|
|
150
|
+
# and what most callers reach for; it is the only ambiguous
|
|
151
|
+
# shape that benefits from the writer-safe upgrade.
|
|
152
|
+
_BEGIN_REWRITE_RE = re.compile(
|
|
153
|
+
r"^\s*BEGIN(?:\s+TRANSACTION)?\s*;?\s*$",
|
|
154
|
+
re.IGNORECASE,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# Recognised session-mode values. The dbapi layer accepts these as
|
|
158
|
+
# the ``session_mode`` kwarg / URL form / env-var value, the SA
|
|
159
|
+
# dialect accepts the same set as ``dqlite_session_mode``
|
|
160
|
+
# execution-option values, and the cursor's BEGIN-rewrite intercept
|
|
161
|
+
# reads ``conn._dqlite_session_mode`` against this set.
|
|
162
|
+
#
|
|
163
|
+
# - ``"immediate"`` (default): bare ``BEGIN`` is rewritten to
|
|
164
|
+
# ``BEGIN IMMEDIATE`` — writer-safe, no SQLITE_BUSY_SNAPSHOT race.
|
|
165
|
+
# - ``"deferred"``: legacy SQLite DEFERRED — bare ``BEGIN`` passes
|
|
166
|
+
# through unchanged. Read-only sessions that want to avoid the
|
|
167
|
+
# writer-lock serialisation tax can opt in.
|
|
168
|
+
# - ``"exclusive"``: dialect emits the explicit ``BEGIN EXCLUSIVE``
|
|
169
|
+
# literal for stronger lock semantics.
|
|
170
|
+
# - ``"read_only"``: bare ``BEGIN`` passes through (DEFERRED form)
|
|
171
|
+
# AND ``PRAGMA query_only = 1`` is set on the connection so the
|
|
172
|
+
# engine rejects every write at PREPARE with SQLITE_READONLY.
|
|
173
|
+
_SESSION_MODE_VALUES: Final[frozenset[str]] = frozenset(
|
|
174
|
+
{"immediate", "deferred", "exclusive", "read_only"}
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
# Env-var default for the session mode. Read at module-import time;
|
|
178
|
+
# explicit ``connect(..., session_mode=...)`` always wins. Missing or
|
|
179
|
+
# empty → ``"immediate"`` (the writer-safe default). Any value
|
|
180
|
+
# outside ``_SESSION_MODE_VALUES`` raises at validation; here we just
|
|
181
|
+
# normalise and return the raw string.
|
|
182
|
+
_DQLITE_SESSION_MODE_ENV: Final[str] = os.environ.get("DQLITE_SESSION_MODE", "").strip().lower()
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def session_mode_default_from_env() -> str:
|
|
186
|
+
"""Return the env-var-derived default for the connection's
|
|
187
|
+
session mode.
|
|
188
|
+
|
|
189
|
+
Used by ``Connection.__init__`` when the caller does not pass an
|
|
190
|
+
explicit ``session_mode`` kwarg. Re-read at each call so test
|
|
191
|
+
fixtures that ``monkeypatch.setenv`` see the live value (the
|
|
192
|
+
module-level cache is only used as the fallback when the env var
|
|
193
|
+
was set at import time).
|
|
194
|
+
|
|
195
|
+
Missing / empty env var → ``"immediate"`` (writer-safe default).
|
|
196
|
+
Invalid value raises ``ValueError`` so misconfiguration surfaces
|
|
197
|
+
at construct time, not at first ``do_begin``.
|
|
198
|
+
"""
|
|
199
|
+
raw = os.environ.get("DQLITE_SESSION_MODE")
|
|
200
|
+
value = (raw if raw is not None else _DQLITE_SESSION_MODE_ENV).strip().lower()
|
|
201
|
+
if not value:
|
|
202
|
+
return "immediate"
|
|
203
|
+
if value not in _SESSION_MODE_VALUES:
|
|
204
|
+
raise ValueError(
|
|
205
|
+
f"DQLITE_SESSION_MODE={raw!r} is not one of {sorted(_SESSION_MODE_VALUES)}"
|
|
206
|
+
)
|
|
207
|
+
return value
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
def validate_session_mode(value: object) -> str:
|
|
211
|
+
"""Coerce + validate a ``session_mode`` value.
|
|
212
|
+
|
|
213
|
+
Returns the canonical lowercase form. Raises ``ValueError`` for
|
|
214
|
+
anything outside ``_SESSION_MODE_VALUES`` so misconfiguration
|
|
215
|
+
surfaces at the boundary (constructor or
|
|
216
|
+
``execution_options(...)`` call), not at the first ``do_begin``.
|
|
217
|
+
|
|
218
|
+
Accepts ``None`` as "use the env-var default" (caller is
|
|
219
|
+
responsible for substituting via ``session_mode_default_from_env``
|
|
220
|
+
when they want that semantics).
|
|
221
|
+
"""
|
|
222
|
+
if not isinstance(value, str):
|
|
223
|
+
raise ValueError(f"session_mode must be a str, got {type(value).__name__}")
|
|
224
|
+
normalised = value.lower()
|
|
225
|
+
if normalised not in _SESSION_MODE_VALUES:
|
|
226
|
+
raise ValueError(
|
|
227
|
+
f"Invalid session_mode {value!r}; valid values are {sorted(_SESSION_MODE_VALUES)}"
|
|
228
|
+
)
|
|
229
|
+
return normalised
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def try_rewrite_begin_to_immediate(
|
|
233
|
+
statement: str,
|
|
234
|
+
*,
|
|
235
|
+
session_mode: str,
|
|
236
|
+
) -> str | None:
|
|
237
|
+
"""Return ``"BEGIN IMMEDIATE"`` if ``statement`` is a plain BEGIN
|
|
238
|
+
form AND the connection's session mode is ``"immediate"``, else
|
|
239
|
+
``None`` (caller leaves the SQL unchanged).
|
|
240
|
+
|
|
241
|
+
The rewrite fires only when ``session_mode == "immediate"`` — the
|
|
242
|
+
writer-safe default. Other modes (``"deferred"``, ``"exclusive"``,
|
|
243
|
+
``"read_only"``) leave bare ``BEGIN`` untouched:
|
|
244
|
+
|
|
245
|
+
- ``"deferred"`` / ``"read_only"``: the SQLite engine interprets
|
|
246
|
+
bare ``BEGIN`` as DEFERRED, which is what these modes want.
|
|
247
|
+
Rewriting to IMMEDIATE would take a useless writer-lock.
|
|
248
|
+
- ``"exclusive"``: the SA dialect's ``do_begin`` emits the
|
|
249
|
+
explicit ``BEGIN EXCLUSIVE`` literal, which doesn't match the
|
|
250
|
+
bare-BEGIN regex anyway. The exclusive case never reaches this
|
|
251
|
+
function with a bare BEGIN under normal SA usage.
|
|
252
|
+
|
|
253
|
+
A ``None`` return also covers the case where ``statement`` is not
|
|
254
|
+
a recognised plain-BEGIN form (e.g. explicit ``BEGIN IMMEDIATE``
|
|
255
|
+
/ ``BEGIN DEFERRED`` / ``BEGIN EXCLUSIVE`` / non-BEGIN statement).
|
|
256
|
+
Caller passes the original SQL through unchanged.
|
|
257
|
+
"""
|
|
258
|
+
if session_mode != "immediate":
|
|
259
|
+
return None
|
|
260
|
+
if not isinstance(statement, str):
|
|
261
|
+
return None
|
|
262
|
+
if _BEGIN_REWRITE_RE.match(statement) is None:
|
|
263
|
+
return None
|
|
264
|
+
return "BEGIN IMMEDIATE"
|
|
@@ -43,6 +43,8 @@ from dqlitedbapi import ( # module-level re-export
|
|
|
43
43
|
CLUSTER_POLICY_REJECTION_PREFIX,
|
|
44
44
|
FAILED_TO_CONNECT_PREFIX,
|
|
45
45
|
MAX_CONTINUATION_FRAMES_UPPER_BOUND,
|
|
46
|
+
UNKNOWN,
|
|
47
|
+
Row,
|
|
46
48
|
complete_statement,
|
|
47
49
|
enable_callback_tracebacks,
|
|
48
50
|
register_converter,
|
|
@@ -60,6 +62,7 @@ from dqlitedbapi._constants import (
|
|
|
60
62
|
from dqlitedbapi.aio.connection import AsyncConnection
|
|
61
63
|
from dqlitedbapi.aio.cursor import AsyncCursor
|
|
62
64
|
from dqlitedbapi.exceptions import (
|
|
65
|
+
AdapterLookupError,
|
|
63
66
|
AmbiguousCommitError,
|
|
64
67
|
DatabaseError,
|
|
65
68
|
DataError,
|
|
@@ -174,6 +177,7 @@ __all__ = [ # grouped by PEP 249 section, not alphabetical
|
|
|
174
177
|
"InternalError",
|
|
175
178
|
"ProgrammingError",
|
|
176
179
|
"NotSupportedError",
|
|
180
|
+
"AdapterLookupError",
|
|
177
181
|
# dqlite-specific OperationalError subclass marking an in-doubt
|
|
178
182
|
# commit (leader flip mid-COMMIT). Exposed alongside the PEP 249
|
|
179
183
|
# standard set for cross-driver introspection symmetry.
|
|
@@ -192,6 +196,9 @@ __all__ = [ # grouped by PEP 249 section, not alphabetical
|
|
|
192
196
|
"NUMBER",
|
|
193
197
|
"DATETIME",
|
|
194
198
|
"ROWID",
|
|
199
|
+
"UNKNOWN",
|
|
200
|
+
# Row factory (sqlite3.Row equivalent)
|
|
201
|
+
"Row",
|
|
195
202
|
# Type aliases
|
|
196
203
|
"DescriptionTuple",
|
|
197
204
|
# Type-adapter registry (shared module-global with the sync
|
|
@@ -233,6 +240,7 @@ def connect(
|
|
|
233
240
|
attempt_timeout: float | None = None,
|
|
234
241
|
dial_func: DialFunc | None = None,
|
|
235
242
|
busy_timeout: float = 5.0,
|
|
243
|
+
session_mode: str | None = None,
|
|
236
244
|
**unknown_kwargs: object,
|
|
237
245
|
) -> AsyncConnection:
|
|
238
246
|
"""Create a dqlite connection (connects lazily on first use).
|
|
@@ -361,6 +369,7 @@ def connect(
|
|
|
361
369
|
attempt_timeout=attempt_timeout,
|
|
362
370
|
dial_func=dial_func,
|
|
363
371
|
busy_timeout=busy_timeout,
|
|
372
|
+
session_mode=session_mode,
|
|
364
373
|
)
|
|
365
374
|
# Apply the validated ``isolation_level`` / ``autocommit`` kwargs
|
|
366
375
|
# via the setters on the freshly-constructed connection — sync
|
|
@@ -386,6 +395,7 @@ async def aconnect(
|
|
|
386
395
|
attempt_timeout: float | None = None,
|
|
387
396
|
dial_func: DialFunc | None = None,
|
|
388
397
|
busy_timeout: float = 5.0,
|
|
398
|
+
session_mode: str | None = None,
|
|
389
399
|
**unknown_kwargs: object,
|
|
390
400
|
) -> AsyncConnection:
|
|
391
401
|
"""Connect to a dqlite database asynchronously.
|
|
@@ -506,6 +516,7 @@ async def aconnect(
|
|
|
506
516
|
attempt_timeout=attempt_timeout,
|
|
507
517
|
dial_func=dial_func,
|
|
508
518
|
busy_timeout=busy_timeout,
|
|
519
|
+
session_mode=session_mode,
|
|
509
520
|
)
|
|
510
521
|
try:
|
|
511
522
|
await conn.connect()
|
|
@@ -560,6 +571,21 @@ async def aconnect(
|
|
|
560
571
|
"aconnect: exception during cleanup-close after failed connect",
|
|
561
572
|
exc_info=True,
|
|
562
573
|
)
|
|
574
|
+
# Defensive null-out: mirrors AsyncConnection.__aenter__'s
|
|
575
|
+
# cleanup arm. ``close()`` may have short-circuited at its
|
|
576
|
+
# TOP-of-method ``if self._closed: return`` guard because a
|
|
577
|
+
# concurrent close (foreign-thread ``force_close_transport``)
|
|
578
|
+
# flipped ``_closed=True`` first. The short-circuit then
|
|
579
|
+
# skips the never-connected branch that nulls these slots,
|
|
580
|
+
# leaving the lazy loop-bound primitives stale. A subsequent
|
|
581
|
+
# reuse on a different loop would hit a misleading
|
|
582
|
+
# cross-loop diagnostic in ``_ensure_locks`` instead of the
|
|
583
|
+
# documented fresh-connect path. Tolerate the attributes
|
|
584
|
+
# being absent on fixture-built objects.
|
|
585
|
+
with contextlib.suppress(AttributeError):
|
|
586
|
+
conn._connect_lock = None
|
|
587
|
+
conn._op_lock = None
|
|
588
|
+
conn._loop_ref = None
|
|
563
589
|
raise
|
|
564
590
|
# Apply the validated ``isolation_level`` / ``autocommit`` kwargs
|
|
565
591
|
# via the setters on the freshly-connected AsyncConnection. Stdlib
|