Skip to content

Enhanced Recursive Type Conversion for DCEvent

Choose a tag to compare

@vadikko2 vadikko2 released this 23 Jan 22:27
· 23 commits to master since this release
a845305

πŸŽ‰ New Features

Enhanced Recursive Type Conversion for DCEvent

This release introduces significant improvements to the DCEvent.from_dict() and DCEvent.to_dict() methods by integrating the dataclass-wizard library. This enhancement provides robust recursive type conversion for complex nested data structures.

Key Improvements:

  • Automatic Type Conversion: DCEvent.from_dict() now automatically converts:

    • String representations of UUIDs to uuid.UUID objects
    • ISO format datetime strings to datetime.datetime objects
    • Nested dictionaries to nested DCEvent dataclass instances
    • Lists containing UUIDs, datetimes, or nested dataclasses
    • Dictionary values with complex types
  • Improved Serialization: DCEvent.to_dict() now uses dataclass-wizard's asdict() for better handling of nested structures and type serialization.

Supported Conversions:

βœ… UUID Conversion

  • String UUIDs β†’ uuid.UUID objects
  • Works recursively in nested structures, lists, and dictionaries

βœ… Datetime Conversion

  • ISO format strings β†’ datetime.datetime objects
  • Supports timezone-aware datetimes
  • Works recursively in nested structures

βœ… Nested Dataclasses

  • Dictionary β†’ Nested DCEvent instances
  • Deeply nested structures are fully supported
  • Works with both DCDomainEvent and DCNotificationEvent

βœ… Collections

  • Lists of UUIDs, datetimes, or nested dataclasses
  • Dictionaries with complex value types
  • Empty collections are handled correctly

Example Usage:

from cqrs.events.event import DCDomainEvent
import dataclasses
import uuid
import datetime

@dataclasses.dataclass(frozen=True)
class UserEvent(DCDomainEvent):
    user_id: uuid.UUID
    created_at: datetime.datetime
    metadata: dict

# Now you can create events from dictionaries with string representations
event = UserEvent.from_dict(
    user_id="550e8400-e29b-41d4-a716-446655440000",  # String UUID
    created_at="2024-01-15T10:30:00+00:00",  # ISO datetime string
    metadata={"key": "value"}
)

# Type conversion happens automatically!
assert isinstance(event.user_id, uuid.UUID)
assert isinstance(event.created_at, datetime.datetime)

πŸ“¦ Dependencies

  • Added: dataclass-wizard==0.* - Provides recursive type conversion capabilities

πŸ§ͺ Testing

Comprehensive test coverage has been added with over 600 lines of tests covering:

  • Basic type conversions
  • UUID and datetime conversions
  • Nested dataclass conversions
  • List and dictionary conversions
  • Complex nested structures
  • Round-trip conversions (to_dict β†’ from_dict)
  • Both Domain and Notification event types

πŸ”§ Technical Details

Changed Methods:

  • DCEvent.from_dict(): Now uses fromdict() from dataclass-wizard instead of direct dataclass instantiation
  • DCEvent.to_dict(): Now uses asdict() from dataclass-wizard instead of dataclasses.asdict()

Backward Compatibility:

βœ… Fully backward compatible - All existing code continues to work without changes. The new functionality enhances type conversion but maintains the same API.

πŸ“ Migration Guide

No migration required! This is a drop-in enhancement. However, you can now take advantage of automatic type conversion:

Before (still works):

event = UserEvent.from_dict(
    user_id=uuid.uuid4(),  # Already a UUID object
    created_at=datetime.datetime.now(),  # Already a datetime object
    metadata={"key": "value"}
)

After (new capability):

event = UserEvent.from_dict(
    user_id="550e8400-e29b-41d4-a716-446655440000",  # String UUID - auto-converted!
    created_at="2024-01-15T10:30:00+00:00",  # ISO string - auto-converted!
    metadata={"key": "value"}
)

πŸ› Bug Fixes

  • Improved handling of nested dataclass structures in from_dict() method
  • Better serialization of complex types in to_dict() method