Skip to content

Commit 65487c0

Browse files
committed
Allow extending py3 enums
1 parent d4ef280 commit 65487c0

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
@@ -1282,22 +1282,36 @@ class py3_enum {
12821282
update();
12831283
}
12841284

1285-
py3_enum& value(const char* name, T value) {
1286-
entries[name] = cast(static_cast<underlying_type>(value));
1287-
update();
1285+
py3_enum& value(const char* name, T value) & {
1286+
add_entry(name, value);
12881287
return *this;
12891288
}
12901289

1290+
py3_enum&& value(const char* name, T value) && {
1291+
add_entry(name, value);
1292+
return std::move(*this);
1293+
}
1294+
1295+
class_<T> extend() && {
1296+
return cast<class_<T>>(type);
1297+
}
1298+
12911299
private:
12921300
const char *name;
12931301
handle scope;
12941302
dict entries;
12951303
object ctor;
12961304
object unique;
12971305
dict kwargs;
1306+
object type;
1307+
1308+
void add_entry(const char *name, T value) {
1309+
entries[name] = cast(static_cast<underlying_type>(value));
1310+
update();
1311+
}
12981312

12991313
void update() {
1300-
object type = unique(ctor(**kwargs));
1314+
type = unique(ctor(**kwargs));
13011315
setattr(scope, name, type);
13021316
detail::type_caster<T>::bind(type, entries);
13031317
}

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
@@ -164,3 +164,7 @@ def test_py3_enum():
164164
with pytest.raises(ValueError) as excinfo:
165165
non_unique_py3_enum()
166166
assert 'duplicate values found' in str(excinfo.value)
167+
168+
assert Py3Enum.ultimate_answer == 42
169+
assert not Py3Enum.A.is_b and Py3Enum.B.is_b and not Py3Enum.C.is_b
170+
assert Py3Enum.A.add(10) == -32 and Py3Enum.C.add(-1) == 41

0 commit comments

Comments
 (0)