panda-pytest-assertions 0.1.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.
- panda_pytest_assertions/__init__.py +0 -0
- panda_pytest_assertions/assert_context/__init__.py +15 -0
- panda_pytest_assertions/assert_context/_assert_context.py +128 -0
- panda_pytest_assertions/assert_object/__init__.py +41 -0
- panda_pytest_assertions/assert_object/_assert_object.py +36 -0
- panda_pytest_assertions/assert_object/_asserter_factories/__init__.py +8 -0
- panda_pytest_assertions/assert_object/_asserter_factories/asserter_factory.py +66 -0
- panda_pytest_assertions/assert_object/_asserter_factories/built_in_asserter_factory.py +29 -0
- panda_pytest_assertions/assert_object/_converters/__init__.py +10 -0
- panda_pytest_assertions/assert_object/_converters/expectation_from_yaml.py +114 -0
- panda_pytest_assertions/assert_object/_converters/expectation_to_yaml.py +78 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/__init__.py +15 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/mapping_subset.py +15 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/object_attibutes.py +15 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/stringified.py +11 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/unordered.py +18 -0
- panda_pytest_assertions/assert_object/_expectation_modificators/with_type.py +135 -0
- panda_pytest_assertions/assert_object/_objects_asserters/__init__.py +36 -0
- panda_pytest_assertions/assert_object/_objects_asserters/asserter.py +35 -0
- panda_pytest_assertions/assert_object/_objects_asserters/equality_asserter.py +33 -0
- panda_pytest_assertions/assert_object/_objects_asserters/mapping_asserter.py +55 -0
- panda_pytest_assertions/assert_object/_objects_asserters/mapping_subset_asserter.py +53 -0
- panda_pytest_assertions/assert_object/_objects_asserters/object_attributes_asserter.py +52 -0
- panda_pytest_assertions/assert_object/_objects_asserters/ordered_elements_asserter.py +55 -0
- panda_pytest_assertions/assert_object/_objects_asserters/stringified_asserter.py +36 -0
- panda_pytest_assertions/assert_object/_objects_asserters/unordered_elements_asserter.py +77 -0
- panda_pytest_assertions/assert_object/_objects_asserters/with_type_asserter.py +57 -0
- panda_pytest_assertions/assert_object/_protocols.py +93 -0
- panda_pytest_assertions/assert_object/generators/__init__.py +41 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/__init__.py +30 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/equality.py +6 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/mapping.py +14 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/mapping_subset.py +14 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/object_attributes.py +12 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/of_type.py +13 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/stringified.py +4 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_mapping.py +13 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_mapping_subset.py +13 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_ordered.py +39 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/uniform_unordered.py +11 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/union.py +13 -0
- panda_pytest_assertions/assert_object/generators/_expectation_definitions/with_type.py +30 -0
- panda_pytest_assertions/assert_object/generators/_generate_expectation.py +23 -0
- panda_pytest_assertions/assert_object/generators/_generator_factories/__init__.py +8 -0
- panda_pytest_assertions/assert_object/generators/_generator_factories/built_in_generator_factory.py +39 -0
- panda_pytest_assertions/assert_object/generators/_generator_factories/generator_factory.py +66 -0
- panda_pytest_assertions/assert_object/generators/_generators/__init__.py +34 -0
- panda_pytest_assertions/assert_object/generators/_generators/equality_generator.py +35 -0
- panda_pytest_assertions/assert_object/generators/_generators/equality_key_mapping_generator.py +54 -0
- panda_pytest_assertions/assert_object/generators/_generators/exceptions.py +1 -0
- panda_pytest_assertions/assert_object/generators/_generators/generator.py +35 -0
- panda_pytest_assertions/assert_object/generators/_generators/mapping_generator.py +60 -0
- panda_pytest_assertions/assert_object/generators/_generators/mapping_subset_generator.py +57 -0
- panda_pytest_assertions/assert_object/generators/_generators/object_attributes_generator.py +53 -0
- panda_pytest_assertions/assert_object/generators/_generators/of_type_generator.py +47 -0
- panda_pytest_assertions/assert_object/generators/_generators/ordered_generator.py +55 -0
- panda_pytest_assertions/assert_object/generators/_generators/stringified_generator.py +35 -0
- panda_pytest_assertions/assert_object/generators/_generators/uniform_mapping_generator.py +50 -0
- panda_pytest_assertions/assert_object/generators/_generators/uniform_mapping_subset_generator.py +52 -0
- panda_pytest_assertions/assert_object/generators/_generators/uniform_ordered_generator.py +49 -0
- panda_pytest_assertions/assert_object/generators/_generators/union_generator.py +51 -0
- panda_pytest_assertions/assert_object/generators/_generators/unordered_generator.py +46 -0
- panda_pytest_assertions/assert_object/generators/_generators/with_type_generator.py +46 -0
- panda_pytest_assertions/py.typed +0 -0
- panda_pytest_assertions-0.1.0.dist-info/LICENSE +201 -0
- panda_pytest_assertions-0.1.0.dist-info/METADATA +32 -0
- panda_pytest_assertions-0.1.0.dist-info/RECORD +68 -0
- panda_pytest_assertions-0.1.0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import MappingDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MappingGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates Mapping expectation.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle MappingDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, MappingDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: MappingDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.keys_generator = generator_factory.create(definition.keys_definition)
|
|
35
|
+
self.items_generators = {
|
|
36
|
+
key: generator_factory.create(value) for key, value in definition.items_definitions.items()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def generate_expectation(self, object_: Any) -> Mapping[Any, Any]: # noqa: ANN401
|
|
40
|
+
"""
|
|
41
|
+
Generate expectation from given object.
|
|
42
|
+
|
|
43
|
+
:param object_: an object to generate expectation from
|
|
44
|
+
:return: generated expectation
|
|
45
|
+
"""
|
|
46
|
+
if not isinstance(object_, Mapping):
|
|
47
|
+
msg = f'Expected mapping, got {type(object_)}'
|
|
48
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
49
|
+
if object_.keys() != self.items_generators.keys():
|
|
50
|
+
msg = (
|
|
51
|
+
f'Object has invalid keys. '
|
|
52
|
+
f'Expected: {set(self.items_generators.keys())}, got {set(object_.keys())}.'
|
|
53
|
+
)
|
|
54
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
55
|
+
expectation = {}
|
|
56
|
+
for key, value_generator in self.items_generators.items():
|
|
57
|
+
key_expectation = self.keys_generator.generate_expectation(key)
|
|
58
|
+
value_expectation = value_generator.generate_expectation(object_[key])
|
|
59
|
+
expectation[key_expectation] = value_expectation
|
|
60
|
+
return expectation
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, MappingSubset
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import MappingSubsetDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class MappingSubsetGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates MappingSubset expectation.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle MappingSubsetDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, MappingSubsetDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: MappingSubsetDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.keys_generator = generator_factory.create(definition.keys_definition)
|
|
35
|
+
self.items_generators = {
|
|
36
|
+
key: generator_factory.create(value) for key, value in definition.items_definitions.items()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
def generate_expectation(self, object_: Any) -> MappingSubset: # noqa: ANN401
|
|
40
|
+
"""
|
|
41
|
+
Generate expectation from given object.
|
|
42
|
+
|
|
43
|
+
:param object_: an object to generate expectation from
|
|
44
|
+
:return: generated expectation
|
|
45
|
+
"""
|
|
46
|
+
if not isinstance(object_, Mapping):
|
|
47
|
+
msg = f'Expected mapping, got {type(object_)}'
|
|
48
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
49
|
+
items_expectations = {}
|
|
50
|
+
for key, value_generator in self.items_generators.items():
|
|
51
|
+
if key not in object_:
|
|
52
|
+
msg = f'"{object_}" does not contain a key "{key}"'
|
|
53
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
54
|
+
key_expectation = self.keys_generator.generate_expectation(key)
|
|
55
|
+
value_expectation = value_generator.generate_expectation(object_[key])
|
|
56
|
+
items_expectations[key_expectation] = value_expectation
|
|
57
|
+
return MappingSubset(items_expectations)
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, ObjectAttributes
|
|
4
|
+
|
|
5
|
+
from .._expectation_definitions import ObjectAttributesDef # noqa: TID252
|
|
6
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
7
|
+
from .generator import Generator
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ObjectAttributesGenerator(Generator):
|
|
11
|
+
"""
|
|
12
|
+
Generates ObjectAttributes expectation.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
17
|
+
"""
|
|
18
|
+
Decide whether provided definiton can be handled by this generator.
|
|
19
|
+
|
|
20
|
+
This generator can handle ObjectAttributesDef definition.
|
|
21
|
+
|
|
22
|
+
:param definition: definition to be tested
|
|
23
|
+
:return: whether definition can be handled by this generator
|
|
24
|
+
"""
|
|
25
|
+
return isinstance(definition, ObjectAttributesDef)
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
30
|
+
definition: ObjectAttributesDef,
|
|
31
|
+
) -> None:
|
|
32
|
+
super().__init__(generator_factory, definition)
|
|
33
|
+
self.attributes_generators = {
|
|
34
|
+
attr_name: generator_factory.create(attr_definition)
|
|
35
|
+
for attr_name, attr_definition in definition.attributes_definitions.items()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
def generate_expectation(self, object_: Any) -> ObjectAttributes: # noqa: ANN401
|
|
39
|
+
"""
|
|
40
|
+
Generate expectation from given object.
|
|
41
|
+
|
|
42
|
+
:param object_: an object to generate expectation from
|
|
43
|
+
:return: generated expectation
|
|
44
|
+
"""
|
|
45
|
+
attributes_expectations = {}
|
|
46
|
+
for attr_name, attr_generator in self.attributes_generators.items():
|
|
47
|
+
if not hasattr(object_, attr_name):
|
|
48
|
+
msg = f'"{object_}" does not have an attribute names "{attr_name}"'
|
|
49
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
50
|
+
attributes_expectations[attr_name] = attr_generator.generate_expectation(
|
|
51
|
+
getattr(object_, attr_name),
|
|
52
|
+
)
|
|
53
|
+
return ObjectAttributes(attributes_expectations)
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from types import NoneType
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import OfTypeDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class OfTypeGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates custom expectation, but only if the object is of a correct type.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle OfTypeDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, OfTypeDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: OfTypeDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.object_generator = generator_factory.create(definition.object_definition)
|
|
35
|
+
self.expected_type = definition.expected_type if definition.expected_type is not None else NoneType
|
|
36
|
+
|
|
37
|
+
def generate_expectation(self, object_: Any) -> Any: # noqa: ANN401
|
|
38
|
+
"""
|
|
39
|
+
Generate expectation from given object.
|
|
40
|
+
|
|
41
|
+
:param object_: an object to generate expectation from
|
|
42
|
+
:return: generated expectation
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(object_, self.expected_type):
|
|
45
|
+
msg = f'Object is expected to be "{self.expected_type}" type. Got "{type(object_)}".'
|
|
46
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
47
|
+
return self.object_generator.generate_expectation(object_)
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
5
|
+
|
|
6
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
7
|
+
from .generator import Generator
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class OrderedGenerator(Generator):
|
|
11
|
+
"""
|
|
12
|
+
Generates ordered collection expectation.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
17
|
+
"""
|
|
18
|
+
Decide whether provided definiton can be handled by this generator.
|
|
19
|
+
|
|
20
|
+
This generator can handle any list or tuple definition.
|
|
21
|
+
|
|
22
|
+
:param definition: definition to be tested
|
|
23
|
+
:return: whether definition can be handled by this generator
|
|
24
|
+
"""
|
|
25
|
+
return isinstance(definition, list | tuple)
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
30
|
+
definition: list[Any] | tuple[Any, ...],
|
|
31
|
+
) -> None:
|
|
32
|
+
super().__init__(generator_factory, definition)
|
|
33
|
+
self.elements_generators = [generator_factory.create(element) for element in definition]
|
|
34
|
+
self.expectation_type = type(definition)
|
|
35
|
+
|
|
36
|
+
def generate_expectation(self, object_: Any) -> list[Any] | tuple[Any, ...]: # noqa: ANN401
|
|
37
|
+
"""
|
|
38
|
+
Generate expectation from given object.
|
|
39
|
+
|
|
40
|
+
:param object_: an object to generate expectation from
|
|
41
|
+
:return: generated expectation
|
|
42
|
+
"""
|
|
43
|
+
if not isinstance(object_, Iterable):
|
|
44
|
+
msg = f'Expected iterale, got {type(object_)}'
|
|
45
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
46
|
+
elements = list(object_)
|
|
47
|
+
if len(elements) != len(self.elements_generators):
|
|
48
|
+
msg = (
|
|
49
|
+
f'Object has incorrect lenght. Expected {len(self.elements_generators)}, got {len(elements)}.'
|
|
50
|
+
)
|
|
51
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
52
|
+
return self.expectation_type(
|
|
53
|
+
generator.generate_expectation(element)
|
|
54
|
+
for element, generator in zip(elements, self.elements_generators, strict=True)
|
|
55
|
+
)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object import Stringified
|
|
4
|
+
|
|
5
|
+
from .._expectation_definitions import StringifiedDef # noqa: TID252
|
|
6
|
+
from .generator import Generator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class StringifiedGenerator(Generator):
|
|
10
|
+
"""
|
|
11
|
+
Generates Stringified expectation from the object.
|
|
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 StringifiedDef definition.
|
|
20
|
+
|
|
21
|
+
:param definition: definition to be tested
|
|
22
|
+
:return: whether definition can be handled by this generator
|
|
23
|
+
"""
|
|
24
|
+
return isinstance(definition, StringifiedDef) or (
|
|
25
|
+
isinstance(definition, type) and issubclass(definition, StringifiedDef)
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
def generate_expectation(self, object_: Any) -> Any: # noqa: ANN401
|
|
29
|
+
"""
|
|
30
|
+
Generate Stringified expectation from given object.
|
|
31
|
+
|
|
32
|
+
:param object_: an object to generate expectation from
|
|
33
|
+
:return: generated expectation
|
|
34
|
+
"""
|
|
35
|
+
return Stringified(str(object_))
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import UniformMappingDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UniformMappingGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates mapping expectation using the same definition for each value.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle UniformMappingDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, UniformMappingDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: UniformMappingDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.keys_generator = generator_factory.create(definition.keys_definition)
|
|
35
|
+
self.values_generator = generator_factory.create(definition.values_definition)
|
|
36
|
+
|
|
37
|
+
def generate_expectation(self, object_: Any) -> Mapping[Any, Any]: # noqa: ANN401
|
|
38
|
+
"""
|
|
39
|
+
Generate expectation from given object.
|
|
40
|
+
|
|
41
|
+
:param object_: an object to generate expectation from
|
|
42
|
+
:return: generated expectation
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(object_, Mapping):
|
|
45
|
+
msg = f'Expected mapping, got {type(object_)}'
|
|
46
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
47
|
+
return {
|
|
48
|
+
self.keys_generator.generate_expectation(key): self.values_generator.generate_expectation(value)
|
|
49
|
+
for key, value in object_.items()
|
|
50
|
+
}
|
panda_pytest_assertions/assert_object/generators/_generators/uniform_mapping_subset_generator.py
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from collections.abc import Mapping
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, MappingSubset
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import UniformMappingSubsetDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UniformMappingSubsetGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates MappingSubset expectation using the same definition for each value.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle UniformMappingSubsetDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, UniformMappingSubsetDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: UniformMappingSubsetDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.keys_generator = generator_factory.create(definition.keys_definition)
|
|
35
|
+
self.values_generator = generator_factory.create(definition.values_definition)
|
|
36
|
+
|
|
37
|
+
def generate_expectation(self, object_: Any) -> MappingSubset: # noqa: ANN401
|
|
38
|
+
"""
|
|
39
|
+
Generate expectation from given object.
|
|
40
|
+
|
|
41
|
+
:param object_: an object to generate expectation from
|
|
42
|
+
:return: generated expectation
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(object_, Mapping):
|
|
45
|
+
msg = f'Expected mapping, got {type(object_)}'
|
|
46
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
47
|
+
items_expectations = {}
|
|
48
|
+
for key, value in object_.items():
|
|
49
|
+
key_expectation = self.keys_generator.generate_expectation(key)
|
|
50
|
+
value_expectation = self.values_generator.generate_expectation(value)
|
|
51
|
+
items_expectations[key_expectation] = value_expectation
|
|
52
|
+
return MappingSubset(items_expectations)
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import UniformOrderedDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UniformOrderedGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates ordered collection expectation using the same definition for each element.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle OrderedDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, UniformOrderedDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: UniformOrderedDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.elements_generator = generator_factory.create(definition.elements_definition)
|
|
35
|
+
self.expectation_type = definition.expectation_type
|
|
36
|
+
|
|
37
|
+
def generate_expectation(self, object_: Any) -> list[Any] | tuple[Any, ...]: # noqa: ANN401
|
|
38
|
+
"""
|
|
39
|
+
Generate expectation from given object.
|
|
40
|
+
|
|
41
|
+
:param object_: an object to generate expectation from
|
|
42
|
+
:return: generated expectation
|
|
43
|
+
"""
|
|
44
|
+
if not isinstance(object_, Iterable):
|
|
45
|
+
msg = f'Expected iterale, got {type(object_)}'
|
|
46
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
47
|
+
return self.expectation_type(
|
|
48
|
+
self.elements_generator.generate_expectation(element) for element in object_
|
|
49
|
+
)
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol
|
|
4
|
+
|
|
5
|
+
from .._expectation_definitions import UnionDef # noqa: TID252
|
|
6
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
7
|
+
from .generator import Generator
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class UnionGenerator(Generator):
|
|
11
|
+
"""
|
|
12
|
+
Generates expectation using the first definition that matches the value.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
@classmethod
|
|
16
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
17
|
+
"""
|
|
18
|
+
Decide whether provided definiton can be handled by this generator.
|
|
19
|
+
|
|
20
|
+
This generator can handle UniformMappingDef definition.
|
|
21
|
+
|
|
22
|
+
:param definition: definition to be tested
|
|
23
|
+
:return: whether definition can be handled by this generator
|
|
24
|
+
"""
|
|
25
|
+
return isinstance(definition, UnionDef)
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
30
|
+
definition: UnionDef,
|
|
31
|
+
) -> None:
|
|
32
|
+
super().__init__(generator_factory, definition)
|
|
33
|
+
self.generators = tuple(
|
|
34
|
+
generator_factory.create(single_definition) for single_definition in definition.definitions
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
def generate_expectation(self, object_: Any) -> Any: # noqa: ANN401
|
|
38
|
+
"""
|
|
39
|
+
Generate expectation from given object.
|
|
40
|
+
|
|
41
|
+
:param object_: an object to generate expectation from
|
|
42
|
+
:return: generated expectation
|
|
43
|
+
"""
|
|
44
|
+
exceptions = []
|
|
45
|
+
for generator in self.generators:
|
|
46
|
+
try:
|
|
47
|
+
return generator.generate_expectation(object_)
|
|
48
|
+
except ObjectNotMatchingDefinitionError as exc:
|
|
49
|
+
exceptions.append(exc)
|
|
50
|
+
msg = f'Object "{object_}" did not match any of the expectation definition. Errors: {exceptions!r}'
|
|
51
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from collections.abc import Iterable
|
|
2
|
+
from typing import Any
|
|
3
|
+
|
|
4
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, Unordered
|
|
5
|
+
|
|
6
|
+
from .._expectation_definitions import UniformUnorderedDef # noqa: TID252
|
|
7
|
+
from .exceptions import ObjectNotMatchingDefinitionError
|
|
8
|
+
from .generator import Generator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UnorderedGenerator(Generator):
|
|
12
|
+
"""
|
|
13
|
+
Generates unordered collection expectation.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
@classmethod
|
|
17
|
+
def matches(cls, definition: Any) -> bool: # noqa: ANN401
|
|
18
|
+
"""
|
|
19
|
+
Decide whether provided definiton can be handled by this generator.
|
|
20
|
+
|
|
21
|
+
This generator can handle UniformUnorderedDef definition.
|
|
22
|
+
|
|
23
|
+
:param definition: definition to be tested
|
|
24
|
+
:return: whether definition can be handled by this generator
|
|
25
|
+
"""
|
|
26
|
+
return isinstance(definition, UniformUnorderedDef)
|
|
27
|
+
|
|
28
|
+
def __init__(
|
|
29
|
+
self,
|
|
30
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
31
|
+
definition: UniformUnorderedDef,
|
|
32
|
+
) -> None:
|
|
33
|
+
super().__init__(generator_factory, definition)
|
|
34
|
+
self.elements_generator = generator_factory.create(definition.elements_definition)
|
|
35
|
+
|
|
36
|
+
def generate_expectation(self, object_: Any) -> Unordered: # noqa: ANN401
|
|
37
|
+
"""
|
|
38
|
+
Generate expectation from given object.
|
|
39
|
+
|
|
40
|
+
:param object_: an object to generate expectation from
|
|
41
|
+
:return: generated expectation
|
|
42
|
+
"""
|
|
43
|
+
if not isinstance(object_, Iterable):
|
|
44
|
+
msg = f'Expected iterale, got {type(object_)}'
|
|
45
|
+
raise ObjectNotMatchingDefinitionError(msg)
|
|
46
|
+
return Unordered([self.elements_generator.generate_expectation(element) for element in object_])
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from panda_pytest_assertions.assert_object import GeneratorFactoryProtocol, WithType
|
|
4
|
+
|
|
5
|
+
from .._expectation_definitions import WithTypeDef # noqa: TID252
|
|
6
|
+
from .generator import Generator
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class WithTypeGenerator(Generator):
|
|
10
|
+
"""
|
|
11
|
+
Generates WithType 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 WithTypeDef definition.
|
|
20
|
+
|
|
21
|
+
:param definition: definition to be tested
|
|
22
|
+
:return: whether definition can be handled by this generator
|
|
23
|
+
"""
|
|
24
|
+
return isinstance(definition, WithTypeDef)
|
|
25
|
+
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
generator_factory: type[GeneratorFactoryProtocol],
|
|
29
|
+
definition: WithTypeDef,
|
|
30
|
+
) -> None:
|
|
31
|
+
super().__init__(generator_factory, definition)
|
|
32
|
+
self.object_generator = generator_factory.create(definition.object_definition)
|
|
33
|
+
self.include_module = definition.include_module
|
|
34
|
+
|
|
35
|
+
def generate_expectation(self, object_: Any) -> WithType: # noqa: ANN401
|
|
36
|
+
"""
|
|
37
|
+
Generate expectation from given object.
|
|
38
|
+
|
|
39
|
+
:param object_: an object to generate expectation from
|
|
40
|
+
:return: generated expectation
|
|
41
|
+
"""
|
|
42
|
+
return WithType(
|
|
43
|
+
self.object_generator.generate_expectation(object_),
|
|
44
|
+
object_.__class__.__name__,
|
|
45
|
+
object_.__class__.__module__ if self.include_module else None,
|
|
46
|
+
)
|
|
File without changes
|