def test_that_only_ints_or_strings_are_allowed_in_identifiers(): identifier = Identifier() invalid_values = [42.0, {"a": 1}, ["a", "b"], True, datetime.utcnow()] for value in invalid_values: with pytest.raises(ValidationError): identifier._load(value)
def test_string_identifiers_are_preserved_as_strings_in_as_dict(): identifier = Identifier() value = identifier._load("42") assert isinstance(value, str) assert identifier.as_dict(value) == "42"
def test_int_identifiers_are_preserved_as_ints_in_as_dict(): identifier = Identifier() value = identifier._load(42) assert isinstance(value, int) assert identifier.as_dict(value) == 42
def test_UUID_identifiers_are_converted_into_strings_in_as_dict(): uuid_val = uuid4() identifier = Identifier() value = identifier._load(uuid_val) assert isinstance(value, UUID) assert identifier.as_dict(value) == str(uuid_val)
class User(BaseEventSourcedAggregate): user_id = Identifier(identifier=True) email = String() name = String() password_hash = String() address = String() is_registered = Boolean() @classmethod def register(cls, command: Register) -> User: user = cls( user_id=command.user_id, email=command.email, name=command.name, password_hash=command.password_hash, ) user.raise_( Registered( user_id=command.user_id, email=command.email, name=command.name, password_hash=command.password_hash, )) return user @apply(Registered) def registered(self, _: Registered) -> None: self.is_registered = True
class User(BaseEventSourcedAggregate): user_id = Identifier(identifier=True) name = String(max_length=50, required=True) email = String(required=True) status = String(choices=UserStatus) @classmethod def register(cls, user_id, name, email): user = cls(user_id=user_id, name=name, email=email) user.raise_(UserRegistered(user_id=user_id, name=name, email=email)) return user def activate(self): self.raise_(UserActivated(user_id=self.user_id)) def change_name(self, name): self.raise_(UserRenamed(user_id=self.user_id, name=name)) @apply(UserRegistered) def registered(self, _: UserRegistered): self.status = UserStatus.INACTIVE.value @apply(UserActivated) def activated(self, _: UserActivated): self.status = UserStatus.ACTIVE.value @apply(UserRenamed) def renamed(self, event: UserRenamed): self.name = event.name
class Registered(BaseEvent): id = Identifier(identifier=True) email = String() name = String() class Meta: aggregate_cls = User
class Create(BaseCommand): id = Identifier(identifier=True) topic = String() content = Text() class Meta: aggregate_cls = Post
class Registered(BaseEvent): user_id = Identifier() email = String() name = String() password_hash = String() class Meta: stream_name = "user"
class Registered(BaseEvent): id = Identifier() email = String() name = String() password_hash = String() class Meta: aggregate_cls = User
class OrderedPerson(BaseView): person_id = Identifier(identifier=True) first_name = String(max_length=50, required=True) last_name = String(max_length=50) age = Integer(default=21) class Meta: order_by = "first_name"
class DbPerson(BaseView): person_id = Identifier(identifier=True) first_name = String(max_length=50, required=True) last_name = String(max_length=50) age = Integer(default=21) class Meta: schema_name = "peoples"
class Subscribed(BaseEvent): """An event generated by an external system in its own stream, that is consumed and stored as part of the User aggregate. """ id = Identifier() class Meta: stream_name = "subscriptions"
class Building(BaseView): building_id = Identifier(identifier=True) name = String(max_length=50) floors = Integer() status = String(choices=BuildingStatus) def defaults(self): if not self.status: if self.floors == 4: self.status = BuildingStatus.DONE.value else: self.status = BuildingStatus.WIP.value def clean(self): errors = defaultdict(list) if self.floors >= 4 and self.status != BuildingStatus.DONE.value: errors["status"].append("should be DONE") return errors
class User(BaseEventSourcedAggregate): user_id = Identifier(identifier=True) email = String() name = String() password_hash = String() address = String() is_registered = Boolean() @classmethod def register(cls, command: Register) -> User: user = cls( user_id=command.user_id, email=command.email, name=command.name, password_hash=command.password_hash, ) user.raise_( Registered( user_id=command.user_id, email=command.email, name=command.name, password_hash=command.password_hash, ) ) return user def change_address(self, address: String) -> None: if address != self.address: self.address = address self.raise_(AddressChanged(user_id=self.user_id, address=address)) @apply(Registered) def registered(self, event: Registered) -> None: self.is_registered = True @apply(AddressChanged) def address_changed(self, event: AddressChanged) -> None: self.address = event.address
class Activated(BaseEvent): id = Identifier(required=True) class Meta: aggregate_cls = User
class Renamed(BaseEvent): id = Identifier(required=True) name = String(required=True, max_length=50) class Meta: aggregate_cls = User
class Registered(BaseEvent): id = Identifier() email = String() name = String() password_hash = String()
class Activated(BaseEvent): id = Identifier() activated_at = DateTime()
class User(BaseEventSourcedAggregate): id = Identifier(identifier=True) email = String() name = String()
class PersonAdded(BaseEvent): id = Identifier(required=True) email = String(max_length=255, required=True) first_name = String(max_length=50, required=True) last_name = String(max_length=50, required=True) age = Integer(default=21)
class Activate(BaseCommand): user_id = Identifier()
class Register(BaseCommand): user_id = Identifier() email = String()
class LoggedIn(BaseEvent): id = Identifier() activated_at = DateTime() class Meta: aggregate_cls = User
class Register(BaseCommand): user_id = Identifier() email = String() name = String() password_hash = String()
class Published(BaseEvent): id = Identifier(required=True) published_time = DateTime(default=datetime.utcnow) class Meta: aggregate_cls = Post
class Published(BaseEvent): id = Identifier(required=True) published_time = DateTime(default=datetime.utcnow)
class Register(BaseCommand): user_id = Identifier() email = String() class Meta: aggregate_cls = User
class Created(BaseEvent): id = Identifier(identifier=True) topic = String() content = Text()
class Activate(BaseCommand): user_id = Identifier() class Meta: aggregate_cls = User