@@ -21,7 +21,7 @@ def {orig_name}({'self, ' if class_name is not None else ''}*args, **kwargs):
2121 result = { trampoline_name } ({ access_prefix } { mangled_name } __mutmut_orig{ access_suffix } , { access_prefix } { mangled_name } __mutmut_mutants{ access_suffix } , args, kwargs{ self_arg } )
2222 return result
2323
24- { orig_name } .__signature__ = _mutmut_signature( { mangled_name } __mutmut_orig)
24+ _mutmut_copy_signature( { orig_name } , { mangled_name } __mutmut_orig)
2525{ mangled_name } __mutmut_orig.__name__ = '{ mangled_name } '
2626"""
2727
@@ -37,11 +37,27 @@ def mangle_function_name(*, name, class_name):
3737# noinspection PyUnresolvedReferences
3838# language=python
3939trampoline_impl = """
40- from inspect import signature as _mutmut_signature
40+ import inspect as _mutmut_inspect
41+ import sys as _mutmut_sys
4142from typing import Annotated
4243from typing import Callable
4344from typing import ClassVar
4445
46+ def _mutmut_copy_signature(trampoline, original_method):
47+ if _mutmut_sys.version_info >= (3, 14):
48+ # PEP 649 introduced deferred loading for annotations
49+ # When some_method.__annotations__ is accessed, Python uses some_method.__annotate__(format) to compute it
50+ # By copying the original __annotate__ method, we provide get the original annotations
51+ trampoline.__annotate__ = original_method.__annotate__
52+
53+ try:
54+ trampoline.__signature__ = _mutmut_inspect.signature(original_method)
55+ except NameError:
56+ # Also, because of PEP 649, it can happen that we cannot eagerly evaluate the signature
57+ # In this case, fall back to stringifying the signature (which could cause different behaviour with runtime introspection)
58+ trampoline.__signature__ = _mutmut_inspect.signature(original_method, annotation_format=_mutmut_inspect.Format.STRING)
59+
60+
4561
4662MutantDict = Annotated[dict[str, Callable], "Mutant"]
4763
0 commit comments