コード例 #1
0
    def prep_class(cls, element_cls, **kwargs):
        if issubclass(element_cls, BaseDomainEvent):
            new_element_cls = element_cls
        else:
            try:
                new_dict = element_cls.__dict__.copy()
                new_dict.pop('__dict__', None)  # Remove __dict__ to prevent recursion

                new_element_cls = type(element_cls.__name__, (BaseDomainEvent, ), new_dict)
            except BaseException as exc:
                logger.debug("Error during Element registration:", repr(exc))
                raise IncorrectUsageError(
                    "Invalid class {element_cls.__name__} for type {element_type.value}"
                    " (Error: {exc})",
                    )

        if hasattr(new_element_cls, 'meta_'):
            if not (hasattr(new_element_cls.meta_, 'aggregate_cls') and new_element_cls.meta_.aggregate_cls):
                new_element_cls.meta_.aggregate_cls = kwargs.pop('aggregate_cls', None)

            new_element_cls.meta_.bounded_context = kwargs.pop('bounded_context', None)

        if not new_element_cls.meta_.aggregate_cls:
            raise IncorrectUsageError("Domain Events need to be associated with an Aggregate")

        return new_element_cls
コード例 #2
0
ファイル: aggregate.py プロジェクト: advishnuprasad/protean
    def prep_class(cls, element_cls, **kwargs):
        if issubclass(element_cls, BaseAggregate):
            new_element_cls = element_cls
        else:
            try:
                new_dict = element_cls.__dict__.copy()
                new_dict.pop('__dict__',
                             None)  # Remove __dict__ to prevent recursion

                new_element_cls = type(element_cls.__name__, (BaseAggregate, ),
                                       new_dict)
            except BaseException as exc:
                logger.debug("Error during Element registration:", repr(exc))
                raise IncorrectUsageError(
                    "Invalid class {element_cls.__name__} for type {element_type.value}"
                    " (Error: {exc})", )

        cls._validate_aggregate_class(new_element_cls)

        new_element_cls.meta_.provider = (kwargs.pop('provider', None) or
                                          (hasattr(new_element_cls, 'meta_')
                                           and new_element_cls.meta_.provider)
                                          or 'default')
        new_element_cls.meta_.model = (kwargs.pop('model', None)
                                       or (hasattr(new_element_cls, 'meta_')
                                           and new_element_cls.meta_.model)
                                       or None)
        new_element_cls.meta_.bounded_context = (
            kwargs.pop('bounded_context', None)
            or (hasattr(new_element_cls, 'meta_')
                and new_element_cls.meta_.bounded_context))

        return new_element_cls
コード例 #3
0
def entity_factory(element_cls, **kwargs):
    element_cls = derive_element_class(element_cls, BaseEntity)

    if element_cls.meta_.abstract is True:
        raise NotSupportedError(
            f"{element_cls.__name__} class has been marked abstract"
            f" and cannot be instantiated")

    element_cls.meta_.provider = (kwargs.pop("provider", None)
                                  or (hasattr(element_cls, "meta_")
                                      and element_cls.meta_.provider)
                                  or "default")
    element_cls.meta_.model = (kwargs.pop("model", None)
                               or (hasattr(element_cls, "meta_")
                                   and element_cls.meta_.model) or None)
    element_cls.meta_.aggregate_cls = (kwargs.pop("aggregate_cls", None)
                                       or (hasattr(element_cls, "meta_")
                                           and element_cls.meta_.aggregate_cls)
                                       or None)

    if not element_cls.meta_.aggregate_cls:
        raise IncorrectUsageError(
            f"Entity `{element_cls.__name__}` needs to be associated with an Aggregate"
        )

    return element_cls
