py-predicate 1.0__tar.gz → 1.2__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.
- {py_predicate-1.0 → py_predicate-1.2}/PKG-INFO +10 -2
- {py_predicate-1.0 → py_predicate-1.2}/README.md +9 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/__init__.py +54 -55
- {py_predicate-1.0 → py_predicate-1.2}/predicate/all_predicate.py +6 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/always_false_predicate.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/always_true_predicate.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/any_predicate.py +6 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/comp_predicate.py +6 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/constructor/construct.py +8 -12
- {py_predicate-1.0 → py_predicate-1.2}/predicate/dict_of_predicate.py +7 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/eq_predicate.py +16 -1
- py_predicate-1.2/predicate/fn_predicate.py +67 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/formatter/format_dot.py +2 -2
- {py_predicate-1.0 → py_predicate-1.2}/predicate/formatter/format_latex.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/ge_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/generator/generate_false.py +112 -24
- {py_predicate-1.0 → py_predicate-1.2}/predicate/generator/generate_predicate.py +6 -3
- {py_predicate-1.0 → py_predicate-1.2}/predicate/generator/generate_true.py +204 -43
- py_predicate-1.2/predicate/generator/helpers.py +364 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/gt_predicate.py +10 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/has_key_predicate.py +5 -0
- py_predicate-1.2/predicate/has_length_predicate.py +37 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/has_path_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/helpers.py +8 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/implies.py +22 -2
- py_predicate-1.2/predicate/in_predicate.py +38 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_falsy_predicate.py +5 -1
- py_predicate-1.2/predicate/is_instance_predicate.py +105 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_none_predicate.py +5 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_not_none_predicate.py +5 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_predicate_of_p.py +4 -0
- py_predicate-1.2/predicate/is_subclass_predicate.py +48 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_truthy_predicate.py +5 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/lazy_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/le_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/list_of_predicate.py +10 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/lt_predicate.py +10 -1
- py_predicate-1.2/predicate/match_predicate.py +230 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/ne_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/negate.py +5 -3
- py_predicate-1.2/predicate/not_in_predicate.py +31 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/all_optimizer.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/and_optimizer.py +3 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/in_optimizer.py +2 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/or_optimizer.py +3 -2
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/predicate_optimizer.py +2 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/xor_optimizer.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/predicate.py +5 -5
- {py_predicate-1.0 → py_predicate-1.2}/predicate/property_predicate.py +11 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/range_predicate.py +20 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/regex_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/set_of_predicate.py +15 -3
- {py_predicate-1.0 → py_predicate-1.2}/predicate/set_predicates.py +0 -61
- py_predicate-1.2/predicate/spec/__init__.py +0 -0
- py_predicate-1.2/predicate/spec/exercise.py +189 -0
- py_predicate-1.2/predicate/spec/instrument.py +48 -0
- py_predicate-1.2/predicate/spec/spec.py +13 -0
- py_predicate-1.2/predicate/standard_predicates.py +95 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/str_predicates.py +1 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/tee_predicate.py +6 -1
- {py_predicate-1.0 → py_predicate-1.2}/predicate/tuple_of_predicate.py +5 -0
- {py_predicate-1.0 → py_predicate-1.2}/pyproject.toml +1 -1
- py_predicate-1.0/predicate/fn_predicate.py +0 -27
- py_predicate-1.0/predicate/generator/helpers.py +0 -216
- py_predicate-1.0/predicate/has_length_predicate.py +0 -23
- py_predicate-1.0/predicate/is_instance_predicate.py +0 -29
- py_predicate-1.0/predicate/match_predicate.py +0 -144
- py_predicate-1.0/predicate/standard_predicates.py +0 -354
- {py_predicate-1.0 → py_predicate-1.2}/LICENSE +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/constructor/__init__.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/constructor/helpers.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/constructor/mutate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/explain.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/formatter/__init__.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/formatter/format_json.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/formatter/helpers.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/generator/__init__.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/implies_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/in_predicate_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/ip_address_predicates.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_callable_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/is_lambda_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/named_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/__init__.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/any_optimizer.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/helpers.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/optimizer/not_optimizer.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/parser.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/root_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/this_predicate.py +0 -0
- {py_predicate-1.0 → py_predicate-1.2}/predicate/truth_table.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: py_predicate
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2
|
|
4
4
|
Summary: Module to create composable predicates
|
|
5
5
|
Author-email: Maurits Rijk <maurits.rijk@gmail.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -50,6 +50,9 @@ Provides-Extra: test
|
|
|
50
50
|
|
|
51
51
|
py-predicate is a typed Python library to create composable predicates.
|
|
52
52
|
|
|
53
|
+
These predicates can be used for generating test-cases (property based testing) and
|
|
54
|
+
run-time instrumenting of functions against a specification based on predicates.
|
|
55
|
+
|
|
53
56
|
# Getting started
|
|
54
57
|
|
|
55
58
|
To get started, install the library with [pip](https://pip.pypa.io/en/stable/)
|
|
@@ -87,9 +90,14 @@ series of integers for which the predicate ``between_2_and_3`` is False. The ``g
|
|
|
87
90
|
infinite (well, with lots of duplicates obviously) series of integers for which the predicate is True.
|
|
88
91
|
|
|
89
92
|
```python
|
|
90
|
-
from predicate import generate_false, generate_true
|
|
93
|
+
from predicate import generate_false, generate_true, ge_p, le_p
|
|
91
94
|
from more_itertools import take
|
|
92
95
|
|
|
96
|
+
ge_2 = ge_p(2)
|
|
97
|
+
le_3 = le_p(3)
|
|
98
|
+
|
|
99
|
+
between_2_and_3 = ge_2 & le_3
|
|
100
|
+
|
|
93
101
|
take(5, generate_true(between_2_and_3))
|
|
94
102
|
|
|
95
103
|
take(5, generate_false(between_2_and_3))
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
py-predicate is a typed Python library to create composable predicates.
|
|
8
8
|
|
|
9
|
+
These predicates can be used for generating test-cases (property based testing) and
|
|
10
|
+
run-time instrumenting of functions against a specification based on predicates.
|
|
11
|
+
|
|
9
12
|
# Getting started
|
|
10
13
|
|
|
11
14
|
To get started, install the library with [pip](https://pip.pypa.io/en/stable/)
|
|
@@ -43,9 +46,14 @@ series of integers for which the predicate ``between_2_and_3`` is False. The ``g
|
|
|
43
46
|
infinite (well, with lots of duplicates obviously) series of integers for which the predicate is True.
|
|
44
47
|
|
|
45
48
|
```python
|
|
46
|
-
from predicate import generate_false, generate_true
|
|
49
|
+
from predicate import generate_false, generate_true, ge_p, le_p
|
|
47
50
|
from more_itertools import take
|
|
48
51
|
|
|
52
|
+
ge_2 = ge_p(2)
|
|
53
|
+
le_3 = le_p(3)
|
|
54
|
+
|
|
55
|
+
between_2_and_3 = ge_2 & le_3
|
|
56
|
+
|
|
49
57
|
take(5, generate_true(between_2_and_3))
|
|
50
58
|
|
|
51
59
|
take(5, generate_false(between_2_and_3))
|
|
@@ -2,86 +2,79 @@
|
|
|
2
2
|
|
|
3
3
|
__version__ = "0.0.1"
|
|
4
4
|
|
|
5
|
+
from predicate.all_predicate import all_p
|
|
5
6
|
from predicate.always_false_predicate import always_false_p, never_p
|
|
6
7
|
from predicate.always_true_predicate import always_p, always_true_p
|
|
8
|
+
from predicate.any_predicate import any_p
|
|
9
|
+
from predicate.comp_predicate import comp_p
|
|
10
|
+
from predicate.dict_of_predicate import is_dict_of_p
|
|
11
|
+
from predicate.eq_predicate import eq_false_p, eq_p, eq_true_p, zero_p
|
|
7
12
|
from predicate.explain import explain
|
|
13
|
+
from predicate.fn_predicate import fn_p, is_even_p, is_finite_p, is_inf_p, is_nan_p, is_odd_p
|
|
8
14
|
from predicate.formatter import to_dot, to_json, to_latex
|
|
15
|
+
from predicate.ge_predicate import ge_p
|
|
9
16
|
from predicate.generator.generate_false import generate_false
|
|
10
17
|
from predicate.generator.generate_true import generate_true
|
|
18
|
+
from predicate.gt_predicate import gt_p, pos_p
|
|
19
|
+
from predicate.has_key_predicate import has_key_p
|
|
20
|
+
from predicate.has_length_predicate import has_length_p, is_empty_p, is_not_empty_p
|
|
21
|
+
from predicate.has_path_predicate import has_path_p
|
|
22
|
+
from predicate.implies_predicate import implies_p
|
|
23
|
+
from predicate.in_predicate import in_p
|
|
24
|
+
from predicate.is_falsy_predicate import is_falsy_p
|
|
25
|
+
from predicate.is_instance_predicate import (
|
|
26
|
+
is_bool_p,
|
|
27
|
+
is_callable_p,
|
|
28
|
+
is_complex_p,
|
|
29
|
+
is_container_p,
|
|
30
|
+
is_datetime_p,
|
|
31
|
+
is_hashable_p,
|
|
32
|
+
is_instance_p,
|
|
33
|
+
is_iterable_p,
|
|
34
|
+
is_predicate_p,
|
|
35
|
+
is_range_p,
|
|
36
|
+
is_set_p,
|
|
37
|
+
is_tuple_p,
|
|
38
|
+
is_uuid_p,
|
|
39
|
+
)
|
|
11
40
|
from predicate.is_lambda_predicate import is_lambda_p, is_lambda_with_signature_p
|
|
41
|
+
from predicate.is_none_predicate import is_none_p
|
|
42
|
+
from predicate.is_not_none_predicate import is_not_none_p
|
|
43
|
+
from predicate.is_predicate_of_p import is_predicate_of_p
|
|
44
|
+
from predicate.is_subclass_predicate import is_enum_p
|
|
45
|
+
from predicate.is_truthy_predicate import is_truthy_p
|
|
46
|
+
from predicate.lazy_predicate import lazy_p
|
|
47
|
+
from predicate.le_predicate import le_p
|
|
48
|
+
from predicate.list_of_predicate import is_list_of_p
|
|
49
|
+
from predicate.lt_predicate import lt_p, neg_p
|
|
12
50
|
from predicate.match_predicate import exactly_n, match_p, optional, plus, repeat, star
|
|
51
|
+
from predicate.ne_predicate import ne_p
|
|
52
|
+
from predicate.not_in_predicate import not_in_p
|
|
13
53
|
from predicate.optimizer.predicate_optimizer import can_optimize, optimize
|
|
54
|
+
from predicate.range_predicate import ge_le_p, ge_lt_p, gt_le_p, gt_lt_p
|
|
55
|
+
from predicate.regex_predicate import regex_p
|
|
56
|
+
from predicate.set_of_predicate import is_set_of_p
|
|
14
57
|
from predicate.set_predicates import (
|
|
15
|
-
in_p,
|
|
16
58
|
is_real_subset_p,
|
|
17
59
|
is_real_superset_p,
|
|
18
60
|
is_subset_p,
|
|
19
61
|
is_superset_p,
|
|
20
|
-
not_in_p,
|
|
21
62
|
)
|
|
63
|
+
from predicate.spec.exercise import exercise
|
|
64
|
+
from predicate.spec.instrument import instrument_function
|
|
65
|
+
from predicate.spec.spec import Spec
|
|
22
66
|
from predicate.standard_predicates import (
|
|
23
|
-
all_p,
|
|
24
|
-
any_p,
|
|
25
|
-
comp_p,
|
|
26
|
-
eq_false_p,
|
|
27
|
-
eq_p,
|
|
28
|
-
eq_true_p,
|
|
29
|
-
fn_p,
|
|
30
|
-
ge_le_p,
|
|
31
|
-
ge_lt_p,
|
|
32
|
-
ge_p,
|
|
33
|
-
gt_le_p,
|
|
34
|
-
gt_lt_p,
|
|
35
|
-
gt_p,
|
|
36
|
-
has_key_p,
|
|
37
|
-
has_length_p,
|
|
38
|
-
is_bool_p,
|
|
39
|
-
is_callable_p,
|
|
40
|
-
is_complex_p,
|
|
41
|
-
is_container_p,
|
|
42
|
-
is_datetime_p,
|
|
43
|
-
is_dict_of_p,
|
|
44
67
|
is_dict_p,
|
|
45
|
-
is_empty_p,
|
|
46
|
-
is_even_p,
|
|
47
|
-
is_falsy_p,
|
|
48
|
-
is_finite_p,
|
|
49
68
|
is_float_p,
|
|
50
|
-
is_hashable_p,
|
|
51
|
-
is_inf_p,
|
|
52
|
-
is_instance_p,
|
|
53
69
|
is_int_p,
|
|
54
70
|
is_iterable_of_p,
|
|
55
|
-
is_iterable_p,
|
|
56
|
-
is_list_of_p,
|
|
57
71
|
is_list_p,
|
|
58
|
-
is_nan_p,
|
|
59
|
-
is_none_p,
|
|
60
|
-
is_not_empty_p,
|
|
61
|
-
is_not_none_p,
|
|
62
|
-
is_odd_p,
|
|
63
|
-
is_predicate_of_p,
|
|
64
|
-
is_predicate_p,
|
|
65
|
-
is_range_p,
|
|
66
|
-
is_set_of_p,
|
|
67
|
-
is_set_p,
|
|
68
72
|
is_str_p,
|
|
69
|
-
is_truthy_p,
|
|
70
|
-
is_tuple_of_p,
|
|
71
|
-
is_tuple_p,
|
|
72
|
-
is_uuid_p,
|
|
73
|
-
lazy_p,
|
|
74
|
-
le_p,
|
|
75
|
-
lt_p,
|
|
76
|
-
ne_p,
|
|
77
|
-
neg_p,
|
|
78
|
-
pos_p,
|
|
79
|
-
regex_p,
|
|
80
73
|
root_p,
|
|
81
|
-
tee_p,
|
|
82
74
|
this_p,
|
|
83
|
-
zero_p,
|
|
84
75
|
)
|
|
76
|
+
from predicate.tee_predicate import tee_p
|
|
77
|
+
from predicate.tuple_of_predicate import is_tuple_of_p
|
|
85
78
|
|
|
86
79
|
__all__ = [
|
|
87
80
|
"all_p",
|
|
@@ -95,6 +88,7 @@ __all__ = [
|
|
|
95
88
|
"eq_p",
|
|
96
89
|
"eq_true_p",
|
|
97
90
|
"exactly_n",
|
|
91
|
+
"exercise",
|
|
98
92
|
"explain",
|
|
99
93
|
"fn_p",
|
|
100
94
|
"ge_le_p",
|
|
@@ -107,7 +101,10 @@ __all__ = [
|
|
|
107
101
|
"gt_p",
|
|
108
102
|
"has_key_p",
|
|
109
103
|
"has_length_p",
|
|
104
|
+
"has_path_p",
|
|
105
|
+
"implies_p",
|
|
110
106
|
"in_p",
|
|
107
|
+
"instrument_function",
|
|
111
108
|
"is_alnum_p",
|
|
112
109
|
"is_alpha_p",
|
|
113
110
|
"is_ascii_p",
|
|
@@ -120,6 +117,7 @@ __all__ = [
|
|
|
120
117
|
"is_dict_of_p",
|
|
121
118
|
"is_dict_p",
|
|
122
119
|
"is_empty_p",
|
|
120
|
+
"is_enum_p",
|
|
123
121
|
"is_even_p",
|
|
124
122
|
"is_falsy_p",
|
|
125
123
|
"is_finite_p",
|
|
@@ -179,6 +177,7 @@ __all__ = [
|
|
|
179
177
|
"to_json",
|
|
180
178
|
"to_latex",
|
|
181
179
|
"zero_p",
|
|
180
|
+
"Spec",
|
|
182
181
|
]
|
|
183
182
|
|
|
184
183
|
from predicate.str_predicates import (
|
|
@@ -2,7 +2,7 @@ from dataclasses import dataclass
|
|
|
2
2
|
from typing import Iterable, override
|
|
3
3
|
|
|
4
4
|
from predicate.helpers import first_false
|
|
5
|
-
from predicate.predicate import Predicate
|
|
5
|
+
from predicate.predicate import Predicate, resolve_predicate
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@dataclass
|
|
@@ -34,3 +34,8 @@ class AllPredicate[T](Predicate[T]):
|
|
|
34
34
|
fail = first_false(iterable, self.predicate)
|
|
35
35
|
|
|
36
36
|
return {"reason": f"Item '{fail}' didn't match predicate {self.predicate!r}"}
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def all_p[T](predicate: Predicate[T]) -> AllPredicate[T]:
|
|
40
|
+
"""Return True if the predicate holds for each item in the iterable, otherwise False."""
|
|
41
|
+
return AllPredicate(predicate=resolve_predicate(predicate))
|
|
@@ -8,7 +8,7 @@ from predicate.predicate import Predicate
|
|
|
8
8
|
class AlwaysFalsePredicate(Predicate):
|
|
9
9
|
"""A predicate class that models the 'False' predicate."""
|
|
10
10
|
|
|
11
|
-
def __call__(self, *args, **kwargs):
|
|
11
|
+
def __call__(self, *args, **kwargs) -> bool:
|
|
12
12
|
return False
|
|
13
13
|
|
|
14
14
|
def __repr__(self) -> str:
|
|
@@ -8,7 +8,7 @@ from predicate.predicate import Predicate
|
|
|
8
8
|
class AlwaysTruePredicate(Predicate):
|
|
9
9
|
"""A predicate class that models the 'True' predicate."""
|
|
10
10
|
|
|
11
|
-
def __call__(self, *args, **kwargs):
|
|
11
|
+
def __call__(self, *args, **kwargs) -> bool:
|
|
12
12
|
return True
|
|
13
13
|
|
|
14
14
|
def __repr__(self) -> str:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from typing import Iterable, override
|
|
3
3
|
|
|
4
|
-
from predicate.predicate import Predicate
|
|
4
|
+
from predicate.predicate import Predicate, resolve_predicate
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
@dataclass
|
|
@@ -31,3 +31,8 @@ class AnyPredicate[T](Predicate[T]):
|
|
|
31
31
|
@override
|
|
32
32
|
def explain_failure(self, iterable: Iterable[T]) -> dict:
|
|
33
33
|
return {"reason": f"No item matches predicate {self.predicate!r}"}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def any_p[T](predicate: Predicate[T]) -> AnyPredicate[T]:
|
|
37
|
+
"""Return True if the predicate holds for any item in the iterable, otherwise False."""
|
|
38
|
+
return AnyPredicate(predicate=resolve_predicate(predicate))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Callable, override
|
|
2
|
+
from typing import Any, Callable, override
|
|
3
3
|
|
|
4
4
|
from predicate.predicate import Predicate
|
|
5
5
|
|
|
@@ -24,3 +24,8 @@ class CompPredicate[S, T](Predicate[T]):
|
|
|
24
24
|
@override
|
|
25
25
|
def explain_failure(self, x: S) -> dict:
|
|
26
26
|
return {"reason": self.predicate.explain(x)}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def comp_p[T](fn: Callable[[Any], T], predicate: Predicate[T]) -> CompPredicate:
|
|
30
|
+
"""Return a predicate, composed of a function and another predicate."""
|
|
31
|
+
return CompPredicate(fn=fn, predicate=predicate)
|
|
@@ -5,30 +5,26 @@ from more_itertools import first, gray_product, take
|
|
|
5
5
|
from predicate import (
|
|
6
6
|
always_false_p,
|
|
7
7
|
always_true_p,
|
|
8
|
+
ge_p,
|
|
9
|
+
gt_p,
|
|
8
10
|
is_datetime_p,
|
|
9
11
|
is_falsy_p,
|
|
10
12
|
is_float_p,
|
|
11
13
|
is_int_p,
|
|
14
|
+
is_none_p,
|
|
12
15
|
is_not_none_p,
|
|
13
16
|
is_set_p,
|
|
14
17
|
is_str_p,
|
|
15
18
|
is_truthy_p,
|
|
16
|
-
)
|
|
17
|
-
from predicate.constructor.helpers import perfect_match, sort_by_match
|
|
18
|
-
from predicate.constructor.mutate import mutations
|
|
19
|
-
from predicate.predicate import Predicate
|
|
20
|
-
from predicate.standard_predicates import (
|
|
21
|
-
ge_p,
|
|
22
|
-
gt_p,
|
|
23
|
-
is_bool_p,
|
|
24
|
-
is_dict_p,
|
|
25
|
-
is_list_p,
|
|
26
|
-
is_none_p,
|
|
27
19
|
le_p,
|
|
28
20
|
lt_p,
|
|
29
21
|
ne_p,
|
|
30
|
-
zero_p,
|
|
31
22
|
)
|
|
23
|
+
from predicate.constructor.helpers import perfect_match, sort_by_match
|
|
24
|
+
from predicate.constructor.mutate import mutations
|
|
25
|
+
from predicate.eq_predicate import zero_p
|
|
26
|
+
from predicate.is_instance_predicate import is_bool_p, is_dict_p, is_list_p
|
|
27
|
+
from predicate.predicate import Predicate
|
|
32
28
|
|
|
33
29
|
|
|
34
30
|
def construct(false_set: list, true_set: list, attempts: int = 30) -> Predicate | None:
|
|
@@ -53,7 +53,7 @@ class DictOfPredicate[T](Predicate[T]):
|
|
|
53
53
|
|
|
54
54
|
|
|
55
55
|
def to_key_p(key_p: Predicate | str) -> Predicate:
|
|
56
|
-
from predicate
|
|
56
|
+
from predicate import eq_p
|
|
57
57
|
|
|
58
58
|
match key_p:
|
|
59
59
|
case str(s):
|
|
@@ -68,3 +68,9 @@ def from_key_p(key_p: Predicate) -> Predicate | str:
|
|
|
68
68
|
return v
|
|
69
69
|
case _:
|
|
70
70
|
return key_p
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def is_dict_of_p(*predicates: tuple[Predicate | str, Predicate]) -> Predicate:
|
|
74
|
+
"""Return True if value is a set, and for all elements in the set the predicate is True, otherwise False."""
|
|
75
|
+
# return is_set_p & all_p(predicate)
|
|
76
|
+
return DictOfPredicate(list(predicates))
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import override
|
|
2
|
+
from typing import Final, override
|
|
3
3
|
|
|
4
4
|
from predicate.predicate import Predicate
|
|
5
5
|
|
|
@@ -23,3 +23,18 @@ class EqPredicate[T](Predicate[T]):
|
|
|
23
23
|
@override
|
|
24
24
|
def explain_failure(self, x: T) -> dict:
|
|
25
25
|
return {"reason": f"{x} is not equal to {self.v!r}"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def eq_p[T](v: T) -> EqPredicate[T]:
|
|
29
|
+
"""Return True if the value is equal to the constant, otherwise False."""
|
|
30
|
+
return EqPredicate(v=v)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
zero_p: Final[EqPredicate] = eq_p(0)
|
|
34
|
+
"""Returns True of the value is zero, otherwise False."""
|
|
35
|
+
|
|
36
|
+
eq_true_p: Final[EqPredicate] = eq_p(True)
|
|
37
|
+
"""Returns True if the value is True, otherwise False."""
|
|
38
|
+
|
|
39
|
+
eq_false_p: Final[EqPredicate] = eq_p(False)
|
|
40
|
+
"""Returns True if the value is False, otherwise False."""
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import math
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from itertools import repeat
|
|
4
|
+
from typing import Callable, Final, Iterator, override
|
|
5
|
+
|
|
6
|
+
from predicate.generator.helpers import generate_even_numbers, generate_odd_numbers, random_floats
|
|
7
|
+
from predicate.predicate import Predicate
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def undefined() -> Iterator:
|
|
11
|
+
raise ValueError("Please register generator type")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class FnPredicate[T](Predicate[T]):
|
|
16
|
+
"""A predicate class that can hold a function."""
|
|
17
|
+
|
|
18
|
+
predicate_fn: Callable[[T], bool]
|
|
19
|
+
generate_false_fn: Callable[[], Iterator] = undefined
|
|
20
|
+
generate_true_fn: Callable[[], Iterator] = undefined
|
|
21
|
+
|
|
22
|
+
def __call__(self, x: T) -> bool:
|
|
23
|
+
return self.predicate_fn(x)
|
|
24
|
+
|
|
25
|
+
def __repr__(self) -> str:
|
|
26
|
+
return f"fn_p(predicate_fn={self.predicate_fn.__name__})"
|
|
27
|
+
|
|
28
|
+
@override
|
|
29
|
+
def explain_failure(self, x: T) -> dict:
|
|
30
|
+
return {"reason": f"Function returned False for value {x}"}
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def fn_p[T](
|
|
34
|
+
fn: Callable[[T], bool],
|
|
35
|
+
generate_false_fn: Callable[[], Iterator[T]] = undefined,
|
|
36
|
+
generate_true_fn: Callable[[], Iterator[T]] = undefined,
|
|
37
|
+
) -> Predicate[T]:
|
|
38
|
+
"""Return the boolean value of the function call."""
|
|
39
|
+
return FnPredicate(predicate_fn=fn, generate_false_fn=generate_false_fn, generate_true_fn=generate_true_fn)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
is_even_p: Final[Predicate[int]] = fn_p(
|
|
43
|
+
fn=lambda x: x % 2 == 0, generate_true_fn=generate_even_numbers, generate_false_fn=generate_odd_numbers
|
|
44
|
+
)
|
|
45
|
+
is_odd_p: Final[Predicate[int]] = fn_p(
|
|
46
|
+
fn=lambda x: x % 2 != 0, generate_true_fn=generate_odd_numbers, generate_false_fn=generate_even_numbers
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def generate_nan() -> Iterator:
|
|
51
|
+
yield from repeat(math.nan)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def generate_inf() -> Iterator:
|
|
55
|
+
while True:
|
|
56
|
+
yield -math.inf
|
|
57
|
+
yield math.inf
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
is_finite_p: Final[Predicate] = fn_p(fn=math.isfinite, generate_true_fn=random_floats, generate_false_fn=generate_inf)
|
|
61
|
+
"""Return True if value is finite, otherwise False."""
|
|
62
|
+
|
|
63
|
+
is_inf_p: Final[Predicate] = fn_p(fn=math.isinf, generate_true_fn=generate_inf, generate_false_fn=random_floats)
|
|
64
|
+
"""Return True if value is infinite, otherwise False."""
|
|
65
|
+
|
|
66
|
+
is_nan_p: Final[Predicate] = fn_p(fn=math.isnan, generate_true_fn=generate_nan, generate_false_fn=random_floats)
|
|
67
|
+
"""Return True if value is not a number, otherwise False."""
|
|
@@ -17,6 +17,7 @@ from predicate.formatter.helpers import set_to_str
|
|
|
17
17
|
from predicate.ge_predicate import GePredicate
|
|
18
18
|
from predicate.gt_predicate import GtPredicate
|
|
19
19
|
from predicate.implies import Implies
|
|
20
|
+
from predicate.in_predicate import InPredicate
|
|
20
21
|
from predicate.is_falsy_predicate import IsFalsyPredicate
|
|
21
22
|
from predicate.is_instance_predicate import IsInstancePredicate
|
|
22
23
|
from predicate.is_none_predicate import IsNonePredicate
|
|
@@ -26,6 +27,7 @@ from predicate.le_predicate import LePredicate
|
|
|
26
27
|
from predicate.lt_predicate import LtPredicate
|
|
27
28
|
from predicate.named_predicate import NamedPredicate
|
|
28
29
|
from predicate.ne_predicate import NePredicate
|
|
30
|
+
from predicate.not_in_predicate import NotInPredicate
|
|
29
31
|
from predicate.optimizer.predicate_optimizer import optimize
|
|
30
32
|
from predicate.predicate import (
|
|
31
33
|
AndPredicate,
|
|
@@ -37,12 +39,10 @@ from predicate.predicate import (
|
|
|
37
39
|
from predicate.range_predicate import GeLePredicate, GeLtPredicate, GtLePredicate, GtLtPredicate
|
|
38
40
|
from predicate.root_predicate import RootPredicate, find_root_predicate
|
|
39
41
|
from predicate.set_predicates import (
|
|
40
|
-
InPredicate,
|
|
41
42
|
IsRealSubsetPredicate,
|
|
42
43
|
IsRealSupersetPredicate,
|
|
43
44
|
IsSubsetPredicate,
|
|
44
45
|
IsSupersetPredicate,
|
|
45
|
-
NotInPredicate,
|
|
46
46
|
)
|
|
47
47
|
from predicate.tee_predicate import TeePredicate
|
|
48
48
|
from predicate.this_predicate import ThisPredicate, find_this_predicate
|
|
@@ -6,6 +6,7 @@ from predicate.eq_predicate import EqPredicate
|
|
|
6
6
|
from predicate.ge_predicate import GePredicate
|
|
7
7
|
from predicate.gt_predicate import GtPredicate
|
|
8
8
|
from predicate.implies_predicate import ImpliesPredicate
|
|
9
|
+
from predicate.in_predicate import InPredicate
|
|
9
10
|
from predicate.le_predicate import LePredicate
|
|
10
11
|
from predicate.lt_predicate import LtPredicate
|
|
11
12
|
from predicate.ne_predicate import NePredicate
|
|
@@ -18,7 +19,6 @@ from predicate.predicate import (
|
|
|
18
19
|
)
|
|
19
20
|
from predicate.range_predicate import GeLePredicate, GeLtPredicate, GtLePredicate, GtLtPredicate
|
|
20
21
|
from predicate.set_predicates import (
|
|
21
|
-
InPredicate,
|
|
22
22
|
IsRealSubsetPredicate,
|
|
23
23
|
IsRealSupersetPredicate,
|
|
24
24
|
IsSubsetPredicate,
|
|
@@ -23,3 +23,8 @@ class GePredicate[T](Predicate[T]):
|
|
|
23
23
|
@override
|
|
24
24
|
def explain_failure(self, x: T) -> dict:
|
|
25
25
|
return {"reason": f"{x} is not greater or equal to {self.v!r}"}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def ge_p(v: ConstrainedT) -> GePredicate[ConstrainedT]:
|
|
29
|
+
"""Return True if the value is greater or equal than the constant, otherwise False."""
|
|
30
|
+
return GePredicate(v=v)
|