]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-139398: [Enum] Add supported sunder names to `__dir__` for REPL completions (GH...
authorRafael Weingartner-Ortner <38643099+RafaelWO@users.noreply.github.com>
Thu, 28 May 2026 19:55:38 +0000 (21:55 +0200)
committerGitHub <noreply@github.com>
Thu, 28 May 2026 19:55:38 +0000 (12:55 -0700)
* Add supported sunder names to Enum `__dir__`

This change adds the sunder names `_generate_next_value_`
and `_missing_` to the `__dir__` method of `EnumType` and `Enum`.
In Addition, The instance level sunder names
`_add_alias_` and `_add_value_alias_` are added to `Enum.__dir__`.

With the sunder names exposed in the `dir()` method,
the REPL autocomplete will also show them.

---------

Co-authored-by: SimonGPrs <107691772+SimonGPrs@users.noreply.github.com>
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
Doc/library/enum.rst
Lib/enum.py
Lib/test/test_enum.py
Misc/NEWS.d/next/Library/2025-10-12-08-46-26.gh-issue-139398.hESOMl.rst [new file with mode: 0644]

index be7f59b0fce2a5ebc2d8876549c2fb0174d5bd93..04b41ad6eadf38c50a62d369d53918a1c9f5347b 100644 (file)
@@ -222,7 +222,7 @@ Data types
       names of the members in *cls*::
 
         >>> dir(Color)
-        ['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__']
+        ['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__', '_generate_next_value_', '_missing_']
 
    .. method:: EnumType.__getitem__(cls, name)
 
@@ -355,7 +355,7 @@ Data types
          ...         print(f'today is {cls(dt.date.today().isoweekday()).name}')
          ...
          >>> dir(Weekday.SATURDAY)
-         ['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value']
+         ['__class__', '__doc__', '__eq__', '__hash__', '__module__', '_add_alias_', '_add_value_alias_', '_generate_next_value_', '_missing_', 'name', 'today', 'value']
 
    .. method:: Enum._generate_next_value_(name, start, count, last_values)
 
index f536a3eae2b6e356dc8c042d9bfcc3aa2fe1d8d5..f97a5193492e602f928d1037408df02afce5d4e7 100644 (file)
@@ -784,6 +784,8 @@ class EnumType(type):
                 '__class__', '__contains__', '__doc__', '__getitem__',
                 '__iter__', '__len__', '__members__', '__module__',
                 '__name__', '__qualname__',
+                # Supported sunder names of Enum class
+                '_generate_next_value_', '_missing_',
                 ]
                 + members
                 )
@@ -1297,7 +1299,8 @@ class Enum(metaclass=EnumType):
         """
         Returns public methods and other interesting attributes.
         """
-        interesting = set()
+        # Initialize with supported sunder names
+        interesting = set(('_generate_next_value_', '_missing_', '_add_alias_', '_add_value_alias_'))
         if self.__class__._member_type_ is not object:
             interesting = set(object.__dir__(self))
         for name in getattr(self, '__dict__', []):
index e0dcc6b8a519e7d3c1a447a010f84fab632044ab..b05eab43bd9eff13c943a547484b7797b1347e2c 100644 (file)
@@ -5105,6 +5105,8 @@ class TestStdLib(unittest.TestCase):
                 ('__qualname__', 'TestStdLib.Color'),
                 ('__init_subclass__', getattr(self.Color, '__init_subclass__')),
                 ('__iter__', self.Color.__iter__),
+                ('_missing_', self.Color._missing_),
+                ('_generate_next_value_', self.Color._generate_next_value_),
                 ))
         result = dict(inspect.getmembers(self.Color))
         self.assertEqual(set(values.keys()), set(result.keys()))
@@ -5147,6 +5149,10 @@ class TestStdLib(unittest.TestCase):
                     defining_class=self.Color, object='Color'),
                 Attribute(name='__qualname__', kind='data',
                     defining_class=self.Color, object='TestStdLib.Color'),
+                Attribute(name='_missing_', kind='class method',
+                    defining_class=Enum, object=Enum.__dict__['_missing_']),
+                Attribute(name='_generate_next_value_', kind='static method',
+                    defining_class=self.Color, object=self.Color.__dict__['_generate_next_value_']),
                 Attribute(name='YELLOW', kind='data',
                     defining_class=self.Color, object=self.Color.YELLOW),
                 Attribute(name='MAGENTA', kind='data',
@@ -5178,11 +5184,13 @@ class TestStdLib(unittest.TestCase):
                 # __doc__ is too big to check exactly, so treat the same as __init_subclass__
                 for name in ('name','kind','defining_class'):
                     if getattr(v, name) != getattr(r, name):
-                        print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
+                        print('\n%s\nexpected: %s\nactual:   %s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
                         failed = True
+                        # breakpoint()
             elif r != v:
-                print('\n%s\n%s\n%s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
+                print('\n%s\nexpected: %s\nactual:   %s\n%s\n' % ('=' * 75, r, v, '=' * 75), sep='')
                 failed = True
+                # breakpoint()
         if failed:
             self.fail("result does not equal expected, see print above")
 
@@ -5537,6 +5545,7 @@ def enum_dir(cls):
             '__class__', '__contains__', '__doc__', '__getitem__',
             '__iter__', '__len__', '__members__', '__module__',
             '__name__', '__qualname__',
+            '_generate_next_value_', '_missing_',
             ]
             + members
             )
@@ -5552,7 +5561,8 @@ def enum_dir(cls):
 
 def member_dir(member):
     if member.__class__._member_type_ is object:
-        allowed = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value'])
+        allowed = set(['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'value',
+                       '_generate_next_value_', '_missing_', '_add_alias_', '_add_value_alias_'])
     else:
         allowed = set(dir(member))
     for cls in member.__class__.mro():
diff --git a/Misc/NEWS.d/next/Library/2025-10-12-08-46-26.gh-issue-139398.hESOMl.rst b/Misc/NEWS.d/next/Library/2025-10-12-08-46-26.gh-issue-139398.hESOMl.rst
new file mode 100644 (file)
index 0000000..201b682
--- /dev/null
@@ -0,0 +1,2 @@
+Add supported ``_sunder_`` names to the :func:`dir` method of the :mod:`enum` module
+to support them in :term:`REPL` autocompletion.