コード例 #4
0
ファイル: subscriber.py プロジェクト: advishnuprasad/protean
    def prep_class(cls, element_cls, **kwargs):
        if issubclass(element_cls, BaseSubscriber):
            new_element_cls = element_cls
        else:
            try:
                new_dict = element_cls.__dict__.copy()
                new_dict.pop('__dict__',
                             None)  # Remove __dict__ to prevent recursion

                new_element_cls = type(element_cls.__name__,
                                       (BaseSubscriber, ), new_dict)
            except BaseException as exc:
                logger.debug("Error during Element registration:", repr(exc))
                raise IncorrectUsageError(
                    "Invalid class {element_cls.__name__} for type {element_type.value}"
                    " (Error: {exc})", )

        cls._validate_subscriber_class(new_element_cls)

        new_element_cls.meta_.domain_event = (kwargs.pop(
            'domain_event', None) or (hasattr(new_element_cls, 'meta_')
                                      and new_element_cls.meta_.domain_event)
                                              or None)
        new_element_cls.meta_.broker = (kwargs.pop('broker', None)
                                        or (hasattr(new_element_cls, 'meta_')
                                            and new_element_cls.meta_.broker)
                                        or 'default')
        new_element_cls.meta_.bounded_context = (
            kwargs.pop('bounded_context', None)
            or (hasattr(new_element_cls, 'meta_')
                and new_element_cls.meta_.bounded_context))
        new_element_cls.meta_.aggregate_cls = (kwargs.pop(
            'aggregate_cls', None) or (hasattr(new_element_cls, 'meta_')
                                       and new_element_cls.meta_.aggregate_cls)
                                               or None)

        if not new_element_cls.meta_.domain_event:
            raise IncorrectUsageError(
                f"Subscriber `{new_element_cls.__name__}` needs to be associated with a Domain Event"
            )

        return new_element_cls
コード例 #5
0
def value_object_factory(element_cls, **kwargs):
    element_cls = derive_element_class(element_cls, BaseValueObject)

    if not (hasattr(element_cls.meta_, "aggregate_cls")
            and element_cls.meta_.aggregate_cls):
        element_cls.meta_.aggregate_cls = kwargs.pop("aggregate_cls", None)

    if not element_cls.meta_.aggregate_cls:
        raise IncorrectUsageError(
            "Value Objects need to be associated with an Aggregate")

    return element_cls
コード例 #6
0
ファイル: subscriber.py プロジェクト: nadirhamid/protean
def subscriber_factory(element_cls, **kwargs):
    element_cls = derive_element_class(element_cls, BaseSubscriber)

    element_cls.meta_.domain_event = (kwargs.pop("domain_event", None)
                                      or (hasattr(element_cls, "meta_")
                                          and element_cls.meta_.domain_event)
                                      or None)

    element_cls.meta_.broker = (kwargs.pop("broker", None)
                                or (hasattr(element_cls, "meta_")
                                    and element_cls.meta_.broker) or "default")

    if not element_cls.meta_.domain_event:
        raise IncorrectUsageError(
            f"Subscriber `{element_cls.__name__}` needs to be associated with a Domain Event"
        )

    if not element_cls.meta_.broker:
        raise IncorrectUsageError(
            f"Subscriber `{element_cls.__name__}` needs to be associated with a Broker"
        )

    return element_cls
コード例 #7
0
def derive_element_class(element_cls, base_cls):
    if not issubclass(element_cls, base_cls):
        try:
            new_dict = element_cls.__dict__.copy()
            new_dict.pop("__dict__",
                         None)  # Remove __dict__ to prevent recursion

            element_cls = type(element_cls.__name__, (base_cls, ), new_dict)
        except BaseException as exc:
            logger.debug("Error during Element registration:", repr(exc))
            raise IncorrectUsageError(
                "Invalid class {element_cls.__name__} for type {element_type.value}"
                " (Error: {exc})", )

    return element_cls
コード例 #8
0
def repository_factory(element_cls, **kwargs):
    element_cls = derive_element_class(element_cls, BaseRepository)

    if not (hasattr(element_cls.meta_, "aggregate_cls")
            and element_cls.meta_.aggregate_cls):
        element_cls.meta_.aggregate_cls = kwargs.pop("aggregate_cls", None)

    if not (hasattr(element_cls.meta_, "database")
            and element_cls.meta_.database):
        element_cls.meta_.database = kwargs.pop("database", "ALL")

    if not element_cls.meta_.aggregate_cls:
        raise IncorrectUsageError(
            "Repositories need to be associated with an Aggregate")

    return element_cls
