Title: Undeprecate inspect.getfullargspec()
Type: behavior Stage: needs patch
Components: Documentation Versions: Python 3.5
Status: open Resolution:
Dependencies: Superseder:
Assigned To: ncoghlan Nosy List: SilentGhost, eric.snow, larry, ncoghlan, ned.deily, python-dev, r.david.murray, ryan.petrello, serhiy.storchaka, yselivanov
Priority: deferred blocker Keywords: patch

Created on 2016-06-01 04:04 by ryan.petrello, last changed 2016-12-03 04:44 by ncoghlan.

File name Uploaded Description Edit
signature-from-callable-skip-bound-arg.patch ryan.petrello, 2016-06-01 04:04 review
signature-from-callable-skip-bound-arg.patch ryan.petrello, 2016-06-01 10:58 review
signature-from-callable-skip-bound-arg.patch ryan.petrello, 2016-06-01 17:27 review
signature-from-callable-skip-bound-arg.patch ryan.petrello, 2016-06-01 18:35 review
signature-from-callable-skip-bound-arg.patch ryan.petrello, 2016-06-01 19:09 review
issue27172_undeprecate_getfullargspec.diff ncoghlan, 2016-11-27 13:13 review
issue27172_undeprecate_getfullargspec_v2.diff ncoghlan, 2016-12-01 13:22 review
Messages (24)
msg266807 - (view) Author: SilentGhost (SilentGhost) * Date: 2016-06-01 07:58
This could only go in 3.6, but it needs proper documentation and test(s).
msg266813 - (view) Author: Ryan Petrello (ryan.petrello) Date: 2016-06-01 10:52
Thanks, I'll upload a new patch shortly that addresses these.
msg266832 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2016-06-01 18:17
Please don't commit this without my review.
msg266972 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2016-06-02 22:06
Nick, what do you think about this one?

I'm +1 to add this, but I'm not sure about the name for the argument. Do you have better ideas, or "skip_bound_arg" is good enough?
msg268932 - (view) Author: Ryan Petrello (ryan.petrello) Date: 2016-06-20 20:57

Any word on this?  I know it's minor, but I'd love to see this make it into Python3.6.
msg269016 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-06-21 19:43
Hi Ryan, sorry for the delayed response.

My own concern with this proposal is that I don't understand the use case for it. We changed the inspect.signature behaviour away from that of inspect.getfullargspec because we considered the latter behaviour to be *wrong*: it reported a parameter the already bound method didn't actually accept when called. The "skip_bound_arg" functionality then remains *within* the inspect module for the sake of providing backwards compatible implementations of getargspec and getfullargspec without duplicating a lot of other callable introspection logic.

If you can provide more information on the motivating use case, we can better determine if exposing this option directly is a suitable design response, or if there may be better alternatives available.
msg269071 - (view) Author: Ryan Petrello (ryan.petrello) Date: 2016-06-22 12:08

My use case is an issue of backwards compatibility and multiple Python version support for a library that makes prolific use of the legacy argspec (args, varargs, varkw, defaults) namedtuple, *including* the bound self argument behavior.  argspec and signature are quite different, and supporting a Py26-Py36 codebase that handles both simultaneously seemed like quite a burden, so I opted to write a compatibility shim that returned an Argspec-like object for all versions of Python;  this seemed the simplest approach to bridge the gap in a codebase that supports Python 2.6 through 3.6, and it's the approach that I've seen other major libraries (like Django) take:

I'm using a similar approach to Python 3.5's getfullargspec() implementation:

...but I don't have a long-term public API for doing it (so I have to rely on the private inspect._signature_from_callable call, which seems icky).
msg269081 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-06-22 18:46
Are you able to use inspect.getfullargspec() on Python 3 rather than inspect.getargspec()?

While both are technically deprecated, only inspect.getargspec() actually emits a deprecation warning - inspect.getfullargspec() still works without complaint and is in no danger of being removed.
msg269082 - (view) Author: Ryan Petrello (ryan.petrello) Date: 2016-06-22 20:01

My main reasoning for not using it is that it's marked as deprecated in the docstring, and I want to avoid relying on it if disappears in the future :)

Warnings or not, the shim that I wrote doesn't use any deprecated code, so that's why I took that approach.
msg269085 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-06-22 20:42
OK, so maybe the right answer here is to officially undeprecate inspect.getfullargspec(), as we definitely *don't* want people feeling obliged to write their own version of that, and potentially introducing inconsistencies between different tools.

