Skip to content

Enum: modify __repr__, __str__; update docs #84247

Description

@ethanfurman
BPO 40066
Nosy @warsaw, @rhettinger, @scoder, @vstinner, @tiran, @ezio-melotti, @ethanfurman, @serhiy-storchaka, @The-Compiler, @vedgar, @mscuthbert, @pablogsal, @kulikjak, @kumaraditya303
PRs
  • bpo-40066: Enum: modify repr() and str() #22392
  • bpo-40066: Enum global repr doctest #25116
  • bpo-40066: Enum: add (re)import of Flag for doctests #25118
  • bpo-40066: [Enum] update str() and format() output #30582
  • Revert "bpo-40066: [Enum] update str() and format() output" #30632
  • bpo-40066: Revert "Revert "bpo-40066: [Enum] update str() and format() output..." #30637
  • bpo-40066: [Enum] fix doc and unit tests #30643
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/ethanfurman'
    closed_at = <Date 2022-01-23.00:28:03.406>
    created_at = <Date 2020-03-25.19:48:58.219>
    labels = ['type-feature', 'library', '3.10', '3.11']
    title = 'Enum: modify __repr__, __str__; update docs'
    updated_at = <Date 2022-01-23.00:28:03.406>
    user = 'https://github.com/ethanfurman'

    bugs.python.org fields:

    activity = <Date 2022-01-23.00:28:03.406>
    actor = 'ethan.furman'
    assignee = 'ethan.furman'
    closed = True
    closed_date = <Date 2022-01-23.00:28:03.406>
    closer = 'ethan.furman'
    components = ['Library (Lib)']
    creation = <Date 2020-03-25.19:48:58.219>
    creator = 'ethan.furman'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 40066
    keywords = ['patch']
    message_count = 25.0
    messages = ['365019', '366190', '376900', '376913', '376915', '376918', '377495', '378019', '378239', '389869', '390895', '390956', '390976', '396790', '410676', '410711', '410758', '410773', '410775', '410796', '410797', '410801', '410802', '410803', '410805']
    nosy_count = 16.0
    nosy_names = ['barry', 'rhettinger', 'scoder', 'vstinner', 'christian.heimes', 'ezio.melotti', 'mrabarnett', 'eli.bendersky', 'ethan.furman', 'serhiy.storchaka', 'The Compiler', 'veky', 'mscuthbert', 'pablogsal', 'kulikjak', 'kumaraditya']
    pr_nums = ['22392', '25116', '25118', '30582', '30632', '30637', '30643']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue40066'
    versions = ['Python 3.10', 'Python 3.11']

    Activity

    1. ethanfurman commented on Mar 25, 2020

      @ethanfurman
      MemberAuthor

      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?

    2. self-assigned this
      on Mar 25, 2020
    3. self-assigned this
      on Mar 25, 2020
    4. vedgar commented on Apr 11, 2020

      vedgarmannequin
      Mannequin

      _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. :-/

    5. ethanfurman commented on Sep 14, 2020

      @ethanfurman
      MemberAuthor

      Looks like the re module's flags have been updated separately in bpo-36548:

        >>> 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?

    6. vedgar commented on Sep 14, 2020

      vedgarmannequin
      Mannequin

      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. :-)

    7. ethanfurman commented on Sep 14, 2020

      @ethanfurman
      MemberAuthor

      "repr as inverse of eval" is nice to have, but it is not a requirement.

    8. 17 remaining items

    9. kulikjak commented on Jan 17, 2022

      kulikjakmannequin
      Mannequin

      This also broke our Solaris build with the following error:

      ======================================================================
      FAIL: testGetaddrinfo (test.test_socket.GeneralModuleTests)
      ----------------------------------------------------------------------

      Traceback (most recent call last):
        File "/..../cpython-main/Lib/test/test_socket.py", line 1523, in testGetaddrinfo
          self.assertEqual(repr(type), '<SocketKind.SOCK_STREAM: 1>')
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      AssertionError: '<SocketKind.SOCK_STREAM: 2>' != '<SocketKind.SOCK_STREAM: 1>'
      - <SocketKind.SOCK_STREAM: 2>
      ?                          ^
      + <SocketKind.SOCK_STREAM: 1>
      ?                          ^

      (test.test_socket.GeneralModuleTests fails with the same error).

      The issue is almost certainly that on Solaris, SOCK_STREAM is defined as 2 rather than 1; the following simple program confirms that:

      #include <stdio.h>
      #include <sys/socket.h>
      
      void main() {
      	printf("%d\n", SOCK_STREAM);
      }

      I'm just not sure whether to fix this with assertRegex or a special branch for Solaris (though I am not sure whether everybody else uses 1 or it's more varied).

    10. vstinner commented on Jan 17, 2022

      @vstinner
      Member

      New changeset 42a64c0 by Victor Stinner in branch 'main':
      Revert "bpo-40066: [Enum] update str() and format() output (GH-30582)" (GH-30632)
      42a64c0

    11. vstinner commented on Jan 17, 2022

      @vstinner
      Member

      Sorry, I had to revert the change since it broke the CI and it prevented to merge new PRs. Tell me if I can help to get this test fixed and to get this change merged again.

      By the way, the PR 30582 was merged even if the Docs CI failed.

    12. ethanfurman commented on Jan 17, 2022

      @ethanfurman
      MemberAuthor

      After merging in doc fix by kumaraditya303, I'll update tests so Solaris passes.

    13. ethanfurman commented on Jan 17, 2022

      @ethanfurman
      MemberAuthor

      New changeset 83d544b by Kumar Aditya in branch 'main':
      bpo-40066: [Enum] skip failing doc test (GH-30637)
      83d544b

    14. vstinner commented on Jan 17, 2022

      @vstinner
      Member

      self.assertEqual(repr(type), '<SocketKind.SOCK_STREAM: 1>')

      For this one, I suggest to replace the value with "..." doctest pattern.

    15. ethanfurman commented on Jan 17, 2022

      @ethanfurman
      MemberAuthor

      vstinner wrote:
      --------------

      > self.assertEqual(repr(type), '<SocketKind.SOCK_STREAM: 1>')

      For this one, I suggest to replace the value with "..." doctest pattern.

      That bit of code is from the unittest suite, not the doctest suite.

      I went with:

      self.assertEqual(repr(type), '<SocketKind.SOCK_STREAM: %r>' % type.value)
      
    16. vstinner commented on Jan 17, 2022

      @vstinner
      Member

      I created python/core-workflow#424 "Should we make the Docs CI mandatory on the Python main branch?".

    17. ethanfurman commented on Jan 17, 2022

      @ethanfurman
      MemberAuthor

      New changeset 62a6594 by Ethan Furman in branch 'main':
      bpo-40066: [Enum] fix tests (GH-30643)
      62a6594

    18. transferred this issue fromon Apr 10, 2022
    19. added a commit that references this issue on Nov 20, 2022
    20. added a commit that references this issue on Jun 19, 2024
    21. added a commit that references this issue on Aug 10, 2025
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    3.10 (EOL)end of life3.11only security fixesstdlibStandard Library Python modules in the Lib/ directorytype-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions