type_enforced.utils

  1import types, re, copy
  2from functools import update_wrapper
  3from typing import Union
  4
  5
  6class Partial:
  7    """
  8    A special class wrapper to allow for easy partial function wrappings and calls.
  9    """
 10
 11    def __init__(
 12        self,
 13        __fn__,
 14        *__args__,
 15        **__kwargs__,
 16    ):
 17        update_wrapper(self, __fn__)
 18        self.__fn__ = __fn__
 19        self.__args__ = __args__
 20        self.__kwargs__ = __kwargs__
 21        self.__fnArity__ = self.__getFnArity__()
 22        self.__arity__ = self.__getArity__(__args__, __kwargs__)
 23        self.__get_fn_arg_default_keys__()
 24
 25    def __exception__(self, message):
 26        pre_message = (
 27            f"({self.__fn__.__module__}.{self.__fn__.__qualname__}_partial): "
 28        )
 29        raise Exception(pre_message + message)
 30
 31    def __call__(self, *args, **kwargs):
 32        new_args = self.__args__ + args
 33        new_kwargs = {**self.__kwargs__, **kwargs}
 34        # Create a comprehensive set of assigned variable names to determine arity
 35        assigned_vars = set(
 36            self.__fn_arg_default_keys__
 37            + self.__fn_arg_keys__[: len(new_args)]
 38            + list(new_kwargs.keys())
 39        )
 40        arity = self.__fnArity__ - len(assigned_vars)
 41        if arity < 0:
 42            self.__exception__("Too many arguments were supplied")
 43        if arity == 0:
 44            results = self.__fn__(*new_args, **new_kwargs)
 45            return results
 46        return Partial(
 47            self.__fn__,
 48            *new_args,
 49            **new_kwargs,
 50        )
 51
 52    def __get_fn_arg_default_keys__(self):
 53        """
 54        Get the default values of the passed function or method and store them in `self.__fn_defaults__`.
 55        """
 56        self.__fn_var_keys__ = list(self.__fn__.__code__.co_varnames)
 57        self.__fn_arg_keys__ = self.__fn_var_keys__[
 58            : self.__fn__.__code__.co_argcount
 59        ]
 60        if self.__fn__.__defaults__ is not None:
 61            self.__fn_arg_default_keys__ = self.__fn_arg_keys__[
 62                -len(self.__fn__.__defaults__) :
 63            ]
 64        else:
 65            self.__fn_arg_default_keys__ = []
 66        if self.__fn__.__kwdefaults__ is not None:
 67            self.__fn_arg_default_keys__.extend(
 68                list(self.__fn__.__kwdefaults__.keys())
 69            )
 70
 71    def __get__(self, instance, owner):
 72        def bind(*args, **kwargs):
 73            if instance is not None and self.__arity__ == self.__fnArity__:
 74                return self.__call__(instance, *args, **kwargs)
 75            else:
 76                return self.__call__(*args, **kwargs)
 77
 78        return bind
 79
 80    def __repr__(self):
 81        return f"<Partial {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>"
 82
 83    def __getArity__(self, args, kwargs):
 84        return self.__fnArity__ - (len(args) + len(kwargs))
 85
 86    def __getFnArity__(self):
 87        if not isinstance(self.__fn__, (types.MethodType, types.FunctionType)):
 88            self.__exception__(
 89                "A non function was passed as a function and does not have any arity. See the stack trace above for more information."
 90            )
 91        extra_method_input_count = (
 92            1 if isinstance(self.__fn__, (types.MethodType)) else 0
 93        )
 94        return self.__fn__.__code__.co_argcount - extra_method_input_count
 95
 96
 97class GenericConstraint:
 98    def __init__(self, constraints: dict):
 99        """
100        Creates a generic constraint object that can be used to validate a value against a set of constraints.
101
102        Required Arguments:
103
104        - `constraints`:
105            - What: A dictionary of constraint names and their associated functions.
106            - Type: dict
107            - Note: All values in the dictionary must be functions that take a single argument and return a boolean.
108            - Note: The dictionary keys will be used to identify the failed constraints in the error messages.
109        """
110        assert all(
111            hasattr(v, "__call__") for v in constraints.values()
112        ), "All constraints must be functions."
113        self.__constraint_checks__ = constraints
114
115    def __validate__(self, varname, value):
116        for check_name, check_func in self.__constraint_checks__.items():
117            try:
118                if not check_func(value):
119                    return f"Constraint `{check_name}` not met with the provided value `{value}`"
120            except Exception as e:
121                return f"An exception was raised when checking the constraint `{check_name}` with the provided value `{value}`. Error: {e}"
122        return True
123
124    def __ror__(self, other):
125        """
126        Allows the use of | operator to combine GenericConstraints via a union.
127        """
128        return Union[other, self]
129
130
131class Constraint(GenericConstraint):
132    def __init__(
133        self,
134        pattern: str | None = None,
135        includes: list | tuple | set | None = None,
136        excludes: list | tuple | set | None = None,
137        gt: float | int | None = None,
138        lt: float | int | None = None,
139        ge: float | int | None = None,
140        le: float | int | None = None,
141        eq: float | int | None = None,
142        ne: float | int | None = None,
143    ):
144        """
145        Creates a constraint object that can be used to validate a value against a set of constraints.
146
147        Optional Arguments:
148
149        - `pattern`:
150            - What: A regex pattern that the value must match.
151            - Type: str or None
152            - Default: None
153        - `includes`:
154            - What: A list of values that the value must be in.
155            - Type: list, tuple, set or None
156            - Default: None
157        - `excludes`:
158            - What: A list of values that the value must not be in.
159            - Type: list, tuple, set or None
160            - Default: None
161        - `gt`:
162            - What: The value must be greater than this value.
163            - Type: float, int or None
164            - Default: None
165        - `lt`:
166            - What: The value must be less than this value.
167            - Type: float, int or None
168            - Default: None
169        - `ge`:
170            - What: The value must be greater than or equal to this value.
171            - Type: float, int or None
172            - Default: None
173        - `le`:
174            - What: The value must be less than or equal to this value.
175            - Type: float, int or None
176            - Default: None
177        - `eq`:
178            - What: The value must be equal to this value.
179            - Type: float, int or None
180            - Default: None
181        - `ne`:
182            - What: The value must not be equal to this value.
183            - Type: float, int or None
184            - Default: None
185        """
186        assert any(
187            v is not None
188            for v in [pattern, gt, lt, ge, le, eq, ne, includes, excludes]
189        ), "At least one constraint must be provided."
190        assert isinstance(
191            includes, (list, tuple, set, type(None))
192        ), "Includes must be a list, tuple, set or None."
193        assert isinstance(
194            excludes, (list, tuple, set, type(None))
195        ), "Excludes must be a list, tuple, set or None."
196        assert isinstance(
197            pattern, (str, type(None))
198        ), "Pattern must be a string or None."
199        assert isinstance(
200            gt, (float, int, type(None))
201        ), "Greater than constraint must be a float, int or None."
202        assert isinstance(
203            lt, (float, int, type(None))
204        ), "Less than constraint must be a float, int or None."
205        assert isinstance(
206            ge, (float, int, type(None))
207        ), "Greater or equal to constraint must be a float, int or None."
208        assert isinstance(
209            le, (float, int, type(None))
210        ), "Less than or equal to constraint must be a float, int or None."
211        assert isinstance(
212            eq, (float, int, type(None))
213        ), "Equal to constraint must be a float, int or None."
214        assert isinstance(
215            ne, (float, int, type(None))
216        ), "Not equal to constraint must be a float, int or None."
217        self.__constraint_checks__ = {}
218        if pattern is not None:
219            self.__constraint_checks__["be a string"] = lambda x: isinstance(
220                x, str
221            )
222            self.__constraint_checks__["Regex Pattern Match"] = lambda x: bool(
223                re.findall(pattern, x)
224            )
225        if includes is not None:
226            self.__constraint_checks__[f"Includes"] = lambda x: x in includes
227        if excludes is not None:
228            self.__constraint_checks__["Excludes"] = lambda x: x not in excludes
229        if gt is not None:
230            self.__constraint_checks__[f"Greater Than ({gt})"] = (
231                lambda x: x > gt
232            )
233        if lt is not None:
234            self.__constraint_checks__[f"Less Than ({lt})"] = lambda x: x < lt
235        if ge is not None:
236            self.__constraint_checks__[f"Greater Than Or Equal To ({ge})"] = (
237                lambda x: x >= ge
238            )
239        if le is not None:
240            self.__constraint_checks__[f"Less Than Or Equal To ({le})"] = (
241                lambda x: x <= le
242            )
243        if eq is not None:
244            self.__constraint_checks__[f"Equal To ({eq})"] = lambda x: x == eq
245        if ne is not None:
246            self.__constraint_checks__[f"Not Equal To ({ne})"] = (
247                lambda x: x != ne
248            )
249
250
251def DeepMerge(original: dict, update: dict):
252    """
253    Merge two dictionaries together, recursively merging any nested dictionaries and extending any nested lists.
254
255    Required Arguments:
256
257    - `original`:
258        - What: The original dictionary to merge the update into.
259        - Type: dict
260    - `update`:
261        - What: The dictionary to merge into the original dictionary.
262        - Type: dict
263    """
264    original = copy.deepcopy(original)
265    for key, value in update.items():
266        if (
267            key in original
268            and isinstance(original[key], dict)
269            and isinstance(value, dict)
270        ):
271            original[key] = DeepMerge(original[key], value)
272        elif (
273            key in original
274            and isinstance(original[key], list)
275            and isinstance(value, list)
276        ):
277            original[key].extend(value)
278        else:
279            original[key] = value
280    return original
281
282
283def WithSubclasses(cls):
284    """
285    A utility class to preserve backwards compatibility
286    with the older versions of type_enforced.
287
288    By default subclasses of all classes are now enforced by type_enforced.
289
290    It is slated to be removed in the next major version.
291    """
292    # TODO: Remove this in the next major version of type_enforced
293    return cls
294
295
296iterable_types = set([list, tuple, set, dict])
class Partial:
 7class Partial:
 8    """
 9    A special class wrapper to allow for easy partial function wrappings and calls.
10    """
11
12    def __init__(
13        self,
14        __fn__,
15        *__args__,
16        **__kwargs__,
17    ):
18        update_wrapper(self, __fn__)
19        self.__fn__ = __fn__
20        self.__args__ = __args__
21        self.__kwargs__ = __kwargs__
22        self.__fnArity__ = self.__getFnArity__()
23        self.__arity__ = self.__getArity__(__args__, __kwargs__)
24        self.__get_fn_arg_default_keys__()
25
26    def __exception__(self, message):
27        pre_message = (
28            f"({self.__fn__.__module__}.{self.__fn__.__qualname__}_partial): "
29        )
30        raise Exception(pre_message + message)
31
32    def __call__(self, *args, **kwargs):
33        new_args = self.__args__ + args
34        new_kwargs = {**self.__kwargs__, **kwargs}
35        # Create a comprehensive set of assigned variable names to determine arity
36        assigned_vars = set(
37            self.__fn_arg_default_keys__
38            + self.__fn_arg_keys__[: len(new_args)]
39            + list(new_kwargs.keys())
40        )
41        arity = self.__fnArity__ - len(assigned_vars)
42        if arity < 0:
43            self.__exception__("Too many arguments were supplied")
44        if arity == 0:
45            results = self.__fn__(*new_args, **new_kwargs)
46            return results
47        return Partial(
48            self.__fn__,
49            *new_args,
50            **new_kwargs,
51        )
52
53    def __get_fn_arg_default_keys__(self):
54        """
55        Get the default values of the passed function or method and store them in `self.__fn_defaults__`.
56        """
57        self.__fn_var_keys__ = list(self.__fn__.__code__.co_varnames)
58        self.__fn_arg_keys__ = self.__fn_var_keys__[
59            : self.__fn__.__code__.co_argcount
60        ]
61        if self.__fn__.__defaults__ is not None:
62            self.__fn_arg_default_keys__ = self.__fn_arg_keys__[
63                -len(self.__fn__.__defaults__) :
64            ]
65        else:
66            self.__fn_arg_default_keys__ = []
67        if self.__fn__.__kwdefaults__ is not None:
68            self.__fn_arg_default_keys__.extend(
69                list(self.__fn__.__kwdefaults__.keys())
70            )
71
72    def __get__(self, instance, owner):
73        def bind(*args, **kwargs):
74            if instance is not None and self.__arity__ == self.__fnArity__:
75                return self.__call__(instance, *args, **kwargs)
76            else:
77                return self.__call__(*args, **kwargs)
78
79        return bind
80
81    def __repr__(self):
82        return f"<Partial {self.__fn__.__module__}.{self.__fn__.__qualname__} object at {hex(id(self))}>"
83
84    def __getArity__(self, args, kwargs):
85        return self.__fnArity__ - (len(args) + len(kwargs))
86
87    def __getFnArity__(self):
88        if not isinstance(self.__fn__, (types.MethodType, types.FunctionType)):
89            self.__exception__(
90                "A non function was passed as a function and does not have any arity. See the stack trace above for more information."
91            )
92        extra_method_input_count = (
93            1 if isinstance(self.__fn__, (types.MethodType)) else 0
94        )
95        return self.__fn__.__code__.co_argcount - extra_method_input_count