Then the deprecation warning on inspect.getargspec() can be updated to point people towards "inspect.signature() or inspect.getfullargspec()", while the docs for getfullargspec() itself can be updated to say it isn't recommended for use in new code, rather than that it's deprecated.
msg269129 - (view) Author: Ryan Petrello (ryan.petrello) Date: 2016-06-23 18:06

That seems reasonable to me :)  I've updated my library to just use inspect.getfullargspec for Py3.  Thanks for taking the time to walk through this with me!
msg269130 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-06-23 18:18
OK, as per the above discussion, I've changed the title of this issue to be to undeprecate inspect.getfullargspec().

That change involves two pieces:

- change the documented deprecation of inspect.getfullargspec() to instead be a recommendation to avoid using it in new code, and instead use inspect.signature()
- update the inspect.getargspec() documentation and programmatic deprecation warning to point to both inspect.signature() and inspect.getfullargspec() as potential replacements

That gives folks already using inspect.getfullargspec assurance that it isn't going away anytime soon (if ever), while folks using inspect.getargspec get a lower impact migration path to a more Python 3 friendly version of the callable introspection API.
msg270121 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-07-10 18:29
The existing patch no longer addresses the revised decision about the API (or the new title of the issue).  So, we need a new patch.
msg270122 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2016-07-10 18:32
Also, this is now a documentation issue, though it does require a code change for the getargspec deprecation message.
msg281603 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-24 04:21
This just came up in a discussion on a urllib3 patch, so I'd like to fix it for 3.6.0rc1.

Ned, given that the code change here is just deleting the deprecation warning from getfullargspec() and rewording the one for getargspec(), does that seem OK for 3.6.0?
msg281604 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-24 04:35
When we undeprecate this, we should remove and reword the deprecation warnings in the next 3.5 maintenance release as well.

I'll need to decide on a way to indicate in the docs that some versions of 3.x.y will report a deprecation warning for getfullargspec() though - probably a "Changed in" note.
msg281605 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-11-24 05:12
Nick, that seems like the right thing to do.  Thanks for following up on it.
msg281825 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-11-27 13:13
Initial patch attached. Key missing pieces:

- needs a What's New note
- needs to undeprecate inspect.getcallargs() as well (more on that below)

As my last couple of comments indicate, I'd forgotten that only getargspec() was programmatically deprecated, which means the sole code change is a rewording of the getargspec() warning to mention both signature() and getfullargspec().

The documentation changes are a bit more extensive, as I couldn't resist fixing the longstanding terminology error in the docs and docstrings, where these functions are mostly reporting *parameter* names, not argument names (callable arguments have values, not names).

I think the "versionchanged" note works well for indicating that folks aren't imagining things if they remembered seeing this function marked as deprecated.

However, I also went back and checked the 3.5 What's New, and that does mention the deprecations, so I'll need to do another version of this patch that includes a 3.6 What's New notice retracting those deprecations.

That check also reveals some other documented deprecations that should probably be reverted.

Firstly, getargvalues() and formatargvalues() are *frame* introspection functions, and hence have nothing whatsoever to do with inspect.signature(). The code and docs are just a bit confusing as they're interleaved with the callable introspection functions. I've filed that as a new issue:

Secondly, notes that inspect.getcallargs() has some behaviours that differ from Signature.bind in a way that's a bit of a pain to replicate on top of the latter. Similar to getfullargspec(), what do folks think of the idea of reverting that deprecation at least until 2.7 goes EOL?

(Noting for the record so folks don't wonder if it's an accidental oversight: I think formatargspec should retain its documented deprecation, as folks really are better off writing their own formatting function based on the data returned or switching to the new signature API)
msg281884 - (view) Author: Yury Selivanov (yselivanov) * (Python committer) Date: 2016-11-28 16:31
Nick, your patch LGTM.  I'd only add to the getargspec section that getfullargspec is usually a drop-in replacement (I've yet to see code where it's not the case).
msg282174 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-12-01 13:22
Updated patch adding What's New and NEWS entries, and addressing Martin's review comments (mostly by accepting his suggestions).

