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

Clean up Exception structures #449

Merged
merged 5 commits into from
Jul 27, 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
5 changes: 1 addition & 4 deletions docs/guides/change-state/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ Out[3]: <PublishArticle: PublishArticle object ({'article_id': '1', 'published_a

In [4]: publish_article_command.published_at = datetime.now() - timedelta(hours=24)
...
IncorrectUsageError: {
'_command': [
'Command Objects are immutable and cannot be modified once created'
]
IncorrectUsageError: 'Command Objects are immutable and cannot be modified once created'
}
```
4 changes: 2 additions & 2 deletions docs/guides/domain-definition/entities.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ specified while defining the identity, you will see an `IncorrectUsageError`:
... class Comment:
... content = String(max_length=500)
...
IncorrectUsageError: {'_entity': ['Entity `Comment` needs to be associated with an Aggregate']}
IncorrectUsageError: 'Entity `Comment` needs to be associated with an Aggregate'
```

An Entity cannot enclose another Entity (or Aggregate). Trying to do so will
Expand All @@ -44,7 +44,7 @@ throw `IncorrectUsageError`.
... class SubComment:
... parent = Comment()
...
IncorrectUsageError: {'_entity': ['Entity `Comment` needs to be associated with an Aggregate']}
IncorrectUsageError: 'Entity `Comment` needs to be associated with an Aggregate'
```
<!-- FIXME Ensure entities cannot enclose other entities. When entities
enclose something other than permitted fields, through an error-->
Expand Down
6 changes: 1 addition & 5 deletions docs/guides/domain-definition/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,5 @@ In [2]: renamed = UserRenamed(user_id=user.id, name="John Doe Jr.")

In [3]: renamed.name = "John Doe Sr."
...
IncorrectUsageError: {
'_message': [
'Event/Command Objects are immutable and cannot be modified once created'
]
}
IncorrectUsageError: 'Event/Command Objects are immutable and cannot be modified once created'
```
6 changes: 3 additions & 3 deletions docs/guides/domain-definition/value-objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ In [3]: class Balance(BaseValueObject):
...: currency = String(max_length=3, unique=True)
...: amount = Float()
...
IncorrectUsageError: {'_value_object': ["Value Objects cannot contain fields marked 'unique' (field 'currency')"]}
IncorrectUsageError: "Value Objects cannot contain fields marked 'unique' (field 'currency')"
```

Same case if you try to find a Value Object's `id_field`:
Expand All @@ -238,7 +238,7 @@ In [4]: from protean.reflection import id_field

In [5]: id_field(Balance)
...
IncorrectUsageError: {"identity": ["<class '__main__.Balance'> does not have identity fields"]}
IncorrectUsageError: "<class '__main__.Balance'> does not have identity fields"
```

## Immutability
Expand All @@ -250,5 +250,5 @@ In [1]: bal1 = Balance(currency='USD', amount=100.0)

In [2]: bal1.currency = "CAD"
...
IncorrectUsageError: {'_value_object': ["Value Objects are immutable and cannot be modified once created"]}
IncorrectUsageError: "Value Objects are immutable and cannot be modified once created"
```
6 changes: 2 additions & 4 deletions src/protean/adapters/repository/elasticsearch.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,10 +235,8 @@ def _update(self, model_obj: Any):
except NotFoundError as exc:
logger.error(f"Database Record not found: {exc}")
raise ObjectNotFoundError(
{
"_entity": f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
)

try:
Expand Down
12 changes: 4 additions & 8 deletions src/protean/adapters/repository/memory.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,10 +390,8 @@ def _update(self, model_obj):
# Check if object is present
if identifier not in conn._db["data"][self.schema_name]:
raise ObjectNotFoundError(
{
"_entity": f"`{self.__class__.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.__class__.__name__}` object with identifier {identifier} "
f"does not exist."
)

conn._db["data"][self.schema_name][identifier] = model_obj
Expand Down Expand Up @@ -434,10 +432,8 @@ def _delete(self, model_obj):
# Check if object is present
if identifier not in conn._db["data"][self.schema_name]:
raise ObjectNotFoundError(
{
"_entity": f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
)

del conn._db["data"][self.schema_name][identifier]
Expand Down
12 changes: 4 additions & 8 deletions src/protean/adapters/repository/sqlalchemy.py
Original file line number Diff line number Diff line change
Expand Up @@ -383,10 +383,8 @@ def _update(self, model_obj):
conn.rollback()
conn.close()
raise ObjectNotFoundError(
{
"_entity": f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
)

# Sync DB Record with current changes. When the session is committed, changes are automatically synced
Expand Down Expand Up @@ -447,10 +445,8 @@ def _delete(self, model_obj):
conn.rollback()
conn.close()
raise ObjectNotFoundError(
{
"_entity": f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.entity_cls.__name__}` object with identifier {identifier} "
f"does not exist."
)

try:
Expand Down
2 changes: 1 addition & 1 deletion src/protean/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def server(
try:
domain = derive_domain(domain)
except NoDomainException as exc:
logger.error(f"Error loading Protean domain: {exc.messages}")
logger.error(f"Error loading Protean domain: {exc.args[0]}")
raise typer.Abort()

from protean.server import Engine
Expand Down
2 changes: 1 addition & 1 deletion src/protean/cli/shell.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def shell(
try:
domain_instance = derive_domain(domain)
except NoDomainException as exc:
logger.error(f"Error loading Protean domain: {exc.messages}")
logger.error(f"Error loading Protean domain: {exc.args[0]}")
raise typer.Abort()

if traverse:
Expand Down
12 changes: 2 additions & 10 deletions src/protean/core/aggregate.py
Original file line number Diff line number Diff line change
Expand Up @@ -257,11 +257,7 @@ def apply(fn):

if len(typing.get_type_hints(fn)) > 2:
raise IncorrectUsageError(
{
"_entity": [
f"Handler method `{fn.__name__}` has incorrect number of arguments"
]
}
f"Handler method `{fn.__name__}` has incorrect number of arguments"
)

try:
Expand All @@ -276,11 +272,7 @@ def apply(fn):
)
except StopIteration:
raise IncorrectUsageError(
{
"_entity": [
f"Apply method `{fn.__name__}` should accept an argument annotated with the Event class"
]
}
f"Apply method `{fn.__name__}` should accept an argument annotated with the Event class"
)

@functools.wraps(fn)
Expand Down
6 changes: 1 addition & 5 deletions src/protean/core/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,7 @@ def command_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of and not element_cls.meta_.abstract:
raise IncorrectUsageError(
{
"_command": [
f"Command `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
]
}
f"Command `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
)

return element_cls
6 changes: 1 addition & 5 deletions src/protean/core/command_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,7 @@ def command_handler_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of:
raise IncorrectUsageError(
{
"_entity": [
f"Command Handler `{element_cls.__name__}` needs to be associated with an Aggregate"
]
}
f"Command Handler `{element_cls.__name__}` needs to be associated with an Aggregate"
)

return element_cls
6 changes: 1 addition & 5 deletions src/protean/core/domain_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,7 @@ def domain_service_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of or len(element_cls.meta_.part_of) < 2:
raise IncorrectUsageError(
{
"_entity": [
f"Domain Service `{element_cls.__name__}` needs to be associated with two or more Aggregates"
]
}
f"Domain Service `{element_cls.__name__}` needs to be associated with two or more Aggregates"
)

# Iterate through methods marked as `@invariant` and record them for later use
Expand Down
6 changes: 1 addition & 5 deletions src/protean/core/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -621,11 +621,7 @@ def entity_factory(element_cls, domain, **opts):

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

# Set up reference fields
Expand Down
6 changes: 1 addition & 5 deletions src/protean/core/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,7 @@ def domain_event_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of and not element_cls.meta_.abstract:
raise IncorrectUsageError(
{
"_event": [
f"Event `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
]
}
f"Event `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
)

return element_cls
6 changes: 1 addition & 5 deletions src/protean/core/event_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ def event_handler_factory(element_cls, domain, **opts):

if not (element_cls.meta_.part_of or element_cls.meta_.stream_category):
raise IncorrectUsageError(
{
"_entity": [
f"Event Handler `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
]
}
f"Event Handler `{element_cls.__name__}` needs to be associated with an aggregate or a stream"
)

return element_cls
22 changes: 5 additions & 17 deletions src/protean/core/event_sourced_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ def __init__(self, domain) -> None:

def add(self, aggregate: BaseAggregate) -> None:
if aggregate is None:
raise IncorrectUsageError(
{"_entity": ["Aggregate object to persist is invalid"]}
)
raise IncorrectUsageError("Aggregate object to persist is invalid")

# Proceed only if aggregate has events
if len(aggregate._events) > 0:
Expand Down Expand Up @@ -91,10 +89,8 @@ def get(self, identifier: Identifier) -> BaseAggregate:

if not aggregate:
raise ObjectNotFoundError(
{
"_entity": f"`{self.meta_.part_of.__name__}` object with identifier {identifier} "
f"does not exist."
}
f"`{self.meta_.part_of.__name__}` object with identifier {identifier} "
f"does not exist."
)

aggregate._event_position = aggregate._version
Expand All @@ -107,20 +103,12 @@ def event_sourced_repository_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of:
raise IncorrectUsageError(
{
"_entity": [
f"Repository `{element_cls.__name__}` should be associated with an Aggregate"
]
}
f"Repository `{element_cls.__name__}` should be associated with an Aggregate"
)

if not element_cls.meta_.part_of.meta_.is_event_sourced:
raise IncorrectUsageError(
{
"_entity": [
f"Repository `{element_cls.__name__}` can only be associated with an Event Sourced Aggregate"
]
}
f"Repository `{element_cls.__name__}` can only be associated with an Event Sourced Aggregate"
)

return element_cls
6 changes: 1 addition & 5 deletions src/protean/core/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,7 @@ def model_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of:
raise IncorrectUsageError(
{
"_entity": [
f"Model `{element_cls.__name__}` should be associated with an Entity or Aggregate"
]
}
f"Model `{element_cls.__name__}` should be associated with an Entity or Aggregate"
)

return element_cls
12 changes: 2 additions & 10 deletions src/protean/core/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,11 +266,7 @@ def repository_factory(element_cls, domain, **opts):

if not element_cls.meta_.part_of:
raise IncorrectUsageError(
{
"_entity": [
f"Repository `{element_cls.__name__}` should be associated with an Aggregate"
]
}
f"Repository `{element_cls.__name__}` should be associated with an Aggregate"
)

# FIXME Uncomment
Expand All @@ -284,11 +280,7 @@ def repository_factory(element_cls, domain, **opts):
database.value for database in Database
]:
raise IncorrectUsageError(
{
"_entity": [
f"Repository `{element_cls.__name__}` should be associated with a valid Database"
]
}
f"Repository `{element_cls.__name__}` should be associated with a valid Database"
)

return element_cls
12 changes: 2 additions & 10 deletions src/protean/core/subscriber.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,12 @@ def subscriber_factory(element_cls, domain, **opts):

if not element_cls.meta_.event:
raise IncorrectUsageError(
{
"_entity": [
f"Subscriber `{element_cls.__name__}` needs to be associated with an Event"
]
}
f"Subscriber `{element_cls.__name__}` needs to be associated with an Event"
)

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

return element_cls
Loading