-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Set the __text_signature__ attribute of callables #945
Comments
Thanks for pointing this out. I've been doing some research into function signatures in Python 3.x. TL;DR Bad news: We can't add There are a couple of issues with Instead, I think we can make use of |
@dean0x7d I wonder if you ever had a chance to look at it? I had a brief look, it would probably be the easiest to do it in pure Python rather than C++ (i.e. parse the signature strings that we generate in C++), but I'm not sure that would be acceptable. |
A side benefit of using So say for example there is an abstract base class defined in Python:
and an implementation of it using pybind11 that reimplements foo without setting a signature, then right now the docstring of foo (as rendered by pydoc or sphinx) would be the pybind11-generated signature, whereas it would be the docstring from the base class if pybind11 did not write its own |
I had a quick stab at it and it is in fact relatively easy to construct the signature object in initialize_generic (ignoring for now what we do with overloaded functions...), at the same time as the docstring-signature is constructed. The real problem is that there is nowhere to actually stash this information, because PyCFunctions do not have (AFAICT?) a |
Looks like this should wait until https://www.python.org/dev/peps/pep-0575/ (possibly Py 3.8) which will give us a |
Add support functions to extract partial function signatures from pybind11 functions via ast-based reparse of pybind11 generated docstring. (Workaround for pybind/pybind11#945) Add initial test coverage with basic c++-level overload, default args and template-based type signatures.
* Expand ignore_unused_kwargs for pybind11 compiled functions. Add support functions to extract partial function signatures from pybind11 functions via ast-based reparse of pybind11 generated docstring. (Workaround for pybind/pybind11#945) Add initial test coverage with basic c++-level overload, default args and template-based type signatures. * Update utility.args for numpy.vectorize and pybind11 types. Update utility.args signature resolution with overload for @numpy.vectorize wrapped functions, allowing ignore_unused_kwargs operation over vectorized test functions. Add baseline test of vecorized-wrapped functions. Update pybind11 docstring-based signature resolution to extract sanitized type annotations from signatures, intended to help while debugging pybind11 method invocation errors. Adds astor to core dependencies to allow regeneration of sanitized signatures for annotations. * Add bind_to_args utility. Add bind_to_args, binding arbitrary inputs into positional arguments. Used to convert param dicts into tuple for gradcheck.
Since PEP575 was withdrawn, is it sensible to pursue the I agree that |
For the regular user, in Linux, you can |
(I'm porting code from Cython to pybind11.) I need to know the parameter names for a function. (Previously, in Cython, |
@riddell-stan, I believe/am afraid it is; the C functions pybind11 exposes to Python do not work with |
@YannickJadoul Thanks! The relevant code wasn't too difficult to write. The relevant Cython compiler directive is described here: https://cython.readthedocs.io/en/latest/src/userguide/source_files_and_compilation.html#compiler-directives
|
@riddell-stan Right, thanks for that reference (never really worked with Cython before) :-) Reading this, I think pybind11 always goes with the first of those two possibilities :-/ |
For the record, the way >>> bisect.bisect_right.__text_signature__
'($module, /, a, x, lo=0, hi=None)'
>>> inspect.signature(bisect.bisect_right)
<Signature (a, x, lo=0, hi=None)> |
@pitrou, hmmm, interesting! Any idea if/how this can work together with the current situation, where we put the full signature (including return type) on the first line? For example, Sphinx autodoc picks up this first line, I believe. |
I think Sphinx autodoc picks up the generated |
But we do lose the signature's information about the return type? :-/ |
Hmm, that is an interesting concern. I had never thought about that. |
Apart from that, I'd love to look into it! If there's a way to provide this, and make all pybind11 functions more native-like, that would be amazing. There were a few other concerns, though, such as the fact that we cannot include type annotations (if that's still correct?): #945 (comment) Ideally, it would be great to support both the current signature as well as |
Here is how I gather things work, based on a real example At the C level,
But this is not what is exposed at the Python level, because >>> print(cmath.isclose.__text_signature__)
($module, /, a, b, *, rel_tol=1e-09, abs_tol=0.0)
>>> print(cmath.isclose.__doc__)
Determine whether two complex numbers are close in value.
[...] So I think that you could add your own signature below the generated text-signature, and your own signature would remain at the top of the Python-visible docstring, for example:
Do note that you cannot experiment on this with Python objects. The automatic extraction only happens on |
Ok, I asked, and you should be able to use type annotations in the text signature, including for the return type (worth checking it for real though :-)). |
@pitrou, thank you so much! I'll look into this, after we get the last few bugs out for 2.6.0! :-) |
I am coming from davidhalter/jedi#1388 and digging around this topic in the last few days. Stating the obvious, but I want to highlight how valuable this addition would be to all downstream projects! Autocompletion in python (only) works pretty well these days, but as soon as it hits binary modules (from pybind11) many language servers seem to struggle (Jedi, Pylance, microsoft-language-server). Explicit signature information through the |
+1 on this |
Strong +1 . Getting explicit type annotations will help tremendously with frameworks that use pybind classes to export functions from python to other computing contexts. |
+1, strong autocompletion is standard in every ide and for every language and library, binary modules must support it as well. |
Issue description
On recent enough Python versions (I think 3.4+), non-overloaded Python functions created by pybind11 could set the
__text_signature__
attribute to a textual representation of the function signature, instead of prepending it to the docstring (seeinspect._signature_from_builtin
in the stdlib). This attribute is recognized (and parsed) by at least pydoc and inspect.signature (and thus, I guess, Sphinx too, though I am not sure), so it would perform the task of communicating the function signature better than the current method.(Originally posted on gitter, it was suggested that I put the proposal here.)
Reproducible example code
N/A
The text was updated successfully, but these errors were encountered: