Skip to content

Commit

Permalink
Replace operator+= API with .finalize() API. The error messages s…
Browse files Browse the repository at this point in the history
…till need cleanup.
  • Loading branch information
rwgk committed Mar 9, 2025
1 parent ce5859e commit 943d066
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 54 deletions.
4 changes: 4 additions & 0 deletions include/pybind11/detail/native_enum_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class native_enum_data {
: parent_scope(parent_scope), enum_name_encoded{enum_name},
enum_type_index{enum_type_index}, use_int_enum{use_int_enum}, enum_name{enum_name} {}

void finalize();

native_enum_data(const native_enum_data &) = delete;
native_enum_data &operator=(const native_enum_data &) = delete;

Expand Down Expand Up @@ -121,5 +123,7 @@ inline void native_enum_add_to_parent(const object &parent, const detail::native
global_internals_native_enum_type_map_set_item(data.enum_type_index, py_enum.release().ptr());
}

inline void native_enum_data::finalize() { native_enum_add_to_parent(parent_scope, *this); }

PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
10 changes: 0 additions & 10 deletions include/pybind11/pybind11.h
Original file line number Diff line number Diff line change
Expand Up @@ -1377,11 +1377,6 @@ class module_ : public object {
// For Python 2, reinterpret_borrow was correct.
return reinterpret_borrow<module_>(m);
}

module_ &operator+=(const detail::native_enum_data &data) {
detail::native_enum_add_to_parent(*this, data);
return *this;
}
};

PYBIND11_NAMESPACE_BEGIN(detail)
Expand Down Expand Up @@ -2192,11 +2187,6 @@ class class_ : public detail::generic_type {
return *this;
}

class_ &operator+=(const detail::native_enum_data &data) {
detail::native_enum_add_to_parent(*this, data);
return *this;
}

private:
/// Initialize holder object, variant 1: object derives from enable_shared_from_this
template <typename T>
Expand Down
99 changes: 55 additions & 44 deletions tests/test_native_enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,36 +71,42 @@ PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
TEST_SUBMODULE(native_enum, m) {
using namespace test_native_enum;

m += py::native_enum<smallenum>(m, "smallenum", py::native_enum_kind::IntEnum)
.value("a", smallenum::a)
.value("b", smallenum::b)
.value("c", smallenum::c);

m += py::native_enum<color>(m, "color", py::native_enum_kind::IntEnum)
.value("red", color::red)
.value("yellow", color::yellow)
.value("green", color::green)
.value("blue", color::blue);

m += py::native_enum<altitude>(m, "altitude", py::native_enum_kind::Enum)
.value("high", altitude::high)
.value("low", altitude::low);

m += py::native_enum<export_values>(m, "export_values", py::native_enum_kind::IntEnum)
.value("exv0", export_values::exv0)
.value("exv1", export_values::exv1)
.export_values();

m += py::native_enum<member_doc>(m, "member_doc", py::native_enum_kind::IntEnum)
.value("mem0", member_doc::mem0, "docA")
.value("mem1", member_doc::mem1)
.value("mem2", member_doc::mem2, "docC");
py::native_enum<smallenum>(m, "smallenum", py::native_enum_kind::IntEnum)
.value("a", smallenum::a)
.value("b", smallenum::b)
.value("c", smallenum::c)
.finalize();

py::native_enum<color>(m, "color", py::native_enum_kind::IntEnum)
.value("red", color::red)
.value("yellow", color::yellow)
.value("green", color::green)
.value("blue", color::blue)
.finalize();

py::native_enum<altitude>(m, "altitude", py::native_enum_kind::Enum)
.value("high", altitude::high)
.value("low", altitude::low)
.finalize();

py::native_enum<export_values>(m, "export_values", py::native_enum_kind::IntEnum)
.value("exv0", export_values::exv0)
.value("exv1", export_values::exv1)
.export_values()
.finalize();

py::native_enum<member_doc>(m, "member_doc", py::native_enum_kind::IntEnum)
.value("mem0", member_doc::mem0, "docA")
.value("mem1", member_doc::mem1)
.value("mem2", member_doc::mem2, "docC")
.finalize();

py::class_<class_with_enum> py_class_with_enum(m, "class_with_enum");
py_class_with_enum
+= py::native_enum<class_with_enum::in_class>(m, "in_class", py::native_enum_kind::IntEnum)
.value("one", class_with_enum::in_class::one)
.value("two", class_with_enum::in_class::two);
py::native_enum<class_with_enum::in_class>(
py_class_with_enum, "in_class", py::native_enum_kind::IntEnum)
.value("one", class_with_enum::in_class::one)
.value("two", class_with_enum::in_class::two)
.finalize();

m.def("isinstance_color", [](const py::object &obj) { return py::isinstance<color>(obj); });

Expand Down Expand Up @@ -146,39 +152,43 @@ TEST_SUBMODULE(native_enum, m) {

m.def("double_registration_native_enum", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>(
py::none(), "fake_double_registration_native_enum", py::native_enum_kind::IntEnum)
.value("x", fake::x);
py::native_enum<fake>(
py::none(), "fake_double_registration_native_enum", py::native_enum_kind::Enum);
m, "fake_double_registration_native_enum", py::native_enum_kind::IntEnum)
.value("x", fake::x)
.finalize();
py::native_enum<fake>(
m, "fake_double_registration_native_enum", py::native_enum_kind::Enum);
});

m.def("native_enum_name_clash", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>(
py::none(), "fake_native_enum_name_clash", py::native_enum_kind::IntEnum)
.value("x", fake::x);
py::native_enum<fake>(m, "fake_native_enum_name_clash", py::native_enum_kind::IntEnum)
.value("x", fake::x)
.finalize();
});

m.def("native_enum_value_name_clash", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>(
py::none(), "fake_native_enum_value_name_clash", py::native_enum_kind::IntEnum)
.value("fake_native_enum_value_name_clash_x", fake::x)
.export_values();
py::native_enum<fake>(
m, "fake_native_enum_value_name_clash", py::native_enum_kind::IntEnum)
.value("fake_native_enum_value_name_clash_x", fake::x)
.export_values()
.finalize();
});

m.def("double_registration_enum_before_native_enum", [](const py::module_ &m) {
enum fake { x };
py::enum_<fake>(m, "fake_enum_first").value("x", fake::x);
py::native_enum<fake>(py::none(), "fake_enum_first", py::native_enum_kind::IntEnum)
.value("x", fake::x);
py::native_enum<fake>(m, "fake_enum_first", py::native_enum_kind::IntEnum)
.value("x", fake::x)
.finalize();
});

m.def("double_registration_native_enum_before_enum", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>(m, "fake_native_enum_first", py::native_enum_kind::IntEnum)
.value("x", fake::x);
py::native_enum<fake>(m, "fake_native_enum_first", py::native_enum_kind::IntEnum)
.value("x", fake::x)
.finalize();
py::enum_<fake>(m, "name_must_be_different_to_reach_desired_code_path");
});

Expand All @@ -187,7 +197,8 @@ TEST_SUBMODULE(native_enum, m) {
enum fake { x };
py::native_enum<fake>(
py::none(), "fake_native_enum_correct_use_failure", py::native_enum_kind::IntEnum)
.value("x", fake::x);
.value("x", fake::x)
.finalize();
});
#else
m.attr("native_enum_correct_use_failure") = "For local testing only: terminates process";
Expand Down

0 comments on commit 943d066

Please sign in to comment.