itercmp 0.0.0.dev0__tar.gz → 0.1.0__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.
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/PKG-INFO +2 -2
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/README.rst +1 -1
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/pyproject.toml +1 -1
- itercmp-0.1.0/src/itercmp/dunder/__init__.py +32 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp.egg-info/PKG-INFO +2 -2
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp.egg-info/SOURCES.txt +3 -1
- itercmp-0.1.0/tests/test_dunder_le.py +466 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/LICENSE.txt +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/MANIFEST.in +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/run_tests.py +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/setup.cfg +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp/__init__.py +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp/py.typed +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp.egg-info/dependency_links.txt +0 -0
- {itercmp-0.0.0.dev0 → itercmp-0.1.0}/src/itercmp.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: itercmp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: This project accesses a given TOML file.
|
|
5
5
|
Author-email: Johannes <johannes.programming@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,4 +25,4 @@ itercmp
|
|
|
25
25
|
|
|
26
26
|
Each minor version has its own documentation.
|
|
27
27
|
These docs can be found as rst-files in the ``docs/`` directory of this project.
|
|
28
|
-
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://
|
|
28
|
+
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://itercmp.johannes-programming.online/>`_.
|
|
@@ -4,4 +4,4 @@ itercmp
|
|
|
4
4
|
|
|
5
5
|
Each minor version has its own documentation.
|
|
6
6
|
These docs can be found as rst-files in the ``docs/`` directory of this project.
|
|
7
|
-
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://
|
|
7
|
+
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://itercmp.johannes-programming.online/>`_.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import operator as op
|
|
2
|
+
from collections.abc import Callable, Collection
|
|
3
|
+
from functools import partial
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
__all__ = ["ge", "gt", "le", "lt", "ordering"]
|
|
7
|
+
|
|
8
|
+
# def eq(x: Collection[Any], y: Collection[Any], /) -> bool:
|
|
9
|
+
# for a, b in zip(x, y):
|
|
10
|
+
# if a is b or a == b:
|
|
11
|
+
# continue
|
|
12
|
+
# return False
|
|
13
|
+
# return len(x) == len(y)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def ordering(
|
|
17
|
+
operator: Callable[[Any, Any], Any],
|
|
18
|
+
x: Collection[Any],
|
|
19
|
+
y: Collection[Any],
|
|
20
|
+
/,
|
|
21
|
+
) -> Any:
|
|
22
|
+
for a, b in zip(x, y):
|
|
23
|
+
if a is b or a == b:
|
|
24
|
+
continue
|
|
25
|
+
return operator(x, y)
|
|
26
|
+
return operator(len(x), len(y))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
ge = partial(ordering, op.ge)
|
|
30
|
+
gt = partial(ordering, op.gt)
|
|
31
|
+
le = partial(ordering, op.le)
|
|
32
|
+
lt = partial(ordering, op.lt)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: itercmp
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: This project accesses a given TOML file.
|
|
5
5
|
Author-email: Johannes <johannes.programming@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -25,4 +25,4 @@ itercmp
|
|
|
25
25
|
|
|
26
26
|
Each minor version has its own documentation.
|
|
27
27
|
These docs can be found as rst-files in the ``docs/`` directory of this project.
|
|
28
|
-
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://
|
|
28
|
+
They can also be viewed on the website `https://itercmp.johannes-programming.online/ <https://itercmp.johannes-programming.online/>`_.
|
|
@@ -9,4 +9,6 @@ src/itercmp/py.typed
|
|
|
9
9
|
src/itercmp.egg-info/PKG-INFO
|
|
10
10
|
src/itercmp.egg-info/SOURCES.txt
|
|
11
11
|
src/itercmp.egg-info/dependency_links.txt
|
|
12
|
-
src/itercmp.egg-info/top_level.txt
|
|
12
|
+
src/itercmp.egg-info/top_level.txt
|
|
13
|
+
src/itercmp/dunder/__init__.py
|
|
14
|
+
tests/test_dunder_le.py
|
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from collections.abc import Generator
|
|
3
|
+
from typing import Any, Self
|
|
4
|
+
|
|
5
|
+
import itercmp.dunder
|
|
6
|
+
|
|
7
|
+
__all__ = ["TestDunderLe"]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestDunderLe(unittest.TestCase):
|
|
11
|
+
def gen_000(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
12
|
+
class A:
|
|
13
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
14
|
+
return False
|
|
15
|
+
|
|
16
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
17
|
+
return NotImplemented
|
|
18
|
+
|
|
19
|
+
class B:
|
|
20
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
21
|
+
return False
|
|
22
|
+
|
|
23
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
24
|
+
return False
|
|
25
|
+
|
|
26
|
+
yield (A(),), (B(),)
|
|
27
|
+
|
|
28
|
+
def gen_001(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
29
|
+
class A:
|
|
30
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
31
|
+
return False
|
|
32
|
+
|
|
33
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
34
|
+
return NotImplemented
|
|
35
|
+
|
|
36
|
+
class B:
|
|
37
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
41
|
+
return True
|
|
42
|
+
|
|
43
|
+
yield (A(),), (B(),)
|
|
44
|
+
|
|
45
|
+
def gen_002(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
46
|
+
# Identity short-circuit: the SAME object in both positions must be
|
|
47
|
+
# treated as equal even when __eq__ says otherwise (the nan case).
|
|
48
|
+
# __le__ returns False so a missing `is` check would give the wrong
|
|
49
|
+
# answer instead of falling through to the length comparison.
|
|
50
|
+
class A:
|
|
51
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
52
|
+
return False
|
|
53
|
+
|
|
54
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
a = A()
|
|
58
|
+
yield (a,), (a,) # identity -> equal -> 1 <= 1 -> True
|
|
59
|
+
yield (a, 1), (a, 2) # identity skips, then 1 <= 2 -> True
|
|
60
|
+
yield (a, 2), (a, 1) # identity skips, then 2 <= 1 -> False
|
|
61
|
+
|
|
62
|
+
def gen_003(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
63
|
+
# Equal prefix -> result decided purely by length, every direction.
|
|
64
|
+
yield (1, 2), (1, 2, 3) # proper prefix, shorter -> True
|
|
65
|
+
yield (1, 2, 3), (1, 2) # proper prefix, longer -> False
|
|
66
|
+
yield (1, 2), (1, 2) # identical -> True
|
|
67
|
+
yield (), () # both empty -> True
|
|
68
|
+
yield (), (1,) # empty vs non-empty -> True
|
|
69
|
+
yield (1,), () # non-empty vs empty -> False
|
|
70
|
+
|
|
71
|
+
def gen_004(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
72
|
+
# Only the first differing pair decides; trailing elements are ignored.
|
|
73
|
+
yield (1, 9, 9), (2, 0, 0) # 1 <= 2 -> True regardless of rest
|
|
74
|
+
yield (2, 0, 0), (1, 9, 9) # 2 <= 1 -> False regardless of rest
|
|
75
|
+
yield (1, 5), (1, 4, 100) # 5 <= 4 -> False even though lhs shorter
|
|
76
|
+
|
|
77
|
+
def gen_005(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
78
|
+
# __eq__ may return a non-bool; only its *truthiness* counts.
|
|
79
|
+
class Truthy:
|
|
80
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
81
|
+
return "non-empty" # truthy -> treated as equal
|
|
82
|
+
|
|
83
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
84
|
+
return False # must NOT be reached
|
|
85
|
+
|
|
86
|
+
class Falsy:
|
|
87
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
88
|
+
return [] # falsy -> treated as different
|
|
89
|
+
|
|
90
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
91
|
+
return True
|
|
92
|
+
|
|
93
|
+
yield (Truthy(),), (Truthy(),) # equal -> 1 <= 1 -> True
|
|
94
|
+
yield (Falsy(),), (Falsy(),) # differ -> __le__ -> True
|
|
95
|
+
|
|
96
|
+
def gen_006(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
97
|
+
# Reflected fallback: __le__ is absent, so a <= b uses b.__ge__(a).
|
|
98
|
+
class A:
|
|
99
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
100
|
+
return False
|
|
101
|
+
|
|
102
|
+
class B:
|
|
103
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
104
|
+
return False
|
|
105
|
+
|
|
106
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
107
|
+
return True
|
|
108
|
+
|
|
109
|
+
yield (A(),), (B(),) # A() <= B() -> B().__ge__(A()) -> True
|
|
110
|
+
|
|
111
|
+
def gen_007(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
112
|
+
# Cross-type numeric elements compared element-wise.
|
|
113
|
+
yield (1, 2.0), (1.0, 2) # all equal -> 2 <= 2 -> True
|
|
114
|
+
yield (True, 0), (1, False) # bool/int equality -> True
|
|
115
|
+
yield (1,), (1.5,) # 1 <= 1.5 -> True
|
|
116
|
+
|
|
117
|
+
def gen_008(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
118
|
+
# Strings and nested sequences: the differing element uses its own <=.
|
|
119
|
+
yield ("a", "b"), ("a", "c")
|
|
120
|
+
yield ("abc",), ("abd",)
|
|
121
|
+
yield ((1, 2),), ((1, 3),)
|
|
122
|
+
yield ((1, 2), 9), ((1, 2), 8)
|
|
123
|
+
|
|
124
|
+
def gen_009(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
125
|
+
# The motivating real-world case: nan.
|
|
126
|
+
nan = float("nan")
|
|
127
|
+
yield (nan,), (nan,) # same obj -> True
|
|
128
|
+
yield (float("nan"),), (float("nan"),) # distinct -> nan<=nan -> False
|
|
129
|
+
yield (1, nan), (1, nan) # same obj after equal prefix
|
|
130
|
+
yield (1, float("nan")), (
|
|
131
|
+
1,
|
|
132
|
+
float("nan"),
|
|
133
|
+
) # distinct after equal prefix
|
|
134
|
+
|
|
135
|
+
def gen_010(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
136
|
+
# Both directions NotImplemented -> a <= b raises TypeError; the
|
|
137
|
+
# container __le__ must propagate it identically.
|
|
138
|
+
class A:
|
|
139
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
140
|
+
return False
|
|
141
|
+
|
|
142
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
143
|
+
return NotImplemented
|
|
144
|
+
|
|
145
|
+
class B:
|
|
146
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
150
|
+
return NotImplemented
|
|
151
|
+
|
|
152
|
+
yield (A(),), (B(),)
|
|
153
|
+
|
|
154
|
+
def gen_011(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
155
|
+
# __eq__ raises during the equality scan. The exception must propagate
|
|
156
|
+
# identically (type, repr, str) instead of being swallowed. Distinct
|
|
157
|
+
# objects, so the identity short-circuit does not hide the call.
|
|
158
|
+
class A:
|
|
159
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
160
|
+
raise ValueError("eq boom")
|
|
161
|
+
|
|
162
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
yield (A(),), (A(),)
|
|
166
|
+
yield (1, A()), (1, A()) # raise only after an equal prefix
|
|
167
|
+
|
|
168
|
+
def gen_012(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
169
|
+
# First pair is unequal, so the FINAL element comparison is reached and
|
|
170
|
+
# its __le__ raises -> must propagate identically.
|
|
171
|
+
class A:
|
|
172
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
176
|
+
raise RuntimeError("le boom")
|
|
177
|
+
|
|
178
|
+
yield (A(),), (A(),)
|
|
179
|
+
|
|
180
|
+
def gen_013(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
181
|
+
# __eq__ returns an object whose __bool__ raises (the numpy-array
|
|
182
|
+
# "ambiguous truth value" case). Taking truthiness of the eq result
|
|
183
|
+
# must raise the same way PyObject_IsTrue does at the C level.
|
|
184
|
+
class Ambiguous:
|
|
185
|
+
def __bool__(self: Self, /) -> Any:
|
|
186
|
+
raise ValueError("ambiguous truth value")
|
|
187
|
+
|
|
188
|
+
class A:
|
|
189
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
190
|
+
return Ambiguous()
|
|
191
|
+
|
|
192
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
193
|
+
return True
|
|
194
|
+
|
|
195
|
+
yield (A(),), (A(),)
|
|
196
|
+
|
|
197
|
+
def gen_014(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
198
|
+
# Both sides' __eq__ return NotImplemented -> Python falls back to
|
|
199
|
+
# identity (False for distinct objects) -> the pair counts as DIFFERENT
|
|
200
|
+
# and the element __le__ decides. An unresolved __eq__ must not be
|
|
201
|
+
# mistaken for "equal".
|
|
202
|
+
class A:
|
|
203
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
204
|
+
return NotImplemented
|
|
205
|
+
|
|
206
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
207
|
+
return True
|
|
208
|
+
|
|
209
|
+
yield (A(),), (A(),)
|
|
210
|
+
|
|
211
|
+
def gen_015(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
212
|
+
# Identity short-circuit must skip a __eq__ that would otherwise raise,
|
|
213
|
+
# proving `is` is tested BEFORE `==`. Same object at the first and at a
|
|
214
|
+
# middle position.
|
|
215
|
+
class Boom:
|
|
216
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
217
|
+
raise ValueError("must not be called")
|
|
218
|
+
|
|
219
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
b = Boom()
|
|
223
|
+
yield (b,), (b,) # identity at pos 0 -> 1 <= 1 -> True
|
|
224
|
+
yield (1, b, 2), (1, b, 3) # identity mid, then 2 <= 3 -> True
|
|
225
|
+
yield (1, b, 9), (1, b, 8) # identity mid, then 9 <= 8 -> False
|
|
226
|
+
|
|
227
|
+
def gen_016(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
228
|
+
# Neither __le__ nor __ge__ defined; __lt__ is present as a red herring
|
|
229
|
+
# (<= must NOT consult it) -> a <= b raises TypeError. Confirms the
|
|
230
|
+
# identical "not supported between instances" message on both paths.
|
|
231
|
+
class A:
|
|
232
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
233
|
+
return False
|
|
234
|
+
|
|
235
|
+
def __lt__(self: Self, other: object, /) -> Any:
|
|
236
|
+
return True
|
|
237
|
+
|
|
238
|
+
class B:
|
|
239
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
240
|
+
return False
|
|
241
|
+
|
|
242
|
+
yield (A(),), (B(),)
|
|
243
|
+
|
|
244
|
+
def gen_017(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
245
|
+
# Long genuinely-equal prefix, divergence only at the last element.
|
|
246
|
+
yield (1, 2, 3, 4, 5), (1, 2, 3, 4, 6)
|
|
247
|
+
yield (1, 2, 3, 4, 6), (1, 2, 3, 4, 5)
|
|
248
|
+
yield (1, 2, 3, 4, 5), (1, 2, 3, 4, 5)
|
|
249
|
+
|
|
250
|
+
def gen_018(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
251
|
+
# Nested sequences whose own <= / length comparison decides the result.
|
|
252
|
+
yield ((1, 2),), ((1, 2, 3),) # inner: proper prefix -> True
|
|
253
|
+
yield ((1, 2, 3),), ((1, 2),) # inner: longer -> False
|
|
254
|
+
yield ((1, 2), (3,)), ((1, 2), (3, 0))
|
|
255
|
+
|
|
256
|
+
def gen_019(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
257
|
+
# Reflected fallback returning a NON-bool object must be preserved
|
|
258
|
+
# verbatim (the gen_900 idea, but reached through b.__ge__).
|
|
259
|
+
class A:
|
|
260
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
261
|
+
return False
|
|
262
|
+
|
|
263
|
+
class B:
|
|
264
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
265
|
+
return False
|
|
266
|
+
|
|
267
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
268
|
+
return "reflected-yes"
|
|
269
|
+
|
|
270
|
+
yield (A(),), (B(),)
|
|
271
|
+
|
|
272
|
+
def gen_020(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
273
|
+
# __eq__ truthiness resolved via __len__ rather than __bool__: empty
|
|
274
|
+
# result -> falsy -> different; non-empty -> truthy -> equal.
|
|
275
|
+
class WithLen:
|
|
276
|
+
def __init__(self: Self, n: int, /) -> None:
|
|
277
|
+
self.n = n
|
|
278
|
+
|
|
279
|
+
def __len__(self: Self, /) -> int:
|
|
280
|
+
return self.n
|
|
281
|
+
|
|
282
|
+
class Eq0:
|
|
283
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
284
|
+
return WithLen(0) # falsy -> treated as different
|
|
285
|
+
|
|
286
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
287
|
+
return True
|
|
288
|
+
|
|
289
|
+
class Eq1:
|
|
290
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
291
|
+
return WithLen(1) # truthy -> treated as equal
|
|
292
|
+
|
|
293
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
294
|
+
return False # must NOT be reached
|
|
295
|
+
|
|
296
|
+
yield (Eq0(),), (Eq0(),) # differ -> __le__ -> True
|
|
297
|
+
yield (Eq1(),), (Eq1(),) # equal -> 1 <= 1 -> True
|
|
298
|
+
|
|
299
|
+
def gen_021(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
300
|
+
# Reflected fallback itself raises: a.__le__ defers (NotImplemented),
|
|
301
|
+
# then b.__ge__ raises -> exception propagates from the element compare.
|
|
302
|
+
class A:
|
|
303
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
304
|
+
return False
|
|
305
|
+
|
|
306
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
307
|
+
return NotImplemented
|
|
308
|
+
|
|
309
|
+
class B:
|
|
310
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
311
|
+
return False
|
|
312
|
+
|
|
313
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
314
|
+
raise RuntimeError("ge boom")
|
|
315
|
+
|
|
316
|
+
yield (A(),), (B(),)
|
|
317
|
+
|
|
318
|
+
def gen_022(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
319
|
+
# Identity short-circuit AFTER a real (==, not identity) equal prefix,
|
|
320
|
+
# combined with a distinct-nan tail; exercises is / == / length together.
|
|
321
|
+
nan = float("nan")
|
|
322
|
+
marker = object()
|
|
323
|
+
yield (1, marker, nan), (1, marker, nan) # same nan object -> True
|
|
324
|
+
yield (1, marker), (1, marker, 0) # equal prefix -> length -> True
|
|
325
|
+
|
|
326
|
+
def gen_900(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
327
|
+
class A:
|
|
328
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
329
|
+
return False
|
|
330
|
+
|
|
331
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
332
|
+
return 42
|
|
333
|
+
|
|
334
|
+
class B:
|
|
335
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
336
|
+
return False
|
|
337
|
+
|
|
338
|
+
yield (A(),), (B(),)
|
|
339
|
+
|
|
340
|
+
def gen_901(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
341
|
+
class A:
|
|
342
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
343
|
+
return NotImplemented
|
|
344
|
+
|
|
345
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
346
|
+
return True
|
|
347
|
+
|
|
348
|
+
class B:
|
|
349
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
350
|
+
return True
|
|
351
|
+
|
|
352
|
+
yield (A(),), (B(),)
|
|
353
|
+
|
|
354
|
+
def gen_902(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
355
|
+
class A:
|
|
356
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
357
|
+
return NotImplemented
|
|
358
|
+
|
|
359
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
360
|
+
return True
|
|
361
|
+
|
|
362
|
+
class B:
|
|
363
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
364
|
+
return False
|
|
365
|
+
|
|
366
|
+
yield (A(),), (B(),)
|
|
367
|
+
|
|
368
|
+
def gen_903(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
369
|
+
class A:
|
|
370
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
371
|
+
return NotImplemented
|
|
372
|
+
|
|
373
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
374
|
+
return False
|
|
375
|
+
|
|
376
|
+
class B:
|
|
377
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
378
|
+
return True
|
|
379
|
+
|
|
380
|
+
yield (A(),), (B(),)
|
|
381
|
+
|
|
382
|
+
def gen_904(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
383
|
+
class A:
|
|
384
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
385
|
+
return NotImplemented
|
|
386
|
+
|
|
387
|
+
def __le__(self: Self, other: object, /) -> Any:
|
|
388
|
+
return False
|
|
389
|
+
|
|
390
|
+
class B:
|
|
391
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
392
|
+
return False
|
|
393
|
+
|
|
394
|
+
yield (A(),), (B(),)
|
|
395
|
+
|
|
396
|
+
def gen_905(self: Self) -> Generator[tuple[Any, Any], None, None]:
|
|
397
|
+
# Both __eq__ return NotImplemented (distinct objects) -> equality falls
|
|
398
|
+
# back to identity (False) -> different -> a <= b via reflected __ge__.
|
|
399
|
+
class A:
|
|
400
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
401
|
+
return NotImplemented
|
|
402
|
+
|
|
403
|
+
class B:
|
|
404
|
+
def __eq__(self: Self, other: object, /) -> Any:
|
|
405
|
+
return NotImplemented
|
|
406
|
+
|
|
407
|
+
def __ge__(self: Self, other: object, /) -> Any:
|
|
408
|
+
return True
|
|
409
|
+
|
|
410
|
+
yield (A(),), (B(),)
|
|
411
|
+
|
|
412
|
+
def go(self: Self, c: Any, x: Any, y: Any, /) -> tuple[Any, Any]:
|
|
413
|
+
try:
|
|
414
|
+
return c(x, y), None
|
|
415
|
+
except Exception as exc:
|
|
416
|
+
return None, exc
|
|
417
|
+
|
|
418
|
+
def test_0_000(self: Self) -> None:
|
|
419
|
+
gens: list[Any]
|
|
420
|
+
t: type[Any]
|
|
421
|
+
x: Any
|
|
422
|
+
x_: Any
|
|
423
|
+
y: Any
|
|
424
|
+
y_: Any
|
|
425
|
+
gens = [
|
|
426
|
+
self.gen_000,
|
|
427
|
+
self.gen_001,
|
|
428
|
+
self.gen_002,
|
|
429
|
+
self.gen_003,
|
|
430
|
+
self.gen_004,
|
|
431
|
+
self.gen_005,
|
|
432
|
+
self.gen_006,
|
|
433
|
+
self.gen_007,
|
|
434
|
+
self.gen_008,
|
|
435
|
+
self.gen_009,
|
|
436
|
+
self.gen_010,
|
|
437
|
+
self.gen_011,
|
|
438
|
+
self.gen_012,
|
|
439
|
+
self.gen_013,
|
|
440
|
+
self.gen_014,
|
|
441
|
+
self.gen_015,
|
|
442
|
+
self.gen_016,
|
|
443
|
+
self.gen_017,
|
|
444
|
+
self.gen_018,
|
|
445
|
+
self.gen_019,
|
|
446
|
+
self.gen_020,
|
|
447
|
+
self.gen_021,
|
|
448
|
+
self.gen_022,
|
|
449
|
+
self.gen_900,
|
|
450
|
+
self.gen_901,
|
|
451
|
+
self.gen_902,
|
|
452
|
+
self.gen_903,
|
|
453
|
+
self.gen_904,
|
|
454
|
+
self.gen_905,
|
|
455
|
+
]
|
|
456
|
+
for gen in gens:
|
|
457
|
+
for x, y in gen():
|
|
458
|
+
for t in (tuple, list):
|
|
459
|
+
x_ = t(x)
|
|
460
|
+
y_ = t(y)
|
|
461
|
+
ans_old, exc_old = self.go(t.__le__, x_, y_)
|
|
462
|
+
ans_new, exc_new = self.go(itercmp.dunder.le, x_, y_)
|
|
463
|
+
self.assertEqual(ans_old, ans_new)
|
|
464
|
+
self.assertEqual(repr(exc_old), repr(exc_new))
|
|
465
|
+
self.assertEqual(str(exc_old), str(exc_new))
|
|
466
|
+
self.assertIs(type(exc_old), type(exc_new))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|