pybind11
pybind11 copied to clipboard
feat: add type signatures to docstrings of properties.
Description
Currently signatures with type information are generated into docstrings for functions.
This PR adds type information in docstrings of properties, like
value_property: int
Property documentation.
Generation of this type information is enabled by default, but can be disabled/enabled with the same setting py::options::disable_function_signatures
as for functions.
I did not consider it necessary to have separate settings for function and property signatures.
Suggested changelog entry:
* Add type signatures in docstrings of properties.
@frosch123 See also https://github.com/pybind/pybind11/issues/3815 which may also cause issues here with static properties.
I initiated our (Google's) global testing for this PR, to see if there is anything that trips over this change.
Quick update: Unfortunately I'm seeing breakages with at least two root causes. The total number of breakages is a few thousands (out of millions). I will try to drill down as soon as I get a chance.
After a couple hours drilling into a deep pile of tooling, and a guess ... the diff below fixes all breakages reported in my previous comment.
I don't have a full explanation. I know that MyPy's stubgen is in the mix, but not much more. There is also a script (currently not open source AFAIK) that post-processes the stubgen output to generate a .pyi file for pytype. I don't know if it is stubgen or the post-processing that stumbles over the name of the property.
What I'm seeing is something like this:
This part is manually edited and untested but hopefully close enough:
.def(py::init([](int left, int bottom, int width, int height) {
return Rect{left, bottom, width, height};
}),
py::arg("left"), py::arg("bottom"), py::arg("width"),
py::arg("height"));
.def_readwrite("left", &Rect::left)
.def_readwrite("bottom", &Rect::bottom)
.def_readwrite("width", &Rect::width)
.def_readwrite("height", &Rect::height);
.pyi file before this PR:
class Rect:
bottom: int
height: int
left: int
width: int
.pyi file with this PR:
class Rect:
bottom: bottom
height: height
left: left
width: width
I won't have time to drill into this much more. Does someone familiar with stubgen have a clue?
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -1384,18 +1384,18 @@ protected:
std::string doc;
if (rec_func != nullptr) {
if (pybind11::options::show_function_signatures()) {
- doc += name;
if (rec_func->signature != nullptr) {
std::string sig = rec_func->signature;
size_t ret = sig.rfind(" -> ");
if (ret != std::string::npos) {
- doc += ": ";
doc += sig.substr(ret + 4);
}
}
- doc += "\n\n";
}
if (rec_func->doc != nullptr && pybind11::options::show_user_defined_docstrings()) {
+ if (!doc.empty()) {
+ doc += "\n\n";
+ }
doc += rec_func->doc;
}
}
diff --git a/tests/test_class.py b/tests/test_class.py
--- a/tests/test_class.py
+++ b/tests/test_class.py
@@ -91,7 +91,7 @@ def test_docstrings(doc):
assert (
doc(UserType.value)
== """
- value: int
+ int
Get/set value using a property
"""
diff --git a/tests/test_docstring_options.py b/tests/test_docstring_options.py
--- a/tests/test_docstring_options.py
+++ b/tests/test_docstring_options.py
@@ -39,13 +39,13 @@ def test_docstring_options():
# Suppression of user-defined docstrings for non-function objects
assert not m.DocstringTestFoo.__doc__
- assert m.DocstringTestFoo.value_prop1.__doc__ == "value_prop1: int\n\n"
+ assert m.DocstringTestFoo.value_prop1.__doc__ == "int"
assert (
m.DocstringTestFoo.value_prop2.__doc__
- == "value_prop2: int\n\nThis is a property docstring"
+ == "int\n\nThis is a property docstring"
)
- assert m.DocstringTestFoo.value_prop3.__doc__ == "value_prop3: int\n\n"
+ assert m.DocstringTestFoo.value_prop3.__doc__ == "int"
assert not m.DocstringTestFoo.value_prop4.__doc__