@@ -459,6 +459,8 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
459459 other using the ``.def(py::init<...>()) `` syntax. The existing machinery
460460 for specifying keyword and default arguments also works.
461461
462+ .. _native_enum :
463+
462464Enumerations and internal types
463465===============================
464466
@@ -487,76 +489,102 @@ The binding code for this example looks as follows:
487489
488490.. code-block :: cpp
489491
492+ #include <pybind11/native_enum.h> // Not already included with pybind11.h
493+
490494 py::class_<Pet> pet(m, "Pet");
491495
492496 pet.def(py::init<const std::string &, Pet::Kind>())
493497 .def_readwrite("name", &Pet::name)
494498 .def_readwrite("type", &Pet::type)
495499 .def_readwrite("attr", &Pet::attr);
496500
497- py::enum_ <Pet::Kind>(pet, "Kind")
501+ py::native_enum <Pet::Kind>(pet, "Kind")
498502 .value("Dog", Pet::Kind::Dog)
499503 .value("Cat", Pet::Kind::Cat)
500- .export_values();
504+ .export_values()
505+ .finalize();
501506
502507 py::class_<Pet::Attributes>(pet, "Attributes")
503508 .def(py::init<>())
504509 .def_readwrite("age", &Pet::Attributes::age);
505510
506511
507- To ensure that the nested types ``Kind `` and ``Attributes `` are created within the scope of `` Pet ``, the
508- `` pet `` ``py::class_ `` instance must be supplied to the :class: ` enum_ ` and `` py::class_ ``
509- constructor. The :func: ` enum_::export_values ` function exports the enum entries
510- into the parent scope, which should be skipped for newer C++11-style strongly
511- typed enums .
512+ To ensure that the nested types ``Kind `` and ``Attributes `` are created
513+ within the scope of `` Pet ``, the `` pet `` ``py::class_ `` instance must be
514+ supplied to the `` py::native_enum `` and `` py::class_ `` constructors. The
515+ `` .export_values() `` function is available for exporting the enum entries
516+ into the parent scope, if desired .
512517
513- .. code-block :: pycon
518+ ``py::native_enum `` was introduced with pybind11v3. It binds C++ enum types
519+ to native Python enum types, typically types in Python's
520+ `stdlib enum <https://docs.python.org/3/library/enum.html >`_ module,
521+ which are `PEP 435 compatible <https://peps.python.org/pep-0435/ >`_.
522+ This is the recommended way to bind C++ enums.
523+ The older ``py::enum_ `` is not PEP 435 compatible
524+ (see `issue #2332 <https://github.com/pybind/pybind11/issues/2332 >`_)
525+ but remains supported indefinitely for backward compatibility.
526+ New bindings should prefer ``py::native_enum ``.
514527
515- >>> p = Pet("Lucy", Pet.Cat)
516- >>> p.type
517- Kind.Cat
518- >>> int(p.type)
519- 1L
528+ .. note ::
520529
521- The entries defined by the enumeration type are exposed in the `` __members__ `` property:
530+ The deprecated `` py::enum_ `` is :ref: ` documented here < deprecated_enum >`.
522531
523- .. code-block :: pycon
532+ The ``.finalize() `` call above is needed because Python's native enums
533+ cannot be built incrementally — all name/value pairs need to be passed at
534+ once. To achieve this, ``py::native_enum `` acts as a buffer to collect the
535+ name/value pairs. The ``.finalize() `` call uses the accumulated name/value
536+ pairs to build the arguments for constructing a native Python enum type.
524537
525- >>> Pet.Kind.__members__
526- {'Dog': Kind.Dog, 'Cat': Kind.Cat}
538+ The ``py::native_enum `` constructor supports a third optional
539+ ``native_type_name `` string argument, with default value ``"enum.Enum" ``.
540+ Other types can be specified like this:
527541
528- The `` name `` property returns the name of the enum value as a unicode string.
542+ .. code-block :: cpp
529543
530- .. note ::
544+ py::native_enum<Pet::Kind>(pet, "Kind", "enum.IntEnum")
531545
532- It is also possible to use ``str(enum) ``, however these accomplish different
533- goals. The following shows how these two approaches differ.
546+ Any fully-qualified Python name can be specified. The only requirement is
547+ that the named type is similar to
548+ `enum.Enum <https://docs.python.org/3/library/enum.html#enum.Enum >`_
549+ in these ways:
534550
535- .. code-block :: pycon
551+ * Has a `constructor similar to that of enum.Enum
552+ <https://docs.python.org/3/howto/enum.html#functional-api> `_::
536553
537- >>> p = Pet("Lucy", Pet.Cat)
538- >>> pet_type = p.type
539- >>> pet_type
540- Pet.Cat
541- >>> str(pet_type)
542- 'Pet.Cat'
543- >>> pet_type.name
544- 'Cat'
554+ Colors = enum.Enum("Colors", (("Red", 0), ("Green", 1)))
555+
556+ * A `C++ underlying <https://en.cppreference.com/w/cpp/types/underlying_type >`_
557+ enum value can be passed to the constructor for the Python enum value::
558+
559+ red = Colors(0)
560+
561+ * The enum values have a ``.value `` property yielding a value that
562+ can be cast to the C++ underlying type::
563+
564+ underlying = red.value
565+
566+ As of Python 3.13, the compatible `types in the stdlib enum module
567+ <https://docs.python.org/3/library/enum.html#module-contents> `_ are:
568+ ``Enum ``, ``IntEnum ``, ``Flag ``, ``IntFlag ``.
545569
546570.. note ::
547571
548- When the special tag ``py::arithmetic() `` is specified to the ``enum_ ``
549- constructor, pybind11 creates an enumeration that also supports rudimentary
550- arithmetic and bit-level operations like comparisons, and, or, xor, negation,
551- etc.
572+ In rare cases, a C++ enum may be bound to Python via a
573+ :ref: `custom type caster <custom_type_caster >`. In such cases, a
574+ template specialization like this may be required:
552575
553576 .. code-block :: cpp
554577
555- py::enum_<Pet::Kind>(pet, "Kind", py::arithmetic())
556- ...
557-
558- By default, these are omitted to conserve space.
578+ #if defined(PYBIND11_HAS_NATIVE_ENUM)
579+ namespace pybind11::detail {
580+ template <typename FancyEnum>
581+ struct type_caster_enum_type_enabled<
582+ FancyEnum,
583+ std::enable_if_t<is_fancy_enum<FancyEnum>::value>> : std::false_type {};
584+ }
585+ #endif
559586
560- .. warning ::
587+ This specialization is needed only if the custom type caster is templated.
561588
562- Contrary to Python customs, enum values from the wrappers should not be compared using ``is ``, but with ``== `` (see `#1177 <https://github.com/pybind/pybind11/issues/1177 >`_ for background).
589+ The ``PYBIND11_HAS_NATIVE_ENUM `` guard is needed only if backward
590+ compatibility with pybind11v2 is required.
0 commit comments