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,1226 @@
|
|
|
1
|
+
"""The typed surface itself: one protocol per kind of value, and the only one of the six written by hand.
|
|
2
|
+
|
|
3
|
+
`assert_that()` picks between them with an overload ladder in `assertpy/assertpy.py`, and a checker sees
|
|
4
|
+
the protocol rather than the builder. That is what makes `assert_that({}).is_positive()` an error before
|
|
5
|
+
it is a `TypeError`.
|
|
6
|
+
|
|
7
|
+
Four of the other five typed modules are generated from this one, so a declaration added here reaches
|
|
8
|
+
the polling chain, both verdict proxies and the negation twins only after the generators run. The
|
|
9
|
+
fifth, the capability facade, reads the runtime mixins instead: it stands in for the builder rather
|
|
10
|
+
than for a view.
|
|
11
|
+
|
|
12
|
+
Declare a method on the protocols it applies to and on no others. One on `_CoreAssertion` is offered to
|
|
13
|
+
every value, which is the distinction this layer exists to make.
|
|
14
|
+
|
|
15
|
+
Everything is under `TYPE_CHECKING`, so nothing here costs an import and nothing here enforces itself.
|
|
16
|
+
`tests/test_protocol_parity.py` and `tests/test_typing_conformance.py` hold a declaration to the runtime.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
from typing import TYPE_CHECKING
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
import datetime
|
|
25
|
+
import re
|
|
26
|
+
from collections.abc import Awaitable, Callable, Hashable, Iterable, Mapping, Sized
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Any, ClassVar, Protocol, SupportsFloat, SupportsIndex, TypeVar, overload
|
|
29
|
+
|
|
30
|
+
from typing_extensions import TypeIs
|
|
31
|
+
|
|
32
|
+
from .._engine._introspection import MappingLike
|
|
33
|
+
from .._matcher_impls import ClassInfo, ExceptionInfo, RetriedInfo, WarningInfo
|
|
34
|
+
from ..assertpy import AssertionBuilder
|
|
35
|
+
from ..matchers import Matcher
|
|
36
|
+
from ._check_typing import (
|
|
37
|
+
_CheckArrayAssertion,
|
|
38
|
+
_CheckBoolAssertion,
|
|
39
|
+
_CheckBytesAssertion,
|
|
40
|
+
_CheckCallableAssertion,
|
|
41
|
+
_CheckCompletedAssertion,
|
|
42
|
+
_CheckComplexAssertion,
|
|
43
|
+
_CheckCoreAssertion,
|
|
44
|
+
_CheckDateAssertion,
|
|
45
|
+
_CheckDateTimeAssertion,
|
|
46
|
+
_CheckDictAssertion,
|
|
47
|
+
_CheckExpectedCompletionAssertion,
|
|
48
|
+
_CheckExpectedRaiseAssertion,
|
|
49
|
+
_CheckExpectedWarningAssertion,
|
|
50
|
+
_CheckFrameAssertion,
|
|
51
|
+
_CheckInvokedAssertion,
|
|
52
|
+
_CheckIterableAssertion,
|
|
53
|
+
_CheckListAssertion,
|
|
54
|
+
_CheckNumericAssertion,
|
|
55
|
+
_CheckObjectAssertion,
|
|
56
|
+
_CheckPathAssertion,
|
|
57
|
+
_CheckStringAssertion,
|
|
58
|
+
_CheckWarnedAssertion,
|
|
59
|
+
)
|
|
60
|
+
from ._compat import Self
|
|
61
|
+
from ._negated_typing import (
|
|
62
|
+
_NegatedArrayAssertion,
|
|
63
|
+
_NegatedBoolAssertion,
|
|
64
|
+
_NegatedBytesAssertion,
|
|
65
|
+
_NegatedCallableAssertion,
|
|
66
|
+
_NegatedCompletedAssertion,
|
|
67
|
+
_NegatedComplexAssertion,
|
|
68
|
+
_NegatedCoreAssertion,
|
|
69
|
+
_NegatedDateAssertion,
|
|
70
|
+
_NegatedDateTimeAssertion,
|
|
71
|
+
_NegatedDictAssertion,
|
|
72
|
+
_NegatedExpectedCompletionAssertion,
|
|
73
|
+
_NegatedExpectedRaiseAssertion,
|
|
74
|
+
_NegatedExpectedWarningAssertion,
|
|
75
|
+
_NegatedFrameAssertion,
|
|
76
|
+
_NegatedInvokedAssertion,
|
|
77
|
+
_NegatedIterableAssertion,
|
|
78
|
+
_NegatedListAssertion,
|
|
79
|
+
_NegatedNumericAssertion,
|
|
80
|
+
_NegatedObjectAssertion,
|
|
81
|
+
_NegatedPathAssertion,
|
|
82
|
+
_NegatedStringAssertion,
|
|
83
|
+
_NegatedTextAssertion,
|
|
84
|
+
_NegatedWarnedAssertion,
|
|
85
|
+
)
|
|
86
|
+
from ._poll_typing import _AsyncPoll, _SyncPoll
|
|
87
|
+
|
|
88
|
+
# ``ignore``/``include`` accept a single key, a nested-path tuple, or a list/set/frozenset of them.
|
|
89
|
+
_KeySpecs = Hashable | list[Hashable] | set[Hashable] | frozenset[Hashable]
|
|
90
|
+
|
|
91
|
+
_E = TypeVar("_E") # tracked element type of a collection assertion
|
|
92
|
+
_R = TypeVar("_R") # result element type after a mapping pivot
|
|
93
|
+
_N = TypeVar("_N", int, float) # tracked numeric type, so value keeps int or float
|
|
94
|
+
_K = TypeVar("_K") # tracked dict key type
|
|
95
|
+
_V = TypeVar("_V") # tracked dict value type
|
|
96
|
+
_B_co = TypeVar("_B_co", bytes, bytearray, covariant=True) # tracked bytes type (output-only -> covariant)
|
|
97
|
+
_U = TypeVar("_U")
|
|
98
|
+
_U2 = TypeVar("_U2")
|
|
99
|
+
_U3 = TypeVar("_U3") # the type a TypeIs predicate refines the tracked value to
|
|
100
|
+
_Other = TypeVar("_Other") # an element of the sequence a pairwise quantifier walks alongside
|
|
101
|
+
_T_co = TypeVar("_T_co", covariant=True) # the subject of a value no overload recognises
|
|
102
|
+
_P_co = TypeVar("_P_co", covariant=True) # what a polled probe hands back, covariant so a subclass reaches its rung
|
|
103
|
+
_Exc = TypeVar("_Exc", bound=BaseException) # the exception a caught call holds, invariant as the builder is
|
|
104
|
+
_Landed = TypeVar("_Landed", bound=BaseException) # the exception `raises()` names, or a pivot lands on
|
|
105
|
+
|
|
106
|
+
# a capability, not a list: the list said `float | Decimal | Fraction` and refused `numpy.int64`
|
|
107
|
+
_Number = SupportsFloat
|
|
108
|
+
|
|
109
|
+
# a predicate's verdict is `object`, not `bool`, which refused a `numpy.bool_`
|
|
110
|
+
|
|
111
|
+
class _MembershipAssertion(Protocol):
|
|
112
|
+
""" "Is every one of my elements in there", asked the same way by three types.
|
|
113
|
+
|
|
114
|
+
`*supersets` is `object`, and that is measured rather than lazy. The runtime compares by `==`,
|
|
115
|
+
so a superset of a wider element type works: `list[Dog]` against `list[Animal]`, `[1]` against
|
|
116
|
+
`1.0`, a `list[object]` holding the right values. Both narrowings tried, `Iterable[_E]` and
|
|
117
|
+
`Iterable[_E] | _E`, refused those, and the first also refused the documented
|
|
118
|
+
`is_subset_of(1, 2, 3)` that our own suite calls.
|
|
119
|
+
|
|
120
|
+
The mapping view declares its own, because there the runtime refuses a shape by name rather
|
|
121
|
+
than by comparison. `contains` stays out for the older reason: a string means `str | Matcher`
|
|
122
|
+
by it, and lifting the untyped form once widened the string by accident.
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
def is_subset_of(self, *supersets: object, allow_empty: bool = ...) -> Self: ...
|
|
126
|
+
|
|
127
|
+
class _SizedAssertion(Protocol):
|
|
128
|
+
"""What every value with a length can be asked, declared once instead of in four protocols.
|
|
129
|
+
|
|
130
|
+
Not on `_CoreAssertion`, because a number has no length and offering `is_empty()` on one would be
|
|
131
|
+
the false promise this whole file exists to avoid. Not generated either: a protocol that other
|
|
132
|
+
protocols inherit is the language's own way of saying "these share a capability", and a checker
|
|
133
|
+
understands it without anything being generated, recorded or kept in step.
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
def has_same_size_as(self, other: Sized) -> Self: ...
|
|
137
|
+
def has_size_greater_than(self, size: SupportsIndex) -> Self: ...
|
|
138
|
+
def has_size_less_than(self, size: SupportsIndex) -> Self: ...
|
|
139
|
+
def has_size_between(self, low: SupportsIndex, high: SupportsIndex) -> Self: ...
|
|
140
|
+
def is_empty(self) -> Self: ...
|
|
141
|
+
def is_not_empty(self) -> Self: ...
|
|
142
|
+
|
|
143
|
+
class _FilesystemAssertion(Protocol):
|
|
144
|
+
"""What a value naming a place on disk can be asked.
|
|
145
|
+
|
|
146
|
+
Carried by both the string and the path protocols, because a path is written as a `str` at least
|
|
147
|
+
as often as it is written as a `Path`, and refusing one of the two spellings would be a rule
|
|
148
|
+
that exists only in the type checker.
|
|
149
|
+
"""
|
|
150
|
+
|
|
151
|
+
def exists(self) -> Self: ...
|
|
152
|
+
def does_not_exist(self) -> Self: ...
|
|
153
|
+
def is_file(self) -> Self: ...
|
|
154
|
+
def is_directory(self) -> Self: ...
|
|
155
|
+
def is_named(self, filename: str) -> Self: ...
|
|
156
|
+
def is_child_of(self, parent: object) -> Self: ...
|
|
157
|
+
def is_readable(self) -> Self: ...
|
|
158
|
+
def is_writable(self) -> Self: ...
|
|
159
|
+
def is_executable(self) -> Self: ...
|
|
160
|
+
|
|
161
|
+
class _RealNumberAssertion(Protocol):
|
|
162
|
+
"""What a real number can be asked, whether it is spelled `int`, `float` or `bool`.
|
|
163
|
+
|
|
164
|
+
`bool` is here because it is an `int` in Python, and an assertion that works on one works on the
|
|
165
|
+
other; leaving it out would be a distinction the runtime does not make. Closeness is the
|
|
166
|
+
exception, declared on the numeric view alone: a distance measured from a flag is a mistake the
|
|
167
|
+
runtime refuses, as `tolerance=` does.
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
def is_positive(self) -> Self: ...
|
|
171
|
+
def is_negative(self) -> Self: ...
|
|
172
|
+
def is_nan(self) -> Self: ...
|
|
173
|
+
def is_not_nan(self) -> Self: ...
|
|
174
|
+
def is_inf(self) -> Self: ...
|
|
175
|
+
def is_not_inf(self) -> Self: ...
|
|
176
|
+
def is_not_between(self, low: _Number, high: _Number) -> Self: ...
|
|
177
|
+
def is_between(self, low: _Number, high: _Number) -> Self: ...
|
|
178
|
+
def is_greater_than(self, other: _Number) -> Self: ...
|
|
179
|
+
def is_greater_than_or_equal_to(self, other: _Number) -> Self: ...
|
|
180
|
+
def is_less_than(self, other: _Number) -> Self: ...
|
|
181
|
+
def is_less_than_or_equal_to(self, other: _Number) -> Self: ...
|
|
182
|
+
|
|
183
|
+
class _WalkAssertion(Protocol):
|
|
184
|
+
"""The quantifiers and the extraction pivot, which anything walkable answers.
|
|
185
|
+
|
|
186
|
+
Apart from the JSON family below because the two domains are not the same: a frame walks
|
|
187
|
+
and is not a document, and offering it `at_json_path` promises a refusal. `_StructureAssertion`
|
|
188
|
+
keeps both together for the mapping and sequence views, which are inside both.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
def extracting(
|
|
192
|
+
self,
|
|
193
|
+
# a selector stays `object`: every narrowing tried refused working code, `Hashable | slice` included
|
|
194
|
+
name: object,
|
|
195
|
+
/,
|
|
196
|
+
*names: object,
|
|
197
|
+
# named rather than `**kwargs`, so `filtr=` is caught; `Mapping` because `dict` is invariant
|
|
198
|
+
filter: str | Mapping[str, object] | Callable[[Any], object] = ..., # noqa: A002 # public keyword
|
|
199
|
+
# `sort` is narrower by the runtime: one index is refused, the same index inside a list is honoured
|
|
200
|
+
sort: str | Iterable[object] | Callable[[Any], object] = ...,
|
|
201
|
+
) -> _ListAssertion[Any]: ...
|
|
202
|
+
def each(self, matcher: Matcher[Any] | Callable[[Any], object], *, allow_empty: bool = ...) -> Self: ...
|
|
203
|
+
def all_satisfy(self, matcher: Matcher[Any] | Callable[[Any], object], *, allow_empty: bool = ...) -> Self: ...
|
|
204
|
+
|
|
205
|
+
class _JsonAssertion(Protocol):
|
|
206
|
+
"""The document family, for a value the JSON assertions accept: a `dict` or a `list`."""
|
|
207
|
+
|
|
208
|
+
def at_json_path(self, path: str) -> _CoreAssertion:
|
|
209
|
+
"""Navigate into the document and continue on whatever is there.
|
|
210
|
+
|
|
211
|
+
A path lands on an object, an array, a string, a number, a boolean or a null, and which one
|
|
212
|
+
it is lives in the document rather than in any type. So what comes back offers the
|
|
213
|
+
assertions every value can answer, and nothing beyond them: naming a shape here is what
|
|
214
|
+
offered `contains_key` on an `int` and made a type check pass on a call that raises.
|
|
215
|
+
|
|
216
|
+
Reaching further is a narrowing the caller states: a matcher, or a `TypeIs` predicate that
|
|
217
|
+
carries the type into the rest of the chain. What runs is the predicate, and what is read
|
|
218
|
+
is its boolean answer, so the declared narrowing is taken on trust from whoever wrote it.
|
|
219
|
+
"""
|
|
220
|
+
...
|
|
221
|
+
|
|
222
|
+
def has_json_path(self, path: str) -> Self: ...
|
|
223
|
+
def does_not_have_json_path(self, path: str) -> Self: ...
|
|
224
|
+
def matches_json_schema(self, schema: dict[str, Any]) -> Self: ...
|
|
225
|
+
def matches_json_schema_from_file(self, path: str | Path) -> Self: ...
|
|
226
|
+
def conforms_to_openapi(
|
|
227
|
+
self,
|
|
228
|
+
spec: dict[str, Any],
|
|
229
|
+
path: str,
|
|
230
|
+
method: str,
|
|
231
|
+
*,
|
|
232
|
+
status: str | int | None = ...,
|
|
233
|
+
content_type: str = ...,
|
|
234
|
+
strict_nullable: bool = ...,
|
|
235
|
+
) -> Self: ...
|
|
236
|
+
|
|
237
|
+
class _StructureAssertion(_WalkAssertion, _JsonAssertion, Protocol):
|
|
238
|
+
"""Quantifiers, the JSON family and the two pivots, which a mapping and a sequence share.
|
|
239
|
+
|
|
240
|
+
That sharing is what a JSON document is made of, and the reason these never belonged to
|
|
241
|
+
either one alone. Kept as one name so the views that are inside both domains compose it
|
|
242
|
+
rather than listing halves.
|
|
243
|
+
"""
|
|
244
|
+
|
|
245
|
+
class _RepeatableAssertion(Protocol[_E]):
|
|
246
|
+
"""What a value with repeatable elements can be asked about its repeats and their order.
|
|
247
|
+
|
|
248
|
+
Generic over the element, and that is not decoration: `contains_in_order` names the element type,
|
|
249
|
+
so a protocol without the parameter leaves `_E` free and lets a list of integers be asked about
|
|
250
|
+
strings. Each carrier binds it to what its own elements are.
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
def contains_duplicates(self) -> Self: ...
|
|
254
|
+
def does_not_contain_duplicates(self) -> Self: ...
|
|
255
|
+
def contains_only_once(self, *items: object) -> Self: ...
|
|
256
|
+
def contains_in_order(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
257
|
+
|
|
258
|
+
class _ZeroAssertion(Protocol):
|
|
259
|
+
"""Zero and its negation, which every numeric spelling shares, complex included."""
|
|
260
|
+
|
|
261
|
+
def is_zero(self) -> Self: ...
|
|
262
|
+
def is_not_zero(self) -> Self: ...
|
|
263
|
+
|
|
264
|
+
class _CoreAssertion(Protocol):
|
|
265
|
+
"""Base protocol with assertions available for all types."""
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def not_(self) -> _NegatedCoreAssertion: ...
|
|
269
|
+
|
|
270
|
+
def described_as(self, description: str) -> Self: ...
|
|
271
|
+
def is_equal_to(
|
|
272
|
+
self,
|
|
273
|
+
other: object,
|
|
274
|
+
*,
|
|
275
|
+
ignore: _KeySpecs | None = ...,
|
|
276
|
+
include: _KeySpecs | None = ...,
|
|
277
|
+
tolerance: float | None = ...,
|
|
278
|
+
rel: float | None = ...,
|
|
279
|
+
comparators: dict[Any, Callable[[Any, Any], Any]] | None = ...,
|
|
280
|
+
ignore_null: bool = ...,
|
|
281
|
+
strict_types: bool = ...,
|
|
282
|
+
) -> Self: ...
|
|
283
|
+
def is_not_equal_to(self, other: object) -> Self: ...
|
|
284
|
+
def is_same_as(self, other: object) -> Self: ...
|
|
285
|
+
def is_not_same_as(self, other: object) -> Self: ...
|
|
286
|
+
def is_true(self) -> Self: ...
|
|
287
|
+
def is_false(self) -> Self: ...
|
|
288
|
+
def is_none(self) -> Self: ...
|
|
289
|
+
def is_not_none(self) -> Self: ...
|
|
290
|
+
def is_type_of(self, some_type: type) -> Self: ...
|
|
291
|
+
def is_instance_of(self, some_class: ClassInfo) -> Self: ...
|
|
292
|
+
def is_instance_of_any(self, *some_classes: ClassInfo) -> Self: ...
|
|
293
|
+
def is_subclass_of(self, some_class: ClassInfo) -> Self: ...
|
|
294
|
+
def is_length(self, length: SupportsIndex | Matcher[int]) -> Self: ...
|
|
295
|
+
def is_length_between(self, low: SupportsIndex, high: SupportsIndex) -> Self: ...
|
|
296
|
+
def is_callable(self) -> Self: ...
|
|
297
|
+
def is_not_callable(self) -> Self: ...
|
|
298
|
+
def is_iterable(self) -> Self: ...
|
|
299
|
+
def is_not_iterable(self) -> Self: ...
|
|
300
|
+
# a protocol narrowing `satisfies` restates the ladder; the predicate stays `Any` in this widest one
|
|
301
|
+
@overload
|
|
302
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[str]]) -> _StringAssertion: ...
|
|
303
|
+
@overload
|
|
304
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[bool]]) -> _BoolAssertion: ...
|
|
305
|
+
@overload
|
|
306
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[int]]) -> _NumericAssertion[int]: ...
|
|
307
|
+
@overload
|
|
308
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[float]]) -> _NumericAssertion[float]: ...
|
|
309
|
+
@overload
|
|
310
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[complex]]) -> _ComplexAssertion: ...
|
|
311
|
+
@overload
|
|
312
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[dict[_K, _V]]]) -> _DictAssertion[_K, _V]: ...
|
|
313
|
+
@overload
|
|
314
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[list[_E] | tuple[_E, ...]]]) -> _IterableAssertion[_E]: ...
|
|
315
|
+
@overload
|
|
316
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[set[_E] | frozenset[_E]]]) -> _IterableAssertion[_E]: ...
|
|
317
|
+
@overload
|
|
318
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[datetime.datetime]]) -> _DateTimeAssertion: ...
|
|
319
|
+
@overload
|
|
320
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[datetime.date]]) -> _DateAssertion: ...
|
|
321
|
+
@overload
|
|
322
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[Path]]) -> _PathAssertion: ...
|
|
323
|
+
@overload
|
|
324
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[bytes]]) -> _BytesAssertion[bytes]: ...
|
|
325
|
+
@overload
|
|
326
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[bytearray]]) -> _BytesAssertion[bytearray]: ...
|
|
327
|
+
@overload
|
|
328
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[Callable[..., object]]]) -> _CallableAssertion[Any]: ...
|
|
329
|
+
@overload
|
|
330
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[_CapableT]]) -> AssertionBuilder[_CapableT]: ...
|
|
331
|
+
@overload
|
|
332
|
+
def satisfies(self, matcher: Callable[[Any], TypeIs[_U]]) -> _ObjectAssertion[_U]: ...
|
|
333
|
+
@overload
|
|
334
|
+
def satisfies(self, matcher: Matcher[Any] | Callable[[Any], object]) -> Self: ...
|
|
335
|
+
def all_fields_satisfy(
|
|
336
|
+
self, matcher: Matcher[Any] | Callable[[Any], object], *, allow_empty: bool = ...
|
|
337
|
+
) -> Self: ...
|
|
338
|
+
def has_no_none_fields(self, *, allow_empty: bool = ...) -> Self: ...
|
|
339
|
+
def is_in(self, *items: object) -> Self: ...
|
|
340
|
+
def is_not_in(self, *items: object) -> Self: ...
|
|
341
|
+
def snapshot(
|
|
342
|
+
self,
|
|
343
|
+
id: str | None = ..., # noqa: A002 # mirrors public snapshot() parameter
|
|
344
|
+
path: str = ...,
|
|
345
|
+
*,
|
|
346
|
+
ignore: _KeySpecs | None = ...,
|
|
347
|
+
include: _KeySpecs | None = ...,
|
|
348
|
+
tolerance: float | None = ...,
|
|
349
|
+
rel: float | None = ...,
|
|
350
|
+
comparators: dict[Any, Callable[[Any, Any], Any]] | None = ...,
|
|
351
|
+
placeholders: Mapping[Any, Matcher[Any] | Callable[[Any], object]] | None = ...,
|
|
352
|
+
) -> Self: ...
|
|
353
|
+
def matches_contract_snapshot(self, id: str | None = ..., path: str = ...) -> Self: ... # noqa: A002 # mirrors public parameter
|
|
354
|
+
def matches_inline(
|
|
355
|
+
self,
|
|
356
|
+
expected: object = ...,
|
|
357
|
+
*,
|
|
358
|
+
ignore: _KeySpecs | None = ...,
|
|
359
|
+
include: _KeySpecs | None = ...,
|
|
360
|
+
tolerance: float | None = ...,
|
|
361
|
+
rel: float | None = ...,
|
|
362
|
+
comparators: dict[Any, Callable[[Any, Any], Any]] | None = ...,
|
|
363
|
+
placeholders: Mapping[Any, Matcher[Any] | Callable[[Any], object]] | None = ...,
|
|
364
|
+
) -> Self: ...
|
|
365
|
+
# a builder twin was tried and dropped: text and numeric ordering collide in one class. A pivot
|
|
366
|
+
# hands back `AssertionBuilder[_E]`, as does what the capability umbrella claims, so both stay untyped
|
|
367
|
+
def check(self) -> _CheckCoreAssertion: ...
|
|
368
|
+
@property
|
|
369
|
+
def value(self) -> object: ...
|
|
370
|
+
|
|
371
|
+
class _Holding(Protocol[_T_co]):
|
|
372
|
+
"""A view as the value it holds and nothing more, which is what the rungs of `is_not_none` are keyed on.
|
|
373
|
+
|
|
374
|
+
Keyed on `_ObjectAssertion` itself, ty answered `Unknown` for nine of the sixteen kinds a rung names: a
|
|
375
|
+
`bool`, an `int`, a `float`, the four sequences and sets, a `datetime` and a callable. Keyed on this it
|
|
376
|
+
resolves each, and the other three checkers answer as they did. A rung reads `value` alone, so a
|
|
377
|
+
protocol of one's own that inherits the view and narrows `value` lands where that value does.
|
|
378
|
+
"""
|
|
379
|
+
|
|
380
|
+
@property
|
|
381
|
+
def value(self) -> _T_co: ...
|
|
382
|
+
|
|
383
|
+
class _ObjectAssertion(_CoreAssertion, Protocol[_T_co]):
|
|
384
|
+
"""What a value no overload recognises can be asked, which is the core surface and ordering.
|
|
385
|
+
|
|
386
|
+
The fallback used to hand back the builder itself, carrying all 152 assertion names, so
|
|
387
|
+
`assert_that(Person()).is_positive()` type-checked and then raised. This is the other end: a
|
|
388
|
+
value with no capability any overload can see gets what applies to every value.
|
|
389
|
+
|
|
390
|
+
Ordering is here and not in `_CoreAssertion`, and the difference matters. Every other view
|
|
391
|
+
spells its own operand (`str` against `str`, a date against a date), which is what makes the
|
|
392
|
+
comparison worth checking, and a frame is refused outright. Only an unrecognised value has no
|
|
393
|
+
operand to name, so it takes `object` and judges anything. That is a recorded boundary rather
|
|
394
|
+
than an oversight: `tests/typing_negative_baseline.py` holds why every narrower spelling trades
|
|
395
|
+
a correct call for an incorrect one, and a `Decimal` compared against an `int` is the case it
|
|
396
|
+
would break.
|
|
397
|
+
|
|
398
|
+
The three refinements are declared here rather than inherited because they have to return this
|
|
399
|
+
view: they are the reason `.value` can be read without a `cast()`, and a refinement that came
|
|
400
|
+
back as the builder would put all 152 names back at the first `is_not_none()`.
|
|
401
|
+
"""
|
|
402
|
+
|
|
403
|
+
@property
|
|
404
|
+
def not_(self) -> _NegatedObjectAssertion[_T_co]: ...
|
|
405
|
+
|
|
406
|
+
@property
|
|
407
|
+
def value(self) -> _T_co: ...
|
|
408
|
+
def matches_structure(self, spec: dict[Any, Any]) -> Self: ...
|
|
409
|
+
def is_greater_than(self, other: Any) -> Self: ...
|
|
410
|
+
def is_greater_than_or_equal_to(self, other: Any) -> Self: ...
|
|
411
|
+
def is_less_than(self, other: Any) -> Self: ...
|
|
412
|
+
def is_less_than_or_equal_to(self, other: Any) -> Self: ...
|
|
413
|
+
def is_between(self, low: Any, high: Any) -> Self: ...
|
|
414
|
+
def is_not_between(self, low: Any, high: Any) -> Self: ...
|
|
415
|
+
|
|
416
|
+
def check(self) -> _CheckObjectAssertion[_T_co]: ...
|
|
417
|
+
|
|
418
|
+
# attrs reaches mypy only, so the object view carries `matches_structure` rather than a shape
|
|
419
|
+
|
|
420
|
+
# the four numeric assertions an unrecognised value can answer whatever it registered as, which
|
|
421
|
+
# is how `Decimal` and `Fraction` arrive here: neither is an `int` or a `float`, so no overload
|
|
422
|
+
# names them. Keyed on the conversion `math.isnan` reads, which does not imply the registration
|
|
423
|
+
# the runtime gate reads and cannot: a value that converts and never registered type-checks here
|
|
424
|
+
# and raises, the same boundary the relational six above already stand on.
|
|
425
|
+
#
|
|
426
|
+
# The other four, `is_nan` and friends, are NOT here and the split is measured: they sit behind
|
|
427
|
+
# `numbers.Real` rather than `numbers.Number`, so `Fraction` answers them and `Decimal` raises.
|
|
428
|
+
# No structural key separates the two, so declaring them would trade a false refusal on one
|
|
429
|
+
# stdlib type for a false acceptance on the other, and the false acceptance is what the fallback
|
|
430
|
+
# exists to remove. The operands drop the datetime half the numeric view carries: a `datetime`
|
|
431
|
+
# has an overload above this one, so a subject here is never one and the pairing cannot arise. The
|
|
432
|
+
# operands take the same union as the receiver: an `__index__`-only registered number is a bound
|
|
433
|
+
# the runtime accepts, measured
|
|
434
|
+
def is_zero(self: _ObjectAssertion[SupportsFloat | SupportsIndex]) -> _ObjectAssertion[_T_co]: ...
|
|
435
|
+
def is_not_zero(self: _ObjectAssertion[SupportsFloat | SupportsIndex]) -> _ObjectAssertion[_T_co]: ...
|
|
436
|
+
def is_close_to(
|
|
437
|
+
self: _ObjectAssertion[SupportsFloat | SupportsIndex],
|
|
438
|
+
other: SupportsFloat | SupportsIndex,
|
|
439
|
+
tolerance: SupportsFloat | SupportsIndex | None = ...,
|
|
440
|
+
*,
|
|
441
|
+
rel: SupportsFloat | SupportsIndex | None = ...,
|
|
442
|
+
) -> _ObjectAssertion[_T_co]: ...
|
|
443
|
+
def is_not_close_to(
|
|
444
|
+
self: _ObjectAssertion[SupportsFloat | SupportsIndex],
|
|
445
|
+
other: SupportsFloat | SupportsIndex,
|
|
446
|
+
tolerance: SupportsFloat | SupportsIndex | None = ...,
|
|
447
|
+
*,
|
|
448
|
+
rel: SupportsFloat | SupportsIndex | None = ...,
|
|
449
|
+
) -> _ObjectAssertion[_T_co]: ...
|
|
450
|
+
|
|
451
|
+
# no rung for a shape: both spellings tried put one checker in the wrong
|
|
452
|
+
@overload
|
|
453
|
+
def is_not_none(self: _Holding[str | None]) -> _StringAssertion: ...
|
|
454
|
+
@overload
|
|
455
|
+
def is_not_none(self: _Holding[bool | None]) -> _BoolAssertion: ...
|
|
456
|
+
@overload
|
|
457
|
+
def is_not_none(self: _Holding[int | None]) -> _NumericAssertion[int]: ...
|
|
458
|
+
@overload
|
|
459
|
+
def is_not_none(self: _Holding[float | None]) -> _NumericAssertion[float]: ...
|
|
460
|
+
@overload
|
|
461
|
+
def is_not_none(self: _Holding[complex | None]) -> _ComplexAssertion: ...
|
|
462
|
+
@overload
|
|
463
|
+
def is_not_none(self: _Holding[dict[_K, _V] | None]) -> _DictAssertion[_K, _V]: ...
|
|
464
|
+
@overload
|
|
465
|
+
def is_not_none(self: _Holding[list[_E] | tuple[_E, ...] | None]) -> _IterableAssertion[_E]: ...
|
|
466
|
+
@overload
|
|
467
|
+
def is_not_none(self: _Holding[set[_E] | frozenset[_E] | None]) -> _IterableAssertion[_E]: ...
|
|
468
|
+
@overload
|
|
469
|
+
def is_not_none(self: _Holding[datetime.datetime | None]) -> _DateTimeAssertion: ...
|
|
470
|
+
@overload
|
|
471
|
+
def is_not_none(self: _Holding[datetime.date | None]) -> _DateAssertion: ...
|
|
472
|
+
@overload
|
|
473
|
+
def is_not_none(self: _Holding[Path | None]) -> _PathAssertion: ...
|
|
474
|
+
@overload
|
|
475
|
+
def is_not_none(self: _Holding[bytes | None]) -> _BytesAssertion[bytes]: ...
|
|
476
|
+
@overload
|
|
477
|
+
def is_not_none(self: _Holding[bytearray | None]) -> _BytesAssertion[bytearray]: ...
|
|
478
|
+
@overload
|
|
479
|
+
def is_not_none(self: _Holding[Callable[..., object] | None]) -> _CallableAssertion[Any]: ...
|
|
480
|
+
@overload
|
|
481
|
+
def is_not_none(self: _Holding[_U | None]) -> _ObjectAssertion[_U]: ...
|
|
482
|
+
@overload
|
|
483
|
+
def is_not_none(self) -> Self: ...
|
|
484
|
+
@overload
|
|
485
|
+
def is_instance_of(self, some_class: type[str]) -> _StringAssertion: ...
|
|
486
|
+
@overload
|
|
487
|
+
def is_instance_of(self, some_class: type[bool]) -> _BoolAssertion: ...
|
|
488
|
+
@overload
|
|
489
|
+
def is_instance_of(self, some_class: type[int]) -> _NumericAssertion[int]: ...
|
|
490
|
+
@overload
|
|
491
|
+
def is_instance_of(self, some_class: type[float]) -> _NumericAssertion[float]: ...
|
|
492
|
+
@overload
|
|
493
|
+
def is_instance_of(self, some_class: type[complex]) -> _ComplexAssertion: ...
|
|
494
|
+
@overload
|
|
495
|
+
def is_instance_of(self, some_class: type[dict[_K, _V]]) -> _DictAssertion[_K, _V]: ...
|
|
496
|
+
@overload
|
|
497
|
+
def is_instance_of(self, some_class: type[list[_E] | tuple[_E, ...]]) -> _IterableAssertion[_E]: ...
|
|
498
|
+
@overload
|
|
499
|
+
def is_instance_of(self, some_class: type[set[_E] | frozenset[_E]]) -> _IterableAssertion[_E]: ...
|
|
500
|
+
@overload
|
|
501
|
+
def is_instance_of(self, some_class: type[datetime.datetime]) -> _DateTimeAssertion: ...
|
|
502
|
+
@overload
|
|
503
|
+
def is_instance_of(self, some_class: type[datetime.date]) -> _DateAssertion: ...
|
|
504
|
+
@overload
|
|
505
|
+
def is_instance_of(self, some_class: type[Path]) -> _PathAssertion: ...
|
|
506
|
+
@overload
|
|
507
|
+
def is_instance_of(self, some_class: type[bytes]) -> _BytesAssertion[bytes]: ...
|
|
508
|
+
@overload
|
|
509
|
+
def is_instance_of(self, some_class: type[bytearray]) -> _BytesAssertion[bytearray]: ...
|
|
510
|
+
@overload
|
|
511
|
+
def is_instance_of(self, some_class: tuple[type[_U], type[_U2]]) -> _ObjectAssertion[_U | _U2]: ...
|
|
512
|
+
@overload
|
|
513
|
+
def is_instance_of(
|
|
514
|
+
self, some_class: tuple[type[_U], type[_U2], type[_U3]]
|
|
515
|
+
) -> _ObjectAssertion[_U | _U2 | _U3]: ...
|
|
516
|
+
@overload
|
|
517
|
+
def is_instance_of(self, some_class: type[_U]) -> _ObjectAssertion[_U]: ...
|
|
518
|
+
@overload
|
|
519
|
+
def is_instance_of(self, some_class: ClassInfo) -> Self: ...
|
|
520
|
+
|
|
521
|
+
@overload
|
|
522
|
+
def is_instance_of_any(self, first: type[_U], second: type[_U2], /) -> _ObjectAssertion[_U | _U2]: ...
|
|
523
|
+
@overload
|
|
524
|
+
def is_instance_of_any(
|
|
525
|
+
self, first: type[_U], second: type[_U2], third: type[_U3], /
|
|
526
|
+
) -> _ObjectAssertion[_U | _U2 | _U3]: ...
|
|
527
|
+
@overload
|
|
528
|
+
def is_instance_of_any(self, *some_classes: ClassInfo) -> Self: ...
|
|
529
|
+
|
|
530
|
+
class _TextAssertion(_MembershipAssertion, _RepeatableAssertion[str], _SizedAssertion, _CoreAssertion, Protocol):
|
|
531
|
+
"""What a piece of text can be asked, whether a caller passed it in or the library caught it.
|
|
532
|
+
|
|
533
|
+
Split out from the string view so the invoked view can share it without sharing the rest. The
|
|
534
|
+
message a raised exception hands back is a `str`, so every assertion here applies to it, and
|
|
535
|
+
the assertions that read a path do not: that inheritance offered `exists()` on the text of an
|
|
536
|
+
exception, which the runtime then looks for on disk.
|
|
537
|
+
"""
|
|
538
|
+
|
|
539
|
+
@property
|
|
540
|
+
def not_(self) -> _NegatedTextAssertion: ...
|
|
541
|
+
|
|
542
|
+
@overload
|
|
543
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[str]]) -> _StringAssertion: ...
|
|
544
|
+
@overload
|
|
545
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[bool]]) -> _BoolAssertion: ...
|
|
546
|
+
@overload
|
|
547
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[int]]) -> _NumericAssertion[int]: ...
|
|
548
|
+
@overload
|
|
549
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[float]]) -> _NumericAssertion[float]: ...
|
|
550
|
+
@overload
|
|
551
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[complex]]) -> _ComplexAssertion: ...
|
|
552
|
+
@overload
|
|
553
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[dict[_K, _V]]]) -> _DictAssertion[_K, _V]: ...
|
|
554
|
+
@overload
|
|
555
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[list[_E] | tuple[_E, ...]]]) -> _IterableAssertion[_E]: ...
|
|
556
|
+
@overload
|
|
557
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[set[_E] | frozenset[_E]]]) -> _IterableAssertion[_E]: ...
|
|
558
|
+
@overload
|
|
559
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[datetime.datetime]]) -> _DateTimeAssertion: ...
|
|
560
|
+
@overload
|
|
561
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[datetime.date]]) -> _DateAssertion: ...
|
|
562
|
+
@overload
|
|
563
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[Path]]) -> _PathAssertion: ...
|
|
564
|
+
@overload
|
|
565
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[bytes]]) -> _BytesAssertion[bytes]: ...
|
|
566
|
+
@overload
|
|
567
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[bytearray]]) -> _BytesAssertion[bytearray]: ...
|
|
568
|
+
@overload
|
|
569
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[Callable[..., object]]]) -> _CallableAssertion[Any]: ...
|
|
570
|
+
@overload
|
|
571
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[_CapableT]]) -> AssertionBuilder[_CapableT]: ...
|
|
572
|
+
@overload
|
|
573
|
+
def satisfies(self, matcher: Callable[[str], TypeIs[_U]]) -> _ObjectAssertion[_U]: ...
|
|
574
|
+
@overload
|
|
575
|
+
def satisfies(self, matcher: Matcher[str] | Callable[[str], object]) -> Self: ...
|
|
576
|
+
|
|
577
|
+
"""Assertions available for ``str`` values."""
|
|
578
|
+
|
|
579
|
+
def contains(self, *items: str | Matcher[str]) -> Self: ...
|
|
580
|
+
|
|
581
|
+
@property
|
|
582
|
+
def value(self) -> str: ...
|
|
583
|
+
def is_equal_to_ignoring_case(self, other: str) -> Self: ...
|
|
584
|
+
def is_equal_to_ignoring_whitespace(self, other: str) -> Self: ...
|
|
585
|
+
def contains_ignoring_case(self, *items: str) -> Self: ...
|
|
586
|
+
def starts_with(self, prefix: str) -> Self: ...
|
|
587
|
+
def starts_with_ignoring_case(self, prefix: str) -> Self: ...
|
|
588
|
+
def ends_with(self, suffix: str) -> Self: ...
|
|
589
|
+
def ends_with_ignoring_case(self, suffix: str) -> Self: ...
|
|
590
|
+
def matches(self, pattern: str | re.Pattern[str]) -> Self: ...
|
|
591
|
+
def does_not_match(self, pattern: str | re.Pattern[str]) -> Self: ...
|
|
592
|
+
def is_alpha(self) -> Self: ...
|
|
593
|
+
def is_digit(self) -> Self: ...
|
|
594
|
+
def is_lower(self) -> Self: ...
|
|
595
|
+
def is_upper(self) -> Self: ...
|
|
596
|
+
def is_alphanumeric(self) -> Self: ...
|
|
597
|
+
def is_whitespace(self) -> Self: ...
|
|
598
|
+
def contains_any_of(self, *items: str) -> Self: ...
|
|
599
|
+
def contains_none_of(self, *items: str) -> Self: ...
|
|
600
|
+
def is_unicode(self) -> Self: ...
|
|
601
|
+
def is_greater_than(self, other: str) -> Self: ...
|
|
602
|
+
def is_greater_than_or_equal_to(self, other: str) -> Self: ...
|
|
603
|
+
def is_less_than(self, other: str) -> Self: ...
|
|
604
|
+
def is_less_than_or_equal_to(self, other: str) -> Self: ...
|
|
605
|
+
def does_not_contain(self, *items: str | Matcher[str]) -> Self: ...
|
|
606
|
+
def contains_only(self, *items: str | Matcher[str]) -> Self: ...
|
|
607
|
+
def contains_sequence(self, *items: str | Matcher[str]) -> Self: ...
|
|
608
|
+
def contains_exactly(self, *items: str | Matcher[str]) -> Self: ...
|
|
609
|
+
def contains_exactly_in_any_order(self, *items: str | Matcher[str]) -> Self: ...
|
|
610
|
+
def is_sorted(
|
|
611
|
+
self, key: Callable[[str], object] = ..., reverse: bool = ..., *, allow_empty: bool = ...
|
|
612
|
+
) -> Self: ...
|
|
613
|
+
# the runtime answers every quantifier for a `str`, so `assert_that("ab").each(...)` was a type error that ran
|
|
614
|
+
def each(self, matcher: Matcher[str] | Callable[[str], object], *, allow_empty: bool = ...) -> Self: ...
|
|
615
|
+
def all_satisfy(self, matcher: Matcher[str] | Callable[[str], object], *, allow_empty: bool = ...) -> Self: ...
|
|
616
|
+
def any_satisfy(self, matcher: Matcher[str] | Callable[[str], object]) -> Self: ...
|
|
617
|
+
def none_satisfy(self, matcher: Matcher[str] | Callable[[str], object]) -> Self: ...
|
|
618
|
+
def satisfies_exactly(self, *matchers: Matcher[str] | Callable[[str], object]) -> Self: ...
|
|
619
|
+
def satisfies_exactly_in_any_order(self, *matchers: Matcher[str] | Callable[[str], object]) -> Self: ...
|
|
620
|
+
# both named: `Any` let a caller write a character operation on whatever the other side holds
|
|
621
|
+
def zip_satisfies(
|
|
622
|
+
self, other: Iterable[_Other], predicate: Callable[[str, _Other], object], *, allow_empty: bool = ...
|
|
623
|
+
) -> Self: ...
|
|
624
|
+
def filtered_on(self, predicate: Matcher[str] | Callable[[str], object]) -> _ListAssertion[str]: ...
|
|
625
|
+
def mapped(self, func: Callable[[str], _R]) -> _ListAssertion[_R]: ...
|
|
626
|
+
def flat_mapped(self, func: Callable[[str], Iterable[_R]]) -> _ListAssertion[_R]: ...
|
|
627
|
+
# the string view here handed the filesystem assertions to a caught message through `first()`
|
|
628
|
+
def first(self) -> _TextAssertion: ...
|
|
629
|
+
def last(self) -> _TextAssertion: ...
|
|
630
|
+
def element(self, index: SupportsIndex) -> _TextAssertion: ...
|
|
631
|
+
def single(self) -> _TextAssertion: ...
|
|
632
|
+
def extracting_group(self, pattern: str | re.Pattern[str], group: int | str = ...) -> Self: ...
|
|
633
|
+
# which of the two a pattern yields cannot be known statically
|
|
634
|
+
def matches_with_groups(self, pattern: str | re.Pattern[str]) -> AssertionBuilder[Any]: ...
|
|
635
|
+
|
|
636
|
+
class _StringAssertion(_TextAssertion, _FilesystemAssertion, Protocol):
|
|
637
|
+
"""Assertions available for ``str`` values.
|
|
638
|
+
|
|
639
|
+
The text assertions plus the ones that read the value as a path, because a path is written as a
|
|
640
|
+
`str` at least as often as it is written as a `Path`.
|
|
641
|
+
"""
|
|
642
|
+
|
|
643
|
+
@property
|
|
644
|
+
def not_(self) -> _NegatedStringAssertion: ...
|
|
645
|
+
|
|
646
|
+
def check(self) -> _CheckStringAssertion: ...
|
|
647
|
+
|
|
648
|
+
# redeclared so a pivot keeps its result a `str` rather than the text capability
|
|
649
|
+
def first(self) -> _StringAssertion: ...
|
|
650
|
+
def last(self) -> _StringAssertion: ...
|
|
651
|
+
def element(self, index: SupportsIndex) -> _StringAssertion: ...
|
|
652
|
+
def single(self) -> _StringAssertion: ...
|
|
653
|
+
|
|
654
|
+
class _NumericAssertion(_RealNumberAssertion, _ZeroAssertion, _CoreAssertion, Protocol[_N]):
|
|
655
|
+
"""Assertions available for ``int`` and ``float`` values.
|
|
656
|
+
|
|
657
|
+
Generic over the number type ``_N`` so ``value`` keeps the exact numeric type instead of the
|
|
658
|
+
``int | float`` union.
|
|
659
|
+
|
|
660
|
+
`complex` and `bool` have protocols of their own, each carrying what the runtime actually
|
|
661
|
+
accepts for that type rather than the whole numeric set.
|
|
662
|
+
"""
|
|
663
|
+
|
|
664
|
+
# either tolerance holding is enough; with neither given the runtime refuses the call
|
|
665
|
+
def is_close_to(
|
|
666
|
+
self, other: _Number, tolerance: _Number | None = ..., *, rel: _Number | None = ...
|
|
667
|
+
) -> Self: ...
|
|
668
|
+
def is_not_close_to(
|
|
669
|
+
self, other: _Number, tolerance: _Number | None = ..., *, rel: _Number | None = ...
|
|
670
|
+
) -> Self: ...
|
|
671
|
+
@property
|
|
672
|
+
def not_(self) -> _NegatedNumericAssertion[_N]: ...
|
|
673
|
+
|
|
674
|
+
def check(self) -> _CheckNumericAssertion[_N]: ...
|
|
675
|
+
|
|
676
|
+
@property
|
|
677
|
+
def value(self) -> _N: ...
|
|
678
|
+
@overload
|
|
679
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[str]]) -> _StringAssertion: ...
|
|
680
|
+
@overload
|
|
681
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[bool]]) -> _BoolAssertion: ...
|
|
682
|
+
@overload
|
|
683
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[int]]) -> _NumericAssertion[int]: ...
|
|
684
|
+
@overload
|
|
685
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[float]]) -> _NumericAssertion[float]: ...
|
|
686
|
+
@overload
|
|
687
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[complex]]) -> _ComplexAssertion: ...
|
|
688
|
+
@overload
|
|
689
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[dict[_K, _V]]]) -> _DictAssertion[_K, _V]: ...
|
|
690
|
+
@overload
|
|
691
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[list[_E] | tuple[_E, ...]]]) -> _IterableAssertion[_E]: ...
|
|
692
|
+
@overload
|
|
693
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[set[_E] | frozenset[_E]]]) -> _IterableAssertion[_E]: ...
|
|
694
|
+
@overload
|
|
695
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[datetime.datetime]]) -> _DateTimeAssertion: ...
|
|
696
|
+
@overload
|
|
697
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[datetime.date]]) -> _DateAssertion: ...
|
|
698
|
+
@overload
|
|
699
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[Path]]) -> _PathAssertion: ...
|
|
700
|
+
@overload
|
|
701
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[bytes]]) -> _BytesAssertion[bytes]: ...
|
|
702
|
+
@overload
|
|
703
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[bytearray]]) -> _BytesAssertion[bytearray]: ...
|
|
704
|
+
@overload
|
|
705
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[Callable[..., object]]]) -> _CallableAssertion[Any]: ...
|
|
706
|
+
@overload
|
|
707
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[_CapableT]]) -> AssertionBuilder[_CapableT]: ...
|
|
708
|
+
@overload
|
|
709
|
+
def satisfies(self, matcher: Callable[[_N], TypeIs[_U]]) -> _ObjectAssertion[_U]: ...
|
|
710
|
+
@overload
|
|
711
|
+
def satisfies(self, matcher: Matcher[_N] | Callable[[_N], object]) -> Self: ...
|
|
712
|
+
# `_Number` rather than `_N`: comparing an `int` against a `float` has to keep working
|
|
713
|
+
def is_even(self) -> Self: ...
|
|
714
|
+
def is_odd(self) -> Self: ...
|
|
715
|
+
def is_divisible_by(self, divisor: SupportsIndex) -> Self: ...
|
|
716
|
+
|
|
717
|
+
class _ComplexAssertion(_ZeroAssertion, _CoreAssertion, Protocol):
|
|
718
|
+
"""Assertions available for ``complex`` values, which is far fewer than for a real number.
|
|
719
|
+
|
|
720
|
+
Ordering is not defined for a complex number, and neither is parity, divisibility, NaN or
|
|
721
|
+
infinity: the runtime refuses all thirteen of those with `TypeError: ordering is not defined for
|
|
722
|
+
type <complex>` and its relatives. It used to advertise them anyway, because `complex` shared
|
|
723
|
+
the numeric protocol, so a checker suggested a method whose only outcome was a crash.
|
|
724
|
+
"""
|
|
725
|
+
|
|
726
|
+
@property
|
|
727
|
+
def not_(self) -> _NegatedComplexAssertion: ...
|
|
728
|
+
|
|
729
|
+
def check(self) -> _CheckComplexAssertion: ...
|
|
730
|
+
|
|
731
|
+
@property
|
|
732
|
+
def value(self) -> complex: ...
|
|
733
|
+
|
|
734
|
+
class _BoolAssertion(_RealNumberAssertion, _ZeroAssertion, _CoreAssertion, Protocol):
|
|
735
|
+
"""Assertions available for ``bool``: every numeric one but the integer-only three and closeness.
|
|
736
|
+
|
|
737
|
+
`bool` is a subclass of `int`, so it used to resolve to the numeric protocol and be offered
|
|
738
|
+
`is_even`, `is_odd` and `is_divisible_by`. The runtime refuses exactly those three with
|
|
739
|
+
`TypeError: val is not an integer, got bool`, and closeness too, and accepts the rest: `True > 0`
|
|
740
|
+
is a real comparison. The type now says the same thing.
|
|
741
|
+
"""
|
|
742
|
+
|
|
743
|
+
@property
|
|
744
|
+
def not_(self) -> _NegatedBoolAssertion: ...
|
|
745
|
+
|
|
746
|
+
def check(self) -> _CheckBoolAssertion: ...
|
|
747
|
+
|
|
748
|
+
@property
|
|
749
|
+
def value(self) -> bool: ...
|
|
750
|
+
|
|
751
|
+
class _IterableAssertion(
|
|
752
|
+
_MembershipAssertion,
|
|
753
|
+
_StructureAssertion,
|
|
754
|
+
_RepeatableAssertion[_E],
|
|
755
|
+
_SizedAssertion,
|
|
756
|
+
_CoreAssertion,
|
|
757
|
+
Protocol[_E],
|
|
758
|
+
):
|
|
759
|
+
"""Assertions available for ``list``, ``tuple``, ``set``, and ``frozenset`` values.
|
|
760
|
+
|
|
761
|
+
Generic over the element type ``_E`` so element-access pivots (``first``/``last``/``element``/
|
|
762
|
+
``single``) narrow the chain to the element, and ``value`` keeps the element type.
|
|
763
|
+
"""
|
|
764
|
+
|
|
765
|
+
@property
|
|
766
|
+
def not_(self) -> _NegatedIterableAssertion[_E]: ...
|
|
767
|
+
|
|
768
|
+
def check(self) -> _CheckIterableAssertion[_E]: ...
|
|
769
|
+
|
|
770
|
+
@property
|
|
771
|
+
def value(self) -> list[_E] | tuple[_E, ...] | set[_E] | frozenset[_E]: ...
|
|
772
|
+
def contains(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
773
|
+
def does_not_contain(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
774
|
+
def contains_only(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
775
|
+
def contains_sequence(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
776
|
+
def contains_exactly(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
777
|
+
def contains_exactly_in_any_order(self, *items: _E | Matcher[_E]) -> Self: ...
|
|
778
|
+
def is_sorted(
|
|
779
|
+
self, key: Callable[[_E], object] = ..., reverse: bool = ..., *, allow_empty: bool = ...
|
|
780
|
+
) -> Self: ...
|
|
781
|
+
def starts_with(self, prefix: _E) -> Self: ...
|
|
782
|
+
def ends_with(self, suffix: _E) -> Self: ...
|
|
783
|
+
def each(self, matcher: Matcher[_E] | Callable[[_E], object], *, allow_empty: bool = ...) -> Self: ...
|
|
784
|
+
def all_satisfy(self, matcher: Matcher[_E] | Callable[[_E], object], *, allow_empty: bool = ...) -> Self: ...
|
|
785
|
+
def any_satisfy(self, matcher: Matcher[_E] | Callable[[_E], object]) -> Self: ...
|
|
786
|
+
def none_satisfy(self, matcher: Matcher[_E] | Callable[[_E], object]) -> Self: ...
|
|
787
|
+
def satisfies_exactly(self, *matchers: Matcher[_E] | Callable[[_E], object]) -> Self: ...
|
|
788
|
+
def satisfies_exactly_in_any_order(self, *matchers: Matcher[_E] | Callable[[_E], object]) -> Self: ...
|
|
789
|
+
def zip_satisfies(
|
|
790
|
+
self, other: Iterable[_Other], predicate: Callable[[_E, _Other], object], *, allow_empty: bool = ...
|
|
791
|
+
) -> Self: ...
|
|
792
|
+
def filtered_on(self, predicate: Matcher[_E] | Callable[[_E], object]) -> _ListAssertion[_E]: ...
|
|
793
|
+
def mapped(self, func: Callable[[_E], _R]) -> _ListAssertion[_R]: ...
|
|
794
|
+
def flat_mapped(self, func: Callable[[_E], Iterable[_R]]) -> _ListAssertion[_R]: ...
|
|
795
|
+
def first(self) -> AssertionBuilder[_E]: ...
|
|
796
|
+
def last(self) -> AssertionBuilder[_E]: ...
|
|
797
|
+
def element(self, index: SupportsIndex) -> AssertionBuilder[_E]: ...
|
|
798
|
+
def single(self) -> AssertionBuilder[_E]: ...
|
|
799
|
+
|
|
800
|
+
class _ListAssertion(_IterableAssertion[_E], Protocol[_E]):
|
|
801
|
+
"""The iterable view of a collection this library built, rather than one a caller passed in.
|
|
802
|
+
|
|
803
|
+
Every pipeline step returns one of these, and the difference from `_IterableAssertion` is a single
|
|
804
|
+
line: `value` is a `list`, not one of four containers. That is not a guess. `filtered_on`,
|
|
805
|
+
`mapped`, `flat_mapped` and `extracting` build a list whatever they were given, on a `tuple`, a
|
|
806
|
+
`set` and a `frozenset` alike, so declaring the union afterwards described an input that has
|
|
807
|
+
already been left behind, and made callers narrow a type the library had already settled.
|
|
808
|
+
"""
|
|
809
|
+
|
|
810
|
+
@property
|
|
811
|
+
def not_(self) -> _NegatedListAssertion[_E]: ...
|
|
812
|
+
|
|
813
|
+
def check(self) -> _CheckListAssertion[_E]: ...
|
|
814
|
+
|
|
815
|
+
@property
|
|
816
|
+
def value(self) -> list[_E]: ...
|
|
817
|
+
|
|
818
|
+
class _DictAssertion(_StructureAssertion, _SizedAssertion, _CoreAssertion, Protocol[_K, _V]):
|
|
819
|
+
"""Assertions available for ``dict`` values, generic over the key and value types."""
|
|
820
|
+
|
|
821
|
+
@property
|
|
822
|
+
def not_(self) -> _NegatedDictAssertion[_K, _V]: ...
|
|
823
|
+
|
|
824
|
+
def check(self) -> _CheckDictAssertion[(_K, _V)]: ...
|
|
825
|
+
|
|
826
|
+
# both spellings, as neither covers the other
|
|
827
|
+
def is_subset_of(self, *supersets: Mapping[Any, Any] | MappingLike, allow_empty: bool = ...) -> Self: ...
|
|
828
|
+
|
|
829
|
+
def contains(self, *items: object) -> Self: ...
|
|
830
|
+
|
|
831
|
+
@property
|
|
832
|
+
def value(self) -> dict[_K, _V]: ...
|
|
833
|
+
def each(self, matcher: Matcher[_K] | Callable[[_K], object], *, allow_empty: bool = ...) -> Self: ...
|
|
834
|
+
def all_satisfy(self, matcher: Matcher[_K] | Callable[[_K], object], *, allow_empty: bool = ...) -> Self: ...
|
|
835
|
+
def contains_key(self, *keys: _K | Matcher[_K]) -> Self: ...
|
|
836
|
+
def does_not_contain_key(self, *keys: _K | Matcher[_K]) -> Self: ...
|
|
837
|
+
def contains_value(self, *values: _V | Matcher[_V]) -> Self: ...
|
|
838
|
+
def does_not_contain_value(self, *values: _V | Matcher[_V]) -> Self: ...
|
|
839
|
+
def contains_entry(self, *args: object, **kwargs: object) -> Self: ...
|
|
840
|
+
def does_not_contain_entry(self, *args: object, **kwargs: object) -> Self: ...
|
|
841
|
+
def does_not_contain(self, *items: object) -> Self: ...
|
|
842
|
+
def contains_only(self, *keys: object) -> Self: ...
|
|
843
|
+
def is_sorted(
|
|
844
|
+
self, key: Callable[[_K], object] = ..., reverse: bool = ..., *, allow_empty: bool = ...
|
|
845
|
+
) -> Self: ...
|
|
846
|
+
# an element pivot hands back the builder: `_K` into the factory's view is dispatch this API cannot write
|
|
847
|
+
def filtered_on(self, predicate: Matcher[_K] | Callable[[_K], object]) -> _ListAssertion[_K]: ...
|
|
848
|
+
def mapped(self, func: Callable[[_K], _R]) -> _ListAssertion[_R]: ...
|
|
849
|
+
def flat_mapped(self, func: Callable[[_K], Iterable[_R]]) -> _ListAssertion[_R]: ...
|
|
850
|
+
def first(self) -> AssertionBuilder[_K]: ...
|
|
851
|
+
def last(self) -> AssertionBuilder[_K]: ...
|
|
852
|
+
def element(self, index: SupportsIndex) -> AssertionBuilder[_K]: ...
|
|
853
|
+
def single(self) -> AssertionBuilder[_K]: ...
|
|
854
|
+
def matches_structure(self, spec: dict[Any, Any]) -> Self: ...
|
|
855
|
+
|
|
856
|
+
# the shapes a checker recognises without importing the library that defines them. Every member is one
|
|
857
|
+
# `pandas-stubs` declares: `pivot` and not `__dataframe__`, which the stubs answer through their catch-all
|
|
858
|
+
# and mypy then reads as an array. No series shape, since nothing separates a series from a `pandas.Index`
|
|
859
|
+
|
|
860
|
+
# the umbrella: any capability keeps the whole surface. `__dict__` is out, it lives on `object`
|
|
861
|
+
|
|
862
|
+
class _CollectionShape(Protocol):
|
|
863
|
+
# `__iter__` alone: a generator has no `__len__` and `contains()` works on one
|
|
864
|
+
def __iter__(self) -> Any: ...
|
|
865
|
+
|
|
866
|
+
class _HeadersShape(Protocol):
|
|
867
|
+
def keys(self) -> Any: ...
|
|
868
|
+
# positional-only, the way typeshed spells it
|
|
869
|
+
def __getitem__(self, key: Any, /) -> Any: ...
|
|
870
|
+
|
|
871
|
+
class _HttpResponseShape(Protocol):
|
|
872
|
+
# read-only, so a client spelling either as a property still matches
|
|
873
|
+
@property
|
|
874
|
+
def status_code(self) -> int: ...
|
|
875
|
+
@property
|
|
876
|
+
def headers(self) -> _HeadersShape: ...
|
|
877
|
+
|
|
878
|
+
class _ModelShape(Protocol):
|
|
879
|
+
def model_dump(self, *args: Any, **kwargs: Any) -> Any: ...
|
|
880
|
+
|
|
881
|
+
class _DataclassShape(Protocol):
|
|
882
|
+
# `ClassVar`, because that is what `__dataclass_fields__` is: as an instance variable it matched nothing
|
|
883
|
+
__dataclass_fields__: ClassVar[Any]
|
|
884
|
+
|
|
885
|
+
class _MappingLikeShape(Protocol):
|
|
886
|
+
def keys(self) -> Any: ...
|
|
887
|
+
# positional-only, the way typeshed spells it
|
|
888
|
+
def __getitem__(self, key: Any, /) -> Any: ...
|
|
889
|
+
|
|
890
|
+
_Capable = _CollectionShape | _HttpResponseShape | _ModelShape | _DataclassShape | _MappingLikeShape
|
|
891
|
+
_CapableT = TypeVar("_CapableT", bound=_Capable)
|
|
892
|
+
|
|
893
|
+
class _FrameShape(Protocol):
|
|
894
|
+
def pivot(self, *args: Any, **kwargs: Any) -> Any: ...
|
|
895
|
+
@property
|
|
896
|
+
def shape(self) -> Any: ...
|
|
897
|
+
|
|
898
|
+
class _ArrayShape(Protocol):
|
|
899
|
+
def __array__(self) -> Any: ...
|
|
900
|
+
@property
|
|
901
|
+
def strides(self) -> Any: ...
|
|
902
|
+
# a numpy scalar carries the other two and no length, and falls through to the numeric fallback
|
|
903
|
+
def __len__(self) -> int: ...
|
|
904
|
+
|
|
905
|
+
# covariant: the view only ever hands the subject back, through `.value`
|
|
906
|
+
_FrameT_co = TypeVar("_FrameT_co", bound=_FrameShape, covariant=True)
|
|
907
|
+
_ArrayT_co = TypeVar("_ArrayT_co", bound=_ArrayShape, covariant=True)
|
|
908
|
+
|
|
909
|
+
class _CollectionShapedAssertion(_SizedAssertion, _MembershipAssertion, _WalkAssertion, Protocol):
|
|
910
|
+
"""What a frame, a series and an array all answer, measured rather than assumed.
|
|
911
|
+
|
|
912
|
+
Every family here is one their runtime gates accept: they are sized, they are walked, and they
|
|
913
|
+
answer membership. What is deliberately absent is as measured: the JSON family refuses them,
|
|
914
|
+
`matches_structure` refuses a polars frame, and the ordering assertions refuse them through
|
|
915
|
+
`is_between` while `is_greater_than` leaks the library's own ambiguity error instead.
|
|
916
|
+
|
|
917
|
+
One boundary the shapes cannot express: a zero-dimensional array carries `__array__` and
|
|
918
|
+
`strides` like any other, and `numpy.ndarray[Any, Any]` covers it, yet it has no length and
|
|
919
|
+
cannot be iterated. So `is_not_empty`, `is_length`, `contains_only` and `each` are offered on
|
|
920
|
+
`numpy.array(1)` and raise there. Separating it statically would need a shape keyed on the
|
|
921
|
+
dimension, which the stubs do not carry, and `tests/test_dataframe.py` holds what it does
|
|
922
|
+
instead.
|
|
923
|
+
"""
|
|
924
|
+
|
|
925
|
+
def contains(self, *items: object) -> Self: ...
|
|
926
|
+
def does_not_contain(self, *items: object) -> Self: ...
|
|
927
|
+
def contains_only(self, *items: object) -> Self: ...
|
|
928
|
+
|
|
929
|
+
class _ArrayLikeAssertion(_CollectionShapedAssertion, _CoreAssertion, Protocol):
|
|
930
|
+
"""The two numpy assertions, which every array-like the runtime accepts can answer."""
|
|
931
|
+
|
|
932
|
+
def is_array_equal(self, expected: object, **options: Any) -> Self: ...
|
|
933
|
+
def is_array_close_to(
|
|
934
|
+
self,
|
|
935
|
+
expected: object,
|
|
936
|
+
*,
|
|
937
|
+
rtol: float = ...,
|
|
938
|
+
atol: float = ...,
|
|
939
|
+
equal_nan: bool = ...,
|
|
940
|
+
**options: Any,
|
|
941
|
+
) -> Self: ...
|
|
942
|
+
|
|
943
|
+
class _FrameAssertion(_ArrayLikeAssertion, Protocol[_FrameT_co]):
|
|
944
|
+
"""Assertions available for a pandas or polars frame, which is array-like as well."""
|
|
945
|
+
|
|
946
|
+
@property
|
|
947
|
+
def not_(self) -> _NegatedFrameAssertion[_FrameT_co]: ...
|
|
948
|
+
|
|
949
|
+
def check(self) -> _CheckFrameAssertion[_FrameT_co]: ...
|
|
950
|
+
|
|
951
|
+
@property
|
|
952
|
+
def value(self) -> _FrameT_co: ...
|
|
953
|
+
def is_frame_equal(self, expected: object, **options: Any) -> Self: ...
|
|
954
|
+
|
|
955
|
+
class _ArrayAssertion(_ArrayLikeAssertion, Protocol[_ArrayT_co]):
|
|
956
|
+
"""Assertions available for a numpy array, which is everything a frame has but `is_frame_equal`."""
|
|
957
|
+
|
|
958
|
+
@property
|
|
959
|
+
def not_(self) -> _NegatedArrayAssertion[_ArrayT_co]: ...
|
|
960
|
+
|
|
961
|
+
def check(self) -> _CheckArrayAssertion[_ArrayT_co]: ...
|
|
962
|
+
|
|
963
|
+
@property
|
|
964
|
+
def value(self) -> _ArrayT_co: ...
|
|
965
|
+
|
|
966
|
+
class _DateAssertion(_CoreAssertion, Protocol):
|
|
967
|
+
"""Assertions available for a ``datetime.date`` value.
|
|
968
|
+
|
|
969
|
+
The chronological nine are not here. They refuse a plain date at run time, on the value and not
|
|
970
|
+
only on the operand, so `assert_that(day).is_before(stamp)` type-checked and raised for as long
|
|
971
|
+
as one view served both types. They live on the datetime view below.
|
|
972
|
+
"""
|
|
973
|
+
|
|
974
|
+
@property
|
|
975
|
+
def not_(self) -> _NegatedDateAssertion: ...
|
|
976
|
+
|
|
977
|
+
def check(self) -> _CheckDateAssertion: ...
|
|
978
|
+
|
|
979
|
+
@property
|
|
980
|
+
def value(self) -> datetime.date: ...
|
|
981
|
+
# at run time the operands must match the value's exact type
|
|
982
|
+
def is_greater_than(self, other: datetime.date) -> Self: ...
|
|
983
|
+
def is_greater_than_or_equal_to(self, other: datetime.date) -> Self: ...
|
|
984
|
+
def is_less_than(self, other: datetime.date) -> Self: ...
|
|
985
|
+
def is_less_than_or_equal_to(self, other: datetime.date) -> Self: ...
|
|
986
|
+
def is_between(self, low: datetime.date, high: datetime.date) -> Self: ...
|
|
987
|
+
def is_not_between(self, low: datetime.date, high: datetime.date) -> Self: ...
|
|
988
|
+
|
|
989
|
+
class _DateTimeAssertion(_CoreAssertion, Protocol):
|
|
990
|
+
"""Assertions available for a ``datetime.datetime`` value.
|
|
991
|
+
|
|
992
|
+
A sibling of the date view rather than a child of it, and the ordering below is why: at run time
|
|
993
|
+
an operand has to match the value's own type, so a datetime orders against a datetime. Inheriting
|
|
994
|
+
the date view brought its `is_less_than(other: datetime.date)` along, and
|
|
995
|
+
`assert_that(stamp).is_less_than(day)` type-checked and raised.
|
|
996
|
+
"""
|
|
997
|
+
|
|
998
|
+
@property
|
|
999
|
+
def not_(self) -> _NegatedDateTimeAssertion: ...
|
|
1000
|
+
|
|
1001
|
+
def check(self) -> _CheckDateTimeAssertion: ...
|
|
1002
|
+
|
|
1003
|
+
@property
|
|
1004
|
+
def value(self) -> datetime.datetime: ...
|
|
1005
|
+
def is_greater_than(self, other: datetime.datetime) -> Self: ...
|
|
1006
|
+
def is_greater_than_or_equal_to(self, other: datetime.datetime) -> Self: ...
|
|
1007
|
+
def is_less_than(self, other: datetime.datetime) -> Self: ...
|
|
1008
|
+
def is_less_than_or_equal_to(self, other: datetime.datetime) -> Self: ...
|
|
1009
|
+
def is_between(self, low: datetime.datetime, high: datetime.datetime) -> Self: ...
|
|
1010
|
+
def is_not_between(self, low: datetime.datetime, high: datetime.datetime) -> Self: ...
|
|
1011
|
+
def is_before(self, other: datetime.datetime) -> Self: ...
|
|
1012
|
+
def is_after(self, other: datetime.datetime) -> Self: ...
|
|
1013
|
+
def is_before_or_equal_to(self, other: datetime.datetime) -> Self: ...
|
|
1014
|
+
def is_after_or_equal_to(self, other: datetime.datetime) -> Self: ...
|
|
1015
|
+
def is_equal_to_ignoring_milliseconds(self, other: datetime.datetime) -> Self: ...
|
|
1016
|
+
def is_equal_to_ignoring_seconds(self, other: datetime.datetime) -> Self: ...
|
|
1017
|
+
def is_equal_to_ignoring_time(self, other: datetime.datetime) -> Self: ...
|
|
1018
|
+
# closeness on a datetime is a timedelta, the one place the numeric family takes something else. Optional
|
|
1019
|
+
# because the one runtime method serves numbers too, where `rel` may stand alone; a datetime has no size
|
|
1020
|
+
# for `rel` to be a fraction of, so it is declared as nothing but `None`
|
|
1021
|
+
def is_close_to(
|
|
1022
|
+
self, other: datetime.datetime, tolerance: datetime.timedelta | None = ..., *, rel: None = ...
|
|
1023
|
+
) -> Self: ...
|
|
1024
|
+
def is_not_close_to(
|
|
1025
|
+
self, other: datetime.datetime, tolerance: datetime.timedelta | None = ..., *, rel: None = ...
|
|
1026
|
+
) -> Self: ...
|
|
1027
|
+
|
|
1028
|
+
class _PathAssertion(_FilesystemAssertion, _CoreAssertion, Protocol):
|
|
1029
|
+
"""Assertions available for ``pathlib.Path`` values."""
|
|
1030
|
+
|
|
1031
|
+
@property
|
|
1032
|
+
def not_(self) -> _NegatedPathAssertion: ...
|
|
1033
|
+
|
|
1034
|
+
def check(self) -> _CheckPathAssertion: ...
|
|
1035
|
+
|
|
1036
|
+
@property
|
|
1037
|
+
def value(self) -> Path: ...
|
|
1038
|
+
|
|
1039
|
+
class _BytesAssertion(_MembershipAssertion, _SizedAssertion, _CoreAssertion, Protocol[_B_co]):
|
|
1040
|
+
"""Assertions available for ``bytes`` and ``bytearray`` values, generic over which one."""
|
|
1041
|
+
|
|
1042
|
+
@property
|
|
1043
|
+
def not_(self) -> _NegatedBytesAssertion[_B_co]: ...
|
|
1044
|
+
|
|
1045
|
+
def check(self) -> _CheckBytesAssertion[_B_co]: ...
|
|
1046
|
+
|
|
1047
|
+
def contains(self, *items: object) -> Self: ...
|
|
1048
|
+
def does_not_contain(self, *items: object) -> Self: ...
|
|
1049
|
+
|
|
1050
|
+
@property
|
|
1051
|
+
def value(self) -> _B_co: ...
|
|
1052
|
+
def is_sorted(
|
|
1053
|
+
self, key: Callable[[int], object] = ..., reverse: bool = ..., *, allow_empty: bool = ...
|
|
1054
|
+
) -> Self: ...
|
|
1055
|
+
def filtered_on(self, predicate: Matcher[int] | Callable[[int], object]) -> _ListAssertion[int]: ...
|
|
1056
|
+
def mapped(self, func: Callable[[int], _R]) -> _ListAssertion[_R]: ...
|
|
1057
|
+
def flat_mapped(self, func: Callable[[int], Iterable[_R]]) -> _ListAssertion[_R]: ...
|
|
1058
|
+
def first(self) -> _NumericAssertion[int]: ...
|
|
1059
|
+
def last(self) -> _NumericAssertion[int]: ...
|
|
1060
|
+
def element(self, index: SupportsIndex) -> _NumericAssertion[int]: ...
|
|
1061
|
+
def single(self) -> _NumericAssertion[int]: ...
|
|
1062
|
+
# the prefix and suffix pair handles bytes natively, so it is reachable under both names
|
|
1063
|
+
def starts_with(self, prefix: bytes | bytearray) -> Self: ...
|
|
1064
|
+
def ends_with(self, suffix: bytes | bytearray) -> Self: ...
|
|
1065
|
+
def is_valid_utf8(self) -> Self: ...
|
|
1066
|
+
def is_valid_encoding(self, encoding: str) -> Self: ...
|
|
1067
|
+
def starts_with_bytes(self, prefix: bytes | bytearray) -> Self: ...
|
|
1068
|
+
def contains_bytes(self, sub: bytes | bytearray) -> Self: ...
|
|
1069
|
+
def has_byte_at(self, index: SupportsIndex, expected: SupportsIndex) -> Self: ...
|
|
1070
|
+
def is_hex_equal_to(self, expected_hex: str) -> Self: ...
|
|
1071
|
+
def decoded_as(self, encoding: str = ...) -> _StringAssertion: ...
|
|
1072
|
+
def is_greater_than(self, other: bytes | bytearray) -> Self: ...
|
|
1073
|
+
def is_greater_than_or_equal_to(self, other: bytes | bytearray) -> Self: ...
|
|
1074
|
+
def is_less_than(self, other: bytes | bytearray) -> Self: ...
|
|
1075
|
+
def is_less_than_or_equal_to(self, other: bytes | bytearray) -> Self: ...
|
|
1076
|
+
|
|
1077
|
+
class _InvokedAssertion(_TextAssertion, Protocol[_Exc]):
|
|
1078
|
+
"""Assertions available after ``when_called_with()`` captured an exception message.
|
|
1079
|
+
|
|
1080
|
+
The captured message is a ``str`` (hence the text assertions, though not the ones reading a
|
|
1081
|
+
path: a message is not a filename).
|
|
1082
|
+
|
|
1083
|
+
`returned()` is absent and that is measured: after `raises()` the call never completed, so it
|
|
1084
|
+
raises `no return value captured`. A call that did complete lands on `_WarnedAssertion` or
|
|
1085
|
+
`_CompletedAssertion`, which carry it instead.
|
|
1086
|
+
"""
|
|
1087
|
+
|
|
1088
|
+
@property
|
|
1089
|
+
def not_(self) -> _NegatedInvokedAssertion[_Exc]: ...
|
|
1090
|
+
|
|
1091
|
+
def check(self) -> _CheckInvokedAssertion[_Exc]: ...
|
|
1092
|
+
|
|
1093
|
+
def raised(self) -> AssertionBuilder[_Exc]: ...
|
|
1094
|
+
# these three pivot to the exception they found; a bare `type` names none, and ty refused it against the bound
|
|
1095
|
+
@overload
|
|
1096
|
+
def caused_by(self, ex: type[_Landed]) -> _InvokedAssertion[_Landed]: ...
|
|
1097
|
+
# the cause is read with `isinstance`, so a union or a tuple of classes is taken, landing on no one class
|
|
1098
|
+
@overload
|
|
1099
|
+
def caused_by(self, ex: ClassInfo) -> _InvokedAssertion[BaseException]: ...
|
|
1100
|
+
def errors(self) -> _ListAssertion[BaseException]: ...
|
|
1101
|
+
@overload
|
|
1102
|
+
def error_of(self, ex: type[_Landed]) -> _InvokedAssertion[_Landed]: ...
|
|
1103
|
+
@overload
|
|
1104
|
+
def error_of(self, ex: type) -> _InvokedAssertion[BaseException]: ...
|
|
1105
|
+
def does_not_contain_error(self, *ex_types: type | ExceptionInfo) -> Self: ...
|
|
1106
|
+
@overload
|
|
1107
|
+
def has_root_cause(self, ex: type[_Landed]) -> _InvokedAssertion[_Landed]: ...
|
|
1108
|
+
@overload
|
|
1109
|
+
def has_root_cause(self, ex: ClassInfo) -> _InvokedAssertion[BaseException]: ...
|
|
1110
|
+
def contains_error(self, *ex_types: type | ExceptionInfo) -> Self: ...
|
|
1111
|
+
# a `list` is a subgroup, so the entry type is recursive; spelled with `Any` inside because a
|
|
1112
|
+
# recursive alias declared here is what ty reads as `Any` anyway, measured in `_typing.py`'s own
|
|
1113
|
+
# history, and naming it would suggest a precision the checkers do not carry
|
|
1114
|
+
def matches_error_tree(self, *expected: type | list[Any]) -> Self: ...
|
|
1115
|
+
|
|
1116
|
+
class _WarnedAssertion(_TextAssertion, Protocol[_P_co]):
|
|
1117
|
+
"""Assertions available after ``when_called_with()`` captured a warning message.
|
|
1118
|
+
|
|
1119
|
+
The message is text like the invoked view's, and the call completed, so
|
|
1120
|
+
[`returned()`][assertpy.exception.ExceptionMixin.returned] reads the value it produced. The
|
|
1121
|
+
exception family is absent: nothing was caught, and every one of those eight raises
|
|
1122
|
+
`no exception captured`, measured.
|
|
1123
|
+
"""
|
|
1124
|
+
|
|
1125
|
+
@property
|
|
1126
|
+
def not_(self) -> _NegatedWarnedAssertion[_P_co]: ...
|
|
1127
|
+
|
|
1128
|
+
def check(self) -> _CheckWarnedAssertion[_P_co]: ...
|
|
1129
|
+
|
|
1130
|
+
# named outright: bound through `self`, ty found no member here that uses the parameter and read `Unknown`
|
|
1131
|
+
def returned(self) -> AssertionBuilder[_P_co]: ...
|
|
1132
|
+
|
|
1133
|
+
class _CallableAssertion(_CoreAssertion, Protocol[_P_co]):
|
|
1134
|
+
"""Assertions available for callable values.
|
|
1135
|
+
|
|
1136
|
+
`when_called_with()` is not here. It refuses a chain with no expectation set, so the four
|
|
1137
|
+
methods that set one hand back the view carrying it.
|
|
1138
|
+
"""
|
|
1139
|
+
|
|
1140
|
+
@property
|
|
1141
|
+
def not_(self) -> _NegatedCallableAssertion[_P_co]: ...
|
|
1142
|
+
|
|
1143
|
+
def check(self) -> _CheckCallableAssertion[_P_co]: ...
|
|
1144
|
+
|
|
1145
|
+
@property
|
|
1146
|
+
def value(self) -> Callable[..., _P_co]: ...
|
|
1147
|
+
@overload
|
|
1148
|
+
def raises(self, ex: type[_Landed]) -> _ExpectedRaiseAssertion[_P_co, _Landed]: ...
|
|
1149
|
+
# several classes, any one of which may be raised, land on no one class, as a bare `type` does
|
|
1150
|
+
@overload
|
|
1151
|
+
def raises(self, ex: type | ExceptionInfo) -> _ExpectedRaiseAssertion[_P_co, BaseException]: ...
|
|
1152
|
+
def does_not_raise(self, ex: type | ExceptionInfo) -> _ExpectedCompletionAssertion[_P_co]: ...
|
|
1153
|
+
def warns(self, warning: type[Warning] | WarningInfo = ...) -> _ExpectedWarningAssertion[_P_co]: ...
|
|
1154
|
+
def does_not_warn(self, warning: type[Warning] | WarningInfo = ...) -> _ExpectedCompletionAssertion[_P_co]: ...
|
|
1155
|
+
# an `async def` probe is awaited on every poll, so the chain is over what the coroutine returns
|
|
1156
|
+
@overload
|
|
1157
|
+
def eventually(
|
|
1158
|
+
self: _Holding[Callable[..., Awaitable[_R]]],
|
|
1159
|
+
*,
|
|
1160
|
+
timeout: float = ...,
|
|
1161
|
+
interval: float = ...,
|
|
1162
|
+
ignoring: type[Exception] | RetriedInfo = ...,
|
|
1163
|
+
trace: bool = ...,
|
|
1164
|
+
) -> _AsyncPoll[_R]: ...
|
|
1165
|
+
@overload
|
|
1166
|
+
def eventually(
|
|
1167
|
+
self,
|
|
1168
|
+
*,
|
|
1169
|
+
timeout: float = ...,
|
|
1170
|
+
interval: float = ...,
|
|
1171
|
+
ignoring: type[Exception] | RetriedInfo = ...,
|
|
1172
|
+
trace: bool = ...,
|
|
1173
|
+
) -> _AsyncPoll[_P_co]: ...
|
|
1174
|
+
def eventually_sync(
|
|
1175
|
+
self,
|
|
1176
|
+
*,
|
|
1177
|
+
timeout: float = ...,
|
|
1178
|
+
interval: float = ...,
|
|
1179
|
+
ignoring: type[Exception] | RetriedInfo = ...,
|
|
1180
|
+
trace: bool = ...,
|
|
1181
|
+
) -> _SyncPoll[_P_co]: ...
|
|
1182
|
+
|
|
1183
|
+
class _CompletedAssertion(_CallableAssertion[_P_co], Protocol[_P_co]):
|
|
1184
|
+
"""Assertions available after a `does_not_raise()` or `does_not_warn()` call completed.
|
|
1185
|
+
|
|
1186
|
+
The value under test is still the callable, not a message, so the text assertions are absent:
|
|
1187
|
+
every one of them raises `val must be a string or an iterable`, measured. What the call
|
|
1188
|
+
produced is reachable through `returned()`.
|
|
1189
|
+
"""
|
|
1190
|
+
|
|
1191
|
+
@property
|
|
1192
|
+
def not_(self) -> _NegatedCompletedAssertion[_P_co]: ...
|
|
1193
|
+
|
|
1194
|
+
def check(self) -> _CheckCompletedAssertion[_P_co]: ...
|
|
1195
|
+
|
|
1196
|
+
def returned(self: _CompletedAssertion[_R]) -> AssertionBuilder[_R]: ...
|
|
1197
|
+
|
|
1198
|
+
class _ExpectedRaiseAssertion(_CallableAssertion[_P_co], Protocol[_P_co, _Exc]):
|
|
1199
|
+
"""A callable with a `raises()` expectation set, waiting for the call that tests it."""
|
|
1200
|
+
|
|
1201
|
+
@property
|
|
1202
|
+
def not_(self) -> _NegatedExpectedRaiseAssertion[_P_co, _Exc]: ...
|
|
1203
|
+
|
|
1204
|
+
def check(self) -> _CheckExpectedRaiseAssertion[_P_co, _Exc]: ...
|
|
1205
|
+
|
|
1206
|
+
def when_called_with(self, *some_args: object, **some_kwargs: object) -> _InvokedAssertion[_Exc]: ...
|
|
1207
|
+
|
|
1208
|
+
class _ExpectedWarningAssertion(_CallableAssertion[_P_co], Protocol[_P_co]):
|
|
1209
|
+
"""A callable with a `warns()` expectation set, waiting for the call that tests it."""
|
|
1210
|
+
|
|
1211
|
+
@property
|
|
1212
|
+
def not_(self) -> _NegatedExpectedWarningAssertion[_P_co]: ...
|
|
1213
|
+
|
|
1214
|
+
def check(self) -> _CheckExpectedWarningAssertion[_P_co]: ...
|
|
1215
|
+
|
|
1216
|
+
def when_called_with(self, *some_args: object, **some_kwargs: object) -> _WarnedAssertion[_P_co]: ...
|
|
1217
|
+
|
|
1218
|
+
class _ExpectedCompletionAssertion(_CallableAssertion[_P_co], Protocol[_P_co]):
|
|
1219
|
+
"""A callable expected to complete, which is what `does_not_raise()` and `does_not_warn()` set."""
|
|
1220
|
+
|
|
1221
|
+
@property
|
|
1222
|
+
def not_(self) -> _NegatedExpectedCompletionAssertion[_P_co]: ...
|
|
1223
|
+
|
|
1224
|
+
def check(self) -> _CheckExpectedCompletionAssertion[_P_co]: ...
|
|
1225
|
+
|
|
1226
|
+
def when_called_with(self, *some_args: object, **some_kwargs: object) -> _CompletedAssertion[_P_co]: ...
|