Advanced Enumerations (compatible with Python's stdlib Enum), NamedTuples, and NamedConstants
76
Helper functions, decorators, and classes for working with enumerations including uniqueness validation, runtime extension, conversion utilities, and named constants.
Decorator that ensures all enum members have unique values, preventing duplicate values that would create aliases.
def unique(enumeration):
"""
Decorator to ensure enum members have unique values.
Args:
enumeration: Enum class to validate
Returns:
The enum class if all values are unique
Raises:
ValueError: If duplicate values are found
"""from aenum import Enum, unique
@unique
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# CRIMSON = 1 # Would raise ValueError: duplicate value found for 'CRIMSON': 1
# Without decorator, duplicates create aliases
class Status(Enum):
ACTIVE = 1
RUNNING = 1 # This creates an alias: Status.RUNNING is Status.ACTIVE
STOPPED = 2
print(Status.ACTIVE is Status.RUNNING) # True (alias)Add new members to an existing enumeration after it has been created.
def extend_enum(enumeration, name, *args, **kwds):
"""
Add new members to an existing enumeration.
Args:
enumeration: Existing enum class
name (str): Name of the new member
*args: Value(s) for the new member
**kwds: Additional keyword arguments
Returns:
The new enum member
"""from aenum import Enum, extend_enum
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# Add new member after creation
extend_enum(Color, 'YELLOW', 4)
print(Color.YELLOW) # Color.YELLOW
print(Color.YELLOW.value) # 4
# Works with any enum type
from aenum import Flag
class Permission(Flag):
READ = 1
WRITE = 2
extend_enum(Permission, 'EXECUTE', 4)
combined = Permission.READ | Permission.EXECUTE
print(combined) # Permission.READ|EXECUTEExport enum members to a namespace (typically globals()) for direct access.
def export(enum_class, namespace=None):
"""
Export enum members to a namespace.
Args:
enum_class: Enum class whose members to export
namespace (dict): Target namespace (defaults to caller's globals)
"""from aenum import Enum, export
class Color(Enum):
RED = 1
GREEN = 2
BLUE = 3
# Export to current namespace
export(Color, globals())
# Now can use directly without Color prefix
print(RED) # Color.RED
print(GREEN) # Color.GREEN
print(BLUE) # Color.BLUE
# Useful in configuration modules
class Settings(Enum):
DEBUG = True
DATABASE_URL = 'postgresql://localhost/myapp'
CACHE_TIMEOUT = 300
export(Settings, globals())
# Now DEBUG, DATABASE_URL, CACHE_TIMEOUT are available directlyPlaceholder for automatic value assignment in enumerations.
class auto:
"""
Placeholder class for automatic value assignment.
Usage:
Use as a value in enum definitions to get auto-generated values.
"""from aenum import Enum, auto
class Direction(Enum):
NORTH = auto() # Gets value 1
SOUTH = auto() # Gets value 2
EAST = auto() # Gets value 3
WEST = auto() # Gets value 4
print(Direction.NORTH.value) # 1
# Custom auto value generation
class Color(Enum):
def _generate_next_value_(name, start, count, last_values):
return name.lower()
RED = auto() # Gets value 'red'
GREEN = auto() # Gets value 'green'
BLUE = auto() # Gets value 'blue'
print(Color.RED.value) # 'red'Helper class for creating enum members with keyword arguments.
class enum:
"""
Helper class for creating members with keywords.
Args:
*args: Positional arguments for the member
**kwargs: Keyword arguments for the member
"""from aenum import Enum, enum
class Planet(Enum):
MERCURY = enum(3.303e+23, 2.4397e6, name='Mercury')
VENUS = enum(4.869e+24, 6.0518e6, name='Venus')
EARTH = enum(5.976e+24, 6.37814e6, name='Earth')
def __init__(self, mass, radius, name=None):
self.mass = mass
self.radius = radius
self.display_name = name or self.name.title()
print(Planet.EARTH.display_name) # 'Earth'Base class for creating groups of named constants that cannot be changed after creation.
class NamedConstant:
"""
Base class for named constants.
Members are immutable after class creation.
"""
def __setattr__(self, name, value):
"""Prevent modification of constants."""
def __delattr__(self, name):
"""Prevent deletion of constants."""from aenum import NamedConstant
class DatabaseConfig(NamedConstant):
HOST = 'localhost'
PORT = 5432
DATABASE = 'myapp'
MAX_CONNECTIONS = 100
TIMEOUT = 30
# Access constants
print(DatabaseConfig.HOST) # 'localhost'
print(DatabaseConfig.PORT) # 5432
# Cannot modify
try:
DatabaseConfig.HOST = 'newhost' # Raises AttributeError
except AttributeError as e:
print(f"Cannot modify: {e}")
# Iteration support
for name, value in DatabaseConfig.__members__.items():
print(f"{name}: {value}")Constant = NamedConstant # Alias for shorter nameDescriptor for creating constant values in classes.
class constant:
"""
Descriptor for constant values.
Args:
value: The constant value
doc (str): Optional documentation
"""
def __init__(self, value, doc=None):
self.value = value
self.doc = doc
def __get__(self, obj, objtype=None):
return self.value
def __set__(self, obj, value):
raise AttributeError("Cannot modify constant")from aenum import constant
class MathConstants:
PI = constant(3.14159, "The ratio of a circle's circumference to its diameter")
E = constant(2.71828, "Euler's number")
GOLDEN_RATIO = constant(1.61803, "The golden ratio")
print(MathConstants.PI) # 3.14159
# Cannot modify
try:
MathConstants.PI = 3.14 # Raises AttributeError
except AttributeError as e:
print(f"Cannot modify constant: {e}")Force an item to become an enum member during class creation.
class member:
"""
Force item to become an Enum member.
Args:
value: Value to make into a member
"""Prevent attributes from becoming enum members or constants.
class skip:
"""
Prevent attributes from becoming constants/enum members.
Args:
value: Value to skip
"""
nonmember = skip # Aliasfrom aenum import Enum, member, skip
class Status(Enum):
ACTIVE = 1
INACTIVE = 2
# Force these to be members even though they might look like methods
count = member(lambda self: len(self.__class__))
# Skip these from becoming members
database_connection = skip(None)
_private_attr = skip("internal")
@skip
def helper_method(self):
return "This won't be an enum member"
print(Status.count) # Status.count
print(Status.ACTIVE.count()) # 2 (number of enum members)
print(Status.database_connection) # None (not an enum member)Enhanced property support for enumeration classes.
class property:
"""
Enhanced property for enums.
Supports enum-specific behavior.
"""
class enum_property(property):
"""
Property enabling enum members to have same-named attributes.
Deprecated: Use property instead.
"""from aenum import Enum, property
class Circle(Enum):
SMALL = 1
MEDIUM = 5
LARGE = 10
@property
def area(self):
import math
return math.pi * (self.value ** 2)
@property
def circumference(self):
import math
return 2 * math.pi * self.value
print(Circle.LARGE.area) # ~314.16
print(Circle.SMALL.circumference) # ~6.28def add_stdlib_integration():
"""Add integration with Python's standard library enum."""
def remove_stdlib_integration():
"""Remove standard library enum integration."""from aenum import add_stdlib_integration, Enum, IntEnum
import enum as stdlib_enum
# Enable stdlib compatibility
add_stdlib_integration()
# Now aenum enums work with stdlib enum functions
class Color(IntEnum):
RED = 1
GREEN = 2
BLUE = 3
print(isinstance(Color.RED, stdlib_enum.Enum)) # Truedef _reduce_ex_by_name(self, proto):
"""Pickle reducer by name for enum members."""
def make_class_unpicklable(cls):
"""Disable pickling for a class."""Function to inspect function signatures in a cross-Python-version compatible way.
def getargspec(method):
"""
Get function argument specification.
Args:
method: Function to inspect
Returns:
tuple: (args, varargs, keywords, defaults)
"""Raise an exception with a specific traceback in a Python version-compatible way.
def raise_with_traceback(exc, tb):
"""
Raise exception with traceback (Python 2/3 compatible).
Args:
exc: Exception instance to raise
tb: Traceback object
"""Raise an exception without chaining (Python 3 only).
def raise_from_none(exc):
"""
Raise exception from None (Python 3 only).
Args:
exc: Exception instance to raise
"""def bin(num, width=None):
"""
Binary representation with optional width.
Args:
num (int): Number to convert
width (int): Minimum width for output
Returns:
str: Binary representation
"""
def bit_count(num):
"""
Count the number of bits set in an integer.
Args:
num (int): Integer to count bits in
Returns:
int: Number of set bits
"""
def is_single_bit(value):
"""
Check if a number represents a single bit.
Args:
value (int): Value to check
Returns:
bool: True if value is a power of 2
"""from aenum import bin, bit_count, is_single_bit
print(bin(10)) # '0b1010'
print(bin(10, 8)) # '0b00001010'
print(bit_count(10)) # 2 (bits set in 1010)
print(is_single_bit(8)) # True (8 = 2^3)
print(is_single_bit(10)) # False (10 = 1010, multiple bits)from aenum import NamedConstant, convert, export
# Create constants from environment or config file
config_dict = {
'DEBUG': True,
'DATABASE_URL': 'postgresql://localhost/myapp',
'REDIS_URL': 'redis://localhost:6379',
'SECRET_KEY': 'your-secret-key',
'MAX_UPLOAD_SIZE': 10485760 # 10MB
}
# Convert to named constants
AppConfig = convert(config_dict, module=__name__)
# Export for easy access
export(AppConfig, globals())
# Now use directly
if DEBUG:
print(f"Database: {DATABASE_URL}")from aenum import Enum, extend_enum, auto
# Start with base permissions
class Permission(Enum):
READ = auto()
WRITE = auto()
# Dynamically add permissions based on features
features = ['admin', 'billing', 'analytics']
for feature in features:
perm_name = f"{feature.upper()}_ACCESS"
extend_enum(Permission, perm_name, auto())
print(list(Permission))
# [Permission.READ, Permission.WRITE, Permission.ADMIN_ACCESS,
# Permission.BILLING_ACCESS, Permission.ANALYTICS_ACCESS]from aenum import NamedConstant, export
class HTTPStatus(NamedConstant):
OK = 200
CREATED = 201
BAD_REQUEST = 400
UNAUTHORIZED = 401
NOT_FOUND = 404
INTERNAL_SERVER_ERROR = 500
class HTTPMethod(NamedConstant):
GET = 'GET'
POST = 'POST'
PUT = 'PUT'
DELETE = 'DELETE'
# Export all constants to module level
export(HTTPStatus, globals())
export(HTTPMethod, globals())
# Now available as module-level constants
def handle_request(method, status):
if method == GET and status == OK:
return "Success"
elif status == NOT_FOUND:
return "Resource not found"Install with Tessl CLI
npx tessl i tessl/pypi-aenumevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10