apexdevkit 1.17.5__tar.gz → 1.17.6__tar.gz

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.
Files changed (48) hide show
  1. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/PKG-INFO +1 -1
  2. apexdevkit-1.17.6/apexdevkit/repository/mssql.py +467 -0
  3. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/pyproject.toml +1 -1
  4. apexdevkit-1.17.5/apexdevkit/repository/mssql.py +0 -104
  5. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/LICENSE +0 -0
  6. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/README.md +0 -0
  7. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/__init__.py +0 -0
  8. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/annotation/__init__.py +0 -0
  9. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/annotation/deprecate.py +0 -0
  10. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/environment.py +0 -0
  11. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/error.py +0 -0
  12. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/__init__.py +0 -0
  13. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/builder.py +0 -0
  14. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/dependable.py +0 -0
  15. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/docs.py +0 -0
  16. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/name.py +0 -0
  17. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/request.py +0 -0
  18. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/resource.py +0 -0
  19. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/response.py +0 -0
  20. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/router.py +0 -0
  21. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/schema.py +0 -0
  22. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fastapi/service.py +0 -0
  23. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/fluent.py +0 -0
  24. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/formatter.py +0 -0
  25. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/__init__.py +0 -0
  26. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/fake.py +0 -0
  27. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/fluent.py +0 -0
  28. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/httpx.py +0 -0
  29. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/json.py +0 -0
  30. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/http/url.py +0 -0
  31. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/key_fn.py +0 -0
  32. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/py.typed +0 -0
  33. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/__init__.py +0 -0
  34. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/base.py +0 -0
  35. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/connector.py +0 -0
  36. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/database.py +0 -0
  37. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/decorator.py +0 -0
  38. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/in_memory.py +0 -0
  39. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/interface.py +0 -0
  40. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/mongo.py +0 -0
  41. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/repository/sqlite.py +0 -0
  42. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/server.py +0 -0
  43. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/synchronization.py +0 -0
  44. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/testing/__init__.py +0 -0
  45. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/testing/database.py +0 -0
  46. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/testing/fake.py +0 -0
  47. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/testing/rest.py +0 -0
  48. {apexdevkit-1.17.5 → apexdevkit-1.17.6}/apexdevkit/value.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.17.5
