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.
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'>}