This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: '__new__' is never shown in `dir(SomeEnum)`
Type: behavior Stage: resolved
Components: Library (Lib) Versions:
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: AlexWaygood, ethan.furman, sobolevn
Priority: normal Keywords: patch

Created on 2022-01-05 15:15 by sobolevn, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 30421 merged sobolevn, 2022-01-05 15:17
Messages (3)
msg409771 - (view) Author: Nikita Sobolev (sobolevn) * (Python triager) Date: 2022-01-05 15:15
Right now `__new__` is marked to be special-cased in `Enum.__dir__`.
It is generally ignored:
But, (I think that was the original idea), when `__new__` is overridden, it should be added to the output.

But, this line is problematic: https://github.com/python/cpython/blame/46e4c257e7c26c813620232135781e6c53fe8d4d/Lib/enum.py#L656

Why? Because `self.__new__` is always `EnumMeta.__new__`. Original `__new__` is renamed to `_new_member_`.

This behavior is also not tested.

So, my proposal is: let's always remove this method from `__dir__`. Why?
- If we modify the check above to compare `_new_member_`, we will show `__new__` as the output. It is kinda misleading
- `__new__` is not supposed to be overloaded in `EnumMeta`, it is very special
- `__new__` is a very basic thing. It would be kinda strange not to see it for some cases, but to see it for others. For example, all (?) other data types always show `__new__`, even if it is not explicitly defined:

```
>>> class A:
...    def __new__(*args, **kwargs): ...
... 
>>> assert '__new__' in dir(A)

>>> class B: ...
... 
>>> assert '__new__' in dir(B)
```

I guess being consistent here (we don't show `__new__` at all times) is better.

I will send a PR that removes these two lines in a moment! Any other ideas are much appreciated! 

Related:
- https://bugs.python.org/issue45535
- https://github.com/python/cpython/pull/29316
msg409785 - (view) Author: Alex Waygood (AlexWaygood) * (Python triager) Date: 2022-01-05 16:46
Thanks, Nikita! My bad for not adding tests for __new__ in PR 29316.

To confirm: yes, my idea in PR 29316 was that "__new__" (along with most enum dunders) should not show up in the output of dir(Enum), but should show up in dir(EnumSubclass) if and only if __new__ has been overridden outside of enum.py. That's because, unlike with most Python classes, the fact that enum.Enum has a __new__ method or a __format__ method doesn't really tell you very much about enum.Enum's behaviour, due to how magical enums are. But if it's been overridden in a custom Enum subclass, that does tell you that the enum class has special behaviour in some way — the HTTPStatus enum at Lib/http/__init__.py:6 is a really good example of that.

But you're right: the existing code doesn't work as expected, at all:

```
>>> from http import HTTPStatus
>>> '__new__' in dir(HTTPStatus)
False
```
msg409790 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2022-01-05 17:06
New changeset 817a6bc9f7b802511c4d42273a621c556a48870b by Nikita Sobolev in branch 'main':
bpo-46269: [Enum] remove special-casing of `__new__` in `EnumType.__dir__` (GH-30421)
https://github.com/python/cpython/commit/817a6bc9f7b802511c4d42273a621c556a48870b
History
Date User Action Args
2022-04-11 14:59:54adminsetgithub: 90427
2022-01-14 12:09:05sobolevnsetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2022-01-05 17:06:07ethan.furmansetmessages: + msg409790
2022-01-05 16:46:31AlexWaygoodsetmessages: + msg409785
2022-01-05 15:17:14sobolevnsetkeywords: + patch
stage: patch review
pull_requests: + pull_request28625
2022-01-05 15:15:11sobolevncreate