Skip to content

Commit b303e4d

Browse files
committed
Allow extending py3 enums
1 parent 42e96c3 commit b303e4d

File tree

3 files changed

+28
-6
lines changed

3 files changed

+28
-6
lines changed

include/pybind11/pybind11.h

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,22 +1263,36 @@ class py3_enum {
12631263
update();
12641264
}
12651265

1266-
py3_enum& value(const char* name, T value) {
1267-
entries[name] = cast(static_cast<underlying_type>(value));
1268-
update();
1266+
py3_enum& value(const char* name, T value) & {
1267+
add_entry(name, value);
12691268
return *this;
12701269
}
12711270

1271+
py3_enum&& value(const char* name, T value) && {
1272+
add_entry(name, value);
1273+
return std::move(*this);
1274+
}
1275+
1276+
class_<T> extend() && {
1277+
return cast<class_<T>>(type);
1278+
}
1279+
12721280
private:
12731281
const char *name;
12741282
handle scope;
12751283
dict entries;
12761284
object ctor;
12771285
object unique;
12781286
dict kwargs;
1287+
object type;
1288+
1289+
void add_entry(const char *name, T value) {
1290+
entries[name] = cast(static_cast<underlying_type>(value));
1291+
update();
1292+
}
12791293

12801294
void update() {
1281-
object type = unique(ctor(**kwargs));
1295+
type = unique(ctor(**kwargs));
12821296
setattr(scope, name, type);
12831297
detail::type_caster<T>::bind(type, entries);
12841298
}

tests/test_enum.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,14 @@ test_initializer enums([](py::module &m) {
8282
auto scope = py::class_<DummyScope>(m, "DummyScope");
8383
py::py3_enum<Py3EnumEmpty>(scope, "Py3EnumEmpty");
8484

85-
py::py3_enum<Py3Enum>(m, "Py3Enum")
85+
auto e = py::py3_enum<Py3Enum>(m, "Py3Enum")
8686
.value("A", Py3Enum::A)
8787
.value("B", Py3Enum::B)
88-
.value("C", Py3Enum::C);
88+
.value("C", Py3Enum::C)
89+
.extend()
90+
.def("add", [](Py3Enum x, int y) { return static_cast<int>(x) + y; })
91+
.def_property_readonly("is_b", [](Py3Enum e) { return e == Py3Enum::B; })
92+
.def_property_readonly_static("ultimate_answer", [](py::object) { return 42; });
8993

9094
py::py3_enum<Py3EnumScoped>(m, "Py3EnumScoped")
9195
.value("X", Py3EnumScoped::X)

tests/test_enum.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,3 +152,7 @@ def test_py3_enum():
152152
with pytest.raises(ValueError) as excinfo:
153153
non_unique_py3_enum()
154154
assert 'duplicate values found' in str(excinfo.value)
155+
156+
assert Py3Enum.ultimate_answer == 42
157+
assert not Py3Enum.A.is_b and Py3Enum.B.is_b and not Py3Enum.C.is_b
158+
assert Py3Enum.A.add(10) == -32 and Py3Enum.C.add(-1) == 41

0 commit comments

Comments
 (0)