"""Convenience wrapper for the Python DB-API library, and some specificly forthe SQLite library."""__author__='Paul Landes'importloggingfromdataclassesimportdataclass,fieldfrompathlibimportPathimportsqlite3from.importDBError,ConnectionManager,DbStashlogger=logging.getLogger(__name__)
[docs]@dataclassclassSqliteConnectionManager(ConnectionManager):"""An SQLite connection factory. """db_file:Path=field()"""The SQLite database file to read or create."""create_db:bool=field(default=True)"""If ``True``, create the database if it does not already exist. Otherwise, :class:`.DBError` is raised (see :meth:`create`). """
[docs]defcreate(self)->sqlite3.Connection:"""Create a connection by accessing the SQLite file. :raise DBError: if the SQLite file does not exist (caveat see :`obj:create_db`) """db_file=self.db_fileiflogger.isEnabledFor(logging.DEBUG):logger.debug(f'creating connection to {db_file}')created=Falseifnotdb_file.exists():ifnotself.create_db:raiseDBError(f'database file {db_file} does not exist')ifnotdb_file.parent.exists():iflogger.isEnabledFor(logging.INFO):logger.info(f'creating sql db directory {db_file.parent}')db_file.parent.mkdir(parents=True)iflogger.isEnabledFor(logging.INFO):logger.info(f'creating sqlite db file: {db_file}')created=Truetypes=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMESconn=sqlite3.connect(str(db_file.absolute()),detect_types=types)ifcreated:logger.info('initializing database...')forsqlinself.persister.parser.get_init_db_sqls():iflogger.isEnabledFor(logging.DEBUG):logger.debug(f'invoking sql: {sql}')conn.execute(sql)conn.commit()returnconn
[docs]defdrop(self)->bool:"""Delete the SQLite database file from the file system."""logger.info(f'deleting: {self.db_file}')ifself.db_file.exists():self.db_file.unlink()returnTruereturnFalse
[docs]@dataclassclassSqliteAttachConnectionManager(ConnectionManager):"""An SQLite connection factory that attaches a file as a database. """db_file:Path=field()"""The SQLite database file to read or create."""database_name:str=field()"""The name of the database used to attach to :obj:`db_file`."""
[docs]defcreate(self)->sqlite3.Connection:"""Create a connection as an attached database to a file."""conn=sqlite3.connect(':memory:')conn.execute(f'ATTACH DATABASE ? AS {self.database_name}',(str(self.db_file),))returnconn
[docs]defdrop(self)->bool:"""Dropping a memory SQLite connection is not supported."""returnFalse
[docs]@dataclassclassSqliteDbStash(DbStash):"""A :class:`~zensols.persist.domain.Stash` implementation that uses an SQLite database to store data. """path:Path=field(default=None)"""The directory of where to store the files."""def_create_connection_manager(self)->ConnectionManager:ifself.pathisNone:raiseDBError(f'No configured path for {type(self)} stash')returnSqliteConnectionManager(self.path)