A special class wrapper to allow for easy partial function wrappings and calls.

Partial(__fn__, *__args__, **__kwargs__)
12    def __init__(
13        self,
14        __fn__,
15        *__args__,
16        **__kwargs__,
17    ):
18        update_wrapper(self, __fn__)
19        self.__fn__ = __fn__
20        self.__args__ = __args__
21        self.__kwargs__ = __kwargs__
22        self.__fnArity__ = self.__getFnArity__()
23        self.__arity__ = self.__getArity__(__args__, __kwargs__)
24        self.__get_fn_arg_default_keys__()
class GenericConstraint:
 98class GenericConstraint:
 99    def __init__(self, constraints: dict):
100        """
101        Creates a generic constraint object that can be used to validate a value against a set of constraints.
102
103        Required Arguments:
104
105        - `constraints`:
106            - What: A dictionary of constraint names and their associated functions.
107            - Type: dict
108            - Note: All values in the dictionary must be functions that take a single argument and return a boolean.
109            - Note: The dictionary keys will be used to identify the failed constraints in the error messages.
110        """
111        assert all(
112            hasattr(v, "__call__") for v in constraints.values()
113        ), "All constraints must be functions."
114        self.__constraint_checks__ = constraints
115
116    def __validate__(self, varname, value):
117        for check_name, check_func in self.__constraint_checks__.items():
118            try:
119                if not check_func(value):
120                    return f"Constraint `{check_name}` not met with the provided value `{value}`"
121            except Exception as e:
122                return f"An exception was raised when checking the constraint `{check_name}` with the provided value `{value}`. Error: {e}"
123        return True
124
125    def __ror__(self, other):
126        """
127        Allows the use of | operator to combine GenericConstraints via a union.
128        """
129        return Union[other, self]
GenericConstraint(constraints: dict)
 99    def __init__(self, constraints: dict):
