Skip to content

Commit 14d655a

Browse files
committed
Allow extending py3 enums
1 parent ccca1c8 commit 14d655a

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
@@ -1279,22 +1279,36 @@ class py3_enum {
12791279
update();
12801280
}
12811281

1282-
py3_enum& value(const char* name, T value) {
1283-
entries[name] = cast(static_cast<underlying_type>(value));
1284-
update();
1282+
py3_enum& value(const char* name, T value) & {
1283+
add_entry(name, value);
12851284
return *this;
12861285
}
12871286

1287+
py3_enum&& value(const char* name, T value) && {
1288+
add_entry(name, value);
1289+
return std::move(*this);
1290+
}
1291+
1292+
class_<T> extend() && {
1293+
return cast<class_<T>>(type);
1294+
}
1295+
12881296
private:
12891297
const char *name;
12901298
handle scope;
12911299
dict entries;
12921300
object ctor;
12931301
object unique;
12941302
dict kwargs;
1303+
object type;
1304+
1305+
void add_entry(const char *name, T value) {
1306+
entries[name] = cast(static_cast<underlying_type>(value));
1307+
update();
1308+
}
12951309

12961310
void update() {
1297-
object type = unique(ctor(**kwargs));
1311+
type = unique(ctor(**kwargs));
12981312
setattr(scope, name, type);
12991313
detail::type_caster<T>::bind(type, entries);
13001314
}

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)