refactor: transform_parameter_types
Failfast if args and kwargs or annotations don't exist
This commit is contained in:
parent
579aa124e1
commit
ec931004ca
1 changed files with 67 additions and 63 deletions
|
|
@ -82,72 +82,76 @@ def transform_parameter_types(func: Callable, args: tuple, kwargs: dict):
|
|||
defined on the function.
|
||||
|
||||
"""
|
||||
if annotations := func.__annotations__:
|
||||
new_args, new_kwargs = list(args), kwargs
|
||||
if not (args or kwargs) or not func.__annotations__:
|
||||
return args, kwargs
|
||||
|
||||
# generate kwargs dict from args
|
||||
arg_names = func.__code__.co_varnames[: func.__code__.co_argcount]
|
||||
annotations = func.__annotations__
|
||||
new_args, new_kwargs = list(args), kwargs
|
||||
|
||||
if not args:
|
||||
prepared_args = kwargs
|
||||
# generate kwargs dict from args
|
||||
arg_names = func.__code__.co_varnames[: func.__code__.co_argcount]
|
||||
|
||||
elif kwargs:
|
||||
arg_values = args or func.__defaults__ or []
|
||||
prepared_args = dict(zip(arg_names, arg_values))
|
||||
prepared_args.update(kwargs)
|
||||
if not args:
|
||||
prepared_args = kwargs
|
||||
|
||||
elif kwargs:
|
||||
arg_values = args or func.__defaults__ or []
|
||||
prepared_args = dict(zip(arg_names, arg_values))
|
||||
prepared_args.update(kwargs)
|
||||
|
||||
else:
|
||||
prepared_args = dict(zip(arg_names, args))
|
||||
|
||||
# check if type hints dont match the default values
|
||||
func_signature = signature(func)
|
||||
func_params = dict(func_signature.parameters)
|
||||
|
||||
# check if the argument types are correct
|
||||
for current_arg, current_arg_type in annotations.items():
|
||||
if current_arg not in prepared_args:
|
||||
continue
|
||||
|
||||
current_arg_value = prepared_args[current_arg]
|
||||
|
||||
# if the type is a ForwardRef or str, ignore it
|
||||
if isinstance(current_arg_type, (ForwardRef, str)):
|
||||
continue
|
||||
elif any(isinstance(x, (ForwardRef, str)) for x in getattr(current_arg_type, "__args__", [])):
|
||||
continue
|
||||
|
||||
# allow slack for Frappe types
|
||||
if current_arg_type in SLACK_DICT:
|
||||
current_arg_type = SLACK_DICT[current_arg_type]
|
||||
|
||||
param_def = func_params.get(current_arg)
|
||||
|
||||
# add default value's type in acceptable types
|
||||
if param_def.default is not _empty:
|
||||
if isinstance(current_arg_type, tuple):
|
||||
if type(param_def.default) not in current_arg_type:
|
||||
current_arg_type += (type(param_def.default),)
|
||||
current_arg_type = Union[current_arg_type]
|
||||
|
||||
elif param_def.default != current_arg_type:
|
||||
current_arg_type = Union[current_arg_type, type(param_def.default)]
|
||||
elif isinstance(current_arg_type, tuple):
|
||||
current_arg_type = Union[current_arg_type]
|
||||
|
||||
# validate the type set using pydantic - raise a TypeError if Validation is raised or Ellipsis is returned
|
||||
try:
|
||||
current_arg_value_after = parse_obj_as(
|
||||
current_arg_type, current_arg_value, type_name=current_arg, config=FrappePydanticConfig
|
||||
)
|
||||
except PyValidationError as e:
|
||||
raise_type_error(current_arg, current_arg_type, current_arg_value, current_exception=e)
|
||||
|
||||
if isinstance(current_arg_value_after, EllipsisType):
|
||||
raise_type_error(current_arg, current_arg_type, current_arg_value)
|
||||
|
||||
# update the args and kwargs with possibly casted value
|
||||
if current_arg in kwargs:
|
||||
new_kwargs[current_arg] = current_arg_value_after
|
||||
else:
|
||||
prepared_args = dict(zip(arg_names, args))
|
||||
new_args[arg_names.index(current_arg)] = current_arg_value_after
|
||||
|
||||
# check if type hints dont match the default values
|
||||
func_signature = signature(func)
|
||||
func_params = dict(func_signature.parameters)
|
||||
|
||||
# check if the argument types are correct
|
||||
for current_arg, current_arg_type in annotations.items():
|
||||
if current_arg not in prepared_args:
|
||||
continue
|
||||
|
||||
current_arg_value = prepared_args[current_arg]
|
||||
|
||||
# if the type is a ForwardRef or str, ignore it
|
||||
if isinstance(current_arg_type, (ForwardRef, str)):
|
||||
continue
|
||||
elif any(isinstance(x, (ForwardRef, str)) for x in getattr(current_arg_type, "__args__", [])):
|
||||
continue
|
||||
|
||||
# allow slack for Frappe types
|
||||
if current_arg_type in SLACK_DICT:
|
||||
current_arg_type = SLACK_DICT[current_arg_type]
|
||||
|
||||
param_def = func_params.get(current_arg)
|
||||
|
||||
# add default value's type in acceptable types
|
||||
if param_def.default is not _empty:
|
||||
if isinstance(current_arg_type, tuple):
|
||||
if type(param_def.default) not in current_arg_type:
|
||||
current_arg_type += (type(param_def.default),)
|
||||
current_arg_type = Union[current_arg_type]
|
||||
|
||||
elif param_def.default != current_arg_type:
|
||||
current_arg_type = Union[current_arg_type, type(param_def.default)]
|
||||
|
||||
try:
|
||||
current_arg_value_after = parse_obj_as(
|
||||
current_arg_type, current_arg_value, type_name=current_arg, config=FrappePydanticConfig
|
||||
)
|
||||
except PyValidationError as e:
|
||||
raise_type_error(current_arg, current_arg_type, current_arg_value, current_exception=e)
|
||||
|
||||
if isinstance(current_arg_value_after, EllipsisType):
|
||||
raise_type_error(current_arg, current_arg_type, current_arg_value)
|
||||
|
||||
else:
|
||||
if current_arg in kwargs:
|
||||
new_kwargs[current_arg] = current_arg_value_after
|
||||
else:
|
||||
new_args[arg_names.index(current_arg)] = current_arg_value_after
|
||||
|
||||
return new_args, new_kwargs
|
||||
|
||||
return args, kwargs
|
||||
return new_args, new_kwargs
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue