DDD-oriented domain primitives and abstractions for any Python stack (framework-agnostic).
Project description
oclarcdo
Reusable domain-layer building blocks for Python: aggregates, domain events, specifications, guard policies, persistence-oriented repository protocols, and transaction abstractions. No web framework or ORM dependency—use from FastAPI, Django, CLI tools, or any host.
This package is the Python equivalent of Odex.AspNetCore.Clarc.Domain on .NET.
Installation
pip install oclarcdo
With uv:
uv add oclarcdo
Pin a version for reproducible builds:
pip install oclarcdo==0.2.0
Requirements
| Item | Version |
|---|---|
| Python | 3.12+ |
| Runtime dependencies | None |
How it fits in CLARC / clean architecture
| Layer | Responsibility | Typical CLARC package |
|---|---|---|
| Domain | Entities, value objects, domain services, invariants, aggregate events (raised, not dispatched) | This package |
| Application | Use cases, commands/queries, handlers, orchestration | Your application layer |
| Infrastructure | Persistence, external APIs, event dispatch, DI | Your infrastructure layer |
Repository protocols accept callables for predicates so implementations can filter in memory or translate to SQL (for example with SQLAlchemy). Wiring DI, ORMs, outboxes, and mediators stays in Application and Infrastructure.
Capabilities
| Area | Types (summary) |
|---|---|
| Aggregates | BaseAggregate — identity, audit timestamps, in-memory domain events. StatefulAggregate — activation and soft-delete flags. |
| Events | AggregateEventProtocol, AggregateEvent — correlation id and occurred_on; collect with _add_event, read with list_events, clear after dispatch. |
| Specifications | Specification with and_ / or_ / not_; to_predicate() for repositories and in-memory checks. |
| Policies | PolicyProtocol, BasePolicy — require_not_null, require_not_null_nor_empty, require_null_or_empty, require_true / require_false, etc. |
| Repositories | BaseRepositoryProtocol — save_changes_async, execute_in_transaction_async. AggregateRepositoryProtocol — async reads/writes, attach helpers. |
| Services | BaseService, AggregateService — transaction and save delegation. |
| Transactions | TransactionContextProtocol — cooperative rollback signalling. |
| Exceptions | DomainException, PolicyViolationException, EntityNotFoundException, ConcurrencyException, InvalidEntityStateException with ExceptionType. |
| Value objects / DTO markers | BaseValueObject, BaseRequest, BaseResponse, PagedRequest, PagedResponse, BaseData. |
Examples
Aggregate and policy
from uuid import UUID, uuid4
from oclarcdo import AggregateEvent, BasePolicy, StatefulAggregate
class ProductRenamed(AggregateEvent):
product_id: UUID
new_name: str
class Product(StatefulAggregate[UUID]):
def __init__(self, name: str) -> None:
super().__init__()
self.id = uuid4()
self.name = name
def rename(self, new_name: str) -> None:
BasePolicy[str]().require_not_null_nor_empty(new_name)
self.name = new_name
self.mark_modified()
self._add_event(ProductRenamed(product_id=self.id, new_name=new_name))
Specification
from oclarcdo import Specification
class ActiveUsersSpec(Specification[User]):
def to_predicate(self):
return lambda u: u.is_active
spec = ActiveUsersSpec().and_(UserNameContainsSpec("alex"))
await repository.list_async(spec.to_predicate())
Application service
from oclarcdo import AggregateService
class ProductService(AggregateService):
def __init__(self, products: AggregateRepositoryProtocol[Product, UUID]) -> None:
super().__init__(products)
self._products = products
async def create_async(self, name: str) -> Product:
product = Product(name)
await self._products.add_async(product)
await self.save_repository_changes_async()
return product
Development
See CONTRIBUTING.md.
git clone https://github.com/o-shabi/odex-clarc-domain-python.git
cd odex-clarc-domain-python
uv sync --all-groups
uv run pytest
uv run ruff check .
uv run mypy
License
MIT — Copyright (c) Asen O'Shabi. See LICENSE.
Links
| Resource | URL |
|---|---|
| PyPI | https://pypi.org/project/oclarcdo/ |
| .NET (NuGet) counterpart | https://www.nuget.org/packages/Odex.AspNetCore.Clarc.Domain |
| Changelog | https://github.com/o-shabi/odex-clarc-domain-python/blob/main/CHANGELOG.md |
| Source / issues | https://github.com/o-shabi/odex-clarc-domain-python |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file oclarcdo-0.2.0.tar.gz.
File metadata
- Download URL: oclarcdo-0.2.0.tar.gz
- Upload date:
- Size: 10.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af966263fa1813daab5defc784dbe0698d9c69c951655934c59f07d38a77f97b
|
|
| MD5 |
8156a607f9055c534e222f3b7423d36f
|
|
| BLAKE2b-256 |
cd008339aa804873c6a7b17812bbe9a5dbb53a264c3c3ab08fcbea9ca5b269a7
|
Provenance
The following attestation bundles were made for oclarcdo-0.2.0.tar.gz:
Publisher:
release.yml on o-shabi/odex-clarc-domain-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oclarcdo-0.2.0.tar.gz -
Subject digest:
af966263fa1813daab5defc784dbe0698d9c69c951655934c59f07d38a77f97b - Sigstore transparency entry: 1568131490
- Sigstore integration time:
-
Permalink:
o-shabi/odex-clarc-domain-python@82b13aed3888746fbbd8a9ef55c7160caf5895a6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/o-shabi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@82b13aed3888746fbbd8a9ef55c7160caf5895a6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file oclarcdo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: oclarcdo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 21.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e166e661b6cfb5adb72d93cfd171c9d9e6d10379312c9bf1a1f76e82e9fd8ad9
|
|
| MD5 |
943395490fdcd714dd282681aa929c69
|
|
| BLAKE2b-256 |
d4a181cf243eee6ad5a3ee3eb1dd0678dc49579544a52ff2814a4e244c4809b7
|
Provenance
The following attestation bundles were made for oclarcdo-0.2.0-py3-none-any.whl:
Publisher:
release.yml on o-shabi/odex-clarc-domain-python
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
oclarcdo-0.2.0-py3-none-any.whl -
Subject digest:
e166e661b6cfb5adb72d93cfd171c9d9e6d10379312c9bf1a1f76e82e9fd8ad9 - Sigstore transparency entry: 1568131634
- Sigstore integration time:
-
Permalink:
o-shabi/odex-clarc-domain-python@82b13aed3888746fbbd8a9ef55c7160caf5895a6 -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/o-shabi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@82b13aed3888746fbbd8a9ef55c7160caf5895a6 -
Trigger Event:
push
-
Statement type: