Skip to main content

An alternative to the built-in Python `enum` implementation

Project description

Data Enums

Build Status Coverage: 10%0 PyPI version

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

data_enum-3.0.0.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

data_enum-3.0.0-py3-none-any.whl (16.1 kB view details)

Uploaded Python 3

File details

Details for the file data_enum-3.0.0.tar.gz.

File metadata

  • Download URL: data_enum-3.0.0.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for data_enum-3.0.0.tar.gz
Algorithm Hash digest
SHA256 0276319a12649cf2786bc093fa7fa447ab444784cff71df7f5be839b0c8f2e24
MD5 5b6198a96ca9543de32d7a471297da6f
BLAKE2b-256 1aa8802bc1ae0b75592225871cd99459c94a5e4ec09553a1e99b03e3af928167

See more details on using hashes here.

File details

Details for the file data_enum-3.0.0-py3-none-any.whl.

File metadata

  • Download URL: data_enum-3.0.0-py3-none-any.whl
  • Upload date:
  • Size: 16.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for data_enum-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e296eb21c9e6ae04b2b36686c1155ce02dfce993a27afdb488045670427bc8ad
MD5 70ba9e04c4d494e7f9f3e0e797b27e8e
BLAKE2b-256 e4ea80d255d22c418d8e8a2b4f3ce7eab4d5e5ba8d97d44ae11beeda467fc144

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page