コード例 #9
0
    def factory_for(self, domain_object_type):
        # Protean
        from protean.core.aggregate import aggregate_factory
        from protean.core.application_service import application_service_factory
        from protean.core.command import command_factory
        from protean.core.command_handler import command_handler_factory
        from protean.core.domain_event import domain_event_factory
        from protean.core.domain_service import domain_service_factory
        from protean.core.email import email_factory
        from protean.core.entity import entity_factory
        from protean.core.model import model_factory
        from protean.core.repository import repository_factory
        from protean.core.serializer import serializer_factory
        from protean.core.subscriber import subscriber_factory
        from protean.core.value_object import value_object_factory
        from protean.core.view import view_factory

        factories = {
            DomainObjects.AGGREGATE.value: aggregate_factory,
            DomainObjects.APPLICATION_SERVICE.value:
            application_service_factory,
            DomainObjects.COMMAND.value: command_factory,
            DomainObjects.COMMAND_HANDLER.value: command_handler_factory,
            DomainObjects.DOMAIN_EVENT.value: domain_event_factory,
            DomainObjects.DOMAIN_SERVICE.value: domain_service_factory,
            DomainObjects.EMAIL.value: email_factory,
            DomainObjects.ENTITY.value: entity_factory,
            DomainObjects.MODEL.value: model_factory,
            DomainObjects.REPOSITORY.value: repository_factory,
            DomainObjects.SUBSCRIBER.value: subscriber_factory,
            DomainObjects.SERIALIZER.value: serializer_factory,
            DomainObjects.VALUE_OBJECT.value: value_object_factory,
            DomainObjects.VIEW.value: view_factory,
        }

        if domain_object_type.value not in factories:
            raise IncorrectUsageError(
                "Unknown Element Type {element_type.value} for class {element_cls.__name__} "
                " (Error: {exc})", )

        return factories[domain_object_type.value]
コード例 #10
0
def model_factory(element_cls, **kwargs):
    element_cls = derive_element_class(element_cls, BaseModel)

    if hasattr(element_cls, "Meta"):
        element_cls.meta_ = ModelMeta(element_cls.Meta)
    else:
        element_cls.meta_ = ModelMeta()

    if not (hasattr(element_cls.meta_, "entity_cls")
            and element_cls.meta_.entity_cls):
        element_cls.meta_.entity_cls = kwargs.pop("entity_cls", None)

    if not (hasattr(element_cls.meta_, "schema") and element_cls.meta_.schema):
        element_cls.meta_.schema = kwargs.pop("schema", None)

    if not (hasattr(element_cls.meta_, "database")
            and element_cls.meta_.database):
        element_cls.meta_.database = kwargs.pop("database", None)

    if not element_cls.meta_.entity_cls:
        raise IncorrectUsageError(
            "Models need to be associated with an Entity or Aggregate")

    return element_cls
