enumerific


Nameenumerific JSON
Version 1.0.5 PyPI version JSON
download
home_pageNone
SummarySimplifies working with Python enums.
upload_time2025-08-02 05:48:15
maintainerNone
docs_urlNone
authorDaniel Sissman
requires_python>=3.10
licenseNone
keywords enum enumeration enumerations
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Enumerific Enums

The Enumerific library provides a greenfield implementation of enumerations with many unique features through the library's own `Enumeration` class, as well as separately offering several useful extra methods for the built-in standard library `enums.Enum` type.

The Enumerific library's `Enumeration` class offers the following features:

 * A greenfield implementation of enumerations compatible with Python 3.10 and later versions;
 * Enumerific enumerations can hold option values of the same or mixed types, including `int`, `float`, `complex`, `str`, `bytes`, `set`, `tuple`, `list`, `dict` as well as arbitrary `object` types;
 * Enumerific enumeration options can be accessed directly as native data types and enumeration options can be used anywhere that the corresponding native data types can be used;
 * Support for automatic typecasting of the `Enumeration` base class to support the use of enumeration option values interchangeably with native data type values;
 * Enumerific enumerations options can be added after an `Enumeration` class has been created either through extending an existing enumerations class by subclassing or by registering new options directly on an existing enumerations class via the `.register()` method; this is especially useful for cases where enumeration options may not all be known prior to runtime;
 * Enumerific enumerations options can be removed after an `Enumeration` class has been created via the `.unregister()` method; this specialised behaviour is prevented by default, but can be enabled for advanced use cases;
 * Enforcement of unique values for all options within an enumeration, unless overridden;
 * Support for aliasing enumeration options, and control over this behaviour;
 * Support for backfilling enumeration options on a superclass when subclassing, and control over this behaviour
 * Support for redefining enumeration options, and control over this behaviour;
 * Support for automatically generating unique number sequences for enumeration options, including powers of two for bitwise enumeration flags, as well as other sequences such as powers of other numbers and factoring;
 * Support for annotating enumeration options with additional arbitrary key-value pairs, which can be particularly useful for associating additional data with a given enumeration option, which may be accessed later anywhere in code that the enumeration option is available;
 * Simple one-line reconciliation of `Enumeration` class options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;
 * Simple one-line validation of `Enumeration` class options; validation by enumeration option name, value and enumeration class instance reference are all supported through the `.validate()` class method;
 * Simple access to all of the options provided by an `Enumeration` class instance through the `.options()` class method;
 * Access to all of the names of the `Enumeration` class options via the `.names()` method;
 * Access to all of the names/keys of the `Enumeration` class options via the `.keys()` method;
 * Access to all of the values of the `Enumeration` class options via the `.values()` method;
 * Access to all of the key-value pairs of the `Enumeration` class options via the `.items()` method;
 * Ability to determine if an enumeration option is an alias of another option, or is an option in its own right via the `Enumeration` class' `.aliased` property.
 * Ability to obtain the aliases for an enumeration option via the `.aliases` property.

Furthermore, as noted, the Enumerific library also offers extended functionality for the built-in standard library `enums.Enum` type:

 * Simple one-line reconciliation of `enums.Enum` options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;
 * Simple one-line validation of `enums.Enum` options; validation by enumeration option name, value and enumeration class instance reference are all supported through the `.validate()` class method;
 * Simple access to all of the options provided by an `enums.Enum` class instance through the `.options()` class method.

### Requirements

The Enumerific library has been tested with Python 3.10, 3.11, 3.12 and 3.13, and is not
compatible with Python 3.9 or earlier.

### Installation

Enumerific is available from the PyPI, so may be added to a project's dependencies via
its `requirements.txt` file or similar by referencing the library's name, `enumerific`,
or the library may be installed directly into your local runtime environment using `pip`
by entering the following command, and following any prompts:

	$ pip install enumerific

### Usage

To use the Enumerific library's implementation of enumerations import the `Enumeration` class from the Enumerific library:

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

assert issubclass(Colors, Enumeration)

# Note that as all of the Colors enumeration options have integer values, the class was
# typecast to int so that its option values can be used interchangeably with integers:
assert issubclass(Colors, int)

color = Colors.RED

# Enumeration class options are instances of the class
assert isinstance(color, Colors)

# They can also be instances of the raw value that was assigned to the option
assert isinstance(color, int)

# Each enumeration class option has a name (the name used to define the option)
assert color.name == "RED"

# Each enumeration class option has a value (the value used when defining the option)
assert color.value == 1

# The identity of an enumeration option matches the option
assert color is Colors.RED

# The equality of an enumeration option can also be compared against the enumeration
# option directly, against the name of the option, or against the value:
assert color == Colors.RED
assert color == "RED"
assert color == 1
assert color != 2
```

#### Example 1: Reconciling a Value

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

# Given a string value in this case
value = 1

# Reconcile it to the associated enumeration option
color = Colors.reconcile(value)

assert color == Colors.RED  # asserts successfully
assert color is Colors.RED  # asserts successfully as Enumeration class options are singletons
```

#### Example 2: Reconciling an Enumeration Option Name

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

# Given a string value in this case
value = "RED"

# Reconcile it to the associated enumeration option
color = Colors.reconcile(value)

assert color == Colors.RED  # asserts successfully
assert color is Colors.RED  # asserts successfully as Enumeration class options are singletons

# Given a string value in this case
value = "red"

# Reconcile it to the associated enumeration option;
# values can be reconciled caselessly too:
color = Colors.reconcile(value, caselessly=True)

assert color == Colors.RED  # asserts successfully
assert color is Colors.RED  # asserts successfully as Enumeration class options are singletons
```

#### Example 3: Validating a Value

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

# The value can be an enumeration option's name, its value, or the enumeration option
value = "RED"
value = 1
value = Colors.RED

if Colors.validate(value) is True:
    # do something if the value could be validated
    pass
else:
    # do something else if the value could not be validated
    pass
```

#### Example 4: Iterating Over Enumeration Options

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

options = Colors.options()

for name, option in options.items():
    # do something with each option
    print(option.name, option.value)
```

#### Example 5: Iterating Over Enumeration Names

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

for name in Colors.names():
    # do something with each option name
    print(name)
```

#### Example 6: Iterating Over Enumeration Keys

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

for key in Colors.keys():
    # do something with each option key
    print(key)
```

#### Example 7: Iterating Over Enumeration Values

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

for value in Colors.values():
    # do something with each option key
    print(value)
```

#### Example 8: Registering New Options

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

Colors.register("PURPLE", 4)
Colors.register("GOLD", 5)

assert "PURPLE" in Colors
assert Colors.PURPLE.name == "PURPLE"
assert Colors.PURPLE.value == 4
assert Colors.PURPLE == 4

assert "GOLD" in Colors
assert Colors.GOLD.name == "GOLD"
assert Colors.GOLD.value == 5
assert Colors.GOLD == 5
```

#### Example 9: Subclassing

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

# Ensure that Colors has the expected options
assert "RED" in Colors
assert "GREEN" in Colors
assert "BLUE" in Colors

# Create a subclass of Colors, inheriting its options
class MoreColors(Colors):
    PURPLE = 4
    GOLD = 5

# Ensure that MoreColors inherited the options from Colors, as well as adding its own
assert "RED" in MoreColors
assert "GREEN" in MoreColors
assert "BLUE" in MoreColors
assert "PURPLE" in MoreColors
assert "GOLD" in MoreColors

# As backfilling is off by default subclass options won't be available on the superclass
assert not "PURPLE" in Colors
assert not "GOLD" in Colors
```

#### Example 10: Subclassing with Backfilling

```python
from enumerific import Enumeration

# To override the default behaviour and to allow backfilling of options from subclasses,
# the `backfill` keyword argument can be set to `True` when creating the class. This
# effectively creates another way to extend an existing enumeration class through
# subclassing and its side-effect of backfilling, compared to using the `.register()`
# method to add new options to an existing enumeration class:
class Colors(Enumeration, backfill=True):
    RED = 1
    GREEN = 2
    BLUE = 3

assert "RED" in Colors
assert "GREEN" in Colors
assert "BLUE" in Colors

class MoreColors(Colors):
    PURPLE = 4
    GOLD = 5

assert "RED" in MoreColors
assert "GREEN" in MoreColors
assert "BLUE" in MoreColors
assert "PURPLE" in MoreColors
assert "GOLD" in MoreColors

# As backfilling has been enabled for the superclass, subclass options are available on
# both the subclass as seen above as well as on the superclass through backfilling:
assert "PURPLE" in Colors
assert "GOLD" in Colors
```

#### Example 11: Subclassing Over

```python
from enumerific import Enumeration

class Colors(Enumeration):
    RED = 1
    GREEN = 2
    BLUE = 3

assert "RED" in Colors
assert Colors.RED == 1

assert "GREEN" in Colors
assert Colors.GREEN == 2

assert "BLUE" in Colors
assert Colors.BLUE == 3

# Subclasses of Enumerations classes can be given the same name as the parent class, so
# within this scope, the subclass shadows the superclass; the subclass inherits all the
# enumeration options of its parent(s) superclasses:
class Colors(Colors):
    PURPLE = 4
    GOLD = 5

assert "RED" in Colors
assert "GREEN" in Colors
assert "BLUE" in Colors

assert "PURPLE" in Colors
assert Colors.PURPLE == 4

assert "GOLD" in Colors
assert Colors.GOLD == 5
```

#### Example 12: Unregistering Existing Option

```python
from enumerific import Enumeration

# Note that unregistering options is prevented by default; to all options to be removed
# the `removable` argument needs to be set to `True` when the class is created:
class Colors(Enumeration, removable=True):
    RED = 1
    GREEN = 2
    BLUE = 3

Colors.unregister("GREEN")

assert "RED" in Colors
assert "GREEN" not in Colors
assert "BLUE" in Colors
```

#### Example 13: Preventing Subclassing of Enumeration Classes

```python
from enumerific import Enumeration, EnumerationSubclassingError
import pytest

# To prevent an enumeration class from being extended through subclassing, the
# `subclassable` keyword argument can be set when creating the class; this will
# result in an `EnumerationSubclassingError` exception being raised on subclassing:
class Colors(Enumeration, subclassable=False):
    RED = 1
    GREEN = 2
    BLUE = 3

with pytest.raises(EnumerationSubclassingError):
    class MoreColors(Colors):
        PURPLE = 4
```

#### Example 14: Aliasing Options

```python
from enumerific import Enumeration

# Note that aliasing options is prevented by default to ensure that all options have
# unique values; to allow aliasing, the `aliased` argument needs to be set to `True`
# when the class is created; aliases can be added by referencing the original option's
# name or its value as demonstrated below with the ROUGE and VERTE aliases:
class Colors(Enumeration, aliased=True):
    RED = 1
    GREEN = 2
    BLUE = 3
    ROUGE = RED
    VERTE = 2

assert "RED" in Colors
assert "GREEN" in Colors
assert "BLUE" in Colors
assert "ROUGE" in Colors
assert "VERTE" in Colors

# Note that aliases are just different names for the same exact option, so the aliases
# can be used interchangeably with the original option, and they have the same identity:
assert Colors.RED is Colors.ROUGE
assert Colors.GREEN is Colors.VERTE

# All of the other properties of aliased options are also identical because the alias is
# just another reference to the same exact object in memory:
assert Colors.RED.name == Colors.ROUGE.name
assert Colors.RED.value == Colors.ROUGE.value

# Different options have their own distinct identities
assert not Colors.RED is Colors.VERTE

# Aliased options report that they have been aliased:
assert Colors.RED.aliased is True
assert Colors.GREEN.aliased is True
assert Colors.ROUGE.aliased is True
assert Colors.VERTE.aliased is True

# Non-aliased options do not report that they have been aliased:
assert Colors.BLUE.aliased is False

# The aliases for an option can be obtained via the .aliases property:
assert Colors.RED.aliases == [Colors.ROUGE]
assert Colors.GREEN.aliases == [Colors.VERTE]
assert Colors.BLUE.aliases == []  # BLUE has not been aliased
```

#### Example 15: Non-Unique Options

```python
from enumerific import Enumeration

# Note that non-unique options are prevented by default to ensure that all options have
# unique values; to allow non-unique option values, the `unique` argument needs to be
# set to `False` when the class is created:
class Colors(Enumeration, unique=False):
    RED = 1
    GREEN = 1
    BLUE = 3

assert "RED" in Colors
assert Colors.RED.name == "RED"
assert Colors.RED.value == 1
assert Colors.RED == 1

assert "GREEN" in Colors
assert Colors.GREEN.name == "GREEN"
assert Colors.GREEN.value == 1
assert Colors.GREEN == 1

assert "BLUE" in Colors
assert Colors.BLUE.name == "BLUE"
assert Colors.BLUE.value == 3
assert Colors.BLUE == 3

# Note that although options can use the same values when the class has been configured
# to allow it, the enumeration options still maintain their own distinct identities:
assert not Colors.RED is Colors.GREEN
assert not Colors.BLUE is Colors.RED

# However, when enumeration options share values, options with the same values will
# compare as equal via equality checking (which is different than identity checking):
assert Colors.RED == Colors.GREEN
assert Colors.BLUE != Colors.RED
```

#### Example 16: Bit Wise Flags

```python
from enumerific import Enumeration

class Permissions(Enumeration, flags=True):
    READ = 1
    WRITE = 2
    EXECUTE = 4
    DELETE = 8

assert "READ" in Permissions
assert Permissions.READ.name == "READ"
assert Permissions.READ.value == 1
assert Permissions.READ == 1

assert "WRITE" in Permissions
assert Permissions.WRITE.name == "WRITE"
assert Permissions.WRITE.value == 2
assert Permissions.WRITE == 2

assert "EXECUTE" in Permissions
assert Permissions.EXECUTE.name == "EXECUTE"
assert Permissions.EXECUTE.value == 4
assert Permissions.EXECUTE == 4

# OR (add/merge) the READ and WRITE permission flags into the 'permissions' variable
permissions = Permissions.READ | Permissions.WRITE

assert str(permissions) == "Permissions.READ|WRITE"
assert Permissions.READ in permissions
assert Permissions.WRITE in permissions
assert not Permissions.EXECUTE in permissions

# Raises an exception as DELETE doesn't exist
assert not Permissions.DELETE in permissions

assert (permissions & Permissions.READ) == Permissions.READ
assert (permissions & Permissions.WRITE) == Permissions.WRITE

# XOR (remove) the WRITE permission from the 'permissions' variable
permissions = permissions ^ Permissions.WRITE

assert Permissions.READ in permissions
assert not Permissions.WRITE in permissions
assert not Permissions.EXECUTE in permissions

assert (permissions & Permissions.READ) == Permissions.READ
assert not (permissions & Permissions.WRITE) == Permissions.WRITE

assert not Permissions.WRITE in permissions
assert str(permissions) == "Permissions.READ"

# The order of the name components follows the order the underlaying flags were declared
assert str(Permissions.READ | Permissions.WRITE) == "Permissions.READ|WRITE"
assert str(Permissions.WRITE | Permissions.READ) == "Permissions.READ|WRITE"
assert (
    str(Permissions.WRITE | Permissions.READ | Permissions.EXECUTE)
    == "Permissions.READ|WRITE|EXECUTE"
)

# Assign 'permissions' to the (~) inverse (opposite) of EXECUTE,
# i.e. all Permissions options except EXECUTE
permissions = ~Permissions.EXECUTE

assert Permissions.READ in permissions
assert Permissions.WRITE in permissions
assert not Permissions.EXECUTE in permissions
assert Permissions.DELETE in permissions
assert str(permissions) == "Permissions.READ|WRITE|DELETE"
```

