assertpy 2.35.0__py3-none-any.whl
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.
- assertpy/__init__.py +87 -0
- assertpy/_clustering.py +511 -0
- assertpy/_dangling.py +505 -0
- assertpy/_engine/__init__.py +1 -0
- assertpy/_engine/_builder_check_typing.py +1365 -0
- assertpy/_engine/_capable_typing.py +772 -0
- assertpy/_engine/_check_typing.py +753 -0
- assertpy/_engine/_compare.py +983 -0
- assertpy/_engine/_compat.py +38 -0
- assertpy/_engine/_contract.py +1926 -0
- assertpy/_engine/_diff.py +1058 -0
- assertpy/_engine/_equality.py +843 -0
- assertpy/_engine/_introspection.py +729 -0
- assertpy/_engine/_membership.py +522 -0
- assertpy/_engine/_mixin_base.py +258 -0
- assertpy/_engine/_negated_typing.py +2176 -0
- assertpy/_engine/_operations.py +75 -0
- assertpy/_engine/_ordering.py +884 -0
- assertpy/_engine/_pairing.py +70 -0
- assertpy/_engine/_path.py +158 -0
- assertpy/_engine/_poll_typing.py +6039 -0
- assertpy/_engine/_require.py +312 -0
- assertpy/_engine/_size.py +31 -0
- assertpy/_engine/_text.py +39 -0
- assertpy/_engine/_typing.py +1226 -0
- assertpy/_hints.py +1213 -0
- assertpy/_inline.py +484 -0
- assertpy/_matcher_impls.py +1876 -0
- assertpy/_passes.py +249 -0
- assertpy/_renamed.py +64 -0
- assertpy/_satisfies.py +835 -0
- assertpy/_snapshot_codec.py +290 -0
- assertpy/assertpy.py +2640 -0
- assertpy/async_assertions.py +864 -0
- assertpy/base.py +862 -0
- assertpy/behave_matchers.py +96 -0
- assertpy/bytes_mixin.py +158 -0
- assertpy/collection.py +528 -0
- assertpy/contains.py +1068 -0
- assertpy/dataframe.py +200 -0
- assertpy/date.py +327 -0
- assertpy/dict.py +249 -0
- assertpy/dynamic.py +222 -0
- assertpy/errors.py +782 -0
- assertpy/exception.py +838 -0
- assertpy/extracting.py +266 -0
- assertpy/file.py +324 -0
- assertpy/helpers.py +747 -0
- assertpy/http_mixin.py +218 -0
- assertpy/json_mixin.py +1265 -0
- assertpy/matchers.py +639 -0
- assertpy/numeric.py +696 -0
- assertpy/outcome.py +163 -0
- assertpy/py.typed +0 -0
- assertpy/pytest_plugin.py +1650 -0
- assertpy/snapshot.py +1031 -0
- assertpy/string.py +803 -0
- assertpy/warning.py +137 -0
- assertpy-2.35.0.dist-info/METADATA +324 -0
- assertpy-2.35.0.dist-info/RECORD +63 -0
- assertpy-2.35.0.dist-info/WHEEL +4 -0
- assertpy-2.35.0.dist-info/entry_points.txt +2 -0
- assertpy-2.35.0.dist-info/licenses/LICENSE +28 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING, Any
|
|
4
|
+
|
|
5
|
+
from ._introspection import Replay, handed_away
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from .._matcher_impls import ExceptionInfo, WarningInfo
|
|
9
|
+
from ..errors import AssertionFailure, DiffResult, PollTrace
|
|
10
|
+
from ..http_mixin import _Response
|
|
11
|
+
from ..outcome import AssertionOutcome, Requirement
|
|
12
|
+
from ._compare import _CompareConfig
|
|
13
|
+
from ._compat import Self
|
|
14
|
+
from ._introspection import WarningLogger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class _MixinBase:
|
|
18
|
+
_response: _Response | None = None
|
|
19
|
+
"""The HTTP response this value came from, when it came from one.
|
|
20
|
+
|
|
21
|
+
Carried by every pivot rather than looked up at the end, because the response is gone by the time a
|
|
22
|
+
failure is composed over its parsed body.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
_equality_comparison = False
|
|
26
|
+
"""Whether the failure being reported came from asking whether two values are equal.
|
|
27
|
+
|
|
28
|
+
Read by the failure composer. Only there does it follow from a type comparing by identity that
|
|
29
|
+
nothing on the other side could have passed: a containment failure over the same values is about
|
|
30
|
+
where they sit, and a comparator of the caller's own owns its leaves outright.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
_comparators_took_part = False
|
|
34
|
+
"""Whether the comparison being reported was given ``comparators=``.
|
|
35
|
+
|
|
36
|
+
Read by the failure composer for a pair inside the diff that prints the same on both sides: identity is
|
|
37
|
+
the reason for it only where no predicate of the caller's could have been what turned it down.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_answering_another = False
|
|
41
|
+
"""Whether the assertion running on this builder answers another assertion rather than the caller.
|
|
42
|
+
|
|
43
|
+
Set by `not_` around the assertion it inverts, and by a snapshot around its own comparison, so the
|
|
44
|
+
vacuity guard leaves both alone. On the builder rather than in a context variable: an assertion that
|
|
45
|
+
a comparator or predicate of the caller's runs is on a builder of its own, and is the caller's own.
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
_unmet_prerequisite: AssertionOutcome | None = None
|
|
49
|
+
"""A verdict run's first failure when it is on something the question presupposes.
|
|
50
|
+
|
|
51
|
+
Recorded by `_unmet()` and read by `not_`, which delivers it as it stands instead of inverting it.
|
|
52
|
+
Inverted, a caught exception that is not a group passed `not_.contains_error(ValueError)`: "not a
|
|
53
|
+
group" read as "holds no such error", where the question has no answer at all. Only the first
|
|
54
|
+
failure, since the strict run stops there: a prerequisite missed after an ordinary failure was
|
|
55
|
+
never reached. Cleared for each verdict run and put back after it, so one left behind outside a
|
|
56
|
+
run is never read.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
_answers_to: Any = None
|
|
60
|
+
"""The builder whose verdict run a pivot made during that run belongs to, or ``None`` for its own.
|
|
61
|
+
|
|
62
|
+
A pivot inherits check mode, and its failures landed in a sink of its own that nobody read: an
|
|
63
|
+
extension asserting on `extracting_group()` held under `check()` while its strict run failed, and
|
|
64
|
+
failed under `not_` for the wrong reason. Set by `builder()` and read through `_verdict_holder()`.
|
|
65
|
+
The pivot takes `_answering_another` along too, since what it asserts answers the same run.
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
_run_pivots: list[Any] | None = None
|
|
69
|
+
"""The pivots made during the verdict run this builder holds, released by `_release_pivots()` when it ends."""
|
|
70
|
+
|
|
71
|
+
_read: Replay | None = None
|
|
72
|
+
"""What a one-shot iterator held as the value has handed out, kept for the links of the chain that follow."""
|
|
73
|
+
|
|
74
|
+
def _walked(self) -> Any:
|
|
75
|
+
"""The value as a walk reads it: a one-shot iterator through what it has handed out so far, else itself.
|
|
76
|
+
|
|
77
|
+
Every assertion that walks the value reads it here, or the second link of a chain over a generator
|
|
78
|
+
passed or failed over nothing. Asked as `materialized` asks, ``iter(value) is value``.
|
|
79
|
+
"""
|
|
80
|
+
value = self.val
|
|
81
|
+
kind = type(value)
|
|
82
|
+
if kind is list or kind is tuple or kind is str or kind is dict or kind is set or kind is frozenset:
|
|
83
|
+
return value
|
|
84
|
+
read = self._read
|
|
85
|
+
if read is not None and read.source is value:
|
|
86
|
+
if read.given_away:
|
|
87
|
+
raise handed_away()
|
|
88
|
+
return read
|
|
89
|
+
try:
|
|
90
|
+
one_shot = iter(value) is value
|
|
91
|
+
except TypeError:
|
|
92
|
+
return value
|
|
93
|
+
if not one_shot:
|
|
94
|
+
return value
|
|
95
|
+
read = self._read = Replay(value)
|
|
96
|
+
return read
|
|
97
|
+
|
|
98
|
+
def _handed_out(self) -> Any:
|
|
99
|
+
"""The value itself, for code of the caller's, which may take from a one-shot iterator what no link sees."""
|
|
100
|
+
read = self._read
|
|
101
|
+
# what a link has read already is all that is looked at: asked for an iterator here, the value ran its
|
|
102
|
+
# `__iter__` ahead of a predicate that may never walk it
|
|
103
|
+
if read is not None and read.source is self.val:
|
|
104
|
+
read.give_away()
|
|
105
|
+
return self.val
|
|
106
|
+
|
|
107
|
+
def _drained(self) -> Any:
|
|
108
|
+
"""The value, or the items of a one-shot iterator in a list of their own, the same items for every link."""
|
|
109
|
+
value = self.val
|
|
110
|
+
kind = type(value)
|
|
111
|
+
# asked here as well: through `_walked` alone, `contains` on a list of 200 cost 11% more
|
|
112
|
+
if kind is list or kind is tuple or kind is str or kind is dict or kind is set or kind is frozenset:
|
|
113
|
+
return value
|
|
114
|
+
walked = self._walked()
|
|
115
|
+
return walked.drained() if type(walked) is Replay else walked
|
|
116
|
+
|
|
117
|
+
_compared: tuple[object, object] | None = None
|
|
118
|
+
"""The two values a failed equality held against each other, set just ahead of `error()`, which takes it.
|
|
119
|
+
|
|
120
|
+
The pair ``==`` alone decided: the value and the operand where nothing was left out, and the copies
|
|
121
|
+
without the keys left out under ``ignore=`` or ``include=``. Not set where something else decided, under
|
|
122
|
+
``tolerance=``, ``comparators=``, ``strict_types=`` or ``ignore_null=``. Kept on the failure for a listener
|
|
123
|
+
that shows two values side by side.
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
_compared_nothing = False
|
|
127
|
+
"""Whether a comparison under ``ignore``/``include`` passed with no key left to compare.
|
|
128
|
+
|
|
129
|
+
Set by the comparison on the pass it decided, never on a failure, and read and cleared by
|
|
130
|
+
`is_equal_to()` as soon as that comparison returns.
|
|
131
|
+
"""
|
|
132
|
+
|
|
133
|
+
if TYPE_CHECKING:
|
|
134
|
+
val: Any
|
|
135
|
+
description: str
|
|
136
|
+
kind: str | None
|
|
137
|
+
expected: type[BaseException] | ExceptionInfo | None
|
|
138
|
+
logger: WarningLogger
|
|
139
|
+
_not_expected: bool
|
|
140
|
+
_expected_warning: type[Warning] | WarningInfo | None
|
|
141
|
+
_return_value: object
|
|
142
|
+
_raised_exception: object
|
|
143
|
+
_value_taint_reason: str | None
|
|
144
|
+
|
|
145
|
+
def error(
|
|
146
|
+
self,
|
|
147
|
+
msg: str,
|
|
148
|
+
*,
|
|
149
|
+
actual: object = ...,
|
|
150
|
+
expected: object = ...,
|
|
151
|
+
diff: DiffResult | None = ...,
|
|
152
|
+
requirement: Requirement | None = ...,
|
|
153
|
+
suppress_context: bool = ...,
|
|
154
|
+
) -> Self: ...
|
|
155
|
+
|
|
156
|
+
def _compose(
|
|
157
|
+
self,
|
|
158
|
+
msg: str,
|
|
159
|
+
*,
|
|
160
|
+
actual: object,
|
|
161
|
+
expected: object,
|
|
162
|
+
diff: DiffResult | None,
|
|
163
|
+
trace: PollTrace | None,
|
|
164
|
+
requirement: Requirement | None = ...,
|
|
165
|
+
) -> AssertionOutcome: ...
|
|
166
|
+
|
|
167
|
+
def _unmet(
|
|
168
|
+
self,
|
|
169
|
+
msg: str,
|
|
170
|
+
*,
|
|
171
|
+
expected: object = ...,
|
|
172
|
+
requirement: Requirement | None = ...,
|
|
173
|
+
suppress_context: bool = ...,
|
|
174
|
+
) -> None: ...
|
|
175
|
+
|
|
176
|
+
@staticmethod
|
|
177
|
+
def _failure(outcome: AssertionOutcome) -> AssertionFailure: ...
|
|
178
|
+
|
|
179
|
+
def builder(
|
|
180
|
+
self,
|
|
181
|
+
val: object,
|
|
182
|
+
description: str = ...,
|
|
183
|
+
kind: str | None = ...,
|
|
184
|
+
expected: type[BaseException] | ExceptionInfo | None = ...,
|
|
185
|
+
logger: WarningLogger | None = ...,
|
|
186
|
+
origin: str | None = ...,
|
|
187
|
+
) -> Self: ...
|
|
188
|
+
|
|
189
|
+
def _when_called_with_warning(
|
|
190
|
+
self, expected: type[Warning] | WarningInfo, *some_args: object, **some_kwargs: object
|
|
191
|
+
) -> Self: ...
|
|
192
|
+
|
|
193
|
+
def _when_called_with_not_warning(
|
|
194
|
+
self, expected: type[Warning] | WarningInfo, *some_args: object, **some_kwargs: object
|
|
195
|
+
) -> Self: ...
|
|
196
|
+
|
|
197
|
+
def _fmt_items(self, items: object) -> str: ...
|
|
198
|
+
|
|
199
|
+
def _fmt_args_kwargs(self, *some_args: object, **some_kwargs: object) -> str: ...
|
|
200
|
+
|
|
201
|
+
def _validate_between_args(self, val_type: type, low: object, high: object) -> None: ...
|
|
202
|
+
|
|
203
|
+
def _validate_close_to_args(self, val: object, other: object, tolerance: object, rel: object = ...) -> None: ...
|
|
204
|
+
|
|
205
|
+
def _is_dict_like(
|
|
206
|
+
self,
|
|
207
|
+
candidate: object,
|
|
208
|
+
check_keys: bool = ...,
|
|
209
|
+
check_values: bool = ...,
|
|
210
|
+
check_getitem: bool = ...,
|
|
211
|
+
) -> bool: ...
|
|
212
|
+
|
|
213
|
+
def _require_dict_like(
|
|
214
|
+
self,
|
|
215
|
+
candidate: object,
|
|
216
|
+
check_keys: bool = ...,
|
|
217
|
+
check_values: bool = ...,
|
|
218
|
+
check_getitem: bool = ...,
|
|
219
|
+
name: str = ...,
|
|
220
|
+
) -> None: ...
|
|
221
|
+
|
|
222
|
+
def _check_iterable(self, val: object, check_getitem: bool = ..., name: str = ...) -> None: ...
|
|
223
|
+
|
|
224
|
+
def _dict_not_equal(
|
|
225
|
+
self,
|
|
226
|
+
val: object,
|
|
227
|
+
other: object,
|
|
228
|
+
ignore: object = ...,
|
|
229
|
+
include: object = ...,
|
|
230
|
+
config: _CompareConfig | None = ...,
|
|
231
|
+
) -> bool | None: ...
|
|
232
|
+
|
|
233
|
+
def _dict_err(
|
|
234
|
+
self,
|
|
235
|
+
val: object,
|
|
236
|
+
other: object,
|
|
237
|
+
ignore: object = ...,
|
|
238
|
+
include: object = ...,
|
|
239
|
+
config: _CompareConfig | None = ...,
|
|
240
|
+
held: tuple[object, object] | None = ...,
|
|
241
|
+
) -> None: ...
|
|
242
|
+
|
|
243
|
+
@staticmethod
|
|
244
|
+
def _to_comparable_dict(obj: object) -> dict[str, object] | None: ...
|
|
245
|
+
|
|
246
|
+
_NUMERIC_COMPAREABLE: frozenset[type]
|
|
247
|
+
_NUMERIC_NON_COMPAREABLE: frozenset[type]
|
|
248
|
+
|
|
249
|
+
def contains(self, *items: object) -> Self: ...
|
|
250
|
+
|
|
251
|
+
def does_not_contain(self, *items: object) -> Self: ...
|
|
252
|
+
|
|
253
|
+
# `Any`, not `object`: the real one is annotated per value type, and a wider one here overrides incompatibly
|
|
254
|
+
def starts_with(self, prefix: Any) -> Self: ...
|
|
255
|
+
|
|
256
|
+
def is_equal_to(self, other: object, **kwargs: object) -> Self: ...
|
|
257
|
+
|
|
258
|
+
def is_not_equal_to(self, other: object) -> Self: ...
|