Implement an enum_ property "name"

The property returns the enum_ value as a string.
For example:

>>> import module
>>> module.enum.VALUE
enum.VALUE
>>> str(module.enum.VALUE)
'enum.VALUE'
>>> module.enum.VALUE.name
'VALUE'

This is actually the equivalent of Boost.Python "name" property.
This commit is contained in:
Boris Staletic 2018-04-02 23:26:48 +02:00 committed by Jason Rhinelander
parent 6862cb9b35
commit 289e5d9cc2
3 changed files with 39 additions and 0 deletions

View File

@ -488,6 +488,24 @@ The entries defined by the enumeration type are exposed in the ``__members__`` p
>>> Pet.Kind.__members__ >>> Pet.Kind.__members__
{'Dog': Kind.Dog, 'Cat': Kind.Cat} {'Dog': Kind.Dog, 'Cat': Kind.Cat}
The ``name`` property returns the name of the enum value as a unicode string.
.. note::
It is also possible to use ``str(enum)``, however these accomplish different
goals. The following shows how these two approaches differ.
.. code-block:: pycon
>>> p = Pet( "Lucy", Pet.Cat )
>>> pet_type = p.type
>>> pet_type
Pet.Cat
>>> str(pet_type)
'Pet.Cat'
>>> pet_type.name
'Cat'
.. note:: .. note::
When the special tag ``py::arithmetic()`` is specified to the ``enum_`` When the special tag ``py::arithmetic()`` is specified to the ``enum_``

View File

@ -1364,6 +1364,7 @@ detail::initimpl::pickle_factory<GetState, SetState> pickle(GetState &&g, SetSta
template <typename Type> class enum_ : public class_<Type> { template <typename Type> class enum_ : public class_<Type> {
public: public:
using class_<Type>::def; using class_<Type>::def;
using class_<Type>::def_property_readonly;
using class_<Type>::def_property_readonly_static; using class_<Type>::def_property_readonly_static;
using Scalar = typename std::underlying_type<Type>::type; using Scalar = typename std::underlying_type<Type>::type;
@ -1381,6 +1382,13 @@ public:
} }
return pybind11::str("{}.???").format(name); return pybind11::str("{}.???").format(name);
}); });
def_property_readonly("name", [m_entries_ptr](Type value) -> pybind11::str {
for (const auto &kv : reinterpret_borrow<dict>(m_entries_ptr)) {
if (pybind11::cast<Type>(kv.second[int_(0)]) == value)
return pybind11::str(kv.first);
}
return pybind11::str("???");
});
def_property_readonly_static("__doc__", [m_entries_ptr](handle self) { def_property_readonly_static("__doc__", [m_entries_ptr](handle self) {
std::string docstring; std::string docstring;
const char *tp_doc = ((PyTypeObject *) self.ptr())->tp_doc; const char *tp_doc = ((PyTypeObject *) self.ptr())->tp_doc;

View File

@ -6,6 +6,19 @@ def test_unscoped_enum():
assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne" assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo" assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
assert str(m.EOne) == "UnscopedEnum.EOne" assert str(m.EOne) == "UnscopedEnum.EOne"
# name property
assert m.UnscopedEnum.EOne.name == "EOne"
assert m.UnscopedEnum.ETwo.name == "ETwo"
assert m.EOne.name == "EOne"
# name readonly
with pytest.raises(AttributeError):
m.UnscopedEnum.EOne.name = ""
# name returns a copy
foo = m.UnscopedEnum.EOne.name
foo = "bar"
assert m.UnscopedEnum.EOne.name == "EOne"
# __members__ property # __members__ property
assert m.UnscopedEnum.__members__ == \ assert m.UnscopedEnum.__members__ == \
{"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo} {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo}