Skip to content

Support functional API for Enum creation #2306

Closed

Description

@gvanrossum

The enum.Enum class (new in Python 3.4, also backported as enum34) supports several short forms of creating an Enum type, described under functional API:

A = Enum('A', 'x y z')
B = Enum('B', ('p', 'q'))

These are equivalent to

class A(Enum):
    x = 1
    y = 2
    z = 3
class B(Enum):
    p = 1
    q = 2

Some other syntactic variants are also allowed:

A = Enum('A', 'x,y,z')
A = Enum('A', 'x, y, z')
B = Enum('B', ['p', 'q'])

The values can also be expressed as a list of tuples:

[('cyan', 4), ('magenta', 5), ('yellow', 6)]

or a mapping:

{'chartreuse': 7, 'sea_green': 11, 'rosemary': 42}

Activity

  1. added this to the milestone on Oct 24, 2016
  2. homeworkprod commented on Jan 31, 2017

    @homeworkprod

    I've been checking out mypy for less than two minutes, stumbled upon the error (Too many arguments for "Enum") with the first few files to check, searched the web, and followed a trail of issues to find out that this is at least known.

    Yeah, I'd like to see this fixed rather sooner than later. This might drive new users away right at the start.

    Until then, is there a way to suppress the error and keep mypy from exiting with a return code > 0 (for use in CI scripts)?

  3. JukkaL commented on Jan 31, 2017

    @JukkaL
    Collaborator

    @homeworkprod The recommended fix is to refactor your code to use an alternative enum syntax. Is that not feasible for some reason? If not, I'd like to hear about your concerns. You can also try adding # type: ignore to silence the message.

    @gvanrossum What do you think about making this a high priority issue? Multiple users seem to be hitting this, and this shouldn't be hard to support (though the implementation will be pretty tedious to write).

  4. gvanrossum commented on Jan 31, 2017

    @gvanrossum
    MemberAuthor

    Agreed.

  5. homeworkprod commented on Jan 31, 2017

    @homeworkprod

    @JukkaL Well, I highly prefer the (oftentimes) one-liner functional API to spreading the definition of a (smaller) enum over multiple lines and including distracting, somewhat error-prone numbers that are irrelevant for the business logic (in the cases in question). Why have (to read) half a page of code when three lines neatly do the trick?

    The ignore hint works for me, so I'll go with that for now, thank you.

  6. added 3 commits that reference this issue on Feb 3, 2017
    1bb21e4
    b77a613
    86accbb
  7. self-assigned this
    on Feb 3, 2017
  8. added a commit that references this issue on Feb 3, 2017
    e907a3d
  9. 3 remaining items

  10. added a commit that references this issue on Feb 7, 2017
    8ffe5f4
  11. added 4 commits that reference this issue on Mar 24, 2017
    4c731ab
    e5c5937
    b5710d3
    62c6f6b
  12. removed this from the milestone on Mar 29, 2017
  13. added a commit that references this issue on Mar 31, 2017
    50f6215
  14. homeworkprod commented on May 25, 2017

    @homeworkprod

    Just a quick feedback: Works for me now (tested with Mypy 0.511). Thanks!

  15. anentropic commented on Nov 1, 2017

    @anentropic

    mypy 0.540

    PictureSize = Enum('PictureSize', 'P0 P1 P2 P3 P4 P5 P6 P7 P8', type=str, module=__name__)

    gives:

    error: Too many arguments for Enum()
    

    Later when trying to access a value from the enum:

    error: "Type[Enum]" has no attribute "P0"
    

    I understand if it won't be fixed, but I thought from previous comment maybe it had been?

  16. anentropic commented on Nov 1, 2017

    @anentropic

    ah I see, removing the type=str, module=__name__ extra kwargs gets rid of the second error too

    I guess with this much working now it ought to be easy to add recognition of all the kwargs the constructor supports as detailed in the docs?https://docs.python.org/3/library/enum.html#functional-api

  17. JukkaL commented on Nov 1, 2017

    @JukkaL
    Collaborator

    @anentropic Yeah, this is something mypy should be able to support pretty easily. Created #4184 to track the issue.

  18. rdbisme commented on Feb 27, 2020

    @rdbisme

    Is this related? #4865

    Because I'm hitting the same problem...

    from enum import IntEnum
    from typing import Collection
    
    
    def list_to_enum(cls, fields: Collection[str]) -> IntEnum:
        """ Convert a list of textual fields to the class:`IntEnum` that needs
        to be stored in this class :attr:`fields` """
    
        return IntEnum(
            cls._FIELDS_ENUM_NAME, dict(zip(fields, range(len(fields))))
        )
    
    

    From here

    The second argument is the source of enumeration member names. It can be a whitespace-separated string of names, a sequence of names, a sequence of 2-tuples with key/value pairs, or a mapping (e.g. dictionary) of names to values. The last two options enable assigning arbitrary values to enumerations; the others auto-assign increasing integers starting with 1 (use the start parameter to specify a different starting value). A new class derived from Enum is returned.

  19. JukkaL commented on Feb 28, 2020

    @JukkaL
    Collaborator

    @rubendibattista Your example is too dynamic for mypy to understand (see #4865 (comment)).

  20. mvoitko commented on Oct 15, 2021

    @mvoitko

    Are there PRs, issues or at least plans to handle the case @rubendibattista metioned?
    I have faced a similar problem:

    import enum
    from typing import Any
    
    
    class StrAutoEnum(str, enum.Enum):
        def _generate_next_value_(name: str, start: Any, count: int, last_values: Any) -> str:  # type: ignore[misc, override] # noqa:E501
            return name
    
    
    Target = StrAutoEnum('Target', {name: enum.auto() for name in model_names})  # type: ignore[call-overload]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions