@@ -893,45 +893,6 @@ def _find_impl(cls, registry):
893893 match = t
894894 return registry .get (match )
895895
896- def _get_singledispatch_annotated_param (func , role ):
897- """Find the first positional and user-specified parameter in a callable
898- or descriptor.
899-
900- Used by singledispatch for registration by type annotation of the parameter.
901- """
902- if isinstance (func , staticmethod ):
903- idx = 0
904- func = func .__func__
905- elif isinstance (func , (classmethod , MethodType )):
906- idx = 1 # Skip parameter bound by instance-level access.
907- func = func .__func__
908- else :
909- # Assume and skip bound parameter when singledispatchmethod is used.
910- idx = 1 if role == "method" else 0
911- # Fast path: emulate `inspect._signature_from_function` if possible.
912- if isinstance (func , FunctionType ) and not hasattr (func , "__wrapped__" ):
913- func_code = func .__code__
914- try :
915- return func_code .co_varnames [:func_code .co_argcount ][idx ]
916- except IndexError :
917- pass
918- # Fall back to `inspect.signature` (slower, but complete).
919- import inspect
920- params = list (inspect .signature (func ).parameters .values ())
921- try :
922- param = params [idx ]
923- except IndexError :
924- pass
925- else :
926- # Allow variadic positional '(*args)' parameters for backward compatibility.
927- if param .kind not in (inspect .Parameter .KEYWORD_ONLY ,
928- inspect .Parameter .VAR_KEYWORD ):
929- return param .name
930- raise TypeError (
931- f"Invalid first argument to `register()`: { func !r} "
932- f"does not accept positional arguments."
933- )
934-
935896def singledispatch (func ):
936897 """Single-dispatch generic function decorator.
937898
@@ -979,7 +940,7 @@ def _is_valid_dispatch_type(cls):
979940 return (isinstance (cls , UnionType ) and
980941 all (isinstance (arg , type ) for arg in cls .__args__ ))
981942
982- def register (cls , func = None , * , _role = "function" ):
943+ def register (cls , func = None ):
983944 """generic_func.register(cls, func) -> func
984945
985946 Registers a new implementation for the given *cls* on a *generic_func*.
@@ -1004,22 +965,11 @@ def register(cls, func=None, *, _role="function"):
1004965 )
1005966 func = cls
1006967
1007- argname = _get_singledispatch_annotated_param (func , role = _role )
1008-
1009968 # only import typing if annotation parsing is necessary
1010969 from typing import get_type_hints
1011970 from annotationlib import Format , ForwardRef
1012- annotations = get_type_hints (func , format = Format .FORWARDREF )
1013-
1014- try :
1015- cls = annotations [argname ]
1016- except KeyError :
1017- raise TypeError (
1018- f"Invalid first argument to `register()`: { func !r} . "
1019- f"Use either `@register(some_class)` or add a type "
1020- f"annotation to parameter { argname !r} of your callable."
1021- ) from None
1022-
971+ argname , cls = next (iter (get_type_hints (
972+ func , format = Format .FORWARDREF ).items ()))
1023973 if not _is_valid_dispatch_type (cls ):
1024974 if isinstance (cls , UnionType ):
1025975 raise TypeError (
@@ -1036,6 +986,17 @@ def register(cls, func=None, *, _role="function"):
1036986 f"Invalid annotation for { argname !r} . "
1037987 f"{ cls !r} is not a class."
1038988 )
989+ if argname == 'return' :
990+ import os
991+ import warnings
992+ warnings .warn (
993+ "Using the return annotation to infer the dispatch type "
994+ "is deprecated and will raise TypeError in Python 3.18. "
995+ "Annotate the dispatch parameter or pass the dispatch "
996+ "type explicitly to register()." ,
997+ DeprecationWarning ,
998+ skip_file_prefixes = (os .path .dirname (__file__ ),),
999+ )
10391000
10401001 if isinstance (cls , UnionType ):
10411002 for arg in cls .__args__ :
@@ -1056,7 +1017,6 @@ def wrapper(*args, **kw):
10561017 funcname = getattr (func , '__name__' , 'singledispatch function' )
10571018 registry [object ] = func
10581019 wrapper .register = register
1059- wrapper .register .__text_signature__ = "(cls, func=None)" # Hide _role from help().
10601020 wrapper .dispatch = dispatch
10611021 wrapper .registry = MappingProxyType (registry )
10621022 wrapper ._clear_cache = dispatch_cache .clear
@@ -1084,7 +1044,7 @@ def register(self, cls, method=None):
10841044
10851045 Registers a new implementation for the given *cls* on a *generic_method*.
10861046 """
1087- return self .dispatcher .register (cls , func = method , _role = "method" )
1047+ return self .dispatcher .register (cls , func = method )
10881048
10891049 def __get__ (self , obj , cls = None ):
10901050 return _singledispatchmethod_get (self , obj , cls )
0 commit comments