Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion include/pybind11/detail/native_enum_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,13 @@ inline void native_enum_data::finalize() {
}
parent_scope.attr(enum_name) = py_enum;
if (export_values_flag) {
// Allow an already-exported Enum member with the same name to be replaced,
// so two native_enums can share exported value names (see issue #6031).
auto enum_base = import_or_getattr("enum.Enum", " (native_enum export_values)");
for (auto member : members) {
auto member_name = member[int_(0)];
if (hasattr(parent_scope, member_name)) {
if (hasattr(parent_scope, member_name)
&& !isinstance(parent_scope.attr(member_name), enum_base)) {
pybind11_fail("pybind11::native_enum<...>(\"" + enum_name_encoded + "\").value(\""
+ member_name.cast<std::string>()
+ "\"): an object with that name is already defined");
Expand Down
9 changes: 9 additions & 0 deletions tests/test_native_enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ enum class flags_uint : unsigned int { bit0 = 0x1u, bit1 = 0x2u, bit2 = 0x4u };

enum class export_values { exv0, exv1 };

enum class export_values2 { exv0, exv2 };

enum class member_doc { mem0, mem1, mem2 };

struct class_with_enum {
Expand Down Expand Up @@ -120,6 +122,13 @@ TEST_SUBMODULE(native_enum, m) {
.export_values()
.finalize();

// Shares "exv0" with export_values above (issue #6031).
py::native_enum<export_values2>(m, "export_values2", "enum.IntEnum")
.value("exv0", export_values2::exv0)
.value("exv2", export_values2::exv2)
.export_values()
.finalize();

py::native_enum<member_doc>(m, "member_doc", "enum.IntEnum")
.value("mem0", member_doc::mem0, "docA")
.value("mem1", member_doc::mem1)
Expand Down
11 changes: 10 additions & 1 deletion tests/test_native_enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@
("exv1", 1),
)

EXPORT_VALUES2_MEMBERS = (
("exv0", 0),
("exv2", 1),
)

MEMBER_DOC_MEMBERS = (
("mem0", 0),
("mem1", 1),
Expand All @@ -62,6 +67,7 @@
(m.flags_uchar, FLAGS_UCHAR_MEMBERS),
(m.flags_uint, FLAGS_UINT_MEMBERS),
(m.export_values, EXPORT_VALUES_MEMBERS),
(m.export_values2, EXPORT_VALUES2_MEMBERS),
(m.member_doc, MEMBER_DOC_MEMBERS),
(m.func_sig_rendering, FUNC_SIG_RENDERING_MEMBERS),
(m.class_with_enum.in_class, CLASS_WITH_ENUM_IN_CLASS_MEMBERS),
Expand Down Expand Up @@ -101,8 +107,11 @@ def test_enum_flag(enum_type):


def test_export_values():
assert m.exv0 is m.export_values.exv0
# Regression test for issue #6031.
assert m.exv1 is m.export_values.exv1
assert m.exv2 is m.export_values2.exv2
assert m.export_values.exv0 is not m.export_values2.exv0
assert m.exv0 is m.export_values2.exv0


def test_class_doc():
Expand Down
Loading