Data Enums
An alternative to the built-in Python enum implementation. Supports Python 3.11+, including free-threaded Python (3.14t).
Data enums allow you to:
- Define enum members with associated data using type hints
- Enforce unique constraints on attributes
- Look up members by name or unique attribute values
- Filter members by any attribute
- Use pure enums without any data attributes
Usage
Install via PyPI:
pip install data-enum
Basic example
from typing import Annotated
from data_enum import DataEnum, UNIQUE, UniqueTogether
class Currency(DataEnum):
__members__ = ("USD", "EUR", "GBP")
symbol: str
name: str
code: Annotated[str, UNIQUE]
Currency.USD = Currency(symbol="$", name="US Dollar", code="USD")
Currency.EUR = Currency(symbol="€", name="Euro", code="EUR")
Currency.GBP = Currency(symbol="£", name="Pound Sterling", code="GBP")
Access data on members
Currency.USD.name # 'US Dollar'
Currency.EUR.symbol # '€'
str(Currency.USD) # 'USD'
repr(Currency.USD) # 'Currency.USD'
Look up members by name
Currency.get("USD") # Currency.USD
Currency.get("MISSING", default=None) # None
Currency.get("MISSING", default=Currency.USD) # Currency.USD
Look up by unique attribute
Currency.get(code="EUR") # Currency.EUR
Currency.get(code="MISSING", default=Currency.USD) # Currency.USD
Filter by any attribute
Currency.filter(symbol="$") # frozenset({Currency.USD})
Currency.filter(symbol="₿") # frozenset()
Compare and hash
Currency.USD == Currency.EUR # False
Currency.USD == Currency.USD # True
{Currency.USD, Currency.EUR} # works in sets
{Currency.USD: "dollar"} # works as dict keys
Default values
Use standard Python default syntax to make attributes optional:
class Currency(DataEnum):
__members__ = ("USD", "EUR", "GBP")
symbol: str
name: str
code: Annotated[str, UNIQUE]
active: bool = True
Currency.USD = Currency(symbol="$", name="US Dollar", code="USD") # active=True
Currency.EUR = Currency(symbol="€", name="Euro", code="EUR", active=False) # active=False
Defaults work with Annotated types too:
tag: Annotated[str, UNIQUE] = "none"
Unique-together constraints
Use UniqueTogether("group_name") to enforce that a combination of attributes is unique:
class State(DataEnum):
__members__ = ("CA_US", "TX_US", "ON_CA", "BC_CA")
country: Annotated[str, UniqueTogether("location")]
code: Annotated[str, UniqueTogether("location")]
name: str
State.CA_US = State(country="US", code="CA", name="California")
State.TX_US = State(country="US", code="TX", name="Texas")
State.ON_CA = State(country="CA", code="ON", name="Ontario")
State.BC_CA = State(country="CA", code="BC", name="British Columbia")
Individual attributes can repeat (country="US" appears twice), but the combination must be unique. Look up by passing all group attributes to get():
State.get(country="US", code="CA") # State.CA_US
State.get(country="CA", code="ON") # State.ON_CA
UniqueTogether works alongside UNIQUE and defaults:
class Place(DataEnum):
__members__ = ("A", "B")
country: Annotated[str, UniqueTogether("location")]
code: Annotated[str, UniqueTogether("location")]
full_name: Annotated[str, UNIQUE]
active: bool = True
Type checker support
DataEnum uses PEP 681 (@dataclass_transform) so type checkers (mypy, pyright, ty) understand the constructor signature generated from your annotations:
Currency(symbol="$", name="US Dollar", code="USD") # type checker knows these kwargs
Currency(symbol="$") # type checker flags missing args
No-data enums
class Direction(DataEnum):
__members__ = ("NORTH", "SOUTH", "EAST", "WEST")
Direction.NORTH = Direction()
Direction.SOUTH = Direction()
Direction.EAST = Direction()
Direction.WEST = Direction()
All members (in declaration order)
Currency.members # (Currency.USD, Currency.EUR, Currency.GBP)
Thread safety
DataEnum is safe for use with free-threaded Python (3.14t, no-GIL). All runtime operations — get(), filter(), attribute access, iteration — are read-only on frozen data structures. Define your enum members at module load time (the normal usage pattern), and they are safe to access concurrently from any number of threads.
Safety
Members are immutable:
Currency.USD.name = "Bitcoin" # raises AttributeError
Duplicate unique values are rejected:
Currency.GBP = Currency(symbol="£", name="Pound", code="EUR") # raises ConfigurationError
All declared members must be assigned before use:
class Color(DataEnum):
__members__ = ("RED", "BLUE")
name: str
Color.RED = Color(name="Red")
Color.get("RED") # raises ConfigurationError (BLUE not yet assigned)
Development
Set up the development environment:
make setup
source .venv/bin/activate
Run the full pipeline:
make
| Task | Command |
|---|---|
| Full pipeline | make (sync, configure, format, lint, check, test) |
| Format | make format |
| Lint | make lint (format first!) |
| Type check | make check |
| Test | make test |
License
Licensed under the Apache License, Version 2.0.
Metadata
Release files for data-enum 3.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| data_enum-3.0.1.tar.gz | 15.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| data_enum-3.0.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.5 kB
Release files / data_enum-3.0.1.tar.gz
| Download URL | data_enum-3.0.1.tar.gz |
|---|---|
| Size | 15.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7933241ffee842c48eeaca7f04c4760290a910d39fbc8e6ee903f13f94b0c4e9
|
|
BLAKE2b-256 checksum How to use checksums |
6003f08db10184860db285a9a9d6668601e4524e7c7131b4ac0b208f3b6a22f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Release files / data_enum-3.0.1-py3-none-any.whl
| Download URL | data_enum-3.0.1-py3-none-any.whl |
|---|---|
| Size | 16.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
f3e0032086381f5d5944e152ce5881af6847a77844991b86bb6042f471ee742e
|
|
BLAKE2b-256 checksum How to use checksums |
24fcb486cb6b1a383d729141620f41cc7d94bbaf0faf79142bbd9321071d23c1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Security for data-enum 3.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.