pyo3 icon indicating copy to clipboard operation
pyo3 copied to clipboard

Docstrings for `#[new]` method implementations

Open davidhewitt opened this issue 1 year ago • 9 comments

Discussed in https://github.com/PyO3/pyo3/discussions/4280

Originally posted by djc June 23, 2024 When I write a docstring on a #[new] fn new() method in a #[pymethods] impl block, I would expect this to show up in the help() output for the type. Instead, the help() output seems to end up with a default docstring:

 |  Static methods defined here:
 |
 |  __new__(*args, **kwargs)
 |      Create and return a new object.  See help(type) for accurate signature.

Is there no way in Python's data model to enable a specific help string for this? The docstring for the type ends up making it into the output sort of next to the constructor type signature, so I guess I could use that. Just seems surprising.


I believe that it should be possible to do something similar to what we already do with the text_signature for #[new] to lift the rest of the documentation onto the class. But this needs some experimentation.

davidhewitt avatar Jul 09 '24 12:07 davidhewitt

If you can give me a few pointers, I might be able to take a look myself.

djc avatar Jul 09 '24 13:07 djc

So changing the exact message Create and return a new object. See help(type) for accurate signature. is probably not possible. These all come from the type "slot wrappers" which take just a function pointer to the C slot implementation and then use that to generate a member on the class.

The one place where we can add class-level documentation is in the Py_tp_doc slot.

We already use pyo3::impl_::class::PyTypeImpl::doc to add the "text signature" from #[new] into the class-level documentation. We could similarly lift docs from #[new]. I think the only question is where in the class level documentation we should apply the docs from #[new], if adding this in is a good idea.

davidhewitt avatar Jul 09 '24 14:07 davidhewitt

Does this also affect other magic methods like __lt__? Regardless of what I write on the Rust side, its docstring is always "Return self<value."

jfolz avatar Jul 30 '24 08:07 jfolz

Yes, the same is true of these. I think the Python "slots" don't allow for documentation to be added, we would need to ask the CPython team for this.

davidhewitt avatar Aug 02 '24 10:08 davidhewitt

That said, there is METH_COEXIST which would allow us to install our own Python-level __lt__ (which could then have documentation). This would be a change to the proc-macros but might be a good thing. 🤔

davidhewitt avatar Aug 02 '24 10:08 davidhewitt

TBF though, I just check what help(set.__lt__) says:

__lt__(self, value, /) unbound builtins.set method
    Return self<value.

If set doesn't care to overwrite its docstring with a more sensible explanation, why should I care? :D

jfolz avatar Aug 02 '24 11:08 jfolz

Looking at this with fresh eyes, I think PyO3 is already doing what needs to be done, and not sure there is anything for me to be done here.

djc avatar Sep 05 '24 11:09 djc

I think what's missing is setting the doc field in the PyMemberDef struct for each method. Looking at the code that sets up the PyMemberDef structs in create_type_object.rs (I think that's the correct spot), it doesn't look like the doc field is ever set.

ngoldbaum avatar Oct 08 '24 21:10 ngoldbaum

+1 to this, I came here to report this issue. I've got constructors that would greatly benefit from having docstrings

Walter-Reactor avatar Oct 12 '24 01:10 Walter-Reactor