mirror of
				https://github.com/python/cpython.git
				synced 2025-11-04 07:31:38 +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 @@
 | 
				
			||||||
    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 @@ def __prepare__(metacls, cls, bases):
 | 
				
			||||||
            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 @@ def __invert__(self):
 | 
				
			||||||
        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 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 @@ class FloatStooges(float, Enum):
 | 
				
			||||||
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 Color(Enum):
 | 
				
			||||||
                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 @@ def test_invert(self):
 | 
				
			||||||
        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 @@ def test_programatic_function_string(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_string_with_start(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_string_list(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_iterable(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_from_dict(self):
 | 
				
			||||||
            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 @@ def test_invert(self):
 | 
				
			||||||
        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 @@ def test_programatic_function_string(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_string_with_start(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_string_list(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_iterable(self):
 | 
				
			||||||
            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 @@ def test_programatic_function_from_dict(self):
 | 
				
			||||||
            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