classification
Title: Enum._convert should change __repr__ and/or __str__ to use module name instead of class name
Type: enhancement Stage: patch review
Components: Versions: Python 3.10
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: ethan.furman Nosy List: barry, eli.bendersky, ethan.furman, ezio.melotti, mrabarnett, rhettinger, serhiy.storchaka, veky
Priority: normal Keywords: patch

Created on 2020-03-25 19:48 by ethan.furman, last changed 2020-10-08 11:58 by veky.

Pull Requests
URL Status Linked Edit
PR 22392 open ethan.furman, 2020-09-24 04:55
Messages (9)
msg365019 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2020-03-25 19:48
Serhiy had the idea of having Enum._convert also modify the __str__ and __repr__ of newly created enumerations to display the module name instead of the enumeration name (https://bugs.python.org/msg325007):

--> socket.AF_UNIX
<AddressFamily.AF_UNIX: 1>   ==>  <socket.AF_UNIX: 1>

--> print(socket.AF_UNIX)
AddressFamily.AF_UNIX        ==>  socket.AF_UNIX

Thoughts?
msg366190 - (view) Author: Vedran Čačić (veky) * Date: 2020-04-11 03:49
> _in some cases when enum instances are exposed as module globals_

Yes. And repr should be inverse of eval, but it's probably too late for that. :-/
msg376900 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2020-09-14 20:26
Looks like the `re` module's flags have been updated separately in issue36548:

  >>> import re
  >>> re.I
  re.IGNORECASE

  >>> print(re.I)
  # should also be re.IGNORECASE

  >>> re.I|re.S|re.X
  re.IGNORECASE|re.DOTALL|re.VERBOSE


For stdlib Enum conversions are we happy with that?  Or should __str__ just print the numeric value?
msg376913 - (view) Author: Vedran Čačić (veky) * Date: 2020-09-14 22:31
If it's considered to be not too backwards-incompatible, I think it would be nice to have str different from repr. That way we can finetune what exactly we need. But we can already do almost exactly that with *int* instead of *str*, so it's not too compelling.

Much more important thing is the "repr as inverse of eval". Is there any way we can have that for our own enums (as a mixin or a decorator)?

    @module_global(re)
    class RegexFlag(Enum):
        ...

It would be fantastic. :-)
msg376915 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2020-09-14 23:04
"repr as inverse of eval" is nice to have, but it is not a requirement.
msg376918 - (view) Author: Vedran Čačić (veky) * Date: 2020-09-15 00:09
Noone said it is a requirement, I just said it would be nice to have it factored out as a decorator or something instead of having to write __repr__ over and over again.
msg377495 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2020-09-25 18:16
At this point, the PR has made the following changes:

- normal Enums
  - repr() -> "classname.membername"
  - str()  -> "membername"

- stdlib Enums available as module attributes (RegexFlag, AddressFamily, etc.)
  - repr() -> "modulename.membername"
  - str()  -> "membername"
msg378019 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2020-10-05 12:22
Python-Dev thread [0], summary below:

> As you may have noticed, Enums are starting to pop up all
> over the stdlib [1].
>
> To facilitate transforming existing module constants to
> IntEnums there is `IntEnum._convert_`.  In Issue36548 [2]
> Serhiy modified the __repr__ of RegexFlag:
>
>   >>> import re
>   >>> re.I
>   re.IGNORECASE
>
> I think for converted constants that that looks nice.
>  For anyone that wants the actual value, it is of course
> available as the `.value` attribute:
>
>   >>> re.I.value
>   2
>
> I'm looking for arguments relating to:
>
> - should _convert_ make the default __repr__ be
>   module_name.member_name?
>
> - should _convert_ make the default __str__ be the same,
>   or be the numeric value?

After discussions with Guido I made a (largely done) PR [3] which:

for stdlib global constants (such as RE)
   - repr() -> uses `module.member_name`
   - str() -> uses `member_name`

for stdlib non-global constants, and enums in general
   - repr() -> uses `class.member_name`
   - str() -> uses `member_name`

The questions I would most appreciate an answer to at this point:

- do you think the change has merit?
- why /shouldn't/ we make the change?

As a reminder, the underlying issue is trying to keep at least the stdlib Enum representations the same for those that are replacing preexisting constants.


[0] https://mail.python.org/archives/list/python-dev@python.org/message/CHQW6THTDYNPPFWQ2KDDTUYSAJDCZFNP/

[1] I'm working on making their creation faster.  If anyone wanted to convert EnumMeta to C I would be grateful.

[2] https://bugs.python.org/issue36548

[3] https://github.com/python/cpython/pull/22392
msg378239 - (view) Author: Vedran Čačić (veky) * Date: 2020-10-08 11:58
> - do you think the change has merit?

Absolutely.

> - why /shouldn't/ we make the change?

Well, standard backward compatibility stuff. :-)
History
Date User Action Args
2020-10-08 11:58:12vekysetmessages: + msg378239
2020-10-05 12:22:52ethan.furmansetnosy: + rhettinger
messages: + msg378019
2020-09-25 18:16:58ethan.furmansetmessages: + msg377495
2020-09-24 04:55:47ethan.furmansetkeywords: + patch
stage: patch review
pull_requests: + pull_request21433
2020-09-15 00:09:03vekysetmessages: + msg376918
2020-09-14 23:04:13ethan.furmansetmessages: + msg376915
2020-09-14 22:31:43vekysetmessages: + msg376913
2020-09-14 20:26:29ethan.furmansetnosy: + ezio.melotti, mrabarnett, serhiy.storchaka

messages: + msg376900
versions: + Python 3.10, - Python 3.9
2020-04-11 03:49:21vekysetnosy: + veky
messages: + msg366190
2020-03-25 19:48:58ethan.furmancreate