mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 06:35:12 +00:00
Add option for enable/disable enum members in docstring. (#2768)
* Add option for enable/disable enum members in docstring * Add tests for disable enum members docstring option * Add docstring options to documentation * style: pre-commit fixes * Fix typos in documentation * Improve documentation wording * Apply suggestions by @Skylion007 Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Ralf W. Grosse-Kunstleve <rwgk@google.com>
This commit is contained in:
parent
65374c8e62
commit
00126859a5
@ -324,6 +324,15 @@ The class ``options`` allows you to selectively suppress auto-generated signatur
|
||||
m.def("add", [](int a, int b) { return a + b; }, "A function which adds two numbers");
|
||||
}
|
||||
|
||||
pybind11 also appends all members of an enum to the resulting enum docstring.
|
||||
This default behavior can be disabled by using the ``disable_enum_members_docstring()``
|
||||
function of the ``options`` class.
|
||||
|
||||
With ``disable_user_defined_docstrings()`` all user defined docstrings of
|
||||
``module_::def()``, ``class_::def()`` and ``enum_()`` are disabled, but the
|
||||
function signatures and enum members are included in the docstring, unless they
|
||||
are disabled separately.
|
||||
|
||||
Note that changes to the settings affect only function bindings created during the
|
||||
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.
|
||||
|
@ -47,6 +47,16 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
options &disable_enum_members_docstring() & {
|
||||
global_state().show_enum_members_docstring = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
options &enable_enum_members_docstring() & {
|
||||
global_state().show_enum_members_docstring = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Getter methods (return the global state):
|
||||
|
||||
static bool show_user_defined_docstrings() {
|
||||
@ -55,6 +65,10 @@ public:
|
||||
|
||||
static bool show_function_signatures() { return global_state().show_function_signatures; }
|
||||
|
||||
static bool show_enum_members_docstring() {
|
||||
return global_state().show_enum_members_docstring;
|
||||
}
|
||||
|
||||
// This type is not meant to be allocated on the heap.
|
||||
void *operator new(size_t) = delete;
|
||||
|
||||
@ -63,6 +77,8 @@ private:
|
||||
bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings.
|
||||
bool show_function_signatures = true; //< Include auto-generated function signatures
|
||||
// in docstrings.
|
||||
bool show_enum_members_docstring = true; //< Include auto-generated member list in enum
|
||||
// docstrings.
|
||||
};
|
||||
|
||||
static state &global_state() {
|
||||
|
@ -1972,29 +1972,35 @@ struct enum_base {
|
||||
name("name"),
|
||||
is_method(m_base));
|
||||
|
||||
m_base.attr("__doc__") = static_property(
|
||||
cpp_function(
|
||||
[](handle arg) -> std::string {
|
||||
std::string docstring;
|
||||
dict entries = arg.attr("__entries");
|
||||
if (((PyTypeObject *) arg.ptr())->tp_doc) {
|
||||
docstring += std::string(((PyTypeObject *) arg.ptr())->tp_doc) + "\n\n";
|
||||
}
|
||||
docstring += "Members:";
|
||||
for (auto kv : entries) {
|
||||
auto key = std::string(pybind11::str(kv.first));
|
||||
auto comment = kv.second[int_(1)];
|
||||
docstring += "\n\n " + key;
|
||||
if (!comment.is_none()) {
|
||||
docstring += " : " + (std::string) pybind11::str(comment);
|
||||
if (options::show_enum_members_docstring()) {
|
||||
m_base.attr("__doc__") = static_property(
|
||||
cpp_function(
|
||||
[](handle arg) -> std::string {
|
||||
std::string docstring;
|
||||
dict entries = arg.attr("__entries");
|
||||
if (((PyTypeObject *) arg.ptr())->tp_doc) {
|
||||
docstring += std::string(
|
||||
reinterpret_cast<PyTypeObject *>(arg.ptr())->tp_doc);
|
||||
docstring += "\n\n";
|
||||
}
|
||||
}
|
||||
return docstring;
|
||||
},
|
||||
name("__doc__")),
|
||||
none(),
|
||||
none(),
|
||||
"");
|
||||
docstring += "Members:";
|
||||
for (auto kv : entries) {
|
||||
auto key = std::string(pybind11::str(kv.first));
|
||||
auto comment = kv.second[int_(1)];
|
||||
docstring += "\n\n ";
|
||||
docstring += key;
|
||||
if (!comment.is_none()) {
|
||||
docstring += " : ";
|
||||
docstring += pybind11::str(comment).cast<std::string>();
|
||||
}
|
||||
}
|
||||
return docstring;
|
||||
},
|
||||
name("__doc__")),
|
||||
none(),
|
||||
none(),
|
||||
"");
|
||||
}
|
||||
|
||||
m_base.attr("__members__") = static_property(cpp_function(
|
||||
[](handle arg) -> dict {
|
||||
|
@ -85,4 +85,57 @@ TEST_SUBMODULE(docstring_options, m) {
|
||||
&DocstringTestFoo::setValue,
|
||||
"This is a property docstring");
|
||||
}
|
||||
|
||||
{
|
||||
enum class DocstringTestEnum1 { Member1, Member2 };
|
||||
|
||||
py::enum_<DocstringTestEnum1>(m, "DocstringTestEnum1", "Enum docstring")
|
||||
.value("Member1", DocstringTestEnum1::Member1)
|
||||
.value("Member2", DocstringTestEnum1::Member2);
|
||||
}
|
||||
|
||||
{
|
||||
py::options options;
|
||||
options.enable_enum_members_docstring();
|
||||
|
||||
enum class DocstringTestEnum2 { Member1, Member2 };
|
||||
|
||||
py::enum_<DocstringTestEnum2>(m, "DocstringTestEnum2", "Enum docstring")
|
||||
.value("Member1", DocstringTestEnum2::Member1)
|
||||
.value("Member2", DocstringTestEnum2::Member2);
|
||||
}
|
||||
|
||||
{
|
||||
py::options options;
|
||||
options.disable_enum_members_docstring();
|
||||
|
||||
enum class DocstringTestEnum3 { Member1, Member2 };
|
||||
|
||||
py::enum_<DocstringTestEnum3>(m, "DocstringTestEnum3", "Enum docstring")
|
||||
.value("Member1", DocstringTestEnum3::Member1)
|
||||
.value("Member2", DocstringTestEnum3::Member2);
|
||||
}
|
||||
|
||||
{
|
||||
py::options options;
|
||||
options.disable_user_defined_docstrings();
|
||||
|
||||
enum class DocstringTestEnum4 { Member1, Member2 };
|
||||
|
||||
py::enum_<DocstringTestEnum4>(m, "DocstringTestEnum4", "Enum docstring")
|
||||
.value("Member1", DocstringTestEnum4::Member1)
|
||||
.value("Member2", DocstringTestEnum4::Member2);
|
||||
}
|
||||
|
||||
{
|
||||
py::options options;
|
||||
options.disable_user_defined_docstrings();
|
||||
options.disable_enum_members_docstring();
|
||||
|
||||
enum class DocstringTestEnum5 { Member1, Member2 };
|
||||
|
||||
py::enum_<DocstringTestEnum5>(m, "DocstringTestEnum5", "Enum docstring")
|
||||
.value("Member1", DocstringTestEnum5::Member1)
|
||||
.value("Member2", DocstringTestEnum5::Member2);
|
||||
}
|
||||
}
|
||||
|
@ -39,3 +39,26 @@ def test_docstring_options():
|
||||
# Suppression of user-defined docstrings for non-function objects
|
||||
assert not m.DocstringTestFoo.__doc__
|
||||
assert not m.DocstringTestFoo.value_prop.__doc__
|
||||
|
||||
# Check existig behaviour of enum docstings
|
||||
assert (
|
||||
m.DocstringTestEnum1.__doc__
|
||||
== "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
|
||||
)
|
||||
|
||||
# options.enable_enum_members_docstring()
|
||||
assert (
|
||||
m.DocstringTestEnum2.__doc__
|
||||
== "Enum docstring\n\nMembers:\n\n Member1\n\n Member2"
|
||||
)
|
||||
|
||||
# options.disable_enum_members_docstring()
|
||||
assert m.DocstringTestEnum3.__doc__ == "Enum docstring"
|
||||
|
||||
# options.disable_user_defined_docstrings()
|
||||
assert m.DocstringTestEnum4.__doc__ == "Members:\n\n Member1\n\n Member2"
|
||||
|
||||
# options.disable_user_defined_docstrings()
|
||||
# options.disable_enum_members_docstring()
|
||||
# When all options are disabled, no docstring (instead of an empty one) should be generated
|
||||
assert m.DocstringTestEnum5.__doc__ is None
|
||||
|
Loading…
Reference in New Issue
Block a user