ransacklib 1.1.0.dev12__tar.gz → 1.1.0.dev13__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.dev12/ransacklib.egg-info → ransacklib-1.1.0.dev13}/PKG-INFO +2 -1
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/pyproject.toml +2 -1
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/operator.py +22 -10
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/transformer.py +20 -7
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13/ransacklib.egg-info}/PKG-INFO +2 -1
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/SOURCES.txt +1 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/requires.txt +1 -0
- ransacklib-1.1.0.dev13/tests/test_postgres.py +1178 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/tests/test_transformer.py +4 -204
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/LICENSE +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/README.rst +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/__init__.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/exceptions.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/function.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/parser.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/py.typed +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/types.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/dependency_links.txt +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/top_level.txt +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/setup.cfg +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/tests/test_operator.py +0 -0
- {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/tests/test_parser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ransacklib
|
|
3
|
-
Version: 1.1.0.
|
|
3
|
+
Version: 1.1.0.dev13
|
|
4
4
|
Summary: A modern, extensible language for manipulation with structured data
|
|
5
5
|
Author-email: "Rajmund H. Hruška" <rajmund.hruska@cesnet.cz>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,7 @@ Requires-Dist: mypy<2.0,>=1.18; extra == "dev"
|
|
|
26
26
|
Requires-Dist: ruff<0.15,>=0.14; extra == "dev"
|
|
27
27
|
Requires-Dist: build<1.4,>=1.3; extra == "dev"
|
|
28
28
|
Requires-Dist: twine<7.0,>=6.2; extra == "dev"
|
|
29
|
+
Requires-Dist: psycopg[binary]; extra == "dev"
|
|
29
30
|
Dynamic: license-file
|
|
30
31
|
|
|
31
32
|
Welcome to ransack
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ransacklib"
|
|
7
|
-
version = "1.1.0.
|
|
7
|
+
version = "1.1.0.dev13"
|
|
8
8
|
description = "A modern, extensible language for manipulation with structured data"
|
|
9
9
|
license = "MIT"
|
|
10
10
|
readme = "README.rst"
|
|
@@ -33,6 +33,7 @@ dev = [
|
|
|
33
33
|
"ruff>=0.14,<0.15",
|
|
34
34
|
"build>=1.3,<1.4",
|
|
35
35
|
"twine>=6.2,<7.0",
|
|
36
|
+
"psycopg[binary]",
|
|
36
37
|
]
|
|
37
38
|
|
|
38
39
|
[project.urls]
|
|
@@ -607,20 +607,16 @@ def _operator_map_sql(op, l_sql, r_sql, t1, t2) -> tuple[str, typing.Any, bool]:
|
|
|
607
607
|
(Number, Number): (f"{l_sql} {op} {r_sql}", False),
|
|
608
608
|
(Number, List(Number)): (f"{l_sql} {op} ANY({r_sql})", False),
|
|
609
609
|
(Number, Range(Number)): (f"{l_sql} {op} {tuple_repr_f}({r_sql})", False),
|
|
610
|
-
(List(Number), Number): (f"ANY({l_sql}) {op} {r_sql}", False),
|
|
611
610
|
(Datetime, Datetime): (f"{l_sql} {op} {r_sql}", False),
|
|
612
611
|
(Datetime, List(Datetime)): (f"{l_sql} {op} ANY({r_sql})", False),
|
|
613
612
|
(Datetime, Range(Datetime)): (
|
|
614
613
|
f"{r_sql} {op} {tuple_repr_f}({l_sql})",
|
|
615
614
|
True,
|
|
616
615
|
),
|
|
617
|
-
(List(Datetime), Datetime): (f"ANY({l_sql}) {op} {r_sql}", False),
|
|
618
616
|
(Timedelta, Timedelta): (f"{l_sql} {op} {r_sql}", False),
|
|
619
617
|
(Timedelta, List(Timedelta)): (f"{l_sql} {op} ANY({r_sql})", False),
|
|
620
|
-
(List(Timedelta), Timedelta): (f"ANY({l_sql}) {op} {r_sql}", False),
|
|
621
618
|
(IP, IP): (f"{l_sql} {op} {r_sql}", False),
|
|
622
619
|
(IP, List(IP)): (f"{l_sql} {op} ANY({r_sql})", False),
|
|
623
|
-
(List(IP), IP): (f"ANY({l_sql}) {op} {r_sql}", False),
|
|
624
620
|
}
|
|
625
621
|
|
|
626
622
|
# Comparison and logical operators (result is always boolean).
|
|
@@ -647,24 +643,40 @@ def _operator_map_sql(op, l_sql, r_sql, t1, t2) -> tuple[str, typing.Any, bool]:
|
|
|
647
643
|
(Range(Any), Range(Any)): (f"upper({l_sql}) > lower({r_sql})", False),
|
|
648
644
|
(Range(Number), Number): (f"upper({l_sql}) > {r_sql}", False),
|
|
649
645
|
(Range(Datetime), Datetime): (f"upper({l_sql}) > {r_sql}", False),
|
|
646
|
+
(List(Number), Number): (f"{r_sql} < ANY({l_sql})", True),
|
|
647
|
+
(List(Datetime), Datetime): (f"{r_sql} < ANY({l_sql})", True),
|
|
648
|
+
(List(Timedelta), Timedelta): (f"{r_sql} < ANY({l_sql})", True),
|
|
649
|
+
(List(IP), IP): (f"{r_sql} < ANY({l_sql})", True),
|
|
650
650
|
},
|
|
651
651
|
">=": _get_comp_dict_sql(">=", "lower")
|
|
652
652
|
| {
|
|
653
653
|
(Range(Any), Range(Any)): (f"upper({l_sql}) >= lower({r_sql})", False),
|
|
654
654
|
(Range(Number), Number): (f"upper({l_sql}) >= {r_sql}", False),
|
|
655
655
|
(Range(Datetime), Datetime): (f"upper({l_sql}) >= {r_sql}", False),
|
|
656
|
+
(List(Number), Number): (f"{r_sql} <= ANY({l_sql})", True),
|
|
657
|
+
(List(Datetime), Datetime): (f"{r_sql} <= ANY({l_sql})", True),
|
|
658
|
+
(List(Timedelta), Timedelta): (f"{r_sql} <= ANY({l_sql})", True),
|
|
659
|
+
(List(IP), IP): (f"{r_sql} <= ANY({l_sql})", True),
|
|
656
660
|
},
|
|
657
661
|
"<": _get_comp_dict_sql("<", "upper")
|
|
658
662
|
| {
|
|
659
663
|
(Range(Any), Range(Any)): (f"lower({l_sql}) < upper({r_sql})", False),
|
|
660
664
|
(Range(Number), Number): (f"lower({l_sql}) < {r_sql}", False),
|
|
661
665
|
(Range(Datetime), Datetime): (f"lower({l_sql}) < {r_sql}", False),
|
|
666
|
+
(List(Number), Number): (f"{r_sql} > ANY({l_sql})", True),
|
|
667
|
+
(List(Datetime), Datetime): (f"{r_sql} > ANY({l_sql})", True),
|
|
668
|
+
(List(Timedelta), Timedelta): (f"{r_sql} > ANY({l_sql})", True),
|
|
669
|
+
(List(IP), IP): (f"{r_sql} > ANY({l_sql})", True),
|
|
662
670
|
},
|
|
663
671
|
"<=": _get_comp_dict_sql("<=", "upper")
|
|
664
672
|
| {
|
|
665
673
|
(Range(Any), Range(Any)): (f"lower({l_sql}) <= upper({r_sql})", False),
|
|
666
674
|
(Range(Number), Number): (f"lower({l_sql}) <= {r_sql}", False),
|
|
667
675
|
(Range(Datetime), Datetime): (f"lower({l_sql}) <= {r_sql}", False),
|
|
676
|
+
(List(Number), Number): (f"{r_sql} >= ANY({l_sql})", True),
|
|
677
|
+
(List(Datetime), Datetime): (f"{r_sql} >= ANY({l_sql})", True),
|
|
678
|
+
(List(Timedelta), Timedelta): (f"{r_sql} >= ANY({l_sql})", True),
|
|
679
|
+
(List(IP), IP): (f"{r_sql} >= ANY({l_sql})", True),
|
|
668
680
|
},
|
|
669
681
|
"and": {(Bool, Bool): (f"{l_sql} AND {r_sql}", False)},
|
|
670
682
|
"or": {(Bool, Bool): (f"({l_sql} OR {r_sql})", False)},
|
|
@@ -743,28 +755,28 @@ def _operator_map_sql(op, l_sql, r_sql, t1, t2) -> tuple[str, typing.Any, bool]:
|
|
|
743
755
|
),
|
|
744
756
|
},
|
|
745
757
|
"*": {
|
|
746
|
-
(Timedelta, Number): (f"{l_sql} * {r_sql}", Timedelta),
|
|
758
|
+
(Timedelta, Number): (f"({l_sql} * {r_sql})", Timedelta),
|
|
747
759
|
(Timedelta, List(Number)): (
|
|
748
760
|
f"array(select {l_sql} * unnest({r_sql}))",
|
|
749
761
|
List(Timedelta),
|
|
750
762
|
),
|
|
751
|
-
(Number, Number): (f"{l_sql} * {r_sql}", Number),
|
|
763
|
+
(Number, Number): (f"({l_sql} * {r_sql})", Number),
|
|
752
764
|
(Number, List(Number)): (
|
|
753
765
|
f"array(select {l_sql} * unnest({r_sql}))",
|
|
754
766
|
List(Number),
|
|
755
767
|
),
|
|
756
768
|
},
|
|
757
769
|
"/": {
|
|
758
|
-
(Timedelta,
|
|
759
|
-
(Timedelta, List(
|
|
770
|
+
(Timedelta, Number): (f"({l_sql} / {r_sql})", Timedelta),
|
|
771
|
+
(Timedelta, List(Number)): (
|
|
760
772
|
f"array(select {l_sql} / unnest({r_sql}))",
|
|
761
773
|
List(Timedelta),
|
|
762
774
|
),
|
|
763
|
-
(List(Timedelta),
|
|
775
|
+
(List(Timedelta), Number): (
|
|
764
776
|
f"array(select unnest({l_sql}) / {r_sql})",
|
|
765
777
|
List(Timedelta),
|
|
766
778
|
),
|
|
767
|
-
(Number, Number): (f"{l_sql} / {r_sql}", Number),
|
|
779
|
+
(Number, Number): (f"({l_sql} / {r_sql})", Number),
|
|
768
780
|
(Number, List(Number)): (
|
|
769
781
|
f"array(select {l_sql} / unnest({r_sql}))",
|
|
770
782
|
List(Number),
|
|
@@ -853,8 +853,9 @@ class SQLInterpreter(Interpreter):
|
|
|
853
853
|
return result, params, type_
|
|
854
854
|
|
|
855
855
|
def number(self, token: TokenWrapper) -> tuple[str, list, types.RansackType]:
|
|
856
|
-
|
|
857
|
-
|
|
856
|
+
if isinstance(token.real_value, int):
|
|
857
|
+
return ("%s::int", [token.real_value], types.Integer)
|
|
858
|
+
return ("%s", [token.real_value], types.Float)
|
|
858
859
|
|
|
859
860
|
def datetime(self, token: TokenWrapper) -> tuple[str, list, types.RansackType]:
|
|
860
861
|
if token.real_value.tzinfo is not None:
|
|
@@ -893,6 +894,8 @@ class SQLInterpreter(Interpreter):
|
|
|
893
894
|
elif l_type is types.Float and r_type is types.Float:
|
|
894
895
|
range_type = "numrange"
|
|
895
896
|
l_type = types.Number
|
|
897
|
+
l_sql = l_sql + "::numeric"
|
|
898
|
+
r_sql = r_sql + "::numeric"
|
|
896
899
|
elif l_type is types.Datetime and r_type is types.Datetime:
|
|
897
900
|
if "WITH TIME ZONE" in l_sql and "WITH TIME ZONE" in r_sql:
|
|
898
901
|
range_type = "tstzrange"
|
|
@@ -950,20 +953,30 @@ class SQLInterpreter(Interpreter):
|
|
|
950
953
|
|
|
951
954
|
return sql, params, type_
|
|
952
955
|
|
|
956
|
+
def _arithmetic_operation(self, operator, l_tree, r_tree) -> tuple[str, list, Any]:
|
|
957
|
+
l_sql, l_params, l_type = self.visit(l_tree)
|
|
958
|
+
r_sql, r_params, r_type = self.visit(r_tree)
|
|
959
|
+
|
|
960
|
+
if l_type == types.List(types.Empty):
|
|
961
|
+
return l_sql, l_params, l_type
|
|
962
|
+
if r_type == types.List(types.Empty):
|
|
963
|
+
return r_sql, r_params, r_type
|
|
964
|
+
return self._binary_operation(operator, l_tree, r_tree)
|
|
965
|
+
|
|
953
966
|
def add(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, Any]:
|
|
954
|
-
return self.
|
|
967
|
+
return self._arithmetic_operation("+", l_tree, r_tree)
|
|
955
968
|
|
|
956
969
|
def sub(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, Any]:
|
|
957
|
-
return self.
|
|
970
|
+
return self._arithmetic_operation("-", l_tree, r_tree)
|
|
958
971
|
|
|
959
972
|
def mul(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, Any]:
|
|
960
|
-
return self.
|
|
973
|
+
return self._arithmetic_operation("*", l_tree, r_tree)
|
|
961
974
|
|
|
962
975
|
def div(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, Any]:
|
|
963
|
-
return self.
|
|
976
|
+
return self._arithmetic_operation("/", l_tree, r_tree)
|
|
964
977
|
|
|
965
978
|
def mod(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, Any]:
|
|
966
|
-
return self.
|
|
979
|
+
return self._arithmetic_operation("%", l_tree, r_tree)
|
|
967
980
|
|
|
968
981
|
def eq(self, l_tree: Tree, r_tree: Tree) -> tuple[str, list, type[bool]]:
|
|
969
982
|
return self._binary_operation("==", l_tree, r_tree)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ransacklib
|
|
3
|
-
Version: 1.1.0.
|
|
3
|
+
Version: 1.1.0.dev13
|
|
4
4
|
Summary: A modern, extensible language for manipulation with structured data
|
|
5
5
|
Author-email: "Rajmund H. Hruška" <rajmund.hruska@cesnet.cz>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -26,6 +26,7 @@ Requires-Dist: mypy<2.0,>=1.18; extra == "dev"
|
|
|
26
26
|
Requires-Dist: ruff<0.15,>=0.14; extra == "dev"
|
|
27
27
|
Requires-Dist: build<1.4,>=1.3; extra == "dev"
|
|
28
28
|
Requires-Dist: twine<7.0,>=6.2; extra == "dev"
|
|
29
|
+
Requires-Dist: psycopg[binary]; extra == "dev"
|
|
29
30
|
Dynamic: license-file
|
|
30
31
|
|
|
31
32
|
Welcome to ransack
|