148 Commits

Author SHA1 Message Date
Ethan Furman
4e704d7847
gh-95077: [Enum] add code-based deprecation warnings for member.member access (GH-95083)
* issue deprecation warning for member.member access
* always store member property in current class
* remove __getattr__
2022-07-25 11:05:10 -07:00
Ethan Furman
73eab9f35c
Revert "gh-93910: [Enum] restore member.member restriction while keeping performance boost (GH-94913)" (#94985)
This reverts commit c20186c3972ff38577c4c5e32ca86748210983d2.
2022-07-18 13:22:52 -07:00
Ethan Furman
c961d14f85
gh-94601: [Enum] fix inheritance for __str__ and friends (GH-94942) 2022-07-17 18:51:04 -07:00
Ethan Furman
c20186c397
gh-93910: [Enum] restore member.member restriction while keeping performance boost (GH-94913) 2022-07-16 18:13:57 -07:00
Michael Droettboom
ed136b9673
gh-93910: Fix enum performance regression (GH-94614)
This removes the performance regression in 3.11, **at the expense of not fixing
the "bug" that allows accessing values from values** (e.g. `Color.RED.BLUE`).

Using the benchmark @markshannon [presented](https://github.com/python/cpython/issues/93910#issuecomment-1165503032), the results are:

| Version | Enum | Fast enum | Normal class |
| --- | --- | --- | --- |
| 3.10 | 2.04 | 0.59 | 0.56 |
| 3.11 | 2.78 | 0.31 | 0.15 |
| This PR | 1.30 | 0.32 | 0.16 |

I share this mostly as information about the source of the regression, as this may be useful. It may be that the lower-risk approach for the beta is just to revert to a previously-known working state.
2022-07-07 04:26:56 -07:00
Serhiy Storchaka
536985814a
gh-93820: Pickle enum.Flag by name (GH-93891) 2022-06-26 10:54:00 +03:00
Sam Ezeh
28a2ccfff2
[Enum] Remove automatic docstring generation (GH-94188) 2022-06-23 13:35:37 -07:00
Ethan Furman
b4e0d6124a
[Enum] fix typo (GH-94158) 2022-06-23 07:48:25 -07:00
Oscar R
fb1e9506c1
gh-91456: [Enum] Deprecate default auto() behavior with mixed value types (GH-91457)
When used with plain Enum, auto() returns the last numeric value assigned, skipping any incompatible member values (such as strings); starting in 3.13 the default auto() for plain Enums will require all the values to be of compatible types, and will return a new value that is 1 higher than any existing value.

Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
2022-06-22 23:20:24 -07:00
Carl Bordum Hansen
9a479c3c10
gh-88123: Implement new Enum __contains__ (GH-93298)
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
2022-06-22 00:04:04 -07:00
Serhiy Storchaka
138db8e48b
gh-93847: Fix repr of enum of generic aliases (GH-93885) 2022-06-16 12:16:12 -07:00
Christian Heimes
05b32c1c79
gh-93820: Fix copy() regression in enum.Flag (GH-93876)
GH-26658 introduced a regression in copy / pickle protocol for combined
`enum.Flag`s. `copy.copy(re.A | re.I)` would fail with
`AttributeError: ASCII|IGNORECASE`.

`enum.Flag` now has a `__reduce_ex__()` method that reduces flags by
combined value, not by combined name.
2022-06-15 23:42:36 -07:00
Ethan Furman
70cfe56caf
gh-93250: [Enum] Change IntEnum boundary to KEEP for backwards compatibility (GH-93302)
In previous versions of Python if an IntEnum member was combined with another integer type value using a bit-wise operation, the resulting value would still be the IntEnum type.  This change restores that behavior.
2022-05-27 15:14:28 -07:00
Tobin Yehle
08cfc3dabf
gh-93035: [Enum] Fix IntFlag crash when no single-bit members (GH-93076)
`EnumType` attempts to create a custom docstring for each enum/flag, but that was failing with pathological flags that had no members (only multi-bit aliases).
2022-05-24 18:16:20 -07:00
Ethan Furman
a49721ea07
gh-93118: [Enum] fix error message (GH-93138)
Include member names in error message.
2022-05-23 11:21:58 -07:00
Ethan Furman
046df59658
gh93107: [Enum] fix missing variable in global_str (GH-93107) 2022-05-23 08:56:07 -07:00
Ethan Furman
5be069568d
[Enum] Remove redundant check for existing members. (GH-92590) 2022-05-09 19:40:42 -07:00
Ethan Furman
93364f9716
gh-78157: [Enum] nested classes will not be members in 3.13 (GH-92366)
- add member() and nonmember() functions
- add deprecation warning for internal classes in enums not
  becoming members in 3.13

Co-authored-by: edwardcwang
2022-05-06 00:16:22 -07:00
Ethan Furman
353e3b2820
bpo-46477: [Enum] ensure Flag subclasses have correct bitwise methods (GH-30816) 2022-01-22 18:27:52 -08:00
Ethan Furman
7c0914d35e
bpo-45535: [Enum] include special dunders in dir() (GH-30677)
Include the `__dunders__` in `dir()` that make `Enum` special:

- `__contains__`
- `__getitem__`
- `__iter__`
- `__len__`
- `__members__`
2022-01-18 15:13:13 -08:00
Kumar Aditya
83d544b929
bpo-40066: [Enum] skip failing doc test (GH-30637) 2022-01-17 07:18:13 -08:00
Victor Stinner
42a64c03ec
Revert "bpo-40066: [Enum] update str() and format() output (GH-30582)" (GH-30632)
This reverts commit acf7403f9baea3ae1119fc6b4a3298522188bf96.
2022-01-17 13:58:40 +01:00
Ethan Furman
acf7403f9b
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`
2022-01-15 22:41:43 -08:00
Nikita Sobolev
e674e48ddc
bpo-46242: [Enum] better error message for extending Enum with members (GH-30357) 2022-01-14 14:18:00 -08:00
Nikita Sobolev
817a6bc9f7
bpo-46269: [Enum] remove special-casing of __new__ in EnumType.__dir__ (GH-30421) 2022-01-05 09:06:02 -08:00
Alex Waygood
b2afdc95cc
bpo-45535: Improve output of Enum `dir()` (GH-29316)
Modify the ``EnumType.__dir__()`` and ``Enum.__dir__()`` to ensure
that user-defined methods and methods inherited from mixin classes always
show up in the output of `help()`. This change also makes it easier for
IDEs to provide auto-completion.
2021-12-02 08:49:52 -08:00
Carl Friedrich Bolz-Tereick
b2af211e22
bpo-45417: [Enum] fix quadratic behavior during creation (GH-28907)
Creating an Enum exhibited quadratic behavior based on the number of members in three places:
- `EnumDict._member_names`: a list searched with each new member's name
- member creation: a `for` loop checking each existing member to see if new member was a duplicate
- `auto()` values: a list of all previous values in enum was copied before being sent to `_generate_next_value()`

Two of those issues have been resolved:
- `_EnumDict._member_names` is now a dictionary so lookups are fast
- member creation tries a fast value lookup before falling back to the slower `for` loop lookup

The third issue still remains, as `_generate_next_value_()` can be user-overridden and could corrupt the last values list if it were not copied.
2021-10-14 13:59:51 -07:00
Pablo Galindo Salgado
24da544014
bpo-44929: [Enum] Fix global repr (GH-27789)
* Fix typo in __repr__ code

* Add more tests for global int flag reprs

* use last module if multi-module string
  - when an enum's `__module__` contains several module names, only
     use the last one

Co-authored-by: Łukasz Langa <lukasz@langa.pl>
Co-authored-by: Ethan Furman <ethan@stoneleaf.us>
2021-08-25 07:24:32 -07:00
Ethan Furman
f60b07ab6c
bpo-43945: [Enum] reduce scope of new format() behavior (GH-26752)
* [Enum] reduce scope of new format behavior

Instead of treating all Enums the same for format(), only user mixed-in
enums will be affected.  In other words, IntEnum and IntFlag will not be
changing the format() behavior, due to the requirement that they be
drop-in replacements of existing integer constants.

If a user creates their own integer-based enum, then the new behavior
will apply:

    class Grades(int, Enum):
        A = 5
        B = 4
        C = 3
        D = 2
        F = 0

Now:  format(Grades.B)  -> DeprecationWarning and '4'
3.12:                   -> no warning, and 'B'
2021-06-18 13:15:46 -07:00
Ethan Furman
741b8ae1cf
bpo-44342: [Enum] sync current docs to 3.10 (GH-26750) 2021-06-15 18:51:19 -07:00
andrei kulakov
689a84475e
Fix a typo in _make_class_unpicklable() docstring (GH-26729) 2021-06-14 19:42:46 -07:00
Ethan Furman
c956734d7a
bpo-44242: [Enum] improve error messages (GH-26669) 2021-06-11 02:44:43 -07:00
Ethan Furman
3a7cccfd6c
bpo-44342: [Enum] fix data type search (GH-26667)
In an inheritance chain of

  int -> my_int -> final_int

the data type is now final_int (not my_int)
2021-06-11 01:25:14 -07:00
Ethan Furman
62f1d2b3d7
bpo-44342: [Enum] changed pickling from by-value to by-name (GH-26658)
by-value lookups could fail on complex enums, necessitating a check for
__reduce__ and possibly sabotaging the final enum;

by-name lookups should never fail, and sabotaging is no longer necessary
for class-based enum creation.
2021-06-10 15:52:09 -07:00
Ethan Furman
8a4f0850d7
bpo-44356: [Enum] allow multiple data-type mixins if they are all the same (GH-26649)
This enables, for example, two base Enums to both inherit from `str`, and then both be mixed into the same final Enum:

    class Str1Enum(str, Enum):
        # some behavior here

    class Str2Enum(str, Enum):
        # some more behavior here

    class FinalStrEnum(Str1Enum, Str2Enum):
        # this now works
2021-06-10 13:30:41 -07:00
Ethan Furman
eea8148b7d
bpo-44242: [Enum] remove missing bits test from Flag creation (GH-26586)
Move the check for missing named flags in flag aliases from Flag creation
to a new *verify* decorator.
2021-06-09 09:03:55 -07:00
Pablo Galindo
9a42d5069a
bpo-43957: Add a missins space to the new format enum warning (#25770) 2021-05-01 20:26:09 +01:00
Ethan Furman
6bd9288b80
bpo-43957: [Enum] Deprecate `TypeError` from containment checks. (GH-25670)
In 3.12 ``True`` or ``False`` will be returned for all containment checks,
with ``True`` being returned if the value is either a member of that enum
or one of its members' value.
2021-04-27 13:05:08 -07:00
Ethan Furman
5987b8c463
bpo-43945: [Enum] Deprecate non-standard mixin format() behavior (GH-25649)
In 3.12 the enum member, not the member's value, will be used for
format() calls.  Format specifiers can be used to retain the current
display of enum members:

Example enumeration:

    class Color(IntEnum):
        RED = 1
        GREEN = 2
        BLUE = 3

Current behavior:

    f'{Color.RED}'  -->  '1'

Future behavior:

    f'{Color.RED}'  --> 'RED'

Using d specifier:

    f'{Color.RED:d}'  --> '1'

Using specifiers can be done now and is future-compatible.
2021-04-26 22:42:57 -07:00
Ethan Furman
6c681e1a4a
bpo-38659: [Enum] do not check '_inverted_' during simple test (GH-25566)
Depending on usage, it's possible for Flag members to have the _inverted_ attribute when they are testing, while the Flag being testing against will not have that attribute on its members -- so skip that comparison.
2021-04-23 19:08:22 -07:00
Ethan Furman
a02cb474f9
bpo-38659: [Enum] add _simple_enum decorator (GH-25497)
add:

* `_simple_enum` decorator to transform a normal class into an enum
* `_test_simple_enum` function to compare
* `_old_convert_` to enable checking `_convert_` generated enums

`_simple_enum` takes a normal class and converts it into an enum:

    @simple_enum(Enum)
    class Color:
        RED = 1
        GREEN = 2
        BLUE = 3

`_old_convert_` works much like` _convert_` does, using the original logic:

    # in a test file
    import socket, enum
    CheckedAddressFamily = enum._old_convert_(
            enum.IntEnum, 'AddressFamily', 'socket',
            lambda C: C.isupper() and C.startswith('AF_'),
            source=_socket,
            )

`_test_simple_enum` takes a traditional enum and a simple enum and
compares the two:

    # in the REPL or the same module as Color
    class CheckedColor(Enum):
        RED = 1
        GREEN = 2
        BLUE = 3

    _test_simple_enum(CheckedColor, Color)

    _test_simple_enum(CheckedAddressFamily, socket.AddressFamily)

Any important differences will raise a TypeError
2021-04-21 10:20:44 -07:00
Ethan Furman
503cdc7c12
Revert "bpo-38659: [Enum] add _simple_enum decorator (GH-25285)" (GH-25476)
This reverts commit dbac8f40e81eb0a29dc833e6409a1abf47467da6.
2021-04-19 19:12:24 -07:00
Ethan Furman
dbac8f40e8
bpo-38659: [Enum] add _simple_enum decorator (GH-25285)
add:

_simple_enum decorator to transform a normal class into an enum
_test_simple_enum function to compare
_old_convert_ to enable checking _convert_ generated enums
_simple_enum takes a normal class and converts it into an enum:

@simple_enum(Enum)
class Color:
    RED = 1
    GREEN = 2
    BLUE = 3

_old_convert_ works much like _convert_ does, using the original logic:

# in a test file
import socket, enum
CheckedAddressFamily = enum._old_convert_(
        enum.IntEnum, 'AddressFamily', 'socket',
        lambda C: C.isupper() and C.startswith('AF_'),
        source=_socket,
        )

test_simple_enum takes a traditional enum and a simple enum and
compares the two:

# in the REPL or the same module as Color
class CheckedColor(Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

_test_simple_enum(CheckedColor, Color)

_test_simple_enum(CheckedAddressFamily, socket.AddressFamily)

Any important differences will raise a TypeError
2021-04-19 18:04:53 -07:00
Ethan Furman
ec09973f5b
bpo-43744: [Enum] fix `_is_private` (GH-25349)
``_is_private`` now returns ``False`` instead of raising an exception when enum name matches beginning of class name
as used in a private variable
2021-04-15 06:58:33 -07:00
Ethan Furman
0dca5eb54b
[Enum] fix doc string (GH-25376) 2021-04-15 06:49:54 -07:00
Ethan Furman
8c14f5a787
bpo-42248: [Enum] ensure exceptions raised in `_missing_` are released (GH-25350) 2021-04-12 08:51:20 -07:00
Ethan Furman
b775106d94
bpo-40066: Enum: modify repr() and str() (GH-22392)
* Enum: streamline repr() and str(); improve docs

- repr() is now ``enum_class.member_name``
- stdlib global enums are ``module_name.member_name``
- str() is now ``member_name``
- add HOW-TO section for ``Enum``
- change main documentation to be an API reference
2021-03-30 21:17:26 -07:00
Ethan Furman
44e580f448
bpo-43162: [Enum] update docs, renable doc tests (GH-24487)
* update docs, renable doc tests
* make deprecation warning active for two releases
2021-03-03 09:54:30 -08:00
Ethan Furman
d65b9033d6
bpo-43162: [Enum] deprecate enum member.member access (GH-24486)
In 3.5 (?) a speed optimization made it possible to access members as
attributes of other members, i.e. ``Color.RED.BLUE``.  This was always
discouraged in the docs, and other recent optimizations has made that
one no longer necessary.  Because some may be relying on it anyway, it
is being deprecated in 3.10, and will be removed in 3.11.
2021-02-08 17:32:38 -08:00
Ethan Furman
7aaeb2a3d6
bpo-38250: [Enum] single-bit flags are canonical (GH-24215)
Flag members are now divided by one-bit verses multi-bit, with multi-bit being treated as aliases. Iterating over a flag only returns the contained single-bit flags.

Iterating, repr(), and str() show members in definition order.

When constructing combined-member flags, any extra integer values are either discarded (CONFORM), turned into ints (EJECT) or treated as errors (STRICT). Flag classes can specify which of those three behaviors is desired:

>>> class Test(Flag, boundary=CONFORM):
...     ONE = 1
...     TWO = 2
...
>>> Test(5)
<Test.ONE: 1>

Besides the three above behaviors, there is also KEEP, which should not be used unless necessary -- for example, _convert_ specifies KEEP as there are flag sets in the stdlib that are incomplete and/or inconsistent (e.g. ssl.Options). KEEP will, as the name suggests, keep all bits; however, iterating over a flag with extra bits will only return the canonical flags contained, not the extra bits.

Iteration is now in member definition order.  If member definition order
matches increasing value order, then a more efficient method of flag
decomposition is used; otherwise, sort() is called on the results of
that method to get definition order.


``re`` module:

repr() has been modified to support as closely as possible its previous
output; the big difference is that inverted flags cannot be output as
before because the inversion operation now always returns the comparable
positive result; i.e.

   re.A|re.I|re.M|re.S is ~(re.L|re.U|re.S|re.T|re.DEBUG)

in both of the above terms, the ``value`` is 282.

re's tests have been updated to reflect the modifications to repr().
2021-01-25 14:26:19 -08:00