CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-proto-plus

Beautiful, Pythonic protocol buffers that make protocol buffer message classes behave like native Python types

Pending
Overview
Eval results
Files

enum-system.mddocs/

Enum System

The Enum system provides protocol buffer enums that behave like native Python enums while maintaining full compatibility with protocol buffer serialization and integer operations. Proto-plus enums extend Python's IntEnum to provide seamless integration with both Python code and protocol buffer wire format.

Capabilities

Enum Definition

Define protocol buffer enums using the proto.Enum base class.

class Enum(enum.IntEnum, metaclass=ProtoEnumMeta):
    """
    A enum object that also builds a protobuf enum descriptor.
    
    Inherits from enum.IntEnum, providing integer compatibility while
    generating the necessary protocol buffer enum descriptor.
    """
    
    def __hash__(self): ...
    def __eq__(self, other): ...
    def __ne__(self, other): ...
    def __lt__(self, other): ...
    def __le__(self, other): ...
    def __ge__(self, other): ...
    def __gt__(self, other): ...

Example usage:

class Status(proto.Enum):
    UNKNOWN = 0
    ACTIVE = 1
    INACTIVE = 2
    PENDING = 3

class Priority(proto.Enum):
    LOW = 1
    MEDIUM = 2
    HIGH = 3
    CRITICAL = 4

# Use in message definitions
class Task(proto.Message):
    title = proto.Field(proto.STRING, number=1)
    status = proto.Field(Status, number=2)
    priority = proto.Field(Priority, number=3)

Enum Usage and Behavior

Proto-plus enums behave like native Python enums with additional integer compatibility.

# Create enum values
status = Status.ACTIVE
priority = Priority.HIGH

# Integer compatibility
print(status == 1)        # True
print(priority > 2)       # True  
print(int(status))        # 1

# String representation
print(status.name)        # "ACTIVE"
print(status.value)       # 1
print(str(status))        # "Status.ACTIVE"

# Comparison operations
print(Priority.HIGH > Priority.LOW)     # True
print(Status.ACTIVE != Status.INACTIVE) # True

# Enum iteration
for status in Status:
    print(f"{status.name}: {status.value}")

# Enum lookup
status_by_value = Status(1)              # Status.ACTIVE
status_by_name = Status['ACTIVE']        # Status.ACTIVE

Message Integration

Enums integrate seamlessly with proto-plus messages.

class OrderStatus(proto.Enum):
    DRAFT = 0
    SUBMITTED = 1 
    PROCESSING = 2
    SHIPPED = 3
    DELIVERED = 4
    CANCELLED = 5

class Order(proto.Message):
    order_id = proto.Field(proto.STRING, number=1)
    status = proto.Field(OrderStatus, number=2)
    items = proto.RepeatedField(proto.STRING, number=3)

# Create and manipulate orders
order = Order(
    order_id="ORD-001",
    status=OrderStatus.DRAFT,
    items=["item1", "item2"]
)

# Update status
order.status = OrderStatus.SUBMITTED

# Check status
if order.status == OrderStatus.PROCESSING:
    print("Order is being processed")

# Conditional logic
if order.status >= OrderStatus.SHIPPED:
    print("Order has shipped")

JSON and Dictionary Serialization

Enums serialize appropriately in JSON and dictionary formats.

class Color(proto.Enum):
    RED = 1
    GREEN = 2  
    BLUE = 3

class Product(proto.Message):
    name = proto.Field(proto.STRING, number=1)
    color = proto.Field(Color, number=2)

product = Product(name="Widget", color=Color.RED)

# JSON serialization with enum as integer (default)
json_str = Product.to_json(product)
# {"name": "Widget", "color": 1}

# JSON serialization with enum as string
json_str = Product.to_json(product, use_integers_for_enums=False)  
# {"name": "Widget", "color": "RED"}

# Dictionary conversion
product_dict = Product.to_dict(product)
# {"name": "Widget", "color": 1}

# Create from dictionary with integer
product2 = Product({"name": "Gadget", "color": 2})  # color=Color.GREEN

# Create from dictionary with enum instance
product3 = Product({"name": "Tool", "color": Color.BLUE})

Repeated Enum Fields

Enums work seamlessly with repeated fields and collections.

class Permission(proto.Enum):
    READ = 1
    WRITE = 2
    EXECUTE = 4
    ADMIN = 8

class User(proto.Message):
    username = proto.Field(proto.STRING, number=1)
    permissions = proto.RepeatedField(Permission, number=2)

# Create user with multiple permissions
user = User(
    username="alice",
    permissions=[Permission.READ, Permission.WRITE]
)

# Add permissions
user.permissions.append(Permission.EXECUTE)

# Check permissions
if Permission.ADMIN in user.permissions:
    print("User has admin access")

# Iterate permissions
for perm in user.permissions:
    print(f"Permission: {perm.name}")

Map Fields with Enums

Enums can be used as both keys and values in map fields.

class Region(proto.Enum):
    US_EAST = 1
    US_WEST = 2  
    EUROPE = 3
    ASIA = 4

class ServiceLevel(proto.Enum):
    BASIC = 1
    STANDARD = 2
    PREMIUM = 3

class Configuration(proto.Message):
    # Enum as map key
    region_settings = proto.MapField(Region, proto.STRING, number=1)
    
    # Enum as map value  
    service_levels = proto.MapField(proto.STRING, ServiceLevel, number=2)

config = Configuration(
    region_settings={
        Region.US_EAST: "config-east.json",
        Region.EUROPE: "config-eu.json"
    },
    service_levels={
        "web": ServiceLevel.STANDARD,
        "api": ServiceLevel.PREMIUM  
    }
)

Enum Validation and Error Handling

Proto-plus enums provide validation and clear error messages.

class Color(proto.Enum):
    RED = 1
    GREEN = 2
    BLUE = 3

# Valid enum creation
color = Color.RED

# Invalid enum value raises ValueError
try:
    invalid_color = Color(99)  
except ValueError as e:
    print(f"Invalid enum value: {e}")

# Invalid enum name raises KeyError  
try:
    invalid_color = Color['PURPLE']
except KeyError as e:
    print(f"Invalid enum name: {e}")

# Message field validation
class Item(proto.Message):
    color = proto.Field(Color, number=1)

# Valid assignment
item = Item(color=Color.RED)
item.color = Color.BLUE

# Invalid assignment raises error
try:
    item.color = 99  # Invalid enum value
except ValueError as e:
    print(f"Field validation error: {e}")

Enum Protocol Buffer Features

Enum Options

Customize enum behavior with protocol buffer options.

class Status(proto.Enum):
    _pb_options = {"allow_alias": True}
    
    UNKNOWN = 0
    ACTIVE = 1
    ENABLED = 1  # Alias for ACTIVE
    INACTIVE = 2

Zero Values

Protocol buffer enums should have zero values for proper defaults.

# Recommended: Include zero value
class Status(proto.Enum):
    UNSPECIFIED = 0  # Zero value
    ACTIVE = 1
    INACTIVE = 2

# Usage in messages gets proper defaults
class User(proto.Message):
    name = proto.Field(proto.STRING, number=1)
    status = proto.Field(Status, number=2)  # Defaults to Status.UNSPECIFIED

user = User(name="alice")
print(user.status)  # Status.UNSPECIFIED

Install with Tessl CLI

npx tessl i tessl/pypi-proto-plus

docs

enum-system.md

field-system.md

index.md

marshal-system.md

message-system.md

module-system.md

tile.json