Skip to content

Commit 1ea2bbe

Browse files
committed
Accept sets and reject bytes-like predicate values
Sets and frozensets fell through to str(), silently sending values like '{25544, 34602}' in the query URL where a list sends '25544,34602'. bytes are registered Sequences, so they were serialised as comma-joined integer ordinals. Join Set values like Sequences, and raise TypeError for bytes-like values instead of building a garbage query.
1 parent 168de31 commit 1ea2bbe

3 files changed

Lines changed: 18 additions & 3 deletions

File tree

newsfragments/169.changed.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Sets and frozensets are now accepted as predicate values and joined with commas like sequences.
2+
Bytes-like values now raise :class:`TypeError` instead of being sent as comma-separated integers.

src/spacetrack/operators.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import datetime
2-
from collections.abc import Sequence
2+
from collections.abc import Sequence, Set
33

44

55
def greater_than(value):
@@ -36,13 +36,17 @@ def _stringify_predicate_value(value):
3636
"""Convert Python objects to Space-Track compatible strings
3737
3838
- Booleans (``True`` -> ``'true'``)
39-
- Sequences (``[25544, 34602]`` -> ``'25544,34602'``)
39+
- Sequences and sets (``[25544, 34602]`` -> ``'25544,34602'``)
4040
- dates/datetimes (``date(2015, 12, 23)`` -> ``'2015-12-23'``)
4141
- ``None`` -> ``'null-val'``
4242
"""
4343
if isinstance(value, bool):
4444
return str(value).lower()
45-
elif isinstance(value, Sequence) and not isinstance(value, str):
45+
elif isinstance(value, (bytes, bytearray, memoryview)):
46+
raise TypeError(
47+
f"predicate values of type {type(value).__name__!r} are not supported"
48+
)
49+
elif isinstance(value, (Sequence, Set)) and not isinstance(value, str):
4650
return ",".join(_stringify_predicate_value(x) for x in value)
4751
elif isinstance(value, datetime.datetime):
4852
if value.tzinfo is not None:

tests/test_operators.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
(False, "false"),
1111
([1, 2], "1,2"),
1212
(["a", "b"], "a,b"),
13+
({1}, "1"),
14+
(frozenset(["a"]), "a"),
1315
((dt.date(2001, 2, 3), dt.date(2004, 5, 6)), "2001-02-03,2004-05-06"),
1416
(dt.datetime(2001, 2, 3, 4, 5, 6), "2001-02-03 04:05:06"),
1517
(dt.datetime(2001, 2, 3, tzinfo=dt.timezone.utc), "2001-02-03 00:00:00"),
@@ -23,6 +25,13 @@ def test_stringify_predicate_value(value, expected):
2325
assert _stringify_predicate_value(value) == expected
2426

2527

28+
@pytest.mark.parametrize("value", [b"abc", bytearray(b"abc"), memoryview(b"abc")])
29+
def test_stringify_predicate_value_rejects_bytes(value):
30+
# bytes would otherwise be serialised as comma-joined integer ordinals.
31+
with pytest.raises(TypeError):
32+
_stringify_predicate_value(value)
33+
34+
2635
operator_data = [
2736
(op.greater_than, "test", ">test"),
2837
(op.less_than, "test", "<test"),

0 commit comments

Comments
 (0)