Skip to content

Commit

Permalink
Add parent_scope as first argument to py::native_enum ctor.
Browse files Browse the repository at this point in the history
  • Loading branch information
rwgk committed Mar 9, 2025
1 parent 06eddc7 commit ce5859e
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 25 deletions.
8 changes: 5 additions & 3 deletions include/pybind11/detail/native_enum_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ PYBIND11_NAMESPACE_BEGIN(detail)

class native_enum_data {
public:
native_enum_data(const char *enum_name,
native_enum_data(object parent_scope,
const char *enum_name,
const std::type_index &enum_type_index,
bool use_int_enum)
: enum_name_encoded{enum_name}, enum_type_index{enum_type_index},
use_int_enum{use_int_enum}, enum_name{enum_name} {}
: 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} {}

native_enum_data(const native_enum_data &) = delete;
native_enum_data &operator=(const native_enum_data &) = delete;
Expand Down Expand Up @@ -50,6 +51,7 @@ class native_enum_data {
mutable bool correct_use_check{false};

public:
object parent_scope;
std::string enum_name_encoded;
std::type_index enum_type_index;
bool use_int_enum;
Expand Down
8 changes: 5 additions & 3 deletions include/pybind11/native_enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ class native_enum : public detail::native_enum_data {
public:
using Underlying = typename std::underlying_type<Type>::type;

explicit native_enum(const char *name, native_enum_kind kind)
: detail::native_enum_data(
name, std::type_index(typeid(Type)), kind == native_enum_kind::IntEnum) {
explicit native_enum(object parent_scope, const char *name, native_enum_kind kind)
: detail::native_enum_data(parent_scope,
name,
std::type_index(typeid(Type)),
kind == native_enum_kind::IntEnum) {
if (detail::get_local_type_info(typeid(Type)) != nullptr
|| detail::get_global_type_info(typeid(Type)) != nullptr) {
pybind11_fail(
Expand Down
41 changes: 22 additions & 19 deletions tests/test_native_enum.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,34 +71,34 @@ PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
TEST_SUBMODULE(native_enum, m) {
using namespace test_native_enum;

m += py::native_enum<smallenum>("smallenum", py::native_enum_kind::IntEnum)
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>("color", py::native_enum_kind::IntEnum)
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>("altitude", py::native_enum_kind::Enum)
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>("export_values", py::native_enum_kind::IntEnum)
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>("member_doc", py::native_enum_kind::IntEnum)
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::class_<class_with_enum> py_class_with_enum(m, "class_with_enum");
py_class_with_enum
+= py::native_enum<class_with_enum::in_class>("in_class", py::native_enum_kind::IntEnum)
+= 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);

Expand Down Expand Up @@ -127,63 +127,66 @@ TEST_SUBMODULE(native_enum, m) {
});

m.def("native_enum_data_was_not_added_error_message", [](const char *enum_name) {
py::detail::native_enum_data data(enum_name, std::type_index(typeid(void)), false);
py::detail::native_enum_data data(
py::none(), enum_name, std::type_index(typeid(void)), false);
data.disarm_correct_use_check();
return data.was_not_added_error_message();
});

m.def("native_enum_ctor_malformed_utf8", [](const char *malformed_utf8) {
enum fake { x };
py::native_enum<fake>{malformed_utf8, py::native_enum_kind::IntEnum};
py::native_enum<fake>{py::none(), malformed_utf8, py::native_enum_kind::IntEnum};
});

m.def("native_enum_value_malformed_utf8", [](const char *malformed_utf8) {
enum fake { x };
py::native_enum<fake>("fake", py::native_enum_kind::IntEnum)
py::native_enum<fake>(py::none(), "fake", py::native_enum_kind::IntEnum)
.value(malformed_utf8, fake::x);
});

m.def("double_registration_native_enum", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>("fake_double_registration_native_enum",
py::native_enum_kind::IntEnum)
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>("fake_double_registration_native_enum", py::native_enum_kind::Enum);
py::native_enum<fake>(
py::none(), "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>("fake_native_enum_name_clash", py::native_enum_kind::IntEnum)
m += py::native_enum<fake>(
py::none(), "fake_native_enum_name_clash", py::native_enum_kind::IntEnum)
.value("x", fake::x);
});

m.def("native_enum_value_name_clash", [](py::module_ m) {
enum fake { x };
m += py::native_enum<fake>("fake_native_enum_value_name_clash",
py::native_enum_kind::IntEnum)
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();
});

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>("fake_enum_first", py::native_enum_kind::IntEnum)
py::native_enum<fake>(py::none(), "fake_enum_first", py::native_enum_kind::IntEnum)
.value("x", fake::x);
});

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

#if defined(PYBIND11_NEGATE_THIS_CONDITION_FOR_LOCAL_TESTING) && !defined(NDEBUG)
m.def("native_enum_correct_use_failure", []() {
enum fake { x };
py::native_enum<fake>("fake_native_enum_correct_use_failure",
py::native_enum_kind::IntEnum)
py::native_enum<fake>(
py::none(), "fake_native_enum_correct_use_failure", py::native_enum_kind::IntEnum)
.value("x", fake::x);
});
#else
Expand Down

0 comments on commit ce5859e

Please sign in to comment.