Skip to content

Commit 04d5364

Browse files
Consolidate the max_total_rows validator into the shared helper
The protocol module had two positive-int-or-None validators with byte-identical behaviour: a generic `_validate_positive_int_or_none` that takes the parameter name as an argument, and an older `_validate_max_total_rows` that hardcoded the name into its error messages. Callers sometimes imported one, sometimes the other. Drop the specialised wrapper and route the four call sites (the two client modules, the pool, and the two dbapi connection modules) through the generic helper. Error messages are byte-identical when the helper is given `name="max_total_rows"`, so the existing validation tests continue to match the exact wording. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent ef541c1 commit 04d5364

4 files changed

Lines changed: 13 additions & 29 deletions

File tree

src/dqliteclient/connection.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
)
1717
from dqliteclient.protocol import (
1818
DqliteProtocol,
19-
_validate_max_total_rows,
2019
_validate_positive_int_or_none,
2120
)
2221
from dqlitewire.exceptions import EncodeError as _WireEncodeError
@@ -108,7 +107,7 @@ def __init__(
108107
self._address = address
109108
self._database = database
110109
self._timeout = timeout
111-
self._max_total_rows = _validate_max_total_rows(max_total_rows)
110+
self._max_total_rows = _validate_positive_int_or_none(max_total_rows, "max_total_rows")
112111
self._max_continuation_frames = _validate_positive_int_or_none(
113112
max_continuation_frames, "max_continuation_frames"
114113
)

src/dqliteclient/pool.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from dqliteclient.connection import DqliteConnection
1212
from dqliteclient.exceptions import DqliteConnectionError
1313
from dqliteclient.node_store import NodeStore
14-
from dqliteclient.protocol import _validate_max_total_rows, _validate_positive_int_or_none
14+
from dqliteclient.protocol import _validate_positive_int_or_none
1515

1616
logger = logging.getLogger(__name__)
1717

@@ -130,7 +130,7 @@ def __init__(
130130
self._min_size = min_size
131131
self._max_size = max_size
132132
self._timeout = timeout
133-
self._max_total_rows = _validate_max_total_rows(max_total_rows)
133+
self._max_total_rows = _validate_positive_int_or_none(max_total_rows, "max_total_rows")
134134
self._max_continuation_frames = _validate_positive_int_or_none(
135135
max_continuation_frames, "max_continuation_frames"
136136
)

src/dqliteclient/protocol.py

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,21 +47,6 @@ def _validate_positive_int_or_none(value: int | None, name: str) -> int | None:
4747
return value
4848

4949

50-
def _validate_max_total_rows(value: int | None) -> int | None:
51-
"""Validate the ``max_total_rows`` constructor argument.
52-
53-
``None`` disables the cap. Otherwise the value must be a positive
54-
``int`` (``bool`` is rejected even though it's a subclass of int).
55-
"""
56-
if value is None:
57-
return None
58-
if isinstance(value, bool) or not isinstance(value, int):
59-
raise TypeError(f"max_total_rows must be int or None, got {type(value).__name__}")
60-
if value <= 0:
61-
raise ValueError(f"max_total_rows must be > 0 or None, got {value}")
62-
return value
63-
64-
6550
class DqliteProtocol:
6651
"""Low-level protocol handler for a single dqlite connection."""
6752

@@ -85,7 +70,7 @@ def __init__(
8570
# the per-operation deadline; without a cumulative cap, clients
8671
# could legitimately allocate hundreds of millions of rows over
8772
# the full deadline. None disables the cap.
88-
self._max_total_rows = _validate_max_total_rows(max_total_rows)
73+
self._max_total_rows = _validate_positive_int_or_none(max_total_rows, "max_total_rows")
8974
# Per-query frame cap. Complements max_total_rows: a server
9075
# sending 10M 1-row frames to reach the row cap would still
9176
# burn 10M × decode-cost of Python work; the frame cap bounds

tests/test_max_total_rows_validation.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,37 +6,37 @@
66

77
from dqliteclient.connection import DqliteConnection
88
from dqliteclient.pool import ConnectionPool
9-
from dqliteclient.protocol import DqliteProtocol, _validate_max_total_rows
9+
from dqliteclient.protocol import DqliteProtocol, _validate_positive_int_or_none
1010

1111

1212
class TestValidator:
1313
def test_none_allowed(self) -> None:
14-
assert _validate_max_total_rows(None) is None
14+
assert _validate_positive_int_or_none(None, "max_total_rows") is None
1515

1616
def test_positive_int_allowed(self) -> None:
17-
assert _validate_max_total_rows(1) == 1
18-
assert _validate_max_total_rows(10_000_000) == 10_000_000
17+
assert _validate_positive_int_or_none(1, "max_total_rows") == 1
18+
assert _validate_positive_int_or_none(10_000_000, "max_total_rows") == 10_000_000
1919

2020
def test_zero_rejected(self) -> None:
2121
with pytest.raises(ValueError, match="max_total_rows must be > 0"):
22-
_validate_max_total_rows(0)
22+
_validate_positive_int_or_none(0, "max_total_rows")
2323

2424
def test_negative_rejected(self) -> None:
2525
with pytest.raises(ValueError, match="max_total_rows must be > 0"):
26-
_validate_max_total_rows(-1)
26+
_validate_positive_int_or_none(-1, "max_total_rows")
2727

2828
def test_float_rejected(self) -> None:
2929
with pytest.raises(TypeError, match="max_total_rows must be int or None"):
30-
_validate_max_total_rows(1.5) # type: ignore[arg-type]
30+
_validate_positive_int_or_none(1.5, "max_total_rows") # type: ignore[arg-type]
3131

3232
def test_bool_rejected(self) -> None:
3333
# True is technically int, but PEP-489-style APIs rightly reject it.
3434
with pytest.raises(TypeError, match="max_total_rows must be int or None"):
35-
_validate_max_total_rows(True) # type: ignore[arg-type]
35+
_validate_positive_int_or_none(True, "max_total_rows") # type: ignore[arg-type]
3636

3737
def test_string_rejected(self) -> None:
3838
with pytest.raises(TypeError, match="max_total_rows must be int or None"):
39-
_validate_max_total_rows("100") # type: ignore[arg-type]
39+
_validate_positive_int_or_none("100", "max_total_rows") # type: ignore[arg-type]
4040

4141

4242
class TestConstructorValidation:

0 commit comments

Comments
 (0)