panda-pytest-assertions 0.1.1__tar.gz → 0.2.1__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.
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/PKG-INFO +1 -1
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_context/__init__.py +2 -1
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_context/_assert_context.py +50 -19
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/__init__.py +6 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_asserter_factories/built_in_asserter_factory.py +4 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_converters/expectation_from_yaml.py +30 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_converters/expectation_to_yaml.py +6 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/__init__.py +5 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/_expectation_modificators/identity.py +14 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/_expectation_modificators/is_type.py +90 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/__init__.py +6 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/_objects_asserters/identity_asserter.py +36 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/_objects_asserters/is_type_asserter.py +51 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/__init__.py +2 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/__init__.py +2 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/generators/_expectation_definitions/is_type.py +8 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generator_factories/built_in_generator_factory.py +2 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/__init__.py +2 -0
- panda_pytest_assertions-0.2.1/panda_pytest_assertions/assert_object/generators/_generators/is_type_generator.py +44 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/pyproject.toml +1 -1
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/LICENSE +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/README.md +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/__init__.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_assert_object.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_asserter_factories/__init__.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_asserter_factories/asserter_factory.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_converters/__init__.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/mapping_subset.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/object_attibutes.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/stringified.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/unordered.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_expectation_modificators/with_type.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/equality_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/mapping_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/mapping_subset_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/object_attributes_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/ordered_elements_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/stringified_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/unordered_elements_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_objects_asserters/with_type_asserter.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/_protocols.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/equality.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/mapping.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/mapping_subset.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/object_attributes.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/of_type.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/stringified.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_mapping.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_mapping_subset.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_ordered.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_unordered.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/union.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_expectation_definitions/with_type.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generate_expectation.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generator_factories/__init__.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generator_factories/generator_factory.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/equality_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/equality_key_mapping_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/exceptions.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/mapping_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/mapping_subset_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/object_attributes_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/of_type_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/ordered_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/stringified_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/uniform_mapping_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/uniform_mapping_subset_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/uniform_ordered_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/union_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/unordered_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/assert_object/generators/_generators/with_type_generator.py +0 -0
- {panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/py.typed +0 -0
|
@@ -6,10 +6,11 @@ pytest.register_assert_rewrite(__name__ + '._assert_context')
|
|
|
6
6
|
# isort: on
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
from ._assert_context import assert_context, AssertContext
|
|
9
|
+
from ._assert_context import assert_context, AssertContext, ExceptionMatch
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
__all__ = [
|
|
13
13
|
'assert_context',
|
|
14
14
|
'AssertContext',
|
|
15
|
+
'ExceptionMatch',
|
|
15
16
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from collections.abc import Generator
|
|
2
2
|
from contextlib import contextmanager, ExitStack, nullcontext
|
|
3
|
-
from typing import Any, overload
|
|
3
|
+
from typing import Any, NamedTuple, overload
|
|
4
4
|
|
|
5
5
|
import pytest
|
|
6
6
|
|
|
@@ -32,18 +32,29 @@ class AssertContext:
|
|
|
32
32
|
assert expected_result == self._result
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
class ExceptionMatch(NamedTuple):
|
|
36
|
+
#: type of expected exception
|
|
37
|
+
type_: type[BaseException]
|
|
38
|
+
#: match parameter passed to pytest.raises
|
|
39
|
+
match_: str
|
|
40
|
+
|
|
41
|
+
|
|
35
42
|
@overload
|
|
36
43
|
@contextmanager
|
|
37
44
|
def assert_context( # noqa: D418
|
|
38
45
|
*,
|
|
39
|
-
exception: type[BaseException] | _Unset = ...,
|
|
46
|
+
exception: type[BaseException] | ExceptionMatch | None | _Unset = ...,
|
|
40
47
|
result: Any | _Unset = ..., # noqa: ANN401
|
|
41
48
|
) -> Generator[AssertContext, None, None]:
|
|
42
49
|
"""
|
|
43
50
|
Context manager that makes sure `with` block behaved according to the arguments.
|
|
44
51
|
|
|
45
|
-
If the `exception` parameter is set, the `with` block is expected to raise an exception
|
|
46
|
-
|
|
52
|
+
If the `exception` parameter is set to exception type, the `with` block is expected to raise an exception
|
|
53
|
+
of provided type. If the `exception` parameter is set to an instance of `ExceptionMatch` class, the `with`
|
|
54
|
+
block is expected to raise an exception of type specified in `type_` field and the value that matches the
|
|
55
|
+
string specified in `match_` field. For exact matching logic see `match` parameter of the `pytest.raises`.
|
|
56
|
+
If the `exception` parameter is NOT set or is set to `None`, the `with` block is expected NOT TO raise
|
|
57
|
+
any exceptions.
|
|
47
58
|
|
|
48
59
|
If the `result` parameter is set, its value is expected to be equal to `with` block result. The `with`
|
|
49
60
|
block result is set with the `set` method of an object yielded by the context manager. The comparison
|
|
@@ -51,7 +62,7 @@ def assert_context( # noqa: D418
|
|
|
51
62
|
If the `result` parameter is NOT set, the `set` method of yielded object is expected
|
|
52
63
|
not to be called at all.
|
|
53
64
|
|
|
54
|
-
:param exception:
|
|
65
|
+
:param exception: specification of exception, expected to be raised
|
|
55
66
|
:param result: value expected to be set with `set` method of yielded object
|
|
56
67
|
"""
|
|
57
68
|
|
|
@@ -60,7 +71,7 @@ def assert_context( # noqa: D418
|
|
|
60
71
|
@contextmanager
|
|
61
72
|
def assert_context( # noqa: D418
|
|
62
73
|
*,
|
|
63
|
-
behaviour: type[BaseException] | Any | _Unset = ..., # noqa: ANN401
|
|
74
|
+
behaviour: type[BaseException] | ExceptionMatch | Any | _Unset = ..., # noqa: ANN401
|
|
64
75
|
) -> Generator[AssertContext, None, None]:
|
|
65
76
|
"""
|
|
66
77
|
Context manager that makes sure `with` block behaved according to the arguments.
|
|
@@ -68,9 +79,11 @@ def assert_context( # noqa: D418
|
|
|
68
79
|
Context manager yields a single object used that provides `set` method used to set the `with`
|
|
69
80
|
block result that is to be asserted.
|
|
70
81
|
|
|
71
|
-
If the `behaviour` parameter is set to
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
If the `behaviour` parameter is set to exception type, the `with` block is expected to raise an exception
|
|
83
|
+
of provided type. If the `behaviour` parameter is set to an instance of `ExceptionMatch` class, the `with`
|
|
84
|
+
block is expected to raise an exception of type specified in `type_` field and the value that matches the
|
|
85
|
+
string specified in `match_` field. For exact matching logic see `match` parameter of the `pytest.raises`.
|
|
86
|
+
In both cases the `set` method of yielded object is expected not to be called at all.
|
|
74
87
|
|
|
75
88
|
If the `behaviour` parameter is set to anything else, its value is expected to be equal to `with`
|
|
76
89
|
block result. The comparison is used with `==` operator, where `result` argument is on the left side and
|
|
@@ -86,20 +99,24 @@ def assert_context( # noqa: D418
|
|
|
86
99
|
@contextmanager
|
|
87
100
|
def assert_context(
|
|
88
101
|
*,
|
|
89
|
-
exception: type[BaseException] | _Unset = _UNSET,
|
|
102
|
+
exception: type[BaseException] | ExceptionMatch | None | _Unset = _UNSET,
|
|
90
103
|
result: Any | _Unset = _UNSET,
|
|
91
|
-
behaviour: type[BaseException] | Any | _Unset = _UNSET,
|
|
104
|
+
behaviour: type[BaseException] | ExceptionMatch | Any | _Unset = _UNSET,
|
|
92
105
|
) -> Generator[AssertContext, None, None]:
|
|
93
106
|
"""
|
|
94
107
|
Context manager that makes sure `with` block behaved according to the arguments.
|
|
95
108
|
|
|
96
109
|
Pair of parameters `exception` and `result` are exclusive with parameter `behaviour`. If `behaviour`
|
|
97
|
-
is set to an exception type, it is the same as if `exception` would be set to
|
|
98
|
-
would not be set. If `behaviour` is set to any other value, its treated as the
|
|
99
|
-
`exception` remains unset.
|
|
110
|
+
is set to an exception type or `ExceptionMatch` instance, it is the same as if `exception` would be set to
|
|
111
|
+
this value and `result` would not be set. If `behaviour` is set to any other value, its treated as the
|
|
112
|
+
value of `result` and the `exception` remains unset.
|
|
100
113
|
|
|
101
|
-
If the `exception` parameter is set, the `with` block is expected to raise an exception
|
|
102
|
-
|
|
114
|
+
If the `exception` parameter is set to exception type, the `with` block is expected to raise an exception
|
|
115
|
+
of provided type. If the `exception` parameter is set to an instance of `ExceptionMatch` class, the `with`
|
|
116
|
+
block is expected to raise an exception of type specified in `type_` field and the value that matches the
|
|
117
|
+
string specified in `match_` field. For exact matching logic see `match` parameter of the `pytest.raises`.
|
|
118
|
+
If the `exception` parameter is NOT set or is set to `None`, the `with` block is expected NOT TO raise
|
|
119
|
+
any exceptions.
|
|
103
120
|
|
|
104
121
|
If the `result` parameter is set, its value is expected to be equal to `with` block result. The `with`
|
|
105
122
|
block result is set with the `set` method of an object yielded by the context manager. The comparison
|
|
@@ -107,7 +124,7 @@ def assert_context(
|
|
|
107
124
|
If the `result` parameter is NOT set, the `set` method of yielded object is expected
|
|
108
125
|
not to be called at all.
|
|
109
126
|
|
|
110
|
-
:param exception:
|
|
127
|
+
:param exception: specification of exception, expected to be raised
|
|
111
128
|
:param result: value expected to be set with `set` method of yielded object
|
|
112
129
|
:param behaviour: a common name for `exception` and `result` parameters, exclusive to them
|
|
113
130
|
:yield: object used to set the result of a `with` block
|
|
@@ -115,12 +132,26 @@ def assert_context(
|
|
|
115
132
|
if behaviour != _UNSET:
|
|
116
133
|
assert exception == _UNSET
|
|
117
134
|
assert result == _UNSET
|
|
118
|
-
if isinstance(behaviour,
|
|
135
|
+
if isinstance(behaviour, ExceptionMatch) or (
|
|
136
|
+
isinstance(behaviour, type) and issubclass(behaviour, BaseException)
|
|
137
|
+
):
|
|
119
138
|
exception = behaviour
|
|
120
139
|
else:
|
|
121
140
|
result = behaviour
|
|
141
|
+
if isinstance(exception, ExceptionMatch):
|
|
142
|
+
match_ = exception.match_
|
|
143
|
+
exception = exception.type_
|
|
144
|
+
else:
|
|
145
|
+
match_ = None
|
|
122
146
|
context = AssertContext()
|
|
123
|
-
exception_behaviour =
|
|
147
|
+
exception_behaviour = (
|
|
148
|
+
nullcontext()
|
|
149
|
+
if isinstance(exception, _Unset | None)
|
|
150
|
+
else pytest.raises(
|
|
151
|
+
exception,
|
|
152
|
+
match=match_,
|
|
153
|
+
)
|
|
154
|
+
)
|
|
124
155
|
|
|
125
156
|
with ExitStack() as behaviours_stack:
|
|
126
157
|
behaviours_stack.enter_context(context.assert_result_equal(result))
|
|
@@ -7,6 +7,9 @@ from ._converters import (
|
|
|
7
7
|
ExpectationYamlLoader,
|
|
8
8
|
)
|
|
9
9
|
from ._expectation_modificators import (
|
|
10
|
+
Is,
|
|
11
|
+
is_type,
|
|
12
|
+
IsType,
|
|
10
13
|
MappingSubset,
|
|
11
14
|
ObjectAttributes,
|
|
12
15
|
Stringified,
|
|
@@ -27,6 +30,9 @@ __all__ = [
|
|
|
27
30
|
'expectation_from_yaml',
|
|
28
31
|
'ExpectationYamlDumper',
|
|
29
32
|
'ExpectationYamlLoader',
|
|
33
|
+
'Is',
|
|
34
|
+
'is_type',
|
|
35
|
+
'IsType',
|
|
30
36
|
'MappingSubset',
|
|
31
37
|
'ObjectAttributes',
|
|
32
38
|
'Stringified',
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from panda_pytest_assertions.assert_object._objects_asserters import (
|
|
2
2
|
EqualityAsserter,
|
|
3
|
+
IdentityAsserter,
|
|
4
|
+
IsTypeAsserter,
|
|
3
5
|
MappingAsserter,
|
|
4
6
|
MappingSubsetAsserter,
|
|
5
7
|
ObjectAttributesAsserter,
|
|
@@ -20,6 +22,8 @@ class BuiltInAsserterFactory(AsserterFactory):
|
|
|
20
22
|
|
|
21
23
|
# MUST be the first one as it implements a fallback mechanism and matches everything
|
|
22
24
|
BuiltInAsserterFactory.register_asserter(EqualityAsserter)
|
|
25
|
+
BuiltInAsserterFactory.register_asserter(IdentityAsserter)
|
|
26
|
+
BuiltInAsserterFactory.register_asserter(IsTypeAsserter)
|
|
23
27
|
BuiltInAsserterFactory.register_asserter(MappingAsserter)
|
|
24
28
|
BuiltInAsserterFactory.register_asserter(MappingSubsetAsserter)
|
|
25
29
|
BuiltInAsserterFactory.register_asserter(ObjectAttributesAsserter)
|
|
@@ -5,6 +5,7 @@ import yaml
|
|
|
5
5
|
from yaml.constructor import ConstructorError
|
|
6
6
|
|
|
7
7
|
from panda_pytest_assertions.assert_object._expectation_modificators import (
|
|
8
|
+
IsType,
|
|
8
9
|
MappingSubset,
|
|
9
10
|
ObjectAttributes,
|
|
10
11
|
Stringified,
|
|
@@ -112,3 +113,32 @@ def _(loader: ExpectationYamlLoader, node: yaml.Node) -> WithType:
|
|
|
112
113
|
problem_mark=node.start_mark,
|
|
113
114
|
)
|
|
114
115
|
return WithType(node_data['expectation'], expected_type_name, expected_type_module)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
_IS_TYPE_KEYS = {'expected_type_name', 'expected_type_module'}
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
@ExpectationYamlLoader.add_construct('!IsType')
|
|
122
|
+
def _(loader: ExpectationYamlLoader, node: yaml.Node) -> IsType:
|
|
123
|
+
if not isinstance(node, yaml.MappingNode):
|
|
124
|
+
raise ConstructorError(
|
|
125
|
+
problem=f'expected a mapping node, but found {type(node)}',
|
|
126
|
+
problem_mark=node.start_mark,
|
|
127
|
+
)
|
|
128
|
+
node_data = loader.construct_mapping(node)
|
|
129
|
+
if node_data.keys() != _IS_TYPE_KEYS:
|
|
130
|
+
raise ConstructorError(
|
|
131
|
+
problem=f'IsType keys must be {_IS_TYPE_KEYS}',
|
|
132
|
+
problem_mark=node.start_mark,
|
|
133
|
+
)
|
|
134
|
+
if not isinstance(expected_type_name := node_data['expected_type_name'], str):
|
|
135
|
+
raise ConstructorError(
|
|
136
|
+
problem='value of IsType "expected_type_name" must be a string',
|
|
137
|
+
problem_mark=node.start_mark,
|
|
138
|
+
)
|
|
139
|
+
if not isinstance(expected_type_module := node_data['expected_type_module'], str | None):
|
|
140
|
+
raise ConstructorError(
|
|
141
|
+
problem='value of IsType "expected_type_module" must be a string or None',
|
|
142
|
+
problem_mark=node.start_mark,
|
|
143
|
+
)
|
|
144
|
+
return IsType(expected_type_name, expected_type_module)
|
|
@@ -5,6 +5,7 @@ from typing import Any, TypeVar
|
|
|
5
5
|
import yaml
|
|
6
6
|
|
|
7
7
|
from panda_pytest_assertions.assert_object._expectation_modificators import (
|
|
8
|
+
IsType,
|
|
8
9
|
MappingSubset,
|
|
9
10
|
ObjectAttributes,
|
|
10
11
|
Stringified,
|
|
@@ -72,6 +73,11 @@ def _with_type_representer(dumper: ExpectationYamlDumper, data: WithType) -> yam
|
|
|
72
73
|
return dumper.represent_mapping('!WithType', data.__dict__)
|
|
73
74
|
|
|
74
75
|
|
|
76
|
+
@ExpectationYamlDumper.add_repr(IsType)
|
|
77
|
+
def _(dumper: ExpectationYamlDumper, data: IsType) -> yaml.MappingNode:
|
|
78
|
+
return dumper.represent_mapping('!IsType', data.__dict__)
|
|
79
|
+
|
|
80
|
+
|
|
75
81
|
@ExpectationYamlDumper.add_repr(Enum, is_multi=True)
|
|
76
82
|
def _(dumper: ExpectationYamlDumper, data: Enum) -> yaml.Node:
|
|
77
83
|
expectation = with_type(type(data))(Stringified(str(data)))
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from .identity import Is
|
|
2
|
+
from .is_type import is_type, IsType
|
|
1
3
|
from .mapping_subset import MappingSubset
|
|
2
4
|
from .object_attibutes import ObjectAttributes
|
|
3
5
|
from .stringified import Stringified
|
|
@@ -6,6 +8,9 @@ from .with_type import with_type, WithType
|
|
|
6
8
|
|
|
7
9
|
|
|
8
10
|
__all__ = [
|
|
11
|
+
'Is',
|
|
12
|
+
'is_type',
|
|
13
|
+
'IsType',
|
|
9
14
|
'MappingSubset',
|
|
10
15
|
'ObjectAttributes',
|
|
11
16
|
'Stringified',
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Is:
|
|
5
|
+
"""
|
|
6
|
+
Wrapper for the expectation that describes object identity (compared with `is` operator).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def __init__(self, value: Any, /) -> None: # noqa: ANN401
|
|
10
|
+
#: expected object
|
|
11
|
+
self.value = value
|
|
12
|
+
|
|
13
|
+
def __repr__(self) -> str:
|
|
14
|
+
return f'Is({self.value!r})'
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
from typing import Any, overload
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class IsType:
|
|
5
|
+
"""
|
|
6
|
+
Wrapper for the expectation that checks object's type.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
expected_type_name: str,
|
|
12
|
+
expected_type_module: str | None,
|
|
13
|
+
/,
|
|
14
|
+
) -> None:
|
|
15
|
+
#: expected name of the object type
|
|
16
|
+
self.expected_type_name = expected_type_name
|
|
17
|
+
#: expected module of the object type
|
|
18
|
+
self.expected_type_module = expected_type_module
|
|
19
|
+
|
|
20
|
+
def __repr__(self) -> str:
|
|
21
|
+
return (
|
|
22
|
+
f'IsType('
|
|
23
|
+
f'expected_type_name={self.expected_type_name!r}, '
|
|
24
|
+
f'expected_type_module={self.expected_type_module!r}'
|
|
25
|
+
f')'
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@overload
|
|
30
|
+
def is_type(value_type: type[Any], /) -> IsType: # noqa: D418
|
|
31
|
+
"""
|
|
32
|
+
Create IsType expectation asserting object type.
|
|
33
|
+
|
|
34
|
+
Expected type name and type module will be extracted from the provided type.
|
|
35
|
+
|
|
36
|
+
:param value_type: type to extract expected type name and module from
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@overload
|
|
41
|
+
def is_type( # noqa: D418
|
|
42
|
+
value_type_name: str,
|
|
43
|
+
value_type_module: str | None = None,
|
|
44
|
+
/,
|
|
45
|
+
) -> IsType:
|
|
46
|
+
"""
|
|
47
|
+
Create IsType expectation asserting object type.
|
|
48
|
+
|
|
49
|
+
Expected type name will be equal to `value_type_name` and expected module name will be
|
|
50
|
+
equal to `value_type_module` (which can be not set if is not supposed to be asserted).
|
|
51
|
+
|
|
52
|
+
:param value_type_name: name of the expected type
|
|
53
|
+
:param value_type_module: module of the expected type
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def is_type(
|
|
58
|
+
value_type: type[Any] | str,
|
|
59
|
+
value_type_module: str | None = None,
|
|
60
|
+
/,
|
|
61
|
+
) -> IsType:
|
|
62
|
+
"""
|
|
63
|
+
Create IsType expectation asserting object type.
|
|
64
|
+
|
|
65
|
+
If `value_type` is a type, expected type name and type module will be extracted from this type.
|
|
66
|
+
|
|
67
|
+
If `value_type` is a string, expected type name will be equal to it and expected module name will be
|
|
68
|
+
equal to provided `value_type_module` (which can be not set if is not supposed to be asserted).
|
|
69
|
+
|
|
70
|
+
:param value_type: expected type or name of the type
|
|
71
|
+
:param value_type_module: expected type's module
|
|
72
|
+
:return: created expectation
|
|
73
|
+
"""
|
|
74
|
+
match value_type, value_type_module:
|
|
75
|
+
case str(), str() | None:
|
|
76
|
+
expected_type_name = value_type
|
|
77
|
+
expected_type_module = value_type_module
|
|
78
|
+
case type(), None:
|
|
79
|
+
expected_type_name = value_type.__name__
|
|
80
|
+
expected_type_module = value_type.__module__
|
|
81
|
+
case _:
|
|
82
|
+
msg = (
|
|
83
|
+
f'IsType helper constructor does not accept the following arguments: '
|
|
84
|
+
f'{(value_type, value_type_module)}'
|
|
85
|
+
)
|
|
86
|
+
raise ValueError(msg)
|
|
87
|
+
return IsType(
|
|
88
|
+
expected_type_name,
|
|
89
|
+
expected_type_module,
|
|
90
|
+
)
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
5
|
pytest.register_assert_rewrite(__name__ + '.equality_asserter')
|
|
6
|
+
pytest.register_assert_rewrite(__name__ + '.identity_asserter')
|
|
7
|
+
pytest.register_assert_rewrite(__name__ + '.is_type_asserter')
|
|
6
8
|
pytest.register_assert_rewrite(__name__ + '.mapping_asserter')
|
|
7
9
|
pytest.register_assert_rewrite(__name__ + '.mapping_subset_asserter')
|
|
8
10
|
pytest.register_assert_rewrite(__name__ + '.object_attributes_asserter')
|
|
@@ -14,6 +16,8 @@ pytest.register_assert_rewrite(__name__ + '.with_type_asserter')
|
|
|
14
16
|
|
|
15
17
|
from .asserter import Asserter
|
|
16
18
|
from .equality_asserter import EqualityAsserter
|
|
19
|
+
from .identity_asserter import IdentityAsserter
|
|
20
|
+
from .is_type_asserter import IsTypeAsserter
|
|
17
21
|
from .mapping_asserter import MappingAsserter
|
|
18
22
|
from .mapping_subset_asserter import MappingSubsetAsserter
|
|
19
23
|
from .object_attributes_asserter import ObjectAttributesAsserter
|
|
@@ -26,6 +30,8 @@ from .with_type_asserter import WithTypeAsserter
|
|
|
26
30
|
__all__ = [
|
|
27
31
|
'Asserter',
|
|
28
32
|
'EqualityAsserter',
|
|
33
|
+
'IdentityAsserter',
|
|
34
|
+
'IsTypeAsserter',
|
|
29
35
|
'MappingAsserter',
|
|
30
36
|
'MappingSubsetAsserter',
|
|
31
37
|
'ObjectAttributesAsserter',
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object._protocols import AsserterFactoryProtocol
|
|
4
|
+
|
|
5
|
+
from .._expectation_modificators import Is # noqa: TID252
|
|
6
|
+
from .asserter import Asserter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IdentityAsserter(Asserter):
|
|
10
|
+
"""
|
|
11
|
+
Assert that the object is identical to the expectation's value.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def matches(cls, expectation: Any) -> bool: # noqa: ANN401
|
|
16
|
+
"""
|
|
17
|
+
Decide whether provided expectation can be handled by this asserter.
|
|
18
|
+
|
|
19
|
+
This asserter can handle an Is expectation.
|
|
20
|
+
|
|
21
|
+
:param expectation: expectation to be tested
|
|
22
|
+
:return: whether expectation can be handled by this asserter
|
|
23
|
+
"""
|
|
24
|
+
return isinstance(expectation, Is)
|
|
25
|
+
|
|
26
|
+
def __init__(self, asserter_factory: type[AsserterFactoryProtocol], expectation: Is) -> None:
|
|
27
|
+
super().__init__(asserter_factory, expectation)
|
|
28
|
+
self.expected_object = expectation.value
|
|
29
|
+
|
|
30
|
+
def assert_object(self, object_: Any) -> None: # noqa: ANN401
|
|
31
|
+
"""
|
|
32
|
+
Assert if the expectation is fulfilled by an object.
|
|
33
|
+
|
|
34
|
+
:param object_: an object to be tested
|
|
35
|
+
"""
|
|
36
|
+
assert self.expected_object is object_
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object._protocols import AsserterFactoryProtocol
|
|
4
|
+
|
|
5
|
+
from .._expectation_modificators import IsType # noqa: TID252
|
|
6
|
+
from .asserter import Asserter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IsTypeAsserter(Asserter):
|
|
10
|
+
"""
|
|
11
|
+
Assert that the object is of a proper type.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def matches(cls, expectation: Any) -> bool: # noqa: ANN401
|
|
16
|
+
"""
|
|
17
|
+
Decide whether provided expectation can be handled by this asserter.
|
|
18
|
+
|
|
19
|
+
This asserter can handle a IsType expectation.
|
|
20
|
+
|
|
21
|
+
:param expectation: expectation to be tested
|
|
22
|
+
:return: whether expectation can be handled by this asserter
|
|
23
|
+
"""
|
|
24
|
+
return isinstance(expectation, IsType)
|
|
25
|
+
|
|
26
|
+
def __init__(self, asserter_factory: type[AsserterFactoryProtocol], expectation: IsType) -> None:
|
|
27
|
+
super().__init__(asserter_factory, expectation)
|
|
28
|
+
self.expected_type_name = expectation.expected_type_name
|
|
29
|
+
self.expected_type_module = expectation.expected_type_module
|
|
30
|
+
|
|
31
|
+
def assert_object(self, object_: Any) -> None: # noqa: ANN401
|
|
32
|
+
"""
|
|
33
|
+
Assert if the expectation is fulfilled by an object.
|
|
34
|
+
|
|
35
|
+
:param object_: an object to be tested
|
|
36
|
+
"""
|
|
37
|
+
if object_.__class__.__name__ != self.expected_type_name:
|
|
38
|
+
msg = (
|
|
39
|
+
f'Object type ("{type(object_)}") has invalid name. '
|
|
40
|
+
f'Expected "{self.expected_type_name}", got "{object_.__class__.__name__}".'
|
|
41
|
+
)
|
|
42
|
+
raise AssertionError(msg)
|
|
43
|
+
if (
|
|
44
|
+
self.expected_type_module is not None
|
|
45
|
+
and object_.__class__.__module__ != self.expected_type_module
|
|
46
|
+
):
|
|
47
|
+
msg = (
|
|
48
|
+
f'Object type ("{type(object_)}") is from invalid module. '
|
|
49
|
+
f'Expected "{self.expected_type_module}", got "{object_.__class__.__module__}".'
|
|
50
|
+
)
|
|
51
|
+
raise AssertionError(msg)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from ._expectation_definitions import (
|
|
2
2
|
EqualityDef,
|
|
3
|
+
IsTypeDef,
|
|
3
4
|
MappingDef,
|
|
4
5
|
MappingSubsetDef,
|
|
5
6
|
ObjectAttributesDef,
|
|
@@ -21,6 +22,7 @@ from ._generators import Generator
|
|
|
21
22
|
|
|
22
23
|
__all__ = [
|
|
23
24
|
'EqualityDef',
|
|
25
|
+
'IsTypeDef',
|
|
24
26
|
'MappingDef',
|
|
25
27
|
'MappingSubsetDef',
|
|
26
28
|
'ObjectAttributesDef',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from .equality import EqualityDef
|
|
2
|
+
from .is_type import IsTypeDef
|
|
2
3
|
from .mapping import MappingDef
|
|
3
4
|
from .mapping_subset import MappingSubsetDef
|
|
4
5
|
from .object_attributes import ObjectAttributesDef
|
|
@@ -14,6 +15,7 @@ from .with_type import with_type_def, WithTypeDef
|
|
|
14
15
|
|
|
15
16
|
__all__ = [
|
|
16
17
|
'EqualityDef',
|
|
18
|
+
'IsTypeDef',
|
|
17
19
|
'MappingDef',
|
|
18
20
|
'MappingSubsetDef',
|
|
19
21
|
'ObjectAttributesDef',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .._generators import ( # noqa: TID252
|
|
2
2
|
EqualityGenerator,
|
|
3
3
|
EqualityKeyMappingGenerator,
|
|
4
|
+
IsTypeGenerator,
|
|
4
5
|
MappingGenerator,
|
|
5
6
|
MappingSubsetGenerator,
|
|
6
7
|
ObjectAttributesGenerator,
|
|
@@ -25,6 +26,7 @@ class BuiltInGeneratorFactory(GeneratorFactory):
|
|
|
25
26
|
|
|
26
27
|
BuiltInGeneratorFactory.register_generator(EqualityGenerator)
|
|
27
28
|
BuiltInGeneratorFactory.register_generator(EqualityKeyMappingGenerator)
|
|
29
|
+
BuiltInGeneratorFactory.register_generator(IsTypeGenerator)
|
|
28
30
|
BuiltInGeneratorFactory.register_generator(MappingGenerator)
|
|
29
31
|
BuiltInGeneratorFactory.register_generator(MappingSubsetGenerator)
|
|
30
32
|
BuiltInGeneratorFactory.register_generator(ObjectAttributesGenerator)
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from .equality_generator import EqualityGenerator
|
|
2
2
|
from .equality_key_mapping_generator import EqualityKeyMappingGenerator
|
|
3
3
|
from .generator import Generator
|
|
4
|
+
from .is_type_generator import IsTypeGenerator
|
|
4
5
|
from .mapping_generator import MappingGenerator
|
|
5
6
|
from .mapping_subset_generator import MappingSubsetGenerator
|
|
6
7
|
from .object_attributes_generator import ObjectAttributesGenerator
|
|
@@ -17,6 +18,7 @@ from .with_type_generator import WithTypeGenerator
|
|
|
17
18
|
|
|
18
19
|
__all__ = [
|
|
19
20
|
'Generator',
|
|
21
|
+
'IsTypeGenerator',
|
|
20
22
|
'EqualityGenerator',
|
|
21
23
|
'EqualityKeyMappingGenerator',
|
|
22
24
|
'MappingGenerator',
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, IsType
|
|
4
|
+
|
|
5
|
+
from .._expectation_definitions import IsTypeDef # noqa: TID252
|
|
6
|
+
from .generator import Generator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IsTypeGenerator(Generator):
|
|
10
|
+
"""
|
|
11
|
+
Generates IsType expectation.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
16
|
+
"""
|
|
17
|
+
Decide whether provided definiton can be handled by this generator.
|
|
18
|
+
|
|
19
|
+
This generator can handle IsTypeDef definition.
|
|
20
|
+
|
|
21
|
+
:param definition: definition to be tested
|
|
22
|
+
:return: whether definition can be handled by this generator
|
|
23
|
+
"""
|
|
24
|
+
return isinstance(definition, IsTypeDef)
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
29
|
+
definition: IsTypeDef,
|
|
30
|
+
) -> None:
|
|
31
|
+
super().__init__(generator_factory, definition)
|
|
32
|
+
self.include_module = definition.include_module
|
|
33
|
+
|
|
34
|
+
def generate_expectation(self, object_: Any) -> IsType: # noqa: ANN401
|
|
35
|
+
"""
|
|
36
|
+
Generate expectation from given object.
|
|
37
|
+
|
|
38
|
+
:param object_: an object to generate expectation from
|
|
39
|
+
:return: generated expectation
|
|
40
|
+
"""
|
|
41
|
+
return IsType(
|
|
42
|
+
object_.__class__.__name__,
|
|
43
|
+
object_.__class__.__module__ if self.include_module else None,
|
|
44
|
+
)
|
|
File without changes
|
|
File without changes
|
{panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{panda_pytest_assertions-0.1.1 → panda_pytest_assertions-0.2.1}/panda_pytest_assertions/py.typed
RENAMED
|
File without changes
|