This project uses Hexagonal Architecture and DDD.
DDD related code.
Micro-framework for other domain related code. See ".NET Microservices: Architecture for Containerized .NET Applications" section "Seedwork (reusable base classes and interfaces for your domain model)" https://learn.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/seedwork-domain-model-base-classes-interfaces
Aggregates are named by their root entity name without any special suffixes.
*Factory
classes are factories for aggregates. They are concrete classes
but can be inherited and overriden on infrastructure level.
*Repository
abstract classes declares repository interface.
They are implemented on infrastructure level.
DomainEvent-based classes are DTO for domain events.
*Service
classes are responsible for execution of domain-level operations.
Also, domain level services can be defined in any way that fits better
for concrete operation.
Reusable value-objects as they are defined in DDD.
Application core as it is in Hexagonal Architecture.
*Service
classes are responsible for execution of commands.
*Queries
abstract classes are responsible for declaration of queries.
These classes are implemented in adapters layer.
*Service
classes are responsible for execution of queries.
*Auth
abstract classes are responsible for declaration of authorization methods
and methods returning information about current user.
Application core level exceptions. Usually raised by command or query services.
Defines event handlers for domain events.
Defines abstract transaction manager interface. This interface is implemented at infrastructure level.
Various adapters as defined in Hexagonal Architecture.
Implements authentication and authorization.
All persistence related implementations, i.e. implements repositories, queries, etc.
Persistence related code implemented with TortoiseORM.
Persistence implemented with SQLAlchemy, partially with Core and partially with Imperative Mapping.
This implementation maps database rows directly to entity classes.
Probably, this way is more preferable when used with hexagonal architecture, because it allows to completely separate entities and persistence and doesn't introduce any intermediate models. But it also has its own downsides: since it monkey patches entity classes, it can probably break them and also heavily depends on implementation details, i.e. protected attributes of entity classes.
Persistence implemented with SQLAlchemy Core only. No ORM used.
Persistence implemented with SQLAlchemy ORM.
'Naive' here means that ORM maps database rows not to entity classes, but to intermediate model classes. Then the model classes are manually mapped to entity classes in repositories.
For direct mapping DB rows to entities see news_fastapi.adapters.persistence.sqlalchemy
.
REST API related code: controllers, middleware, ASGI app, etc.
news_fastapi.main.asgi
constructs ASGI application for ASGI web servers,
such as uvicorn.
news_fastapi.main.container
IOC container, dependency root.
news_fastapi.main.*
another application entrypoints, usually auxiliary CLI scripts.
Run the following commands to check the code quality:
cd src
# sort imports
isort .
# format code
black .
# check types
mypy news_fastapi
# lint
pylint --rcfile ../pyproject.toml news_fastapi
# all previous commands can be run at once by qa.sh script
./qa.sh
cd src
# all tests
python -m unittest
# tests from single file
python -m unittest tests/path/to/file/test_whatever_you_need.py
# tests from package
python -m unittest discover tests/path/to/package/directory/