mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 13:15:12 +00:00
Prepend all overload signatures to docstrings
This commit is contained in:
parent
a1d00916b2
commit
a4b246ae07
@ -365,6 +365,77 @@ Note that changes to the settings affect only function bindings created during t
|
|||||||
lifetime of the ``options`` instance. When it goes out of scope at the end of the module's init function,
|
lifetime of the ``options`` instance. When it goes out of scope at the end of the module's init function,
|
||||||
the default settings are restored to prevent unwanted side effects.
|
the default settings are restored to prevent unwanted side effects.
|
||||||
|
|
||||||
|
Overloaded functions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The docstring of an overloaded function is prepended with the signature of each overload.
|
||||||
|
All overload docstrings are then concatenated together
|
||||||
|
into sections that are separated by each function signature.
|
||||||
|
The prepended signatures can be read by tools like Sphinx.
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
m.def("add", [](int a, int b)->int { return a + b; },
|
||||||
|
"Add two integers together.");
|
||||||
|
m.def("add", [](float a, float b)->float { return a + b; },
|
||||||
|
"Add two floating point numbers together.");
|
||||||
|
}
|
||||||
|
|
||||||
|
The above example would produce the following docstring:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> help(example.add)
|
||||||
|
|
||||||
|
add(...)
|
||||||
|
| add(arg0: int, arg1: int) -> int
|
||||||
|
| add(arg0: float, arg1: float) -> float
|
||||||
|
| Overloaded function.
|
||||||
|
|
|
||||||
|
| 1. add(arg0: int, arg1: int) -> int
|
||||||
|
|
|
||||||
|
| Add two integers together.
|
||||||
|
|
|
||||||
|
| 2. add(arg0: float, arg1: float) -> float
|
||||||
|
|
|
||||||
|
| Add two floating point numbers together.
|
||||||
|
|
||||||
|
Calling ``options.disable_function_signatures()`` as shown previously
|
||||||
|
will cause the docstrings of overloaded functions to be generated without the section headings.
|
||||||
|
The prepended overload signatures will remain:
|
||||||
|
|
||||||
|
.. code-block:: cpp
|
||||||
|
|
||||||
|
PYBIND11_MODULE(example, m) {
|
||||||
|
py::options options;
|
||||||
|
options.disable_function_signatures();
|
||||||
|
|
||||||
|
m.def("add", [](int a, int b)->int { return a + b; },
|
||||||
|
"A function which adds two numbers.\n"); // Note the additional newline here.
|
||||||
|
m.def("add", [](float a, float b)->float { return a + b; },
|
||||||
|
"Internally, a simple addition is performed.");
|
||||||
|
m.def("add", [](const py::none&, const py::none&)->py::none { return py::none(); },
|
||||||
|
"Both numbers can be None, and None will be returned.");
|
||||||
|
}
|
||||||
|
|
||||||
|
The above example would produce the following docstring:
|
||||||
|
|
||||||
|
.. code-block:: pycon
|
||||||
|
|
||||||
|
>>> help(example.add)
|
||||||
|
add(...)
|
||||||
|
| add(arg0: int, arg1: int) -> int
|
||||||
|
| add(arg0: float, arg1: float) -> float
|
||||||
|
| add(arg0: None, arg1: None) -> None
|
||||||
|
| A function which adds two numbers.
|
||||||
|
|
|
||||||
|
| Internally, a simple addition is performed.
|
||||||
|
| Both numbers can be None, and None will be returned.
|
||||||
|
|
||||||
|
Not every overload must supply a docstring.
|
||||||
|
You may find it easier for a single overload to supply the entire docstring.
|
||||||
|
|
||||||
.. [#f4] http://www.sphinx-doc.org
|
.. [#f4] http://www.sphinx-doc.org
|
||||||
.. [#f5] http://github.com/pybind/python_example
|
.. [#f5] http://github.com/pybind/python_example
|
||||||
|
|
||||||
|
@ -610,11 +610,15 @@ protected:
|
|||||||
int index = 0;
|
int index = 0;
|
||||||
/* Create a nice pydoc rec including all signatures and
|
/* Create a nice pydoc rec including all signatures and
|
||||||
docstrings of the functions in the overload chain */
|
docstrings of the functions in the overload chain */
|
||||||
if (chain && options::show_function_signatures()) {
|
if (chain) {
|
||||||
// First a generic signature
|
for (auto *it = chain_start; it != nullptr; it = it->next) {
|
||||||
signatures += rec->name;
|
signatures += rec->name;
|
||||||
signatures += "(*args, **kwargs)\n";
|
signatures += it->signature;
|
||||||
signatures += "Overloaded function.\n\n";
|
signatures += "\n";
|
||||||
|
}
|
||||||
|
if (options::show_function_signatures()) {
|
||||||
|
signatures += "Overloaded function.\n\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Then specific overload signatures
|
// Then specific overload signatures
|
||||||
bool first_user_def = true;
|
bool first_user_def = true;
|
||||||
|
@ -27,8 +27,20 @@ TEST_SUBMODULE(docstring_options, m) {
|
|||||||
m.def("test_overloaded3", [](int) {}, py::arg("i"));
|
m.def("test_overloaded3", [](int) {}, py::arg("i"));
|
||||||
m.def("test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
|
m.def("test_overloaded3", [](double) {}, py::arg("d"), "Overload docstr");
|
||||||
|
|
||||||
|
m.def("test_overloaded4", [](int a, int b)->int { return a + b; },
|
||||||
|
"A function which adds two numbers.\n");
|
||||||
|
m.def("test_overloaded4", [](float a, float b)->float { return a + b; },
|
||||||
|
"Internally, a simple addition is performed.");
|
||||||
|
m.def("test_overloaded4", [](const py::none&, const py::none&)->py::none { return py::none(); },
|
||||||
|
"Both numbers can be None, and None will be returned.");
|
||||||
|
|
||||||
options.enable_function_signatures();
|
options.enable_function_signatures();
|
||||||
|
|
||||||
|
m.def("test_overloaded5", [](int a, int b)->int { return a + b; },
|
||||||
|
"Add two integers together.");
|
||||||
|
m.def("test_overloaded5", [](float a, float b)->float { return a + b; },
|
||||||
|
"Add two floating point numbers together.");
|
||||||
|
|
||||||
m.def("test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
|
m.def("test_function3", [](int, int) {}, py::arg("a"), py::arg("b"));
|
||||||
m.def("test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
m.def("test_function4", [](int, int) {}, py::arg("a"), py::arg("b"), "A custom docstring");
|
||||||
|
|
||||||
|
@ -10,13 +10,50 @@ def test_docstring_options():
|
|||||||
assert m.test_function2.__doc__ == "A custom docstring"
|
assert m.test_function2.__doc__ == "A custom docstring"
|
||||||
|
|
||||||
# docstring specified on just the first overload definition:
|
# docstring specified on just the first overload definition:
|
||||||
assert m.test_overloaded1.__doc__ == "Overload docstring"
|
assert m.test_overloaded1.__doc__ == (
|
||||||
|
"test_overloaded1(i: int) -> None\n"
|
||||||
|
"test_overloaded1(d: float) -> None\n"
|
||||||
|
"Overload docstring"
|
||||||
|
)
|
||||||
|
|
||||||
# docstring on both overloads:
|
# docstring on both overloads:
|
||||||
assert m.test_overloaded2.__doc__ == "overload docstring 1\noverload docstring 2"
|
assert m.test_overloaded2.__doc__ == (
|
||||||
|
"test_overloaded2(i: int) -> None\n"
|
||||||
|
"test_overloaded2(d: float) -> None\n"
|
||||||
|
"overload docstring 1\n"
|
||||||
|
"overload docstring 2"
|
||||||
|
)
|
||||||
|
|
||||||
# docstring on only second overload:
|
# docstring on only second overload:
|
||||||
assert m.test_overloaded3.__doc__ == "Overload docstr"
|
assert m.test_overloaded3.__doc__ == (
|
||||||
|
"test_overloaded3(i: int) -> None\n"
|
||||||
|
"test_overloaded3(d: float) -> None\n"
|
||||||
|
"Overload docstr"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check overload configuration behaviour matches the documentation
|
||||||
|
assert m.test_overloaded4.__doc__ == (
|
||||||
|
"test_overloaded4(arg0: int, arg1: int) -> int\n"
|
||||||
|
"test_overloaded4(arg0: float, arg1: float) -> float\n"
|
||||||
|
"test_overloaded4(arg0: None, arg1: None) -> None\n"
|
||||||
|
"A function which adds two numbers.\n\n"
|
||||||
|
"Internally, a simple addition is performed.\n"
|
||||||
|
"Both numbers can be None, and None will be returned."
|
||||||
|
)
|
||||||
|
|
||||||
|
assert m.test_overloaded5.__doc__ == (
|
||||||
|
"test_overloaded5(arg0: int, arg1: int) -> int\n"
|
||||||
|
"test_overloaded5(arg0: float, arg1: float) -> float\n"
|
||||||
|
"Overloaded function.\n"
|
||||||
|
"\n"
|
||||||
|
"1. test_overloaded5(arg0: int, arg1: int) -> int\n"
|
||||||
|
"\n"
|
||||||
|
"Add two integers together.\n"
|
||||||
|
"\n"
|
||||||
|
"2. test_overloaded5(arg0: float, arg1: float) -> float\n"
|
||||||
|
"\n"
|
||||||
|
"Add two floating point numbers together.\n"
|
||||||
|
)
|
||||||
|
|
||||||
# options.enable_function_signatures()
|
# options.enable_function_signatures()
|
||||||
assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None")
|
assert m.test_function3.__doc__.startswith("test_function3(a: int, b: int) -> None")
|
||||||
|
@ -88,7 +88,10 @@ def test_init_factory_signature(msg):
|
|||||||
assert (
|
assert (
|
||||||
msg(m.TestFactory1.__init__.__doc__)
|
msg(m.TestFactory1.__init__.__doc__)
|
||||||
== """
|
== """
|
||||||
__init__(*args, **kwargs)
|
__init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) -> None
|
||||||
|
__init__(self: m.factory_constructors.TestFactory1, arg0: str) -> None
|
||||||
|
__init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.pointer_tag) -> None
|
||||||
|
__init__(self: m.factory_constructors.TestFactory1, arg0: object, arg1: int, arg2: object) -> None
|
||||||
Overloaded function.
|
Overloaded function.
|
||||||
|
|
||||||
1. __init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) -> None
|
1. __init__(self: m.factory_constructors.TestFactory1, arg0: m.factory_constructors.tag.unique_ptr_tag, arg1: int) -> None
|
||||||
|
Loading…
Reference in New Issue
Block a user