22EnumerationMother module.
33"""
44
5+ from abc import ABC
56from datetime import date , datetime
67from enum import Enum
8+ from inspect import isclass
79from random import choice
8- from typing import Any , Generic , Iterable , TypeVar
10+ from sys import version_info
11+ from typing import Any , Generic , Iterable , TypeVar , get_args , get_origin
912from uuid import UUID , uuid4
1013
14+ if version_info >= (3 , 12 ):
15+ from typing import override # pragma: no cover
16+ else :
17+ from typing_extensions import override # pragma: no cover
18+
1119from faker import Faker
1220
1321E = TypeVar ('E' , bound = Enum )
1422
1523
16- class EnumerationMother (Generic [E ]):
24+ class EnumerationMother (ABC , Generic [E ]):
1725 """
1826 EnumerationMother class is responsible for creating random enum values.
1927
@@ -33,7 +41,11 @@ class ColorEnumeration(Enum):
3341 BLUE = 3
3442
3543
36- color_mother = EnumerationMother(enumeration=ColorEnumeration)
44+ class ColorMother(EnumerationMother[ColorEnumeration]):
45+ pass
46+
47+
48+ color_mother = ColorMother()
3749
3850 color = color_mother.create()
3951 print(color)
@@ -43,43 +55,34 @@ class ColorEnumeration(Enum):
4355
4456 _enumeration : type [E ]
4557
46- def __init__ (self , * , enumeration : type [E ]) -> None :
58+ @override
59+ def __init_subclass__ (cls , ** kwargs : Any ) -> None :
4760 """
48- Initialize the EnumerationMother with the specified enumeration class `enumeration` .
61+ Initializes the class.
4962
5063 Args:
51- enumeration (type[E] ): The enumeration class to generate values from .
64+ **kwargs (Any ): Keyword arguments .
5265
5366 Raises:
54- TypeError: If the provided `enumeration` is not a subclass of Enum.
55-
56- Example:
57- ```python
58- from enum import Enum, unique
59-
60- from object_mother_pattern.mothers import EnumerationMother
61-
62-
63- @unique
64- class ColorEnumeration(Enum):
65- RED = 1
66- GREEN = 2
67- BLUE = 3
67+ TypeError: If the class parameter is not an Enum subclass.
68+ TypeError: If the class is not parameterized.
69+ """
70+ super ().__init_subclass__ (** kwargs )
6871
72+ for base in getattr (cls , '__orig_bases__' , ()):
73+ if get_origin (tp = base ) is EnumerationMother :
74+ enumeration , * _ = get_args (tp = base )
6975
70- color_mother = EnumerationMother(enumeration=ColorEnumeration)
76+ if not (isclass (object = enumeration ) and issubclass (enumeration , Enum )):
77+ raise TypeError (f'EnumerationMother[...] <<<{ enumeration } >>> must be an Enum subclass. Got <<<{ type (enumeration ).__name__ } >>> type.' ) # noqa: E501 # fmt: skip
7178
72- color = color_mother.create()
73- print(color)
74- # >>> Color.GREEN
75- ```
76- """
77- if type (enumeration ) is not type (Enum ):
78- raise TypeError ('EnumerationMother enumeration must be a subclass of Enum.' )
79+ cls ._enumeration = enumeration
80+ return
7981
80- self . _enumeration = enumeration
82+ raise TypeError ( 'EnumerationMother must be parameterized, e.g. "class ColorMother(EnumerationMother[ColorEnumeration])".' ) # noqa: E501 # fmt: skip
8183
82- def create (self , * , value : E | None = None ) -> E :
84+ @classmethod
85+ def create (cls , * , value : E | None = None ) -> E :
8386 """
8487 Create a random enumeration value from the enumeration class. If a specific
8588 value is provided, it is returned after ensuring it is a member of the enumeration.
@@ -107,20 +110,24 @@ class ColorEnumeration(Enum):
107110 BLUE = 3
108111
109112
110- color_mother = EnumerationMother(enumeration=ColorEnumeration)
113+ class ColorMother(EnumerationMother[ColorEnumeration]):
114+ pass
115+
116+
117+ color_mother = ColorMother()
111118
112119 color = color_mother.create()
113120 print(color)
114121 # >>> Color.GREEN
115122 ```
116123 """
117124 if value is not None :
118- if type (value ) is not self ._enumeration :
119- raise TypeError (f'{ self ._enumeration .__name__ } Mother value must be an instance of { self ._enumeration .__name__ } .' ) # noqa: E501 # fmt: skip
125+ if not isinstance (value , cls ._enumeration ) :
126+ raise TypeError (f'{ cls ._enumeration .__name__ } Mother value must be an instance of <<< { cls ._enumeration .__name__ } >>> type .' ) # noqa: E501 # fmt: skip
120127
121- return value
128+ return value # type: ignore[no-any-return]
122129
123- return choice (seq = tuple (self ._enumeration )) # noqa: S311
130+ return choice (seq = tuple (cls ._enumeration )) # type: ignore[arg-type] # noqa: S311
124131
125132 @staticmethod
126133 def invalid_type (remove_types : Iterable [type [Any ]] | None = None ) -> Any : # noqa: C901
0 commit comments