Skip to content

Commit 6d19036

Browse files
authored
support docstrings in enum::value() (#1160)
1 parent 0a0758c commit 6d19036

File tree

4 files changed

+43
-9
lines changed

4 files changed

+43
-9
lines changed

docs/changelog.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ v2.3.0 (Not yet released)
1818
* Added support for write only properties.
1919
`#1144 <https://github.com/pybind/pybind11/pull/1144>`_.
2020

21+
* The ``value()`` method of ``py::enum_`` now accepts an optional docstring
22+
that will be shown in the documentation of the associated enumeration.
23+
2124
v2.2.1 (September 14, 2017)
2225
-----------------------------------------------------
2326

include/pybind11/pybind11.h

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,15 +1375,30 @@ template <typename Type> class enum_ : public class_<Type> {
13751375
auto m_entries_ptr = m_entries.inc_ref().ptr();
13761376
def("__repr__", [name, m_entries_ptr](Type value) -> pybind11::str {
13771377
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
1378-
if (pybind11::cast<Type>(kv.second) == value)
1378+
if (pybind11::cast<Type>(kv.second[int_(0)]) == value)
13791379
return pybind11::str("{}.{}").format(name, kv.first);
13801380
}
13811381
return pybind11::str("{}.???").format(name);
13821382
});
1383-
def_property_readonly_static("__members__", [m_entries_ptr](object /* self */) {
1383+
def_property_readonly_static("__doc__", [m_entries_ptr](handle self) {
1384+
std::string docstring;
1385+
const char *tp_doc = ((PyTypeObject *) self.ptr())->tp_doc;
1386+
if (tp_doc)
1387+
docstring += std::string(tp_doc) + "\n\n";
1388+
docstring += "Members:";
1389+
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
1390+
auto key = std::string(pybind11::str(kv.first));
1391+
auto comment = kv.second[int_(1)];
1392+
docstring += "\n\n " + key;
1393+
if (!comment.is_none())
1394+
docstring += " : " + (std::string) pybind11::str(comment);
1395+
}
1396+
return docstring;
1397+
});
1398+
def_property_readonly_static("__members__", [m_entries_ptr](handle /* self */) {
13841399
dict m;
13851400
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr))
1386-
m[kv.first] = kv.second;
1401+
m[kv.first] = kv.second[int_(0)];
13871402
return m;
13881403
}, return_value_policy::copy);
13891404
def(init([](Scalar i) { return static_cast<Type>(i); }));
@@ -1431,15 +1446,15 @@ template <typename Type> class enum_ : public class_<Type> {
14311446
/// Export enumeration entries into the parent scope
14321447
enum_& export_values() {
14331448
for (const auto &kv : m_entries)
1434-
m_parent.attr(kv.first) = kv.second;
1449+
m_parent.attr(kv.first) = kv.second[int_(0)];
14351450
return *this;
14361451
}
14371452

14381453
/// Add an enumeration entry
1439-
enum_& value(char const* name, Type value) {
1454+
enum_& value(char const* name, Type value, const char *doc = nullptr) {
14401455
auto v = pybind11::cast(value, return_value_policy::copy);
14411456
this->attr(name) = v;
1442-
m_entries[pybind11::str(name)] = v;
1457+
m_entries[pybind11::str(name)] = std::make_pair(v, doc);
14431458
return *this;
14441459
}
14451460

tests/test_enum.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ TEST_SUBMODULE(enums, m) {
1515
EOne = 1,
1616
ETwo
1717
};
18-
py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic())
19-
.value("EOne", EOne)
20-
.value("ETwo", ETwo)
18+
py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic(), "An unscoped enumeration")
19+
.value("EOne", EOne, "Docstring for EOne")
20+
.value("ETwo", ETwo, "Docstring for ETwo")
2121
.export_values();
2222

2323
// test_scoped_enum

tests/test_enum.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,22 @@ def test_unscoped_enum():
1818
assert m.UnscopedEnum.__members__ == \
1919
{"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo}
2020

21+
assert m.UnscopedEnum.__doc__ == \
22+
'''An unscoped enumeration
23+
24+
Members:
25+
26+
EOne : Docstring for EOne
27+
28+
ETwo : Docstring for ETwo''' or m.UnscopedEnum.__doc__ == \
29+
'''An unscoped enumeration
30+
31+
Members:
32+
33+
ETwo : Docstring for ETwo
34+
35+
EOne : Docstring for EOne'''
36+
2137
# no TypeError exception for unscoped enum ==/!= int comparisons
2238
y = m.UnscopedEnum.ETwo
2339
assert y == 2

0 commit comments

Comments
 (0)