Skip to content

Repository ORM

Actions Status Actions Status Coverage Status

Library to persist Pydantic models into different storage backends following the repository pattern.

Installing

pip install repository-orm

A Simple Example

from repository_orm import Entity, load_repository


class Author(Entity):
    first_name: str
    last_name: str
    country: str


repo = load_repository()

author = Author(first_name="Brandon", last_name="Sanderson", country="US")

# Add entities
repo.add(author)
repo.commit()

# Retrieve entities by their ID
brandon = repo.get(0, Author)
assert brandon == author

# Search entities
brandon = repo.search({"first_name": "Brandon"}, Author)[0]
assert brandon == author

# Delete entities
repo.delete(brandon)
repo.commit()
assert len(repo.all(Author)) == 0

# Close the connection
repo.close()

Repository pattern theory

The repository pattern is an abstraction over persistent storage, allowing you to decouple the model layer from the data layer. It hides the boring details of data access by pretending that all of our data is in memory.

It has the following advantages:

  • Give a simple interface, which you control, between persistent storage and our domain model.
  • It's easy to make a fake version of the repository for unit testing, or to swap out different storage solutions, because the model is fully decoupled from the infrastructure.
  • Writing the domain model before thinking about persistence helps focus on the problem at hand. If we need to change our approach, we can do that in our model, without needing to worry about foreign keys or migrations until later.
  • Our database schema is simple because we have complete control over how we map our object to tables.
  • Speeds up and makes more clean the business logic tests.
  • It's easy to implement.

But the following disadvantages:

  • An ORM already buys you some decoupling. Changing foreign keys might be hard, but it should be pretty easy to swap between MySQL and PostgreSQL if you ever need to.
  • Maintaining ORM mappings by hand requires extra work and extra code.
  • An extra layer of abstraction is introduced, and although we may hope it will reduce complexity overall, it does add complexity locally. Furthermore it adds the WTF factor for Python programmers who've never seen this pattern before.

repository-orm aims to mitigate the last ones by:

  • Supplying classes that already have the common operations for different storage solutions.
  • Supplying test classes and fixtures so extending the provided repositories is easy.

Repositories

There are two kinds of repositories:

Projects using repository-orm

If you want to see the library being used in a simple project, check pynbox code. Other projects using repository-orm are:

  • clinv: A DevSecOps command line asset inventory tool.
  • pydo: A free software command line task manager built in Python.

If you use the library and want to be listed here, open an issue.

References

As most open sourced programs, repository-orm is standing on the shoulders of giants, namely:

pydantic
Used for the Entities definition.
DeepDiff
Used to search strings in complex objects in the FakeRepository.
TinyDB
Used to interact with the NoSQL database in the TinyDBRepository
Pypika
Used to build the SQL queries in the PypikaRepository.
Yoyo
Used to manage the schema changes of the PypikaRepository.
Pytest
Testing framework, enhanced by the awesome pytest-cases library that made the parametrization of the tests a lovely experience.
Mypy
Python static type checker.
Flakeheaven
Python linter with lots of checks.
Black
Python formatter to keep a nice style without effort.
Autoimport
Python formatter to automatically fix wrong import statements.
isort
Python formatter to order the import statements.
PDM
Command line tool to manage the dependencies.
Mkdocs
To build this documentation site, with the Material theme.
Safety
To check the installed dependencies for known security vulnerabilities.
Bandit
To finds common security issues in Python code.
Yamlfix
YAML fixer.

Contributing

For guidance on setting up a development environment, and how to make a contribution to repository-orm, see Contributing to repository-orm.


Last update: 2022-08-12