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