3
+ Version: 1.17.6
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -0,0 +1,467 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Generic, Iterable, Iterator, TypeVar
5
+
6
+ from pymssql.exceptions import DatabaseError
7
+
8
+ from apexdevkit.error import DoesNotExistError, ExistsError
9
+ from apexdevkit.formatter import Formatter
10
+ from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
11
+
12
+ ItemT = TypeVar("ItemT")
13
+
14
+
15
+ @dataclass
16
+ class MsSqlRepository(RepositoryBase[ItemT]):
17
+ db: Database
18
+ table: SqlTable[ItemT]
19
+
20
+ def __iter__(self) -> Iterator[ItemT]:
21
+ for raw in self.db.execute(self.table.select_all()).fetch_all():
22
+ yield self.table.load(raw)
23
+
24
+ def __len__(self) -> int:
25
+ raw = self.db.execute(self.table.count_all()).fetch_one()
26
+
27
+ try:
28
+ return int(raw["n_items"])
29
+ except KeyError:
30
+ raise UnknownError(raw)
31
+
32
+ def delete(self, item_id: str) -> None:
33
+ self.db.execute(self.table.delete(item_id)).fetch_none()
34
+
35
+ def delete_all(self) -> None:
36
+ self.db.execute(self.table.delete_all()).fetch_none()
37
+
38
+ def create(self, item: ItemT) -> ItemT:
39
+ try:
40
+ return self.table.load(self.db.execute(self.table.insert(item)).fetch_one())
41
+ except DatabaseError as e:
42
+ e = MssqlException(e)
43
+
44
+ if e.is_duplication():
45
+ raise self.table.exists(item)
46
+
47
+ raise UnknownError(e.message)
48
+
49
+ def read(self, item_id: str) -> ItemT:
50
+ raw = self.db.execute(self.table.select(item_id)).fetch_one()
51
+
52
+ if not raw:
53
+ raise DoesNotExistError(item_id)
54
+
55
+ return self.table.load(raw)
56
+
57
+ def update(self, item: ItemT) -> None:
58
+ self.db.execute(self.table.update(item)).fetch_none()
59
+
60
+
61
+ class SqlTable(Generic[ItemT]): # pragma: no cover
62
+ def count_all(self) -> DatabaseCommand:
63
+ raise NotImplementedError
64
+
65
+ def insert(self, item: ItemT) -> DatabaseCommand:
66
+ raise NotImplementedError
67
+
68
+ def select(self, item_id: str) -> DatabaseCommand:
69
+ raise NotImplementedError
70
+
71
+ def select_all(self) -> DatabaseCommand:
72
+ raise NotImplementedError
73
+
74
+ def delete(self, item_id: str) -> DatabaseCommand:
75
+ raise NotImplementedError
76
+
77
+ def delete_all(self) -> DatabaseCommand:
78
+ raise NotImplementedError
79
+
80
+ def update(self, item: ItemT) -> DatabaseCommand:
81
+ raise NotImplementedError
82
+
83
+ def load(self, data: dict[str, Any]) -> ItemT:
84
+ raise NotImplementedError
85
+
86
+ def exists(self, duplicate: ItemT) -> ExistsError:
87
+ raise NotImplementedError
88
+
89
+
90
+ @dataclass
91
+ class SqlTableDecorator(Generic[ItemT]):
92
+ table: DefaultSqlTable[ItemT]
93
+
94
+ def count_all(self) -> DatabaseCommand:
95
+ return self.table.count_all()
96
+
97
+ def insert(self, item: ItemT) -> DatabaseCommand:
98
+ return self.table.insert(item)
99
+
100
+ def select(self, item_id: str) -> DatabaseCommand:
101
+ return self.table.select(item_id)
102
+
103
+ def select_all(self) -> DatabaseCommand:
104
+ return self.table.select_all()
105
+
106
+ def delete(self, item_id: str) -> DatabaseCommand:
107
+ return self.table.delete(item_id)
108
+
109
+ def delete_all(self) -> DatabaseCommand:
110
+ return self.table.delete_all()
111
+
112
+ def update(self, item: ItemT) -> DatabaseCommand:
113
+ return self.table.update(item)
114
+
115
+ def load(self, data: dict[str, Any]) -> ItemT:
116
+ return self.table.load(data)
117
+
118
+ def exists(self, duplicate: ItemT) -> ExistsError:
119
+ return self.table.exists(duplicate)
120
+
121
+
122
+ @dataclass
123
+ class MssqlException:
124
+ code: int
125
+ message: str
126
+
127
+ def __init__(self, e: DatabaseError):
128
+ self.code = e.args[0]
129
+ self.message = e.args[1].decode()
130
+
131
+ def is_duplication(self) -> bool:
132
+ return self.code in [2627, 70003]
133
+
134
+
135
+ @dataclass
136
+ class UnknownError(Exception):
137
+ raw: Any
138
+
139
+
140
+ @dataclass(frozen=True)
141
+ class MsSqlTableBuilder(Generic[ItemT]):
142
+ username: str | None = None
143
+ schema: str | None = None
144
+ table: str | None = None
145
+ formatter: Formatter[dict[str, Any], ItemT] | None = None
146
+ fields: list[MsSqlField] | None = None
147
+ ordering: list[str] | None = None
148
+ parent_field: str | None = None
149
+ parent_value: Any | None = None
150
+
151
+ def with_username(self, value: str) -> MsSqlTableBuilder[ItemT]:
152
+ return MsSqlTableBuilder[ItemT](
153
+ value,
154
+ self.schema,
155
+ self.table,
156
+ self.formatter,
157
+ self.fields,
158
+ self.ordering,
159
+ self.parent_field,
160
+ self.parent_value,
161
+ )
162
+
163
+ def with_schema(self, value: str) -> MsSqlTableBuilder[ItemT]:
164
+ return MsSqlTableBuilder[ItemT](
165
+ self.username,
166
+ value,
167
+ self.table,
168
+ self.formatter,
169
+ self.fields,
170
+ self.ordering,
171
+ self.parent_field,
172
+ self.parent_value,
173
+ )
174
+
175
+ def with_table(self, value: str) -> MsSqlTableBuilder[ItemT]:
176
+ return MsSqlTableBuilder[ItemT](
177
+ self.username,
178
+ self.schema,
179
+ value,
180
+ self.formatter,
181
+ self.fields,
182
+ self.ordering,
183
+ self.parent_field,
184
+ self.parent_value,
185
+ )
186
+
187
+ def with_formatter(
188
+ self, value: Formatter[dict[str, Any], ItemT]
189
+ ) -> MsSqlTableBuilder[ItemT]:
190
+ return MsSqlTableBuilder[ItemT](
191
+ self.username,
192
+ self.schema,
193
+ self.table,
194
+ value,
195
+ self.fields,
196
+ self.ordering,
197
+ self.parent_field,
198
+ self.parent_value,
199
+ )
200
+
201
+ def with_fields(self, fields: Iterable[str]) -> MsSqlTableBuilder[ItemT]:
202
+ return MsSqlTableBuilder[ItemT](
203
+ self.username,
204
+ self.schema,
205
+ self.table,
206
+ self.formatter,
207
+ [MsSqlField(field, field == "id") for field in list(fields)],
208
+ self.ordering,
209
+ self.parent_field,
210
+ self.parent_value,
211
+ )
212
+
213
+ def with_order_fields(self, ordering: Iterable[str]) -> MsSqlTableBuilder[ItemT]:
214
+ ordered = list(ordering)
215
+ assert self.fields is not None, "Set fields first."
216
+
217
+ for key in ordered:
218
+ if key not in [field.name for field in self.fields]:
219
+ raise ValueError("Missing fields in the table.")
220
+ return MsSqlTableBuilder[ItemT](
221
+ self.username,
222
+ self.schema,
223
+ self.table,
224
+ self.formatter,
225
+ self.fields,
226
+ ordered,
227
+ self.parent_field,
228
+ self.parent_value,
229
+ )
230
+
231
+ def with_id(self, identifier: str) -> MsSqlTableBuilder[ItemT]:
232
+ assert self.fields is not None, "Set fields first."
233
+ if identifier not in [field.name for field in self.fields]:
234
+ raise ValueError("Missing fields in the table.")
235
+
236
+ return MsSqlTableBuilder[ItemT](
237
+ self.username,
238
+ self.schema,
239
+ self.table,
240
+ self.formatter,
241
+ [MsSqlField(field.name, field.name == identifier) for field in self.fields],
242
+ self.ordering,
243
+ self.parent_field,
244
+ self.parent_value,
245
+ )
246
+
247
+ def with_parent(
248
+ self, parent_field: str, parent_value: Any
249
+ ) -> MsSqlTableBuilder[ItemT]:
250
+ assert self.fields is not None, "Set fields first."
251
+ if parent_field not in [field.name for field in self.fields]:
252
+ raise ValueError("Missing fields in the table.")
253
+
254
+ return MsSqlTableBuilder[ItemT](
255
+ self.username,
256
+ self.schema,
257
+ self.table,
258
+ self.formatter,
259
+ self.fields,
260
+ self.ordering,
261
+ parent_field,
262
+ parent_value,
263
+ )
264
+
265
+ def build(self) -> SqlTable[ItemT]:
266
+ if not self.schema or not self.table or not self.formatter or not self.fields:
267
+ raise ValueError("Cannot build sql table.")
268
+
269
+ return DefaultSqlTable(
270
+ self.username,
271
+ self.schema,
272
+ self.table,
273
+ self.formatter,
274
+ self.fields,
275
+ self.ordering,
276
+ self.parent_field,
277
+ self.parent_value,
278
+ )
279
+
280
+
281
+ @dataclass(frozen=True)
282
+ class DefaultSqlTable(SqlTable[ItemT]):
283
+ username: str | None
284
+ schema: str
285
+ table: str
286
+ formatter: Formatter[dict[str, Any], ItemT]
287
+ fields: list[MsSqlField]
288
+ ordering: list[str] | None
289
+ parent_key: str | None
290
+ parent_value: Any | None
291
+
292
+ def count_all(self) -> DatabaseCommand:
293
+ where_statement = ""
294
+ if self.parent_key is not None:
295
+ where_statement += (
296
+ "WHERE [" + self.parent_key + "] = " + self._parent_value_sql
297
+ )
298
+
299
+ return DatabaseCommand(f"""
300
+ {self._user_check}
301
+ SELECT count(*) AS n_items
302
+ FROM [{self.schema}].[{self.table}]
303
+ {where_statement}
304
+ REVERT
305
+ """)
306
+
307
+ def insert(self, item: ItemT) -> DatabaseCommand:
308
+ dumped = self.formatter.dump(item)
309
+ if self.parent_key is not None:
310
+ dumped[self.parent_key] = self.parent_value
311
+
312
+ columns = ", ".join(["[" + field.name + "]" for field in self.fields])
313
+ placeholders = ", ".join([f"%({key.name})s" for key in self.fields])
314
+ output = ", ".join(["INSERTED." + field.name for field in self.fields])
315
+
316
+ return DatabaseCommand(f"""
317
+ {self._user_check}
318
+ INSERT INTO [{self.schema}].[{self.table}] (
319
+ {columns}
320
+ ) OUTPUT
321
+ {output}
322
+ VALUES (
323
+ {placeholders}
324
+ )
325
+ REVERT
326
+ """).with_data(dumped)
327
+
328
+ def select(self, item_id: str) -> DatabaseCommand:
329
+ raw: dict[str, Any] = {self._id: item_id}
330
+ where_statement = f"WHERE [{self._id}] = %({self._id})s"
331
+ if self.parent_key is not None:
332
+ raw[self.parent_key] = self.parent_value
333
+ where_statement += (
334
+ ", [" + self.parent_key + "] = %(" + self.parent_key + ")s"
335
+ )
336
+
337
+ columns = ", ".join(["[" + field.name + "]" for field in self.fields])
338
+
339
+ return DatabaseCommand(f"""
340
+ {self._user_check}
341
+ SELECT
342
+ {columns}
343
+ FROM [{self.schema}].[{self.table}]
344
+ {where_statement}
345
+ REVERT
346
+ """).with_data(raw)
347
+
348
+ def select_all(self) -> DatabaseCommand:
349
+ columns = ", ".join(["[" + field.name + "]" for field in self.fields])
350
+ where_statement = ""
351
+ if self.parent_key is not None:
352
+ where_statement += (
353
+ "WHERE [" + self.parent_key + "] = " + self._parent_value_sql
354
+ )
355
+
356
+ return DatabaseCommand(f"""
357
+ {self._user_check}
358
+ SELECT
359
+ {columns}
360
+ FROM [{self.schema}].[{self.table}]
361
+ {where_statement}
362
+ {self._order}
363
+ REVERT
364
+ """)
365
+
366
+ def update(self, item: ItemT) -> DatabaseCommand:
367
+ dumped = self.formatter.dump(item)
368
+ if self.parent_key is not None:
369
+ dumped[self.parent_key] = self.parent_value
370
+
371
+ where_statement = f"WHERE [{self._id}] = %({self._id})s"
372
+ if self.parent_key is not None:
373
+ where_statement += (
374
+ ", [" + self.parent_key + "] = %(" + self.parent_key + ")s"
375
+ )
376
+
377
+ updates = ", ".join(
378
+ [
379
+ f"{field.name} = %({field.name})s"
380
+ for field in self.fields
381
+ if not field.is_id and field.name != self.parent_key
382
+ ]
383
+ )
384
+
385
+ return DatabaseCommand(f"""
386
+ {self._user_check}
387
+ UPDATE [{self.schema}].[{self.table}]
388
+ SET
389
+ {updates}
390
+ {where_statement}
391
+ REVERT
392
+ """).with_data(dumped)
393
+
394
+ def delete(self, item_id: str) -> DatabaseCommand:
395
+ raw: dict[str, Any] = {self._id: item_id}
396
+ where_statement = f"WHERE [{self._id}] = %({self._id})s"
397
+ if self.parent_key is not None:
398
+ raw[self.parent_key] = self.parent_value
399
+ where_statement += (
400
+ ", [" + self.parent_key + "] = %(" + self.parent_key + ")s"
401
+ )
402
+
403
+ return DatabaseCommand(f"""
404
+ {self._user_check}
405
+ DELETE
406
+ FROM [{self.schema}].[{self.table}]
407
+ {where_statement}
408
+ REVERT
409
+ """).with_data(raw)
410
+
411
+ def delete_all(self) -> DatabaseCommand:
412
+ where_statement = ""
413
+ if self.parent_key is not None:
414
+ where_statement += (
415
+ "WHERE [" + self.parent_key + "] = " + self._parent_value_sql
416
+ )
417
+
418
+ return DatabaseCommand(f"""
419
+ {self._user_check}
420
+ DELETE
421
+ FROM [{self.schema}].[{self.table}]
422
+ {where_statement}
423
+ REVERT
424
+ """)
425
+
426
+ def load(self, data: dict[str, Any]) -> ItemT:
427
+ return self.formatter.load(data)
428
+
429
+ def exists(self, duplicate: ItemT) -> ExistsError:
430
+ raw = self.formatter.dump(duplicate)
431
+ return ExistsError(duplicate).with_duplicate(
432
+ lambda i: f"{self._id}<{raw[self._id]}>"
433
+ )
434
+
435
+ @property
436
+ def _id(self) -> str:
437
+ result = next((field for field in self.fields if field.is_id), None)
438
+ if result is None:
439
+ raise ValueError("Id field is required.")
440
+ return result.name
441
+
442
+ @property
443
+ def _user_check(self) -> str:
444
+ if self.username is not None:
445
+ return f"EXECUTE AS USER = '{self.username}'"
446
+ else:
447
+ return ""
448
+
449
+ @property
450
+ def _order(self) -> str:
451
+ if self.ordering is not None and len(self.ordering) > 0:
452
+ return "ORDER BY " + ", ".join(self.ordering)
453
+ else:
454
+ return ""
455
+
456
+ @property
457
+ def _parent_value_sql(self) -> str:
458
+ if isinstance(self.parent_value, str):
459
+ return "'" + self.parent_value + "'"
460
+ else:
461
+ return str(self.parent_value)
462
+
463
+
464
+ @dataclass(frozen=True)
465
+ class MsSqlField:
466
+ name: str
467
+ is_id: bool
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.17.5"
3
+ version = "1.17.6"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -1,104 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass
4
- from typing import Any, Generic, Iterator, TypeVar
5
-
6
- from pymssql.exceptions import DatabaseError
7
-
8
- from apexdevkit.error import DoesNotExistError, ExistsError
9
- from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
10
-
11
- ItemT = TypeVar("ItemT")
12
-
13
-
14
- @dataclass
15
- class MsSqlRepository(RepositoryBase[ItemT]):
16
- db: Database
17
- table: SqlTable[ItemT]
18
-
19
- def __iter__(self) -> Iterator[ItemT]:
20
- for raw in self.db.execute(self.table.select_all()).fetch_all():
21
- yield self.table.load(raw)
22
-
23
- def __len__(self) -> int:
24
- raw = self.db.execute(self.table.count_all()).fetch_one()
25
-
26
- try:
27
- return int(raw["n_items"])
28
- except KeyError:
29
- raise UnknownError(raw)
30
-
31
- def delete(self, item_id: str) -> None:
32
- self.db.execute(self.table.delete(item_id)).fetch_none()
33
-
34
- def delete_all(self) -> None:
35
- self.db.execute(self.table.delete_all()).fetch_none()
36
-
37
- def create(self, item: ItemT) -> ItemT:
38
- try:
39
- return self.table.load(self.db.execute(self.table.insert(item)).fetch_one())
40
- except DatabaseError as e:
41
- e = MssqlException(e)
42
-
43
- if e.is_duplication():
44
- raise self.table.exists(item)
45
-
46
- raise UnknownError(e.message)
47
-
48
- def read(self, item_id: str) -> ItemT:
49
- raw = self.db.execute(self.table.select(item_id)).fetch_one()
50
-
51
- if not raw:
52
- raise DoesNotExistError(item_id)
53
-
54
- return self.table.load(raw)
55
-
56
- def update(self, item: ItemT) -> None:
57
- self.db.execute(self.table.update(item)).fetch_none()
58
-
59
-
60
- class SqlTable(Generic[ItemT]): # pragma: no cover
61
- def count_all(self) -> DatabaseCommand:
62
- raise NotImplementedError
63
-
64
- def insert(self, item: ItemT) -> DatabaseCommand:
65
- raise NotImplementedError
66
-
67
- def select(self, item_id: str) -> DatabaseCommand:
68
- raise NotImplementedError
69
-
70
- def select_all(self) -> DatabaseCommand:
71
- raise NotImplementedError
72
-
73
- def delete(self, item_id: str) -> DatabaseCommand:
74
- raise NotImplementedError
75
-
76
- def delete_all(self) -> DatabaseCommand:
77
- raise NotImplementedError
78
-
79
- def update(self, item: ItemT) -> DatabaseCommand:
80
- raise NotImplementedError
81
-
82
- def load(self, data: dict[str, Any]) -> ItemT:
83
- raise NotImplementedError
84
-
85
- def exists(self, duplicate: ItemT) -> ExistsError:
86
- raise NotImplementedError
87
-
88
-
89
- @dataclass
90
- class MssqlException:
91
- code: int
92
- message: str
93
-
94
- def __init__(self, e: DatabaseError):
95
- self.code = e.args[0]
96
- self.message = e.args[1].decode()
97
-
98
- def is_duplication(self) -> bool:
99
- return self.code in [2627, 70003]
100
-
101
-
102
- @dataclass
103
- class UnknownError(Exception):
104
- raw: Any
File without changes
File without changes