|
3 | 3 | import re |
4 | 4 | from collections.abc import Callable, Coroutine, Iterable, Mapping, Sequence |
5 | 5 | from types import TracebackType |
6 | | -from typing import TYPE_CHECKING, Any, Protocol |
| 6 | +from typing import TYPE_CHECKING, Any, Final, Protocol |
7 | 7 |
|
8 | 8 | import dqliteclient.exceptions as _client_exc |
9 | 9 | from dqlitedbapi.exceptions import ( |
|
35 | 35 | # FOREIGN_KEY = 787, etc.) all share ``code & 0xFF == 19``. PEP 249 |
36 | 36 | # mandates IntegrityError for these, so map them here rather than |
37 | 37 | # leaving every caller to inspect the code themselves. |
38 | | -_SQLITE_CONSTRAINT = 19 |
| 38 | +_SQLITE_CONSTRAINT: Final[int] = 19 |
39 | 39 |
|
40 | 40 | # SQLite primary error code 2 (SQLITE_INTERNAL). stdlib ``sqlite3`` |
41 | 41 | # routes this to ``sqlite3.InternalError`` (CPython's |
42 | 42 | # ``_pysqlite_seterror``); PEP 249 defines ``InternalError`` for exactly |
43 | 43 | # this purpose — "internal errors of the database, e.g. the cursor is |
44 | 44 | # not valid anymore". |
45 | | -_SQLITE_INTERNAL = 2 |
| 45 | +_SQLITE_INTERNAL: Final[int] = 2 |
46 | 46 |
|
47 | 47 | # SQLITE_TOOBIG (18) — "value exceeds size limit" — is the canonical |
48 | 48 | # PEP 249 ``DataError`` case ("problems with the processed data"). |
49 | | -_SQLITE_TOOBIG = 18 |
| 49 | +_SQLITE_TOOBIG: Final[int] = 18 |
50 | 50 |
|
51 | 51 | # SQLITE_MISMATCH (20) — datatype mismatch on STRICT tables. CPython |
52 | 52 | # stdlib ``sqlite3`` (``Modules/_sqlite/util.c::_pysqlite_seterror``) |
|
55 | 55 | # are defensible PEP 249 readings for STRICT-table datatype mismatch, |
56 | 56 | # but callers porting between stdlib and dqlite expect the stdlib |
57 | 57 | # grouping — so align to it. |
58 | | -_SQLITE_MISMATCH = 20 |
| 58 | +_SQLITE_MISMATCH: Final[int] = 20 |
59 | 59 |
|
60 | 60 | # SQLITE_RANGE (25) — "bind index out of range" — is a caller-side |
61 | 61 | # parameter-binding error; PEP 249 ``ProgrammingError`` is the right |
62 | 62 | # fit ("bad parameter ... wrong number of parameters") rather than |
63 | 63 | # ``DataError``. |
64 | | -_SQLITE_RANGE = 25 |
| 64 | +_SQLITE_RANGE: Final[int] = 25 |
65 | 65 |
|
66 | 66 | # SQLITE_NOMEM (7) — server-side allocation failure. CPython stdlib |
67 | 67 | # ``sqlite3`` raises ``MemoryError`` (system-level, bypasses PEP 249); |
68 | 68 | # we route through ``InternalError`` so callers stay inside the |
69 | 69 | # PEP 249 hierarchy and ``except dbapi.Error:`` continues to catch. |
70 | | -_SQLITE_NOMEM = 7 |
| 70 | +_SQLITE_NOMEM: Final[int] = 7 |
71 | 71 |
|
72 | 72 | # SQLITE_CORRUPT (11), SQLITE_FORMAT (24), SQLITE_NOTADB (26) — the |
73 | 73 | # server-side database file is malformed / wrong format / not a |
|
84 | 84 | # default unmapped codes to OperationalError so this entry is |
85 | 85 | # documentary — it pins the contract so a future audit shows the |
86 | 86 | # code was considered. |
87 | | -_SQLITE_PROTOCOL = 15 |
| 87 | +_SQLITE_PROTOCOL: Final[int] = 15 |
88 | 88 |
|
89 | 89 | # Registry of primary-code → PEP 249 class. Keep the default |
90 | 90 | # (OperationalError) outside the dict so adding a code is one line. |
@@ -328,15 +328,15 @@ def _strip_leading_comments(sql: str) -> str: |
328 | 328 | return s |
329 | 329 |
|
330 | 330 |
|
331 | | -_ROW_RETURNING_PREFIXES = ("SELECT", "VALUES", "PRAGMA", "EXPLAIN", "WITH") |
| 331 | +_ROW_RETURNING_PREFIXES: Final[tuple[str, ...]] = ("SELECT", "VALUES", "PRAGMA", "EXPLAIN", "WITH") |
332 | 332 |
|
333 | 333 | # Verbs that take no parameters and cannot legitimately drive an |
334 | 334 | # ``executemany`` call. Stdlib ``sqlite3.Cursor.executemany`` rejects |
335 | 335 | # the same shapes via its statement-type check; admitting them here |
336 | 336 | # silently re-runs the bare statement N times against ignored bind |
337 | 337 | # params, producing duplicate server-side savepoint frames (and other |
338 | 338 | # state divergence) that compound with the duplicate-name LIFO rule. |
339 | | -_EXECUTEMANY_REJECT_VERBS = frozenset( |
| 339 | +_EXECUTEMANY_REJECT_VERBS: Final[frozenset[str]] = frozenset( |
340 | 340 | {"SAVEPOINT", "RELEASE", "ROLLBACK", "BEGIN", "COMMIT", "END"} |
341 | 341 | ) |
342 | 342 |
|
@@ -608,8 +608,8 @@ def _is_dml_with_returning(sql: str) -> bool: |
608 | 608 | return body.startswith(("INSERT", "UPDATE", "DELETE", "REPLACE")) |
609 | 609 |
|
610 | 610 |
|
611 | | -_INT64_OVERFLOW_THRESHOLD = 1 << 63 |
612 | | -_UINT64_RANGE = 1 << 64 |
| 611 | +_INT64_OVERFLOW_THRESHOLD: Final[int] = 1 << 63 |
| 612 | +_UINT64_RANGE: Final[int] = 1 << 64 |
613 | 613 |
|
614 | 614 |
|
615 | 615 | def _to_signed_int64(value: int) -> int: |
|
0 commit comments