streamrip/rip/db.py
nathom 2f3f425687 Rewrite db.py for extensibility
Signed-off-by: nathom <nathanthomas707@gmail.com>
2021-07-03 13:47:54 -07:00

98 lines
2.6 KiB
Python

"""Wrapper over a database that stores item IDs."""
import logging
import os
import sqlite3
from typing import Union, List
import abc
logger = logging.getLogger("streamrip")
class Database:
# list of table column names
structure: list
# name of table
name: str
def __init__(self, path, empty=False):
assert self.structure != []
assert self.name
if empty:
self.path = None
return
self.path = path
if not os.path.exists(self.path):
self.create()
def create(self):
if self.path is None:
return
with sqlite3.connect(self.path) as conn:
try:
params = ", ".join(
f"{key} TEXT UNIQUE NOT NULL" for key in self.structure
)
command = f"CREATE TABLE {self.name} ({params});"
logger.debug(f"executing {command}")
conn.execute(command)
except sqlite3.OperationalError:
pass
def keys(self):
return self.structure
def contains(self, **items):
allowed_keys = set(self.structure)
assert all(
key in allowed_keys for key in items.keys()
), f"Invalid key. Valid keys: {self.structure}"
items = {k: str(v) for k, v in items.items()}
if self.path is None:
return False
with sqlite3.connect(self.path) as conn:
conditions = " AND ".join(f"{key}=?" for key in items.keys())
command = f"SELECT {self.structure[0]} FROM {self.name} WHERE {conditions}"
logger.debug(f"executing {command}")
return conn.execute(command, tuple(items.values())).fetchone() is not None
def __contains__(self, keys: dict) -> bool:
return self.contains(**keys)
def add(self, items: List[str]):
assert len(items) == len(self.structure)
if self.path is None:
return
params = ", ".join(self.structure)
question_marks = ", ".join("?" for _ in items)
command = f"INSERT INTO {self.name} ({params}) VALUES ({question_marks})"
logger.debug(f"executing {command}")
with sqlite3.connect(self.path) as conn:
conn.execute(command, tuple(items))
def __iter__(self):
with sqlite3.connect(self.path) as conn:
return conn.execute(f"SELECT * FROM {self.name}")
class Downloads(Database):
structure = ["id"]
name = "downloads"
class FailedDownloads(Database):
structure = ["source", "type", "id"]
name = "failed_downloads"