2024-01-30 01:25:02 -08:00
|
|
|
import transaction
|
2024-01-28 22:14:50 -08:00
|
|
|
import base64
|
|
|
|
import hashlib
|
2024-01-28 14:31:50 -08:00
|
|
|
import logging
|
2024-01-28 00:46:19 -08:00
|
|
|
|
2024-01-28 22:14:50 -08:00
|
|
|
from functools import cached_property
|
|
|
|
|
2024-01-30 01:25:02 -08:00
|
|
|
from pyramid_sqlalchemy import Session
|
|
|
|
from pyramid_sqlalchemy import init_sqlalchemy
|
|
|
|
from pyramid_sqlalchemy import metadata as _metadata
|
|
|
|
|
2024-01-28 00:46:19 -08:00
|
|
|
from sqlalchemy import create_engine
|
2024-01-28 22:14:50 -08:00
|
|
|
from sqlalchemy.exc import IntegrityError
|
2024-01-28 00:46:19 -08:00
|
|
|
|
|
|
|
from ttfrog.path import database
|
2024-01-30 01:25:02 -08:00
|
|
|
import ttfrog.db.schema
|
|
|
|
|
|
|
|
ttfrog.db.schema
|
2024-01-28 00:46:19 -08:00
|
|
|
|
|
|
|
|
|
|
|
class SQLDatabaseManager:
|
|
|
|
"""
|
|
|
|
A context manager for working with sqllite database.
|
|
|
|
"""
|
|
|
|
@cached_property
|
|
|
|
def url(self):
|
|
|
|
return f"sqlite:///{database()}"
|
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def engine(self):
|
2024-01-30 01:25:02 -08:00
|
|
|
return create_engine(self.url)
|
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def session(self):
|
|
|
|
return Session
|
2024-01-28 00:46:19 -08:00
|
|
|
|
|
|
|
@cached_property
|
2024-01-30 01:25:02 -08:00
|
|
|
def metadata(self):
|
|
|
|
return _metadata
|
2024-01-28 00:46:19 -08:00
|
|
|
|
|
|
|
@cached_property
|
|
|
|
def tables(self):
|
2024-01-30 01:25:02 -08:00
|
|
|
return dict((t.name, t) for t in self.metadata.sorted_tables)
|
2024-01-28 00:46:19 -08:00
|
|
|
|
|
|
|
def query(self, *args, **kwargs):
|
2024-01-30 01:25:02 -08:00
|
|
|
return self.session.query(*args, **kwargs)
|
2024-01-28 00:46:19 -08:00
|
|
|
|
2024-01-28 22:14:50 -08:00
|
|
|
def execute(self, statement) -> tuple:
|
2024-01-30 01:25:02 -08:00
|
|
|
logging.info(statement)
|
2024-01-28 22:14:50 -08:00
|
|
|
result = None
|
|
|
|
error = None
|
|
|
|
try:
|
2024-01-30 01:25:02 -08:00
|
|
|
with transaction.manager as tx:
|
|
|
|
result = self.session.execute(statement)
|
|
|
|
tx.commit()
|
2024-01-28 22:14:50 -08:00
|
|
|
except IntegrityError as exc:
|
|
|
|
logging.error(exc)
|
2024-01-30 01:25:02 -08:00
|
|
|
error = "I AM ERROR."
|
2024-01-28 22:14:50 -08:00
|
|
|
return result, error
|
|
|
|
|
|
|
|
def insert(self, table, **kwargs) -> tuple:
|
|
|
|
stmt = table.insert().values(**kwargs)
|
|
|
|
return self.execute(stmt)
|
|
|
|
|
2024-01-28 14:31:50 -08:00
|
|
|
def update(self, table, **kwargs):
|
2024-01-28 22:14:50 -08:00
|
|
|
primary_key = kwargs.pop('id')
|
|
|
|
stmt = table.update().values(**kwargs).where(table.columns.id == primary_key)
|
|
|
|
return self.execute(stmt)
|
2024-01-28 14:31:50 -08:00
|
|
|
|
2024-01-28 22:14:50 -08:00
|
|
|
def slugify(self, rec: dict) -> str:
|
|
|
|
"""
|
|
|
|
Create a uniquish slug from a dictionary.
|
|
|
|
"""
|
|
|
|
sha1bytes = hashlib.sha1(str(rec['id']).encode())
|
|
|
|
return base64.urlsafe_b64encode(sha1bytes.digest()).decode("ascii")[:10]
|
|
|
|
|
2024-01-30 01:25:02 -08:00
|
|
|
def init(self):
|
|
|
|
init_sqlalchemy(self.engine)
|
|
|
|
self.metadata.create_all(self.engine)
|
2024-01-28 22:14:50 -08:00
|
|
|
|
2024-01-28 00:46:19 -08:00
|
|
|
def __getattr__(self, name: str):
|
|
|
|
try:
|
|
|
|
return self.tables[name]
|
|
|
|
except KeyError:
|
|
|
|
raise AttributeError(f"{self} does not contain the attribute '{name}'.")
|
|
|
|
|
|
|
|
|
|
|
|
db = SQLDatabaseManager()
|