-
Notifications
You must be signed in to change notification settings - Fork 146
Description
With the changes in #469 mutations to default arguments will have no effect and thus always be reported (TODO: test this, add E2E test).
We probably could use decorators to handle this case:
def check(some_flag: bool = False) -> None:
return some_flagCould mutate to something like
P = ParamSpec('P')
R = TypeVar('R')
def __mutmut_dispatcher(func: Callable[P, R]) -> Callable[P, R]:
@wraps(func)
def trampoline(*args: P.args, **kwargs: P.kwargs) -> R:
# check environment variable
# and call correct function from the mutants dict
func_to_call = mutants_dict[...]
return func_to_call(*args, **kwargs)
return trampoline
@__mutmut_dispatcher
def check(some_flag: bool = False) -> None:
return some_flagAnd depending on the os.environ['MUTANT_UNDER_TEST'] the @__mutmut_dispatcher would pass the args to the original function or the mutated method. The decorator could use *args, **kwargs as parameters and thus accept any args (with or without defaults).
I also like that with the decorator we would not need to do parsing of the args and handle all edge cases ourselve, but simply pass on *args, **kwargs.
For static typing, I think using ParamSpec should retain the original signature for static typing.
But I'm not sure how it works with runtime type hints. Maybe with a @functool.wraps decorator this is fine?