コード例 #11
0
ファイル: domain.py プロジェクト: advishnuprasad/protean
    def _register_element(self, element_type, element_cls,
                          **kwargs):  # noqa: C901
        """Register class into the domain"""
        # Check if `element_cls` is already a subclass of the Element Type
        #   which would be the case in an explicit declaration like `class Account(BaseEntity):`
        #
        # We will need to construct a class derived from the right base class
        #   if the Element was specified through annotation, like so:
        #
        #  ```
        #       @Entity
        #       class Account:
        #  ```

        if element_type == DomainObjects.VALUE_OBJECT:
            from protean.core.value_object import ValueObjectFactory
            new_cls = ValueObjectFactory.prep_class(element_cls, **kwargs)
        elif element_type == DomainObjects.REPOSITORY:
            from protean.core.repository.base import RepositoryFactory
            new_cls = RepositoryFactory.prep_class(element_cls, **kwargs)
        elif element_type == DomainObjects.AGGREGATE:
            from protean.core.aggregate import AggregateFactory
            new_cls = AggregateFactory.prep_class(element_cls, **kwargs)
        elif element_type == DomainObjects.ENTITY:
            from protean.core.entity import EntityFactory
            new_cls = EntityFactory.prep_class(element_cls, **kwargs)
        elif element_type == DomainObjects.SUBSCRIBER:
            from protean.core.broker.subscriber import SubscriberFactory
            new_cls = SubscriberFactory.prep_class(element_cls, **kwargs)
        elif element_type == DomainObjects.DOMAIN_EVENT:
            from protean.core.domain_event import DomainEventFactory
            new_cls = DomainEventFactory.prep_class(element_cls, **kwargs)
        else:
            try:
                if not issubclass(element_cls,
                                  self.base_class_mapping[element_type.value]):
                    new_dict = element_cls.__dict__.copy()
                    new_dict.pop('__dict__',
                                 None)  # Remove __dict__ to prevent recursion

                    # Hack to switch between `marshmallow.Schema` and `BaseSerializer`
                    #   while creating the derived class for Serializers
                    #
                    # This becomes necessary because we need to derive the undecorated class
                    #   from `BaseSerializer`, but once derived, the base hierarchy only reflects
                    #   `marshmallow.Schema` (This is a metaclass, so it disrupts hierarchy).
                    if element_type == DomainObjects.SERIALIZER:
                        from protean.core.serializer import BaseSerializer
                        base_cls = BaseSerializer
                    else:
                        base_cls = self.base_class_mapping[element_type.value]

                    new_cls = type(element_cls.__name__, (base_cls, ),
                                   new_dict)
                else:
                    new_cls = element_cls  # Element was already subclassed properly
            except BaseException as exc:
                logger.debug("Error during Element registration:", repr(exc))
                raise IncorrectUsageError(
                    "Invalid class {element_cls.__name__} for type {element_type.value}"
                    " (Error: {exc})", )

            aggregate_cls = None

            if (element_type == DomainObjects.MODEL
                    and self._validate_model_class(new_cls)):
                # Associate aggregate/entity class with model if `entity_cls` was supplied as an explicit parameter
                from protean.core.repository.model import ModelMeta
                if hasattr(new_cls, 'Meta'):
                    new_cls.meta_ = ModelMeta(new_cls.Meta)
                else:
                    new_cls.meta_ = ModelMeta()

                entity_cls = new_cls.meta_.entity_cls or kwargs.pop(
                    'entity_cls', None)
                if not entity_cls:
                    raise IncorrectUsageError(
                        "Models need to be associated with an Entity or Aggregate"
                    )

                if not new_cls.meta_.entity_cls:
                    new_cls.meta_.entity_cls = entity_cls

                # Remember model association with aggregate/entity class, for easy fetching
                self._models[fully_qualified_name(entity_cls)] = new_cls

            if element_type == DomainObjects.COMMAND_HANDLER and self._validate_command_handler_class(
                    new_cls):
                command_cls = new_cls.meta_.command_cls or kwargs.pop(
                    'command', None)
                broker_name = new_cls.meta_.broker or 'default'
                if not command_cls:
                    raise IncorrectUsageError(
                        "Command Handlers need to be associated with a Command"
                    )

                new_cls.meta_.command_cls = command_cls
                new_cls.meta_.broker = broker_name

            if element_type == DomainObjects.EMAIL and self._validate_email_class(
                    new_cls):
                provider_name = new_cls.meta_.provider or 'default'
                new_cls.meta_.provider = provider_name

            # Enrich element with domain information
            if hasattr(new_cls, 'meta_'):
                new_cls.meta_.aggregate_cls = aggregate_cls or kwargs.pop(
                    'aggregate_cls', None)
                new_cls.meta_.bounded_context = kwargs.pop(
                    'bounded_context', None)

        # Register element with domain
        self._domain_registry.register_element(new_cls)

        return new_cls