#### Example 17: Annotating Enumeration Option Values

```python
from enumerific import Enumeration, anno

# The 'anno' (annotation) class can be used to add annotations to enumeration options;
# these are arbitrary key-value pairs that can be used to hold any additional data that
# is useful to keep associated with the enumeration option; the annotation values are
# then accessible anywhere that the enumeration is, and can be accessed as attributes:
class Colors(Enumeration):
    RED = anno(1, rgb=(255, 0, 0), primary=True)
    GREEN = anno(2, rgb=(0, 255, 0), primary=True)
    BLUE = anno(3, rgb=(0, 0, 255), primary=True)
    PURPLE = anno(4, rgb=(255, 0, 255), primary=False)

assert "RED" in Colors
assert Colors.RED.name == "RED"
assert Colors.RED.value == 1
assert Colors.RED == 1
assert Colors.RED.rgb == (255, 0, 0)
assert Colors.RED.primary is True

assert "GREEN" in Colors
assert Colors.GREEN.name == "GREEN"
assert Colors.GREEN.value == 2
assert Colors.GREEN == 2
assert Colors.GREEN.rgb == (0, 255, 0)
assert Colors.GREEN.primary is True

assert "BLUE" in Colors
assert Colors.BLUE.name == "BLUE"
assert Colors.BLUE.value == 3
assert Colors.BLUE == 3
assert Colors.BLUE.rgb == (0, 0, 255)
assert Colors.BLUE.primary is True

assert "PURPLE" in Colors
assert Colors.PURPLE.name == "PURPLE"
assert Colors.PURPLE.value == 4
assert Colors.PURPLE == 4
assert Colors.PURPLE.rgb == (255, 0, 255)
assert Colors.PURPLE.primary is False
```

#### Example 18: Annotating Enumeration Option Values with Automatic Sequencing

```python
from enumerific import Enumeration, auto

# The 'auto' (automatic) class can be used to generate unique numeric sequence numbers
# for enumeration options and to optionally add annotations to those same options; the
# annotation key-value pairs can be used to hold any additional data that is useful to
# keep associated with the enumeration option; the annotation values are then accessible
# anywhere that the enumeration is, and can be accessed as attributes:
class Colors(Enumeration):
    RED = auto(rgb=(255, 0, 0), primary=True)
    GREEN = auto(rgb=(0, 255, 0), primary=True)
    BLUE = auto(rgb=(0, 0, 255), primary=True)
    PURPLE = auto(rgb=(255, 0, 255), primary=False)

assert "RED" in Colors
assert Colors.RED.name == "RED"
assert Colors.RED.value == 1
assert Colors.RED == 1
assert Colors.RED.rgb == (255, 0, 0)
assert Colors.RED.primary is True

assert "GREEN" in Colors
assert Colors.GREEN.name == "GREEN"
assert Colors.GREEN.value == 2
assert Colors.GREEN == 2
assert Colors.GREEN.rgb == (0, 255, 0)
assert Colors.GREEN.primary is True

assert "BLUE" in Colors
assert Colors.BLUE.name == "BLUE"
assert Colors.BLUE.value == 3
assert Colors.BLUE == 3
assert Colors.BLUE.rgb == (0, 0, 255)
assert Colors.BLUE.primary is True

assert "PURPLE" in Colors
assert Colors.PURPLE.name == "PURPLE"
assert Colors.PURPLE.value == 4
assert Colors.PURPLE == 4
assert Colors.PURPLE.rgb == (255, 0, 255)
assert Colors.PURPLE.primary is False
```

# Enumerific Library Enumerations: Classes & Methods

The Enumerific library's `Enumeration` class is a greenfield implementation of enumerations
and does not inherit from any of the standard library enumeration classes, but offers equivalent
and extended functionality implemented from scratch. Enumerific library enumerations can be used
in any situation that enumerations are needed, and can replace the use of standard library
enumerations in almost every case unless some very specific functionality or underlying behaviour
of standard library enumerations are relied upon in user code. For the majority of cases, the
functionality is sufficiently equivalent from an application binary interface (ABI) perspective
that the two implementations can be used interchangeably.

The Enumerific library's extended enumerations module offers the following classes:

 * `EnumerationConfiguration` – The `EnumerationConfiguration` class is used internally by the library
 to hold configuration information for an `Enumeration` class instance.

 * `EnumerationMetaClass` – The `EnumerationMetaClass` metaclass is responsible for creating instances of the `Enumeration` class for use, and provides an interface between the class definition and some of the special behaviours needed to facilitate enumerations, such as each enumeration option being an instance of the enumeration class.

 * `Enumeration` – The `Enumeration` class is the base class for all Enumerific library extended enumerations; the `Enumeration` class defines shared functionality used by all `Enumeration` class instances.

 * `EnumerationType` – The `EnumerationType` class is actually a subclass of `Enumeration` and is used internally by the library to track the data type of the options assigned to an enumeration class.

 * `EnumerationInteger` – The `EnumerationInteger` class is a subclass of `int` and `Enumeration` and supports interacting with enumeration options natively as `int` (integer) data types.

 * `EnumerationFloat` – The `EnumerationFloat` class is a subclass of `float` and `Enumeration` and supports interacting with enumeration options natively as `float` (floating point) data types.

 * `EnumerationComplex` – The `EnumerationComplex` class is a subclass of `complex` and `Enumeration` and supports interacting with enumeration options natively as `complex` (complex number) data types.

 * `EnumerationBytes` – The `EnumerationBytes` class is a subclass of `bytes` and `Enumeration` and supports interacting with enumeration options natively as `bytes` data types.

 * `EnumerationString` – The `EnumerationString` class is a subclass of `str` and `Enumeration` and supports interacting with enumeration options natively as `str` (string) data types.

 * `EnumerationTuple` – The `EnumerationTuple` class is a subclass of `tuple` and `Enumeration` and supports interacting with enumeration options natively as `tuple` data types.

 * `EnumerationSet` – The `EnumerationSet` class is a subclass of `set` and `Enumeration` and supports interacting with enumeration options natively as `set` data types.

 * `EnumerationList` – The `EnumerationList` class is a subclass of `list` and `Enumeration` and supports interacting with enumeration options natively as `list` data types.

 * `EnumerationDictionary` – The `EnumerationDictionary` class is a subclass of `dict` and `Enumeration` and supports interacting with enumeration options natively as `dict` (dictionary) data types.

 * `EnumerationFlag` – The `EnumerationFlag` class is a special subclass of `int` and `Enumeration` and supports interacting with enumeration options natively as `int` (integer) data types and supports bitwise operations on the enumeration options so that enumeration options can be used as bitwise flags.

