class PersonSQLite(BaseAggregate): first_name = String(max_length=50, required=True) last_name = String(max_length=50, required=True) age = Integer(default=21) class Meta: provider = "sqlite"
class Registered(BaseEvent): id = Identifier(identifier=True) email = String() name = String() class Meta: aggregate_cls = User
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 Author(BaseEntity): first_name = String(required=True, max_length=25) last_name = String(max_length=25) account = Reference("Account") class Meta: aggregate_cls = Account
class DbPerson(BaseEntity): first_name = String(max_length=50, required=True) last_name = String(max_length=50) age = Integer(default=21) class Meta: schema_name = "pepes"
class OrderedPerson(BaseEntity): 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 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): email = String() name = String() password_hash = String() @classmethod def register(cls, command: Registered) -> User: user = cls( id=command.id, email=command.email, name=command.name, password_hash=command.password_hash, ) user.raise_( Registered( id=command.id, email=command.email, name=command.name, password_hash=command.password_hash, ) ) current_domain.repository_for(User).add(user) return user
class Person(BaseAggregate): first_name = String(max_length=50, required=True) last_name = String(max_length=50, required=True) age = Integer(default=21) @classmethod def add_newcomer(cls, person_dict): """Factory method to add a new Person to the system""" newcomer = Person( first_name=person_dict["first_name"], last_name=person_dict["last_name"], age=person_dict["age"], ) # Publish Event via the domain current_domain.publish( PersonAdded( id=newcomer.id, first_name=newcomer.first_name, last_name=newcomer.last_name, age=newcomer.age, ) ) return newcomer
class SendEmailCommand(BaseCommand): to = String() subject = String() content = String() class Meta: aggregate_cls = SendEmail
class Registered(BaseEvent): id = Identifier() email = String() name = String() password_hash = String() class Meta: aggregate_cls = User
class PersonAdded(BaseEvent): id = Auto(identifier=True) first_name = String(max_length=50, required=True) last_name = String(max_length=50, required=True) age = Integer(default=21) class Meta: aggregate_cls = Person
class Post(BaseAggregate): title = String(required=True, max_length=1000) slug = String(required=True, max_length=1024) content = Text(required=True) posted_at = DateTime(required=True, default=datetime.now()) meta = HasOne("tests.unit_of_work.aggregate_elements.PostMeta") comments = HasMany("tests.unit_of_work.aggregate_elements.Comment")
class Post(BaseAggregate): title = String(required=True, max_length=1000) slug = String(required=True, max_length=1024) content = Text(required=True) posted_at = DateTime(required=True, default=datetime.now()) post_meta = HasOne("tests.repository.child_entities.PostMeta") comments = HasMany("tests.repository.child_entities.Comment")
class Registered(BaseEvent): user_id = Identifier() email = String() name = String() password_hash = String() class Meta: stream_name = "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 Author(BaseEntity): first_name = String(required=True, max_length=25) last_name = String(max_length=25) posts = HasMany("tests.aggregate.elements.Post") account = Reference("tests.aggregate.elements.Account") class Meta: aggregate_cls = Account
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 User(BaseAggregate): name = String(max_length=50, required=True) email = String(required=True) status = String(choices=UserStatus) def activate(self): self.raise_(UserActivated(user_id=self.id)) def change_name(self, name): self.raise_(UserRenamed(user_id=self.id, name=name))
class BaseEmail(BaseContainer, OptionsMixin): # FIXME Remove OptionsMixin """Base Email class that should implemented by all Domain Email Messages. This is also a marker class that is referenced when emails are registered with the domain. """ element_type = DomainObjects.EMAIL @classmethod def _default_options(cls): return [("provider", "default")] subject = String() from_email = String() to = List(content_type=String) bcc = List(content_type=String) cc = List(content_type=String) reply_to = String() # Supplied content text = Text() html = Text() # JSON data with template data = Dict() template = String() def defaults(self): """ Initialize a single email message (which can be sent to multiple recipients). """ self.to = convert_str_values_to_list(self.to) self.cc = convert_str_values_to_list(self.cc) self.bcc = convert_str_values_to_list(self.bcc) self.reply_to = ( convert_str_values_to_list(self.reply_to) if self.reply_to else self.from_email ) @property def recipients(self): """ Return a list of all recipients of the email (includes direct addressees as well as Cc and Bcc entries). """ return [email for email in (self.to + self.cc + self.bcc) if email]
class Email(BaseValueObject): """An email address value object, with two clearly identified parts: * local_part * domain_part """ # This is the external facing data attribute address = String(max_length=254, required=True) @classmethod def from_address(cls, address): """Construct an Email VO from an email address. email = Email.from_address('*****@*****.**') """ if not cls.validate(address): raise ValueError("Email address is invalid") return cls(address=address) @classmethod def validate(cls, address): """Business rules of Email address""" if (type(address) is not str or "@" not in address or address.count("@") > 1 or len(address) > 255): return False return True
class CommentVia(BaseEntity): content = Text() added_on = DateTime() posting_id = String() class Meta: aggregate_cls = PostVia
class Create(BaseCommand): id = Identifier(identifier=True) topic = String() content = Text() class Meta: aggregate_cls = Post
class Recalled(BaseEvent): email = String() sent_at = DateTime() class Meta: aggregate_cls = Email stream_name = "recalls"
class User(BaseEventSourcedAggregate): email = String() name = String() status = String(default="INACTIVE") @apply(Registered) def registered(self, _: Registered) -> None: self.status = "INACTIVE" @apply(Activated) def activated(self, _: Activated) -> None: self.status = "ACTIVE" @apply(Renamed) def renamed(self, event: Renamed) -> None: self.name = event.name
class Building(BaseValueObject): 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 Address(BaseValueObject): unit_no = String() street_no = String(required=True) street_name = String(required=True) province = String() country = String(required=True) zipcode = String(required=True)
def test_choice(self): """Test choices validations for the string field""" class StatusChoices(enum.Enum): """Set of choices for the status""" PENDING = "Pending" SUCCESS = "Success" ERROR = "Error" status = String(max_length=10, choices=StatusChoices) assert status is not None # Test loading of values to the status field assert status._load("Pending") == "Pending" with pytest.raises(ValidationError) as e_info: status._load("Failure") assert e_info.value.messages == { "unlinked": [ "Value `'Failure'` is not a valid choice. " "Must be among ['Pending', 'Success', 'Error']" ] }
class Email(BaseValueObject): REGEXP = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?" # This is the external facing data attribute address = String(max_length=254, required=True) def clean(self): """Business rules of Email address""" errors = defaultdict(list) if not bool(re.match(Email.REGEXP, self.address)): errors["address"].append("is invalid") return errors