I ended up leaving `inspect.getcallargs()` deprecated, and instead added a comment to issue 20438 noting how to achieve the bound args -> unbound args conversion in a general way:
msg282234 - (view) Author: Roundup Robot (python-dev) Date: 2016-12-02 10:35
New changeset 14c2d93ffcb3 by Nick Coghlan in branch '3.6':
Issue #27172: Undeprecate inspect.getfullargspec()
msg282235 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-12-02 10:38
I've pushed the change for 3.6.0rc1 based on Yury and Martin's review, but wasn't able to forward merge it to default due to merge conflicts on Misc/NEWS that I wasn't sure how to resolve.
msg282256 - (view) Author: Ned Deily (ned.deily) * (Python committer) Date: 2016-12-02 21:15
It looks like Serhiy took care of the merge to default in dd4c420b8e66.
msg282268 - (view) Author: Nick Coghlan (ncoghlan) * (Python committer) Date: 2016-12-03 04:44
Thank you Serhiy!

That leaves this just as a pending update for 3.5.3 to bring it into line with 3.6.0.

I've reverted the stage to "needs patch" and removed the patch keyword, as the 3.5 patch will be slightly different:

- using 3.5.3 in the versionchanged notice
- adjusting the 3.5 What's New to change the list of deprecated inspect module APIs
Date User Action Args
2016-12-03 04:44:16ncoghlansetstage: commit review -> needs patch
messages: + msg282268
versions: - Python 3.7
2016-12-02 21:15:32ned.deilysetnosy: + serhiy.storchaka
messages: + msg282256
2016-12-02 10:38:10ncoghlansetpriority: release blocker -> deferred blocker

stage: needs patch -> commit review
messages: + msg282235
versions: - Python 3.6
2016-12-02 10:35:13python-devsetnosy: + python-dev
messages: + msg282234
2016-12-01 13:22:33ncoghlansetfiles: + issue27172_undeprecate_getfullargspec_v2.diff

messages: + msg282174
2016-11-28 16:31:28yselivanovsetmessages: + msg281884
2016-11-27 13:13:20ncoghlansetfiles: + issue27172_undeprecate_getfullargspec.diff
keywords: + patch
messages: + msg281825
2016-11-24 05:12:02ned.deilysetpriority: normal -> release blocker
versions: + Python 3.7
nosy: + larry

messages: + msg281605
2016-11-24 04:35:06ncoghlansetmessages: + msg281604
versions: + Python 3.5
2016-11-24 04:21:25ncoghlansetassignee: ncoghlan

messages: + msg281603
nosy: + ned.deily
2016-07-10 18:32:26r.david.murraysetmessages: + msg270122

assignee: yselivanov -> (no value)
components: + Documentation, - Library (Lib)
keywords: - patch
type: enhancement -> behavior
2016-07-10 18:29:24r.david.murraysetnosy: + r.david.murray

messages: + msg270121
stage: commit review -> needs patch
2016-06-23 18:18:21ncoghlansetmessages: + msg269130
title: Add skip_bound_arg argument to inspect.Signature.from_callable() -> Undeprecate inspect.getfullargspec()
2016-06-23 18:06:17ryan.petrellosetmessages: + msg269129
2016-06-22 20:42:21ncoghlansetmessages: + msg269085
2016-06-22 20:01:58ryan.petrellosetmessages: + msg269082
2016-06-22 18:46:01ncoghlansetmessages: + msg269081
2016-06-22 12:08:34ryan.petrellosetmessages: + msg269071
2016-06-21 19:43:10ncoghlansetmessages: + msg269016
2016-06-20 20:57:57ryan.petrellosetmessages: + msg268932
2016-06-02 22:06:56yselivanovsetnosy: + ncoghlan
messages: + msg266972
2016-06-01 19:09:04ryan.petrellosetfiles: + signature-from-callable-skip-bound-arg.patch
2016-06-01 18:35:39ryan.petrellosetfiles: + signature-from-callable-skip-bound-arg.patch
2016-06-01 18:22:00SilentGhostsetassignee: yselivanov
stage: patch review -> commit review
2016-06-01 18:17:34yselivanovsetmessages: + msg266832
2016-06-01 18:10:19berker.peksagsetstage: test needed -> patch review
2016-06-01 17:27:06ryan.petrellosetfiles: + signature-from-callable-skip-bound-arg.patch
2016-06-01 11:46:48ryan.petrellosetnosy: + eric.snow
2016-06-01 10:58:53ryan.petrellosetfiles: + signature-from-callable-skip-bound-arg.patch
2016-06-01 10:52:23ryan.petrellosetmessages: + msg266813
2016-06-01 07:58:08SilentGhostsetversions: - Python 3.5
nosy: + SilentGhost, yselivanov

messages: + msg266807

stage: test needed
2016-06-01 04:17:26ryan.petrellosetversions: + Python 3.5
2016-06-01 04:04:50ryan.petrellocreate