@@ -1026,9 +1026,6 @@ def __init__(self, func):
10261026 self .dispatcher = singledispatch (func )
10271027 self .func = func
10281028
1029- import weakref # see comment in singledispatch function
1030- self ._method_cache = weakref .WeakKeyDictionary ()
1031-
10321029 def register (self , cls , method = None ):
10331030 """generic_method.register(cls, func) -> func
10341031
@@ -1037,36 +1034,50 @@ def register(self, cls, method=None):
10371034 return self .dispatcher .register (cls , func = method )
10381035
10391036 def __get__ (self , obj , cls = None ):
1040- if self ._method_cache is not None :
1041- try :
1042- _method = self ._method_cache [obj ]
1043- except TypeError :
1044- self ._method_cache = None
1045- except KeyError :
1046- pass
1047- else :
1048- return _method
1037+ return _singledispatchmethod_get (self , obj , cls )
10491038
1050- dispatch = self .dispatcher .dispatch
1051- funcname = getattr (self .func , '__name__' , 'singledispatchmethod method' )
1052- def _method (* args , ** kwargs ):
1053- if not args :
1054- raise TypeError (f'{ funcname } requires at least '
1055- '1 positional argument' )
1056- return dispatch (args [0 ].__class__ ).__get__ (obj , cls )(* args , ** kwargs )
1039+ @property
1040+ def __isabstractmethod__ (self ):
1041+ return getattr (self .func , '__isabstractmethod__' , False )
10571042
1058- _method .__isabstractmethod__ = self .__isabstractmethod__
1059- _method .register = self .register
1060- update_wrapper (_method , self .func )
10611043
1062- if self ._method_cache is not None :
1063- self ._method_cache [obj ] = _method
1044+ class _singledispatchmethod_get :
1045+ def __init__ (self , unbound , obj , cls ):
1046+ self ._unbound = unbound
1047+ self ._dispatch = unbound .dispatcher .dispatch
1048+ self ._obj = obj
1049+ self ._cls = cls
1050+ # Set instance attributes which cannot be handled in __getattr__()
1051+ # because they conflict with type descriptors.
1052+ func = unbound .func
1053+ try :
1054+ self .__module__ = func .__module__
1055+ except AttributeError :
1056+ pass
1057+ try :
1058+ self .__doc__ = func .__doc__
1059+ except AttributeError :
1060+ pass
1061+
1062+ def __call__ (self , / , * args , ** kwargs ):
1063+ if not args :
1064+ funcname = getattr (self ._unbound .func , '__name__' ,
1065+ 'singledispatchmethod method' )
1066+ raise TypeError (f'{ funcname } requires at least '
1067+ '1 positional argument' )
1068+ return self ._dispatch (args [0 ].__class__ ).__get__ (self ._obj , self ._cls )(* args , ** kwargs )
10641069
1065- return _method
1070+ def __getattr__ (self , name ):
1071+ # Resolve these attributes lazily to speed up creation of
1072+ # the _singledispatchmethod_get instance.
1073+ if name not in {'__name__' , '__qualname__' , '__isabstractmethod__' ,
1074+ '__annotations__' , '__type_params__' }:
1075+ raise AttributeError
1076+ return getattr (self ._unbound .func , name )
10661077
10671078 @property
1068- def __isabstractmethod__ (self ):
1069- return getattr ( self .func , '__isabstractmethod__' , False )
1079+ def register (self ):
1080+ return self ._unbound . register
10701081
10711082
10721083################################################################################
0 commit comments