(self, function: 'AnyCallableT', config: 'ConfigType')
| 59 | |
| 60 | class ValidatedFunction: |
| 61 | def __init__(self, function: 'AnyCallableT', config: 'ConfigType'): # noqa C901 |
| 62 | from inspect import Parameter, signature |
| 63 | |
| 64 | parameters: Mapping[str, Parameter] = signature(function).parameters |
| 65 | |
| 66 | if parameters.keys() & {ALT_V_ARGS, ALT_V_KWARGS, V_POSITIONAL_ONLY_NAME, V_DUPLICATE_KWARGS}: |
| 67 | raise ConfigError( |
| 68 | f'"{ALT_V_ARGS}", "{ALT_V_KWARGS}", "{V_POSITIONAL_ONLY_NAME}" and "{V_DUPLICATE_KWARGS}" ' |
| 69 | f'are not permitted as argument names when using the "{validate_arguments.__name__}" decorator' |
| 70 | ) |
| 71 | |
| 72 | self.raw_function = function |
| 73 | self.arg_mapping: Dict[int, str] = {} |
| 74 | self.positional_only_args = set() |
| 75 | self.v_args_name = 'args' |
| 76 | self.v_kwargs_name = 'kwargs' |
| 77 | |
| 78 | type_hints = get_all_type_hints(function) |
| 79 | takes_args = False |
| 80 | takes_kwargs = False |
| 81 | fields: Dict[str, Tuple[Any, Any]] = {} |
| 82 | for i, (name, p) in enumerate(parameters.items()): |
| 83 | if p.annotation is p.empty: |
| 84 | annotation = Any |
| 85 | else: |
| 86 | annotation = type_hints[name] |
| 87 | |
| 88 | default = ... if p.default is p.empty else p.default |
| 89 | if p.kind == Parameter.POSITIONAL_ONLY: |
| 90 | self.arg_mapping[i] = name |
| 91 | fields[name] = annotation, default |
| 92 | fields[V_POSITIONAL_ONLY_NAME] = List[str], None |
| 93 | self.positional_only_args.add(name) |
| 94 | elif p.kind == Parameter.POSITIONAL_OR_KEYWORD: |
| 95 | self.arg_mapping[i] = name |
| 96 | fields[name] = annotation, default |
| 97 | fields[V_DUPLICATE_KWARGS] = List[str], None |
| 98 | elif p.kind == Parameter.KEYWORD_ONLY: |
| 99 | fields[name] = annotation, default |
| 100 | elif p.kind == Parameter.VAR_POSITIONAL: |
| 101 | self.v_args_name = name |
| 102 | fields[name] = Tuple[annotation, ...], None |
| 103 | takes_args = True |
| 104 | else: |
| 105 | assert p.kind == Parameter.VAR_KEYWORD, p.kind |
| 106 | self.v_kwargs_name = name |
| 107 | fields[name] = Dict[str, annotation], None # type: ignore |
| 108 | takes_kwargs = True |
| 109 | |
| 110 | # these checks avoid a clash between "args" and a field with that name |
| 111 | if not takes_args and self.v_args_name in fields: |
| 112 | self.v_args_name = ALT_V_ARGS |
| 113 | |
| 114 | # same with "kwargs" |
| 115 | if not takes_kwargs and self.v_kwargs_name in fields: |
| 116 | self.v_kwargs_name = ALT_V_KWARGS |
| 117 | |
| 118 | if not takes_args: |
nothing calls this directly
no test coverage detected