The extended enumerations module also offers the following classes for annotating enumeration
options and for automatically generating sequence numbers for annotation options:

 * `anno` – The `anno` class provides support for annotating an enumeration option's value, allowing an enumeration option to carry both a value of any data type, and optional additional annotations of key-value pairs that can be accessed as properties on the annotated enumeration option.
 
 * `auto` – The `auto` class is a subclass of `anno` and provides support both for annotating and enumeration option's value as per the functionality supported by its superclass, and additionally provides support for automatically generating unique number sequences to use for enumeration options, obviating the need to manually assign unique values to each enumeration option; number sequences can be configured to suit a range of needs, including generating number sequences as powers of two, which is particularly useful for the enumeration of bitwise flags as supported by the `EnumerationFlag` subclass.

# Standard Library Enumerations: Classes & Methods

The Enumerific library's own `Enum` class is a subclass of the built-in `enum.Enum` class,
so all of the built-in functionality of `enum.Enum` is available, as well as several additional class methods:

* `reconcile(value: object, default: Enum = None, raises: bool = False)` (`Enum`) – The `reconcile()` method allows for an enumeration's value or an enumeration option's name to be reconciled against a matching enumeration option. If the provided value can be matched against one of the enumeration's available options, that option will be returned, otherwise there are two possible behaviours: if the `raises` keyword argument has been set to or left as `False` (its default), the value assigned to the `default` keyword argument will be returned, which may be `None` if no default value has been specified; if the `raises` argument has been set to `True` an `EnumValueError` exception will be raised as an alert that the provided value could not be matched. One can also provide an enumeration option as the input value to the `reconcile` method, and these will be validated and returned as-is.

* `validate(value: object)` (`bool`) – The `validate()` method takes the same range of input values as the `reconcile` method, and returns `True` when the provided value can be reconciled against an enumeration option, or `False` otherwise.

* `options()` (`list[Enum]`) – The `options()` method provides easy access to the list of the enumeration's available options.

The benefits of being able to validate and reconcile various input values against an enumeration, include allowing for a controlled vocabulary of options to be checked against, and the ability to convert enumeration values into their corresponding enumeration option. This can be especially useful when working with input data where you need to convert those values to their corresponding enumeration options, and to be able to do so without maintaining boilerplate code to perform the matching and assignment.

To make use of the extra functionality for the standard library's `Enum` class, import the `Enum` class from the Enumerific library:

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2

val = Colors.RED
```

You can also import the `Enum` class directly from the `enumerific` library and use it directly:

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
```

Some examples of use include the following code samples, where each make use of the example `Colors` class, defined as follows:

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2
```

#### Example 1: Reconciling a Value

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2

# Given a string value in this case
value = 1

# Reconcile it to the associated enumeration option
color = Colors.reconcile(value)

assert color == Colors.RED  # asserts successfully
assert color is Colors.RED  # asserts successfully as enums are singletons
```

#### Example 2: Reconciling an Enumeration Option Name

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2

# Given a string value in this case
value = "GREEN"

# Reconcile it to the associated enumeration option
color = Colors.reconcile(value)

assert color == Colors.GREEN  # asserts successfully
assert color is Colors.GREEN  # asserts successfully as enums are singletons
```

#### Example 3: Validating a Value

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2

# The value can be an enumeration option's name, its value, or the enumeration option
value = "RED"
value = 1
value = Colors.RED

if Colors.validate(value) is True:
    # do something if the value could be validated
    pass
else:
    # do something else if the value could not be validated
    pass
```

#### Example 4: Iterating Over Enumeration Options

```python
from enumerific import Enum

class Colors(Enum):
  RED = 1
  GREEN = 2

for option in Colors.options():
    # do something with each option
    print(option.name, option.value)
```

### Unit Tests

The Enumerific library includes a suite of comprehensive unit tests which ensure that the
library functionality operates as expected. The unit tests were developed with and are run via `pytest`.

