Skip to content

Commit bd37ab8

Browse files
authored
Adds docs about Enum type (#11805)
* Adds docs about `Enum` type * Better structure
1 parent 7143424 commit bd37ab8

File tree

1 file changed

+119
-1
lines changed

1 file changed

+119
-1
lines changed

docs/source/literal_types.rst

+119-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
Literal types and Enums
2+
=======================
3+
14
.. _literal_types:
25

36
Literal types
4-
=============
7+
-------------
58

69
Literal types let you indicate that an expression is equal to some specific
710
primitive value. For example, if we annotate a variable with type ``Literal["foo"]``,
@@ -369,3 +372,118 @@ whatever type the parameter has. For example, ``Literal[3]`` is treated as a
369372
subtype of ``int`` and so will inherit all of ``int``'s methods directly. This
370373
means that ``Literal[3].__add__`` accepts the same arguments and has the same
371374
return type as ``int.__add__``.
375+
376+
377+
Enums
378+
-----
379+
380+
Mypy has special support for :py:class:`enum.Enum` and its subclasses:
381+
:py:class:`enum.IntEnum`, :py:class:`enum.Flag`, and :py:class:`enum.IntFlag`.
382+
383+
.. code-block:: python
384+
385+
from enum import Enum
386+
387+
class Direction(Enum):
388+
up = 'up'
389+
down = 'down'
390+
391+
reveal_type(Direction.up) # Revealed type is "Literal[Direction.up]?"
392+
reveal_type(Direction.down) # Revealed type is "Literal[Direction.down]?"
393+
394+
You can use enums to annotate types as you would expect:
395+
396+
.. code-block:: python
397+
398+
class Movement:
399+
def __init__(self, direction: Direction, speed: float) -> None:
400+
self.direction = direction
401+
self.speed = speed
402+
403+
Movement(Direction.up, 5.0) # ok
404+
Movement('up', 5.0) # E: Argument 1 to "Movemement" has incompatible type "str"; expected "Direction"
405+
406+
Exhaustive checks
407+
*****************
408+
409+
Similiar to ``Literal`` types ``Enum`` supports exhaustive checks.
410+
Let's start with a definition:
411+
412+
.. code-block:: python
413+
414+
from enum import Enum
415+
from typing import NoReturn
416+
417+
def assert_never(value: NoReturn) -> NoReturn:
418+
# This also works in runtime as well:
419+
assert False, 'This code should never be reached, got: {0}'.format(value)
420+
421+
class Direction(Enum):
422+
up = 'up'
423+
down = 'down'
424+
425+
Now, let's define an exhaustive check:
426+
427+
.. code-block:: python
428+
429+
def choose_direction(direction: Direction) -> None:
430+
if direction is Direction.up:
431+
reveal_type(direction) # N: Revealed type is "Literal[ex.Direction.up]"
432+
print('Going up!')
433+
return
434+
elif direction is Direction.down:
435+
print('Down')
436+
return
437+
assert_never(direction)
438+
439+
And then test that it raises an error when some cases are not covered:
440+
441+
.. code-block:: python
442+
443+
def choose_direction(direction: Direction) -> None:
444+
if direction == Direction.up:
445+
print('Going up!')
446+
return
447+
assert_never(direction) # E: Argument 1 to "assert_never" has incompatible type "Direction"; expected "NoReturn"
448+
449+
Extra Enum checks
450+
*****************
451+
452+
Mypy also tries to support special features of ``Enum``
453+
the same way Python's runtime does.
454+
455+
Extra checks:
456+
457+
- Any ``Enum`` class with values is implicitly :ref:`final <final_attrs>`.
458+
This is what happens in CPython:
459+
460+
.. code-block:: python
461+
462+
>>> class AllDirection(Direction):
463+
... left = 'left'
464+
... right = 'right'
465+
Traceback (most recent call last):
466+
...
467+
TypeError: Other: cannot extend enumeration 'Some'
468+
469+
We do the same thing:
470+
471+
.. code-block:: python
472+
473+
class AllDirection(Direction): # E: Cannot inherit from final class "Some"
474+
left = 'left'
475+
right = 'right'
476+
477+
- All ``Enum`` fields are implictly ``final`` as well.
478+
479+
.. code-block:: python
480+
481+
Direction.up = '^' # E: Cannot assign to final attribute "up"
482+
483+
- All field names are checked to be unique.
484+
485+
.. code-block:: python
486+
487+
class Some(Enum):
488+
x = 1
489+
x = 2 # E: Attempted to reuse member name "x" in Enum definition "Some"

0 commit comments

Comments
 (0)