@@ -459,6 +459,8 @@ you can use ``py::detail::overload_cast_impl`` with an additional set of parenth
459
459
other using the ``.def(py::init<...>()) `` syntax. The existing machinery
460
460
for specifying keyword and default arguments also works.
461
461
462
+ .. _native_enum :
463
+
462
464
Enumerations and internal types
463
465
===============================
464
466
@@ -487,76 +489,102 @@ The binding code for this example looks as follows:
487
489
488
490
.. code-block :: cpp
489
491
492
+ #include <pybind11/native_enum.h> // Not already included with pybind11.h
493
+
490
494
py::class_<Pet> pet(m, "Pet");
491
495
492
496
pet.def(py::init<const std::string &, Pet::Kind>())
493
497
.def_readwrite("name", &Pet::name)
494
498
.def_readwrite("type", &Pet::type)
495
499
.def_readwrite("attr", &Pet::attr);
496
500
497
- py::enum_ <Pet::Kind>(pet, "Kind")
501
+ py::native_enum <Pet::Kind>(pet, "Kind")
498
502
.value("Dog", Pet::Kind::Dog)
499
503
.value("Cat", Pet::Kind::Cat)
500
- .export_values();
504
+ .export_values()
505
+ .finalize();
501
506
502
507
py::class_<Pet::Attributes>(pet, "Attributes")
503
508
.def(py::init<>())
504
509
.def_readwrite("age", &Pet::Attributes::age);
505
510
506
511
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 .
512
517
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 ``.
514
527
515
- >>> p = Pet("Lucy", Pet.Cat)
516
- >>> p.type
517
- Kind.Cat
518
- >>> int(p.type)
519
- 1L
528
+ .. note ::
520
529
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 >`.
522
531
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.
524
537
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:
527
541
528
- The `` name `` property returns the name of the enum value as a unicode string.
542
+ .. code-block :: cpp
529
543
530
- .. note ::
544
+ py::native_enum<Pet::Kind>(pet, "Kind", "enum.IntEnum")
531
545
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:
534
550
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> `_::
536
553
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 ``.
545
569
546
570
.. note ::
547
571
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:
552
575
553
576
.. code-block :: cpp
554
577
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
559
586
560
- .. warning ::
587
+ This specialization is needed only if the custom type caster is templated.
561
588
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