100        """
101        Creates a generic constraint object that can be used to validate a value against a set of constraints.
102
103        Required Arguments:
104
105        - `constraints`:
106            - What: A dictionary of constraint names and their associated functions.
107            - Type: dict
108            - Note: All values in the dictionary must be functions that take a single argument and return a boolean.
109            - Note: The dictionary keys will be used to identify the failed constraints in the error messages.
110        """
111        assert all(
112            hasattr(v, "__call__") for v in constraints.values()
113        ), "All constraints must be functions."
114        self.__constraint_checks__ = constraints

Creates a generic constraint object that can be used to validate a value against a set of constraints.

Required Arguments:

  • constraints:
    • What: A dictionary of constraint names and their associated functions.
    • Type: dict
    • Note: All values in the dictionary must be functions that take a single argument and return a boolean.
    • Note: The dictionary keys will be used to identify the failed constraints in the error messages.
class Constraint(GenericConstraint):
132class Constraint(GenericConstraint):
133    def __init__(
134        self,
135        pattern: str | None = None,
136        includes: list | tuple | set | None = None,
137        excludes: list | tuple | set | None = None,
138        gt: float | int | None = None,
139        lt: float | int | None = None,
140        ge: float | int | None = None,
141        le: float | int | None = None,
142        eq: float | int | None = None,
143        ne: float | int | None = None,
144    ):
145        """
146        Creates a constraint object that can be used to validate a value against a set of constraints.
147
148        Optional Arguments:
149
150        - `pattern`:
151            - What: A regex pattern that the value must match.
152            - Type: str or None
153            - Default: None
154        - `includes`:
155            - What: A list of values that the value must be in.
156            - Type: list, tuple, set or None
157            - Default: None
158        - `excludes`:
159            - What: A list of values that the value must not be in.
160            - Type: list, tuple, set or None
161            - Default: None
162        - `gt`:
163            - What: The value must be greater than this value.
164            - Type: float, int or None
165            - Default: None
166        - `lt`:
167            - What: The value must be less than this value.
168            - Type: float, int or None
169            - Default: None
170        - `ge`:
171            - What: The value must be greater than or equal to this value.
172            - Type: float, int or None
173            - Default: None
174        - `le`:
175            - What: The value must be less than or equal to this value.
176            - Type: float, int or None
177            - Default: None
178        - `eq`:
179            - What: The value must be equal to this value.
180            - Type: float, int or None
181            - Default: None
182        - `ne`:
183            - What: The value must not be equal to this value.
184            - Type: float, int or None
185            - Default: None
186        """
187        assert any(
188            v is not None
189            for v in [pattern, gt, lt, ge, le, eq, ne, includes, excludes]
190        ), "At least one constraint must be provided."
191        assert isinstance(
192            includes, (list, tuple, set, type(None))
193        ), "Includes must be a list, tuple, set or None."
194        assert isinstance(
195            excludes, (list, tuple, set, type(None))
196        ), "Excludes must be a list, tuple, set or None."
197        assert isinstance(
198            pattern, (str, type(None))
199        ), "Pattern must be a string or None."
200        assert isinstance(
201            gt, (float, int, type(None))
202        ), "Greater than constraint must be a float, int or None."
203        assert isinstance(
204            lt, (float, int, type(None))
205        ), "Less than constraint must be a float, int or None."
206        assert isinstance(
207            ge, (float, int, type(None))
208        ), "Greater or equal to constraint must be a float, int or None."
209        assert isinstance(
210            le, (float, int, type(None))
211        ), "Less than or equal to constraint must be a float, int or None."
212        assert isinstance(
213            eq, (float, int, type(None))
214        ), "Equal to constraint must be a float, int or None."
215        assert isinstance(
216            ne, (float, int, type(None))
217        ), "Not equal to constraint must be a float, int or None."
218        self.__constraint_checks__ = {}
219        if pattern is not None:
220            self.__constraint_checks__["be a string"] = lambda x: isinstance(
221                x, str
222            )
223            self.__constraint_checks__["Regex Pattern Match"] = lambda x: bool(
224                re.findall(pattern, x)
225            )
226        if includes is not None:
227            self.__constraint_checks__[f"Includes"] = lambda x: x in includes
228        if excludes is not None:
229            self.__constraint_checks__["Excludes"] = lambda x: x not in excludes
230        if gt is not None:
231            self.__constraint_checks__[f"Greater Than ({gt})"] = (
232                lambda x: x > gt
233            )
234        if lt is not None:
235            self.__constraint_checks__[f"Less Than ({lt})"] = lambda x: x < lt
236        if ge is not None:
237            self.__constraint_checks__[f"Greater Than Or Equal To ({ge})"] = (
238                lambda x: x >= ge
239            )
240        if le is not None:
241            self.__constraint_checks__[f"Less Than Or Equal To ({le})"] = (
242                lambda x: x <= le
243            )
244        if eq is not None:
245            self.__constraint_checks__[f"Equal To ({eq})"] = lambda x: x == eq
246        if ne is not None:
247            self.__constraint_checks__[f"Not Equal To ({ne})"] = (
248                lambda x: x != ne
249            )
Constraint( pattern: str | None = None, includes: list | tuple | set | None = None, excludes: list | tuple | set | None = None, gt: float | int | None = None, lt: float | int | None = None, ge: float | int | None = None, le: float | int | None = None, eq: float | int | None = None, ne: float | int | None = None)
133    def __init__(
134        self,
135        pattern: str | None = None,
136        includes: list | tuple | set | None = None,
137        excludes: list | tuple | set | None = None,
138        gt: float | int | None = None,
139        lt: float | int | None = None,
140        ge: float | int | None = None,
141        le: float | int | None = None,
142        eq: float | int | None = None,
143        ne: float | int | None = None,
144    ):
145        """
146        Creates a constraint object that can be used to validate a value against a set of constraints.
147
148        Optional Arguments:
149
150        - `pattern`:
151            - What: A regex pattern that the value must match.
152            - Type: str or None
153            - Default: None
154        - `includes`:
155            - What: A list of values that the value must be in.
156            - Type: list, tuple, set or None
157            - Default: None
158        - `excludes`:
159            - What: A list of values that the value must not be in.
160            - Type: list, tuple, set or None
161            - Default: None
162        - `gt`:
163            - What: The value must be greater than this value.
164            - Type: float, int or None
165            - Default: None
166        - `lt`:
167            - What: The value must be less than this value.
168            - Type: float, int or None
169            - Default: None
170        - `ge`:
171            - What: The value must be greater than or equal to this value.
172            - Type: float, int or None
173            - Default: None
174        - `le`:
175            - What: The value must be less than or equal to this value.
176            - Type: float, int or None
177            - Default: None
178        - `eq`:
179            - What: The value must be equal to this value.
180            - Type: float, int or None
181            - Default: None
182        - `ne`:
183            - What: The value must not be equal to this value.
184            - Type: float, int or None
185            - Default: None
186        """
187        assert any(
188            v is not None
189            for v in [pattern, gt, lt, ge, le, eq, ne, includes, excludes]
190        ), "At least one constraint must be provided."
191        assert isinstance(
192            includes, (list, tuple, set, type(None))
193        ), "Includes must be a list, tuple, set or None."
194        assert isinstance(
195            excludes, (list, tuple, set, type(None))
196        ), "Excludes must be a list, tuple, set or None."
197        assert isinstance(
198            pattern, (str, type(None))
199        ), "Pattern must be a string or None."
200        assert isinstance(
201            gt, (float, int, type(None))
202        ), "Greater than constraint must be a float, int or None."
203        assert isinstance(
204            lt, (float, int, type(None))
205        ), "Less than constraint must be a float, int or None."
206        assert isinstance(
207            ge, (float, int, type(None))
208        ), "Greater or equal to constraint must be a float, int or None."
209        assert isinstance(
210            le, (float, int, type(None))
211        ), "Less than or equal to constraint must be a float, int or None."
212        assert isinstance(
213            eq, (float, int, type(None))
214        ), "Equal to constraint must be a float, int or None."
215        assert isinstance(
216            ne, (float, int, type(None))
217        ), "Not equal to constraint must be a float, int or None."
218        self.__constraint_checks__ = {}
219        if pattern is not None:
220            self.__constraint_checks__["be a string"] = lambda x: isinstance(
221                x, str
222            )
223            self.__constraint_checks__["Regex Pattern Match"] = lambda x: bool(
224                re.findall(pattern, x)
225            )
226        if includes is not None:
227            self.__constraint_checks__[f"Includes"] = lambda x: x in includes
228        if excludes is not None:
229            self.__constraint_checks__["Excludes"] = lambda x: x not in excludes
230        if gt is not None:
231            self.__constraint_checks__[f"Greater Than ({gt})"] = (
232                lambda x: x > gt
233            )
234        if lt is not None:
235            self.__constraint_checks__[f"Less Than ({lt})"] = lambda x: x < lt
236        if ge is not None:
237            self.__constraint_checks__[f"Greater Than Or Equal To ({ge})"] = (
238                lambda x: x >= ge
239            )
240        if le is not None:
241            self.__constraint_checks__[f"Less Than Or Equal To ({le})"] = (
242                lambda x: x <= le
243            )
244        if eq is not None:
245            self.__constraint_checks__[f"Equal To ({eq})"] = lambda x: x == eq
246        if ne is not None:
247            self.__constraint_checks__[f"Not Equal To ({ne})"] = (
248                lambda x: x != ne
249            )

