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:

Contributing

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

Donations

Donate using
Liberapay or ko-fi

If you are using some of my open-source tools, have enjoyed them, and want to say "thanks", this is a very strong way to do it.

If your product/company depends on these tools, you can sponsor me to ensure I keep happily maintaining them.

If these tools are helping you save money, time, effort, or frustrations; or they are helping you make money, be more productive, efficient, secure, enjoy a bit more your work, or get your product ready faster, this is a great way to show your appreciation. Thanks for that!

And by sponsoring me, you are helping make these tools, that already help you, sustainable and healthy.


Last update: 2022-12-14