You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
inspect.getfullargspec should use __signature__ #61683
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
assignee='https://github.com/1st1'closed_at=<Date2014-01-29.16:46:22.224>created_at=<Date2013-03-19.17:31:32.474>labels= ['type-feature', 'library']
title='inspect.getfullargspec should use __signature__'updated_at=<Date2014-01-29.16:54:26.797>user='https://github.com/voidspace'
inspect.getfullargspec (and potentially getargspec?) could *use* function.__signature__ if set. This allows functions that lie about their signature with the new introspection tool (Signature) to still work with older code.
While I plan to change Idle code to use signature directly, instead of getfullargspec, I agree that changing inspect also, and in 3.4, is a good idea. It may, however, affect tests other than Idle's, if there are any other stdlib consumers. I will try to look at the patch after changing Idle.
I upgraded the description to a "should". Argument Clinic and other changes in Python 3.4 greatly improve introspection support for various aspects of the runtime and standard library (for example, bpo-20223 will handle the new functools.partialmethod support). By also making those enhancements available via getfullargpsec, we should significantly increase the amount of existing code which benefits automatically for those enhancements, as it will no longer require explicit migration to the new PEP-362 APIs at the application/library level.
If we modify inspect.getfullargspec, shouldn't we modify inspect.getargspec too? "deprecated" doesn't mean "unsupported", it means "not recommended for new code, please stop using it".
getargspec() is just a thin wrapper around getfullargspec(), so we get that for free.
Similarly, getcallargs() is also implicitly updated to full PEP-362 support by changing the implementation of getfullargspec().
The other two standard library consumers appear to be IDLE (as Terry noted above) and xmlrpc.server.ServerHTMLDoc.docroutine (the self-documenting XML-RPC server API, which sadly appears to be lacking test cases).
Reviewing those cases (especially the XML-RPC one) have convinced me we need a backwards compatibility fallback in the updated getfullargspec implementation. Specifically, if the new API throws ValueError (because it can't find a way to build a coherent signature object), we should fall back to the old approach. Otherwise we run the risk of introducing unexpected exceptions into introspection code.
That is, the new call to signature in getfullargspec should look something like:
try:
sig = signature(func)
except ValueError:
if not hasattr(func, "__code__"):
raise # The legacy fallback doesn't support this input type
# The callable signature appears to be incoherent, so we fall
# back to the legacy implementation to preserve compatibility
args, varargs, kwonlyargs, varkw = _getfullargs(func.__code__)
return FullArgSpec(args, varargs, varkw, func.__defaults__,
kwonlyargs, func.__kwdefaults__, func.__annotations__)
I suspect this may actually be a better solution for IDLE rather than updating it to call inspect.signature directly (since IDLE probably *wants* the more graceful fallback to the old behaviour).
The way I would document all this in What's New is to update the current argument clinic section to also explain that we've taken advantage of PEP-362 to improve introspection in multiple areas, including for code that is using the introspection APIs that predate PEP-362.
The relevant code in CallTips.py is
argspec = ""
if hasattr(ob, '__call__'):
...
if isinstance(fob, (types.FunctionType, types.MethodType)):
argspec = inspect.formatargspec(*inspect.getfullargspec(fob))
So I want to broaden the second condition (or remove it), but if it returns something .formatargspec cannot digest, the outer call will have to be conditioned. My impression is that str(signature object) returns pretty much what .formatargspec does, but I have not experimented yet.
My bpo-20122 patch moves currently commented out tests in CallTips.py that use the above to test_calltips.py. I will commit as soon as I test on 3.4. Until then, getfullargspec is not being used in the Idle test suite.
I just want to mention, while we're all thinking about this stuff: I plan to enhance the Signature object to reflect "optional groups". Right now Signature objects cannot express parameters that are optional but don't have a published default. (e.g. a string parameter for a builtin having a default of NULL). A lot of these are being converted using optional groups, and I want to make it at least possible for user code to introspect those functions and understand that those are optional parameters.
My original plan was to add a "group" member, containing an arbitrary identifier of the "group" this parameter belongs to. I'm not sure that's sufficient; I may also need a "parent_group" parameter, or something like that, to represent the group that this group is nested in. I'm still thinking about it. But I'm hoping to get to this in the next two or three days.
Sounds reasonable - we'll need that to convert range() and slice()
anyway (I totally failed at finding time to look at the builtins this
weekend, but I'd still like to handle those before the 3rd beta).
An alternative would be to actually add "ParameterGroup" as a new
class that contains parameters (assuming tuple isn't sufficient), so
the structure of the parameters more directly matches the underlying
signature.
YurySelivanov commented on Jan 19, 2014
YurySelivanovmannequin
Mannequin
More actions
Larry,
I saw your message on the tracker regarding adding support for parameters groups to the signature object. Would you mind if I join the discussion with my ideas of how this feature might be implemented?
Yury
On Sunday, January 19, 2014 at 5:44 AM, Larry Hastings wrote:
Larry Hastings added the comment:
I just want to mention, while we're all thinking about this stuff: I plan to enhance the Signature object to reflect "optional groups". Right now Signature objects cannot express parameters that are optional but don't have a published default. (e.g. a string parameter for a builtin having a default of NULL). A lot of these are being converted using optional groups, and I want to make it at least possible for user code to introspect those functions and understand that those are optional parameters.
My original plan was to add a "group" member, containing an arbitrary identifier of the "group" this parameter belongs to. I'm not sure that's sufficient; I may also need a "parent_group" parameter, or something like that, to represent the group that this group is nested in. I'm still thinking about it. But I'm hoping to get to this in the next two or three days.
Instead of keeping the check, we could just unconditionally convert exceptions from the signature call to a TypeError in order to maintain compatibility with the old external behaviour.
Agreed. See the new patch (getargsspec_02.patch)
Unfortunately, we have to keep the old 'ismethod' check in place for backwards compatibility purposes.
Larry,
The attached patch contains one failing unit-test: 'inspect.signature' returns 'None' for '_testapi.docstring_no_signature'. It should instead raise a ValueError.
There's a major difference between getfullargspec/getargspec and inspect.signature: getfullargspec shows you the "self" parameter for bound methods, and inspect.signature does not.
This is why help() (currently) shows bound parameters for methods implemented in Python, but doesn't show them for methods implemented in C. pydoc uses inspect.getfullargspec for pure Python functions and inspect.signature for builtins.
There's a major difference between getfullargspec/getargspec and inspect.signature: getfullargspec shows you the "self" parameter for bound methods, and inspect.signature does not.
Larry, yes, that's correct. The attached patch simulates this behaviour, with:
ifismethod(func):
func=func.__func__
I'm attaching 'getargsspec_03.patch', as the previous one (02) was a bit crippled.
Please review the final patch (getargsspec_04.patch). I'd like to commit it tomorrow.
This one is the last one (hopefully), and it supports builtin methods properly -- i.e. works around 'self' parameter correctly. To do that, I check if the '__text_signature__' starts with "($", etc.
New changeset 0fa2750c7241 by Yury Selivanov in branch 'default':
inspect.test.getfullargspec: Add a unittest to ensure correct annotations http://hg.python.org/cpython/rev/0fa2750c7241
Activity
voidspace commentedon Mar 19, 2013
inspect.getfullargspec (and potentially getargspec?) could *use* function.__signature__ if set. This allows functions that lie about their signature with the new introspection tool (Signature) to still work with older code.
1st1 commentedon Jan 11, 2014
Please consider the attached patch (getargsspec_01.patch).
It modifies 'getargspec' and 'getfullargspec' to use the 'inspect.signature' API. The entire test suite passes just fine.
This also will address issue bpo-16490.
I can also update the docs, if it's necessary.
1st1 commentedon Jan 17, 2014
Can somebody review the patch? I'd be cool if this lands in 3.4.
terryjreedy commentedon Jan 18, 2014
While I plan to change Idle code to use signature directly, instead of getfullargspec, I agree that changing inspect also, and in 3.4, is a good idea. It may, however, affect tests other than Idle's, if there are any other stdlib consumers. I will try to look at the patch after changing Idle.
ncoghlan commentedon Jan 19, 2014
I upgraded the description to a "should". Argument Clinic and other changes in Python 3.4 greatly improve introspection support for various aspects of the runtime and standard library (for example, bpo-20223 will handle the new functools.partialmethod support). By also making those enhancements available via getfullargpsec, we should significantly increase the amount of existing code which benefits automatically for those enhancements, as it will no longer require explicit migration to the new PEP-362 APIs at the application/library level.
Reviewing the patch now.
[-]inspect.getfullargspec could use __signature__[/-][+]inspect.getfullargspec should use __signature__[/+]larryhastings commentedon Jan 19, 2014
If we modify inspect.getfullargspec, shouldn't we modify inspect.getargspec too? "deprecated" doesn't mean "unsupported", it means "not recommended for new code, please stop using it".
1st1 commentedon Jan 19, 2014
Larry,
getargspec uses getfullargspec, so it's covered.
ncoghlan commentedon Jan 19, 2014
getargspec() is just a thin wrapper around getfullargspec(), so we get that for free.
Similarly, getcallargs() is also implicitly updated to full PEP-362 support by changing the implementation of getfullargspec().
The other two standard library consumers appear to be IDLE (as Terry noted above) and xmlrpc.server.ServerHTMLDoc.docroutine (the self-documenting XML-RPC server API, which sadly appears to be lacking test cases).
Reviewing those cases (especially the XML-RPC one) have convinced me we need a backwards compatibility fallback in the updated getfullargspec implementation. Specifically, if the new API throws ValueError (because it can't find a way to build a coherent signature object), we should fall back to the old approach. Otherwise we run the risk of introducing unexpected exceptions into introspection code.
That is, the new call to signature in getfullargspec should look something like:
I suspect this may actually be a better solution for IDLE rather than updating it to call inspect.signature directly (since IDLE probably *wants* the more graceful fallback to the old behaviour).
The way I would document all this in What's New is to update the current argument clinic section to also explain that we've taken advantage of PEP-362 to improve introspection in multiple areas, including for code that is using the introspection APIs that predate PEP-362.
terryjreedy commentedon Jan 19, 2014
The relevant code in CallTips.py is
argspec = ""
if hasattr(ob, '__call__'):
...
if isinstance(fob, (types.FunctionType, types.MethodType)):
argspec = inspect.formatargspec(*inspect.getfullargspec(fob))
So I want to broaden the second condition (or remove it), but if it returns something .formatargspec cannot digest, the outer call will have to be conditioned. My impression is that str(signature object) returns pretty much what .formatargspec does, but I have not experimented yet.
My bpo-20122 patch moves currently commented out tests in CallTips.py that use the above to test_calltips.py. I will commit as soon as I test on 3.4. Until then, getfullargspec is not being used in the Idle test suite.
larryhastings commentedon Jan 19, 2014
I just want to mention, while we're all thinking about this stuff: I plan to enhance the Signature object to reflect "optional groups". Right now Signature objects cannot express parameters that are optional but don't have a published default. (e.g. a string parameter for a builtin having a default of NULL). A lot of these are being converted using optional groups, and I want to make it at least possible for user code to introspect those functions and understand that those are optional parameters.
My original plan was to add a "group" member, containing an arbitrary identifier of the "group" this parameter belongs to. I'm not sure that's sufficient; I may also need a "parent_group" parameter, or something like that, to represent the group that this group is nested in. I'm still thinking about it. But I'm hoping to get to this in the next two or three days.
ncoghlan commentedon Jan 19, 2014
Sounds reasonable - we'll need that to convert range() and slice()
anyway (I totally failed at finding time to look at the builtins this
weekend, but I'd still like to handle those before the 3rd beta).
An alternative would be to actually add "ParameterGroup" as a new
class that contains parameters (assuming tuple isn't sufficient), so
the structure of the parameters more directly matches the underlying
signature.
YurySelivanov commentedon Jan 19, 2014
Larry,
I saw your message on the tracker regarding adding support for parameters groups to the signature object. Would you mind if I join the discussion with my ideas of how this feature might be implemented?
Yury
On Sunday, January 19, 2014 at 5:44 AM, Larry Hastings wrote:
7 remaining items
1st1 commentedon Jan 20, 2014
Agreed. See the new patch (getargsspec_02.patch)
Unfortunately, we have to keep the old 'ismethod' check in place for backwards compatibility purposes.
Larry,
The attached patch contains one failing unit-test: 'inspect.signature' returns 'None' for '_testapi.docstring_no_signature'. It should instead raise a ValueError.
1st1 commentedon Jan 20, 2014
Larry,
I created a separate issue for that: http://bugs.python.org/issue20313
1st1 commentedon Jan 23, 2014
Larry, Nick,
So what's the resolution on this one? Do I have a green light?
larryhastings commentedon Jan 23, 2014
My solution for pydoc was to call isroutine() instead of isfunction(), and yes handle it throwing an exception.
(I just checked, and I wasn't catching TypeError, only ValueError. I'll fix that in my next patch for bpo-20189.)
ncoghlan commentedon Jan 24, 2014
Another case of "don't land it until Larry has dealt with the builtins".
The patch itself looks fine, though :)
larryhastings commentedon Jan 24, 2014
The patch from bpo-20189 has landed.
larryhastings commentedon Jan 25, 2014
There's a major difference between getfullargspec/getargspec and inspect.signature: getfullargspec shows you the "self" parameter for bound methods, and inspect.signature does not.
This is why help() (currently) shows bound parameters for methods implemented in Python, but doesn't show them for methods implemented in C. pydoc uses inspect.getfullargspec for pure Python functions and inspect.signature for builtins.
1st1 commentedon Jan 27, 2014
Larry, yes, that's correct. The attached patch simulates this behaviour, with:
I'm attaching 'getargsspec_03.patch', as the previous one (02) was a bit crippled.
1st1 commentedon Jan 28, 2014
Larry and Nick,
Please review the final patch (getargsspec_04.patch). I'd like to commit it tomorrow.
This one is the last one (hopefully), and it supports builtin methods properly -- i.e. works around 'self' parameter correctly. To do that, I check if the '__text_signature__' starts with "($", etc.
python-dev commentedon Jan 29, 2014
New changeset 6d1e8162e855 by Yury Selivanov in branch 'default':
inspect.getfullargspec: Use inspect.signature API behind the scenes bpo-17481
http://hg.python.org/cpython/rev/6d1e8162e855
1st1 commentedon Jan 29, 2014
Committed.
Thanks for the reviews!
python-dev commentedon Jan 29, 2014
New changeset 0fa2750c7241 by Yury Selivanov in branch 'default':
inspect.test.getfullargspec: Add a unittest to ensure correct annotations
http://hg.python.org/cpython/rev/0fa2750c7241