`enum`s generated by Pyo3 don't actually subclass Python's `Enum`
enums generated by Pyo3 don't actually subclass Python's Enum. Due to this, some attributes/methods are missing from Pyo3 enums that you would expect in Python. Additionally, EnumType is not the metaclass of Pyo3 enums leading to the same problems.
I am not entirely sure how this might be fixed, simply because I don't know the restrictions of the Python C API.
Enum isn't exposed in the C-API, so if we were to add the inheritance we would first need to solve #991.
More likely we could add methods to our exposed enums to match what the expected interface would be. This would be a case of someone enumerating what's missing and we decide whether to support it or not.
That is what I assumed was the answer. For future reference, this is the total list of attributes missing from enums as they stand, to the best of my understanding.
From EnumType and Enum:
__contains____getitem____iter____len____reversed____call____members___name_name_value_value_missing_
As a side note, __new__ is supposed to return a list of the Enum members, which I'm not sure it does right now.
Enums are supposed to be able to be accessed via either their value or their name. e.g. ExampleEnum(0) or ExampleEnum['example_member'] The value access is handled __call__ and the name access by __getitem__.
All Enum members need a respective value, whether unique or not. Values do not need to be numbers.
There are additional attributes expected on some standard Enum subclasses, but leaving those to the user or a later date seems fine.
https://docs.python.org/3/library/enum.html https://peps.python.org/pep-0435/
For reference of the difference between the two:
PyO3 Enum:
dir(MyEnum)
['OtherVariant', 'Variant', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
dir(MyEnum.Variant)
['OtherVariant', 'Variant', '__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__int__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
Python Enum:
dir(PyEnum)
['OtherVariant', 'Variant', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__']
dir(PyEnum.Variant)
['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value']
pybind11 v3 binds C++ enums to Python enum.Enum subclasses using the py::native_enum function. It might interesting to have a look at their approach.
Following the @Tpt 's suggestion and had a look at pybind11, it seems they have implemented Enum classes getter and setter themselves here: https://github.com/pybind/pybind11/blob/7aa3780dd48c0ebedce68f75bf38994dec6ed298/include/pybind11/detail/native_enum_data.h
I am afraid we will have to do the same.