sqliter-py 0.1.1__py3-none-any.whl → 0.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sqliter/constants.py +20 -0
- sqliter/exceptions.py +6 -0
- sqliter/model/model.py +74 -8
- sqliter/query/query.py +362 -84
- sqliter/sqliter.py +71 -19
- sqliter_py-0.3.0.dist-info/METADATA +601 -0
- sqliter_py-0.3.0.dist-info/RECORD +12 -0
- sqliter_py-0.3.0.dist-info/licenses/LICENSE.txt +20 -0
- sqliter_py-0.1.1.dist-info/METADATA +0 -204
- sqliter_py-0.1.1.dist-info/RECORD +0 -10
- {sqliter_py-0.1.1.dist-info → sqliter_py-0.3.0.dist-info}/WHEEL +0 -0
sqliter/sqliter.py
CHANGED
|
@@ -27,9 +27,24 @@ if TYPE_CHECKING: # pragma: no cover
|
|
|
27
27
|
class SqliterDB:
|
|
28
28
|
"""Class to manage SQLite database interactions."""
|
|
29
29
|
|
|
30
|
-
def __init__(
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
db_filename: Optional[str] = None,
|
|
33
|
+
*,
|
|
34
|
+
memory: bool = False,
|
|
35
|
+
auto_commit: bool = True,
|
|
36
|
+
) -> None:
|
|
31
37
|
"""Initialize the class and options."""
|
|
32
|
-
|
|
38
|
+
if memory:
|
|
39
|
+
self.db_filename = ":memory:"
|
|
40
|
+
elif db_filename:
|
|
41
|
+
self.db_filename = db_filename
|
|
42
|
+
else:
|
|
43
|
+
err = (
|
|
44
|
+
"Database name must be provided if not using an in-memory "
|
|
45
|
+
"database."
|
|
46
|
+
)
|
|
47
|
+
raise ValueError(err)
|
|
33
48
|
self.auto_commit = auto_commit
|
|
34
49
|
self.conn: Optional[sqlite3.Connection] = None
|
|
35
50
|
|
|
@@ -42,17 +57,29 @@ class SqliterDB:
|
|
|
42
57
|
raise DatabaseConnectionError(self.db_filename) from exc
|
|
43
58
|
return self.conn
|
|
44
59
|
|
|
60
|
+
def close(self) -> None:
|
|
61
|
+
"""Close the connection to the SQLite database."""
|
|
62
|
+
if self.conn:
|
|
63
|
+
self._maybe_commit()
|
|
64
|
+
self.conn.close()
|
|
65
|
+
self.conn = None
|
|
66
|
+
|
|
67
|
+
def commit(self) -> None:
|
|
68
|
+
"""Commit any pending transactions."""
|
|
69
|
+
if self.conn:
|
|
70
|
+
self.conn.commit()
|
|
71
|
+
|
|
45
72
|
def create_table(self, model_class: type[BaseDBModel]) -> None:
|
|
46
73
|
"""Create a table based on the Pydantic model."""
|
|
47
74
|
table_name = model_class.get_table_name()
|
|
48
75
|
primary_key = model_class.get_primary_key()
|
|
49
|
-
|
|
76
|
+
create_pk = model_class.should_create_pk()
|
|
50
77
|
|
|
51
78
|
fields = ", ".join(
|
|
52
79
|
f"{field_name} TEXT" for field_name in model_class.model_fields
|
|
53
80
|
)
|
|
54
81
|
|
|
55
|
-
if
|
|
82
|
+
if create_pk:
|
|
56
83
|
create_table_sql = f"""
|
|
57
84
|
CREATE TABLE IF NOT EXISTS {table_name} (
|
|
58
85
|
{primary_key} INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
@@ -75,32 +102,33 @@ class SqliterDB:
|
|
|
75
102
|
except sqlite3.Error as exc:
|
|
76
103
|
raise TableCreationError(table_name) from exc
|
|
77
104
|
|
|
78
|
-
def _maybe_commit(self
|
|
105
|
+
def _maybe_commit(self) -> None:
|
|
79
106
|
"""Commit changes if auto_commit is True."""
|
|
80
|
-
if self.auto_commit:
|
|
81
|
-
conn.commit()
|
|
107
|
+
if self.auto_commit and self.conn:
|
|
108
|
+
self.conn.commit()
|
|
82
109
|
|
|
83
110
|
def insert(self, model_instance: BaseDBModel) -> None:
|
|
84
111
|
"""Insert a new record into the table defined by the Pydantic model."""
|
|
85
112
|
model_class = type(model_instance)
|
|
86
113
|
table_name = model_class.get_table_name()
|
|
87
114
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
115
|
+
data = model_instance.model_dump()
|
|
116
|
+
fields = ", ".join(data.keys())
|
|
117
|
+
placeholders = ", ".join(
|
|
118
|
+
["?" if value is not None else "NULL" for value in data.values()]
|
|
92
119
|
)
|
|
120
|
+
values = tuple(value for value in data.values() if value is not None)
|
|
93
121
|
|
|
94
122
|
insert_sql = f"""
|
|
95
123
|
INSERT INTO {table_name} ({fields})
|
|
96
124
|
VALUES ({placeholders})
|
|
97
|
-
|
|
125
|
+
""" # noqa: S608
|
|
98
126
|
|
|
99
127
|
try:
|
|
100
128
|
with self.connect() as conn:
|
|
101
129
|
cursor = conn.cursor()
|
|
102
130
|
cursor.execute(insert_sql, values)
|
|
103
|
-
self._maybe_commit(
|
|
131
|
+
self._maybe_commit()
|
|
104
132
|
except sqlite3.Error as exc:
|
|
105
133
|
raise RecordInsertionError(table_name) from exc
|
|
106
134
|
|
|
@@ -167,7 +195,7 @@ class SqliterDB:
|
|
|
167
195
|
if cursor.rowcount == 0:
|
|
168
196
|
raise RecordNotFoundError(primary_key_value)
|
|
169
197
|
|
|
170
|
-
self._maybe_commit(
|
|
198
|
+
self._maybe_commit()
|
|
171
199
|
|
|
172
200
|
except sqlite3.Error as exc:
|
|
173
201
|
raise RecordUpdateError(table_name) from exc
|
|
@@ -190,13 +218,36 @@ class SqliterDB:
|
|
|
190
218
|
|
|
191
219
|
if cursor.rowcount == 0:
|
|
192
220
|
raise RecordNotFoundError(primary_key_value)
|
|
193
|
-
self._maybe_commit(
|
|
221
|
+
self._maybe_commit()
|
|
194
222
|
except sqlite3.Error as exc:
|
|
195
223
|
raise RecordDeletionError(table_name) from exc
|
|
196
224
|
|
|
197
|
-
def select(
|
|
198
|
-
|
|
199
|
-
|
|
225
|
+
def select(
|
|
226
|
+
self,
|
|
227
|
+
model_class: type[BaseDBModel],
|
|
228
|
+
fields: Optional[list[str]] = None,
|
|
229
|
+
exclude: Optional[list[str]] = None,
|
|
230
|
+
) -> QueryBuilder:
|
|
231
|
+
"""Start a query for the given model.
|
|
232
|
+
|
|
233
|
+
Args:
|
|
234
|
+
model_class: The model class to query.
|
|
235
|
+
fields: Optional list of field names to select. If None, all fields
|
|
236
|
+
are selected.
|
|
237
|
+
exclude: Optional list of field names to exclude from the query
|
|
238
|
+
output.
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
QueryBuilder: An instance of QueryBuilder for the given model and
|
|
242
|
+
fields.
|
|
243
|
+
"""
|
|
244
|
+
query_builder = QueryBuilder(self, model_class, fields)
|
|
245
|
+
|
|
246
|
+
# If exclude is provided, apply the exclude method
|
|
247
|
+
if exclude:
|
|
248
|
+
query_builder.exclude(exclude)
|
|
249
|
+
|
|
250
|
+
return query_builder
|
|
200
251
|
|
|
201
252
|
# --- Context manager methods ---
|
|
202
253
|
def __enter__(self) -> Self:
|
|
@@ -216,7 +267,8 @@ class SqliterDB:
|
|
|
216
267
|
if exc_type:
|
|
217
268
|
# Roll back the transaction if there was an exception
|
|
218
269
|
self.conn.rollback()
|
|
219
|
-
|
|
270
|
+
else:
|
|
271
|
+
self.conn.commit()
|
|
220
272
|
finally:
|
|
221
273
|
# Close the connection and reset the instance variable
|
|
222
274
|
self.conn.close()
|