diff --git a/src/protean/adapters/event_store/memory.py b/src/protean/adapters/event_store/memory.py index a89b1b67..4267229a 100644 --- a/src/protean/adapters/event_store/memory.py +++ b/src/protean/adapters/event_store/memory.py @@ -4,19 +4,14 @@ from protean import BaseAggregate, BaseRepository from protean.globals import current_domain from protean.port import BaseEventStore -from protean.utils import DomainObjects from protean.utils.mixins import MessageMetadata, MessageRecord class MemoryMessage(BaseAggregate, MessageRecord): - class Meta: - provider = "memory" + pass class MemoryMessageRepository(BaseRepository): - class Meta: - part_of = MemoryMessage - def is_category(self, stream_name: str) -> bool: if not stream_name: return False @@ -93,8 +88,8 @@ def __init__(self, domain, conn_info) -> None: super().__init__("Memory", domain, conn_info) self.domain = domain - self.domain._register_element(DomainObjects.AGGREGATE, MemoryMessage) - self.domain.register(MemoryMessageRepository) + self.domain.register(MemoryMessage, provider="memory") + self.domain.register(MemoryMessageRepository, part_of=MemoryMessage) def _write( self, diff --git a/src/protean/adapters/repository/__init__.py b/src/protean/adapters/repository/__init__.py index fe434c9b..28d89bda 100644 --- a/src/protean/adapters/repository/__init__.py +++ b/src/protean/adapters/repository/__init__.py @@ -75,9 +75,11 @@ def _register_repository(self, part_of, repository_cls): # } # # And repository as: + # @domain.repository(part_of=Post, database="postgresql") # class CustomPostRepository: - # class Meta: - # database = "postgresql" + # def custom_method(self): + # ... + # # The value of `database` would be `postgresql`. # # In the absence of an explicit database value, the repository is associated with "ALL" diff --git a/src/protean/container.py b/src/protean/container.py index 89a2bcdf..f6242c57 100644 --- a/src/protean/container.py +++ b/src/protean/container.py @@ -43,12 +43,15 @@ def __init__(self, opts: Union[dict, Type] = None) -> None: if not (attr[0].startswith("__") and attr[0].endswith("__")): setattr(self, attr[0], attr[1]) + self.abstract = getattr(opts, "abstract", None) or False elif isinstance(opts, dict): for opt_name, opt_value in opts.items(): setattr(self, opt_name, opt_value) - # Common Meta attributes - self.abstract = getattr(opts, "abstract", None) or False + self.abstract = opts.get("abstract", None) or False + else: + # Common Meta attributes + self.abstract = getattr(opts, "abstract", None) or False def __setattr__(self, __name: str, __value: Any) -> None: # Ignore if `_opts` is being set @@ -88,23 +91,10 @@ def __init_subclass__(subclass) -> None: Args: subclass (Protean Element): Subclass to initialize with metadata """ - # Retrieve inner Meta class - # Gather `Meta` class/object if defined - options = getattr(subclass, "Meta", None) - - # Ensure that options are defined in this element class - # and not in one of its base class, by checking if the parent of the - # inner Meta class is the subclass being initialized - # - # PEP-3155 https://www.python.org/dev/peps/pep-3155/ - # `__qualname__` contains the Inner class name in the form of a dot notation: - # .. - if options and options.__qualname__.split(".")[-2] == subclass.__name__: - subclass.meta_ = Options(options) - else: - subclass.meta_ = Options() + if not hasattr(subclass, "meta_"): + setattr(subclass, "meta_", Options()) - # Assign default options for remaining items + # Assign default options subclass._set_defaults() super().__init_subclass__() @@ -116,11 +106,8 @@ def _set_defaults(cls): # Element Roots are `Event`, `Subscriber`, `Repository`, and so on. for key, default in cls._default_options(): # FIXME Should the `None` check be replaced with a SENTINEL check? - if hasattr(cls.meta_, key) and getattr(cls.meta_, key) is not None: - value = getattr(cls.meta_, key) - else: - value = default - setattr(cls.meta_, key, value) + if not (hasattr(cls.meta_, key) and getattr(cls.meta_, key) is not None): + setattr(cls.meta_, key, default) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -186,7 +173,7 @@ class BaseContainer(metaclass=ContainerMeta): def __new__(cls, *args, **kwargs): if cls is BaseContainer: - raise TypeError("BaseContainer cannot be instantiated") + raise NotSupportedError("BaseContainer cannot be instantiated") return super().__new__(cls) def __init__(self, *template, **kwargs): # noqa: C901 diff --git a/src/protean/core/aggregate.py b/src/protean/core/aggregate.py index 7bdebfdc..39be2661 100644 --- a/src/protean/core/aggregate.py +++ b/src/protean/core/aggregate.py @@ -5,6 +5,7 @@ from protean.container import EventedMixin from protean.core.entity import BaseEntity +from protean.exceptions import NotSupportedError from protean.fields import Integer from protean.utils import DomainObjects, derive_element_class, inflection @@ -39,15 +40,12 @@ class Dog: def __new__(cls, *args, **kwargs): if cls is BaseAggregate: - raise TypeError("BaseAggregate cannot be instantiated") + raise NotSupportedError("BaseAggregate cannot be instantiated") return super().__new__(cls) # Track current version of Aggregate _version = Integer(default=-1) - class Meta: - abstract = True - def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/src/protean/core/application_service.py b/src/protean/core/application_service.py index 130ade2f..f41af0dd 100644 --- a/src/protean/core/application_service.py +++ b/src/protean/core/application_service.py @@ -1,6 +1,7 @@ import logging from protean.container import Element, OptionsMixin +from protean.exceptions import NotSupportedError from protean.utils import DomainObjects, derive_element_class logger = logging.getLogger(__name__) @@ -20,12 +21,9 @@ class BaseApplicationService(Element, OptionsMixin): element_type = DomainObjects.APPLICATION_SERVICE - class Meta: - abstract = True - def __new__(cls, *args, **kwargs): if cls is BaseApplicationService: - raise TypeError("BaseApplicationService cannot be instantiated") + raise NotSupportedError("BaseApplicationService cannot be instantiated") return object.__new__(cls, *args, **kwargs) @classmethod diff --git a/src/protean/core/command.py b/src/protean/core/command.py index f95440c3..03dab09d 100644 --- a/src/protean/core/command.py +++ b/src/protean/core/command.py @@ -1,5 +1,10 @@ from protean.container import BaseContainer, OptionsMixin -from protean.exceptions import IncorrectUsageError, InvalidDataError, ValidationError +from protean.exceptions import ( + IncorrectUsageError, + InvalidDataError, + ValidationError, + NotSupportedError, +) from protean.fields import Field from protean.reflection import _ID_FIELD_NAME, declared_fields from protean.utils import DomainObjects, derive_element_class @@ -14,8 +19,10 @@ class BaseCommand(BaseContainer, OptionsMixin): element_type = DomainObjects.COMMAND - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseCommand: + raise NotSupportedError("BaseCommand cannot be instantiated") + return super().__new__(cls) def __init_subclass__(subclass) -> None: super().__init_subclass__() diff --git a/src/protean/core/command_handler.py b/src/protean/core/command_handler.py index 128d1040..f150dca9 100644 --- a/src/protean/core/command_handler.py +++ b/src/protean/core/command_handler.py @@ -22,7 +22,7 @@ def _default_options(cls): def __new__(cls, *args, **kwargs): if cls is BaseCommandHandler: - raise TypeError("BaseCommandHandler cannot be instantiated") + raise NotSupportedError("BaseCommandHandler cannot be instantiated") return super().__new__(cls) diff --git a/src/protean/core/domain_service.py b/src/protean/core/domain_service.py index d6184a75..5d51b992 100644 --- a/src/protean/core/domain_service.py +++ b/src/protean/core/domain_service.py @@ -7,7 +7,7 @@ from protean import BaseAggregate from protean.container import Element, OptionsMixin -from protean.exceptions import IncorrectUsageError, ValidationError +from protean.exceptions import IncorrectUsageError, ValidationError, NotSupportedError from protean.utils import DomainObjects, derive_element_class logger = logging.getLogger(__name__) @@ -22,12 +22,9 @@ class BaseDomainService(Element, OptionsMixin): element_type = DomainObjects.DOMAIN_SERVICE - class Meta: - abstract = True - def __new__(cls, *args, **kwargs): if cls is BaseDomainService: - raise TypeError("BaseDomainService cannot be instantiated") + raise NotSupportedError("BaseDomainService cannot be instantiated") return super().__new__(cls) @classmethod diff --git a/src/protean/core/entity.py b/src/protean/core/entity.py index 2b3f71b8..4bb4759a 100644 --- a/src/protean/core/entity.py +++ b/src/protean/core/entity.py @@ -110,9 +110,6 @@ class User(BaseEntity): element_type = DomainObjects.ENTITY - class Meta: - abstract = True - def __init_subclass__(subclass) -> None: super().__init_subclass__() @@ -513,16 +510,6 @@ def _set_root_and_owner(self, root, owner): def entity_factory(element_cls, **kwargs): element_cls = derive_element_class(element_cls, BaseEntity, **kwargs) - if element_cls.meta_.abstract is True: - raise NotSupportedError( - { - "_entity": [ - f"`{element_cls.__name__}` class has been marked abstract" - f" and cannot be instantiated" - ] - } - ) - if not element_cls.meta_.part_of: raise IncorrectUsageError( { diff --git a/src/protean/core/event.py b/src/protean/core/event.py index b1116b26..d1653388 100644 --- a/src/protean/core/event.py +++ b/src/protean/core/event.py @@ -1,7 +1,7 @@ import logging from protean.container import BaseContainer, OptionsMixin -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.fields import Field from protean.reflection import _ID_FIELD_NAME, declared_fields from protean.utils import DomainObjects, derive_element_class @@ -18,8 +18,10 @@ class BaseEvent(BaseContainer, OptionsMixin): # FIXME Remove OptionsMixin element_type = DomainObjects.EVENT - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseEvent: + raise NotSupportedError("BaseEvent cannot be instantiated") + return super().__new__(cls) def __init_subclass__(subclass) -> None: super().__init_subclass__() diff --git a/src/protean/core/event_handler.py b/src/protean/core/event_handler.py index f720bba0..6c3eeb5b 100644 --- a/src/protean/core/event_handler.py +++ b/src/protean/core/event_handler.py @@ -3,7 +3,7 @@ from protean.container import Element, OptionsMixin from protean.core.event import BaseEvent -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import DomainObjects, derive_element_class, fully_qualified_name from protean.utils.mixins import HandlerMixin @@ -15,8 +15,10 @@ class BaseEventHandler(Element, HandlerMixin, OptionsMixin): element_type = DomainObjects.EVENT_HANDLER - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseEventHandler: + raise NotSupportedError("BaseEventHandler cannot be instantiated") + return super().__new__(cls) @classmethod def _default_options(cls): @@ -30,11 +32,6 @@ def _default_options(cls): ("source_stream", None), ] - def __new__(cls, *args, **kwargs): - if cls is BaseEventHandler: - raise TypeError("BaseEventHandler cannot be instantiated") - return super().__new__(cls) - def event_handler_factory(element_cls, **opts): element_cls = derive_element_class(element_cls, BaseEventHandler, **opts) diff --git a/src/protean/core/event_sourced_aggregate.py b/src/protean/core/event_sourced_aggregate.py index d4f03d6d..1f8864bd 100644 --- a/src/protean/core/event_sourced_aggregate.py +++ b/src/protean/core/event_sourced_aggregate.py @@ -8,7 +8,7 @@ from protean.container import BaseContainer, EventedMixin, IdentityMixin, OptionsMixin from protean.core.event import BaseEvent -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.fields import Field, Integer from protean.reflection import _ID_FIELD_NAME, declared_fields, has_fields, id_field from protean.utils import ( @@ -34,8 +34,10 @@ class BaseEventSourcedAggregate( # Track current version of Aggregate _version = Integer(default=-1) - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseEventSourcedAggregate: + raise NotSupportedError("BaseEventSourcedAggregate cannot be instantiated") + return super().__new__(cls) @classmethod def _default_options(cls): diff --git a/src/protean/core/event_sourced_repository.py b/src/protean/core/event_sourced_repository.py index a410c0bb..f4cbdd75 100644 --- a/src/protean/core/event_sourced_repository.py +++ b/src/protean/core/event_sourced_repository.py @@ -2,7 +2,11 @@ from protean import BaseEventSourcedAggregate from protean.container import Element, OptionsMixin -from protean.exceptions import IncorrectUsageError, ObjectNotFoundError +from protean.exceptions import ( + IncorrectUsageError, + ObjectNotFoundError, + NotSupportedError, +) from protean.fields import Identifier from protean.globals import current_domain, current_uow from protean.utils import DomainObjects, derive_element_class @@ -20,7 +24,7 @@ def _default_options(cls): def __new__(cls, *args, **kwargs): # Prevent instantiation of `BaseEventSourcedRepository itself` if cls is BaseEventSourcedRepository: - raise TypeError("BaseEventSourcedRepository cannot be instantiated") + raise NotSupportedError("BaseEventSourcedRepository cannot be instantiated") return super().__new__(cls) def __init__(self, domain) -> None: diff --git a/src/protean/core/model.py b/src/protean/core/model.py index b03232b3..2c3c8200 100644 --- a/src/protean/core/model.py +++ b/src/protean/core/model.py @@ -1,7 +1,7 @@ from abc import abstractmethod from protean.container import Element -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import DomainObjects @@ -32,7 +32,7 @@ class BaseModel(Element): def __new__(cls, *args, **kwargs): if cls is BaseModel: - raise TypeError("BaseModel cannot be instantiated") + raise NotSupportedError("BaseModel cannot be instantiated") return super().__new__(cls) @classmethod diff --git a/src/protean/core/repository.py b/src/protean/core/repository.py index 2fde49c7..d7532e5d 100644 --- a/src/protean/core/repository.py +++ b/src/protean/core/repository.py @@ -3,7 +3,7 @@ from functools import lru_cache from protean.container import Element, OptionsMixin -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.fields import HasMany, HasOne from protean.globals import current_domain from protean.reflection import association_fields, has_association_fields @@ -39,7 +39,7 @@ def _default_options(cls): def __new__(cls, *args, **kwargs): # Prevent instantiation of `BaseRepository itself` if cls is BaseRepository: - raise TypeError("BaseRepository cannot be instantiated") + raise NotSupportedError("BaseRepository cannot be instantiated") return super().__new__(cls) def __init__(self, domain, provider) -> None: diff --git a/src/protean/core/serializer.py b/src/protean/core/serializer.py index dd2e50d7..8b54f9bd 100644 --- a/src/protean/core/serializer.py +++ b/src/protean/core/serializer.py @@ -192,7 +192,7 @@ class Address(BaseSerializer): def __new__(cls, *args, **kwargs): if cls is BaseSerializer: - raise TypeError("BaseSerializer cannot be instantiated") + raise NotSupportedError("BaseSerializer cannot be instantiated") return super().__new__(cls) diff --git a/src/protean/core/subscriber.py b/src/protean/core/subscriber.py index eb5fb1f8..49652cd9 100644 --- a/src/protean/core/subscriber.py +++ b/src/protean/core/subscriber.py @@ -5,7 +5,7 @@ from protean.container import Element, OptionsMixin from protean.core.event import BaseEvent -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import DomainObjects, derive_element_class logger = logging.getLogger(__name__) @@ -20,15 +20,15 @@ class BaseSubscriber(Element, OptionsMixin): element_type = DomainObjects.SUBSCRIBER - @classmethod - def _default_options(cls): - return [("event", None), ("broker", "default")] - def __new__(cls, *args, **kwargs): if cls is BaseSubscriber: - raise TypeError("BaseSubscriber cannot be instantiated") + raise NotSupportedError("BaseSubscriber cannot be instantiated") return super().__new__(cls) + @classmethod + def _default_options(cls): + return [("event", None), ("broker", "default")] + @abstractmethod def __call__(self, event: BaseEvent) -> Optional[Any]: """Placeholder method for receiving notifications on event""" diff --git a/src/protean/core/value_object.py b/src/protean/core/value_object.py index 54e37de5..8fc37d3f 100644 --- a/src/protean/core/value_object.py +++ b/src/protean/core/value_object.py @@ -17,8 +17,10 @@ class BaseValueObject(BaseContainer, OptionsMixin): element_type = DomainObjects.VALUE_OBJECT - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseValueObject: + raise NotSupportedError("BaseValueObject cannot be instantiated") + return super().__new__(cls) def __init_subclass__(subclass) -> None: super().__init_subclass__() diff --git a/src/protean/core/view.py b/src/protean/core/view.py index 74beef3c..7257b7a0 100644 --- a/src/protean/core/view.py +++ b/src/protean/core/view.py @@ -16,8 +16,10 @@ class BaseView(BaseContainer, OptionsMixin): element_type = DomainObjects.VIEW - class Meta: - abstract = True + def __new__(cls, *args, **kwargs): + if cls is BaseView: + raise NotSupportedError("BaseView cannot be instantiated") + return super().__new__(cls) @classmethod def _default_options(cls): @@ -53,13 +55,9 @@ def __validate_id_field(subclass): setattr(subclass, _ID_FIELD_NAME, id_field.field_name) except StopIteration: - raise IncorrectUsageError( - { - "_entity": [ - f"View `{subclass.__name__}` needs to have at least one identifier" - ] - } - ) + # View does not have an ID field. An error will be thrown + # on registering the view, in the factory method. + pass @classmethod def __validate_for_basic_field_types(subclass): @@ -109,10 +107,13 @@ def __hash__(self): def view_factory(element_cls, **kwargs): element_cls = derive_element_class(element_cls, BaseView, **kwargs) - if element_cls.meta_.abstract is True: - raise NotSupportedError( - f"{element_cls.__name__} class has been marked abstract" - f" and cannot be instantiated" + if not element_cls.meta_.abstract and not hasattr(element_cls, _ID_FIELD_NAME): + raise IncorrectUsageError( + { + "_entity": [ + f"View `{element_cls.__name__}` needs to have at least one identifier" + ] + } ) element_cls.meta_.provider = ( diff --git a/src/protean/utils/__init__.py b/src/protean/utils/__init__.py index de216355..1d283706 100644 --- a/src/protean/utils/__init__.py +++ b/src/protean/utils/__init__.py @@ -133,19 +133,21 @@ class DomainObjects(Enum): def derive_element_class(element_cls, base_cls, **opts): + from protean.container import Options + if not issubclass(element_cls, base_cls): try: new_dict = element_cls.__dict__.copy() new_dict.pop("__dict__", None) # Remove __dict__ to prevent recursion + new_dict["meta_"] = Options(opts) + element_cls = type(element_cls.__name__, (base_cls,), new_dict) except BaseException as exc: logger.debug("Error during Element registration:", repr(exc)) raise - - if hasattr(element_cls, "meta_"): - for key, value in opts.items(): - setattr(element_cls.meta_, key, value) + else: + element_cls.meta_ = Options(opts) # Assign default options for remaining items element_cls._set_defaults() diff --git a/tests/adapters/broker/celery_broker/elements.py b/tests/adapters/broker/celery_broker/elements.py index 792cc708..b939dbdf 100644 --- a/tests/adapters/broker/celery_broker/elements.py +++ b/tests/adapters/broker/celery_broker/elements.py @@ -42,9 +42,6 @@ class NotifySSOSubscriber(BaseSubscriber): that a new person was added into the system """ - class Meta: - event = PersonAdded - def __call__(self, domain_event_dict): print("Received Event: ", domain_event_dict) print("Event class: ", self.meta_.event) diff --git a/tests/adapters/broker/celery_broker/test_subscriber.py b/tests/adapters/broker/celery_broker/test_subscriber.py index b0e891ac..62c76c0b 100644 --- a/tests/adapters/broker/celery_broker/test_subscriber.py +++ b/tests/adapters/broker/celery_broker/test_subscriber.py @@ -3,19 +3,23 @@ from celery import Task from protean.adapters.broker.celery import CeleryBroker, ProteanTask -from protean.globals import current_domain -from tests.adapters.broker.celery_broker.elements import NotifySSOSubscriber, Person +from tests.adapters.broker.celery_broker.elements import ( + NotifySSOSubscriber, + Person, + PersonAdded, +) class TestSubscriberNotifications: @pytest.fixture(autouse=True) - def register(self): - current_domain.register(Person) - current_domain.register(NotifySSOSubscriber) + def register(self, test_domain): + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) + test_domain.register(NotifySSOSubscriber, event=PersonAdded) @pytest.fixture - def broker(self): - return current_domain.brokers["default"] + def broker(self, test_domain): + return test_domain.brokers["default"] @pytest.fixture def decorated_task_obj(self, broker): diff --git a/tests/adapters/broker/celery_broker/tests.py b/tests/adapters/broker/celery_broker/tests.py index acc98863..ec084589 100644 --- a/tests/adapters/broker/celery_broker/tests.py +++ b/tests/adapters/broker/celery_broker/tests.py @@ -27,8 +27,8 @@ class TestEventProcessing: @pytest.fixture(autouse=True) def register(self): current_domain.register(Person) - current_domain.register(PersonAdded) - current_domain.register(NotifySSOSubscriber) + current_domain.register(PersonAdded, part_of=Person) + current_domain.register(NotifySSOSubscriber, event=PersonAdded) @pytest.mark.xfail @patch.object(CeleryBroker, "publish") diff --git a/tests/adapters/broker/redis_broker/elements.py b/tests/adapters/broker/redis_broker/elements.py index b374078f..b939dbdf 100644 --- a/tests/adapters/broker/redis_broker/elements.py +++ b/tests/adapters/broker/redis_broker/elements.py @@ -36,18 +36,12 @@ class PersonAdded(BaseEvent): last_name = String(max_length=50, required=True) age = Integer(default=21) - class Meta: - part_of = Person - class NotifySSOSubscriber(BaseSubscriber): """Subscriber that notifies an external SSO system that a new person was added into the system """ - class Meta: - event = PersonAdded - def __call__(self, domain_event_dict): print("Received Event: ", domain_event_dict) print("Event class: ", self.meta_.event) diff --git a/tests/adapters/broker/redis_broker/tests.py b/tests/adapters/broker/redis_broker/tests.py index 0f29bd48..871a439a 100644 --- a/tests/adapters/broker/redis_broker/tests.py +++ b/tests/adapters/broker/redis_broker/tests.py @@ -6,7 +6,13 @@ from protean.adapters.broker.redis import RedisBroker from protean.globals import current_domain -from .elements import PersonAdded +from .elements import PersonAdded, Person + + +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) @pytest.mark.redis @@ -81,8 +87,6 @@ def test_retrieving_an_event_message(self, test_domain): assert message.data["id"] == event.id def test_reconstructing_an_event_object_from_message(self, test_domain): - test_domain.register(PersonAdded) - # Publish event event = PersonAdded( id="1234", diff --git a/tests/adapters/email/sendgrid_email/elements.py b/tests/adapters/email/sendgrid_email/elements.py index d0398ed1..365def73 100644 --- a/tests/adapters/email/sendgrid_email/elements.py +++ b/tests/adapters/email/sendgrid_email/elements.py @@ -56,9 +56,6 @@ class WelcomeNewPerson(BaseSubscriber): that a new person was added into the system """ - class Meta: - event = PersonAdded - def notify(self, event): email = WelcomeEmail(to=event.email, data=event.to_dict()) current_domain.send_email(email) diff --git a/tests/adapters/email/sendgrid_email/tests.py b/tests/adapters/email/sendgrid_email/tests.py index d63b98b2..71aba28d 100644 --- a/tests/adapters/email/sendgrid_email/tests.py +++ b/tests/adapters/email/sendgrid_email/tests.py @@ -11,9 +11,10 @@ class TestEmailTriggering: @patch.object(SendgridEmailProvider, "send_email") def test_that_email_is_pushed_via_aggregate_command_method(self, mock, test_domain): - test_domain.register(PersonAdded) + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) test_domain.register(WelcomeEmail) - test_domain.register(WelcomeNewPerson) + test_domain.register(WelcomeNewPerson, event=PersonAdded) Person.add_newcomer( { @@ -26,9 +27,10 @@ def test_that_email_is_pushed_via_aggregate_command_method(self, mock, test_doma mock.assert_called_once() def test_that_sendgrid_email_method_is_called(self, mocker, test_domain): - test_domain.register(PersonAdded) + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) test_domain.register(WelcomeEmail) - test_domain.register(WelcomeNewPerson) + test_domain.register(WelcomeNewPerson, event=PersonAdded) spy = mocker.spy(SendgridEmailProvider, "send_email") diff --git a/tests/adapters/model/dict_model/elements.py b/tests/adapters/model/dict_model/elements.py index eefd9954..a1acd819 100644 --- a/tests/adapters/model/dict_model/elements.py +++ b/tests/adapters/model/dict_model/elements.py @@ -18,9 +18,6 @@ class PersonRepository(BaseRepository): def find_adults(self, minimum_age: int = 21) -> List[Person]: return current_domain.repository_for(Person)._dao.filter(age__gte=minimum_age) - class Meta: - part_of = Person - class Email(BaseValueObject): REGEXP = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?" @@ -48,10 +45,6 @@ class Provider(BaseAggregate): class ProviderCustomModel(BaseModel): name = Text() - class Meta: - entity_cls = Provider - schema_name = "adults" - class Receiver(BaseAggregate): name = String() diff --git a/tests/adapters/model/dict_model/tests.py b/tests/adapters/model/dict_model/tests.py index 20402663..93fc2c4c 100644 --- a/tests/adapters/model/dict_model/tests.py +++ b/tests/adapters/model/dict_model/tests.py @@ -83,7 +83,9 @@ def test_conversion_from_model_to_entity(self, test_domain): class TestCustomModel: def test_that_custom_model_is_associated_with_entity(self, test_domain): test_domain.register(Provider) - test_domain.register(ProviderCustomModel) + test_domain.register( + ProviderCustomModel, entity_cls=Provider, schema_name="adults" + ) assert ( test_domain.repository_for(Provider)._model.__name__ diff --git a/tests/adapters/model/elasticsearch_model/conftest.py b/tests/adapters/model/elasticsearch_model/conftest.py index b212204c..f51d7c04 100644 --- a/tests/adapters/model/elasticsearch_model/conftest.py +++ b/tests/adapters/model/elasticsearch_model/conftest.py @@ -30,7 +30,9 @@ def setup_db(): domain.register(User) domain.register(ComplexUser) domain.register(Provider) - domain.register_model(ProviderCustomModel, entity_cls=Provider) + domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="providers" + ) domain.providers["default"]._create_database_artifacts() diff --git a/tests/adapters/model/elasticsearch_model/elements.py b/tests/adapters/model/elasticsearch_model/elements.py index 7f4953c1..5eaf2bd5 100644 --- a/tests/adapters/model/elasticsearch_model/elements.py +++ b/tests/adapters/model/elasticsearch_model/elements.py @@ -58,9 +58,6 @@ class ProviderCustomModel(BaseModel): name = Text(fields={"raw": Keyword()}) about = Text() - class Meta: - schema_name = "providers" - class Receiver(BaseAggregate): name = String() diff --git a/tests/adapters/model/elasticsearch_model/tests.py b/tests/adapters/model/elasticsearch_model/tests.py index 7bf44de7..d0479af4 100644 --- a/tests/adapters/model/elasticsearch_model/tests.py +++ b/tests/adapters/model/elasticsearch_model/tests.py @@ -93,10 +93,7 @@ class Person(BaseAggregate): name = String(max_length=50, required=True) about = Text() - class Meta: - schema_name = "people" - - test_domain.register(Person) + test_domain.register(Person, schema_name="people") model_cls = test_domain.repository_for(Person)._model assert model_cls._index._name == "people" @@ -154,10 +151,7 @@ class Person(BaseAggregate): name = String(max_length=50, required=True) about = Text() - class Meta: - schema_name = "people" - - test_domain.register(Person) + test_domain.register(Person, schema_name="people") model_cls = test_domain.repository_for(Person)._model assert model_cls._index._name == "foo_people" @@ -272,7 +266,9 @@ def test_conversation_from_model_to_entity(self, test_domain): class TestCustomModel: def test_that_custom_model_can_be_associated_with_entity(self, test_domain): test_domain.register(Provider) - test_domain.register_model(ProviderCustomModel, entity_cls=Provider) + test_domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="providers" + ) model_cls = test_domain.repository_for(Provider)._model assert model_cls.__name__ == "ProviderCustomModel" @@ -281,7 +277,9 @@ def test_that_explicit_schema_name_takes_precedence_over_generated( self, test_domain ): test_domain.register(Provider) - test_domain.register_model(ProviderCustomModel, entity_cls=Provider) + test_domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="providers" + ) # FIXME Should schema name be equated to the overridden name in the model? assert Provider.meta_.schema_name == "provider" @@ -292,7 +290,9 @@ def test_that_explicit_schema_name_takes_precedence_over_generated( def test_that_custom_model_is_persisted_via_dao(self, test_domain): test_domain.register(Provider) - test_domain.register_model(ProviderCustomModel, entity_cls=Provider) + test_domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="providers" + ) provider_dao = test_domain.repository_for(Provider)._dao provider = provider_dao.create(name="John", about="Me, Myself, and Jane") @@ -300,7 +300,9 @@ def test_that_custom_model_is_persisted_via_dao(self, test_domain): def test_that_custom_model_is_retrievable_via_dao(self, test_domain): test_domain.register(Provider) - test_domain.register_model(ProviderCustomModel, entity_cls=Provider) + test_domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="providers" + ) provider_dao = test_domain.repository_for(Provider)._dao provider = provider_dao.create(name="John", about="Me, Myself, and Jane") diff --git a/tests/adapters/model/sqlalchemy_model/postgresql/conftest.py b/tests/adapters/model/sqlalchemy_model/postgresql/conftest.py index 64c9d26b..8f81a146 100644 --- a/tests/adapters/model/sqlalchemy_model/postgresql/conftest.py +++ b/tests/adapters/model/sqlalchemy_model/postgresql/conftest.py @@ -40,7 +40,9 @@ def setup_db(): domain.register(ListUser) domain.register(IntegerListUser) - domain.register_model(ProviderCustomModel, entity_cls=Provider) + domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="adults" + ) domain.repository_for(ArrayUser)._dao domain.repository_for(GenericPostgres)._dao diff --git a/tests/adapters/model/sqlalchemy_model/postgresql/elements.py b/tests/adapters/model/sqlalchemy_model/postgresql/elements.py index deebe00c..2b9692fd 100644 --- a/tests/adapters/model/sqlalchemy_model/postgresql/elements.py +++ b/tests/adapters/model/sqlalchemy_model/postgresql/elements.py @@ -47,10 +47,6 @@ class Provider(BaseAggregate): class ProviderCustomModel(BaseModel): name = Column(Text) - class Meta: - entity_cls = Provider - schema_name = "adults" - class Receiver(BaseAggregate): name = String() diff --git a/tests/adapters/model/sqlalchemy_model/postgresql/test_model.py b/tests/adapters/model/sqlalchemy_model/postgresql/test_model.py index 9a4476fb..ce444908 100644 --- a/tests/adapters/model/sqlalchemy_model/postgresql/test_model.py +++ b/tests/adapters/model/sqlalchemy_model/postgresql/test_model.py @@ -99,7 +99,9 @@ def test_conversation_from_model_to_entity(self, test_domain): @pytest.mark.postgresql class TestCustomModel: def test_that_custom_model_can_be_associated_with_entity(self, test_domain): - test_domain.register(ProviderCustomModel) + test_domain.register( + ProviderCustomModel, entity_cls=Provider, schema_name="adults" + ) model_cls = test_domain.repository_for(Provider)._model assert model_cls.__name__ == "ProviderCustomModel" diff --git a/tests/adapters/model/sqlalchemy_model/sqlite/conftest.py b/tests/adapters/model/sqlalchemy_model/sqlite/conftest.py index b280a806..87c7a80f 100644 --- a/tests/adapters/model/sqlalchemy_model/sqlite/conftest.py +++ b/tests/adapters/model/sqlalchemy_model/sqlite/conftest.py @@ -27,7 +27,9 @@ def setup_db(): domain.register(Person) domain.register(Provider) domain.register(User) - domain.register_model(ProviderCustomModel, entity_cls=Provider) + domain.register_model( + ProviderCustomModel, entity_cls=Provider, schema_name="adults" + ) domain.repository_for(ArrayUser)._dao domain.repository_for(ComplexUser)._dao diff --git a/tests/adapters/model/sqlalchemy_model/sqlite/elements.py b/tests/adapters/model/sqlalchemy_model/sqlite/elements.py index 689a6fd2..04f5203d 100644 --- a/tests/adapters/model/sqlalchemy_model/sqlite/elements.py +++ b/tests/adapters/model/sqlalchemy_model/sqlite/elements.py @@ -47,10 +47,6 @@ class Provider(BaseAggregate): class ProviderCustomModel(BaseModel): name = Column(Text) - class Meta: - entity_cls = Provider - schema_name = "adults" - class Receiver(BaseAggregate): name = String() diff --git a/tests/adapters/model/sqlalchemy_model/sqlite/test_model.py b/tests/adapters/model/sqlalchemy_model/sqlite/test_model.py index 3328f6f2..21e81104 100644 --- a/tests/adapters/model/sqlalchemy_model/sqlite/test_model.py +++ b/tests/adapters/model/sqlalchemy_model/sqlite/test_model.py @@ -99,7 +99,9 @@ def test_conversation_from_model_to_entity(self, test_domain): @pytest.mark.sqlite class TestCustomModel: def test_that_custom_model_can_be_associated_with_entity(self, test_domain): - test_domain.register(ProviderCustomModel) + test_domain.register( + ProviderCustomModel, entity_cls=Provider, schema_name="adults" + ) model_cls = test_domain.repository_for(Provider)._model assert model_cls.__name__ == "ProviderCustomModel" diff --git a/tests/adapters/repository/sqlalchemy_repo/postgresql/conftest.py b/tests/adapters/repository/sqlalchemy_repo/postgresql/conftest.py index 19a31966..8ab47513 100644 --- a/tests/adapters/repository/sqlalchemy_repo/postgresql/conftest.py +++ b/tests/adapters/repository/sqlalchemy_repo/postgresql/conftest.py @@ -27,10 +27,10 @@ def setup_db(): domain.register(Person) domain.register(User) domain.register(Post) - domain.register(Comment) + domain.register(Comment, part_of=Post) domain.register(Audit) - domain.register(Customer) domain.register(Order) + domain.register(Customer, part_of=Order) domain.repository_for(Alien)._dao domain.repository_for(ComplexUser)._dao diff --git a/tests/adapters/repository/sqlalchemy_repo/postgresql/elements.py b/tests/adapters/repository/sqlalchemy_repo/postgresql/elements.py index f13e3751..b621959a 100644 --- a/tests/adapters/repository/sqlalchemy_repo/postgresql/elements.py +++ b/tests/adapters/repository/sqlalchemy_repo/postgresql/elements.py @@ -15,8 +15,7 @@ class Person(BaseAggregate): class PersonRepository(BaseRepository): - class Meta: - part_of = Person + pass class Alien(BaseAggregate): diff --git a/tests/adapters/repository/sqlalchemy_repo/postgresql/test_associations.py b/tests/adapters/repository/sqlalchemy_repo/postgresql/test_associations.py index 92b22dd3..85d455bd 100644 --- a/tests/adapters/repository/sqlalchemy_repo/postgresql/test_associations.py +++ b/tests/adapters/repository/sqlalchemy_repo/postgresql/test_associations.py @@ -12,9 +12,6 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = "Post" - class Post(BaseAggregate): content = Text(required=True) @@ -32,7 +29,7 @@ class Audit(BaseAggregate): @pytest.mark.postgresql def test_updating_a_has_many_association(test_domain): test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) post_repo = test_domain.repository_for(Post) post = Post(content="bar") diff --git a/tests/adapters/repository/sqlalchemy_repo/postgresql/test_persisting_list_of_value_objects.py b/tests/adapters/repository/sqlalchemy_repo/postgresql/test_persisting_list_of_value_objects.py index b4693184..04313165 100644 --- a/tests/adapters/repository/sqlalchemy_repo/postgresql/test_persisting_list_of_value_objects.py +++ b/tests/adapters/repository/sqlalchemy_repo/postgresql/test_persisting_list_of_value_objects.py @@ -16,9 +16,6 @@ class Customer(BaseEntity): email = String(max_length=254, required=True) addresses = List(content_type=ValueObject(Address)) - class Meta: - part_of = "Order" - # Aggregate that encloses Customer Entity class Order(BaseAggregate): @@ -28,7 +25,7 @@ class Order(BaseAggregate): @pytest.mark.postgresql def test_persisting_and_retrieving_list_of_value_objects(test_domain): test_domain.register(Order) - test_domain.register(Customer) + test_domain.register(Customer, part_of=Order) test_domain.register(Address) order = Order( diff --git a/tests/adapters/repository/test_generic.py b/tests/adapters/repository/test_generic.py index 8374c69f..038f4473 100644 --- a/tests/adapters/repository/test_generic.py +++ b/tests/adapters/repository/test_generic.py @@ -27,9 +27,6 @@ class PersonRepository(BaseRepository): def find_adults(self, minimum_age: int = 21) -> List[Person]: return current_domain.repository_for(Person)._dao.filter(age__gte=minimum_age) - class Meta: - part_of = Person - class Email(BaseValueObject): REGEXP = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?" @@ -52,7 +49,7 @@ class User(BaseAggregate): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Person) - test_domain.register(PersonRepository) + test_domain.register(PersonRepository, part_of=Person) test_domain.register(User) diff --git a/tests/aggregate/aggregate_elements.py b/tests/aggregate/aggregate_elements.py index 077255f0..ec78f038 100644 --- a/tests/aggregate/aggregate_elements.py +++ b/tests/aggregate/aggregate_elements.py @@ -19,15 +19,9 @@ class PostMeta(BaseEntity): post = Reference(Post) - class Meta: - part_of = Post - class Comment(BaseEntity): content = Text(required=True) commented_at = DateTime(required=True, default=datetime.now()) post = Reference(Post) - - class Meta: - part_of = Post diff --git a/tests/aggregate/aggregate_elements_with_value_objects.py b/tests/aggregate/aggregate_elements_with_value_objects.py index 186a49d0..fa638597 100644 --- a/tests/aggregate/aggregate_elements_with_value_objects.py +++ b/tests/aggregate/aggregate_elements_with_value_objects.py @@ -13,9 +13,6 @@ class File(BaseValueObject): url = String(max_length=1024) type = String(max_length=15, choices=FileType) - class Meta: - part_of = "Resource" - class Resource(BaseAggregate): title = String(required=True, max_length=50) diff --git a/tests/aggregate/elements.py b/tests/aggregate/elements.py index 4a9e2de0..348e6870 100644 --- a/tests/aggregate/elements.py +++ b/tests/aggregate/elements.py @@ -55,9 +55,6 @@ class SubclassRole(Role): class AbstractRole(BaseAggregate): foo = String(max_length=25) - class Meta: - abstract = True - class ConcreteRole(AbstractRole): bar = String(max_length=25) @@ -66,46 +63,6 @@ class ConcreteRole(AbstractRole): # Aggregates to test Abstraction # END # -# Aggregates to test Meta Info overriding # START # -class DbRole(BaseAggregate): - bar = String(max_length=25) - - class Meta: - schema_name = "foosball" - - -class SqlRole(Role): - class Meta: - schema_name = "roles" - - -class DifferentDbRole(Role): - class Meta: - provider = "non-default" - - -class SqlDifferentDbRole(Role): - class Meta: - provider = "non-default-sql" - - -class OrderedRole(BaseAggregate): - bar = String(max_length=25) - - class Meta: - order_by = "bar" - - -class OrderedRoleSubclass(Role): - bar = String(max_length=25) - - class Meta: - order_by = "bar" - - -# Aggregates to test Meta Info overriding # END # - - # Aggregates to test associations # START # class Post(BaseAggregate): content = Text(required=True) @@ -119,9 +76,6 @@ class Comment(BaseEntity): post = Reference("tests.aggregate.elements.Post") - class Meta: - part_of = Post - class Account(BaseAggregate): email = String(required=True, max_length=255, unique=True, identifier=True) @@ -136,9 +90,6 @@ class Author(BaseEntity): posts = HasMany("tests.aggregate.elements.Post") account = Reference("tests.aggregate.elements.Account") - class Meta: - part_of = Account - class AccountWithId(BaseAggregate): email = String(required=True, max_length=255, unique=True) @@ -151,16 +102,10 @@ class Profile(BaseEntity): about_me = Text() account = Reference("tests.aggregate.elements.Account") - class Meta: - part_of = Account - class ProfileWithAccountId(BaseEntity): about_me = Text() account = Reference("tests.aggregate.elements.AccountWithId") - class Meta: - part_of = AccountWithId - # Aggregates to test associations # END # diff --git a/tests/aggregate/test_aggregate_abstraction.py b/tests/aggregate/test_aggregate_abstraction.py index 43b59dd4..fc538038 100644 --- a/tests/aggregate/test_aggregate_abstraction.py +++ b/tests/aggregate/test_aggregate_abstraction.py @@ -1,6 +1,5 @@ import pytest -from protean import BaseAggregate from protean.exceptions import NotSupportedError from protean.fields import String from protean.reflection import declared_fields @@ -9,9 +8,11 @@ class TestAggregateAbstraction: - def test_that_abstract_entities_cannot_be_initialized(self): + def test_that_abstract_entities_cannot_be_initialized(self, test_domain): + test_domain.register(AbstractRole, abstract=True) + with pytest.raises(NotSupportedError) as exc2: - AbstractRole(name="Titan") + AbstractRole(foo="Titan") assert exc2.value.args[0] == ( "AbstractRole class has been marked abstract" " and cannot be instantiated" ) @@ -25,12 +26,10 @@ def test_that_concrete_entities_can_be_created_from_abstract_entities_through_in assert concrete_role.foo == "Titan" def test_that_abstract_entities_can_be_created_with_annotations(self, test_domain): - class CustomBaseClass(BaseAggregate): + @test_domain.aggregate(abstract=True) + class CustomBaseClass: foo = String(max_length=25) - class Meta: - abstract = True - @test_domain.aggregate class ConcreateSubclass(CustomBaseClass): bar = String(max_length=25) diff --git a/tests/aggregate/test_aggregate_association.py b/tests/aggregate/test_aggregate_association.py index 6f8ab87a..ad5a110a 100644 --- a/tests/aggregate/test_aggregate_association.py +++ b/tests/aggregate/test_aggregate_association.py @@ -15,10 +15,10 @@ class TestHasOne: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Account) - test_domain.register(Comment) - test_domain.register(Author) test_domain.register(Post) - test_domain.register(Profile) + test_domain.register(Comment, part_of=Post) + test_domain.register(Author, part_of=Account) + test_domain.register(Profile, part_of=Account) test_domain.init(traverse=False) def test_successful_initialization_of_entity_with_has_one_association( @@ -49,9 +49,9 @@ class TestHasMany: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Account) - test_domain.register(Author) + test_domain.register(Author, part_of=Account) test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) test_domain.init(traverse=False) @pytest.fixture diff --git a/tests/aggregate/test_aggregate_association_dao.py b/tests/aggregate/test_aggregate_association_dao.py index 30fd7617..1ac5f115 100644 --- a/tests/aggregate/test_aggregate_association_dao.py +++ b/tests/aggregate/test_aggregate_association_dao.py @@ -20,9 +20,9 @@ class TestHasOne: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Account) - test_domain.register(Author) + test_domain.register(Author, part_of=Account) test_domain.register(Post) - test_domain.register(Profile) + test_domain.register(Profile, part_of=Account) def test_successful_initialization_of_entity_with_has_one_association( self, test_domain @@ -45,7 +45,7 @@ class TestHasMany: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) @pytest.fixture def persisted_post(self, test_domain): diff --git a/tests/aggregate/test_aggregate_events.py b/tests/aggregate/test_aggregate_events.py index b9d5a2b5..86ceecbf 100644 --- a/tests/aggregate/test_aggregate_events.py +++ b/tests/aggregate/test_aggregate_events.py @@ -28,21 +28,17 @@ def change_name(self, name): class UserActivated(BaseEvent): user_id = Identifier(required=True) - class Meta: - part_of = User - class UserRenamed(BaseEvent): user_id = Identifier(required=True) name = String(required=True, max_length=50) - class Meta: - part_of = User - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(User) + test_domain.register(UserActivated, part_of=User) + test_domain.register(UserRenamed, part_of=User) def test_that_aggregate_has_events_list(): diff --git a/tests/aggregate/test_aggregate_initialization.py b/tests/aggregate/test_aggregate_initialization.py index 39a9e79c..dbd1d79a 100644 --- a/tests/aggregate/test_aggregate_initialization.py +++ b/tests/aggregate/test_aggregate_initialization.py @@ -4,7 +4,7 @@ import pytest from protean import BaseEntity, BaseAggregate -from protean.exceptions import ValidationError +from protean.exceptions import ValidationError, NotSupportedError from protean.reflection import attributes, declared_fields from protean.utils import fully_qualified_name @@ -22,7 +22,7 @@ class TestAggregateStructure: def test_that_base_aggregate_cannot_be_instantiated(self): - with pytest.raises(TypeError) as exc: + with pytest.raises(NotSupportedError) as exc: BaseAggregate() assert str(exc.value) == "BaseAggregate cannot be instantiated" diff --git a/tests/aggregate/test_aggregate_reference_field.py b/tests/aggregate/test_aggregate_reference_field.py index 8b84c301..9baa2306 100644 --- a/tests/aggregate/test_aggregate_reference_field.py +++ b/tests/aggregate/test_aggregate_reference_field.py @@ -10,9 +10,9 @@ class TestReferenceFieldAssociation: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Account) - test_domain.register(Author) + test_domain.register(Author, part_of=Account) test_domain.register(Post) - test_domain.register(Profile) + test_domain.register(Profile, part_of=Account) def test_initialization_of_an_entity_containing_reference_field(self, test_domain): account = Account(email="john.doe@gmail.com", password="a1b2c3") diff --git a/tests/aggregate/test_aggregate_registration.py b/tests/aggregate/test_aggregate_registration.py index 1aa3a1a1..02d5f605 100644 --- a/tests/aggregate/test_aggregate_registration.py +++ b/tests/aggregate/test_aggregate_registration.py @@ -16,11 +16,7 @@ def test_settings_in_manual_registration(self, test_domain): class User(BaseAggregate): name = String(max_length=50) - class Meta: - provider = "foobar" - model = "UserModel" - - test_domain.register(User) + test_domain.register(User, provider="foobar", model="UserModel") assert User.meta_.provider == "foobar" assert User.meta_.model == "UserModel" @@ -30,7 +26,5 @@ def test_setting_provider_in_decorator_based_registration(self, test_domain): class User(BaseAggregate): name = String(max_length=50) - test_domain.register(User) - assert User.meta_.provider == "foobar" assert User.meta_.model == "UserModel" diff --git a/tests/aggregate/test_aggregates_with_entities.py b/tests/aggregate/test_aggregates_with_entities.py index 87448f49..e16d05ad 100644 --- a/tests/aggregate/test_aggregates_with_entities.py +++ b/tests/aggregate/test_aggregates_with_entities.py @@ -7,8 +7,8 @@ class TestAggregatesWithEntities: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Post) - test_domain.register(PostMeta) - test_domain.register(Comment) + test_domain.register(PostMeta, part_of=Post) + test_domain.register(Comment, part_of=Post) test_domain.init(traverse=False) @pytest.fixture diff --git a/tests/aggregate/test_as_dict.py b/tests/aggregate/test_as_dict.py index 6468eaa0..ebe6aa68 100644 --- a/tests/aggregate/test_as_dict.py +++ b/tests/aggregate/test_as_dict.py @@ -59,9 +59,6 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = "Post" - class Post(BaseAggregate): title = String(required=True, max_length=1000) slug = String(required=True, max_length=1024) @@ -70,7 +67,7 @@ class Post(BaseAggregate): comments = HasMany(Comment) test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) post = Post(title="Test Post", slug="test-post", content="Do Re Mi Fa") comment1 = Comment(content="first comment") @@ -95,9 +92,6 @@ class Comment(BaseEntity): content = Text(required=True) post = Reference("Post") - class Meta: - part_of = "Post" - class Post(BaseAggregate): title = String(required=True, max_length=1000) slug = String(required=True, max_length=1024) @@ -106,7 +100,7 @@ class Post(BaseAggregate): comments = HasMany(Comment) test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) test_domain.init(traverse=False) post = Post(title="Test Post", slug="test-post", content="Do Re Mi Fa") @@ -136,11 +130,8 @@ class Post(BaseAggregate): class PostMeta(BaseEntity): likes = Integer(default=0) - class Meta: - part_of = Post - test_domain.register(Post) - test_domain.register(PostMeta) + test_domain.register(PostMeta, part_of=Post) test_domain.init(traverse=False) meta = PostMeta(likes=27) diff --git a/tests/application_service/tests.py b/tests/application_service/tests.py index d7a0d2b2..d6f8e6b1 100644 --- a/tests/application_service/tests.py +++ b/tests/application_service/tests.py @@ -1,6 +1,7 @@ import pytest from protean import BaseApplicationService +from protean.exceptions import NotSupportedError from protean.utils import fully_qualified_name from .elements import DummyApplicationService @@ -8,7 +9,7 @@ class TestApplicationServiceInitialization: def test_that_base_application_service_class_cannot_be_instantiated(self): - with pytest.raises(TypeError): + with pytest.raises(NotSupportedError): BaseApplicationService() def test_that_application_service_can_be_instantiated(self): diff --git a/tests/command/test_automatic_stream_association.py b/tests/command/test_automatic_stream_association.py index 59cb2414..8c71ec36 100644 --- a/tests/command/test_automatic_stream_association.py +++ b/tests/command/test_automatic_stream_association.py @@ -33,9 +33,6 @@ class Login(BaseCommand): id = Identifier() activated_at = DateTime() - class Meta: - part_of = User - class Subscribe(BaseCommand): """An event generated by an external system in its own stream, @@ -44,9 +41,6 @@ class Subscribe(BaseCommand): id = Identifier() - class Meta: - stream_name = "subscriptions" - class Send(BaseCommand): email = String() @@ -57,10 +51,6 @@ class Recall(BaseCommand): email = String() sent_at = DateTime() - class Meta: - part_of = Email - stream_name = "recalls" - class UserCommandHandler(BaseCommandHandler): @handle(Register) @@ -93,22 +83,28 @@ def recall(self, _: Recall) -> None: @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(User) + test_domain.register(Login, part_of=User) + test_domain.register(Register, part_of=User) + test_domain.register(Activate, part_of=User) + test_domain.register(Subscribe, stream_name="subscriptions") test_domain.register(Email) + test_domain.register(Send, part_of=Email) + test_domain.register(Recall, part_of=Email, stream_name="recalls") test_domain.register(UserCommandHandler, part_of=User) test_domain.register(EmailCommandHandler, part_of=Email) def test_automatic_association_of_events_with_aggregate_and_stream(): - assert Register.meta_.part_of is None + assert Register.meta_.part_of is User assert Register.meta_.stream_name == "user" - assert Activate.meta_.part_of is None + assert Activate.meta_.part_of is User assert Activate.meta_.stream_name == "user" assert Subscribe.meta_.part_of is None assert Subscribe.meta_.stream_name == "subscriptions" - assert Send.meta_.part_of is None + assert Send.meta_.part_of is Email assert Send.meta_.stream_name == "email" assert Recall.meta_.part_of is Email diff --git a/tests/command/test_command_meta.py b/tests/command/test_command_meta.py index 61ed28a0..2bb17e50 100644 --- a/tests/command/test_command_meta.py +++ b/tests/command/test_command_meta.py @@ -37,11 +37,8 @@ def test_that_abstract_commands_can_be_defined_without_aggregate_or_stream(test_ class AbstractCommand(BaseCommand): foo = String() - class Meta: - abstract = True - try: - test_domain.register(AbstractCommand) + test_domain.register(AbstractCommand, abstract=True) except Exception: pytest.fail( "Abstract commands should be definable without being associated with an aggregate or a stream" diff --git a/tests/command_handler/test_command_handler_options.py b/tests/command_handler/test_command_handler_options.py index ba232023..39038265 100644 --- a/tests/command_handler/test_command_handler_options.py +++ b/tests/command_handler/test_command_handler_options.py @@ -22,10 +22,9 @@ class UserCommandHandlers(BaseCommandHandler): def test_aggregate_cls_specified_as_a_meta_attribute(test_domain): class UserCommandHandlers(BaseCommandHandler): - class Meta: - part_of = User + pass - test_domain.register(UserCommandHandlers) + test_domain.register(UserCommandHandlers, part_of=User) assert UserCommandHandlers.meta_.part_of == User diff --git a/tests/command_handler/test_inline_command_processing.py b/tests/command_handler/test_inline_command_processing.py index 9afca1c4..e1c8290e 100644 --- a/tests/command_handler/test_inline_command_processing.py +++ b/tests/command_handler/test_inline_command_processing.py @@ -18,9 +18,6 @@ class Register(BaseCommand): user_id = Identifier() email = String() - class Meta: - part_of = User - class UserCommandHandlers(BaseCommandHandler): @handle(Register) diff --git a/tests/command_handler/test_retrieving_handlers_by_command.py b/tests/command_handler/test_retrieving_handlers_by_command.py index 192f8071..922ddb7e 100644 --- a/tests/command_handler/test_retrieving_handlers_by_command.py +++ b/tests/command_handler/test_retrieving_handlers_by_command.py @@ -25,9 +25,6 @@ class ChangeAddress(BaseCommand): user_id = Identifier() full_address = String() - class Meta: - part_of = User - class UserCommandHandlers(BaseCommandHandler): @handle(Register) @@ -60,8 +57,11 @@ def create_new_post(self, _: Create): def test_retrieving_handler_by_command(test_domain): test_domain.register(User) + test_domain.register(Register, part_of=User) + test_domain.register(ChangeAddress, part_of=User) test_domain.register(UserCommandHandlers, part_of=User) test_domain.register(Post) + test_domain.register(Create, part_of=Post) test_domain.register(PostCommandHandler, part_of=Post) assert test_domain.command_handler_for(Register()) == UserCommandHandlers diff --git a/tests/domain/tests.py b/tests/domain/tests.py index 314c8430..1feb1902 100644 --- a/tests/domain/tests.py +++ b/tests/domain/tests.py @@ -104,9 +104,6 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = Post - # Still a string reference assert isinstance(declared_fields(Comment)["post"].to_cls, str) @@ -115,7 +112,7 @@ class Meta: ) # Comment has not been registered yet # Registering `Comment` resolves references in both `Comment` and `Post` classes - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) test_domain._resolve_references() assert declared_fields(Post)["comments"].to_cls == Comment @@ -150,10 +147,7 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = Post - - domain.register(Comment) + domain.register(Comment, part_of=Post) assert len(domain._pending_class_resolutions) == 2 assert all( @@ -179,10 +173,7 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = Post - - domain.register(Comment) + domain.register(Comment, part_of=Post) # `init` resolves references domain.init(traverse=False) @@ -214,10 +205,7 @@ class Comment(BaseEntity): post = Reference("Post") foo = Reference("Foo") - class Meta: - part_of = Post - - domain.register(Comment) + domain.register(Comment, part_of=Post) with pytest.raises(ConfigurationError) as exc: domain.init() @@ -244,11 +232,8 @@ class Comment(BaseEntity): post = Reference("Post") - class Meta: - part_of = Post - test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) test_domain._resolve_references() assert declared_fields(Post)["comments"].to_cls == Comment @@ -268,11 +253,8 @@ class Author(BaseEntity): last_name = String(max_length=25) account = Reference("Account") - class Meta: - part_of = Account - test_domain.register(Account) - test_domain.register(Author) + test_domain.register(Author, part_of=Account) test_domain._resolve_references() assert declared_fields(Account)["author"].to_cls == Author diff --git a/tests/domain_service/test_domain_service_as_callable_class.py b/tests/domain_service/test_domain_service_as_callable_class.py index 2b48284e..dd20731f 100644 --- a/tests/domain_service/test_domain_service_as_callable_class.py +++ b/tests/domain_service/test_domain_service_as_callable_class.py @@ -35,9 +35,6 @@ class OrderConfirmed(BaseEvent): order_id = Identifier(required=True) confirmed_at = DateTime(required=True) - class Meta: - part_of = "Order" - class Order(BaseAggregate): customer_id = Identifier(required=True) @@ -57,26 +54,17 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = Order - class Warehouse(BaseValueObject): location = String() contact = String() - class Meta: - part_of = "Inventory" - class StockReserved(BaseEvent): product_id = Identifier(required=True) quantity = Integer(required=True) reserved_at = DateTime(required=True) - class Meta: - part_of = "Inventory" - class Inventory(BaseAggregate): product_id = Identifier(required=True) @@ -95,9 +83,6 @@ def reserve_stock(self, quantity: int): class OrderPlacementService(BaseDomainService): - class Meta: - part_of = [Order, Inventory] - def __init__(self, order, inventories): super().__init__(*(order, inventories)) @@ -126,12 +111,12 @@ def __call__(self): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(OrderItem) - test_domain.register(Warehouse) + test_domain.register(OrderItem, part_of=Order) + test_domain.register(OrderConfirmed, part_of=Order) test_domain.register(Inventory) - test_domain.register(OrderConfirmed) - test_domain.register(StockReserved) - test_domain.register(OrderPlacementService) + test_domain.register(Warehouse, part_of=Inventory) + test_domain.register(StockReserved, part_of=Inventory) + test_domain.register(OrderPlacementService, part_of=[Order, Inventory]) test_domain.init(traverse=False) diff --git a/tests/domain_service/test_domain_service_as_instantiable_class.py b/tests/domain_service/test_domain_service_as_instantiable_class.py index ff8a4b04..bdac126b 100644 --- a/tests/domain_service/test_domain_service_as_instantiable_class.py +++ b/tests/domain_service/test_domain_service_as_instantiable_class.py @@ -35,9 +35,6 @@ class OrderConfirmed(BaseEvent): order_id = Identifier(required=True) confirmed_at = DateTime(required=True) - class Meta: - part_of = "Order" - class Order(BaseAggregate): customer_id = Identifier(required=True) @@ -57,26 +54,17 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = Order - class Warehouse(BaseValueObject): location = String() contact = String() - class Meta: - part_of = "Inventory" - class StockReserved(BaseEvent): product_id = Identifier(required=True) quantity = Integer(required=True) reserved_at = DateTime(required=True) - class Meta: - part_of = "Inventory" - class Inventory(BaseAggregate): product_id = Identifier(required=True) @@ -95,9 +83,6 @@ def reserve_stock(self, quantity: int): class OrderPlacementRegularService(BaseDomainService): - class Meta: - part_of = [Order, Inventory] - def __init__(self, order, inventories): super().__init__(*(order, inventories)) @@ -126,12 +111,12 @@ def place_order(self): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(OrderItem) - test_domain.register(Warehouse) + test_domain.register(OrderItem, part_of=Order) + test_domain.register(OrderConfirmed, part_of=Order) test_domain.register(Inventory) - test_domain.register(OrderConfirmed) - test_domain.register(StockReserved) - test_domain.register(OrderPlacementRegularService) + test_domain.register(Warehouse, part_of=Inventory) + test_domain.register(StockReserved, part_of=Inventory) + test_domain.register(OrderPlacementRegularService, part_of=[Order, Inventory]) test_domain.init(traverse=False) diff --git a/tests/domain_service/test_domain_service_with_class_methods.py b/tests/domain_service/test_domain_service_with_class_methods.py index 2841fb7e..15814c45 100644 --- a/tests/domain_service/test_domain_service_with_class_methods.py +++ b/tests/domain_service/test_domain_service_with_class_methods.py @@ -33,9 +33,6 @@ class OrderConfirmed(BaseEvent): order_id = Identifier(required=True) confirmed_at = DateTime(required=True) - class Meta: - part_of = "Order" - class Order(BaseAggregate): customer_id = Identifier(required=True) @@ -55,26 +52,17 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = Order - class Warehouse(BaseValueObject): location = String() contact = String() - class Meta: - part_of = "Inventory" - class StockReserved(BaseEvent): product_id = Identifier(required=True) quantity = Integer(required=True) reserved_at = DateTime(required=True) - class Meta: - part_of = "Inventory" - class Inventory(BaseAggregate): product_id = Identifier(required=True) @@ -93,9 +81,6 @@ def reserve_stock(self, quantity: int): class OrderPlacementService(BaseDomainService): - class Meta: - part_of = [Order, Inventory] - @classmethod def place_order(cls, order: Order, inventories: list[Inventory]): for item in order.items: @@ -115,12 +100,12 @@ def place_order(cls, order: Order, inventories: list[Inventory]): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(OrderItem) - test_domain.register(Warehouse) + test_domain.register(OrderItem, part_of=Order) + test_domain.register(OrderConfirmed, part_of=Order) test_domain.register(Inventory) - test_domain.register(OrderConfirmed) - test_domain.register(StockReserved) - test_domain.register(OrderPlacementService) + test_domain.register(Warehouse, part_of=Inventory) + test_domain.register(StockReserved, part_of=Inventory) + test_domain.register(OrderPlacementService, part_of=[Order, Inventory]) test_domain.init(traverse=False) diff --git a/tests/domain_service/test_invariants_decorator.py b/tests/domain_service/test_invariants_decorator.py index b89cc1b4..44fa9e91 100644 --- a/tests/domain_service/test_invariants_decorator.py +++ b/tests/domain_service/test_invariants_decorator.py @@ -10,9 +10,6 @@ class Aggregate2(BaseAggregate): class test_handler(BaseDomainService): - class Meta: - part_of = [Aggregate1, Aggregate2] - @invariant.pre def some_invariant_1(self): pass @@ -28,7 +25,7 @@ def __call__(self): def test_that_domain_service_has_recorded_invariants(test_domain): test_domain.register(Aggregate1) test_domain.register(Aggregate2) - test_domain.register(test_handler) + test_domain.register(test_handler, part_of=[Aggregate1, Aggregate2]) test_domain.init(traverse=False) assert len(test_handler._invariants) == 2 diff --git a/tests/domain_service/test_invariants_triggering.py b/tests/domain_service/test_invariants_triggering.py index 47228ab7..13ddc0ef 100644 --- a/tests/domain_service/test_invariants_triggering.py +++ b/tests/domain_service/test_invariants_triggering.py @@ -37,9 +37,6 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = "Order" - class OrderItemVO(BaseValueObject): product_id = Identifier(required=True) @@ -53,9 +50,6 @@ class OrderConfirmed(BaseEvent): items = List(content_type=ValueObject(OrderItemVO), required=True) confirmed_at = DateTime(required=True) - class Meta: - part_of = "Order" - class Order(BaseAggregate): customer_id = Identifier(required=True) @@ -91,18 +85,12 @@ class Warehouse(BaseValueObject): location = String() contact = String() - class Meta: - part_of = "Inventory" - class StockReserved(BaseEvent): product_id = Identifier(required=True) quantity = Integer(required=True) reserved_at = DateTime(required=True) - class Meta: - part_of = "Inventory" - class Inventory(BaseAggregate): product_id = Identifier(required=True) @@ -121,9 +109,6 @@ def reserve_stock(self, quantity: int): class OrderPlacementService(BaseDomainService): - class Meta: - part_of = [Order, Inventory] - def __init__(self, order, inventories): super().__init__(*(order, inventories)) @@ -189,12 +174,12 @@ def __call__(self): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(OrderItem) - test_domain.register(Warehouse) + test_domain.register(OrderItem, part_of=Order) + test_domain.register(OrderConfirmed, part_of=Order) test_domain.register(Inventory) - test_domain.register(OrderConfirmed) - test_domain.register(StockReserved) - test_domain.register(OrderPlacementService) + test_domain.register(Warehouse, part_of=Inventory) + test_domain.register(StockReserved, part_of=Inventory) + test_domain.register(OrderPlacementService, part_of=[Order, Inventory]) test_domain.init(traverse=False) diff --git a/tests/domain_service/tests.py b/tests/domain_service/tests.py index ef6915ee..6f7050b4 100644 --- a/tests/domain_service/tests.py +++ b/tests/domain_service/tests.py @@ -4,7 +4,7 @@ from protean import BaseAggregate, BaseDomainService from protean.core import domain_service -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.utils import fully_qualified_name @@ -17,15 +17,12 @@ class Aggregate2(BaseAggregate): class perform_something(BaseDomainService): - class Meta: - part_of = [Aggregate1, Aggregate2] - def __call__(self): print("Performing complex process...") def test_that_base_domain_service_class_cannot_be_instantiated(): - with pytest.raises(TypeError): + with pytest.raises(NotSupportedError): BaseDomainService() @@ -40,10 +37,9 @@ def test_that_domain_service_needs_to_be_associated_with_at_least_2_aggregates( with pytest.raises(IncorrectUsageError): class bad_domain_service(BaseDomainService): - class Meta: - part_of = [Aggregate1] + pass - test_domain.register(bad_domain_service) + test_domain.register(bad_domain_service, part_of=[Aggregate1]) def test_that_domain_service_is_a_callable_class(): @@ -51,7 +47,7 @@ def test_that_domain_service_is_a_callable_class(): def test_that_domain_service_can_be_registered_with_domain(test_domain): - test_domain.register(perform_something) + test_domain.register(perform_something, part_of=[Aggregate1, Aggregate2]) assert ( fully_qualified_name(perform_something) in test_domain.registry.domain_services @@ -104,6 +100,6 @@ def test_call_to_wrap_methods_with_invariant_calls(test_domain): mock_wrap = mock.Mock(return_value=perform_something) domain_service.wrap_methods_with_invariant_calls = mock_wrap - test_domain.register(perform_something) + test_domain.register(perform_something, part_of=[Aggregate1, Aggregate2]) mock_wrap.assert_called_once() diff --git a/tests/email_provider/elements.py b/tests/email_provider/elements.py index 06f7554f..2cda760b 100644 --- a/tests/email_provider/elements.py +++ b/tests/email_provider/elements.py @@ -33,9 +33,6 @@ class PersonAdded(BaseEvent): last_name = String(max_length=50, required=True) age = Integer(default=21) - class Meta: - part_of = Person - class WelcomeEmail(BaseEmail): """Emailer to welcome new additions""" @@ -65,9 +62,6 @@ class WelcomeNewPerson(BaseSubscriber): that a new person was added into the system """ - class Meta: - event = PersonAdded - def notify(self, event): email = WelcomeEmail(to=event["email"], data=event) current_domain.send_email(email) diff --git a/tests/email_provider/tests.py b/tests/email_provider/tests.py index 38d06612..8580343f 100644 --- a/tests/email_provider/tests.py +++ b/tests/email_provider/tests.py @@ -42,9 +42,10 @@ class TestEmailTriggering: @pytest.mark.xfail # `notify` methods will not be called inline. `send_email` is another notify-type method @patch.object(DummyEmailProvider, "send_email") def test_that_email_is_pushed_via_aggregate_command_method(self, mock, test_domain): - test_domain.register(PersonAdded) + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) test_domain.register(WelcomeEmail) - test_domain.register(WelcomeNewPerson) + test_domain.register(WelcomeNewPerson, event=PersonAdded) Person.add_newcomer( { diff --git a/tests/entity/associations/test_for_association_type_validation.py b/tests/entity/associations/test_for_association_type_validation.py index f25ce508..df51f537 100644 --- a/tests/entity/associations/test_for_association_type_validation.py +++ b/tests/entity/associations/test_for_association_type_validation.py @@ -14,23 +14,17 @@ class Department(BaseEntity): name = String(max_length=50) dean = HasOne("Dean") - class Meta: - part_of = University - class Dean(BaseEntity): name = String(max_length=50) age = Integer(min_value=21) - class Meta: - part_of = Department - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(University) - test_domain.register(Department) - test_domain.register(Dean) + test_domain.register(Department, part_of=University) + test_domain.register(Dean, part_of=Department) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_many_filtering.py b/tests/entity/associations/test_has_many_filtering.py index cc572b23..e1cf0150 100644 --- a/tests/entity/associations/test_has_many_filtering.py +++ b/tests/entity/associations/test_has_many_filtering.py @@ -17,14 +17,11 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = Order - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(OrderItem) + test_domain.register(OrderItem, part_of=Order) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_many_recursive.py b/tests/entity/associations/test_has_many_recursive.py index 53ddd2e4..d95cea57 100644 --- a/tests/entity/associations/test_has_many_recursive.py +++ b/tests/entity/associations/test_has_many_recursive.py @@ -16,24 +16,18 @@ class Order(BaseEntity): ordered_on = Date() items = HasMany("OrderItem") - class Meta: - part_of = Customer - class OrderItem(BaseEntity): product_id = Identifier(required=True) quantity = Float() price = Float() - class Meta: - part_of = Order - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Customer) - test_domain.register(Order) - test_domain.register(OrderItem) + test_domain.register(Order, part_of=Customer) + test_domain.register(OrderItem, part_of=Order) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_many_with_has_one.py b/tests/entity/associations/test_has_many_with_has_one.py index 2bbbfab3..8cc3e40c 100644 --- a/tests/entity/associations/test_has_many_with_has_one.py +++ b/tests/entity/associations/test_has_many_with_has_one.py @@ -14,23 +14,17 @@ class Department(BaseEntity): name = String(max_length=50) dean = HasOne("Dean") - class Meta: - part_of = University - class Dean(BaseEntity): name = String(max_length=50) age = Integer(min_value=21) - class Meta: - part_of = Department - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(University) - test_domain.register(Department) - test_domain.register(Dean) + test_domain.register(Department, part_of=University) + test_domain.register(Dean, part_of=Department) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_many_with_has_one_with_has_one.py b/tests/entity/associations/test_has_many_with_has_one_with_has_one.py index 6ea62e48..e065f6dd 100644 --- a/tests/entity/associations/test_has_many_with_has_one_with_has_one.py +++ b/tests/entity/associations/test_has_many_with_has_one_with_has_one.py @@ -14,33 +14,24 @@ class Department(BaseEntity): name = String(max_length=50) dean = HasOne("Dean") - class Meta: - part_of = University - class Dean(BaseEntity): name = String(max_length=50) age = Integer(min_value=21) office = HasOne("Office") - class Meta: - part_of = Department - class Office(BaseEntity): building = String(max_length=25) room = Integer(min_value=1) - class Meta: - part_of = Dean - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(University) - test_domain.register(Department) - test_domain.register(Dean) - test_domain.register(Office) + test_domain.register(Department, part_of=University) + test_domain.register(Dean, part_of=Department) + test_domain.register(Office, part_of=Dean) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_one_recursive.py b/tests/entity/associations/test_has_one_recursive.py index c08701d7..13fb0a29 100644 --- a/tests/entity/associations/test_has_one_recursive.py +++ b/tests/entity/associations/test_has_one_recursive.py @@ -15,23 +15,17 @@ class Dean(BaseEntity): age = Integer(min_value=21) office = HasOne("Office") - class Meta: - part_of = University - class Office(BaseEntity): building = String(max_length=25) room = Integer(min_value=1) - class Meta: - part_of = Dean - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(University) - test_domain.register(Dean) - test_domain.register(Office) + test_domain.register(Dean, part_of=University) + test_domain.register(Office, part_of=Dean) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_has_one_with_has_many.py b/tests/entity/associations/test_has_one_with_has_many.py index 9fb96c8c..399c50eb 100644 --- a/tests/entity/associations/test_has_one_with_has_many.py +++ b/tests/entity/associations/test_has_one_with_has_many.py @@ -16,24 +16,18 @@ class Order(BaseEntity): ordered_on = Date() items = HasMany("OrderItem") - class Meta: - part_of = Shipment - class OrderItem(BaseEntity): product_id = String(max_length=50) quantity = Integer() price = Float() - class Meta: - part_of = Order - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Shipment) - test_domain.register(Order) - test_domain.register(OrderItem) + test_domain.register(Order, part_of=Shipment) + test_domain.register(OrderItem, part_of=Order) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_multiple_has_many.py b/tests/entity/associations/test_multiple_has_many.py index 03b5e535..620e4bc3 100644 --- a/tests/entity/associations/test_multiple_has_many.py +++ b/tests/entity/associations/test_multiple_has_many.py @@ -16,9 +16,6 @@ class Customer(BaseAggregate): class Order(BaseEntity): ordered_on = Date() - class Meta: - part_of = Customer - class Address(BaseEntity): street = String(max_length=50) @@ -26,15 +23,12 @@ class Address(BaseEntity): state = String(max_length=50) zip_code = String(max_length=10) - class Meta: - part_of = Customer - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Customer) - test_domain.register(Order) - test_domain.register(Address) + test_domain.register(Order, part_of=Customer) + test_domain.register(Address, part_of=Customer) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_multiple_has_one.py b/tests/entity/associations/test_multiple_has_one.py index 584d4c85..4eeabe5c 100644 --- a/tests/entity/associations/test_multiple_has_one.py +++ b/tests/entity/associations/test_multiple_has_one.py @@ -15,22 +15,16 @@ class Dean(BaseEntity): name = String(max_length=50) age = Integer(min_value=21) - class Meta: - part_of = Department - class Location(BaseEntity): building = String(max_length=50) - class Meta: - part_of = Department - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Department) - test_domain.register(Dean) - test_domain.register(Location) + test_domain.register(Dean, part_of=Department) + test_domain.register(Location, part_of=Department) test_domain.init(traverse=False) diff --git a/tests/entity/associations/test_owner_and_root.py b/tests/entity/associations/test_owner_and_root.py index 35dd38f5..1b35f18c 100644 --- a/tests/entity/associations/test_owner_and_root.py +++ b/tests/entity/associations/test_owner_and_root.py @@ -13,33 +13,24 @@ class Department(BaseEntity): name = String(max_length=50) dean = HasOne("Dean") - class Meta: - part_of = University - class Dean(BaseEntity): name = String(max_length=50) age = Integer(min_value=21) office = HasOne("Office") - class Meta: - part_of = Department - class Office(BaseEntity): building = String(max_length=25) room = Integer(min_value=1) - class Meta: - part_of = Dean - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(University) - test_domain.register(Department) - test_domain.register(Dean) - test_domain.register(Office) + test_domain.register(Department, part_of=University) + test_domain.register(Dean, part_of=Department) + test_domain.register(Office, part_of=Dean) test_domain.init(traverse=False) diff --git a/tests/entity/elements.py b/tests/entity/elements.py index f20db1c1..fd96a2bc 100644 --- a/tests/entity/elements.py +++ b/tests/entity/elements.py @@ -9,29 +9,20 @@ class Account(BaseAggregate): account_number = String(max_length=50, required=True) -class AbstractPerson(BaseEntity): +class AbstractPerson(BaseAggregate): age = Integer(default=5) - class Meta: - abstract = True - class ConcretePerson(BaseEntity): first_name = String(max_length=50, required=True) last_name = String(max_length=50) - class Meta: - part_of = "Account" - class Person(BaseEntity): first_name = String(max_length=50, required=True) last_name = String(max_length=50) age = Integer(default=21) - class Meta: - part_of = "Account" - class PersonAutoSSN(BaseEntity): ssn = Auto(identifier=True) @@ -39,9 +30,6 @@ class PersonAutoSSN(BaseEntity): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - part_of = "Account" - class PersonExplicitID(BaseEntity): ssn = String(max_length=36, identifier=True) @@ -49,9 +37,6 @@ class PersonExplicitID(BaseEntity): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - part_of = "Account" - class Relative(BaseEntity): first_name = String(max_length=50, required=True) @@ -59,26 +44,16 @@ class Relative(BaseEntity): age = Integer(default=21) relative_of = HasOne(Person) - class Meta: - part_of = "Account" - class Adult(Person): pass - class Meta: - schema_name = "adults" - part_of = "Account" - class NotAPerson(BaseEntity): first_name = String(max_length=50, required=True) last_name = String(max_length=50) age = Integer(default=21) - class Meta: - part_of = "Account" - # Entities to test Meta Info overriding # START # class DbPerson(BaseEntity): @@ -86,27 +61,17 @@ class DbPerson(BaseEntity): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - schema_name = "pepes" - part_of = "Account" - class SqlPerson(Person): - class Meta: - schema_name = "people" - part_of = "Account" + pass class DifferentDbPerson(Person): - class Meta: - provider = "non-default" - part_of = "Account" + pass class SqlDifferentDbPerson(Person): - class Meta: - provider = "non-default-sql" - part_of = "Account" + pass class OrderedPerson(BaseEntity): @@ -114,15 +79,9 @@ class OrderedPerson(BaseEntity): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - order_by = "first_name" - part_of = "Account" - class OrderedPersonSubclass(Person): - class Meta: - order_by = "last_name" - part_of = "Account" + pass class BuildingStatus(Enum): @@ -139,9 +98,6 @@ class Building(BaseEntity): floors = Integer() status = String(choices=BuildingStatus) - class Meta: - part_of = "Area" - def defaults(self): if not self.status: if self.floors == 4: diff --git a/tests/entity/fields/test_list_of_value_objects.py b/tests/entity/fields/test_list_of_value_objects.py index 601e0f4c..7255b7cc 100644 --- a/tests/entity/fields/test_list_of_value_objects.py +++ b/tests/entity/fields/test_list_of_value_objects.py @@ -16,9 +16,6 @@ class Customer(BaseEntity): email = String(max_length=254, required=True) addresses = List(content_type=ValueObject(Address)) - class Meta: - part_of = "Order" - # Aggregate that encloses Customer Entity class Order(BaseAggregate): @@ -28,7 +25,7 @@ class Order(BaseAggregate): @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Order) - test_domain.register(Customer) + test_domain.register(Customer, part_of=Order) test_domain.register(Address) diff --git a/tests/entity/invariants/test_invariant_decorator.py b/tests/entity/invariants/test_invariant_decorator.py index 49b272ec..6f7e8c63 100644 --- a/tests/entity/invariants/test_invariant_decorator.py +++ b/tests/entity/invariants/test_invariant_decorator.py @@ -57,9 +57,6 @@ class OrderItem(BaseEntity): quantity = Integer() price = Float() - class Meta: - part_of = Order - @invariant.post def price_should_be_non_negative(self): if self.price < 0: @@ -67,8 +64,8 @@ def price_should_be_non_negative(self): def test_that_entity_has_recorded_invariants(test_domain): - test_domain.register(OrderItem) test_domain.register(Order) + test_domain.register(OrderItem, part_of=Order) test_domain.init(traverse=False) assert len(Order._invariants["pre"]) == 1 diff --git a/tests/entity/invariants/test_invariant_triggerring.py b/tests/entity/invariants/test_invariant_triggerring.py index adfcfdf6..91a6e083 100644 --- a/tests/entity/invariants/test_invariant_triggerring.py +++ b/tests/entity/invariants/test_invariant_triggerring.py @@ -74,9 +74,6 @@ class OrderItem(BaseEntity): price = Float() subtotal = Float() - class Meta: - part_of = Order - @invariant.post def the_quantity_must_be_a_positive_integer_and_the_subtotal_must_be_correctly_calculated( self, @@ -93,8 +90,8 @@ def the_quantity_must_be_a_positive_integer_and_the_subtotal_must_be_correctly_c @pytest.fixture(autouse=True) def register_elements(test_domain): - test_domain.register(OrderItem) test_domain.register(Order) + test_domain.register(OrderItem, part_of=Order) test_domain.init(traverse=False) diff --git a/tests/entity/test_entity.py b/tests/entity/test_entity.py index 465204b3..7fc2a3e5 100644 --- a/tests/entity/test_entity.py +++ b/tests/entity/test_entity.py @@ -1,8 +1,11 @@ +import pytest + from protean.container import Options from protean.fields import Auto, Integer, String from protean.reflection import attributes, declared_fields from .elements import ( + Account, AbstractPerson, ConcretePerson, Person, @@ -16,6 +19,24 @@ ) +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(Account) + test_domain.register(AbstractPerson, abstract=True) + test_domain.register(ConcretePerson, part_of=Account) + test_domain.register(Person, part_of=Account) + test_domain.register(PersonAutoSSN, part_of=Account) + test_domain.register(Relative, part_of=Account) + test_domain.register( + SqlDifferentDbPerson, part_of=Account, provider="non-default-sql" + ) + test_domain.register(SqlPerson, part_of=Account, schema_name="people") + test_domain.register(DbPerson, part_of=Account, schema_name="pepes") + test_domain.register(DifferentDbPerson, part_of=Account, provider="non-default") + test_domain.register(Adult, part_of=Account, schema_name="adults") + test_domain.init(traverse=False) + + class TestEntityMeta: def test_entity_meta_structure(self): assert hasattr(Person, "meta_") @@ -80,16 +101,19 @@ def test_entity_meta_has_attributes_on_construction(self): "last_name", "age", "id", + "account_id", ] assert list(attributes(PersonAutoSSN).keys()) == [ "ssn", "first_name", "last_name", "age", + "account_id", ] assert list(attributes(Relative).keys()) == [ "first_name", "last_name", "age", "id", + "account_id", ] # `relative_of` is ignored diff --git a/tests/entity/test_entity_meta.py b/tests/entity/test_entity_meta.py index 1ffecad8..23b34c54 100644 --- a/tests/entity/test_entity_meta.py +++ b/tests/entity/test_entity_meta.py @@ -80,18 +80,21 @@ def test_entity_meta_has_attributes_on_construction(self): "last_name", "age", "id", + "account_id", ] assert list(attributes(PersonAutoSSN).keys()) == [ "ssn", "first_name", "last_name", "age", + "account_id", ] assert list(attributes(Relative).keys()) == [ "first_name", "last_name", "age", "id", + "account_id", ] # `relative_of` is ignored def test_meta_equality(self): diff --git a/tests/entity/test_entity_registration.py b/tests/entity/test_entity_registration.py index 27a71ca4..79ec9e71 100644 --- a/tests/entity/test_entity_registration.py +++ b/tests/entity/test_entity_registration.py @@ -11,11 +11,8 @@ class Post(BaseAggregate): class Comment(BaseEntity): content = String(max_length=500) - class Meta: - part_of = Post - test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) assert fully_qualified_name(Comment) in test_domain.registry.entities assert Comment.meta_.part_of == Post @@ -25,13 +22,10 @@ def test_setting_provider_in_decorator_based_registration(self, test_domain): class Post: name = String(max_length=50) - @test_domain.entity + @test_domain.entity(part_of=Post) class Comment(BaseEntity): content = String(max_length=500) - class Meta: - part_of = Post - assert Comment.meta_.part_of == Post def test_setting_provider_in_decorator_based_registration_with_parameters( diff --git a/tests/entity/test_lifecycle_methods.py b/tests/entity/test_lifecycle_methods.py index aff57514..58455649 100644 --- a/tests/entity/test_lifecycle_methods.py +++ b/tests/entity/test_lifecycle_methods.py @@ -30,8 +30,8 @@ def defaults(self): class TestInvariantValidation: def test_that_building_cannot_be_WIP_if_above_4_floors(self, test_domain): - test_domain.register(Building) test_domain.register(Area) + test_domain.register(Building, part_of=Area) test_domain.init(traverse=False) with pytest.raises(ValidationError): diff --git a/tests/entity/test_temp.py b/tests/entity/test_temp.py index 364ed3b9..05fe9bcf 100644 --- a/tests/entity/test_temp.py +++ b/tests/entity/test_temp.py @@ -9,13 +9,11 @@ class AbstractRole(BaseAggregate): foo = String(max_length=25) - class Meta: - abstract = True - -def test_that_abstract_entities_cannot_be_initialized(): +def test_that_abstract_entities_cannot_be_initialized(test_domain): + test_domain.register(AbstractRole, abstract=True) with pytest.raises(NotSupportedError) as exc2: - AbstractRole(name="Titan") + AbstractRole(foo="Titan") assert exc2.value.args[0] == ( "AbstractRole class has been marked abstract" " and cannot be instantiated" ) diff --git a/tests/event/elements.py b/tests/event/elements.py index 63987f28..66d5af31 100644 --- a/tests/event/elements.py +++ b/tests/event/elements.py @@ -41,9 +41,6 @@ class PersonAdded(BaseEvent): last_name = String(max_length=50, required=True) age = Integer(default=21) - class Meta: - part_of = Person - class PersonService(BaseApplicationService): @classmethod diff --git a/tests/event/test_automatic_stream_association.py b/tests/event/test_automatic_stream_association.py index e6561da8..6d5a2c98 100644 --- a/tests/event/test_automatic_stream_association.py +++ b/tests/event/test_automatic_stream_association.py @@ -33,9 +33,6 @@ class LoggedIn(BaseEvent): id = Identifier() activated_at = DateTime() - class Meta: - part_of = User - class Subscribed(BaseEvent): """An event generated by an external system in its own stream, @@ -44,9 +41,6 @@ class Subscribed(BaseEvent): id = Identifier() - class Meta: - stream_name = "subscriptions" - class Sent(BaseEvent): email = String() @@ -57,10 +51,6 @@ class Recalled(BaseEvent): email = String() sent_at = DateTime() - class Meta: - part_of = Email - stream_name = "recalls" - class UserEventHandler(BaseEventHandler): @handle(Registered) @@ -97,7 +87,13 @@ def record_recalls(self, _: Recalled) -> None: @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(User) + test_domain.register(Registered, stream_name="user") + test_domain.register(Activated, stream_name="user") + test_domain.register(LoggedIn, part_of=User) + test_domain.register(Subscribed, stream_name="subscriptions") test_domain.register(Email) + test_domain.register(Sent, stream_name="email") + test_domain.register(Recalled, part_of=Email, stream_name="recalls") test_domain.register(UserEventHandler, part_of=User) test_domain.register(EmailEventHandler, part_of=Email) diff --git a/tests/event/test_event_meta.py b/tests/event/test_event_meta.py index 0f3c9c3f..f51618ef 100644 --- a/tests/event/test_event_meta.py +++ b/tests/event/test_event_meta.py @@ -58,11 +58,8 @@ def test_that_abstract_events_can_be_defined_without_aggregate_or_stream(test_do class AbstractEvent(BaseEvent): foo = String() - class Meta: - abstract = True - try: - test_domain.register(AbstractEvent) + test_domain.register(AbstractEvent, abstract=True) except Exception: pytest.fail( "Abstract events should be definable without being associated with an aggregate or a stream" diff --git a/tests/event/test_raising_events.py b/tests/event/test_raising_events.py index d0b5c0e6..8e6bd56b 100644 --- a/tests/event/test_raising_events.py +++ b/tests/event/test_raising_events.py @@ -16,14 +16,11 @@ class User(BaseEventSourcedAggregate): class UserLoggedIn(BaseEvent): user_id = Identifier(identifier=True) - class Meta: - stream_name = "authentication" - @pytest.mark.eventstore def test_raising_event(test_domain): test_domain.register(User) - test_domain.register(UserLoggedIn) + test_domain.register(UserLoggedIn, stream_name="authentication") identifier = str(uuid4()) test_domain.raise_(UserLoggedIn(user_id=identifier)) diff --git a/tests/event/tests.py b/tests/event/tests.py index d3648eaa..0065474a 100644 --- a/tests/event/tests.py +++ b/tests/event/tests.py @@ -19,10 +19,7 @@ class UserAdded(BaseEvent): email = ValueObject(Email, required=True) name = String(max_length=50) - class Meta: - stream_name = "user" - - test_domain.register(UserAdded) + test_domain.register(UserAdded, stream_name="user") event = UserAdded(email_address="john.doe@gmail.com", name="John Doe") assert event is not None @@ -44,9 +41,6 @@ class UserAdded(BaseEvent): email = ValueObject(Email, required=True) name = String(max_length=50) - class Meta: - stream_name = "user" - assert UserAdded( { "email": { @@ -69,7 +63,7 @@ def test_that_domain_event_can_be_instantiated(self): class TestDomainEventRegistration: def test_that_domain_event_can_be_registered_with_domain(self, test_domain): - test_domain.register(PersonAdded) + test_domain.register(PersonAdded, part_of=Person) assert fully_qualified_name(PersonAdded) in test_domain.registry.events diff --git a/tests/event_handler/test_any_event_handler.py b/tests/event_handler/test_any_event_handler.py index 22e4727f..2031824a 100644 --- a/tests/event_handler/test_any_event_handler.py +++ b/tests/event_handler/test_any_event_handler.py @@ -6,9 +6,6 @@ class AllEventHandler(BaseEventHandler): def universal_handler(self, event: BaseEventHandler) -> None: pass - class Meta: - stream_name = "$all" - class MultipleAnyEventHandler(BaseEventHandler): @handle("$any") @@ -19,19 +16,16 @@ def handler1(self, event: BaseEvent) -> None: def handler2(self, event: BaseEvent) -> None: pass - class Meta: - stream_name = "$all" - def test_any_handler(test_domain): - test_domain.register(AllEventHandler) + test_domain.register(AllEventHandler, stream_name="$all") len(AllEventHandler._handlers) == 1 assert AllEventHandler._handlers["$any"] == {AllEventHandler.universal_handler} def test_that_there_can_be_only_one_any_handler_method_per_event_handler(test_domain): - test_domain.register(MultipleAnyEventHandler) + test_domain.register(MultipleAnyEventHandler, stream_name="$all") assert len(MultipleAnyEventHandler._handlers["$any"]) == 1 assert MultipleAnyEventHandler._handlers["$any"] == { diff --git a/tests/event_handler/test_event_handler_options.py b/tests/event_handler/test_event_handler_options.py index 903589ae..1fa91490 100644 --- a/tests/event_handler/test_event_handler_options.py +++ b/tests/event_handler/test_event_handler_options.py @@ -25,10 +25,9 @@ class UserEventHandlers(BaseEventHandler): def test_aggregate_cls_specified_as_a_meta_attribute(test_domain): class UserEventHandlers(BaseEventHandler): - class Meta: - part_of = User + pass - test_domain.register(UserEventHandlers) + test_domain.register(UserEventHandlers, part_of=User) assert UserEventHandlers.meta_.part_of == User @@ -52,10 +51,9 @@ class UserEventHandlers(BaseEventHandler): def test_options_defined_at_different_levels(test_domain): class UserEventHandlers(BaseEventHandler): - class Meta: - stream_name = "person" + pass - test_domain.register(UserEventHandlers, part_of=User) + test_domain.register(UserEventHandlers, part_of=User, stream_name="person") assert UserEventHandlers.meta_.part_of == User assert UserEventHandlers.meta_.stream_name == "person" @@ -64,6 +62,7 @@ def test_that_a_default_stream_name_is_derived_from_aggregate_cls(test_domain): class UserEventHandlers(BaseEventHandler): pass + test_domain.register(User) test_domain.register(UserEventHandlers, part_of=User) assert UserEventHandlers.meta_.stream_name == "user" diff --git a/tests/event_handler/test_retrieving_handlers_by_event.py b/tests/event_handler/test_retrieving_handlers_by_event.py index d6ddff0c..ad62fc19 100644 --- a/tests/event_handler/test_retrieving_handlers_by_event.py +++ b/tests/event_handler/test_retrieving_handlers_by_event.py @@ -31,9 +31,6 @@ class Renamed(BaseEvent): id = Identifier() name = String() - class Meta: - part_of = User - class Sent(BaseEvent): email = String() @@ -65,22 +62,22 @@ class UserMetrics(BaseEventHandler): def count_registrations(self, _: BaseEvent) -> None: pass - class Meta: - part_of = User - class AllEventsHandler(BaseEventHandler): - class Meta: - stream_name = "$all" - @handle("$any") def universal_handler(self, _: BaseEvent) -> None: pass def test_retrieving_handler_by_event(test_domain): + test_domain.register(User) + test_domain.register(Registered, part_of=User) + test_domain.register(Activated, part_of=User) + test_domain.register(Renamed, part_of=User) test_domain.register(UserEventHandler, part_of=User) test_domain.register(UserMetrics, part_of=User) + test_domain.register(Email) + test_domain.register(Sent, part_of=Email) test_domain.register(EmailEventHandler, part_of=Email) assert test_domain.handlers_for(Registered()) == {UserEventHandler, UserMetrics} @@ -88,14 +85,20 @@ def test_retrieving_handler_by_event(test_domain): def test_that_all_streams_handler_is_returned(test_domain): - test_domain.register(AllEventsHandler) + test_domain.register(AllEventsHandler, stream_name="$all") assert test_domain.handlers_for(Renamed()) == {AllEventsHandler} def test_that_all_streams_handler_is_always_returned_with_other_handlers(test_domain): - test_domain.register(AllEventsHandler) + test_domain.register(User) + test_domain.register(Registered, part_of=User) + test_domain.register(Activated, part_of=User) + test_domain.register(Renamed, part_of=User) + test_domain.register(AllEventsHandler, stream_name="$all") test_domain.register(UserEventHandler, part_of=User) test_domain.register(UserMetrics, part_of=User) + test_domain.register(Email) + test_domain.register(Sent, part_of=Email) test_domain.register(EmailEventHandler, part_of=Email) assert test_domain.handlers_for(Registered()) == { diff --git a/tests/event_sourced_aggregates/test_event_sourced_aggregate_options.py b/tests/event_sourced_aggregates/test_event_sourced_aggregate_options.py index c954666c..40464bc3 100644 --- a/tests/event_sourced_aggregates/test_event_sourced_aggregate_options.py +++ b/tests/event_sourced_aggregates/test_event_sourced_aggregate_options.py @@ -1,3 +1,5 @@ +import pytest + from protean import BaseEventSourcedAggregate from protean.fields import Integer, String @@ -15,8 +17,12 @@ class Person(BaseEventSourcedAggregate): name = String() age = Integer() - class Meta: - stream_name = "people" + +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(User) + test_domain.register(AdminUser) + test_domain.register(Person, stream_name="people") def test_stream_name_option_of_an_event_sourced_aggregate(): diff --git a/tests/event_sourced_repository/test_loading_aggregates.py b/tests/event_sourced_repository/test_loading_aggregates.py index 1098b6de..7d289a92 100644 --- a/tests/event_sourced_repository/test_loading_aggregates.py +++ b/tests/event_sourced_repository/test_loading_aggregates.py @@ -24,17 +24,11 @@ class Register(BaseCommand): name = String() password_hash = String() - class Meta: - part_of = "User" - class ChangeAddress(BaseCommand): user_id = Identifier() address = String() - class Meta: - part_of = "User" - class Registered(BaseEvent): user_id = Identifier() @@ -42,17 +36,11 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = "User" - class AddressChanged(BaseEvent): user_id = Identifier() address = String() - class Meta: - part_of = "User" - class User(BaseEventSourcedAggregate): user_id = Identifier(identifier=True) @@ -111,18 +99,15 @@ def change_address(self, command: ChangeAddress) -> None: user_repo.add(user) - class Meta: - part_of = User - @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(User) - test_domain.register(Register) - test_domain.register(Registered) - test_domain.register(ChangeAddress) - test_domain.register(AddressChanged) - test_domain.register(UserCommandHandler) + test_domain.register(Register, part_of=User) + test_domain.register(Registered, part_of=User) + test_domain.register(ChangeAddress, part_of=User) + test_domain.register(AddressChanged, part_of=User) + test_domain.register(UserCommandHandler, part_of=User) @pytest.mark.eventstore diff --git a/tests/event_sourced_repository/test_retrieving_event_sourced_repository.py b/tests/event_sourced_repository/test_retrieving_event_sourced_repository.py index 1a708449..392b79ad 100644 --- a/tests/event_sourced_repository/test_retrieving_event_sourced_repository.py +++ b/tests/event_sourced_repository/test_retrieving_event_sourced_repository.py @@ -27,8 +27,7 @@ def test_that_a_custom_repository_cannot_be_associated_with_event_sourced_aggreg test_domain, ): class CustomUserRepository(BaseEventSourcedRepository): - class Meta: - part_of = User + pass with pytest.raises(IncorrectUsageError): - test_domain.register(CustomUserRepository) + test_domain.register(CustomUserRepository, part_of=User) diff --git a/tests/event_store/test_appending_events.py b/tests/event_store/test_appending_events.py index fcd6c1ad..911c7fa9 100644 --- a/tests/event_store/test_appending_events.py +++ b/tests/event_store/test_appending_events.py @@ -12,12 +12,11 @@ class UserLoggedIn(BaseEvent): user_id = Identifier(identifier=True) - class Meta: - stream_name = "authentication" - @pytest.mark.eventstore def test_appending_raw_events(test_domain): + test_domain.register(UserLoggedIn, stream_name="authentication") + identifier = str(uuid4()) event = UserLoggedIn(user_id=identifier) test_domain.event_store.store.append(event) diff --git a/tests/event_store/test_inline_event_processing_on_publish.py b/tests/event_store/test_inline_event_processing_on_publish.py index 7bb54fab..e5d1a4ad 100644 --- a/tests/event_store/test_inline_event_processing_on_publish.py +++ b/tests/event_store/test_inline_event_processing_on_publish.py @@ -27,9 +27,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - stream_name = "user" - class UserEventHandler(BaseEventHandler): @handle(Registered) @@ -39,7 +36,7 @@ def registered(self, _: Registered) -> None: @pytest.mark.eventstore def test_inline_event_processing_on_publish_in_sync_mode(test_domain): - test_domain.register(Registered) + test_domain.register(Registered, stream_name="user") test_domain.register(UserEventHandler, stream_name="user") current_domain.publish( diff --git a/tests/event_store/test_reading_all_streams.py b/tests/event_store/test_reading_all_streams.py index 90a258cc..111ef58e 100644 --- a/tests/event_store/test_reading_all_streams.py +++ b/tests/event_store/test_reading_all_streams.py @@ -18,24 +18,15 @@ class Registered(BaseEvent): id = Identifier() email = String() - class Meta: - part_of = User - class Activated(BaseEvent): id = Identifier(required=True) - class Meta: - part_of = User - class Renamed(BaseEvent): id = Identifier(required=True) name = String(required=True, max_length=50) - class Meta: - part_of = User - class Post(BaseEventSourcedAggregate): topic = String() @@ -47,17 +38,11 @@ class Created(BaseEvent): topic = String() content = Text() - class Meta: - part_of = Post - class Published(BaseEvent): id = Identifier(required=True) published_time = DateTime(default=utcnow_func) - class Meta: - part_of = Post - @pytest.mark.eventstore def test_reading_messages_from_all_streams(test_domain): diff --git a/tests/event_store/test_reading_events_of_type.py b/tests/event_store/test_reading_events_of_type.py index 016cc6a7..9d1c2642 100644 --- a/tests/event_store/test_reading_events_of_type.py +++ b/tests/event_store/test_reading_events_of_type.py @@ -18,31 +18,22 @@ class Registered(BaseEvent): id = Identifier() email = String() - class Meta: - part_of = User - class Activated(BaseEvent): id = Identifier(required=True) - class Meta: - part_of = User - class Renamed(BaseEvent): id = Identifier(required=True) name = String(required=True, max_length=50) - class Meta: - part_of = User - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(User) - test_domain.register(Registered) - test_domain.register(Activated) - test_domain.register(Renamed) + test_domain.register(Registered, part_of=User) + test_domain.register(Activated, part_of=User) + test_domain.register(Renamed, part_of=User) @pytest.fixture diff --git a/tests/event_store/test_reading_last_event_of_type.py b/tests/event_store/test_reading_last_event_of_type.py index 0612650a..83adcd92 100644 --- a/tests/event_store/test_reading_last_event_of_type.py +++ b/tests/event_store/test_reading_last_event_of_type.py @@ -18,31 +18,22 @@ class Registered(BaseEvent): id = Identifier() email = String() - class Meta: - part_of = User - class Activated(BaseEvent): id = Identifier(required=True) - class Meta: - part_of = User - class Renamed(BaseEvent): id = Identifier(required=True) name = String(required=True, max_length=50) - class Meta: - part_of = User - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(User) - test_domain.register(Registered) - test_domain.register(Activated) - test_domain.register(Renamed) + test_domain.register(Registered, part_of=User) + test_domain.register(Activated, part_of=User) + test_domain.register(Renamed, part_of=User) @pytest.fixture diff --git a/tests/event_store/test_reading_messages.py b/tests/event_store/test_reading_messages.py index 2915afbd..30edfc05 100644 --- a/tests/event_store/test_reading_messages.py +++ b/tests/event_store/test_reading_messages.py @@ -20,24 +20,15 @@ class Registered(BaseEvent): id = Identifier() email = String() - class Meta: - part_of = User - class Activated(BaseEvent): id = Identifier(required=True) - class Meta: - part_of = User - class Renamed(BaseEvent): id = Identifier(required=True) name = String(required=True, max_length=50) - class Meta: - part_of = User - @pytest.mark.eventstore def test_reading_a_message(test_domain): diff --git a/tests/field/elements.py b/tests/field/elements.py index 982e309b..bbc2e638 100644 --- a/tests/field/elements.py +++ b/tests/field/elements.py @@ -19,15 +19,9 @@ class PostMeta(BaseEntity): post = Reference(Post) - class Meta: - part_of = Post - class Comment(BaseEntity): content = Text(required=True) commented_at = DateTime(required=True, default=datetime.now()) post = Reference(Post) - - class Meta: - part_of = Post diff --git a/tests/field/test_has_many.py b/tests/field/test_has_many.py index 298e1139..bc1bdbbf 100644 --- a/tests/field/test_has_many.py +++ b/tests/field/test_has_many.py @@ -14,14 +14,11 @@ class Post(BaseAggregate): class Comment(BaseEntity): content = String() - class Meta: - part_of = Post - @pytest.fixture(autouse=True) def register_elements(test_domain): test_domain.register(Post) - test_domain.register(Comment) + test_domain.register(Comment, part_of=Post) test_domain.init(traverse=False) diff --git a/tests/field/test_has_one.py b/tests/field/test_has_one.py index d015ce7a..74f60b69 100644 --- a/tests/field/test_has_one.py +++ b/tests/field/test_has_one.py @@ -15,14 +15,11 @@ class Author(BaseEntity): name = String(required=True, max_length=50) book = Reference("Book") - class Meta: - part_of = "Book" - @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(Book) - test_domain.register(Author) + test_domain.register(Author, part_of=Book) test_domain.init(traverse=False) diff --git a/tests/field/test_has_one_without_explicit_reference.py b/tests/field/test_has_one_without_explicit_reference.py index 30636baf..a317da1a 100644 --- a/tests/field/test_has_one_without_explicit_reference.py +++ b/tests/field/test_has_one_without_explicit_reference.py @@ -19,14 +19,11 @@ class Book(BaseAggregate): class Author(BaseEntity): name = String(required=True, max_length=50) - class Meta: - part_of = "Book" - @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(Book) - test_domain.register(Author) + test_domain.register(Author, part_of=Book) test_domain.init(traverse=False) diff --git a/tests/field/test_reference.py b/tests/field/test_reference.py index eb56dc41..98ff6ea8 100644 --- a/tests/field/test_reference.py +++ b/tests/field/test_reference.py @@ -8,9 +8,6 @@ class Address(BaseEntity): postal_code = String(max_length=6) - class Meta: - part_of = "User" - class User(BaseAggregate): address = Reference(Address, required=True) diff --git a/tests/message/test_message_to_object.py b/tests/message/test_message_to_object.py index 7e3cc6cb..f84cd494 100644 --- a/tests/message/test_message_to_object.py +++ b/tests/message/test_message_to_object.py @@ -17,18 +17,12 @@ class Register(BaseCommand): email = String() name = String() - class Meta: - part_of = User - class Registered(BaseEvent): id = Identifier() email = String() name = String() - class Meta: - part_of = User - class SendEmail(BaseEventSourcedAggregate): to = String() @@ -41,17 +35,14 @@ class SendEmailCommand(BaseCommand): subject = String() content = String() - class Meta: - part_of = SendEmail - @pytest.fixture(autouse=True) def register(test_domain): test_domain.register(User) - test_domain.register(Register) - test_domain.register(Registered) + test_domain.register(Register, part_of=User) + test_domain.register(Registered, part_of=User) test_domain.register(SendEmail) - test_domain.register(SendEmailCommand) + test_domain.register(SendEmailCommand, part_of=SendEmail) def test_construct_event_from_message(test_domain): diff --git a/tests/message/test_object_to_message.py b/tests/message/test_object_to_message.py index c79d7d17..e8d74371 100644 --- a/tests/message/test_object_to_message.py +++ b/tests/message/test_object_to_message.py @@ -18,18 +18,12 @@ class Register(BaseCommand): email = String() name = String() - class Meta: - part_of = User - class Registered(BaseEvent): id = Identifier(identifier=True) email = String() name = String() - class Meta: - part_of = User - class SendEmail(BaseEventSourcedAggregate): to = String() @@ -42,8 +36,14 @@ class SendEmailCommand(BaseCommand): subject = String() content = String() - class Meta: - part_of = SendEmail + +@pytest.fixture(autouse=True) +def register(test_domain): + test_domain.register(User) + test_domain.register(Register, part_of=User) + test_domain.register(Registered, part_of=User) + test_domain.register(SendEmail) + test_domain.register(SendEmailCommand, part_of=SendEmail) def test_construct_message_from_event(test_domain): diff --git a/tests/reflection/test_has_id_field.py b/tests/reflection/test_has_id_field.py index 5984c793..d7296fba 100644 --- a/tests/reflection/test_has_id_field.py +++ b/tests/reflection/test_has_id_field.py @@ -4,14 +4,11 @@ from protean.reflection import has_id_field -class Entity1(BaseEntity): +class Aggregate1(BaseAggregate): foo = String() - class Meta: - part_of = "Aggregate1" - -class Aggregate1(BaseAggregate): +class Entity1(BaseEntity): foo = String() diff --git a/tests/repository/child_entities.py b/tests/repository/child_entities.py index b37d0163..a515ca39 100644 --- a/tests/repository/child_entities.py +++ b/tests/repository/child_entities.py @@ -19,15 +19,9 @@ class PostMeta(BaseEntity): post = Reference(Post) - class Meta: - part_of = Post - class Comment(BaseEntity): content = Text(required=True) commented_at = DateTime(required=True, default=datetime.now()) post = Reference(Post) - - class Meta: - part_of = Post diff --git a/tests/repository/elements.py b/tests/repository/elements.py index 0728a58b..fcf14a21 100644 --- a/tests/repository/elements.py +++ b/tests/repository/elements.py @@ -18,9 +18,6 @@ class PersonRepository(BaseRepository): def find_adults(self, minimum_age: int = 21) -> List[Person]: return current_domain.repository_for(Person)._dao.filter(age__gte=minimum_age) - class Meta: - part_of = Person - class Email(BaseValueObject): REGEXP = r"\"?([-a-zA-Z0-9.`?{}]+@\w+\.\w+)\"?" diff --git a/tests/repository/test_aggregate_persistence.py b/tests/repository/test_aggregate_persistence.py index 62748dea..628931bc 100644 --- a/tests/repository/test_aggregate_persistence.py +++ b/tests/repository/test_aggregate_persistence.py @@ -18,7 +18,7 @@ class TestAggregatePersistenceWithRepository: @pytest.fixture(autouse=True) def register_repositories(self, test_domain): test_domain.register(Person) - test_domain.register(PersonRepository) + test_domain.register(PersonRepository, part_of=Person) yield @pytest.fixture diff --git a/tests/repository/test_child_persistence.py b/tests/repository/test_child_persistence.py index a7a7305f..e753f247 100644 --- a/tests/repository/test_child_persistence.py +++ b/tests/repository/test_child_persistence.py @@ -9,8 +9,8 @@ class TestHasOnePersistence: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Post) - test_domain.register(PostMeta) - test_domain.register(Comment) + test_domain.register(PostMeta, part_of=Post) + test_domain.register(Comment, part_of=Post) test_domain.init(traverse=False) @pytest.fixture(autouse=True) @@ -83,8 +83,8 @@ class TestHasManyPersistence: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Post) - test_domain.register(PostMeta) - test_domain.register(Comment) + test_domain.register(PostMeta, part_of=Post) + test_domain.register(Comment, part_of=Post) @pytest.fixture def persisted_post(self, test_domain): diff --git a/tests/repository/test_custom_repositories.py b/tests/repository/test_custom_repositories.py index 25322b23..7bf9c20e 100644 --- a/tests/repository/test_custom_repositories.py +++ b/tests/repository/test_custom_repositories.py @@ -20,18 +20,12 @@ def find_adults(self, minimum_age: int = 21) -> List[PersonGeneric]: age__gte=minimum_age ) - class Meta: - part_of = PersonGeneric - 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 PersonSQLiteGenericRepository(BaseRepository): def find_adults(self, minimum_age: int = 21) -> List[PersonGeneric]: @@ -39,9 +33,6 @@ def find_adults(self, minimum_age: int = 21) -> List[PersonGeneric]: age__gte=minimum_age ) - class Meta: - part_of = PersonSQLite - class PersonSQLiteCustomRepository(BaseRepository): def find_adults(self, minimum_age: int = 21) -> List[PersonGeneric]: @@ -50,10 +41,6 @@ def find_adults(self, minimum_age: int = 21) -> List[PersonGeneric]: return result - class Meta: - part_of = PersonSQLite - database = "sqlite" - class TestRepositoryConstructionAndRegistration: @pytest.fixture @@ -80,7 +67,7 @@ def test_default_repository_construction_and_registration(self, custom_test_doma def test_custom_generic_repository_registration(self, custom_test_domain): custom_test_domain.register(PersonGeneric) - custom_test_domain.register(PersonCustomRepository) + custom_test_domain.register(PersonCustomRepository, part_of=PersonGeneric) custom_test_domain.repository_for(PersonGeneric) repo_cls_constructed = custom_test_domain.providers._repositories[ @@ -94,7 +81,7 @@ def test_custom_generic_repository_registration(self, custom_test_domain): def test_default_repository_construction_and_registration_for_non_memory_database( self, custom_test_domain ): - custom_test_domain.register(PersonSQLite) + custom_test_domain.register(PersonSQLite, provider="sqlite") custom_test_domain.repository_for(PersonSQLite) repo_cls_constructed = custom_test_domain.providers._repositories[ @@ -108,8 +95,10 @@ def test_default_repository_construction_and_registration_for_non_memory_databas def test_custom_repository_construction_and_registration_for_non_memory_database( self, custom_test_domain ): - custom_test_domain.register(PersonSQLite) - custom_test_domain.register(PersonSQLiteCustomRepository) + custom_test_domain.register(PersonSQLite, provider="sqlite") + custom_test_domain.register( + PersonSQLiteCustomRepository, part_of=PersonSQLite, database="sqlite" + ) custom_test_domain.repository_for(PersonSQLite) repo_cls_constructed = custom_test_domain.providers._repositories[ @@ -123,9 +112,11 @@ def test_custom_repository_construction_and_registration_for_non_memory_database def test_that_sqlite_repository_is_chosen_over_generic_provider( self, custom_test_domain ): - custom_test_domain.register(PersonSQLite) - custom_test_domain.register(PersonSQLiteGenericRepository) - custom_test_domain.register(PersonSQLiteCustomRepository) + custom_test_domain.register(PersonSQLite, provider="sqlite") + custom_test_domain.register(PersonSQLiteGenericRepository, part_of=PersonSQLite) + custom_test_domain.register( + PersonSQLiteCustomRepository, part_of=PersonSQLite, database="sqlite" + ) custom_test_domain.repository_for(PersonSQLite) repo_cls_constructed = custom_test_domain.providers._repositories[ diff --git a/tests/repository/test_repository_registration.py b/tests/repository/test_repository_registration.py index a5315860..8e44f61c 100644 --- a/tests/repository/test_repository_registration.py +++ b/tests/repository/test_repository_registration.py @@ -1,7 +1,7 @@ import pytest from protean import BaseRepository -from protean.exceptions import IncorrectUsageError +from protean.exceptions import IncorrectUsageError, NotSupportedError from protean.fields import String from protean.utils import fully_qualified_name @@ -10,7 +10,7 @@ class TestRepositoryInitialization: def test_that_base_repository_class_cannot_be_instantiated(self): - with pytest.raises(TypeError): + with pytest.raises(NotSupportedError): BaseRepository() def test_that_repository_can_be_instantiated(self, test_domain): @@ -20,26 +20,12 @@ def test_that_repository_can_be_instantiated(self, test_domain): class TestRepositoryRegistration: def test_that_repository_can_be_registered_with_domain(self, test_domain): - test_domain.register(PersonRepository) + test_domain.register(PersonRepository, part_of=Person) assert ( fully_qualified_name(PersonRepository) in test_domain.registry.repositories ) - def test_that_repository_can_be_registered_via_annotations(self, test_domain): - @test_domain.repository - class AnnotatedRepository: - def special_method(self): - pass - - class Meta: - part_of = Person - - assert ( - fully_qualified_name(AnnotatedRepository) - in test_domain.registry.repositories - ) - def test_that_repository_can_be_registered_via_annotations_with_aggregate_cls_parameter( self, test_domain ): @@ -66,7 +52,7 @@ def special_method(self): def test_that_repository_can_be_retrieved_from_domain_by_its_aggregate_cls( self, test_domain ): - test_domain.register(PersonRepository) + test_domain.register(PersonRepository, part_of=Person) assert isinstance(test_domain.repository_for(Person), PersonRepository) @@ -127,55 +113,40 @@ def test_retrieving_the_database_specific_repository(self, test_domain): class User: name = String() - @test_domain.repository(part_of=User) + @test_domain.repository(part_of=User, database="memory") class UserMemoryRepository: def special_method(self): pass - class Meta: - database = "memory" - - @test_domain.repository(part_of=User) + @test_domain.repository(part_of=User, database="elasticsearch") class UserElasticRepository: def special_method(self): pass - class Meta: - database = "elasticsearch" - assert isinstance(test_domain.repository_for(User), UserMemoryRepository) # Next, we test for a secondary database repository by relinking the User aggregate - @test_domain.aggregate + @test_domain.aggregate(provider="secondary") class User: name = String() - class Meta: - provider = "secondary" - assert isinstance(test_domain.repository_for(User), UserElasticRepository) # FIXME Reset test_domain? def test_incorrect_usage_error_on_repositories_associated_with_invalid_databases( self, test_domain ): - @test_domain.aggregate + @test_domain.aggregate(provider="secondary") class User: name = String() - class Meta: - provider = "secondary" - with pytest.raises(IncorrectUsageError) as exc: - @test_domain.repository(part_of=User) + @test_domain.repository(part_of=User, database="UNKNOWN") class CustomUserRepository: def special_method(self): pass - class Meta: - database = "UNKNOWN" - assert exc.value.messages == { "_entity": [ "Repository `CustomUserRepository` should be associated with a valid Database" diff --git a/tests/serializer/test_list_field.py b/tests/serializer/test_list_field.py index 796e3673..e76b63b8 100644 --- a/tests/serializer/test_list_field.py +++ b/tests/serializer/test_list_field.py @@ -14,9 +14,6 @@ class Qux(BaseAggregate): class FooRepresentation(BaseSerializer): bars = List(content_type=Dict) - class Meta: - part_of = Qux - def test_that_list_of_dicts_are_serialized_correctly(): serialized = FooRepresentation().dump(Qux(bars=[{"a": 1, "b": 1}])) diff --git a/tests/serializer/tests.py b/tests/serializer/tests.py index 53d77213..e2686134 100644 --- a/tests/serializer/tests.py +++ b/tests/serializer/tests.py @@ -1,6 +1,7 @@ import pytest from protean import BaseSerializer +from protean.exceptions import NotSupportedError from protean.fields import Integer, String from protean.reflection import declared_fields from protean.utils import fully_qualified_name @@ -10,7 +11,7 @@ class TestSerializerInitialization: def test_that_base_serializer_class_cannot_be_instantiated(self): - with pytest.raises(TypeError): + with pytest.raises(NotSupportedError): BaseSerializer() def test_that_a_concrete_serializer_can_be_instantiated(self): @@ -37,9 +38,6 @@ class PersonSchema: name = String(required=True) age = Integer(required=True) - class Meta: - part_of = User - assert fully_qualified_name(PersonSchema) in test_domain.registry.serializers diff --git a/tests/server/test_any_event_handler.py b/tests/server/test_any_event_handler.py index 150504bc..cea72431 100644 --- a/tests/server/test_any_event_handler.py +++ b/tests/server/test_any_event_handler.py @@ -27,9 +27,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - class UserEventHandler(BaseEventHandler): @handle("$any") @@ -40,7 +37,7 @@ def increment(self, event: BaseEventHandler) -> None: @pytest.mark.asyncio async def test_that_an_event_handler_can_be_associated_with_an_all_stream(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) identifier = str(uuid4()) diff --git a/tests/server/test_command_handler_subscription.py b/tests/server/test_command_handler_subscription.py index c49474a4..1a057bf7 100644 --- a/tests/server/test_command_handler_subscription.py +++ b/tests/server/test_command_handler_subscription.py @@ -37,6 +37,9 @@ def activate(self, command: Activate) -> None: @pytest.fixture(autouse=True) def register(test_domain): + test_domain.register(User) + test_domain.register(Register, part_of=User) + test_domain.register(Activate, part_of=User) test_domain.register(UserCommandHandler, part_of=User) diff --git a/tests/server/test_command_handling.py b/tests/server/test_command_handling.py index 0e8ac2d0..bc532241 100644 --- a/tests/server/test_command_handling.py +++ b/tests/server/test_command_handling.py @@ -20,16 +20,10 @@ class Register(BaseCommand): user_id = Identifier() email = String() - class Meta: - part_of = User - class Activate(BaseCommand): user_id = Identifier() - class Meta: - part_of = User - def dummy(*args): global counter @@ -49,8 +43,8 @@ def activate(self, command: Activate) -> None: @pytest.mark.asyncio async def test_handler_invocation(test_domain): test_domain.register(User) - test_domain.register(Register) - test_domain.register(Activate) + test_domain.register(Register, part_of=User) + test_domain.register(Activate, part_of=User) test_domain.register(UserCommandHandler, part_of=User) identifier = str(uuid4()) diff --git a/tests/server/test_engine_run.py b/tests/server/test_engine_run.py index 6c242c77..b4e124aa 100644 --- a/tests/server/test_engine_run.py +++ b/tests/server/test_engine_run.py @@ -18,18 +18,12 @@ def count_up(): class UserLoggedIn(BaseEvent): user_id = Identifier(identifier=True) - class Meta: - stream_name = "authentication" - class UserEventHandler(BaseEventHandler): @handle(UserLoggedIn) def count_users(self, event: UserLoggedIn) -> None: count_up() - class Meta: - stream_name = "authentication" - @pytest.fixture(autouse=True) def auto_set_and_close_loop(): @@ -45,10 +39,13 @@ def auto_set_and_close_loop(): asyncio.set_event_loop(None) # Explicitly unset the loop -def test_processing_messages_on_start(test_domain): - test_domain.register(UserLoggedIn) - test_domain.register(UserEventHandler) +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(UserLoggedIn, stream_name="authentication") + test_domain.register(UserEventHandler, stream_name="authentication") + +def test_processing_messages_on_start(test_domain): identifier = str(uuid4()) event = UserLoggedIn(user_id=identifier) test_domain.event_store.store.append(event) @@ -61,9 +58,6 @@ def test_processing_messages_on_start(test_domain): def test_that_read_position_is_updated_after_engine_run(test_domain): - test_domain.register(UserLoggedIn) - test_domain.register(UserEventHandler) - identifier = str(uuid4()) event = UserLoggedIn(user_id=identifier) test_domain.event_store.store.append(event) @@ -79,9 +73,6 @@ def test_that_read_position_is_updated_after_engine_run(test_domain): def test_processing_messages_from_beginning_the_first_time(test_domain): - test_domain.register(UserLoggedIn) - test_domain.register(UserEventHandler) - identifier = str(uuid4()) event = UserLoggedIn(user_id=identifier) test_domain.event_store.store.append(event) diff --git a/tests/server/test_error_handling.py b/tests/server/test_error_handling.py index 3b012d9d..ec0f86a6 100644 --- a/tests/server/test_error_handling.py +++ b/tests/server/test_error_handling.py @@ -22,9 +22,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - def some_function(): raise Exception("Some exception") @@ -53,7 +50,7 @@ def auto_set_and_close_loop(): @pytest.mark.asyncio async def test_that_exception_is_raised(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) identifier = str(uuid4()) @@ -80,7 +77,7 @@ async def test_that_exception_is_raised(test_domain): def test_exceptions_stop_processing(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) identifier = str(uuid4()) diff --git a/tests/server/test_event_handler_subscription.py b/tests/server/test_event_handler_subscription.py index 307f4f23..8768236b 100644 --- a/tests/server/test_event_handler_subscription.py +++ b/tests/server/test_event_handler_subscription.py @@ -72,6 +72,7 @@ def setup_event_loop(): def test_event_subscriptions(test_domain): + test_domain.register(User) test_domain.register(UserEventHandler, part_of=User) engine = Engine(test_domain, test_mode=True) @@ -81,6 +82,7 @@ def test_event_subscriptions(test_domain): def test_origin_stream_name_in_subscription(test_domain): + test_domain.register(User) test_domain.register(EmailEventHandler, part_of=User, source_stream="email") engine = Engine(test_domain, test_mode=True) diff --git a/tests/server/test_event_handling.py b/tests/server/test_event_handling.py index 937cbd4b..338246a5 100644 --- a/tests/server/test_event_handling.py +++ b/tests/server/test_event_handling.py @@ -24,9 +24,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - def count_up(): global counter @@ -42,7 +39,7 @@ def send_notification(self, event: Registered) -> None: @pytest.mark.asyncio async def test_handler_invocation(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) identifier = str(uuid4()) diff --git a/tests/server/test_handling_all_events.py b/tests/server/test_handling_all_events.py index 36f1673b..11e33abf 100644 --- a/tests/server/test_handling_all_events.py +++ b/tests/server/test_handling_all_events.py @@ -27,9 +27,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - class Post(BaseEventSourcedAggregate): topic = String() @@ -41,27 +38,21 @@ class Created(BaseEvent): topic = String() content = Text() - class Meta: - part_of = Post - class SystemMetrics(BaseEventHandler): @handle("$any") def increment(self, event: BaseEventHandler) -> None: count_up() - class Meta: - stream_name = "$all" - @pytest.mark.asyncio @pytest.mark.eventstore async def test_that_any_message_can_be_handled_with_any_handler(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(Post) - test_domain.register(Created) - test_domain.register(SystemMetrics) + test_domain.register(Created, part_of=Post) + test_domain.register(SystemMetrics, stream_name="$all") identifier = str(uuid4()) registered = Registered( diff --git a/tests/subscription/test_read_position_updates.py b/tests/subscription/test_read_position_updates.py index e81c57dd..acb57114 100644 --- a/tests/subscription/test_read_position_updates.py +++ b/tests/subscription/test_read_position_updates.py @@ -32,25 +32,16 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - class Activated(BaseEvent): id = Identifier() activated_at = DateTime() - class Meta: - part_of = User - class Sent(BaseEvent): email = String() sent_at = DateTime() - class Meta: - stream_name = "email" - class UserEventHandler(BaseEventHandler): @handle(Registered) @@ -76,9 +67,9 @@ def record_sent_email(self, event: Sent) -> None: def register_elements(test_domain): test_domain.register(User) test_domain.register(Email) - test_domain.register(Registered) - test_domain.register(Activated) - test_domain.register(Sent) + test_domain.register(Registered, part_of=User) + test_domain.register(Activated, part_of=User) + test_domain.register(Sent, stream_name="email") test_domain.register(UserEventHandler, part_of=User) test_domain.register(EmailEventHandler, stream_name="email") diff --git a/tests/support/test_domains/test20/auth/account20.py b/tests/support/test_domains/test20/auth/account20.py index a466edcf..cafc2c53 100644 --- a/tests/support/test_domains/test20/auth/account20.py +++ b/tests/support/test_domains/test20/auth/account20.py @@ -11,10 +11,7 @@ class Account: author = HasOne("Author") -@publishing.entity +@publishing.entity(part_of=Account) class Author: first_name = String(required=True, max_length=25) last_name = String(max_length=25) - - class Meta: - part_of = Account diff --git a/tests/support/test_domains/test21/auth/account21.py b/tests/support/test_domains/test21/auth/account21.py index 4a37a23b..30c95866 100644 --- a/tests/support/test_domains/test21/auth/account21.py +++ b/tests/support/test_domains/test21/auth/account21.py @@ -11,10 +11,7 @@ class Account: author = HasOne("Author") -@publishing.entity +@publishing.entity(part_of=Account) class Author: first_name = String(required=True, max_length=25) last_name = String(max_length=25) - - class Meta: - part_of = Account diff --git a/tests/test_aggregates.py b/tests/test_aggregates.py index 9b51a25c..279ae2d9 100644 --- a/tests/test_aggregates.py +++ b/tests/test_aggregates.py @@ -57,38 +57,29 @@ class Person: username = String(identifier=True) def test_that_abstract_aggregates_get_an_id_field_by_default(self, test_domain): - @test_domain.aggregate + @test_domain.aggregate(abstract=True) class TimeStamped: created_at = DateTime(default=utcnow_func) updated_at = DateTime(default=utcnow_func) - class Meta: - abstract = True - assert "id" in declared_fields(TimeStamped) def test_that_an_aggregate_can_opt_to_have_no_id_field_by_default( self, test_domain ): - @test_domain.aggregate + @test_domain.aggregate(auto_add_id_field=False) class TimeStamped: created_at = DateTime(default=utcnow_func) updated_at = DateTime(default=utcnow_func) - class Meta: - auto_add_id_field = False - assert "id" not in declared_fields(TimeStamped) def test_that_abstract_aggregates_can_have_an_explicit_id_field(self, test_domain): - @test_domain.aggregate + @test_domain.aggregate(abstract=True) class User(BaseAggregate): email = String(identifier=True) name = String(max_length=55) - class Meta: - abstract = True - assert "email" in declared_fields(User) @@ -109,14 +100,11 @@ class Post: comments = HasMany("Comment") - @test_domain.entity + @test_domain.entity(part_of=Post) class Comment: content = String(max_length=500) post = Reference("Post") - class Meta: - part_of = Post - test_domain.init(traverse=False) post = Post(name="The World") diff --git a/tests/test_brokers.py b/tests/test_brokers.py index a281acf8..3aa59ac1 100644 --- a/tests/test_brokers.py +++ b/tests/test_brokers.py @@ -3,7 +3,6 @@ from protean import ( BaseAggregate, BaseCommand, - BaseCommandHandler, BaseEvent, BaseSubscriber, ) @@ -25,14 +24,8 @@ class PersonAdded(BaseEvent): last_name = String(max_length=50, required=True) age = Integer(default=21) - class Meta: - part_of = Person - class NotifySSOSubscriber(BaseSubscriber): - class Meta: - event = PersonAdded - def __call__(self, domain_event_dict): print("Received Event: ", domain_event_dict) @@ -43,21 +36,14 @@ class AddPersonCommand(BaseCommand): age = Integer(default=21) -class AddNewPersonCommandHandler(BaseCommandHandler): - """CommandHandler that adds a new person into the system""" - - class Meta: - command_cls = AddPersonCommand - - def notify(self, command): - print("Received command: ", command) +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(Person) + test_domain.register(PersonAdded, part_of=Person) + test_domain.register(NotifySSOSubscriber, event=PersonAdded) class TestBrokerInitialization: - @pytest.fixture(autouse=True) - def register_elements(self, test_domain): - test_domain.register(PersonAdded) - def test_that_base_broker_class_cannot_be_instantiated(self): with pytest.raises(TypeError): BaseBroker() @@ -114,11 +100,6 @@ def test_that_brokers_can_be_registered_manually(self, test_domain): class TestEventPublish: - @pytest.fixture(autouse=True) - def register_elements(self, test_domain): - test_domain.register(Person) - test_domain.register(PersonAdded) - @pytest.mark.eventstore def test_that_event_is_persisted_on_publish(self, mocker, test_domain): test_domain.publish( @@ -138,8 +119,6 @@ def test_that_event_is_persisted_on_publish(self, mocker, test_domain): class TestBrokerSubscriberInitialization: def test_that_registered_subscribers_are_initialized(self, test_domain): - test_domain.register(NotifySSOSubscriber) - test_domain._initialize() assert ( @@ -156,8 +135,7 @@ def test_that_registered_subscribers_are_initialized(self, test_domain): def test_that_subscribers_with_unknown_brokers_cannot_be_initialized( self, test_domain ): - NotifySSOSubscriber.meta_.broker = "unknown" - test_domain.register(NotifySSOSubscriber) + test_domain.register(NotifySSOSubscriber, event=PersonAdded, broker="unknown") with pytest.raises(ConfigurationError) as exc: test_domain._initialize() diff --git a/tests/test_commands.py b/tests/test_commands.py index 165c5ad9..b37aa540 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -20,9 +20,6 @@ class UserRegistrationCommand(BaseCommand): password = String(required=True, max_length=255) age = Integer(default=21) - class Meta: - part_of = User - class TestCommandInitialization: def test_that_command_object_class_cannot_be_instantiated(self): @@ -59,7 +56,7 @@ def test_that_invalid_data_input_throws_an_exception(self): class TestCommandRegistration: def test_that_command_can_be_registered_with_domain(self, test_domain): - test_domain.register(UserRegistrationCommand) + test_domain.register(UserRegistrationCommand, part_of=User) assert ( fully_qualified_name(UserRegistrationCommand) @@ -121,9 +118,6 @@ class TestCommandInheritance: class AbstractCommand(BaseCommand): foo = String() - class Meta: - abstract = True - class ConcreteCommand(AbstractCommand): bar = String() @@ -134,13 +128,10 @@ def test_inheritance_of_parent_fields(self): ) def test_inheritance_of_parent_fields_with_annotations(self, test_domain): - @test_domain.command + @test_domain.command(abstract=True) class AbstractCommand2: foo = String() - class Meta: - abstract = True - @test_domain.command(part_of=User) class ConcreteCommand2(AbstractCommand2): bar = String() diff --git a/tests/test_registry.py b/tests/test_registry.py index 264bc5c9..409aa402 100644 --- a/tests/test_registry.py +++ b/tests/test_registry.py @@ -21,9 +21,6 @@ class Role(BaseEntity): name = String(max_length=15, required=True) created_on = DateTime(default=datetime.today()) - class Meta: - part_of = User - def test_element_registration(): register = _DomainRegistry() diff --git a/tests/test_subscribers.py b/tests/test_subscribers.py index 78a0caee..5aae188a 100644 --- a/tests/test_subscribers.py +++ b/tests/test_subscribers.py @@ -1,6 +1,7 @@ import pytest from protean import BaseEvent, BaseSubscriber +from protean.exceptions import NotSupportedError from protean.fields import Identifier, Integer, String from protean.utils import fully_qualified_name @@ -17,16 +18,13 @@ class NotifySSOSubscriber(BaseSubscriber): that a new person was added into the system """ - class Meta: - event = PersonAdded - def notify(self, event): print("Received Event: ", event) class TestSubscriberInitialization: def test_that_base_subscriber_class_cannot_be_instantiated(self): - with pytest.raises(TypeError): + with pytest.raises(NotSupportedError): BaseSubscriber() def test_that_subscriber_can_be_instantiated(self, test_domain): @@ -36,7 +34,7 @@ def test_that_subscriber_can_be_instantiated(self, test_domain): class TestSubscriberRegistration: def test_that_domain_event_can_be_registered_with_domain(self, test_domain): - test_domain.register(NotifySSOSubscriber) + test_domain.register(NotifySSOSubscriber, event=PersonAdded) assert ( fully_qualified_name(NotifySSOSubscriber) diff --git a/tests/unit_of_work/aggregate_elements.py b/tests/unit_of_work/aggregate_elements.py index 0fbe489f..f65c65fb 100644 --- a/tests/unit_of_work/aggregate_elements.py +++ b/tests/unit_of_work/aggregate_elements.py @@ -19,9 +19,6 @@ class PostMeta(BaseEntity): post = Reference(Post) - class Meta: - part_of = Post - class Comment(BaseEntity): content = Text(required=True) @@ -29,9 +26,6 @@ class Comment(BaseEntity): post = Reference(Post) - class Meta: - part_of = Post - class PostRepository(BaseRepository): pass diff --git a/tests/unit_of_work/test_child_object_persistence.py b/tests/unit_of_work/test_child_object_persistence.py index 43b65e91..d7326721 100644 --- a/tests/unit_of_work/test_child_object_persistence.py +++ b/tests/unit_of_work/test_child_object_persistence.py @@ -9,8 +9,8 @@ class TestUnitOfWorkRegistration: @pytest.fixture(autouse=True) def register_elements(self, test_domain): test_domain.register(Post) - test_domain.register(PostMeta) - test_domain.register(Comment) + test_domain.register(PostMeta, part_of=Post) + test_domain.register(Comment, part_of=Post) test_domain.register(PostRepository, part_of=Post) diff --git a/tests/unit_of_work/test_inline_event_processing.py b/tests/unit_of_work/test_inline_event_processing.py index 2ab61d29..4d9dcd34 100644 --- a/tests/unit_of_work/test_inline_event_processing.py +++ b/tests/unit_of_work/test_inline_event_processing.py @@ -89,16 +89,13 @@ class UserMetrics(BaseEventHandler): def count_registrations(self, _: BaseEventHandler) -> None: count_up() - class Meta: - part_of = User - @pytest.mark.eventstore def test_inline_event_processing_in_sync_mode(test_domain): test_domain.register(User) - test_domain.register(Registered) + test_domain.register(Registered, part_of=User) test_domain.register(UserEventHandler, part_of=User) - test_domain.register(UserMetrics) + test_domain.register(UserMetrics, part_of=User) identifier = str(uuid4()) UserCommandHandler().register_user( diff --git a/tests/unit_of_work/test_nested_inline_event_processing.py b/tests/unit_of_work/test_nested_inline_event_processing.py index fae344b7..f9a90875 100644 --- a/tests/unit_of_work/test_nested_inline_event_processing.py +++ b/tests/unit_of_work/test_nested_inline_event_processing.py @@ -52,9 +52,6 @@ class Create(BaseCommand): topic = String() content = Text() - class Meta: - part_of = Post - class Created(BaseEvent): id = Identifier(identifier=True) @@ -88,15 +85,15 @@ def record_publishing(self, _: Published) -> None: global published_count published_count += 1 - class Meta: - stream_name = "post" - @pytest.mark.eventstore def test_nested_uow_processing(test_domain): test_domain.register(Post) + test_domain.register(Create, part_of=Post) + test_domain.register(Created, part_of=Post) + test_domain.register(Published, part_of=Post) test_domain.register(PostEventHandler, part_of=Post) - test_domain.register(Metrics) + test_domain.register(Metrics, stream_name="post") identifier = str(uuid4()) PostCommandHandler().create_new_post( diff --git a/tests/unit_of_work/test_storing_events_on_commit.py b/tests/unit_of_work/test_storing_events_on_commit.py index 2136c3f6..036e9e6b 100644 --- a/tests/unit_of_work/test_storing_events_on_commit.py +++ b/tests/unit_of_work/test_storing_events_on_commit.py @@ -51,9 +51,6 @@ class Registered(BaseEvent): name = String() password_hash = String() - class Meta: - part_of = User - class UserCommandHandler(BaseCommandHandler): @handle(Register) diff --git a/tests/value_object/tests.py b/tests/value_object/tests.py index 415d8e16..128187a0 100644 --- a/tests/value_object/tests.py +++ b/tests/value_object/tests.py @@ -16,12 +16,11 @@ ) -def test_vo_marked_abstract_cannot_be_instantiated(): +def test_vo_marked_abstract_cannot_be_instantiated(test_domain): class AbstractBalance(Balance): amount = Float() - class Meta: - abstract = True + test_domain.register(AbstractBalance, abstract=True) with pytest.raises(NotSupportedError) as exc: AbstractBalance(amount=100.0) diff --git a/tests/views/test_view_validations_for_fields.py b/tests/views/test_view_validations_for_fields.py index 67228823..3741f427 100644 --- a/tests/views/test_view_validations_for_fields.py +++ b/tests/views/test_view_validations_for_fields.py @@ -12,22 +12,17 @@ class User(BaseAggregate): class Email(BaseValueObject): address = String() - class Meta: - part_of = "User" - class Role(BaseEntity): name = String(max_length=50) - class Meta: - part_of = "User" +def test_that_views_should_have_at_least_one_identifier_field(test_domain): + class User(BaseView): + first_name = String() -def test_that_views_should_have_at_least_one_identifier_field(): with pytest.raises(IncorrectUsageError) as exception: - - class User(BaseView): - first_name = String() + test_domain.register(User) assert ( exception.value.messages["_entity"][0] diff --git a/tests/views/tests.py b/tests/views/tests.py index 3071cf61..83683ccf 100644 --- a/tests/views/tests.py +++ b/tests/views/tests.py @@ -1,9 +1,9 @@ +import pytest + from collections import defaultdict from enum import Enum from uuid import uuid4 -import pytest - from protean import BaseView from protean.container import Options from protean.exceptions import InvalidOperationError, ValidationError @@ -15,9 +15,6 @@ class AbstractPerson(BaseView): age = Integer(default=5) - class Meta: - abstract = True - class ConcretePerson(BaseView): person_id = Identifier(identifier=True) @@ -49,9 +46,6 @@ class PersonExplicitID(BaseView): class Adult(Person): pass - class Meta: - schema_name = "adults" - class NotAPerson(BaseView): identifier = Identifier(identifier=True) @@ -67,23 +61,17 @@ class DbPerson(BaseView): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - schema_name = "peoples" - class SqlPerson(Person): - class Meta: - schema_name = "people" + pass class DifferentDbPerson(Person): - class Meta: - provider = "non-default" + pass class SqlDifferentDbPerson(Person): - class Meta: - provider = "non-default-sql" + pass class OrderedPerson(BaseView): @@ -92,13 +80,9 @@ class OrderedPerson(BaseView): last_name = String(max_length=50) age = Integer(default=21) - class Meta: - order_by = "first_name" - class OrderedPersonSubclass(Person): - class Meta: - order_by = "last_name" + pass class BuildingStatus(Enum): @@ -128,6 +112,23 @@ def _postcheck(self): return errors +@pytest.fixture(autouse=True) +def register_elements(test_domain): + test_domain.register(AbstractPerson, abstract=True) + test_domain.register(Person) + test_domain.register(PersonAutoSSN) + test_domain.register(PersonExplicitID) + test_domain.register(Adult) + test_domain.register(NotAPerson) + test_domain.register(DbPerson, schema_name="peoples") + test_domain.register(SqlPerson, schema_name="people") + test_domain.register(DifferentDbPerson, provider="non-default") + test_domain.register(SqlDifferentDbPerson, provider="non-default-sql") + test_domain.register(OrderedPerson, order_by="first_name") + test_domain.register(OrderedPersonSubclass, order_by="last_name") + test_domain.register(Building) + + class TestViewRegistration: def test_manual_registration_of_view(self, test_domain): class Comment(BaseView):