# from IPython.core.display import display, HTML # a depreciated import
from IPython.display import display, HTML
0002_signature_from_callable
Expand cell
"<style>.container { width:100% !important; }</style>")) display(HTML(
Imports and initiate
from fastdebug.core import *
from fastcore.meta import *
= locals()
g = Fastdb(inspect._signature_from_callable, outloc=g)
fdb = Fastdb(FixSigMeta, outloc=g) fdbF
Examples
from fastdebug.utils import whatinside
=inspect.Signature) inspect._signature_from_callable(whatinside, sigcls
<Signature (mo, dun: bool = False, func: bool = False, clas: bool = False, bltin: bool = False, lib: bool = False, cal: bool = False)>
= "inspect._signature_from_callable(whatinside, sigcls=inspect.Signature)"
fdb.eg
= """
fdb.eg class Base: # pass
def __new__(self, **args): pass # defines a __new__
class Foo_new(Base):
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_new, sigcls=inspect.Signature))
"""
= """
fdb.eg class Base: # pass
def __new__(self, **args): pass # defines a __new__
class Foo_new_fix(Base, metaclass=FixSigMeta):
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_new_fix, sigcls=inspect.Signature))
"""
= """
fdb.eg class BaseMeta(type):
# using __new__ from type
def __call__(cls, *args, **kwargs): pass
class Foo_call(metaclass=BaseMeta):
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call, sigcls=inspect.Signature))
"""
= """
fdbF.eg class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
"""
= """
fdb.eg class Foo_init:
def __init__(self, a, b, c): pass
pprint(inspect._signature_from_callable(Foo_init, sigcls=inspect.Signature))
"""
2, "how does a metaclass create a class instance; what does super().__new__() do here;", "inspect.getdoc(super)")
fdbF.docsrc(4, "how to remove self from a signature; how to check whether a class' __init__ is inherited from object or not;",\
fdbF.docsrc("res", "res.__init__ is not object.__init__")
1, "Any class having FixSigMeta as metaclass will have its own __init__ func stored in its attr __signature__;\
fdbF.docsrc(FixSigMeta uses its __new__ to create a class instance; then check whether its class instance has its own __init__;\
if so, remove self from the sig of __init__; then assign this new sig to __signature__ for the class instance;")
======================================================== Investigating FixSigMeta ========================================================
=============================================================== on line 2 ================================================================
with example
class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
print selected srcline with expands below--------
class FixSigMeta(type): (0)
"A metaclass that fixes the signature on classes that override `__new__`" (1)
def __new__(cls, name, bases, dict):================================================================================================================(2)
how does a metaclass create a class instance; what does super().__new__() do here;
res = super().__new__(cls, name, bases, dict) (3)
if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__)) (4)
==================================================================================================================Start of my srcline exploration:
inspect.getdoc(super) => inspect.getdoc(super) : super() -> same as super(__class__, <first argument>)
super(type) -> unbound super object
super(type, obj) -> bound super object; requires isinstance(obj, type)
super(type, type2) -> bound super object; requires issubclass(type2, type)
Typical use to call a cooperative superclass method:
class C(B):
def meth(self, arg):
super().meth(arg)
This works for class methods too:
class C(B):
@classmethod
def cmeth(cls, arg):
super().cmeth(arg)
====================================================================================================================End of my srcline exploration:
<Signature (d, e, f)>
Review srcode with all comments added so far======================================================================================================
class FixSigMeta(type):===================================================================(0)
"A metaclass that fixes the signature on classes that override `__new__`"=============(1)
def __new__(cls, name, bases, dict):==================================================(2) # how does a metaclass create a class instance; what does super().__new__() do here;;
res = super().__new__(cls, name, bases, dict)=====================================(3)
if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__)) (4)
return res========================================================================(5)
(6)
part No.1 out of 1 parts
======================================================== Investigating FixSigMeta ========================================================
=============================================================== on line 4 ================================================================
with example
class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
print selected srcline with expands below--------
def __new__(cls, name, bases, dict): (2)
res = super().__new__(cls, name, bases, dict) (3)
if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__))===========================================(4)
how to remove self from a signature; how to check whether a class' __init__ is inherited from object or not;
return res (5)
(6)
==================================================================================================================Start of my srcline exploration:
res => res : <class '__main__.Foo_call_fix'>
res.__init__ is not object.__init__ => res.__init__ is not object.__init__ : True
====================================================================================================================End of my srcline exploration:
<Signature (d, e, f)>
Review srcode with all comments added so far======================================================================================================
class FixSigMeta(type):===================================================================(0)
"A metaclass that fixes the signature on classes that override `__new__`"=============(1)
def __new__(cls, name, bases, dict):==================================================(2) # how does a metaclass create a class instance; what does super().__new__() do here;;
res = super().__new__(cls, name, bases, dict)=====================================(3)
if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__)) # how to remove self from a signature; how to check whether a class' __init__ is inherited from object or not;; (4)
return res========================================================================(5)
(6)
part No.1 out of 1 parts
======================================================== Investigating FixSigMeta ========================================================
=============================================================== on line 1 ================================================================
with example
class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
print selected srcline with expands below--------
class FixSigMeta(type): (0)
"A metaclass that fixes the signature on classes that override `__new__`"===========================================================================(1)
Any class having FixSigMeta as metaclass will have its own __init__ func stored in its attr __signature__;FixSigMeta uses its __new__ to create a class instance; then check whether its class instance has its own __init__;if so, remove self from the sig of __init__; then assign this new sig to __signature__ for the class instance;
def __new__(cls, name, bases, dict): (2)
res = super().__new__(cls, name, bases, dict) (3)
fdbF.snoop()
23:01:29.15 >>> Call to FixSigMeta.__new__ in File "/tmp/FixSigMeta.py", line 5
23:01:29.15 .......... cls = <class '__main__.BaseMeta'>
23:01:29.15 .......... name = 'Foo_call_fix'
23:01:29.15 .......... bases = ()
23:01:29.15 .......... dict = {'__module__': '__main__', '__qualname__': 'Foo_call_fix', '__init__': <function Foo_call_fix.__init__>}
23:01:29.15 .......... len(dict) = 3
23:01:29.15 .......... __class__ = <class 'fastcore.meta.FixSigMeta'>
23:01:29.15 5 | def __new__(cls, name, bases, dict):
23:01:29.15 6 | res = super().__new__(cls, name, bases, dict)
23:01:29.15 .............. res = <class '__main__.Foo_call_fix'>
23:01:29.15 7 | if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__))
23:01:29.15 8 | return res
23:01:29.15 <<< Return value from FixSigMeta.__new__: <class '__main__.Foo_call_fix'>
======================================================== Investigating FixSigMeta ========================================================
============================================================== on line None ==============================================================
with example
class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
<Signature (d, e, f)>
29, "How to check whether a class has __signature__?", "hasattr(obj, '__signature__')")
fdb.docsrc(82, "how to check whether obj whose signature is builtins;", "inspect.getdoc(_signature_is_builtin)")
fdb.docsrc(7, "inspect.signature is calling inspect._signature_from_callable; \
fdb.docsrc(create _get_signature_of using functools.partial to call on _signature_from_callable itself;\
obj is first tested for callable; then test obj for classmethod; then unwrap to the end unless obj has __signature__;\
if obj has __signature__, assign __signature__ to sig; then test obj for function, is true calling _signature_from_function; \
then test obj whose signature is builtins or not; test whether obj created by functools.partial; test obj is a class or not; \
if obj is a class, then check obj has its own __call__ first; then its own __new__; then its own __init__; then inherited __new__; \
finally inherited __init__; and then get sig from either of them by calling _get_signature_of on them; \
FixSigMeta assigns __init__ function to __signature__ attr for the instance class it creates; \
so that class with FixSigMeta as metaclass can have sig from __init__ through __signature__; \
no more worry about interference of sig from __call__ or __new__.")
================================================= Investigating _signature_from_callable =================================================
=============================================================== on line 29 ===============================================================
with example
class Foo_init:
def __init__(self, a, b, c): pass
pprint(inspect._signature_from_callable(Foo_init, sigcls=inspect.Signature))
print selected srcline with expands below--------
# Was this function wrapped by a decorator? (27)
if follow_wrapper_chains: (28)
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))=================================================================================(29)
How to check whether a class has __signature__?
if isinstance(obj, types.MethodType): (30)
# If the unwrapped object is a *method*, we might want to (31)
==================================================================================================================Start of my srcline exploration:
hasattr(obj, '__signature__') => hasattr(obj, '__signature__') : False
====================================================================================================================End of my srcline exploration:
<Signature (a, b, c)>
Review srcode with all comments added so far======================================================================================================
sig = _get_signature_of(obj.__func__)=============================================(20)
(21)
if skip_bound_arg:================================================================(22)
return _signature_bound_method(sig)===========================================(23)
else:=============================================================================(24)
return sig====================================================================(25)
(26)
# Was this function wrapped by a decorator?===========================================(27)
if follow_wrapper_chains:=============================================================(28)
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))===================(29) # How to check whether a class has __signature__?;
if isinstance(obj, types.MethodType):=============================================(30)
# If the unwrapped object is a *method*, we might want to=====================(31)
# skip its first parameter (self).============================================(32)
# See test_signature_wrapped_bound_method for details.========================(33)
return _get_signature_of(obj)=================================================(34)
(35)
try:==================================================================================(36)
sig = obj.__signature__===========================================================(37)
except AttributeError:================================================================(38)
pass==============================================================================(39)
part No.2 out of 10 parts
================================================= Investigating _signature_from_callable =================================================
=============================================================== on line 82 ===============================================================
with example
class Foo_init:
def __init__(self, a, b, c): pass
pprint(inspect._signature_from_callable(Foo_init, sigcls=inspect.Signature))
print selected srcline with expands below--------
skip_bound_arg=skip_bound_arg) (80)
(81)
if _signature_is_builtin(obj):======================================================================================================================(82)
how to check whether obj whose signature is builtins;
return _signature_from_builtin(sigcls, obj, (83)
skip_bound_arg=skip_bound_arg) (84)
==================================================================================================================Start of my srcline exploration:
inspect.getdoc(_signature_is_builtin) => inspect.getdoc(_signature_is_builtin) : Private helper to test if `obj` is a callable that might
support Argument Clinic's __text_signature__ protocol.
====================================================================================================================End of my srcline exploration:
<Signature (a, b, c)>
Review srcode with all comments added so far======================================================================================================
skip_bound_arg=skip_bound_arg)====================(80)
(81)
if _signature_is_builtin(obj):========================================================(82) # how to check whether obj whose signature is builtins;;
return _signature_from_builtin(sigcls, obj,=======================================(83)
skip_bound_arg=skip_bound_arg)=====================(84)
(85)
if isinstance(obj, functools.partial):================================================(86)
wrapped_sig = _get_signature_of(obj.func)=========================================(87)
return _signature_get_partial(wrapped_sig, obj)===================================(88)
(89)
sig = None============================================================================(90)
if isinstance(obj, type):=============================================================(91)
# obj is a class or a metaclass===================================================(92)
(93)
# First, let's see if it has an overloaded __call__ defined=======================(94)
# in its metaclass================================================================(95)
call = _signature_get_user_defined_method(type(obj), '__call__')==================(96)
if call is not None:==============================================================(97)
sig = _get_signature_of(call)=================================================(98)
else:=============================================================================(99)
part No.5 out of 10 parts
================================================= Investigating _signature_from_callable =================================================
=============================================================== on line 7 ================================================================
with example
class Foo_init:
def __init__(self, a, b, c): pass
pprint(inspect._signature_from_callable(Foo_init, sigcls=inspect.Signature))
print selected srcline with expands below--------
"""Private helper function to get signature for arbitrary (5)
callable objects. (6)
"""=================================================================================================================================================(7)
inspect.signature is calling inspect._signature_from_callable; create _get_signature_of using functools.partial to call on _signature_from_callable itself;obj is first tested for callable; then test obj for classmethod; then unwrap to the end unless obj has __signature__;if obj has __signature__, assign __signature__ to sig; then test obj for function, is true calling _signature_from_function; then test obj whose signature is builtins or not; test whether obj created by functools.partial; test obj is a class or not; if obj is a class, then check obj has its own __call__ first; then its own __new__; then its own __init__; then inherited __new__; finally inherited __init__; and then get sig from either of them by calling _get_signature_of on them; FixSigMeta assigns __init__ function to __signature__ attr for the instance class it creates; so that class with FixSigMeta as metaclass can have sig from __init__ through __signature__; no more worry about interference of sig from __call__ or __new__.
(8)
_get_signature_of = functools.partial(_signature_from_callable, (9)
fdb.snoop()
23:01:29.21 >>> Call to _signature_from_callable in File "/tmp/_signature_from_callable.py", line 3
23:01:29.21 ...... obj = <class '__main__.Foo_init'>
23:01:29.21 ...... follow_wrapper_chains = True
23:01:29.21 ...... skip_bound_arg = True
23:01:29.21 ...... sigcls = <class 'inspect.Signature'>
23:01:29.21 3 | def _signature_from_callable(obj, *,
23:01:29.21 12 | _get_signature_of = functools.partial(_signature_from_callable,
23:01:29.21 13 | follow_wrapper_chains=follow_wrapper_chains,
23:01:29.21 14 | skip_bound_arg=skip_bound_arg,
23:01:29.21 15 | sigcls=sigcls)
23:01:29.21 12 | _get_signature_of = functools.partial(_signature_from_callable,
23:01:29.21 .......... _get_signature_of = functools.partial(<function _signature_from_call...und_arg=True, sigcls=<class 'inspect.Signature'>)
23:01:29.21 17 | if not callable(obj):
23:01:29.22 20 | if isinstance(obj, types.MethodType):
23:01:29.22 31 | if follow_wrapper_chains:
23:01:29.22 32 | obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))
23:01:29.22 33 | if isinstance(obj, types.MethodType):
23:01:29.22 39 | try:
23:01:29.22 40 | sig = obj.__signature__
================================================= Investigating _signature_from_callable =================================================
============================================================== on line None ==============================================================
with example
class Foo_init:
def __init__(self, a, b, c): pass
pprint(inspect._signature_from_callable(Foo_init, sigcls=inspect.Signature))
23:01:29.35 !!! AttributeError: type object 'Foo_init' has no attribute '__signature__'
23:01:29.35 !!! When getting attribute: obj.__signature__
23:01:29.35 41 | except AttributeError:
23:01:29.35 42 | pass
23:01:29.35 51 | try:
23:01:29.35 52 | partialmethod = obj._partialmethod
23:01:29.36 !!! AttributeError: type object 'Foo_init' has no attribute '_partialmethod'
23:01:29.36 !!! When getting attribute: obj._partialmethod
23:01:29.36 53 | except AttributeError:
23:01:29.36 54 | pass
23:01:29.36 79 | if isfunction(obj) or _signature_is_functionlike(obj):
23:01:29.36 85 | if _signature_is_builtin(obj):
23:01:29.36 89 | if isinstance(obj, functools.partial):
23:01:29.36 93 | sig = None
23:01:29.36 94 | if isinstance(obj, type):
23:01:29.36 99 | call = _signature_get_user_defined_method(type(obj), '__call__')
23:01:29.36 .............. call = None
23:01:29.36 100 | if call is not None:
23:01:29.36 103 | factory_method = None
23:01:29.36 104 | new = _signature_get_user_defined_method(obj, '__new__')
23:01:29.36 .................. new = None
23:01:29.36 105 | init = _signature_get_user_defined_method(obj, '__init__')
23:01:29.36 .................. init = <function Foo_init.__init__>
23:01:29.36 107 | if '__new__' in obj.__dict__:
23:01:29.36 110 | elif '__init__' in obj.__dict__:
23:01:29.36 111 | factory_method = init
23:01:29.36 ...................... factory_method = <function Foo_init.__init__>
23:01:29.36 118 | if factory_method is not None:
23:01:29.36 119 | sig = _get_signature_of(factory_method)
23:01:29.36 ...................... sig = <Signature (self, a, b, c)>
23:01:29.36 121 | if sig is None:
23:01:29.36 170 | if sig is not None:
23:01:29.36 173 | if skip_bound_arg:
23:01:29.36 174 | return _signature_bound_method(sig)
23:01:29.36 <<< Return value from _signature_from_callable: <Signature (a, b, c)>
<Signature (a, b, c)>
print() fdbF.
======================================================== Investigating FixSigMeta ========================================================
============================================================== on line None ==============================================================
with example
class BaseMeta(FixSigMeta):
# using __new__ of FixSigMeta instead of type
def __call__(cls, *args, **kwargs): pass
class Foo_call_fix(metaclass=BaseMeta): # Base
def __init__(self, d, e, f): pass
pprint(inspect._signature_from_callable(Foo_call_fix, sigcls=inspect.Signature))
class FixSigMeta(type):===================================================================(0)
"A metaclass that fixes the signature on classes that override `__new__`"=============(1) # Any class having FixSigMeta as metaclass will have its own __init__ func stored in its attr __signature__;FixSigMeta uses its __new__ to create a class instance; then check whether its class instance has its own __init__;if so, remove self from the sig of __init__; then assign this new sig to __signature__ for the class instance;;
def __new__(cls, name, bases, dict):==================================================(2) # how does a metaclass create a class instance; what does super().__new__() do here;;
res = super().__new__(cls, name, bases, dict)=====================================(3)
if res.__init__ is not object.__init__: res.__signature__ = _rm_self(inspect.signature(res.__init__)) # how to remove self from a signature; how to check whether a class' __init__ is inherited from object or not;; (4)
return res========================================================================(5)
(6)
print(30, 1) fdb.
def _signature_from_callable(obj, *,======================================================(0)
follow_wrapper_chains=True,==================================(1)
skip_bound_arg=True,=========================================(2)
sigcls):=====================================================(3)
(4)
"""Private helper function to get signature for arbitrary=============================(5)
callable objects.=====================================================================(6)
"""===================================================================================(7) # inspect.signature is calling inspect._signature_from_callable; create _get_signature_of using functools.partial to call on _signature_from_callable itself;obj is first tested for callable; then test obj for classmethod; then unwrap to the end unless obj has __signature__;if obj has __signature__, assign __signature__ to sig; then test obj for function, is true calling _signature_from_function; then test obj whose signature is builtins or not; test whether obj created by functools.partial; test obj is a class or not; if obj is a class, then check obj has its own __call__ first; then its own __new__; then its own __init__; then inherited __new__; finally inherited __init__; and then get sig from either of them by calling _get_signature_of on them; FixSigMeta assigns __init__ function to __signature__ attr for the instance class it creates; so that class with FixSigMeta as metaclass can have sig from __init__ through __signature__; no more worry about interference of sig from __call__ or __new__.;
(8)
_get_signature_of = functools.partial(_signature_from_callable,=======================(9)
follow_wrapper_chains=follow_wrapper_chains,==============(10)
skip_bound_arg=skip_bound_arg,============================(11)
sigcls=sigcls)============================================(12)
(13)
if not callable(obj):=================================================================(14)
raise TypeError('{!r} is not a callable object'.format(obj))======================(15)
(16)
if isinstance(obj, types.MethodType):=================================================(17)
# In this case we skip the first parameter of the underlying======================(18)
# function (usually `self` or `cls`).=============================================(19)
sig = _get_signature_of(obj.__func__)=============================================(20)
(21)
if skip_bound_arg:================================================================(22)
return _signature_bound_method(sig)===========================================(23)
else:=============================================================================(24)
return sig====================================================================(25)
(26)
# Was this function wrapped by a decorator?===========================================(27)
if follow_wrapper_chains:=============================================================(28)
obj = unwrap(obj, stop=(lambda f: hasattr(f, "__signature__")))===================(29) # How to check whether a class has __signature__?;
part No.1 out of 7 parts