To ensure that the unit tests are run within a predictable runtime environment where all of the necessary dependencies are available, a [Docker](https://www.docker.com) image is created within which the tests are run. To run the unit tests, ensure Docker and Docker Compose is [installed](https://docs.docker.com/engine/install/), and perform the following commands, which will build the Docker image via `docker compose build` and then run the tests via `docker compose run` – the output of running the tests will be displayed:

```shell
$ docker compose build
$ docker compose run tests
```

To run the unit tests with optional command line arguments being passed to `pytest`, append the relevant arguments to the `docker compose run tests` command, as follows, for example passing `-vv` to enable verbose output:

```shell
$ docker compose run tests -vv
```

See the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding available optional command line arguments.

### Copyright & License Information

Copyright © 2024–2025 Daniel Sissman; licensed under the MIT License.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "enumerific",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "enum, enumeration, enumerations",
    "author": "Daniel Sissman",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/9c/5d/ebe156f07774ef56ecfdef85e3820c5add54af86ed103d337feade4f54ce/enumerific-1.0.5.tar.gz",
    "platform": null,
    "description": "# Enumerific Enums\n\nThe Enumerific library provides a greenfield implementation of enumerations with many unique features through the library's own `Enumeration` class, as well as separately offering several useful extra methods for the built-in standard library `enums.Enum` type.\n\nThe Enumerific library's `Enumeration` class offers the following features:\n\n * A greenfield implementation of enumerations compatible with Python 3.10 and later versions;\n * Enumerific enumerations can hold option values of the same or mixed types, including `int`, `float`, `complex`, `str`, `bytes`, `set`, `tuple`, `list`, `dict` as well as arbitrary `object` types;\n * Enumerific enumeration options can be accessed directly as native data types and enumeration options can be used anywhere that the corresponding native data types can be used;\n * Support for automatic typecasting of the `Enumeration` base class to support the use of enumeration option values interchangeably with native data type values;\n * Enumerific enumerations options can be added after an `Enumeration` class has been created either through extending an existing enumerations class by subclassing or by registering new options directly on an existing enumerations class via the `.register()` method; this is especially useful for cases where enumeration options may not all be known prior to runtime;\n * Enumerific enumerations options can be removed after an `Enumeration` class has been created via the `.unregister()` method; this specialised behaviour is prevented by default, but can be enabled for advanced use cases;\n * Enforcement of unique values for all options within an enumeration, unless overridden;\n * Support for aliasing enumeration options, and control over this behaviour;\n * Support for backfilling enumeration options on a superclass when subclassing, and control over this behaviour\n * Support for redefining enumeration options, and control over this behaviour;\n * Support for automatically generating unique number sequences for enumeration options, including powers of two for bitwise enumeration flags, as well as other sequences such as powers of other numbers and factoring;\n * Support for annotating enumeration options with additional arbitrary key-value pairs, which can be particularly useful for associating additional data with a given enumeration option, which may be accessed later anywhere in code that the enumeration option is available;\n * Simple one-line reconciliation of `Enumeration` class options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;\n * Simple one-line validation of `Enumeration` class options; validation by enumeration option name, value and enumeration class instance reference are all supported through the `.validate()` class method;\n * Simple access to all of the options provided by an `Enumeration` class instance through the `.options()` class method;\n * Access to all of the names of the `Enumeration` class options via the `.names()` method;\n * Access to all of the names/keys of the `Enumeration` class options via the `.keys()` method;\n * Access to all of the values of the `Enumeration` class options via the `.values()` method;\n * Access to all of the key-value pairs of the `Enumeration` class options via the `.items()` method;\n * Ability to determine if an enumeration option is an alias of another option, or is an option in its own right via the `Enumeration` class' `.aliased` property.\n * Ability to obtain the aliases for an enumeration option via the `.aliases` property.\n\nFurthermore, as noted, the Enumerific library also offers extended functionality for the built-in standard library `enums.Enum` type:\n\n * Simple one-line reconciliation of `enums.Enum` options to the corresponding `enums.Enum` class instance that represents the corresponding option; reconciliation by enumeration option name, value and enumeration class instance reference are all supported through the `.reconcile()` class method;\n * Simple one-line validation of `enums.Enum` options; validation by enumeration option name, value and enumeration class instance reference are all supported through the `.validate()` class method;\n * Simple access to all of the options provided by an `enums.Enum` class instance through the `.options()` class method.\n\n### Requirements\n\nThe Enumerific library has been tested with Python 3.10, 3.11, 3.12 and 3.13, and is not\ncompatible with Python 3.9 or earlier.\n\n### Installation\n\nEnumerific is available from the PyPI, so may be added to a project's dependencies via\nits `requirements.txt` file or similar by referencing the library's name, `enumerific`,\nor the library may be installed directly into your local runtime environment using `pip`\nby entering the following command, and following any prompts:\n\n\t$ pip install enumerific\n\n### Usage\n\nTo use the Enumerific library's implementation of enumerations import the `Enumeration` class from the Enumerific library:\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nassert issubclass(Colors, Enumeration)\n\n# Note that as all of the Colors enumeration options have integer values, the class was\n# typecast to int so that its option values can be used interchangeably with integers:\nassert issubclass(Colors, int)\n\ncolor = Colors.RED\n\n# Enumeration class options are instances of the class\nassert isinstance(color, Colors)\n\n# They can also be instances of the raw value that was assigned to the option\nassert isinstance(color, int)\n\n# Each enumeration class option has a name (the name used to define the option)\nassert color.name == \"RED\"\n\n# Each enumeration class option has a value (the value used when defining the option)\nassert color.value == 1\n\n# The identity of an enumeration option matches the option\nassert color is Colors.RED\n\n# The equality of an enumeration option can also be compared against the enumeration\n# option directly, against the name of the option, or against the value:\nassert color == Colors.RED\nassert color == \"RED\"\nassert color == 1\nassert color != 2\n```\n\n#### Example 1: Reconciling a Value\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\n# Given a string value in this case\nvalue = 1\n\n# Reconcile it to the associated enumeration option\ncolor = Colors.reconcile(value)\n\nassert color == Colors.RED  # asserts successfully\nassert color is Colors.RED  # asserts successfully as Enumeration class options are singletons\n```\n\n#### Example 2: Reconciling an Enumeration Option Name\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\n# Given a string value in this case\nvalue = \"RED\"\n\n# Reconcile it to the associated enumeration option\ncolor = Colors.reconcile(value)\n\nassert color == Colors.RED  # asserts successfully\nassert color is Colors.RED  # asserts successfully as Enumeration class options are singletons\n\n# Given a string value in this case\nvalue = \"red\"\n\n# Reconcile it to the associated enumeration option;\n# values can be reconciled caselessly too:\ncolor = Colors.reconcile(value, caselessly=True)\n\nassert color == Colors.RED  # asserts successfully\nassert color is Colors.RED  # asserts successfully as Enumeration class options are singletons\n```\n\n#### Example 3: Validating a Value\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\n# The value can be an enumeration option's name, its value, or the enumeration option\nvalue = \"RED\"\nvalue = 1\nvalue = Colors.RED\n\nif Colors.validate(value) is True:\n    # do something if the value could be validated\n    pass\nelse:\n    # do something else if the value could not be validated\n    pass\n```\n\n#### Example 4: Iterating Over Enumeration Options\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\noptions = Colors.options()\n\nfor name, option in options.items():\n    # do something with each option\n    print(option.name, option.value)\n```\n\n#### Example 5: Iterating Over Enumeration Names\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nfor name in Colors.names():\n    # do something with each option name\n    print(name)\n```\n\n#### Example 6: Iterating Over Enumeration Keys\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nfor key in Colors.keys():\n    # do something with each option key\n    print(key)\n```\n\n#### Example 7: Iterating Over Enumeration Values\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nfor value in Colors.values():\n    # do something with each option key\n    print(value)\n```\n\n#### Example 8: Registering New Options\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nColors.register(\"PURPLE\", 4)\nColors.register(\"GOLD\", 5)\n\nassert \"PURPLE\" in Colors\nassert Colors.PURPLE.name == \"PURPLE\"\nassert Colors.PURPLE.value == 4\nassert Colors.PURPLE == 4\n\nassert \"GOLD\" in Colors\nassert Colors.GOLD.name == \"GOLD\"\nassert Colors.GOLD.value == 5\nassert Colors.GOLD == 5\n```\n\n#### Example 9: Subclassing\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\n# Ensure that Colors has the expected options\nassert \"RED\" in Colors\nassert \"GREEN\" in Colors\nassert \"BLUE\" in Colors\n\n# Create a subclass of Colors, inheriting its options\nclass MoreColors(Colors):\n    PURPLE = 4\n    GOLD = 5\n\n# Ensure that MoreColors inherited the options from Colors, as well as adding its own\nassert \"RED\" in MoreColors\nassert \"GREEN\" in MoreColors\nassert \"BLUE\" in MoreColors\nassert \"PURPLE\" in MoreColors\nassert \"GOLD\" in MoreColors\n\n# As backfilling is off by default subclass options won't be available on the superclass\nassert not \"PURPLE\" in Colors\nassert not \"GOLD\" in Colors\n```\n\n#### Example 10: Subclassing with Backfilling\n\n```python\nfrom enumerific import Enumeration\n\n# To override the default behaviour and to allow backfilling of options from subclasses,\n# the `backfill` keyword argument can be set to `True` when creating the class. This\n# effectively creates another way to extend an existing enumeration class through\n# subclassing and its side-effect of backfilling, compared to using the `.register()`\n# method to add new options to an existing enumeration class:\nclass Colors(Enumeration, backfill=True):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nassert \"RED\" in Colors\nassert \"GREEN\" in Colors\nassert \"BLUE\" in Colors\n\nclass MoreColors(Colors):\n    PURPLE = 4\n    GOLD = 5\n\nassert \"RED\" in MoreColors\nassert \"GREEN\" in MoreColors\nassert \"BLUE\" in MoreColors\nassert \"PURPLE\" in MoreColors\nassert \"GOLD\" in MoreColors\n\n# As backfilling has been enabled for the superclass, subclass options are available on\n# both the subclass as seen above as well as on the superclass through backfilling:\nassert \"PURPLE\" in Colors\nassert \"GOLD\" in Colors\n```\n\n#### Example 11: Subclassing Over\n\n```python\nfrom enumerific import Enumeration\n\nclass Colors(Enumeration):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nassert \"RED\" in Colors\nassert Colors.RED == 1\n\nassert \"GREEN\" in Colors\nassert Colors.GREEN == 2\n\nassert \"BLUE\" in Colors\nassert Colors.BLUE == 3\n\n# Subclasses of Enumerations classes can be given the same name as the parent class, so\n# within this scope, the subclass shadows the superclass; the subclass inherits all the\n# enumeration options of its parent(s) superclasses:\nclass Colors(Colors):\n    PURPLE = 4\n    GOLD = 5\n\nassert \"RED\" in Colors\nassert \"GREEN\" in Colors\nassert \"BLUE\" in Colors\n\nassert \"PURPLE\" in Colors\nassert Colors.PURPLE == 4\n\nassert \"GOLD\" in Colors\nassert Colors.GOLD == 5\n```\n\n#### Example 12: Unregistering Existing Option\n\n```python\nfrom enumerific import Enumeration\n\n# Note that unregistering options is prevented by default; to all options to be removed\n# the `removable` argument needs to be set to `True` when the class is created:\nclass Colors(Enumeration, removable=True):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nColors.unregister(\"GREEN\")\n\nassert \"RED\" in Colors\nassert \"GREEN\" not in Colors\nassert \"BLUE\" in Colors\n```\n\n#### Example 13: Preventing Subclassing of Enumeration Classes\n\n```python\nfrom enumerific import Enumeration, EnumerationSubclassingError\nimport pytest\n\n# To prevent an enumeration class from being extended through subclassing, the\n# `subclassable` keyword argument can be set when creating the class; this will\n# result in an `EnumerationSubclassingError` exception being raised on subclassing:\nclass Colors(Enumeration, subclassable=False):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n\nwith pytest.raises(EnumerationSubclassingError):\n    class MoreColors(Colors):\n        PURPLE = 4\n```\n\n#### Example 14: Aliasing Options\n\n```python\nfrom enumerific import Enumeration\n\n# Note that aliasing options is prevented by default to ensure that all options have\n# unique values; to allow aliasing, the `aliased` argument needs to be set to `True`\n# when the class is created; aliases can be added by referencing the original option's\n# name or its value as demonstrated below with the ROUGE and VERTE aliases:\nclass Colors(Enumeration, aliased=True):\n    RED = 1\n    GREEN = 2\n    BLUE = 3\n    ROUGE = RED\n    VERTE = 2\n\nassert \"RED\" in Colors\nassert \"GREEN\" in Colors\nassert \"BLUE\" in Colors\nassert \"ROUGE\" in Colors\nassert \"VERTE\" in Colors\n\n# Note that aliases are just different names for the same exact option, so the aliases\n# can be used interchangeably with the original option, and they have the same identity:\nassert Colors.RED is Colors.ROUGE\nassert Colors.GREEN is Colors.VERTE\n\n# All of the other properties of aliased options are also identical because the alias is\n# just another reference to the same exact object in memory:\nassert Colors.RED.name == Colors.ROUGE.name\nassert Colors.RED.value == Colors.ROUGE.value\n\n# Different options have their own distinct identities\nassert not Colors.RED is Colors.VERTE\n\n# Aliased options report that they have been aliased:\nassert Colors.RED.aliased is True\nassert Colors.GREEN.aliased is True\nassert Colors.ROUGE.aliased is True\nassert Colors.VERTE.aliased is True\n\n# Non-aliased options do not report that they have been aliased:\nassert Colors.BLUE.aliased is False\n\n# The aliases for an option can be obtained via the .aliases property:\nassert Colors.RED.aliases == [Colors.ROUGE]\nassert Colors.GREEN.aliases == [Colors.VERTE]\nassert Colors.BLUE.aliases == []  # BLUE has not been aliased\n```\n\n#### Example 15: Non-Unique Options\n\n```python\nfrom enumerific import Enumeration\n\n# Note that non-unique options are prevented by default to ensure that all options have\n# unique values; to allow non-unique option values, the `unique` argument needs to be\n# set to `False` when the class is created:\nclass Colors(Enumeration, unique=False):\n    RED = 1\n    GREEN = 1\n    BLUE = 3\n\nassert \"RED\" in Colors\nassert Colors.RED.name == \"RED\"\nassert Colors.RED.value == 1\nassert Colors.RED == 1\n\nassert \"GREEN\" in Colors\nassert Colors.GREEN.name == \"GREEN\"\nassert Colors.GREEN.value == 1\nassert Colors.GREEN == 1\n\nassert \"BLUE\" in Colors\nassert Colors.BLUE.name == \"BLUE\"\nassert Colors.BLUE.value == 3\nassert Colors.BLUE == 3\n\n# Note that although options can use the same values when the class has been configured\n# to allow it, the enumeration options still maintain their own distinct identities:\nassert not Colors.RED is Colors.GREEN\nassert not Colors.BLUE is Colors.RED\n\n# However, when enumeration options share values, options with the same values will\n# compare as equal via equality checking (which is different than identity checking):\nassert Colors.RED == Colors.GREEN\nassert Colors.BLUE != Colors.RED\n```\n\n#### Example 16: Bit Wise Flags\n\n```python\nfrom enumerific import Enumeration\n\nclass Permissions(Enumeration, flags=True):\n    READ = 1\n    WRITE = 2\n    EXECUTE = 4\n    DELETE = 8\n\nassert \"READ\" in Permissions\nassert Permissions.READ.name == \"READ\"\nassert Permissions.READ.value == 1\nassert Permissions.READ == 1\n\nassert \"WRITE\" in Permissions\nassert Permissions.WRITE.name == \"WRITE\"\nassert Permissions.WRITE.value == 2\nassert Permissions.WRITE == 2\n\nassert \"EXECUTE\" in Permissions\nassert Permissions.EXECUTE.name == \"EXECUTE\"\nassert Permissions.EXECUTE.value == 4\nassert Permissions.EXECUTE == 4\n\n# OR (add/merge) the READ and WRITE permission flags into the 'permissions' variable\npermissions = Permissions.READ | Permissions.WRITE\n\nassert str(permissions) == \"Permissions.READ|WRITE\"\nassert Permissions.READ in permissions\nassert Permissions.WRITE in permissions\nassert not Permissions.EXECUTE in permissions\n\n# Raises an exception as DELETE doesn't exist\nassert not Permissions.DELETE in permissions\n\nassert (permissions & Permissions.READ) == Permissions.READ\nassert (permissions & Permissions.WRITE) == Permissions.WRITE\n\n# XOR (remove) the WRITE permission from the 'permissions' variable\npermissions = permissions ^ Permissions.WRITE\n\nassert Permissions.READ in permissions\nassert not Permissions.WRITE in permissions\nassert not Permissions.EXECUTE in permissions\n\nassert (permissions & Permissions.READ) == Permissions.READ\nassert not (permissions & Permissions.WRITE) == Permissions.WRITE\n\nassert not Permissions.WRITE in permissions\nassert str(permissions) == \"Permissions.READ\"\n\n# The order of the name components follows the order the underlaying flags were declared\nassert str(Permissions.READ | Permissions.WRITE) == \"Permissions.READ|WRITE\"\nassert str(Permissions.WRITE | Permissions.READ) == \"Permissions.READ|WRITE\"\nassert (\n    str(Permissions.WRITE | Permissions.READ | Permissions.EXECUTE)\n    == \"Permissions.READ|WRITE|EXECUTE\"\n)\n\n# Assign 'permissions' to the (~) inverse (opposite) of EXECUTE,\n# i.e. all Permissions options except EXECUTE\npermissions = ~Permissions.EXECUTE\n\nassert Permissions.READ in permissions\nassert Permissions.WRITE in permissions\nassert not Permissions.EXECUTE in permissions\nassert Permissions.DELETE in permissions\nassert str(permissions) == \"Permissions.READ|WRITE|DELETE\"\n```\n\n#### Example 17: Annotating Enumeration Option Values\n\n```python\nfrom enumerific import Enumeration, anno\n\n# The 'anno' (annotation) class can be used to add annotations to enumeration options;\n# these are arbitrary key-value pairs that can be used to hold any additional data that\n# is useful to keep associated with the enumeration option; the annotation values are\n# then accessible anywhere that the enumeration is, and can be accessed as attributes:\nclass Colors(Enumeration):\n    RED = anno(1, rgb=(255, 0, 0), primary=True)\n    GREEN = anno(2, rgb=(0, 255, 0), primary=True)\n    BLUE = anno(3, rgb=(0, 0, 255), primary=True)\n    PURPLE = anno(4, rgb=(255, 0, 255), primary=False)\n\nassert \"RED\" in Colors\nassert Colors.RED.name == \"RED\"\nassert Colors.RED.value == 1\nassert Colors.RED == 1\nassert Colors.RED.rgb == (255, 0, 0)\nassert Colors.RED.primary is True\n\nassert \"GREEN\" in Colors\nassert Colors.GREEN.name == \"GREEN\"\nassert Colors.GREEN.value == 2\nassert Colors.GREEN == 2\nassert Colors.GREEN.rgb == (0, 255, 0)\nassert Colors.GREEN.primary is True\n\nassert \"BLUE\" in Colors\nassert Colors.BLUE.name == \"BLUE\"\nassert Colors.BLUE.value == 3\nassert Colors.BLUE == 3\nassert Colors.BLUE.rgb == (0, 0, 255)\nassert Colors.BLUE.primary is True\n\nassert \"PURPLE\" in Colors\nassert Colors.PURPLE.name == \"PURPLE\"\nassert Colors.PURPLE.value == 4\nassert Colors.PURPLE == 4\nassert Colors.PURPLE.rgb == (255, 0, 255)\nassert Colors.PURPLE.primary is False\n```\n\n#### Example 18: Annotating Enumeration Option Values with Automatic Sequencing\n\n```python\nfrom enumerific import Enumeration, auto\n\n# The 'auto' (automatic) class can be used to generate unique numeric sequence numbers\n# for enumeration options and to optionally add annotations to those same options; the\n# annotation key-value pairs can be used to hold any additional data that is useful to\n# keep associated with the enumeration option; the annotation values are then accessible\n# anywhere that the enumeration is, and can be accessed as attributes:\nclass Colors(Enumeration):\n    RED = auto(rgb=(255, 0, 0), primary=True)\n    GREEN = auto(rgb=(0, 255, 0), primary=True)\n    BLUE = auto(rgb=(0, 0, 255), primary=True)\n    PURPLE = auto(rgb=(255, 0, 255), primary=False)\n\nassert \"RED\" in Colors\nassert Colors.RED.name == \"RED\"\nassert Colors.RED.value == 1\nassert Colors.RED == 1\nassert Colors.RED.rgb == (255, 0, 0)\nassert Colors.RED.primary is True\n\nassert \"GREEN\" in Colors\nassert Colors.GREEN.name == \"GREEN\"\nassert Colors.GREEN.value == 2\nassert Colors.GREEN == 2\nassert Colors.GREEN.rgb == (0, 255, 0)\nassert Colors.GREEN.primary is True\n\nassert \"BLUE\" in Colors\nassert Colors.BLUE.name == \"BLUE\"\nassert Colors.BLUE.value == 3\nassert Colors.BLUE == 3\nassert Colors.BLUE.rgb == (0, 0, 255)\nassert Colors.BLUE.primary is True\n\nassert \"PURPLE\" in Colors\nassert Colors.PURPLE.name == \"PURPLE\"\nassert Colors.PURPLE.value == 4\nassert Colors.PURPLE == 4\nassert Colors.PURPLE.rgb == (255, 0, 255)\nassert Colors.PURPLE.primary is False\n```\n\n# Enumerific Library Enumerations: Classes & Methods\n\nThe Enumerific library's `Enumeration` class is a greenfield implementation of enumerations\nand does not inherit from any of the standard library enumeration classes, but offers equivalent\nand extended functionality implemented from scratch. Enumerific library enumerations can be used\nin any situation that enumerations are needed, and can replace the use of standard library\nenumerations in almost every case unless some very specific functionality or underlying behaviour\nof standard library enumerations are relied upon in user code. For the majority of cases, the\nfunctionality is sufficiently equivalent from an application binary interface (ABI) perspective\nthat the two implementations can be used interchangeably.\n\nThe Enumerific library's extended enumerations module offers the following classes:\n\n * `EnumerationConfiguration` \u2013 The `EnumerationConfiguration` class is used internally by the library\n to hold configuration information for an `Enumeration` class instance.\n\n * `EnumerationMetaClass` \u2013 The `EnumerationMetaClass` metaclass is responsible for creating instances of the `Enumeration` class for use, and provides an interface between the class definition and some of the special behaviours needed to facilitate enumerations, such as each enumeration option being an instance of the enumeration class.\n\n * `Enumeration` \u2013 The `Enumeration` class is the base class for all Enumerific library extended enumerations; the `Enumeration` class defines shared functionality used by all `Enumeration` class instances.\n\n * `EnumerationType` \u2013 The `EnumerationType` class is actually a subclass of `Enumeration` and is used internally by the library to track the data type of the options assigned to an enumeration class.\n\n * `EnumerationInteger` \u2013 The `EnumerationInteger` class is a subclass of `int` and `Enumeration` and supports interacting with enumeration options natively as `int` (integer) data types.\n\n * `EnumerationFloat` \u2013 The `EnumerationFloat` class is a subclass of `float` and `Enumeration` and supports interacting with enumeration options natively as `float` (floating point) data types.\n\n * `EnumerationComplex` \u2013 The `EnumerationComplex` class is a subclass of `complex` and `Enumeration` and supports interacting with enumeration options natively as `complex` (complex number) data types.\n\n * `EnumerationBytes` \u2013 The `EnumerationBytes` class is a subclass of `bytes` and `Enumeration` and supports interacting with enumeration options natively as `bytes` data types.\n\n * `EnumerationString` \u2013 The `EnumerationString` class is a subclass of `str` and `Enumeration` and supports interacting with enumeration options natively as `str` (string) data types.\n\n * `EnumerationTuple` \u2013 The `EnumerationTuple` class is a subclass of `tuple` and `Enumeration` and supports interacting with enumeration options natively as `tuple` data types.\n\n * `EnumerationSet` \u2013 The `EnumerationSet` class is a subclass of `set` and `Enumeration` and supports interacting with enumeration options natively as `set` data types.\n\n * `EnumerationList` \u2013 The `EnumerationList` class is a subclass of `list` and `Enumeration` and supports interacting with enumeration options natively as `list` data types.\n\n * `EnumerationDictionary` \u2013 The `EnumerationDictionary` class is a subclass of `dict` and `Enumeration` and supports interacting with enumeration options natively as `dict` (dictionary) data types.\n\n * `EnumerationFlag` \u2013 The `EnumerationFlag` class is a special subclass of `int` and `Enumeration` and supports interacting with enumeration options natively as `int` (integer) data types and supports bitwise operations on the enumeration options so that enumeration options can be used as bitwise flags.\n\nThe extended enumerations module also offers the following classes for annotating enumeration\noptions and for automatically generating sequence numbers for annotation options:\n\n * `anno` \u2013 The `anno` class provides support for annotating an enumeration option's value, allowing an enumeration option to carry both a value of any data type, and optional additional annotations of key-value pairs that can be accessed as properties on the annotated enumeration option.\n \n * `auto` \u2013 The `auto` class is a subclass of `anno` and provides support both for annotating and enumeration option's value as per the functionality supported by its superclass, and additionally provides support for automatically generating unique number sequences to use for enumeration options, obviating the need to manually assign unique values to each enumeration option; number sequences can be configured to suit a range of needs, including generating number sequences as powers of two, which is particularly useful for the enumeration of bitwise flags as supported by the `EnumerationFlag` subclass.\n\n# Standard Library Enumerations: Classes & Methods\n\nThe Enumerific library's own `Enum` class is a subclass of the built-in `enum.Enum` class,\nso all of the built-in functionality of `enum.Enum` is available, as well as several additional class methods:\n\n* `reconcile(value: object, default: Enum = None, raises: bool = False)` (`Enum`) \u2013 The `reconcile()` method allows for an enumeration's value or an enumeration option's name to be reconciled against a matching enumeration option. If the provided value can be matched against one of the enumeration's available options, that option will be returned, otherwise there are two possible behaviours: if the `raises` keyword argument has been set to or left as `False` (its default), the value assigned to the `default` keyword argument will be returned, which may be `None` if no default value has been specified; if the `raises` argument has been set to `True` an `EnumValueError` exception will be raised as an alert that the provided value could not be matched. One can also provide an enumeration option as the input value to the `reconcile` method, and these will be validated and returned as-is.\n\n* `validate(value: object)` (`bool`) \u2013 The `validate()` method takes the same range of input values as the `reconcile` method, and returns `True` when the provided value can be reconciled against an enumeration option, or `False` otherwise.\n\n* `options()` (`list[Enum]`) \u2013 The `options()` method provides easy access to the list of the enumeration's available options.\n\nThe benefits of being able to validate and reconcile various input values against an enumeration, include allowing for a controlled vocabulary of options to be checked against, and the ability to convert enumeration values into their corresponding enumeration option. This can be especially useful when working with input data where you need to convert those values to their corresponding enumeration options, and to be able to do so without maintaining boilerplate code to perform the matching and assignment.\n\nTo make use of the extra functionality for the standard library's `Enum` class, import the `Enum` class from the Enumerific library:\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n\nval = Colors.RED\n```\n\nYou can also import the `Enum` class directly from the `enumerific` library and use it directly:\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n```\n\nSome examples of use include the following code samples, where each make use of the example `Colors` class, defined as follows:\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n```\n\n#### Example 1: Reconciling a Value\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n\n# Given a string value in this case\nvalue = 1\n\n# Reconcile it to the associated enumeration option\ncolor = Colors.reconcile(value)\n\nassert color == Colors.RED  # asserts successfully\nassert color is Colors.RED  # asserts successfully as enums are singletons\n```\n\n#### Example 2: Reconciling an Enumeration Option Name\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n\n# Given a string value in this case\nvalue = \"GREEN\"\n\n# Reconcile it to the associated enumeration option\ncolor = Colors.reconcile(value)\n\nassert color == Colors.GREEN  # asserts successfully\nassert color is Colors.GREEN  # asserts successfully as enums are singletons\n```\n\n#### Example 3: Validating a Value\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n\n# The value can be an enumeration option's name, its value, or the enumeration option\nvalue = \"RED\"\nvalue = 1\nvalue = Colors.RED\n\nif Colors.validate(value) is True:\n    # do something if the value could be validated\n    pass\nelse:\n    # do something else if the value could not be validated\n    pass\n```\n\n#### Example 4: Iterating Over Enumeration Options\n\n```python\nfrom enumerific import Enum\n\nclass Colors(Enum):\n  RED = 1\n  GREEN = 2\n\nfor option in Colors.options():\n    # do something with each option\n    print(option.name, option.value)\n```\n\n### Unit Tests\n\nThe Enumerific library includes a suite of comprehensive unit tests which ensure that the\nlibrary functionality operates as expected. The unit tests were developed with and are run via `pytest`.\n\nTo ensure that the unit tests are run within a predictable runtime environment where all of the necessary dependencies are available, a [Docker](https://www.docker.com) image is created within which the tests are run. To run the unit tests, ensure Docker and Docker Compose is [installed](https://docs.docker.com/engine/install/), and perform the following commands, which will build the Docker image via `docker compose build` and then run the tests via `docker compose run` \u2013 the output of running the tests will be displayed:\n\n```shell\n$ docker compose build\n$ docker compose run tests\n```\n\nTo run the unit tests with optional command line arguments being passed to `pytest`, append the relevant arguments to the `docker compose run tests` command, as follows, for example passing `-vv` to enable verbose output:\n\n```shell\n$ docker compose run tests -vv\n```\n\nSee the documentation for [PyTest](https://docs.pytest.org/en/latest/) regarding available optional command line arguments.\n\n### Copyright & License Information\n\nCopyright \u00a9 2024\u20132025 Daniel Sissman; licensed under the MIT License.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Simplifies working with Python enums.",
    "version": "1.0.5",
    "project_urls": {
        "changelog": "https://github.com/bluebinary/enumerific/blob/main/CHANGELOG.md",
        "documentation": "https://github.com/bluebinary/enumerific/blob/main/README.md",
        "homepage": "https://github.com/bluebinary/enumerific",
        "issues": "https://github.com/bluebinary/enumerific/issues",
        "repository": "https://github.com/bluebinary/enumerific"
    },
    "split_keywords": [
        "enum",
        " enumeration",
        " enumerations"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3ef37dc5cebd1d68834a0867046201edfdbd0bccd0e4a2fb8dc06c2d12508290",
                "md5": "375e8234d3d590730f2e98e64bec8a16",
                "sha256": "01c5890c098f11c5b0baf1c1601665dad115ea9bbd16d9405f45e1d11a96b7ff"
            },
            "downloads": -1,
            "filename": "enumerific-1.0.5-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "375e8234d3d590730f2e98e64bec8a16",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 25164,
            "upload_time": "2025-08-02T05:48:14",
            "upload_time_iso_8601": "2025-08-02T05:48:14.270162Z",
            "url": "https://files.pythonhosted.org/packages/3e/f3/7dc5cebd1d68834a0867046201edfdbd0bccd0e4a2fb8dc06c2d12508290/enumerific-1.0.5-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9c5debe156f07774ef56ecfdef85e3820c5add54af86ed103d337feade4f54ce",
                "md5": "b70db753b218f630c43f9face499d811",
                "sha256": "ba3e47a7999da57b2477b2cd4d07676f0a0cd42fe205f9b2a47026abf6f6516a"
            },
            "downloads": -1,
            "filename": "enumerific-1.0.5.tar.gz",
            "has_sig": false,
            "md5_digest": "b70db753b218f630c43f9face499d811",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 48080,
            "upload_time": "2025-08-02T05:48:15",
            "upload_time_iso_8601": "2025-08-02T05:48:15.803190Z",
            "url": "https://files.pythonhosted.org/packages/9c/5d/ebe156f07774ef56ecfdef85e3820c5add54af86ed103d337feade4f54ce/enumerific-1.0.5.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-02 05:48:15",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "bluebinary",
    "github_project": "enumerific",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [],
    "lcname": "enumerific"
}
        
Elapsed time: 2.05216s