Uh oh!
There was an error while loading. Please reload this page.
gh-73536: Add support for multi-signatures - #117671
Conversation
* Add inspect.MultiSignature which is a subclass of inspect.Signature. * Add inspect.signatures(). * inspect.signature() can now return a multi-signature. * Support multi-signatures in pydoc. * Support multi-signatures in IDLE calltips. * Support multi-signatures in dataclasses docstrings. * Allow multiple @text_signature in Argument Clinic. * Add representable signatures for all builtin functions and methods of builtin classes except type() and super().
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| def _multisignature_get_partial(wrapped_sig, partial, extra_args=()): | ||
| last_exc = None |
There was a problem hiding this comment.
Unless the case of the list being empty is handled elsewhere, this could result in a raise None. Maybe that None should instead be something like Exception("Empty MultiSignature list") ?
There was a problem hiding this comment.
It is checked in the constructor. I think even about removing this assignment, NameError is clearer indication if something goes wrong.
| return True | ||
| if isinstance(other, MultiSignature): | ||
| return self._signatures == other._signatures | ||
| if len(self._signatures) == 1 and isinstance(other, Signature): |
There was a problem hiding this comment.
I think this should be
| iflen(self._signatures) ==1andisinstance(other, Signature): | |
| ifisinstance(other, Signature): | |
| returnlen(self._signatures) ==1 |
and the addition to Signature's eq should be removed, above.
There was a problem hiding this comment.
No, it is not correct, it would make a 1-element MultiSignature equal to any Signature.
You perhaps mistyped, I wrote more correct fix.
There was a problem hiding this comment.
I did. That's good. (I would suggest removing the line about MultiSignature in Signature's eq as I believe it's dead code now, but up to you).
There was a problem hiding this comment.
It is not dead. It is called in SignatureSubclass() == MultiSignature(). Although it is not covered by tests yet.
| def signature(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False): | ||
| """Get a signature object for the passed callable.""" | ||
| return Signature.from_callable(obj, follow_wrapped=follow_wrapped, |
There was a problem hiding this comment.
Given that the original Signature.from_callable is not changed and does the exact same call to _from_callable, that means both signature and Signature.from_callable may return a MultiSignature object, right ?
Strictly speaking this is not a violation of backwards compatibility as MultiSignature is a subclass of Signature, but I find it weird and it may break some strict-type behaviors. Is there a way to have those only return pure Signature objects, without breaking everything this update brings to the table ?
There was a problem hiding this comment.
Yes, it is. The idea was that inspect.signature() will start to support previously not supported cases and return a MultiSignature which should be compatible with Signature. But now I am no longer sure. They are not so well compatible as I expected, and in most cases I needed to rewrite the code to explicitly handle MultiSignature. This is why I added inspect.signatures(). Now the code is in the intermediate state -- either MultiSignature will be made more compatible with Signature and inspect.signatures() may disappear, or they will became completely different things.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
| def _multisignature_get_partial(wrapped_sig, partial, extra_args=()): | ||
| last_exc = None |
There was a problem hiding this comment.
It is checked in the constructor. I think even about removing this assignment, NameError is clearer indication if something goes wrong.
Uh oh!
There was an error while loading. Please reload this page.
| return True | ||
| if isinstance(other, MultiSignature): | ||
| return self._signatures == other._signatures | ||
| if len(self._signatures) == 1 and isinstance(other, Signature): |
There was a problem hiding this comment.
No, it is not correct, it would make a 1-element MultiSignature equal to any Signature.
You perhaps mistyped, I wrote more correct fix.
| def signature(obj, *, follow_wrapped=True, globals=None, locals=None, eval_str=False): | ||
| """Get a signature object for the passed callable.""" | ||
| return Signature.from_callable(obj, follow_wrapped=follow_wrapped, |
There was a problem hiding this comment.
Yes, it is. The idea was that inspect.signature() will start to support previously not supported cases and return a MultiSignature which should be compatible with Signature. But now I am no longer sure. They are not so well compatible as I expected, and in most cases I needed to rewrite the code to explicitly handle MultiSignature. This is why I added inspect.signatures(). Now the code is in the intermediate state -- either MultiSignature will be made more compatible with Signature and inspect.signatures() may disappear, or they will became completely different things.
skirpichev
commented
Oct 29, 2024
@serhiy-storchaka, now this again has conflicts with the main. I did pr serhiy-storchaka#22 that address this, hope it helps. Are you thinking about writing a PEP as Petr suggested? |
skirpichev
commented
Feb 24, 2025
@serhiy-storchaka, will you be ok if I continue this work in a separate pr? Or you disappointed in this approach? |
Version-specific patches adapted from existing ones: - relocatable-python-config: same change as 3.x-0001 but adjusted for line offset in 3.13+ python-config.sh.in (shared between 3.13 and 3.14 since the file is identical) - remove-module-deps: removes ProjectDependencies from the python project in PCbuild/pcbuild.sln (separate patches for 3.13 and 3.14 due to different GUID sets) - _ctypes-ffi (3.13 only): converts static formattable[] array to dynamic initialization for shared libffi compatibility. Not needed for 3.14 where this was fixed upstream by restructuring cfield.c into a named struct (python/cpython#117671) The _msi-vcxproj patch is no longer needed since msilib was removed in 3.13 per PEP 594 (python/cpython#104911).
This PR is stale because it has been open for 30 days with no activity. |
Uh oh!
There was an error while loading. Please reload this page.