"""Provide any inheriting object with a dataset-powered database management.""" # Standard library modules import logging # Third party modules import dataset class ObjectWithDatabase(object): """Objects inheriting from this class will have a `.db` method. Using `subclass_instance.db` will open a SQL transaction. To perform multiple SQL queries in a single transaction use a with statement as in this simple example: ``` with my_object.db as db: if db['my_table'].find_one(id=14): db['fourteen_exists'].insert( {'exists': True} ) ``` """ def __init__(self, database_url=None): """Instantiate object and open connection with database.""" if database_url is None: database_url = 'database.db' if ':///' not in database_url: # Default database engine is sqlite, which operates on a # single-file database having `.db` extension if not database_url.endswith('.db'): database_url += '.db' database_url = f'sqlite:///{database_url}' self._database_url = database_url try: self._database = dataset.connect(self.db_url) except Exception as e: self._database_url = None self._database = None logging.error(f"{e}") @property def db_url(self): """Return complete path to database.""" return self._database_url @property def db(self): """Return the dataset.Database instance related to `self`.""" return self._database def create_views(self, views, overwrite=False): """Take a list of `views` and add them to bot database. Overwrite existing views if `overwrite` is set to True. Each element of this list should have - a `name` field - a `query field` """ with self.db as db: for view in views: try: if overwrite: db.query( f"DROP VIEW IF EXISTS {view['name']}" ) db.query( f"CREATE VIEW IF NOT EXISTS {view['name']} " f"AS {view['query']}" ) except Exception as e: logging.error(f"{e}")