Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove support for inner Meta class #433

Merged
merged 2 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions src/protean/adapters/event_store/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 4 additions & 2 deletions src/protean/adapters/repository/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
35 changes: 11 additions & 24 deletions src/protean/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
# <OuterClass>.<InnerClass>.
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__()
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand Down
6 changes: 2 additions & 4 deletions src/protean/core/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down
6 changes: 2 additions & 4 deletions src/protean/core/application_service.py
Original file line number Diff line number Diff line change
@@ -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__)
Expand All @@ -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
Expand Down
13 changes: 10 additions & 3 deletions src/protean/core/command.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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__()
Expand Down
2 changes: 1 addition & 1 deletion src/protean/core/command_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
7 changes: 2 additions & 5 deletions src/protean/core/domain_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -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__)
Expand All @@ -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
Expand Down
13 changes: 0 additions & 13 deletions src/protean/core/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,6 @@ class User(BaseEntity):

element_type = DomainObjects.ENTITY

class Meta:
abstract = True

def __init_subclass__(subclass) -> None:
super().__init_subclass__()

Expand Down Expand Up @@ -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(
{
Expand Down
8 changes: 5 additions & 3 deletions src/protean/core/event.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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__()
Expand Down
13 changes: 5 additions & 8 deletions src/protean/core/event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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):
Expand All @@ -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)
Expand Down
8 changes: 5 additions & 3 deletions src/protean/core/event_sourced_aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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):
Expand Down
8 changes: 6 additions & 2 deletions src/protean/core/event_sourced_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand Down
4 changes: 2 additions & 2 deletions src/protean/core/model.py
Original file line number Diff line number Diff line change
@@ -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


Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/protean/core/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion src/protean/core/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)


Expand Down
Loading
Loading