mirror of
https://github.com/python/cpython.git
synced 2025-09-26 10:19:53 +00:00
issue23591: add docs; code cleanup; more tests
This commit is contained in:
parent
c19f00b238
commit
65a5a47d79
3 changed files with 213 additions and 78 deletions
|
@ -23,9 +23,9 @@ by identity, and the enumeration itself can be iterated over.
|
||||||
Module Contents
|
Module Contents
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
This module defines two enumeration classes that can be used to define unique
|
This module defines four enumeration classes that can be used to define unique
|
||||||
sets of names and values: :class:`Enum` and :class:`IntEnum`. It also defines
|
sets of names and values: :class:`Enum`, :class:`IntEnum`, and
|
||||||
one decorator, :func:`unique`.
|
:class:`IntFlags`. It also defines one decorator, :func:`unique`.
|
||||||
|
|
||||||
.. class:: Enum
|
.. class:: Enum
|
||||||
|
|
||||||
|
@ -37,10 +37,23 @@ one decorator, :func:`unique`.
|
||||||
Base class for creating enumerated constants that are also
|
Base class for creating enumerated constants that are also
|
||||||
subclasses of :class:`int`.
|
subclasses of :class:`int`.
|
||||||
|
|
||||||
|
.. class:: IntFlag
|
||||||
|
|
||||||
|
Base class for creating enumerated constants that can be combined using
|
||||||
|
the bitwise operators without losing their :class:`IntFlag` membership.
|
||||||
|
:class:`IntFlag` members are also subclasses of :class:`int`.
|
||||||
|
|
||||||
|
.. class:: Flag
|
||||||
|
|
||||||
|
Base class for creating enumerated constants that can be combined using
|
||||||
|
the bitwise operations without losing their :class:`Flag` membership.
|
||||||
|
|
||||||
.. function:: unique
|
.. function:: unique
|
||||||
|
|
||||||
Enum class decorator that ensures only one name is bound to any one value.
|
Enum class decorator that ensures only one name is bound to any one value.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6 ``Flag``, ``IntFlag``
|
||||||
|
|
||||||
|
|
||||||
Creating an Enum
|
Creating an Enum
|
||||||
----------------
|
----------------
|
||||||
|
@ -478,7 +491,7 @@ Derived Enumerations
|
||||||
IntEnum
|
IntEnum
|
||||||
^^^^^^^
|
^^^^^^^
|
||||||
|
|
||||||
A variation of :class:`Enum` is provided which is also a subclass of
|
The first variation of :class:`Enum` that is provided is also a subclass of
|
||||||
:class:`int`. Members of an :class:`IntEnum` can be compared to integers;
|
:class:`int`. Members of an :class:`IntEnum` can be compared to integers;
|
||||||
by extension, integer enumerations of different types can also be compared
|
by extension, integer enumerations of different types can also be compared
|
||||||
to each other::
|
to each other::
|
||||||
|
@ -521,13 +534,54 @@ However, they still can't be compared to standard :class:`Enum` enumerations::
|
||||||
>>> [i for i in range(Shape.square)]
|
>>> [i for i in range(Shape.square)]
|
||||||
[0, 1]
|
[0, 1]
|
||||||
|
|
||||||
For the vast majority of code, :class:`Enum` is strongly recommended,
|
|
||||||
since :class:`IntEnum` breaks some semantic promises of an enumeration (by
|
IntFlag
|
||||||
being comparable to integers, and thus by transitivity to other
|
^^^^^^^
|
||||||
unrelated enumerations). It should be used only in special cases where
|
|
||||||
there's no other choice; for example, when integer constants are
|
The next variation of :class:`Enum` provided, :class:`IntFlag`, is also based
|
||||||
replaced with enumerations and backwards compatibility is required with code
|
on :class:`int`. The difference being :class:`IntFlag` members can be combined
|
||||||
that still expects integers.
|
using the bitwise operators (&, \|, ^, ~) and the result is still an
|
||||||
|
:class:`IntFlag` member. However, as the name implies, :class:`IntFlag`
|
||||||
|
members also subclass :class:`int` and can be used wherever an :class:`int` is.
|
||||||
|
Any operation on an :class:`IntFlag` member besides the bit-wise operations
|
||||||
|
will lose the :class:`IntFlag` membership.
|
||||||
|
|
||||||
|
>>> from enum import IntFlag
|
||||||
|
>>> class Perm(IntFlag):
|
||||||
|
... R = 4
|
||||||
|
... W = 2
|
||||||
|
... X = 1
|
||||||
|
...
|
||||||
|
>>> Perm.R | Perm.W
|
||||||
|
<Perm.R|W: 6>
|
||||||
|
>>> Perm.R + Perm.W
|
||||||
|
6
|
||||||
|
>>> RW = Perm.R | Perm.W
|
||||||
|
>>> Perm.R in RW
|
||||||
|
True
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
|
||||||
|
Flag
|
||||||
|
^^^^
|
||||||
|
|
||||||
|
The last variation is :class:`Flag`. Like :class:`IntFlag`, :class:`Flag`
|
||||||
|
members can be combined using the bitwise operators (^, \|, ^, ~). Unlike
|
||||||
|
:class:`IntFlag`, they cannot be combined with, nor compared against, any
|
||||||
|
other :class:`Flag` enumeration nor :class:`int`.
|
||||||
|
|
||||||
|
.. versionadded:: 3.6
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
For the majority of new code, :class:`Enum` and :class:`Flag` are strongly
|
||||||
|
recommended, since :class:`IntEnum` and :class:`IntFlag` break some
|
||||||
|
semantic promises of an enumeration (by being comparable to integers, and
|
||||||
|
thus by transitivity to other unrelated enumerations). :class:`IntEnum`
|
||||||
|
and :class:`IntFlag` should be used only in cases where :class:`Enum` and
|
||||||
|
:class:`Flag` will not do; for example, when integer constants are replaced
|
||||||
|
with enumerations, or for interoperability with other systems.
|
||||||
|
|
||||||
|
|
||||||
Others
|
Others
|
||||||
|
@ -567,10 +621,10 @@ Some rules:
|
||||||
Interesting examples
|
Interesting examples
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
While :class:`Enum` and :class:`IntEnum` are expected to cover the majority of
|
While :class:`Enum`, :class:`IntEnum`, :class:`IntFlag`, and :class:`Flag` are
|
||||||
use-cases, they cannot cover them all. Here are recipes for some different
|
expected to cover the majority of use-cases, they cannot cover them all. Here
|
||||||
types of enumerations that can be used directly, or as examples for creating
|
are recipes for some different types of enumerations that can be used directly,
|
||||||
one's own.
|
or as examples for creating one's own.
|
||||||
|
|
||||||
|
|
||||||
AutoNumber
|
AutoNumber
|
||||||
|
@ -731,55 +785,33 @@ member instances.
|
||||||
Finer Points
|
Finer Points
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
:class:`Enum` members are instances of an :class:`Enum` class, and even
|
Supported ``__dunder__`` names
|
||||||
though they are accessible as `EnumClass.member`, they should not be accessed
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
directly from the member as that lookup may fail or, worse, return something
|
|
||||||
besides the :class:`Enum` member you looking for::
|
|
||||||
|
|
||||||
>>> class FieldTypes(Enum):
|
:attr:`__members__` is an :class:`OrderedDict` of ``member_name``:``member``
|
||||||
... name = 0
|
items. It is only available on the class.
|
||||||
... value = 1
|
|
||||||
... size = 2
|
|
||||||
...
|
|
||||||
>>> FieldTypes.value.size
|
|
||||||
<FieldTypes.size: 2>
|
|
||||||
>>> FieldTypes.size.value
|
|
||||||
2
|
|
||||||
|
|
||||||
.. versionchanged:: 3.5
|
: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.
|
||||||
|
|
||||||
Boolean evaluation: Enum classes that are mixed with non-Enum types (such as
|
|
||||||
:class:`int`, :class:`str`, etc.) are evaluated according to the mixed-in
|
|
||||||
type's rules; otherwise, all members evaluate as ``True``. To make your own
|
|
||||||
Enum's boolean evaluation depend on the member's value add the following to
|
|
||||||
your class::
|
|
||||||
|
|
||||||
def __bool__(self):
|
Supported ``_sunder_`` names
|
||||||
return bool(self.value)
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The :attr:`__members__` attribute is only available on the class.
|
- ``_name_`` -- name of the member
|
||||||
|
- ``_value_`` -- value of the member; can be set / modified in ``__new__``
|
||||||
|
|
||||||
If you give your :class:`Enum` subclass extra methods, like the `Planet`_
|
- ``_missing_`` -- a lookup function used when a value is not found; may be
|
||||||
class above, those methods will show up in a :func:`dir` of the member,
|
overridden
|
||||||
but not of the class::
|
- ``_order_`` -- used in Python 2/3 code to ensure member order is consistent
|
||||||
|
(class attribute, removed during class creation)
|
||||||
|
|
||||||
>>> dir(Planet)
|
.. versionadded:: 3.6 ``_missing_``, ``_order_``
|
||||||
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
|
|
||||||
>>> dir(Planet.EARTH)
|
|
||||||
['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
|
|
||||||
|
|
||||||
The :meth:`__new__` method will only be used for the creation of the
|
To help keep Python 2 / Python 3 code in sync an :attr:`_order_` attribute can
|
||||||
:class:`Enum` members -- after that it is replaced. Any custom :meth:`__new__`
|
be provided. It will be checked against the actual order of the enumeration
|
||||||
method must create the object and set the :attr:`_value_` attribute
|
and raise an error if the two do not match::
|
||||||
appropriately.
|
|
||||||
|
|
||||||
If you wish to change how :class:`Enum` members are looked up you should either
|
|
||||||
write a helper function or a :func:`classmethod` for the :class:`Enum`
|
|
||||||
subclass.
|
|
||||||
|
|
||||||
To help keep Python 2 / Python 3 code in sync a user-specified :attr:`_order_`,
|
|
||||||
if provided, will be checked to ensure the actual order of the enumeration
|
|
||||||
matches::
|
|
||||||
|
|
||||||
>>> class Color(Enum):
|
>>> class Color(Enum):
|
||||||
... _order_ = 'red green blue'
|
... _order_ = 'red green blue'
|
||||||
|
@ -794,4 +826,53 @@ matches::
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
In Python 2 code the :attr:`_order_` attribute is necessary as definition
|
In Python 2 code the :attr:`_order_` attribute is necessary as definition
|
||||||
order is lost during class creation.
|
order is lost before it can be recorded.
|
||||||
|
|
||||||
|
``Enum`` member type
|
||||||
|
~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
:class:`Enum` members are instances of an :class:`Enum` class, and even
|
||||||
|
though they are accessible as `EnumClass.member`, they should not be accessed
|
||||||
|
directly from the member as that lookup may fail or, worse, return something
|
||||||
|
besides the ``Enum`` member you looking for::
|
||||||
|
|
||||||
|
>>> class FieldTypes(Enum):
|
||||||
|
... name = 0
|
||||||
|
... value = 1
|
||||||
|
... size = 2
|
||||||
|
...
|
||||||
|
>>> FieldTypes.value.size
|
||||||
|
<FieldTypes.size: 2>
|
||||||
|
>>> FieldTypes.size.value
|
||||||
|
2
|
||||||
|
|
||||||
|
.. versionchanged:: 3.5
|
||||||
|
|
||||||
|
|
||||||
|
Boolean value of ``Enum`` classes and members
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
``Enum`` members that are mixed with non-Enum types (such as
|
||||||
|
:class:`int`, :class:`str`, etc.) are evaluated according to the mixed-in
|
||||||
|
type's rules; otherwise, all members evaluate as :data:`True`. To make your own
|
||||||
|
Enum's boolean evaluation depend on the member's value add the following to
|
||||||
|
your class::
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self.value)
|
||||||
|
|
||||||
|
``Enum`` classes always evaluate as :data:`True`.
|
||||||
|
|
||||||
|
|
||||||
|
``Enum`` classes with methods
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
If you give your :class:`Enum` subclass extra methods, like the `Planet`_
|
||||||
|
class above, those methods will show up in a :func:`dir` of the member,
|
||||||
|
but not of the class::
|
||||||
|
|
||||||
|
>>> dir(Planet)
|
||||||
|
['EARTH', 'JUPITER', 'MARS', 'MERCURY', 'NEPTUNE', 'SATURN', 'URANUS', 'VENUS', '__class__', '__doc__', '__members__', '__module__']
|
||||||
|
>>> dir(Planet.EARTH)
|
||||||
|
['__class__', '__doc__', '__module__', 'name', 'surface_gravity', 'value']
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ except ImportError:
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['EnumMeta', 'Enum', 'IntEnum', 'Flags', 'IntFlags', 'unique']
|
__all__ = ['EnumMeta', 'Enum', 'IntEnum', 'Flag', 'IntFlag', 'unique']
|
||||||
|
|
||||||
|
|
||||||
def _is_descriptor(obj):
|
def _is_descriptor(obj):
|
||||||
|
@ -104,7 +104,7 @@ class EnumMeta(type):
|
||||||
enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
|
enum_dict['_generate_next_value_'] = getattr(first_enum, '_generate_next_value_', None)
|
||||||
return enum_dict
|
return enum_dict
|
||||||
|
|
||||||
def __new__(metacls, cls, bases, classdict, **kwds):
|
def __new__(metacls, cls, bases, classdict):
|
||||||
# an Enum class is final once enumeration items have been defined; it
|
# an Enum class is final once enumeration items have been defined; it
|
||||||
# cannot be mixed with other types (int, float, etc.) if it has an
|
# cannot be mixed with other types (int, float, etc.) if it has an
|
||||||
# inherited __new__ unless a new __new__ is defined (or the resulting
|
# inherited __new__ unless a new __new__ is defined (or the resulting
|
||||||
|
@ -614,7 +614,7 @@ class IntEnum(int, Enum):
|
||||||
def _reduce_ex_by_name(self, proto):
|
def _reduce_ex_by_name(self, proto):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
class Flags(Enum):
|
class Flag(Enum):
|
||||||
"""Support for flags"""
|
"""Support for flags"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _generate_next_value_(name, start, count, last_value):
|
def _generate_next_value_(name, start, count, last_value):
|
||||||
|
@ -736,7 +736,7 @@ class Flags(Enum):
|
||||||
return self.__class__(inverted)
|
return self.__class__(inverted)
|
||||||
|
|
||||||
|
|
||||||
class IntFlags(int, Flags):
|
class IntFlag(int, Flag):
|
||||||
"""Support for integer-based Flags"""
|
"""Support for integer-based Flags"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|
|
@ -3,7 +3,7 @@ import inspect
|
||||||
import pydoc
|
import pydoc
|
||||||
import unittest
|
import unittest
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from enum import Enum, IntEnum, EnumMeta, Flags, IntFlags, unique
|
from enum import Enum, IntEnum, EnumMeta, Flag, IntFlag, unique
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
|
from pickle import dumps, loads, PicklingError, HIGHEST_PROTOCOL
|
||||||
from test import support
|
from test import support
|
||||||
|
@ -33,6 +33,14 @@ try:
|
||||||
except Exception as exc:
|
except Exception as exc:
|
||||||
FloatStooges = exc
|
FloatStooges = exc
|
||||||
|
|
||||||
|
try:
|
||||||
|
class FlagStooges(Flag):
|
||||||
|
LARRY = 1
|
||||||
|
CURLY = 2
|
||||||
|
MOE = 3
|
||||||
|
except Exception as exc:
|
||||||
|
FlagStooges = exc
|
||||||
|
|
||||||
# for pickle test and subclass tests
|
# for pickle test and subclass tests
|
||||||
try:
|
try:
|
||||||
class StrEnum(str, Enum):
|
class StrEnum(str, Enum):
|
||||||
|
@ -1633,13 +1641,13 @@ class TestOrder(unittest.TestCase):
|
||||||
verde = green
|
verde = green
|
||||||
|
|
||||||
|
|
||||||
class TestFlags(unittest.TestCase):
|
class TestFlag(unittest.TestCase):
|
||||||
"""Tests of the Flags."""
|
"""Tests of the Flags."""
|
||||||
|
|
||||||
class Perm(Flags):
|
class Perm(Flag):
|
||||||
R, W, X = 4, 2, 1
|
R, W, X = 4, 2, 1
|
||||||
|
|
||||||
class Open(Flags):
|
class Open(Flag):
|
||||||
RO = 0
|
RO = 0
|
||||||
WO = 1
|
WO = 1
|
||||||
RW = 2
|
RW = 2
|
||||||
|
@ -1760,7 +1768,7 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
|
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
|
||||||
|
|
||||||
def test_programatic_function_string(self):
|
def test_programatic_function_string(self):
|
||||||
Perm = Flags('Perm', 'R W X')
|
Perm = Flag('Perm', 'R W X')
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -1775,7 +1783,7 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_string_with_start(self):
|
def test_programatic_function_string_with_start(self):
|
||||||
Perm = Flags('Perm', 'R W X', start=8)
|
Perm = Flag('Perm', 'R W X', start=8)
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -1790,7 +1798,7 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_string_list(self):
|
def test_programatic_function_string_list(self):
|
||||||
Perm = Flags('Perm', ['R', 'W', 'X'])
|
Perm = Flag('Perm', ['R', 'W', 'X'])
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -1805,7 +1813,7 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_iterable(self):
|
def test_programatic_function_iterable(self):
|
||||||
Perm = Flags('Perm', (('R', 2), ('W', 8), ('X', 32)))
|
Perm = Flag('Perm', (('R', 2), ('W', 8), ('X', 32)))
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -1820,7 +1828,7 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_from_dict(self):
|
def test_programatic_function_from_dict(self):
|
||||||
Perm = Flags('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
|
Perm = Flag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -1834,16 +1842,42 @@ class TestFlags(unittest.TestCase):
|
||||||
self.assertIn(e, Perm)
|
self.assertIn(e, Perm)
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
|
def test_pickle(self):
|
||||||
|
if isinstance(FlagStooges, Exception):
|
||||||
|
raise FlagStooges
|
||||||
|
test_pickle_dump_load(self.assertIs, FlagStooges.CURLY|FlagStooges.MOE)
|
||||||
|
test_pickle_dump_load(self.assertIs, FlagStooges)
|
||||||
|
|
||||||
class TestIntFlags(unittest.TestCase):
|
|
||||||
|
def test_containment(self):
|
||||||
|
Perm = self.Perm
|
||||||
|
R, W, X = Perm
|
||||||
|
RW = R | W
|
||||||
|
RX = R | X
|
||||||
|
WX = W | X
|
||||||
|
RWX = R | W | X
|
||||||
|
self.assertTrue(R in RW)
|
||||||
|
self.assertTrue(R in RX)
|
||||||
|
self.assertTrue(R in RWX)
|
||||||
|
self.assertTrue(W in RW)
|
||||||
|
self.assertTrue(W in WX)
|
||||||
|
self.assertTrue(W in RWX)
|
||||||
|
self.assertTrue(X in RX)
|
||||||
|
self.assertTrue(X in WX)
|
||||||
|
self.assertTrue(X in RWX)
|
||||||
|
self.assertFalse(R in WX)
|
||||||
|
self.assertFalse(W in RX)
|
||||||
|
self.assertFalse(X in RW)
|
||||||
|
|
||||||
|
class TestIntFlag(unittest.TestCase):
|
||||||
"""Tests of the IntFlags."""
|
"""Tests of the IntFlags."""
|
||||||
|
|
||||||
class Perm(IntFlags):
|
class Perm(IntFlag):
|
||||||
X = 1 << 0
|
X = 1 << 0
|
||||||
W = 1 << 1
|
W = 1 << 1
|
||||||
R = 1 << 2
|
R = 1 << 2
|
||||||
|
|
||||||
class Open(IntFlags):
|
class Open(IntFlag):
|
||||||
RO = 0
|
RO = 0
|
||||||
WO = 1
|
WO = 1
|
||||||
RW = 2
|
RW = 2
|
||||||
|
@ -2003,7 +2037,7 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
|
self.assertIs((Open.WO|Open.CE) & ~Open.WO, Open.CE)
|
||||||
|
|
||||||
def test_programatic_function_string(self):
|
def test_programatic_function_string(self):
|
||||||
Perm = IntFlags('Perm', 'R W X')
|
Perm = IntFlag('Perm', 'R W X')
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -2019,7 +2053,7 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_string_with_start(self):
|
def test_programatic_function_string_with_start(self):
|
||||||
Perm = IntFlags('Perm', 'R W X', start=8)
|
Perm = IntFlag('Perm', 'R W X', start=8)
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -2035,7 +2069,7 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_string_list(self):
|
def test_programatic_function_string_list(self):
|
||||||
Perm = IntFlags('Perm', ['R', 'W', 'X'])
|
Perm = IntFlag('Perm', ['R', 'W', 'X'])
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -2051,7 +2085,7 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_iterable(self):
|
def test_programatic_function_iterable(self):
|
||||||
Perm = IntFlags('Perm', (('R', 2), ('W', 8), ('X', 32)))
|
Perm = IntFlag('Perm', (('R', 2), ('W', 8), ('X', 32)))
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -2067,7 +2101,7 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
def test_programatic_function_from_dict(self):
|
def test_programatic_function_from_dict(self):
|
||||||
Perm = IntFlags('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
|
Perm = IntFlag('Perm', OrderedDict((('R', 2), ('W', 8), ('X', 32))))
|
||||||
lst = list(Perm)
|
lst = list(Perm)
|
||||||
self.assertEqual(len(lst), len(Perm))
|
self.assertEqual(len(lst), len(Perm))
|
||||||
self.assertEqual(len(Perm), 3, Perm)
|
self.assertEqual(len(Perm), 3, Perm)
|
||||||
|
@ -2083,6 +2117,26 @@ class TestIntFlags(unittest.TestCase):
|
||||||
self.assertIs(type(e), Perm)
|
self.assertIs(type(e), Perm)
|
||||||
|
|
||||||
|
|
||||||
|
def test_containment(self):
|
||||||
|
Perm = self.Perm
|
||||||
|
R, W, X = Perm
|
||||||
|
RW = R | W
|
||||||
|
RX = R | X
|
||||||
|
WX = W | X
|
||||||
|
RWX = R | W | X
|
||||||
|
self.assertTrue(R in RW)
|
||||||
|
self.assertTrue(R in RX)
|
||||||
|
self.assertTrue(R in RWX)
|
||||||
|
self.assertTrue(W in RW)
|
||||||
|
self.assertTrue(W in WX)
|
||||||
|
self.assertTrue(W in RWX)
|
||||||
|
self.assertTrue(X in RX)
|
||||||
|
self.assertTrue(X in WX)
|
||||||
|
self.assertTrue(X in RWX)
|
||||||
|
self.assertFalse(R in WX)
|
||||||
|
self.assertFalse(W in RX)
|
||||||
|
self.assertFalse(X in RW)
|
||||||
|
|
||||||
class TestUnique(unittest.TestCase):
|
class TestUnique(unittest.TestCase):
|
||||||
|
|
||||||
def test_unique_clean(self):
|
def test_unique_clean(self):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue