Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf323dbd

Browse files
committed
full backwards compatibility
1 parent8fa0ec5 commitf323dbd

File tree

1 file changed

+68
-49
lines changed

1 file changed

+68
-49
lines changed

‎Lib/functools.py

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,9 @@ def __setstate__(self, state):
432432
exceptImportError:
433433
pass
434434

435+
_NULL=object()
436+
_UNKNOWN_DESCRIPTOR=object()
437+
_STD_METHOD_TYPES= (staticmethod,classmethod,FunctionType,partial)
435438

436439
# Descriptor version
437440
classpartialmethod:
@@ -443,86 +446,102 @@ class partialmethod:
443446
"""
444447

445448
__slots__= ("func","args","keywords","wrapper",
446-
"__isabstractmethod__","__dict__","__weakref__")
449+
"__dict__","__weakref__")
447450

448451
__repr__=_partial_repr
449-
__class_getitem__=classmethod(GenericAlias)
450452

451453
def__init__(self,func,/,*args,**keywords):
454+
ifnotcallable(func)andgetattr(func,'__get__',None)isNone:
455+
raiseTypeError(f'the first argument{func!r} must be a callable '
456+
'or a descriptor')
457+
452458
ifisinstance(func,partialmethod):
453459
# Subclass optimization
454460
temp=partial(lambda:None,*func.args,**func.keywords)
455461
temp=partial(temp,*args,**keywords)
456-
isabstract=func.__isabstractmethod__
457462
func=func.func
458463
args=temp.args
459464
keywords=temp.keywords
460-
else:
461-
isabstract=getattr(func,'__isabstractmethod__',False)
465+
462466
self.func=func
463467
self.args=args
464468
self.keywords=keywords
465-
self.__isabstractmethod__=isabstract
466469

467-
# 5 cases
470+
if (isinstance(func,_STD_METHOD_TYPES)or
471+
getattr(func,'__get__',None)isNone):
472+
self.method=None
473+
else:
474+
# Unknown descriptor
475+
self.method=_UNKNOWN_DESCRIPTOR
476+
477+
def_set_func_attrs(self,func):
478+
func.__partialmethod__=self
479+
ifself.__isabstractmethod__:
480+
func=abstractmethod(func)
481+
returnfunc
482+
483+
def_make_method(self):
484+
args=self.args
485+
func=self.func
486+
487+
# 4 cases
468488
ifisinstance(func,staticmethod):
469-
wrapper=partial(func.__wrapped__,*args,**keywords)
470-
self.wrapper=_rewrap_func(wrapper,isabstract,staticmethod)
489+
func=partial(func.__wrapped__,*args,**self.keywords)
490+
self._set_func_attrs(func)
491+
returnstaticmethod(func)
471492
elifisinstance(func,classmethod):
472-
wrapper=_partial_unbound(func.__wrapped__,args,keywords)
473-
self.wrapper=_rewrap_func(wrapper,isabstract,classmethod)
474-
elifisinstance(func, (FunctionType,partial)):
475-
# instance method
476-
wrapper=_partial_unbound(func,args,keywords)
477-
self.wrapper=_rewrap_func(wrapper,isabstract)
478-
elifgetattr(func,'__get__',None)isNone:
479-
# callable object without __get__
480-
# treat this like an instance method
481-
ifnotcallable(func):
482-
raiseTypeError(f'the first argument{func!r} must be a callable '
483-
'or a descriptor')
484-
wrapper=_partial_unbound(func,args,keywords)
485-
self.wrapper=_rewrap_func(wrapper,isabstract)
493+
ph_args= (Placeholder,)ifargselse ()
494+
func=partial(func.__wrapped__,*ph_args,*args,**self.keywords)
495+
self._set_func_attrs(func)
496+
returnclassmethod(func)
486497
else:
487-
# Unknown descriptor
488-
self.wrapper=None
498+
# instance method. 2 cases:
499+
# a) FunctionType | partial
500+
# b) callable object without __get__
501+
ph_args= (Placeholder,)ifargselse ()
502+
func=partial(func,*ph_args,*args,**self.keywords)
503+
self._set_func_attrs(func)
504+
returnfunc
489505

490506
def__get__(self,obj,cls=None):
491-
ifself.wrapperisnotNone:
492-
returnself.wrapper.__get__(obj,cls)
493-
else:
494-
#Unknown descriptor
495-
new_func=getattr(self.func,'__get__')(obj,cls)
507+
method=self.method
508+
ifmethodis_UNKNOWN_DESCRIPTOR:
509+
# Unknown descriptor == unknown binding
510+
#Need to get callable at runtime and apply partial on top
511+
new_func=self.func.__get__(obj,cls)
496512
result=partial(new_func,*self.args,**self.keywords)
497-
try:
498-
result.__self__=new_func.__self__
499-
exceptAttributeError:
500-
pass
513+
self._set_func_attrs(func)
514+
__self__=getattr(new_func,'__self__',_NULL)
515+
if__self__isnot_NULL:
516+
result.__self__=__self__
501517
returnresult
518+
ifmethodisNone:
519+
# Cache method
520+
self.method=method=self._make_method()
521+
returnmethod.__get__(obj,cls)
502522

523+
@property
524+
def__isabstractmethod__(self):
525+
returngetattr(self.func,'__isabstractmethod__',False)
503526

504-
# Helper functions
527+
__class_getitem__=classmethod(GenericAlias)
505528

506-
def_partial_unbound(func,args,keywords):
507-
ifnotargs:
508-
returnpartial(func,**keywords)
509-
returnpartial(func,Placeholder,*args,**keywords)
510-
511-
def_rewrap_func(func,isabstract,decorator=None):
512-
ifisabstract:
513-
func=abstractmethod(func)
514-
ifdecoratorisnotNone:
515-
func=decorator(func)
516-
returnfunc
529+
# Helper functions
517530

518531
def_unwrap_partial(func):
519-
whileisinstance(func,partial):
532+
ifisinstance(func,partial):
520533
func=func.func
521534
returnfunc
522535

523536
def_unwrap_partialmethod(func):
524-
whileisinstance(func, (partial,partialmethod)):
525-
func=func.func
537+
prev=None
538+
whilefuncisnotprev:
539+
prev=func
540+
__partialmethod__=getattr(func,"__partialmethod__",None)
541+
ifisinstance(__partialmethod__,partialmethod):
542+
func=__partialmethod__.func
543+
ifisinstance(func, (partial,partialmethod)):
544+
func=func.func
526545
returnfunc
527546

528547

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp