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.
Files changed (22) hide show
  1. {ransacklib-1.1.0.dev12/ransacklib.egg-info → ransacklib-1.1.0.dev13}/PKG-INFO +2 -1
  2. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/pyproject.toml +2 -1
  3. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/operator.py +22 -10
  4. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/transformer.py +20 -7
  5. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13/ransacklib.egg-info}/PKG-INFO +2 -1
  6. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/SOURCES.txt +1 -0
  7. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/requires.txt +1 -0
  8. ransacklib-1.1.0.dev13/tests/test_postgres.py +1178 -0
  9. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/tests/test_transformer.py +4 -204
  10. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/LICENSE +0 -0
  11. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/README.rst +0 -0
  12. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/__init__.py +0 -0
  13. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/exceptions.py +0 -0
  14. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/function.py +0 -0
  15. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/parser.py +0 -0
  16. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/py.typed +0 -0
  17. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransack/types.py +0 -0
  18. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/dependency_links.txt +0 -0
  19. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/ransacklib.egg-info/top_level.txt +0 -0
  20. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/setup.cfg +0 -0
  21. {ransacklib-1.1.0.dev12 → ransacklib-1.1.0.dev13}/tests/test_operator.py +0 -0
  22. {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.dev12
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.dev12"
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, Timedelta): (f"{l_sql} / {r_sql}", Timedelta),
759
- (Timedelta, List(Timedelta)): (
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), 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
- type_ = types.Integer if isinstance(token.real_value, int) else types.Float
857
- return ("%s", [token.real_value], type_)
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._binary_operation("+", l_tree, r_tree)
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._binary_operation("-", l_tree, r_tree)
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._binary_operation("*", l_tree, r_tree)
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._binary_operation("/", l_tree, r_tree)
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._binary_operation("%", l_tree, r_tree)
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.dev12
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
@@ -16,4 +16,5 @@ ransacklib.egg-info/requires.txt
16
16
  ransacklib.egg-info/top_level.txt
17
17
  tests/test_operator.py
18
18
  tests/test_parser.py
19
+ tests/test_postgres.py
19
20
  tests/test_transformer.py
@@ -10,3 +10,4 @@ mypy<2.0,>=1.18
10
10
  ruff<0.15,>=0.14
11
11
  build<1.4,>=1.3
12
12
  twine<7.0,>=6.2
13
+ psycopg[binary]