mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-29 00:22:00 +00:00
Add enum value to enum repr (#2126)
This changes enum reprs to look like `<Enum.name: value>` similarly to the Python enum module. This keeps the str of enums as `Enum.name`, like the Python enum module.
This commit is contained in:
parent
5a8ec8e505
commit
5e6ec49652
@ -1486,6 +1486,16 @@ detail::initimpl::pickle_factory<GetState, SetState> pickle(GetState &&g, SetSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||||
|
|
||||||
|
inline str enum_name(handle arg) {
|
||||||
|
dict entries = arg.get_type().attr("__entries");
|
||||||
|
for (const auto &kv : entries) {
|
||||||
|
if (handle(kv.second[int_(0)]).equal(arg))
|
||||||
|
return pybind11::str(kv.first);
|
||||||
|
}
|
||||||
|
return "???";
|
||||||
|
}
|
||||||
|
|
||||||
struct enum_base {
|
struct enum_base {
|
||||||
enum_base(handle base, handle parent) : m_base(base), m_parent(parent) { }
|
enum_base(handle base, handle parent) : m_base(base), m_parent(parent) { }
|
||||||
|
|
||||||
@ -1495,29 +1505,21 @@ struct enum_base {
|
|||||||
auto static_property = handle((PyObject *) get_internals().static_property_type);
|
auto static_property = handle((PyObject *) get_internals().static_property_type);
|
||||||
|
|
||||||
m_base.attr("__repr__") = cpp_function(
|
m_base.attr("__repr__") = cpp_function(
|
||||||
[](handle arg) -> str {
|
[](object arg) -> str {
|
||||||
handle type = type::handle_of(arg);
|
handle type = type::handle_of(arg);
|
||||||
object type_name = type.attr("__name__");
|
object type_name = type.attr("__name__");
|
||||||
dict entries = type.attr("__entries");
|
return pybind11::str("<{}.{}: {}>").format(type_name, enum_name(arg), int_(arg));
|
||||||
for (auto kv : entries) {
|
|
||||||
object other = kv.second[int_(0)];
|
|
||||||
if (other.equal(arg))
|
|
||||||
return pybind11::str("{}.{}").format(type_name, kv.first);
|
|
||||||
}
|
|
||||||
return pybind11::str("{}.???").format(type_name);
|
|
||||||
}, name("__repr__"), is_method(m_base)
|
}, name("__repr__"), is_method(m_base)
|
||||||
);
|
);
|
||||||
|
|
||||||
m_base.attr("name") = property(cpp_function(
|
m_base.attr("name") = property(cpp_function(&enum_name, name("name"), is_method(m_base)));
|
||||||
|
|
||||||
|
m_base.attr("__str__") = cpp_function(
|
||||||
[](handle arg) -> str {
|
[](handle arg) -> str {
|
||||||
dict entries = type::handle_of(arg).attr("__entries");
|
object type_name = type::handle_of(arg).attr("__name__");
|
||||||
for (auto kv : entries) {
|
return pybind11::str("{}.{}").format(type_name, enum_name(arg));
|
||||||
if (handle(kv.second[int_(0)]).equal(arg))
|
|
||||||
return pybind11::str(kv.first);
|
|
||||||
}
|
|
||||||
return "???";
|
|
||||||
}, name("name"), is_method(m_base)
|
}, name("name"), is_method(m_base)
|
||||||
));
|
);
|
||||||
|
|
||||||
m_base.attr("__doc__") = static_property(cpp_function(
|
m_base.attr("__doc__") = static_property(cpp_function(
|
||||||
[](handle arg) -> std::string {
|
[](handle arg) -> std::string {
|
||||||
|
@ -7,6 +7,9 @@ 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"
|
||||||
|
assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
|
||||||
|
assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
|
||||||
|
assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
|
||||||
|
|
||||||
# name property
|
# name property
|
||||||
assert m.UnscopedEnum.EOne.name == "EOne"
|
assert m.UnscopedEnum.EOne.name == "EOne"
|
||||||
@ -143,6 +146,8 @@ def test_scoped_enum():
|
|||||||
def test_implicit_conversion():
|
def test_implicit_conversion():
|
||||||
assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
|
assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
|
||||||
assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
|
assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
|
||||||
|
assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
|
||||||
|
assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
|
||||||
|
|
||||||
f = m.ClassWithUnscopedEnum.test_function
|
f = m.ClassWithUnscopedEnum.test_function
|
||||||
first = m.ClassWithUnscopedEnum.EFirstMode
|
first = m.ClassWithUnscopedEnum.EFirstMode
|
||||||
@ -167,7 +172,7 @@ def test_implicit_conversion():
|
|||||||
x[f(first)] = 3
|
x[f(first)] = 3
|
||||||
x[f(second)] = 4
|
x[f(second)] = 4
|
||||||
# Hashing test
|
# Hashing test
|
||||||
assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
|
assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
|
||||||
|
|
||||||
|
|
||||||
def test_binary_operators():
|
def test_binary_operators():
|
||||||
|
Loading…
Reference in New Issue
Block a user