Coverage for src/pypermission/db.py: 100%
17 statements
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 14:14 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2025-11-14 14:14 +0000
1from sqlite3 import Connection
3from sqlalchemy.engine.base import Engine
4from sqlalchemy.event import contains
5from sqlalchemy.pool.base import (
6 _ConnectionRecord, # pyright: ignore[reportPrivateUsage]
7)
9from pypermission.exc import PyPermissionError
10from pypermission.models import BaseORM
13def create_rbac_database_table(*, engine: Engine) -> None:
14 """
15 Create all required database tables via. SQLAlchemy for PyPermission.
17 Parameters
18 ----------
19 engine : Engine
20 The SQLAlchemy engine.
21 """
22 if engine.driver == "pysqlite" and not contains(
23 engine, "connect", set_sqlite_pragma
24 ):
25 raise PyPermissionError(
26 "Foreign keys pragma appears to not be set! Please use the 'set_sqlite_pragma' function"
27 " on your SQLite engine before interacting with the database!"
28 )
30 BaseORM.metadata.create_all(bind=engine)
33# https://docs.sqlalchemy.org/en/20/dialects/sqlite.html#foreign-key-support
34def set_sqlite_pragma(
35 dbapi_connection: Connection, _connection_record: _ConnectionRecord
36) -> None:
37 """
38 Enable foreign key constraints for SQLite connections.
40 This function ensures that SQLite foreign key constraints are enabled.
42 Notes
43 -----
44 SQLite's foreign key support is disabled by default and requires explicit
45 enabling. The sqlite driver will not set PRAGMA foreign_keys if
46 autocommit=False, which is why this function temporarily enables it.
48 References
49 ----------
50 - SQLAlchemy SQLite Foreign Key Support:
51 https://docs.sqlalchemy.org/en/20/dialects/sqlite.html#foreign-key-support
53 Examples
54 --------
55 >>> from sqlalchemy import create_engine
56 >>> from sqlalchemy.event import listen
57 >>> engine = create_engine('sqlite:///example.db')
58 >>> listen(engine, 'connect', set_sqlite_pragma)
59 """
60 ac = dbapi_connection.autocommit
61 dbapi_connection.autocommit = True
63 cursor = dbapi_connection.cursor()
64 cursor.execute("PRAGMA foreign_keys=ON")
65 cursor.close()
67 dbapi_connection.autocommit = ac