Classe de base ORM légère pour SQLite
Project description
sqlite-persist
Classe de base ORM légère pour SQLite, sans dépendances externes.
Installation
# depuis un dépôt git
uv add git+https://codeberg.org/styfore/sqlite-persist.git
# ou en local
uv add sqlite-persist
Mise en place
from sqlite_persist import Persistence # AsyncPersistence pour la version async, et adapater avec des await, async, etc
import sqlite3
con = sqlite3.connect("ma_base.db")
class User(Persistence):
def __init__(self, id: int | None, username: str, email: str, age: int):
self.id = id
self.username = username
self.email = email
self.age = age
Lecture
# Par PK — lève KeyError si introuvable
user = User.get(1, con=con)
# Par PK — retourne None si introuvable
user = User.find(1, con=con)
# Sélection avec filtres
users = User.select(con=con) # SELECT *
users = User.select({"username": "alice"}, con=con) # opérateur = par défaut
users = User.select({"username LIKE": "ali%"}, con=con) # opérateur custom
users = User.select({"age >=": 18, "age <": 30}, con=con) # même colonne, deux opérateurs
users = User.select({"username": "alice"}, order_by="age", con=con)
users = User.select({"username": "alice"}, order_by=["age", "email DESC"], con=con)
# Requête libre (JOIN, sous-requêtes, etc.)
users = User.select(
"username LIKE :q OR email LIKE :q",
params={"q": "%alice%"},
con=con,
)
# Requête SQL complète
users = User.from_query("""
SELECT u.*, COUNT(o.id) as nb_orders
FROM user u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id
HAVING nb_orders > :min
""", params={"min": 2}, con=con)
# Les colonnes extra (nb_orders) sont accessibles dans __dict__,
# attention un update après lèvera une erreur — nommer la colonne supplémentaire
# en commençant par _ pour l'exclure de _row_data
# Comptage et existence
count = User.count(con=con) # SELECT COUNT(*)
count = User.count({"age >=": 18}, con=con) # avec filtre dict
count = User.count("age >= :a", {"a": 18}, con=con) # avec requête libre
exists = User.exists({"username": "alice"}, con=con) # True / False
exists = User.exists("age >= :a", {"a": 18}, con=con)
Écriture
# Insert — met à jour self.id avec la valeur générée par SQLite
user = User(None, "alice", "alice@example.com", 30)
user.insert(con=con)
print(user.id) # id généré
# Update strict — la ligne doit exister
user.age = 31
user.update(con=con)
# Upsert — INSERT OR REPLACE, gère les deux cas
user.upsert(con=con)
# Delete
user.delete(con=con)
Opérations batch
users = [
User(None, "alice", "alice@example.com", 30),
User(None, "bob", "bob@example.com", 25),
]
User.insert_all(users, con=con) # ids mis à jour sur chaque item, atomique
User.update_all(users, con=con)
User.upsert_all(users, con=con) # ids récupérés si absents
User.delete_all(users, con=con)
# Sans instances
User.update_where(values={"age": 0}, where={"username": "bob"}, con=con)
User.delete_where({"username": "bob"}, con=con)
Transactions
Grouper plusieurs opérations dans une transaction atomique — commit automatique à la sortie du bloc, rollback en cas d'exception :
with User.transaction(con) as tx:
u1 = User(None, "alice", "alice@example.com", 30)
u2 = User(None, "bob", "bob@example.com", 25)
u1.insert(con=tx)
u2.insert(con=tx)
# commit ici
# rollback automatique si exception
try:
with User.transaction(con) as tx:
u.insert(con=tx)
u.insert(con=tx) # IntegrityError → rollback, rien n'est inséré
except sqlite3.IntegrityError:
pass
Les opérations batch (insert_all, upsert_all, etc.) sont elles-mêmes
atomiques — elles utilisent transaction() en interne.
Injection automatique de connexion (ex. Flask)
renseigner _database au niveau de la classe
Possibilité d’utiliser un contexte manager avec la connection créer automatiquement dans ce cas.
from sqlite_persist import Persistence
from mon_app.db import get_db
class User(AppPersistence):
_database = "path/to/database.db"
...
with User.connection():
user = User.get(1) # con= injecté automatiquement
user.age = 31
user.update()
# la connection est fermée à la fin du context
Cette connexion n’est utilisée que dans ce cas là et ne dispense pas de renseigner le paramètre con= ou de surcharger _con dans les autres utilisations, car il n’y a que dans le contexte que l’ouverture et fermeture peut-être gérée automatiquement
Surcharger _con() dans une classe intermédiaire — plus besoin de passer con= partout :
from sqlite_persist import Persistence
from mon_app.db import get_db
class AppPersistence(Persistence):
@classmethod
def _con(cls):
return get_db()
class User(AppPersistence):
...
user = User.get(1) # con= injecté automatiquement
user.age = 31
user.update()
Nom de table personnalisé
Par défaut le nom de la table est le nom de la classe. Pour le surcharger :
class User(AppPersistence):
_table = "app_user"
Clé primaire composite
class Conge(AppPersistence):
_pk = ("calendrier_id", "date_conge")
conge = Conge.get(42, "2025-06-01", con=con)
Attributs transitoires
Tout attribut commençant par _ est ignoré lors des opérations SQL :
class User(AppPersistence):
def __init__(self, id, username, email, age):
self.id = id
self.username = username
self.email = email
self.age = age
self._cache = {} # jamais envoyé en base
self._dirty = False # jamais envoyé en base
Représentation
__repr__ par défaut affiche la table, les colonnes PK puis le reste :
User[id=1 | username='alice', email='alice@example.com', age=30]
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 sqlite_persist-0.3.0b3.tar.gz.
File metadata
- Download URL: sqlite_persist-0.3.0b3.tar.gz
- Upload date:
- Size: 7.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abf877ef0c09d82c09a3a0a9b06f24de7d2f1cb8457d3b8e7a1583485f368931
|
|
| MD5 |
8443c538ab59744f11b4aa97a08231f1
|
|
| BLAKE2b-256 |
c16c7c376a10e83383160c3daa92c68996f65f9c1ea6282229ae67e62536b5b0
|
File details
Details for the file sqlite_persist-0.3.0b3-py3-none-any.whl.
File metadata
- Download URL: sqlite_persist-0.3.0b3-py3-none-any.whl
- Upload date:
- Size: 11.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.2 {"installer":{"name":"uv","version":"0.11.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa57db7d886e692db9bd7cc8cb6c2559342a1535db5679320ef844d054e172b9
|
|
| MD5 |
469526d620054bb35e1f53650cf8b002
|
|
| BLAKE2b-256 |
64520aad25192c5657550b6ffe0ecbb101272f5c53fbc29194ef2164a3c1909c
|