Ensure that the signature of the second function matches the first.
(
source_func: Callable[..., Any],
check_func: Callable[..., Any],
*,
exclude_params: set[str] = set(),
description: str = "",
)
| 11 | |
| 12 | |
| 13 | def assert_signatures_in_sync( |
| 14 | source_func: Callable[..., Any], |
| 15 | check_func: Callable[..., Any], |
| 16 | *, |
| 17 | exclude_params: set[str] = set(), |
| 18 | description: str = "", |
| 19 | ) -> None: |
| 20 | """Ensure that the signature of the second function matches the first.""" |
| 21 | |
| 22 | check_sig = inspect.signature(check_func) |
| 23 | source_sig = inspect.signature(source_func) |
| 24 | |
| 25 | errors: list[str] = [] |
| 26 | |
| 27 | for name, source_param in source_sig.parameters.items(): |
| 28 | if name in exclude_params: |
| 29 | continue |
| 30 | |
| 31 | custom_param = check_sig.parameters.get(name) |
| 32 | if not custom_param: |
| 33 | errors.append(f"the `{name}` param is missing") |
| 34 | continue |
| 35 | |
| 36 | if custom_param.annotation != source_param.annotation: |
| 37 | errors.append( |
| 38 | f"types for the `{name}` param are do not match; source={repr(source_param.annotation)} checking={repr(custom_param.annotation)}" |
| 39 | ) |
| 40 | continue |
| 41 | |
| 42 | if errors: |
| 43 | raise AssertionError( |
| 44 | f"{len(errors)} errors encountered when comparing signatures{description}:\n\n" + "\n\n".join(errors) |
| 45 | ) |