classification
Title: enum repr should use __qualname__
Type: enhancement Stage: patch review
Components: Library (Lib) Versions: Python 3.8
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: ethan.furman Nosy List: barry, danishprakash, doerwalter, eli.bendersky, enedil, ethan.furman, orlnub123, serhiy.storchaka, underscore_asterisk
Priority: normal Keywords: easy, patch

Created on 2018-08-20 16:34 by doerwalter, last changed 2018-09-11 16:34 by ethan.furman.

Pull Requests
URL Status Linked Edit
PR 8989 closed danishprakash, 2018-08-29 09:39
PR 9011 closed orlnub123, 2018-08-30 23:15
Messages (11)
msg323799 - (view) Author: Walter Dörwald (doerwalter) * (Python committer) Date: 2018-08-20 16:34
The __repr__ output of an enum class should use __qualname__ instead of __name__. The following example shows the problem:

import enum

class X:
   class I:
      pass

class Y:
   class I(enum.Enum):
      pass

print(X.I)
print(Y.I)

This prints:

<class '__main__.X.I'>
<enum 'I'>

I would have expected it to print

<class '__main__.X.I'>
<enum 'Y.I'>

or even for maximum consistency

<class '__main__.X.I'>
<enum '__main__.Y.I'>
msg323801 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-08-20 17:15
__qualname__ should be used only together with __module__.

I agree that the repr of enum should be more consistent with the repr of class.
msg323822 - (view) Author: (underscore_asterisk) * Date: 2018-08-21 06:27
Hi,
I would like to work on this issue. I can submit a PR by tomorrow (or maybe even later today).
msg324110 - (view) Author: Michał Radwański (enedil) * Date: 2018-08-26 00:50
Serhiy, would it be ok to put '__module__' + '.' + __qualname__ here?
msg324313 - (view) Author: Danish Prakash (danishprakash) * Date: 2018-08-29 09:41
Serhiy, why should __qualname__ always be used together with __module__? I can't seem to find a valid reason, I've been through the pep.

<made a PR due to inactivity>
msg324402 - (view) Author: (orlnub123) * Date: 2018-08-30 23:22
I've created a separate PR that also changes the __str__s.
msg324442 - (view) Author: (orlnub123) * Date: 2018-08-31 19:54
After some thinking I've come to the conclusion that making the __str__s use the fully qualified name was a bad idea. I've closed my PR.
msg325006 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-09-11 14:03
> Serhiy, why should __qualname__ always be used together with __module__?

Because what is the purpose of using __qualname__?
msg325007 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2018-09-11 14:18
I think using more longer name in repr and/or str for *instances* of enum classes is not good idea. They are already verbose, and this will make them more verbose.

Actually in some cases when enum instances are exposed as module globals, I would want to make them including the module name instead of the enum class name. For example:

>>> import socket
>>> socket.AF_UNIX
<AddressFamily.AF_UNIX: 1>
>>> print(socket.AF_UNIX)
AddressFamily.AF_UNIX

"socket.AF_UNIX" instead of "AddressFamily.AF_UNIX" would look better to me.
msg325020 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-09-11 16:00
Serhiy said:
-----------
> I think using more longer name in repr and/or str for *instances* of
> enum classes is not good idea. They are already verbose, and this
> will make them more verbose.

I'm okay with verbose reprs, as debugging is the primary feature for those (at least for me).  I'm not okay with __str__ being other than what it is now (but see below).

Serhiy also said:
----------------
> Actually in some cases when enum instances are exposed as module
> globals, I would want to make them including the module name instead
> of the enum class name. For example:
> 
> >>> import socket
> >>> socket.AF_UNIX
> <AddressFamily.AF_UNIX: 1>
> >>> print(socket.AF_UNIX)
> AddressFamily.AF_UNIX
>
> "socket.AF_UNIX" instead of "AddressFamily.AF_UNIX" would look better
> to me.

Since AddressFamily, and other stdlib converted constants, are created user `_convert`, I have no problem with that method also changing the __str__ to be `module.member' instead.
msg325023 - (view) Author: Ethan Furman (ethan.furman) * (Python committer) Date: 2018-09-11 16:34
Okay, I might be changing my mind.  In most cases I suspect the difference would be minimal, but when it isn't, it really isn't.  Take this example from a pydoc test:

  class Color(enum.Enum)
   |  Color(value, names=None, *, module=None, qualname=None, type=None, start=1)
   |  
   |  An enumeration.
   |  
   |  Method resolution order:
   |      Color
   |      enum.Enum
   |      builtins.object
   |  
   |  Data and other attributes defined here:
   |  
-  |  blue = <test.test_enum.TestStdLib.Color.blue: 3>
+  |  blue = <Color.blue: 3>
   |  
-  |  green = <test.test_enum.TestStdLib.Color.green: 2>
+  |  green = <Color.green: 2>
   |  
-  |  red = <test.test_enum.TestStdLib.Color.red: 1>
+  |  red = <Color.red: 1>

It feels like the important information is completely lost in the noise.

Okay, I'm rejecting the __repr__ changes.  Besides the potential verbosity, there should usually only be one of any particular Enum, __module__ and __qualname__ are both readily available when there are more than one (either on accident or by design), and users can modify their own __repr__s if they like.

I'm still thinking about the change in _convert_ to modify __str__ to use the module name instead of the class name....  Here are my questions about that:

- Modify just __str__ or __repr__ as well?
    socket.AF_UNIX instead of AddressFamily.AF_UNIX
    <socket.AddressFamily.AF_UNIX: 1> instead of <AddressFamily.AF_UNIX: 1>

- potential confusion that actual instances of Enum in the stdlib appear
  differently than "regular" Enums?  Or perhaps call out those differences
  in the documentation as examples of customization?
History
Date User Action Args
2018-09-11 16:34:16ethan.furmansetmessages: + msg325023
2018-09-11 16:00:40ethan.furmansetmessages: + msg325020
2018-09-11 14:18:14serhiy.storchakasetmessages: + msg325007
2018-09-11 14:03:43serhiy.storchakasetmessages: + msg325006
2018-08-31 19:54:40orlnub123setmessages: + msg324442
2018-08-30 23:22:46orlnub123setnosy: + orlnub123
messages: + msg324402
2018-08-30 23:15:27orlnub123setpull_requests: + pull_request8481
2018-08-29 09:41:49danishprakashsetnosy: + danishprakash
messages: + msg324313
2018-08-29 09:39:35danishprakashsetkeywords: + patch
stage: patch review
pull_requests: + pull_request8462
2018-08-26 00:50:14enedilsetnosy: + enedil
messages: + msg324110
2018-08-21 06:27:59underscore_asterisksetnosy: + underscore_asterisk
messages: + msg323822
2018-08-20 17:39:51ethan.furmansetassignee: ethan.furman
2018-08-20 17:15:59serhiy.storchakasetnosy: + barry, eli.bendersky, serhiy.storchaka, ethan.furman

messages: + msg323801
versions: + Python 3.8
2018-08-20 16:35:45doerwaltersetkeywords: + easy
2018-08-20 16:34:28doerwaltercreate