support docstrings in enum::value() (#1160)
diff --git a/docs/changelog.rst b/docs/changelog.rst
index b0d958d..ec8dc72 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -18,6 +18,9 @@
* Added support for write only properties.
`#1144 <https://github.com/pybind/pybind11/pull/1144>`_.
+* The ``value()`` method of ``py::enum_`` now accepts an optional docstring
+ that will be shown in the documentation of the associated enumeration.
+
v2.2.1 (September 14, 2017)
-----------------------------------------------------
diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h
index b489bb2..5bd2ccc 100644
--- a/include/pybind11/pybind11.h
+++ b/include/pybind11/pybind11.h
@@ -1375,15 +1375,30 @@
auto m_entries_ptr = m_entries.inc_ref().ptr();
def("__repr__", [name, m_entries_ptr](Type value) -> pybind11::str {
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
- if (pybind11::cast<Type>(kv.second) == value)
+ if (pybind11::cast<Type>(kv.second[int_(0)]) == value)
return pybind11::str("{}.{}").format(name, kv.first);
}
return pybind11::str("{}.???").format(name);
});
- def_property_readonly_static("__members__", [m_entries_ptr](object /* self */) {
+ def_property_readonly_static("__doc__", [m_entries_ptr](handle self) {
+ std::string docstring;
+ const char *tp_doc = ((PyTypeObject *) self.ptr())->tp_doc;
+ if (tp_doc)
+ docstring += std::string(tp_doc) + "\n\n";
+ docstring += "Members:";
+ for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
+ 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);
+ }
+ return docstring;
+ });
+ def_property_readonly_static("__members__", [m_entries_ptr](handle /* self */) {
dict m;
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr))
- m[kv.first] = kv.second;
+ m[kv.first] = kv.second[int_(0)];
return m;
}, return_value_policy::copy);
def(init([](Scalar i) { return static_cast<Type>(i); }));
@@ -1431,15 +1446,15 @@
/// Export enumeration entries into the parent scope
enum_& export_values() {
for (const auto &kv : m_entries)
- m_parent.attr(kv.first) = kv.second;
+ m_parent.attr(kv.first) = kv.second[int_(0)];
return *this;
}
/// Add an enumeration entry
- enum_& value(char const* name, Type value) {
+ enum_& value(char const* name, Type value, const char *doc = nullptr) {
auto v = pybind11::cast(value, return_value_policy::copy);
this->attr(name) = v;
- m_entries[pybind11::str(name)] = v;
+ m_entries[pybind11::str(name)] = std::make_pair(v, doc);
return *this;
}
diff --git a/tests/test_enum.cpp b/tests/test_enum.cpp
index 49f31ba..4cd14a9 100644
--- a/tests/test_enum.cpp
+++ b/tests/test_enum.cpp
@@ -15,9 +15,9 @@
EOne = 1,
ETwo
};
- py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic())
- .value("EOne", EOne)
- .value("ETwo", ETwo)
+ py::enum_<UnscopedEnum>(m, "UnscopedEnum", py::arithmetic(), "An unscoped enumeration")
+ .value("EOne", EOne, "Docstring for EOne")
+ .value("ETwo", ETwo, "Docstring for ETwo")
.export_values();
// test_scoped_enum
diff --git a/tests/test_enum.py b/tests/test_enum.py
index d8eff52..d3f5b4d 100644
--- a/tests/test_enum.py
+++ b/tests/test_enum.py
@@ -18,6 +18,22 @@
assert m.UnscopedEnum.__members__ == \
{"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo}
+ assert m.UnscopedEnum.__doc__ == \
+ '''An unscoped enumeration
+
+Members:
+
+ EOne : Docstring for EOne
+
+ ETwo : Docstring for ETwo''' or m.UnscopedEnum.__doc__ == \
+ '''An unscoped enumeration
+
+Members:
+
+ ETwo : Docstring for ETwo
+
+ EOne : Docstring for EOne'''
+
# no TypeError exception for unscoped enum ==/!= int comparisons
y = m.UnscopedEnum.ETwo
assert y == 2