Skip to content

Commit a911380

Browse files
redjaxredjax
and
redjax
authored
Feat/sqlite context mgr (#251)
* feat(sqlite-contextmanager): Add SQLite connection context manager Defines a Python context manager class to control SQLite database interactions. * Add imports for new SQLiteConnManager context manager --------- Co-authored-by: redjax <[email protected]>
1 parent 8710769 commit a911380

File tree

4 files changed

+98
-1
lines changed

4 files changed

+98
-1
lines changed

red_utils/__init__.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import pkgutil
44

55
## Import modules with only stdlib dependencies directly
6-
from .context_managers import DictProtect, ListProtect, async_benchmark, benchmark
6+
from .context_managers import DictProtect, ListProtect, SQLiteConnManager
7+
from .context_managers import async_benchmark, benchmark
78
from .dict_utils import debug_dict, merge_dicts, update_dict, validate_dict
89
from .file_utils import crawl_dir, default_json_dir, export_json, ts
910
from .hash_utils import get_hash_from_str
@@ -23,6 +24,7 @@
2324
trim_uuid,
2425
)
2526

27+
2628
## Use pkgutil to only load modules
2729
# if dependencies are met
2830
if pkgutil.find_loader("diskcache"):

red_utils/context_managers/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
from .benchmarks import async_benchmark, benchmark
44
from .object_managers.protect import DictProtect, ListProtect
5+
from .database_managers.sqlite_managers import SQLiteConnManager
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .sqlite_managers import SQLiteConnManager
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
"""
2+
Context manager utilities for interacting with SQLite databases, using
3+
the stdlib sqlite3 library.
4+
"""
5+
from __future__ import annotations
6+
7+
from pathlib import Path
8+
import sqlite3
9+
10+
from typing import Union
11+
12+
class SQLiteConnManager:
13+
"""Handle interactions with a SQLite database.
14+
15+
Uses built-in functions to query a database, execute SQL statements,
16+
and gracefully open/close the DB using context managers.
17+
18+
Usage:
19+
Provide a path string to the SQLite database:
20+
sqlite_connection = SQLiteConnManager(path="/path/to/db.sqlite")
21+
22+
Call sqlite3 functions, i.e. "get_tables()":
23+
tables = sqlite_conn.get_tables()
24+
"""
25+
26+
def __init__(self, path: Path):
27+
"""Initialize SQLite connection manager."""
28+
self.path = path
29+
30+
def __enter__(self):
31+
"""Run when used like 'with SQLiteConnManager() as conn: ..."""
32+
self.connection: sqlite3.Connection = sqlite3.connect(self.path)
33+
self.connection.row_factory = sqlite3.Row
34+
self.cursor: sqlite3.Cursor = self.connection.cursor()
35+
36+
## Return self, a configured SQLite client
37+
return self
38+
39+
def __exit__(self, exc_type, exc_val, exc_traceback):
40+
"""Run on exit, success or failure."""
41+
self.connection.close()
42+
43+
def get_cols(self, table: str = None) -> list[str]:
44+
"""Return list of column names from a given table."""
45+
cols: list[str] = []
46+
stmt: str = f"SELECT * FROM {table}"
47+
48+
try:
49+
with SQLiteConnManager(self.path) as conn:
50+
cursor = conn.cursor
51+
res = cursor.execute(stmt).fetchone()
52+
53+
for col in res.keys():
54+
cols.append(col)
55+
56+
return cols
57+
58+
except Exception as exc:
59+
raise Exception(f"Unhandled exception executing SQL. Details: {exc}")
60+
61+
def get_tables(self) -> list[str]:
62+
"""Get all table names from a SQLite databse."""
63+
get_tbls_stmt: str = "SELECT name FROM sqlite_master WHERE type='table';"
64+
tables: list[str] = []
65+
66+
try:
67+
with SQLiteConnManager(self.path) as conn:
68+
cursor = conn.cursor
69+
res = cursor.execute(get_tbls_stmt).fetchall()
70+
71+
for row in res:
72+
tables.append(row["name"])
73+
74+
return tables
75+
76+
except Exception as exc:
77+
raise Exception(f"Unhandled exception getting tables. Details: {exc}")
78+
79+
def run_sqlite_stmt(self, stmt: str = None) -> list[sqlite3.Row]:
80+
"""Execute a SQL statement."""
81+
assert stmt, "Must pass a SQL statement"
82+
assert isinstance(stmt, str), "Statement must be a Python str"
83+
84+
try:
85+
with SQLiteConnManager(self.path) as conn:
86+
cursor = conn.cursor
87+
res = cursor.execute(stmt).fetchall()
88+
89+
return res
90+
except Exception as exc:
91+
raise Exception(
92+
f"Unhandled exception running SQL statement. Details: {exc}"
93+
)

0 commit comments

Comments
 (0)