)]}'
{
  "commit": "f365314ec0a86c76d697b9fa4d7a3e804ff35180",
  "tree": "0c399774f8ad43fac7f56a244b48fcb3a59d97cc",
  "parents": [
    "48eb5ad9b993f535957f2d690b92b54e115ea018"
  ],
  "author": {
    "name": "Ralf W. Grosse-Kunstleve",
    "email": "rwgkio@gmail.com",
    "time": "Mon Mar 24 20:31:59 2025 -0700"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Mon Mar 24 20:31:59 2025 -0700"
  },
  "message": "Enable Conversions Between Native Python Enum Types and C++ Enums (#5555)\n\n* Apply smart_holder-branch-based PR #5280 on top of master.\n\n* Add pytest.skip(\"GraalPy does not raise UnicodeDecodeError\")\n\n* Add `parent_scope` as first argument to `py::native_enum` ctor.\n\n* Replace `operator+\u003d` API with `.finalize()` API. The error messages still need cleanup.\n\n* Resolve clang-tidy performance-unnecessary-value-param errors\n\n* Rename (effectively) native_enum_add_to_parent() -\u003e finalize()\n\n* Update error message: pybind11::native_enum\u003c...\u003e(\"Fake\", ...): MISSING .finalize()\n\n* Pass py::module_ by reference to resolve clang-tidy errors (this is entirely inconsequential otherwise for all practical purposes).\n\n* test_native_enum_correct_use_failure -\u003e test_native_enum_missing_finalize_failure\n\n* Add test_native_enum_double_finalize(), test_native_enum_value_after_finalize()\n\n* Clean up public/protected API.\n\n* [ci skip] Update the Enumerations section in classes.rst\n\n* Rename `py::native_enum_kind` → `py::enum_kind` as suggested by gh-henryiii:\n\nhttps://github.com/pybind/pybind11/pull/5555#issuecomment-2711672335\n\n* Experiment: StrEnum\n\nenum.StrEnum does not map to C++ enum:\n\n* https://chatgpt.com/share/67d5e965-ccb0-8008-95b7-0df2502309b3\n\n```\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d test session starts \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nplatform linux -- Python 3.12.3, pytest-8.3.3, pluggy-1.5.0\nC++ Info: 13.3.0 C++20 __pybind11_internals_v10000000_system_libstdcpp_gxx_abi_1xxx_use_cxx11_abi_1__ PYBIND11_SIMPLE_GIL_MANAGEMENT\u003dFalse PYBIND11_NUMPY_1_ONLY\u003dFalse\nconfigfile: pytest.ini\nplugins: parallel-0.1.1, xdist-3.6.1\ncollected 40 items / 39 deselected / 1 selected\n\ntest_native_enum.py F                                                    [100%]\n\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d FAILURES \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n________________________ test_native_enum_StrEnum_greek ________________________\n\n    def test_native_enum_StrEnum_greek():\n        assert not hasattr(m, \"greek\")\n\u003e       m.native_enum_StrEnum_greek(m)\n\ntest_native_enum.py:150:\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n/usr/lib/python3.12/enum.py:764: in __call__\n    return cls._create_(\n        boundary   \u003d None\n        cls        \u003d \u003cenum \u0027StrEnum\u0027\u003e\n        module     \u003d None\n        names      \u003d [(\u0027Alpha\u0027, 10), (\u0027Omega\u0027, 20)]\n        qualname   \u003d None\n        start      \u003d 1\n        type       \u003d None\n        value      \u003d \u0027greek\u0027\n        values     \u003d ()\n/usr/lib/python3.12/enum.py:917: in _create_\n    return metacls.__new__(metacls, class_name, bases, classdict, boundary\u003dboundary)\n        _          \u003d \u003cclass \u0027str\u0027\u003e\n        bases      \u003d (\u003cenum \u0027StrEnum\u0027\u003e,)\n        boundary   \u003d None\n        class_name \u003d \u0027greek\u0027\n        classdict  \u003d {\u0027_generate_next_value_\u0027: \u003cfunction StrEnum._generate_next_value_ at 0x701ec1711e40\u003e, \u0027Alpha\u0027: 10, \u0027Omega\u0027: 20, \u0027__module__\u0027: \u0027test_native_enum\u0027}\n        cls        \u003d \u003cenum \u0027StrEnum\u0027\u003e\n        first_enum \u003d \u003cenum \u0027StrEnum\u0027\u003e\n        item       \u003d (\u0027Omega\u0027, 20)\n        member_name \u003d \u0027Omega\u0027\n        member_value \u003d 20\n        metacls    \u003d \u003cclass \u0027enum.EnumType\u0027\u003e\n        module     \u003d \u0027test_native_enum\u0027\n        names      \u003d [(\u0027Alpha\u0027, 10), (\u0027Omega\u0027, 20)]\n        qualname   \u003d None\n        start      \u003d 1\n        type       \u003d None\n/usr/lib/python3.12/enum.py:606: in __new__\n    raise exc.with_traceback(tb)\n        __class__  \u003d \u003cclass \u0027enum.EnumType\u0027\u003e\n        __new__    \u003d \u003cfunction StrEnum.__new__ at 0x701ec1711da0\u003e\n        _gnv       \u003d \u003cstaticmethod(\u003cfunction StrEnum._generate_next_value_ at 0x701ec1711e40\u003e)\u003e\n        _order_    \u003d None\n        _simple    \u003d False\n        bases      \u003d (\u003cenum \u0027StrEnum\u0027\u003e,)\n        boundary   \u003d None\n        classdict  \u003d {\u0027Alpha\u0027: \u003cenum._proto_member object at 0x701ebc74f9b0\u003e, \u0027Omega\u0027: \u003cenum._proto_member object at 0x701ebc74cce0\u003e, \u0027__module__\u0027: \u0027test_native_enum\u0027, \u0027_all_bits_\u0027: 0, ...}\n        cls        \u003d \u0027greek\u0027\n        exc        \u003d TypeError(\u002710 is not a string\u0027)\n        first_enum \u003d \u003cenum \u0027StrEnum\u0027\u003e\n        ignore     \u003d [\u0027_ignore_\u0027]\n        invalid_names \u003d set()\n        key        \u003d \u0027_ignore_\u0027\n        kwds       \u003d {}\n        member_names \u003d {\u0027Alpha\u0027: None, \u0027Omega\u0027: None}\n        member_type \u003d \u003cclass \u0027str\u0027\u003e\n        metacls    \u003d \u003cclass \u0027enum.EnumType\u0027\u003e\n        name       \u003d \u0027Omega\u0027\n        save_new   \u003d False\n        tb         \u003d \u003ctraceback object at 0x701ebc7a6cc0\u003e\n        use_args   \u003d True\n        value      \u003d 20\n/usr/lib/python3.12/enum.py:596: in __new__\n    enum_class \u003d super().__new__(metacls, cls, bases, classdict, **kwds)\n        __class__  \u003d \u003cclass \u0027enum.EnumType\u0027\u003e\n        __new__    \u003d \u003cfunction StrEnum.__new__ at 0x701ec1711da0\u003e\n        _gnv       \u003d \u003cstaticmethod(\u003cfunction StrEnum._generate_next_value_ at 0x701ec1711e40\u003e)\u003e\n        _order_    \u003d None\n        _simple    \u003d False\n        bases      \u003d (\u003cenum \u0027StrEnum\u0027\u003e,)\n        boundary   \u003d None\n        classdict  \u003d {\u0027Alpha\u0027: \u003cenum._proto_member object at 0x701ebc74f9b0\u003e, \u0027Omega\u0027: \u003cenum._proto_member object at 0x701ebc74cce0\u003e, \u0027__module__\u0027: \u0027test_native_enum\u0027, \u0027_all_bits_\u0027: 0, ...}\n        cls        \u003d \u0027greek\u0027\n        exc        \u003d TypeError(\u002710 is not a string\u0027)\n        first_enum \u003d \u003cenum \u0027StrEnum\u0027\u003e\n        ignore     \u003d [\u0027_ignore_\u0027]\n        invalid_names \u003d set()\n        key        \u003d \u0027_ignore_\u0027\n        kwds       \u003d {}\n        member_names \u003d {\u0027Alpha\u0027: None, \u0027Omega\u0027: None}\n        member_type \u003d \u003cclass \u0027str\u0027\u003e\n        metacls    \u003d \u003cclass \u0027enum.EnumType\u0027\u003e\n        name       \u003d \u0027Omega\u0027\n        save_new   \u003d False\n        tb         \u003d \u003ctraceback object at 0x701ebc7a6cc0\u003e\n        use_args   \u003d True\n        value      \u003d 20\n/usr/lib/python3.12/enum.py:271: in __set_name__\n    enum_member \u003d enum_class._new_member_(enum_class, *args)\n        args       \u003d (10,)\n        enum_class \u003d \u003cenum \u0027greek\u0027\u003e\n        member_name \u003d \u0027Alpha\u0027\n        self       \u003d \u003cenum._proto_member object at 0x701ebc74f9b0\u003e\n        value      \u003d 10\n_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _\n\ncls \u003d \u003cenum \u0027greek\u0027\u003e, values \u003d (10,)\n\n    def __new__(cls, *values):\n        \"values must already be of type `str`\"\n        if len(values) \u003e 3:\n            raise TypeError(\u0027too many arguments for str(): %r\u0027 % (values, ))\n        if len(values) \u003d\u003d 1:\n            # it must be a string\n            if not isinstance(values[0], str):\n\u003e               raise TypeError(\u0027%r is not a string\u0027 % (values[0], ))\nE               TypeError: 10 is not a string\n\ncls        \u003d \u003cenum \u0027greek\u0027\u003e\nvalues     \u003d (10,)\n\n/usr/lib/python3.12/enum.py:1322: TypeError\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d short test summary info \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\nFAILED test_native_enum.py::test_native_enum_StrEnum_greek - TypeError: 10 is...\n\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d 1 failed, 39 deselected in 0.07s \u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\u003d\n\nERROR: completed_process.returncode\u003d1\n```\n\n* Remove StrEnum code.\n\n* Make enum_kind::Enum the default kind.\n\n* Catch redundant .export_values() calls.\n\n* [ci skip] Add back original documentation for `py::enum_` under new advanced/deprecated.rst\n\n* [ci skip] Add documentation for `py::enum_kind` and `py::detail::type_caster_enum_type_enabled`\n\n* Rename `Type` to `EnumType` for readability.\n\n* Eliminate py::enum_kind, use \"enum.Enum\", \"enum.IntEnum\" directly. This is still WIP.\n\n* EXPERIMENTAL StrEnum code. To be removed.\n\n* Remove experimental StrEnum code:\n\nMy judgement: Supporting StrEnum is maybe nice, but not very valuable. I don\u0027t think it is worth the extra C++ code.\n\nA level of indirection would need to be managed, e.g.\n\n    RED   ↔ Python \"r\" ↔ C++ 0\n    Green ↔ Python \"g\" ↔ C++ 1\n\nThese mappings would need to be stored and processed.\n\n* Add test with enum.IntFlag (no production code changes required).\n\n* First import_or_getattr() implementation (dedicated tests are still missing).\n\n* Fix import_or_getattr() implementation, add tests, fix clang-tidy errors.\n\n* [ci skip] Update classes.rst: replace `py::enum_kind` with `native_type_name`\n\n* For \"constructor similar to that of enum.Enum\" point to https://docs.python.org/3/howto/enum.html#functional-api, as suggested by gh-timohl (https://github.com/pybind/pybind11/pull/5555#discussion_r2009277507).\n\n* Advertise Enum, IntEnum, Flag, IntFlags are compatible stdlib enum types in the documentation (as suggested by gh-timohl, https://github.com/pybind/pybind11/pull/5555#pullrequestreview-2708832587); add test for enum.Flag to ensure that is actually true.",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "23e114e20aabd75645419f74ae981a9c86bb9a0f",
      "old_mode": 33188,
      "old_path": "CMakeLists.txt",
      "new_id": "2161c92693eab65cb906772aa601e7abc356fc47",
      "new_mode": 33188,
      "new_path": "CMakeLists.txt"
    },
    {
      "type": "modify",
      "old_id": "5a626f3ba82ef5a06454788308e1a0852f21daa2",
      "old_mode": 33188,
      "old_path": "docs/advanced/cast/custom.rst",
      "new_id": "1de0f0a21a227c98ccfafde8c0b015b5707c474d",
      "new_mode": 33188,
      "new_path": "docs/advanced/cast/custom.rst"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "a43c447aa5b993ebb3008414d4b23008e4dd07d3",
      "new_mode": 33188,
      "new_path": "docs/advanced/deprecated.rst"
    },
    {
      "type": "modify",
      "old_id": "5406668f0be97571ea648688d9aff67cc5dcec25",
      "old_mode": 33188,
      "old_path": "docs/classes.rst",
      "new_id": "e68b802ee93dbccfce0accb73bf58bafc512fe3d",
      "new_mode": 33188,
      "new_path": "docs/classes.rst"
    },
    {
      "type": "modify",
      "old_id": "4e2e8ca3a04a072d9adfdfa4bb98f5c221be10ea",
      "old_mode": 33188,
      "old_path": "docs/index.rst",
      "new_id": "77b097c5749d9db31a55a515fa646322b577e954",
      "new_mode": 33188,
      "new_path": "docs/index.rst"
    },
    {
      "type": "modify",
      "old_id": "89d3d43a7af5452f8d135879bb9b6811b595efd1",
      "old_mode": 33188,
      "old_path": "include/pybind11/cast.h",
      "new_id": "410215244739c9870d30e41131bf3fbebd682f5e",
      "new_mode": 33188,
      "new_path": "include/pybind11/cast.h"
    },
    {
      "type": "modify",
      "old_id": "08e23afb59d6d183139a70dda22e1af786a66501",
      "old_mode": 33188,
      "old_path": "include/pybind11/detail/class.h",
      "new_id": "98ff61f5d7964f75c01953ed7666b74f8f892519",
      "new_mode": 33188,
      "new_path": "include/pybind11/detail/class.h"
    },
    {
      "type": "modify",
      "old_id": "841c8fe155692653974f93404ababd44ac597a05",
      "old_mode": 33188,
      "old_path": "include/pybind11/detail/internals.h",
      "new_id": "2fd1f6719c6f85829ce3ac67fd4634f295638863",
      "new_mode": 33188,
      "new_path": "include/pybind11/detail/internals.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "5192ed51a67ece9a3c4fad162442c81ab10229ff",
      "new_mode": 33188,
      "new_path": "include/pybind11/detail/native_enum_data.h"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "759acd48db782d3d753c6a76941d53b2970d251b",
      "new_mode": 33188,
      "new_path": "include/pybind11/native_enum.h"
    },
    {
      "type": "modify",
      "old_id": "cf11e373dc50592475d625f45fdb84e5e0fdc177",
      "old_mode": 33188,
      "old_path": "include/pybind11/pybind11.h",
      "new_id": "caca57b3e47a4cf2e9c34ceb4d56fb22e35c7cd0",
      "new_mode": 33188,
      "new_path": "include/pybind11/pybind11.h"
    },
    {
      "type": "modify",
      "old_id": "1147cab8ece6bb770f644517c8206573fe78a707",
      "old_mode": 33188,
      "old_path": "include/pybind11/pytypes.h",
      "new_id": "57f1279657107af1c193979f714725ccdc2bb8ee",
      "new_mode": 33188,
      "new_path": "include/pybind11/pytypes.h"
    },
    {
      "type": "modify",
      "old_id": "e2fab9c13d8b99e52a2ec58a497dff809f17454e",
      "old_mode": 33188,
      "old_path": "tests/CMakeLists.txt",
      "new_id": "1b65729dfd9c8c744b643a3700219fc76e850f31",
      "new_mode": 33188,
      "new_path": "tests/CMakeLists.txt"
    },
    {
      "type": "modify",
      "old_id": "5d7299c2acbeba119962159832feeb8f691844f6",
      "old_mode": 33188,
      "old_path": "tests/extra_python_package/test_files.py",
      "new_id": "2fa47c614ad5c6076818778b558ef17732df2c0a",
      "new_mode": 33188,
      "new_path": "tests/extra_python_package/test_files.py"
    },
    {
      "type": "modify",
      "old_id": "2597b275ef6dc806f33cffb0499fa0ba971a6085",
      "old_mode": 33188,
      "old_path": "tests/test_enum.cpp",
      "new_id": "4ec0af7245b43067dabd97365c188af99fa63955",
      "new_mode": 33188,
      "new_path": "tests/test_enum.cpp"
    },
    {
      "type": "modify",
      "old_id": "044ef1803e4c6b0b7c619300757dfc5af06150e7",
      "old_mode": 33188,
      "old_path": "tests/test_enum.py",
      "new_id": "697e28843f37e60a374b454845ac7587bb4e883d",
      "new_mode": 33188,
      "new_path": "tests/test_enum.py"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "1a4c3180c7863476cbebf3d375176a369c627aa9",
      "new_mode": 33188,
      "new_path": "tests/test_native_enum.cpp"
    },
    {
      "type": "add",
      "old_id": "0000000000000000000000000000000000000000",
      "old_mode": 0,
      "old_path": "/dev/null",
      "new_id": "f98ebd0459c055928cfa7a6e5630f7110df4a9a4",
      "new_mode": 33188,
      "new_path": "tests/test_native_enum.py"
    }
  ]
}