Creates a constraint object that can be used to validate a value against a set of constraints.

Optional Arguments:

  • pattern:
    • What: A regex pattern that the value must match.
    • Type: str or None
    • Default: None
  • includes:
    • What: A list of values that the value must be in.
    • Type: list, tuple, set or None
    • Default: None
  • excludes:
    • What: A list of values that the value must not be in.
    • Type: list, tuple, set or None
    • Default: None
  • gt:
    • What: The value must be greater than this value.
    • Type: float, int or None
    • Default: None
  • lt:
    • What: The value must be less than this value.
    • Type: float, int or None
    • Default: None
  • ge:
    • What: The value must be greater than or equal to this value.
    • Type: float, int or None
    • Default: None
  • le:
    • What: The value must be less than or equal to this value.
    • Type: float, int or None
    • Default: None
  • eq:
    • What: The value must be equal to this value.
    • Type: float, int or None
    • Default: None
  • ne:
    • What: The value must not be equal to this value.
    • Type: float, int or None
    • Default: None
def DeepMerge(original: dict, update: dict):
252def DeepMerge(original: dict, update: dict):
253    """
254    Merge two dictionaries together, recursively merging any nested dictionaries and extending any nested lists.
255
256    Required Arguments:
257
258    - `original`:
259        - What: The original dictionary to merge the update into.
260        - Type: dict
261    - `update`:
262        - What: The dictionary to merge into the original dictionary.
263        - Type: dict
264    """
265    original = copy.deepcopy(original)
266    for key, value in update.items():
267        if (
268            key in original
269            and isinstance(original[key], dict)
270            and isinstance(value, dict)
271        ):
272            original[key] = DeepMerge(original[key], value)
273        elif (
274            key in original
275            and isinstance(original[key], list)
276            and isinstance(value, list)
277        ):
278            original[key].extend(value)
279        else:
280            original[key] = value
281    return original

Merge two dictionaries together, recursively merging any nested dictionaries and extending any nested lists.

Required Arguments:

  • original:
    • What: The original dictionary to merge the update into.
    • Type: dict
  • update:
    • What: The dictionary to merge into the original dictionary.
    • Type: dict
def WithSubclasses(cls):
284def WithSubclasses(cls):
285    """
286    A utility class to preserve backwards compatibility
287    with the older versions of type_enforced.
288
289    By default subclasses of all classes are now enforced by type_enforced.
290
291    It is slated to be removed in the next major version.
292    """
293    # TODO: Remove this in the next major version of type_enforced
294    return cls

A utility class to preserve backwards compatibility with the older versions of type_enforced.

By default subclasses of all classes are now enforced by type_enforced.

It is slated to be removed in the next major version.

iterable_types = {<class 'list'>, <class 'set'>, <class 'tuple'>, <class 'dict'>}