diff options
author | Ethan Furman <ethan@stoneleaf.us> | 2022-01-16 06:41:43 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-16 06:41:43 (GMT) |
commit | acf7403f9baea3ae1119fc6b4a3298522188bf96 (patch) | |
tree | fcffbb83c601353ac1fce9b35b0f2424c8ce9899 /Doc/library | |
parent | 37eab55ac9da6b6361f136a1da15bfcef12ed954 (diff) | |
download | cpython-acf7403f9baea3ae1119fc6b4a3298522188bf96.zip cpython-acf7403f9baea3ae1119fc6b4a3298522188bf96.tar.gz cpython-acf7403f9baea3ae1119fc6b4a3298522188bf96.tar.bz2 |
bpo-40066: [Enum] update str() and format() output (GH-30582)
Undo rejected PEP-663 changes:
- restore `repr()` to its 3.10 status
- restore `str()` to its 3.10 status
New changes:
- `IntEnum` and `IntFlag` now leave `__str__` as the original `int.__str__` so that str() and format() return the same result
- zero-valued flags without a name have a slightly changed repr(), e.g. `repr(Color(0)) == '<Color: 0>'`
- update `dir()` for mixed-in types to return all the methods and attributes of the mixed-in type
- added `_numeric_repr_` to `Flag` to control display of unnamed values
- enums without doc strings have a more comprehensive doc string added
- `ReprEnum` added -- inheriting from this makes it so only `__repr__` is replaced, not `__str__` nor `__format__`; `IntEnum`, `IntFlag`, and `StrEnum` all inherit from `ReprEnum`
Diffstat (limited to 'Doc/library')
-rw-r--r-- | Doc/library/enum.rst | 265 | ||||
-rw-r--r-- | Doc/library/ssl.rst | 4 |
2 files changed, 175 insertions, 94 deletions
diff --git a/Doc/library/enum.rst b/Doc/library/enum.rst index 8bb19dc..906c60b 100644 --- a/Doc/library/enum.rst +++ b/Doc/library/enum.rst @@ -31,7 +31,7 @@ An enumeration: * uses *call* syntax to return members by value * uses *index* syntax to return members by name -Enumerations are created either by using the :keyword:`class` syntax, or by +Enumerations are created either by using :keyword:`class` syntax, or by using function-call syntax:: >>> from enum import Enum @@ -45,7 +45,7 @@ using function-call syntax:: >>> # functional syntax >>> Color = Enum('Color', ['RED', 'GREEN', 'BLUE']) -Even though we can use the :keyword:`class` syntax to create Enums, Enums +Even though we can use :keyword:`class` syntax to create Enums, Enums are not normal Python classes. See :ref:`How are Enums different? <enum-class-differences>` for more details. @@ -53,7 +53,7 @@ are not normal Python classes. See - The class :class:`Color` is an *enumeration* (or *enum*) - The attributes :attr:`Color.RED`, :attr:`Color.GREEN`, etc., are - *enumeration members* (or *enum members*) and are functionally constants. + *enumeration members* (or *members*) and are functionally constants. - The enum members have *names* and *values* (the name of :attr:`Color.RED` is ``RED``, the value of :attr:`Color.BLUE` is ``3``, etc.) @@ -110,15 +110,10 @@ Module Contents :class:`StrEnum` defaults to the lower-cased version of the member name, while other Enums default to 1 and increase from there. - :func:`global_enum` - - :class:`Enum` class decorator to apply the appropriate global `__repr__`, - and export its members into the global name space. - - :func:`.property` + :func:`property` Allows :class:`Enum` members to have attributes without conflicting with - other members' names. + member names. :func:`unique` @@ -131,7 +126,7 @@ Module Contents .. versionadded:: 3.6 ``Flag``, ``IntFlag``, ``auto`` -.. versionadded:: 3.11 ``StrEnum``, ``EnumCheck``, ``FlagBoundary`` +.. versionadded:: 3.11 ``StrEnum``, ``EnumCheck``, ``FlagBoundary``, ``property`` --------------- @@ -145,6 +140,11 @@ Data Types to subclass *EnumType* -- see :ref:`Subclassing EnumType <enumtype-examples>` for details. + *EnumType* is responsible for setting the correct :meth:`__repr__`, + :meth:`__str__`, :meth:`__format__`, and :meth:`__reduce__` methods on the + final *enum*, as well as creating the enum members, properly handling + duplicates, providing iteration over the enum class, etc. + .. method:: EnumType.__contains__(cls, member) Returns ``True`` if member belongs to the ``cls``:: @@ -162,32 +162,31 @@ Data Types .. method:: EnumType.__dir__(cls) Returns ``['__class__', '__doc__', '__members__', '__module__']`` and the - names of the members in ``cls``. User-defined methods and methods from - mixin classes will also be included:: + names of the members in *cls*:: >>> dir(Color) - ['BLUE', 'GREEN', 'RED', '__class__', '__doc__', '__members__', '__module__'] + ['BLUE', 'GREEN', 'RED', '__class__', '__contains__', '__doc__', '__getitem__', '__init_subclass__', '__iter__', '__len__', '__members__', '__module__', '__name__', '__qualname__'] .. method:: EnumType.__getattr__(cls, name) Returns the Enum member in *cls* matching *name*, or raises an :exc:`AttributeError`:: >>> Color.GREEN - Color.GREEN + <Color.GREEN: 2> .. method:: EnumType.__getitem__(cls, name) - Returns the Enum member in *cls* matching *name*, or raises a :exc:`KeyError`:: + Returns the Enum member in *cls* matching *name*, or raises an :exc:`KeyError`:: >>> Color['BLUE'] - Color.BLUE + <Color.BLUE: 3> .. method:: EnumType.__iter__(cls) Returns each member in *cls* in definition order:: >>> list(Color) - [Color.RED, Color.GREEN, Color.BLUE] + [<Color.RED: 1>, <Color.GREEN: 2>, <Color.BLUE: 3>] .. method:: EnumType.__len__(cls) @@ -201,7 +200,7 @@ Data Types Returns each member in *cls* in reverse definition order:: >>> list(reversed(Color)) - [Color.BLUE, Color.GREEN, Color.RED] + [<Color.BLUE: 3>, <Color.GREEN: 2>, <Color.RED: 1>] .. class:: Enum @@ -232,7 +231,7 @@ Data Types .. attribute:: Enum._ignore_ ``_ignore_`` is only used during creation and is removed from the - enumeration once that is complete. + enumeration once creation is complete. ``_ignore_`` is a list of names that will not become members, and whose names will also be removed from the completed enumeration. See @@ -261,7 +260,7 @@ Data Types .. method:: Enum.__dir__(self) Returns ``['__class__', '__doc__', '__module__', 'name', 'value']`` and - any public methods defined on ``self.__class__`` or a mixin class:: + any public methods defined on *self.__class__*:: >>> from datetime import date >>> class Weekday(Enum): @@ -276,7 +275,7 @@ Data Types ... def today(cls): ... print('today is %s' % cls(date.today().isoweekday()).name) >>> dir(Weekday.SATURDAY) - ['__class__', '__doc__', '__module__', 'name', 'today', 'value'] + ['__class__', '__doc__', '__eq__', '__hash__', '__module__', 'name', 'today', 'value'] .. method:: Enum._generate_next_value_(name, start, count, last_values) @@ -298,6 +297,11 @@ Data Types >>> PowersOfThree.SECOND.value 6 + .. method:: Enum.__init_subclass__(cls, \**kwds) + + A *classmethod* that is used to further configure subsequent subclasses. + By default, does nothing. + .. method:: Enum._missing_(cls, value) A *classmethod* for looking up values not found in *cls*. By default it @@ -317,42 +321,55 @@ Data Types >>> Build.DEBUG.value 'debug' >>> Build('deBUG') - Build.DEBUG + <Build.DEBUG: 'debug'> .. method:: Enum.__repr__(self) Returns the string used for *repr()* calls. By default, returns the - *Enum* name and the member name, but can be overridden:: + *Enum* name, member name, and value, but can be overridden:: - >>> class OldStyle(Enum): - ... RETRO = auto() - ... OLD_SCHOOl = auto() - ... YESTERYEAR = auto() + >>> class OtherStyle(Enum): + ... ALTERNATE = auto() + ... OTHER = auto() + ... SOMETHING_ELSE = auto() ... def __repr__(self): ... cls_name = self.__class__.__name__ - ... return f'<{cls_name}.{self.name}: {self.value}>' - >>> OldStyle.RETRO - <OldStyle.RETRO: 1> + ... return f'{cls_name}.{self.name}' + >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" + (OtherStyle.ALTERNATE, 'OtherStyle.ALTERNATE', 'OtherStyle.ALTERNATE') .. method:: Enum.__str__(self) Returns the string used for *str()* calls. By default, returns the - member name, but can be overridden:: + *Enum* name and member name, but can be overridden:: - >>> class OldStyle(Enum): - ... RETRO = auto() - ... OLD_SCHOOl = auto() - ... YESTERYEAR = auto() + >>> class OtherStyle(Enum): + ... ALTERNATE = auto() + ... OTHER = auto() + ... SOMETHING_ELSE = auto() ... def __str__(self): - ... cls_name = self.__class__.__name__ - ... return f'{cls_name}.{self.name}' - >>> OldStyle.RETRO - OldStyle.RETRO + ... return f'{self.name}' + >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" + (<OtherStyle.ALTERNATE: 1>, 'ALTERNATE', 'ALTERNATE') + + .. method:: Enum.__format__(self) + + Returns the string used for *format()* and *f-string* calls. By default, + returns :meth:`__str__` returns, but can be overridden:: + + >>> class OtherStyle(Enum): + ... ALTERNATE = auto() + ... OTHER = auto() + ... SOMETHING_ELSE = auto() + ... def __format__(self, spec): + ... return f'{self.name}' + >>> OtherStyle.ALTERNATE, str(OtherStyle.ALTERNATE), f"{OtherStyle.ALTERNATE}" + (<OtherStyle.ALTERNATE: 1>, 'OtherStyle.ALTERNATE', 'ALTERNATE') -.. note:: + .. note:: - Using :class:`auto` with :class:`Enum` results in integers of increasing value, - starting with ``1``. + Using :class:`auto` with :class:`Enum` results in integers of increasing value, + starting with ``1``. .. class:: IntEnum @@ -367,7 +384,7 @@ Data Types ... TWO = 2 ... THREE = 3 >>> Numbers.THREE - Numbers.THREE + <Numbers.THREE: 3> >>> Numbers.ONE + Numbers.TWO 3 >>> Numbers.THREE + 5 @@ -375,10 +392,14 @@ Data Types >>> Numbers.THREE == 3 True -.. note:: + .. note:: - Using :class:`auto` with :class:`IntEnum` results in integers of increasing value, - starting with ``1``. + Using :class:`auto` with :class:`IntEnum` results in integers of increasing + value, starting with ``1``. + + .. versionchanged:: 3.11 :meth:`__str__` is now :func:`int.__str__` to + better support the *replacement of existing constants* use-case. + :meth:`__format__` was already :func:`int.__format__` for that same reason. .. class:: StrEnum @@ -392,13 +413,16 @@ Data Types instead of ``isinstance(str, unknown)``), and in those locations you will need to use ``str(StrEnum.member)``. + .. note:: -.. note:: + Using :class:`auto` with :class:`StrEnum` results in the lower-cased member + name as the value. - Using :class:`auto` with :class:`StrEnum` results in values of the member name, - lower-cased. + .. note:: :meth:`__str__` is :func:`str.__str__` to better support the + *replacement of existing constants* use-case. :meth:`__format__` is likewise + :func:`int.__format__` for that same reason. -.. versionadded:: 3.11 + .. versionadded:: 3.11 .. class:: Flag @@ -431,9 +455,9 @@ Data Types Returns all contained members:: >>> list(Color.RED) - [Color.RED] + [<Color.RED: 1>] >>> list(purple) - [Color.RED, Color.BLUE] + [<Color.RED: 1>, <Color.BLUE: 4>] .. method:: __len__(self): @@ -461,42 +485,52 @@ Data Types Returns current flag binary or'ed with other:: >>> Color.RED | Color.GREEN - Color.RED|Color.GREEN + <Color.RED|GREEN: 3> .. method:: __and__(self, other) Returns current flag binary and'ed with other:: >>> purple & white - Color.RED|Color.BLUE + <Color.RED|BLUE: 5> >>> purple & Color.GREEN - 0x0 + <Color: 0> .. method:: __xor__(self, other) Returns current flag binary xor'ed with other:: >>> purple ^ white - Color.GREEN + <Color.GREEN: 2> >>> purple ^ Color.GREEN - Color.RED|Color.GREEN|Color.BLUE + <Color.RED|GREEN|BLUE: 7> .. method:: __invert__(self): Returns all the flags in *type(self)* that are not in self:: >>> ~white - 0x0 + <Color: 0> >>> ~purple - Color.GREEN + <Color.GREEN: 2> >>> ~Color.RED - Color.GREEN|Color.BLUE + <Color.GREEN|BLUE: 6> + + .. method:: _numeric_repr_ + + Function used to format any remaining unnamed numeric values. Default is + the value's repr; common choices are :func:`hex` and :func:`oct`. + + .. note:: -.. note:: + Using :class:`auto` with :class:`Flag` results in integers that are powers + of two, starting with ``1``. - Using :class:`auto` with :class:`Flag` results in integers that are powers - of two, starting with ``1``. + .. versionchanged:: 3.11 The *repr()* of zero-valued flags has changed. It + is now:: + >>> Color(0) + <Color: 0> .. class:: IntFlag @@ -509,9 +543,9 @@ Data Types ... GREEN = auto() ... BLUE = auto() >>> Color.RED & 2 - 0x0 + <Color: 0> >>> Color.RED | 2 - Color.RED|Color.GREEN + <Color.RED|GREEN: 3> If any integer operation is performed with an *IntFlag* member, the result is not an *IntFlag*:: @@ -524,15 +558,25 @@ Data Types * the result is a valid *IntFlag*: an *IntFlag* is returned * the result is not a valid *IntFlag*: the result depends on the *FlagBoundary* setting -.. note:: + The *repr()* of unnamed zero-valued flags has changed. It is now: + + >>> Color(0) + <Color: 0> + + .. note:: + + Using :class:`auto` with :class:`IntFlag` results in integers that are powers + of two, starting with ``1``. + + .. versionchanged:: 3.11 :meth:`__str__` is now :func:`int.__str__` to + better support the *replacement of existing constants* use-case. + :meth:`__format__` was already :func:`int.__format__` for that same reason. - Using :class:`auto` with :class:`IntFlag` results in integers that are powers - of two, starting with ``1``. .. class:: EnumCheck *EnumCheck* contains the options used by the :func:`verify` decorator to ensure - various constraints; failed constraints result in a :exc:`TypeError`. + various constraints; failed constraints result in a :exc:`ValueError`. .. attribute:: UNIQUE @@ -582,11 +626,11 @@ Data Types ... ValueError: invalid Flag 'Color': aliases WHITE and NEON are missing combined values of 0x18 [use enum.show_flag_values(value) for details] -.. note:: + .. note:: - CONTINUOUS and NAMED_FLAGS are designed to work with integer-valued members. + CONTINUOUS and NAMED_FLAGS are designed to work with integer-valued members. -.. versionadded:: 3.11 + .. versionadded:: 3.11 .. class:: FlagBoundary @@ -606,7 +650,7 @@ Data Types >>> StrictFlag(2**2 + 2**4) Traceback (most recent call last): ... - ValueError: StrictFlag: invalid value: 20 + ValueError: <flag 'StrictFlag'> invalid value 20 given 0b0 10100 allowed 0b0 00111 @@ -621,7 +665,7 @@ Data Types ... GREEN = auto() ... BLUE = auto() >>> ConformFlag(2**2 + 2**4) - ConformFlag.BLUE + <ConformFlag.BLUE: 4> .. attribute:: EJECT @@ -647,12 +691,52 @@ Data Types ... GREEN = auto() ... BLUE = auto() >>> KeepFlag(2**2 + 2**4) - KeepFlag.BLUE|0x10 + <KeepFlag.BLUE|16: 20> .. versionadded:: 3.11 --------------- +Supported ``__dunder__`` names +"""""""""""""""""""""""""""""" + +:attr:`__members__` is a read-only ordered mapping of ``member_name``:``member`` +items. It is only available on the class. + +:meth:`__new__`, if specified, must create and return the enum members; it is +also a very good idea to set the member's :attr:`_value_` appropriately. Once +all the members are created it is no longer used. + + +Supported ``_sunder_`` names +"""""""""""""""""""""""""""" + +- ``_name_`` -- name of the member +- ``_value_`` -- value of the member; can be set / modified in ``__new__`` + +- ``_missing_`` -- a lookup function used when a value is not found; may be + overridden +- ``_ignore_`` -- a list of names, either as a :class:`list` or a :class:`str`, + that will not be transformed into members, and will be removed from the final + class +- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent + (class attribute, removed during class creation) +- ``_generate_next_value_`` -- used to get an appropriate value for an enum + member; may be overridden + + .. note:: + + For standard :class:`Enum` classes the next value chosen is the last value seen + incremented by one. + + For :class:`Flag` classes the next value chosen will be the next highest + power-of-two, regardless of the last value seen. + +.. versionadded:: 3.6 ``_missing_``, ``_order_``, ``_generate_next_value_`` +.. versionadded:: 3.7 ``_ignore_`` + +--------------- + Utilities and Decorators ------------------------ @@ -668,15 +752,6 @@ Utilities and Decorators ``_generate_next_value_`` can be overridden to customize the values used by *auto*. -.. decorator:: global_enum - - A :keyword:`class` decorator specifically for enumerations. It replaces the - :meth:`__repr__` method with one that shows *module_name*.*member_name*. It - also injects the members, and their aliases, into the global namespace they - were defined in. - -.. versionadded:: 3.11 - .. decorator:: property A decorator similar to the built-in *property*, but specifically for @@ -688,7 +763,7 @@ Utilities and Decorators *Enum* class, and *Enum* subclasses can define members with the names ``value`` and ``name``. -.. versionadded:: 3.11 + .. versionadded:: 3.11 .. decorator:: unique @@ -714,7 +789,7 @@ Utilities and Decorators :class:`EnumCheck` are used to specify which constraints should be checked on the decorated enumeration. -.. versionadded:: 3.11 + .. versionadded:: 3.11 --------------- @@ -726,14 +801,20 @@ Notes These three enum types are designed to be drop-in replacements for existing integer- and string-based values; as such, they have extra limitations: - - ``format()`` will use the value of the enum member, unless ``__str__`` - has been overridden + - ``__str__`` uses the value and not the name of the enum member - - ``StrEnum.__str__`` uses the value and not the name of the enum member + - ``__format__``, because it uses ``__str__``, will also use the value of + the enum member instead of its name - If you do not need/want those limitations, you can create your own base - class by mixing in the ``int`` or ``str`` type yourself:: + If you do not need/want those limitations, you can either create your own + base class by mixing in the ``int`` or ``str`` type yourself:: >>> from enum import Enum >>> class MyIntEnum(int, Enum): ... pass + + or you can reassign the appropriate :meth:`str`, etc., in your enum:: + + >>> from enum import IntEnum + >>> class MyIntEnum(IntEnum): + ... __str__ = IntEnum.__str__ diff --git a/Doc/library/ssl.rst b/Doc/library/ssl.rst index eb33d7e..4d8488a 100644 --- a/Doc/library/ssl.rst +++ b/Doc/library/ssl.rst @@ -2070,7 +2070,7 @@ to speed up repeated connections from the same clients. :attr:`SSLContext.verify_flags` returns :class:`VerifyFlags` flags: >>> ssl.create_default_context().verify_flags # doctest: +SKIP - ssl.VERIFY_X509_TRUSTED_FIRST + <VerifyFlags.VERIFY_X509_TRUSTED_FIRST: 32768> .. attribute:: SSLContext.verify_mode @@ -2082,7 +2082,7 @@ to speed up repeated connections from the same clients. :attr:`SSLContext.verify_mode` returns :class:`VerifyMode` enum: >>> ssl.create_default_context().verify_mode - ssl.CERT_REQUIRED + <VerifyMode.CERT_REQUIRED: 2> .. index:: single: certificates |