ransacklib 1.1.0.dev14__tar.gz → 1.1.0.dev15__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.
- {ransacklib-1.1.0.dev14/ransacklib.egg-info → ransacklib-1.1.0.dev15}/PKG-INFO +1 -1
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/pyproject.toml +1 -1
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/transformer.py +2 -7
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15/ransacklib.egg-info}/PKG-INFO +1 -1
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/tests/test_postgres.py +125 -3
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/tests/test_transformer.py +1 -123
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/LICENSE +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/README.rst +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/__init__.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/exceptions.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/function.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/operator.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/parser.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/py.typed +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransack/types.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransacklib.egg-info/SOURCES.txt +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransacklib.egg-info/dependency_links.txt +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransacklib.egg-info/requires.txt +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/ransacklib.egg-info/top_level.txt +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/setup.cfg +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/tests/test_operator.py +0 -0
- {ransacklib-1.1.0.dev14 → ransacklib-1.1.0.dev15}/tests/test_parser.py +0 -0
|
@@ -871,12 +871,7 @@ class SQLInterpreter(Interpreter):
|
|
|
871
871
|
return ("%s", [token.real_value], types.String)
|
|
872
872
|
|
|
873
873
|
def ip(self, token: TokenWrapper) -> tuple[str, list, types.RansackType]:
|
|
874
|
-
|
|
875
|
-
case IP4() | IP6():
|
|
876
|
-
cast = "ipaddress"
|
|
877
|
-
case IP4Range() | IP6Range() | IP4Net() | IP6Net():
|
|
878
|
-
cast = "iprange"
|
|
879
|
-
return (f"%s::{cast}", [token.real_value], types.IP)
|
|
874
|
+
return ("%s::iprange", [token.real_value], types.IP)
|
|
880
875
|
|
|
881
876
|
def neg(self, tree: Tree) -> tuple[str, list, Any]:
|
|
882
877
|
sql, params, type_ = self.visit(tree)
|
|
@@ -903,7 +898,7 @@ class SQLInterpreter(Interpreter):
|
|
|
903
898
|
range_type = "tsrange"
|
|
904
899
|
elif l_type is types.IP and r_type is types.IP:
|
|
905
900
|
return (
|
|
906
|
-
f"iprange({l_sql}, {r_sql})",
|
|
901
|
+
f"iprange({l_sql}::text::ipaddress, {r_sql}::text::ipaddress)",
|
|
907
902
|
l_params + r_params,
|
|
908
903
|
types.IP,
|
|
909
904
|
)
|
|
@@ -2,9 +2,10 @@ from datetime import datetime, timedelta, timezone
|
|
|
2
2
|
from zoneinfo import ZoneInfo
|
|
3
3
|
|
|
4
4
|
import pytest
|
|
5
|
+
from ipranges import IP4, IP6, IP4Net, IP4Range, IP6Net, IP6Range
|
|
5
6
|
from psycopg.types.range import Range
|
|
6
7
|
|
|
7
|
-
from ransack import Parser, SQLInterpreter, types
|
|
8
|
+
from ransack import Parser, RansackError, SQLInterpreter, types
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
@pytest.fixture
|
|
@@ -27,9 +28,11 @@ def test_data(db):
|
|
|
27
28
|
ts_value timestamp,
|
|
28
29
|
tstz_value timestamptz,
|
|
29
30
|
interval_value interval,
|
|
31
|
+
ip_value iprange,
|
|
30
32
|
|
|
31
33
|
int_array integer[],
|
|
32
34
|
text_array text[],
|
|
35
|
+
iprange_array iprange[],
|
|
33
36
|
interval_array interval[],
|
|
34
37
|
null_array integer[]
|
|
35
38
|
);
|
|
@@ -39,8 +42,8 @@ def test_data(db):
|
|
|
39
42
|
f"""
|
|
40
43
|
INSERT INTO {table}
|
|
41
44
|
VALUES (
|
|
42
|
-
%s, %s, %s, %s, %s, %s, %s, %s, %s,
|
|
43
|
-
%s, %s, %s, %s
|
|
45
|
+
%s, %s, %s, %s, %s, %s, %s, %s, %s, %s,
|
|
46
|
+
%s, %s, %s, %s, %s
|
|
44
47
|
)
|
|
45
48
|
""",
|
|
46
49
|
(
|
|
@@ -53,8 +56,10 @@ def test_data(db):
|
|
|
53
56
|
datetime(2025, 1, 1, 12, 0, 0),
|
|
54
57
|
datetime(2025, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
|
|
55
58
|
timedelta(days=2, seconds=123),
|
|
59
|
+
IP4("192.168.1.120"),
|
|
56
60
|
[1, 2, 3],
|
|
57
61
|
["a", "b", "c"],
|
|
62
|
+
[IP4("192.168.0.1"), IP4("192.168.0.20"), IP4Net("192.168.1.0/24")],
|
|
58
63
|
[
|
|
59
64
|
timedelta(hours=1),
|
|
60
65
|
timedelta(hours=2),
|
|
@@ -83,8 +88,10 @@ def ransack_sql_mapping():
|
|
|
83
88
|
"creation_time": ("ts_value", types.Datetime),
|
|
84
89
|
"detection_time": ("tstz_value", types.Datetime),
|
|
85
90
|
"delta": ("interval_value", types.Timedelta),
|
|
91
|
+
"source_ip": ("ip_value", types.IP),
|
|
86
92
|
"ports": ("int_array", types.List[types.Number]),
|
|
87
93
|
"categories": ("text_array", types.List[types.String]),
|
|
94
|
+
"iprange_array": ("iprange_array", types.List(types.IP)),
|
|
88
95
|
"deltas": ("interval_array", types.List[types.Timedelta]),
|
|
89
96
|
"null_array": ("null_array", types.List[types.Number]),
|
|
90
97
|
}
|
|
@@ -135,6 +142,13 @@ def test_connection(db):
|
|
|
135
142
|
("''", ""),
|
|
136
143
|
('"string"', "string"),
|
|
137
144
|
('"\';DROP TABLE USERS"', "';DROP TABLE USERS"),
|
|
145
|
+
# IP.
|
|
146
|
+
("192.168.0.0", IP4("192.168.0.0")),
|
|
147
|
+
("192.168.0.0/16", IP4Net("192.168.0.0/16")),
|
|
148
|
+
("192.168.0.10-192.168.0.50", IP4Range("192.168.0.10-192.168.0.50")),
|
|
149
|
+
("fd00::1", IP6("fd00::1")),
|
|
150
|
+
("fd00::/8", IP6Net("fd00::/8")),
|
|
151
|
+
("fd00::1-fd00::10", IP6Range("fd00::1-fd00::10")),
|
|
138
152
|
],
|
|
139
153
|
)
|
|
140
154
|
def test_basic_types(db, expr, expected):
|
|
@@ -152,6 +166,19 @@ def test_basic_types(db, expr, expected):
|
|
|
152
166
|
("[1, 2, 3]", [1, 2, 3]),
|
|
153
167
|
("[01:23:34]", [timedelta(seconds=5014)]),
|
|
154
168
|
('[["a"]]', [["a"]]),
|
|
169
|
+
("[192.168.0.0, 192.168.0.1]", [IP4("192.168.0.0"), IP4("192.168.0.1")]),
|
|
170
|
+
(
|
|
171
|
+
"[192.168.0.0, 192.168.0.0/16, 192.168.0.10-192.168.0.50]",
|
|
172
|
+
[
|
|
173
|
+
IP4("192.168.0.0"),
|
|
174
|
+
IP4Net("192.168.0.0/16"),
|
|
175
|
+
IP4Range("192.168.0.10-192.168.0.50"),
|
|
176
|
+
],
|
|
177
|
+
),
|
|
178
|
+
(
|
|
179
|
+
"[fd00::1, fd00::/8, fd00::1-fd00::10]",
|
|
180
|
+
[IP6("fd00::1"), IP6Net("fd00::/8"), IP6Range("fd00::1-fd00::10")],
|
|
181
|
+
),
|
|
155
182
|
# Ranges.
|
|
156
183
|
("100..1", Range(1, 101, "[)")),
|
|
157
184
|
("100.12..1.14", Range(1.14, 100.12, "[]")),
|
|
@@ -175,6 +202,8 @@ def test_basic_types(db, expr, expected):
|
|
|
175
202
|
"[]",
|
|
176
203
|
),
|
|
177
204
|
),
|
|
205
|
+
("192.168.0.10..192.168.0.50", IP4Range("192.168.0.10-192.168.0.50")),
|
|
206
|
+
("fd00::1..fd00::10", IP6Range("fd00::1-fd00::10")),
|
|
178
207
|
],
|
|
179
208
|
)
|
|
180
209
|
def test_container_types(db, expr, expected):
|
|
@@ -195,8 +224,13 @@ def test_container_types(db, expr, expected):
|
|
|
195
224
|
("creation_time", datetime(2025, 1, 1, 12, 0)),
|
|
196
225
|
("detection_time", datetime(2025, 1, 1, 12, 0, tzinfo=ZoneInfo(key="Etc/UTC"))),
|
|
197
226
|
("delta", timedelta(days=2, seconds=123)),
|
|
227
|
+
("source_ip", IP4("192.168.1.120")),
|
|
198
228
|
("ports", [1, 2, 3]),
|
|
199
229
|
("categories", ["a", "b", "c"]),
|
|
230
|
+
(
|
|
231
|
+
"iprange_array",
|
|
232
|
+
[IP4("192.168.0.1"), IP4("192.168.0.20"), IP4Net("192.168.1.0/24")],
|
|
233
|
+
),
|
|
200
234
|
("deltas", [timedelta(seconds=3600), timedelta(seconds=7200)]),
|
|
201
235
|
("[a_int, b_int]", [12, -200]),
|
|
202
236
|
("a_int..b_int", Range(-200, 13, "[)")),
|
|
@@ -303,6 +337,7 @@ def test_concat_operator(db, expr, expected, test_data, ransack_sql_mapping):
|
|
|
303
337
|
("len(ports)", 3),
|
|
304
338
|
("len(categories)", 3),
|
|
305
339
|
("length([0, 1, 2, 3])", 4),
|
|
340
|
+
("length(iprange_array)", 3),
|
|
306
341
|
],
|
|
307
342
|
)
|
|
308
343
|
def test_functions(db, expr, expected, test_data, ransack_sql_mapping):
|
|
@@ -897,6 +932,24 @@ def test_any_equal_operator(db, expr, expected):
|
|
|
897
932
|
("delta = [01:00:00]", False),
|
|
898
933
|
("01:00:00 = deltas", True),
|
|
899
934
|
("03:00:00 = deltas", False),
|
|
935
|
+
# IP = IP
|
|
936
|
+
("10.10.10.10 = 10.10.10.10", True),
|
|
937
|
+
("10.10.10.10 = 10.10.10.0 .. 10.10.10.20", True),
|
|
938
|
+
("192.168.0.5 = 192.168.0.0-192.168.0.255", True),
|
|
939
|
+
("192.168.0.12 = 192.168.1.0/24", False),
|
|
940
|
+
("10.10.10.10-10.10.10.20 = 10.10.10.15-10.10.10.25", True),
|
|
941
|
+
("10.10.10.10-10.10.10.20 = 192.168.0.0/16", False),
|
|
942
|
+
("192.168.1.0/24 = 192.168.0.0/16", True),
|
|
943
|
+
# IP = List[IP]
|
|
944
|
+
("192.168.1.10 = [192.168.0.0/24, 192.168.0.0/16]", True),
|
|
945
|
+
("192.168.1.10 = [10.0.0.0/8, 172.16.0.0/12]", False),
|
|
946
|
+
("2001:db8::1 = [2001:db8:1::/48, 2001:db8::/32]", True),
|
|
947
|
+
("2001:db8::1 = [fd00::/8, fe80::/10]", False),
|
|
948
|
+
# List[IP] = IP
|
|
949
|
+
("[192.168.0.0/24, 192.168.0.0/16] = 192.168.1.10", True),
|
|
950
|
+
("[10.0.0.0/8, 172.16.0.0/12] = 192.168.1.10", False),
|
|
951
|
+
("[2001:db8:1::/48, 2001:db8::/32] = 2001:db8::1", True),
|
|
952
|
+
("[fd00::/8, fe80::/10] = 2001:db8::1", False),
|
|
900
953
|
# List = List (overlap).
|
|
901
954
|
("ports = [3, 4, 5]", True),
|
|
902
955
|
("ports = [4, 5]", False),
|
|
@@ -992,6 +1045,57 @@ def test_any_equal_operator_variables(
|
|
|
992
1045
|
("01:00:00 >= 01:00:00", True),
|
|
993
1046
|
("01:00:00 < 02:00:00", True),
|
|
994
1047
|
("01:00:00 <= 01:00:00", True),
|
|
1048
|
+
# IP x IP.
|
|
1049
|
+
("10.0.0.2 > 10.0.0.1", True),
|
|
1050
|
+
("10.0.0.1 > 10.0.0.2", False),
|
|
1051
|
+
("10.0.0.1 >= 10.0.0.1", True),
|
|
1052
|
+
("10.0.0.1 >= 10.0.0.2", False),
|
|
1053
|
+
("10.0.0.1 < 10.0.0.2", True),
|
|
1054
|
+
("10.0.0.2 < 10.0.0.1", False),
|
|
1055
|
+
("10.0.0.1 <= 10.0.0.1", True),
|
|
1056
|
+
("10.0.0.2 <= 10.0.0.1", False),
|
|
1057
|
+
("2001:db8::2 > 2001:db8::1", True),
|
|
1058
|
+
("2001:db8::1 > 2001:db8::2", False),
|
|
1059
|
+
("2001:db8::1 >= 2001:db8::1", True),
|
|
1060
|
+
("2001:db8::1 >= 2001:db8::2", False),
|
|
1061
|
+
("2001:db8::1 < 2001:db8::2", True),
|
|
1062
|
+
("2001:db8::2 < 2001:db8::1", False),
|
|
1063
|
+
("2001:db8::1 <= 2001:db8::1", True),
|
|
1064
|
+
("2001:db8::2 <= 2001:db8::1", False),
|
|
1065
|
+
# IP x List(IP).
|
|
1066
|
+
("10.0.0.5 > [10.0.0.1, 10.0.0.10]", True),
|
|
1067
|
+
("10.0.0.0 > [10.0.0.1, 10.0.0.10]", False),
|
|
1068
|
+
("10.0.0.5 >= [10.0.0.5, 10.0.0.10]", True),
|
|
1069
|
+
("10.0.0.4 >= [10.0.0.5, 10.0.0.10]", False),
|
|
1070
|
+
("10.0.0.5 < [10.0.0.1, 10.0.0.10]", True),
|
|
1071
|
+
("10.0.0.20 < [10.0.0.1, 10.0.0.10]", False),
|
|
1072
|
+
("10.0.0.5 <= [10.0.0.1, 10.0.0.5]", True),
|
|
1073
|
+
("10.0.0.20 <= [10.0.0.1, 10.0.0.5]", False),
|
|
1074
|
+
("2001:db8::5 > [2001:db8::1, 2001:db8::10]", True),
|
|
1075
|
+
("2001:db8::0 > [2001:db8::1, 2001:db8::10]", False),
|
|
1076
|
+
("2001:db8::5 >= [2001:db8::5, 2001:db8::10]", True),
|
|
1077
|
+
("2001:db8::4 >= [2001:db8::5, 2001:db8::10]", False),
|
|
1078
|
+
("2001:db8::5 < [2001:db8::1, 2001:db8::10]", True),
|
|
1079
|
+
("2001:db8::20 < [2001:db8::1, 2001:db8::10]", False),
|
|
1080
|
+
("2001:db8::5 <= [2001:db8::1, 2001:db8::5]", True),
|
|
1081
|
+
("2001:db8::20 <= [2001:db8::1, 2001:db8::5]", False),
|
|
1082
|
+
# List(IP) x IP.
|
|
1083
|
+
("[10.0.0.1, 10.0.0.10] > 10.0.0.5", True),
|
|
1084
|
+
("[10.0.0.1, 10.0.0.2] > 10.0.0.5", False),
|
|
1085
|
+
("[10.0.0.5, 10.0.0.10] >= 10.0.0.5", True),
|
|
1086
|
+
("[10.0.0.1, 10.0.0.2] >= 10.0.0.5", False),
|
|
1087
|
+
("[10.0.0.1, 10.0.0.10] < 10.0.0.5", True),
|
|
1088
|
+
("[10.0.0.10, 10.0.0.20] < 10.0.0.5", False),
|
|
1089
|
+
("[10.0.0.1, 10.0.0.5] <= 10.0.0.5", True),
|
|
1090
|
+
("[10.0.0.10, 10.0.0.20] <= 10.0.0.5", False),
|
|
1091
|
+
("[2001:db8::1, 2001:db8::10] > 2001:db8::5", True),
|
|
1092
|
+
("[2001:db8::1, 2001:db8::2] > 2001:db8::5", False),
|
|
1093
|
+
("[2001:db8::5, 2001:db8::10] >= 2001:db8::5", True),
|
|
1094
|
+
("[2001:db8::1, 2001:db8::2] >= 2001:db8::5", False),
|
|
1095
|
+
("[2001:db8::1, 2001:db8::10] < 2001:db8::5", True),
|
|
1096
|
+
("[2001:db8::10, 2001:db8::20] < 2001:db8::5", False),
|
|
1097
|
+
("[2001:db8::1, 2001:db8::5] <= 2001:db8::5", True),
|
|
1098
|
+
("[2001:db8::10, 2001:db8::20] <= 2001:db8::5", False),
|
|
995
1099
|
# Empty arrays.
|
|
996
1100
|
("1 > []", False),
|
|
997
1101
|
("1 >= []", False),
|
|
@@ -1176,3 +1280,21 @@ def test_complex_expressions(
|
|
|
1176
1280
|
params,
|
|
1177
1281
|
)
|
|
1178
1282
|
assert cur.fetchone()[0] is expected
|
|
1283
|
+
|
|
1284
|
+
|
|
1285
|
+
@pytest.mark.sql
|
|
1286
|
+
@pytest.mark.parametrize(
|
|
1287
|
+
("expr"),
|
|
1288
|
+
[
|
|
1289
|
+
"2000-12-24..192.168.0.50", # Unsupported type of range.
|
|
1290
|
+
"1..1.5",
|
|
1291
|
+
"1..2025-01-01",
|
|
1292
|
+
'"abc"..123',
|
|
1293
|
+
"01:00:00..5",
|
|
1294
|
+
"not_there", # Unknown column.
|
|
1295
|
+
],
|
|
1296
|
+
)
|
|
1297
|
+
def test_invalid_cases(expr):
|
|
1298
|
+
tree = Parser().parse(expr)
|
|
1299
|
+
with pytest.raises(RansackError):
|
|
1300
|
+
SQLInterpreter().to_sql(tree)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from datetime import datetime, timedelta, timezone
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
|
-
from ipranges import IP4, IP6, IP4Net, IP4Range, IP6Net, IP6Range
|
|
4
|
+
from ipranges import IP4, IP6, IP4Net, IP4Range, IP6Net, IP6Range
|
|
5
5
|
from lark import Token
|
|
6
6
|
|
|
7
7
|
from ransack.exceptions import RansackError, ShapeError
|
|
@@ -13,7 +13,6 @@ from ransack.transformer import (
|
|
|
13
13
|
TokenWrapper,
|
|
14
14
|
get_values,
|
|
15
15
|
)
|
|
16
|
-
from ransack.types import Integer, List, String
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
@pytest.fixture
|
|
@@ -574,124 +573,3 @@ class TestFilter:
|
|
|
574
573
|
exp_tree = expr_transformer.transform(parser.parse_only("my_var == 14"))
|
|
575
574
|
res = filter_.transform(exp_tree)
|
|
576
575
|
assert res
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
class TestSQLInterpreter:
|
|
580
|
-
def parse(self, parser, sql, expression):
|
|
581
|
-
tree = parser.parse(expression)
|
|
582
|
-
data = {
|
|
583
|
-
"a_int": ("a", Integer),
|
|
584
|
-
"b_int": ("b", Integer),
|
|
585
|
-
"c_int": ("c", Integer),
|
|
586
|
-
"d_int": ("d", Integer),
|
|
587
|
-
"Description": ("description", String),
|
|
588
|
-
"Category": ("category", List[String]),
|
|
589
|
-
}
|
|
590
|
-
return sql.to_sql(tree, data)
|
|
591
|
-
|
|
592
|
-
@pytest.mark.parametrize(
|
|
593
|
-
("expr", "expected_sql", "expected_params"),
|
|
594
|
-
[
|
|
595
|
-
# IPs.
|
|
596
|
-
("192.168.0.0", "%s::ipaddress", [from_str("192.168.0.0")]),
|
|
597
|
-
("192.168.0.0/16", "%s::iprange", [from_str("192.168.0.0/16")]),
|
|
598
|
-
(
|
|
599
|
-
"192.168.0.10-192.168.0.50",
|
|
600
|
-
"%s::iprange",
|
|
601
|
-
[from_str("192.168.0.10-192.168.0.50")],
|
|
602
|
-
),
|
|
603
|
-
("fd00::1", "%s::ipaddress", [from_str("fd00::1")]),
|
|
604
|
-
("fd00::/8", "%s::iprange", [from_str("fd00::/8")]),
|
|
605
|
-
("fd00::1-fd00::10", "%s::iprange", [from_str("fd00::1-fd00::10")]),
|
|
606
|
-
(
|
|
607
|
-
"192.168.0.10..192.168.0.50",
|
|
608
|
-
"iprange(%s::ipaddress, %s::ipaddress)",
|
|
609
|
-
[from_str("192.168.0.10"), from_str("192.168.0.50")],
|
|
610
|
-
),
|
|
611
|
-
(
|
|
612
|
-
"fd00::1..fd00::10",
|
|
613
|
-
"iprange(%s::ipaddress, %s::ipaddress)",
|
|
614
|
-
[from_str("fd00::1"), from_str("fd00::10")],
|
|
615
|
-
),
|
|
616
|
-
# Test = operator.
|
|
617
|
-
(
|
|
618
|
-
"10.10.10.10 = 10.10.10.10",
|
|
619
|
-
"%s::ipaddress && %s::ipaddress",
|
|
620
|
-
[from_str("10.10.10.10"), from_str("10.10.10.10")],
|
|
621
|
-
),
|
|
622
|
-
(
|
|
623
|
-
"10.10.10.10 = 10.10.10.0 .. 10.10.10.20",
|
|
624
|
-
"%s::ipaddress && iprange(%s::ipaddress, %s::ipaddress)",
|
|
625
|
-
[
|
|
626
|
-
from_str("10.10.10.10"),
|
|
627
|
-
from_str("10.10.10.0"),
|
|
628
|
-
from_str("10.10.10.20"),
|
|
629
|
-
],
|
|
630
|
-
),
|
|
631
|
-
(
|
|
632
|
-
"192.168.0.5 = 192.168.0.0-192.168.0.255",
|
|
633
|
-
"%s::ipaddress && %s::iprange",
|
|
634
|
-
[from_str("192.168.0.5"), from_str("192.168.0.0-192.168.0.255")],
|
|
635
|
-
),
|
|
636
|
-
(
|
|
637
|
-
"192.168.0.12 = 192.168.1.0/24",
|
|
638
|
-
"%s::ipaddress && %s::iprange",
|
|
639
|
-
[from_str("192.168.0.12"), from_str("192.168.1.0/24")],
|
|
640
|
-
),
|
|
641
|
-
(
|
|
642
|
-
"10.10.10.10-10.10.10.20 = 10.10.10.15-10.10.10.25",
|
|
643
|
-
"%s::iprange && %s::iprange",
|
|
644
|
-
[
|
|
645
|
-
from_str("10.10.10.10-10.10.10.20"),
|
|
646
|
-
from_str("10.10.10.15-10.10.10.25"),
|
|
647
|
-
],
|
|
648
|
-
),
|
|
649
|
-
(
|
|
650
|
-
"10.10.10.10-10.10.10.20 = 192.168.0.0/16",
|
|
651
|
-
"%s::iprange && %s::iprange",
|
|
652
|
-
[from_str("10.10.10.10-10.10.10.20"), from_str("192.168.0.0/16")],
|
|
653
|
-
),
|
|
654
|
-
(
|
|
655
|
-
"192.168.1.0/24 = 192.168.0.0/16",
|
|
656
|
-
"%s::iprange && %s::iprange",
|
|
657
|
-
[from_str("192.168.1.0/24"), from_str("192.168.0.0/16")],
|
|
658
|
-
),
|
|
659
|
-
(
|
|
660
|
-
"192.168.1.10 = [192.168.0.0/24, 192.168.0.0/16]",
|
|
661
|
-
("%s::ipaddress && ANY(ARRAY[%s::iprange, %s::iprange])"),
|
|
662
|
-
[
|
|
663
|
-
from_str("192.168.1.10"),
|
|
664
|
-
from_str("192.168.0.0/24"),
|
|
665
|
-
from_str("192.168.0.0/16"),
|
|
666
|
-
],
|
|
667
|
-
),
|
|
668
|
-
],
|
|
669
|
-
)
|
|
670
|
-
def test_parse_sql(self, parser, sql, expr, expected_sql, expected_params):
|
|
671
|
-
sql_str, params, _ = self.parse(parser, sql, expr)
|
|
672
|
-
|
|
673
|
-
assert sql_str == expected_sql
|
|
674
|
-
assert params == expected_params
|
|
675
|
-
|
|
676
|
-
def to_sql_and_expect_error(self, parser, sql, expression):
|
|
677
|
-
tree = parser.parse(expression)
|
|
678
|
-
with pytest.raises(RansackError):
|
|
679
|
-
sql.to_sql(tree)
|
|
680
|
-
|
|
681
|
-
@pytest.mark.parametrize(
|
|
682
|
-
"expression",
|
|
683
|
-
[
|
|
684
|
-
"2000-12-24..192.168.0.50", # Unsupported type of range.
|
|
685
|
-
"1..1.5",
|
|
686
|
-
"1..2025-01-01",
|
|
687
|
-
'"abc"..123',
|
|
688
|
-
"01:00:00..5",
|
|
689
|
-
"not_there", # Unknown column.
|
|
690
|
-
],
|
|
691
|
-
)
|
|
692
|
-
def test_invalid_cases(self, parser, sql, expression):
|
|
693
|
-
self.to_sql_and_expect_error(
|
|
694
|
-
parser,
|
|
695
|
-
sql,
|
|
696
|
-
expression,
|
|
697
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|