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 |
Metadata
Release files for oclarcdo 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| oclarcdo-0.2.0.tar.gz | 10.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| oclarcdo-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 31.9 kB
Release files / oclarcdo-0.2.0.tar.gz
| Download URL | oclarcdo-0.2.0.tar.gz |
|---|---|
| Size | 10.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
af966263fa1813daab5defc784dbe0698d9c69c951655934c59f07d38a77f97b
|
|
BLAKE2b-256 checksum How to use checksums |
cd008339aa804873c6a7b17812bbe9a5dbb53a264c3c3ab08fcbea9ca5b269a7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency logRelease files / oclarcdo-0.2.0-py3-none-any.whl
| Download URL | oclarcdo-0.2.0-py3-none-any.whl |
|---|---|
| Size | 21.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e166e661b6cfb5adb72d93cfd171c9d9e6d10379312c9bf1a1f76e82e9fd8ad9
|
|
BLAKE2b-256 checksum How to use checksums |
d4a181cf243eee6ad5a3ee3eb1dd0678dc49579544a52ff2814a4e244c4809b7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 18, 2026.
Transparency log