pyo3 icon indicating copy to clipboard operation
pyo3 copied to clipboard

adding a text_signature to a function breaks inspect.signature()

Open DanielT opened this issue 11 months ago • 4 comments

Bug Description

I started adding text_signature annotations to my python module, in order to offer better support for IDEs. When trying to read back my new annotations with inspect.signature(), I got a ValueError. Before adding the text_signature it worked, but only provided the automatically derived information.

Steps to Reproduce

My code:

#[pymethods]
struct Test {
    #[pyo3(text_signature = "(self, greet_text: str) -> None")] // <- this is new
    fn hello(&self, greet_text: &str) {
        // ...
    }
}

Before adding the text_signature:

>>> import mymodule
>>> import inspect
>>> inspect.signature(mymodule.Test.hello)
<Signature (self, /, greet_text)>

after adding the text_signature:

>>> import mymodule
>>> import inspect
>>> inspect.signature(mymodule.Test.hello)
Traceback (most recent call last):
  File "<python-input-2>", line 1, in <module>
    inspect.signature(mymodule.Test.hello)
    ~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\inspect.py", line 3344, in signature
    return Signature.from_callable(obj, follow_wrapped=follow_wrapped,
           ~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                   globals=globals, locals=locals, eval_str=eval_str)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Program Files\Python313\Lib\inspect.py", line 3070, in from_callable
    return _signature_from_callable(obj, sigcls=cls,
                                    follow_wrapper_chains=follow_wrapped,
                                    globals=globals, locals=locals, eval_str=eval_str)
  File "C:\Program Files\Python313\Lib\inspect.py", line 2582, in _signature_from_callable
    return _signature_from_builtin(sigcls, obj,
                                   skip_bound_arg=skip_bound_arg)
  File "C:\Program Files\Python313\Lib\inspect.py", line 2368, in _signature_from_builtin
    raise ValueError("no signature found for builtin {!r}".format(func))
ValueError: no signature found for builtin <method 'hello' of 'mymodule.Test' objects>

After some poking around I found that the __text__signature__ attribute is now missing:

>>> mymodule.Test.hello.__text__signature__ is None
True

This looks like a bug to me.

Backtrace


Your operating system and version

Windows 10

Your Python version (python --version)

Python 3.13.2

Your Rust version (rustc --version)

rust 1.85

Your PyO3 version

0.23.4

How did you install python? Did you use a virtualenv?

I'm using a venv, which I re-created before reporting this bug, just to make sure I wasn't chasing an already-fixed bug

Additional Info

No response

DanielT avatar Feb 23 '25 16:02 DanielT

I've also discovered that the function signature turns up in __doc__ when __text_signature__ is broken

DanielT avatar Feb 23 '25 19:02 DanielT

I figured it out - the text signature does not support a return type, so adding -> None made my signature invalid

DanielT avatar Feb 23 '25 20:02 DanielT

@DanielT is -> None always invalid here or is it only invalid for your use case? If the former, I think we should re-open and aim to fail to compile here.

LilyFirefly avatar Feb 23 '25 23:02 LilyFirefly

The return type is always invalid here. I dug into the CPython source code, and it is looking for a separator pattern between the text signature and the doc comment, and that pattern must end with a ")" on the text signature.

Edit: Additonally, as far as I can tell inspect.signature would be unable to handle the return type while building a Signature object

DanielT avatar Feb 23 '25 23:02 DanielT