apexdevkit 1.17.1__tar.gz → 1.17.3__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.
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/PKG-INFO +1 -1
- apexdevkit-1.17.3/apexdevkit/repository/sqlite.py +277 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/pyproject.toml +1 -1
- apexdevkit-1.17.1/apexdevkit/repository/sqlite.py +0 -97
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/LICENSE +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/README.md +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/error.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/request.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/mongo.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/repository/mssql.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/server.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.17.1 → apexdevkit-1.17.3}/apexdevkit/value.py +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from sqlite3 import IntegrityError
|
|
5
|
+
from typing import Any, Generic, Iterable, Iterator
|
|
6
|
+
|
|
7
|
+
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
8
|
+
from apexdevkit.formatter import Formatter
|
|
9
|
+
from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
|
|
10
|
+
from apexdevkit.repository.interface import ItemT
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class SqliteRepository(RepositoryBase[ItemT]):
|
|
15
|
+
db: Database
|
|
16
|
+
table: SqlTable[ItemT]
|
|
17
|
+
|
|
18
|
+
def bind(self, **kwargs: Any) -> SqliteRepository[ItemT]:
|
|
19
|
+
return SqliteRepository(self.db, self.table.bind(**kwargs))
|
|
20
|
+
|
|
21
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
22
|
+
for raw in self.db.execute(self.table.select_all()).fetch_all():
|
|
23
|
+
yield self.table.load(raw)
|
|
24
|
+
|
|
25
|
+
def __len__(self) -> int:
|
|
26
|
+
raw = self.db.execute(self.table.count_all()).fetch_one()
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
return int(raw["n_items"])
|
|
30
|
+
except KeyError:
|
|
31
|
+
raise UnknownError(raw)
|
|
32
|
+
|
|
33
|
+
def create(self, item: ItemT) -> ItemT:
|
|
34
|
+
try:
|
|
35
|
+
return self.table.load(self.db.execute(self.table.insert(item)).fetch_one())
|
|
36
|
+
except IntegrityError: # pragma: no cover
|
|
37
|
+
item = self.table.load(
|
|
38
|
+
self.db.execute(self.table.select_duplicate(item)).fetch_one()
|
|
39
|
+
)
|
|
40
|
+
self.table.duplicate(item).fire()
|
|
41
|
+
return item
|
|
42
|
+
|
|
43
|
+
def read(self, item_id: str) -> ItemT:
|
|
44
|
+
raw = self.db.execute(self.table.select(str(item_id))).fetch_one()
|
|
45
|
+
|
|
46
|
+
if not raw:
|
|
47
|
+
raise DoesNotExistError(item_id)
|
|
48
|
+
|
|
49
|
+
return self.table.load(raw)
|
|
50
|
+
|
|
51
|
+
def update(self, item: ItemT) -> None:
|
|
52
|
+
self.db.execute(self.table.update(item)).fetch_none()
|
|
53
|
+
|
|
54
|
+
def delete(self, item_id: str) -> None:
|
|
55
|
+
self.db.execute(self.table.delete(str(item_id))).fetch_none()
|
|
56
|
+
|
|
57
|
+
def delete_all(self) -> None:
|
|
58
|
+
self.db.execute(self.table.delete_all()).fetch_none()
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class SqlTable(Generic[ItemT]): # pragma: no cover
|
|
62
|
+
def bind(self, **kwargs: Any) -> SqlTable[ItemT]:
|
|
63
|
+
return self
|
|
64
|
+
|
|
65
|
+
def count_all(self) -> DatabaseCommand:
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
|
|
68
|
+
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
69
|
+
raise NotImplementedError
|
|
70
|
+
|
|
71
|
+
def select(self, item_id: str) -> DatabaseCommand:
|
|
72
|
+
raise NotImplementedError
|
|
73
|
+
|
|
74
|
+
def select_duplicate(self, item: ItemT) -> DatabaseCommand:
|
|
75
|
+
raise NotImplementedError
|
|
76
|
+
|
|
77
|
+
def select_all(self) -> DatabaseCommand:
|
|
78
|
+
raise NotImplementedError
|
|
79
|
+
|
|
80
|
+
def update(self, item: ItemT) -> DatabaseCommand:
|
|
81
|
+
raise NotImplementedError
|
|
82
|
+
|
|
83
|
+
def delete(self, item_id: str) -> DatabaseCommand:
|
|
84
|
+
raise NotImplementedError
|
|
85
|
+
|
|
86
|
+
def delete_all(self) -> DatabaseCommand:
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
|
|
89
|
+
def load(self, data: dict[str, Any]) -> ItemT:
|
|
90
|
+
raise NotImplementedError
|
|
91
|
+
|
|
92
|
+
def duplicate(self, item: ItemT) -> ExistsError:
|
|
93
|
+
return ExistsError(item).with_duplicate(lambda i: "Unknown")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class UnknownError(Exception):
|
|
98
|
+
raw: dict[str, Any]
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
@dataclass(frozen=True)
|
|
102
|
+
class SqliteTableBuilder(Generic[ItemT]):
|
|
103
|
+
table_name: str | None = None
|
|
104
|
+
formatter: Formatter[dict[str, Any], ItemT] | None = None
|
|
105
|
+
fields: list[SqliteField] | None = None
|
|
106
|
+
|
|
107
|
+
def with_name(self, value: str) -> SqliteTableBuilder[ItemT]:
|
|
108
|
+
return SqliteTableBuilder[ItemT](value, self.formatter, self.fields)
|
|
109
|
+
|
|
110
|
+
def with_formatter(
|
|
111
|
+
self, value: Formatter[dict[str, Any], ItemT]
|
|
112
|
+
) -> SqliteTableBuilder[ItemT]:
|
|
113
|
+
return SqliteTableBuilder[ItemT](self.table_name, value, self.fields)
|
|
114
|
+
|
|
115
|
+
def with_fields(self, fields: Iterable[str]) -> SqliteTableBuilder[ItemT]:
|
|
116
|
+
return SqliteTableBuilder[ItemT](
|
|
117
|
+
self.table_name,
|
|
118
|
+
self.formatter,
|
|
119
|
+
[SqliteField(field, field == "id", False) for field in list(fields)],
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
def with_id(self, identifier: str) -> SqliteTableBuilder[ItemT]:
|
|
123
|
+
assert self.fields is not None, "Set fields first."
|
|
124
|
+
if identifier not in [field.name for field in self.fields]:
|
|
125
|
+
raise ValueError("Missing fields in the table.")
|
|
126
|
+
|
|
127
|
+
return SqliteTableBuilder[ItemT](
|
|
128
|
+
self.table_name,
|
|
129
|
+
self.formatter,
|
|
130
|
+
[
|
|
131
|
+
SqliteField(field.name, field.name == identifier, field.is_composite)
|
|
132
|
+
for field in self.fields
|
|
133
|
+
],
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
def with_composite_key(
|
|
137
|
+
self, composites: Iterable[str]
|
|
138
|
+
) -> SqliteTableBuilder[ItemT]:
|
|
139
|
+
assert self.fields is not None, "Set fields first."
|
|
140
|
+
|
|
141
|
+
names = [field.name for field in self.fields]
|
|
142
|
+
if not all(field in names for field in list(composites)):
|
|
143
|
+
raise ValueError("Missing fields in the table.")
|
|
144
|
+
|
|
145
|
+
return SqliteTableBuilder[ItemT](
|
|
146
|
+
self.table_name,
|
|
147
|
+
self.formatter,
|
|
148
|
+
[
|
|
149
|
+
SqliteField(field.name, field.is_id, field.name in list(composites))
|
|
150
|
+
for field in self.fields
|
|
151
|
+
],
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def build(self) -> SqlTable[ItemT]:
|
|
155
|
+
if not self.table_name or not self.formatter or not self.fields:
|
|
156
|
+
raise ValueError("Cannot build sql table.")
|
|
157
|
+
|
|
158
|
+
return _DefaultSqlTable(self.table_name, self.formatter, self.fields)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
@dataclass(frozen=True)
|
|
162
|
+
class _DefaultSqlTable(SqlTable[ItemT]):
|
|
163
|
+
table_name: str
|
|
164
|
+
formatter: Formatter[dict[str, Any], ItemT]
|
|
165
|
+
fields: list[SqliteField]
|
|
166
|
+
|
|
167
|
+
def count_all(self) -> DatabaseCommand:
|
|
168
|
+
return DatabaseCommand(f"""
|
|
169
|
+
SELECT count(*) as n_items
|
|
170
|
+
FROM {self.table_name.capitalize()};
|
|
171
|
+
""")
|
|
172
|
+
|
|
173
|
+
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
174
|
+
columns = ", ".join([field.name for field in self.fields])
|
|
175
|
+
placeholders = ", ".join([f":{key.name}" for key in self.fields])
|
|
176
|
+
|
|
177
|
+
return DatabaseCommand(f"""
|
|
178
|
+
INSERT INTO {self.table_name.capitalize()} (
|
|
179
|
+
{columns}
|
|
180
|
+
) VALUES (
|
|
181
|
+
{placeholders}
|
|
182
|
+
)
|
|
183
|
+
RETURNING {columns};
|
|
184
|
+
""").with_data(self.formatter.dump(item))
|
|
185
|
+
|
|
186
|
+
def select(self, item_id: str) -> DatabaseCommand:
|
|
187
|
+
columns = ", ".join([field.name for field in self.fields])
|
|
188
|
+
|
|
189
|
+
return DatabaseCommand(f"""
|
|
190
|
+
SELECT
|
|
191
|
+
{columns}
|
|
192
|
+
FROM {self.table_name.capitalize()}
|
|
193
|
+
WHERE {self._id} = :{self._id};
|
|
194
|
+
""").with_data({self._id: item_id})
|
|
195
|
+
|
|
196
|
+
def select_duplicate(self, item: ItemT) -> DatabaseCommand:
|
|
197
|
+
raw = self.formatter.dump(item)
|
|
198
|
+
columns = ", ".join([field.name for field in self.fields])
|
|
199
|
+
|
|
200
|
+
duplicates = " AND ".join([f"{field} = :{field}" for field in self._composite])
|
|
201
|
+
|
|
202
|
+
return DatabaseCommand(f"""
|
|
203
|
+
SELECT
|
|
204
|
+
{columns}
|
|
205
|
+
FROM {self.table_name.capitalize()}
|
|
206
|
+
WHERE {duplicates};
|
|
207
|
+
""").with_data({key: raw[key] for key in raw if key in self._composite})
|
|
208
|
+
|
|
209
|
+
def select_all(self) -> DatabaseCommand:
|
|
210
|
+
columns = ", ".join([field.name for field in self.fields])
|
|
211
|
+
|
|
212
|
+
return DatabaseCommand(f"""
|
|
213
|
+
SELECT
|
|
214
|
+
{columns}
|
|
215
|
+
FROM {self.table_name.capitalize()};
|
|
216
|
+
""")
|
|
217
|
+
|
|
218
|
+
def update(self, item: ItemT) -> DatabaseCommand:
|
|
219
|
+
updates = ", ".join(
|
|
220
|
+
[
|
|
221
|
+
f"{field.name} = :{field.name}"
|
|
222
|
+
for field in self.fields
|
|
223
|
+
if not field.is_id
|
|
224
|
+
]
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
return DatabaseCommand(f"""
|
|
228
|
+
UPDATE {self.table_name.capitalize()}
|
|
229
|
+
SET
|
|
230
|
+
{updates}
|
|
231
|
+
WHERE
|
|
232
|
+
{self._id} = :{self._id};
|
|
233
|
+
""").with_data(self.formatter.dump(item))
|
|
234
|
+
|
|
235
|
+
def delete(self, item_id: str) -> DatabaseCommand:
|
|
236
|
+
return DatabaseCommand(f"""
|
|
237
|
+
DELETE
|
|
238
|
+
FROM {self.table_name.capitalize()}
|
|
239
|
+
WHERE
|
|
240
|
+
{self._id} = :{self._id};
|
|
241
|
+
""").with_data({self._id: item_id})
|
|
242
|
+
|
|
243
|
+
def delete_all(self) -> DatabaseCommand:
|
|
244
|
+
return DatabaseCommand(f"""
|
|
245
|
+
DELETE
|
|
246
|
+
FROM {self.table_name.capitalize()};
|
|
247
|
+
""")
|
|
248
|
+
|
|
249
|
+
def load(self, data: dict[str, Any]) -> ItemT:
|
|
250
|
+
return self.formatter.load(data)
|
|
251
|
+
|
|
252
|
+
def duplicate(self, item: ItemT) -> ExistsError:
|
|
253
|
+
raw = self.formatter.dump(item)
|
|
254
|
+
return ExistsError(item).with_duplicate(
|
|
255
|
+
lambda i: ",".join(
|
|
256
|
+
[f"{key}<{raw[key]}>" for key in raw if key in self._composite]
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
@property
|
|
261
|
+
def _id(self) -> str:
|
|
262
|
+
result = next((field for field in self.fields if field.is_id), None)
|
|
263
|
+
if result is None:
|
|
264
|
+
raise ValueError("Id field is required.")
|
|
265
|
+
return result.name
|
|
266
|
+
|
|
267
|
+
@property
|
|
268
|
+
def _composite(self) -> list[str]:
|
|
269
|
+
names = [field.name for field in self.fields if field.is_composite]
|
|
270
|
+
return [self._id] if len(names) == 0 else names
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
@dataclass(frozen=True)
|
|
274
|
+
class SqliteField:
|
|
275
|
+
name: str
|
|
276
|
+
is_id: bool
|
|
277
|
+
is_composite: bool
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from sqlite3 import IntegrityError
|
|
5
|
-
from typing import Any, Generic, Iterator
|
|
6
|
-
|
|
7
|
-
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
8
|
-
from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
|
|
9
|
-
from apexdevkit.repository.interface import ItemT
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@dataclass(frozen=True)
|
|
13
|
-
class SqliteRepository(RepositoryBase[ItemT]):
|
|
14
|
-
db: Database
|
|
15
|
-
table: SqlTable[ItemT]
|
|
16
|
-
|
|
17
|
-
def bind(self, **kwargs: Any) -> SqliteRepository[ItemT]:
|
|
18
|
-
return SqliteRepository(self.db, self.table.bind(**kwargs))
|
|
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 create(self, item: ItemT) -> ItemT:
|
|
33
|
-
try:
|
|
34
|
-
return self.table.load(self.db.execute(self.table.insert(item)).fetch_one())
|
|
35
|
-
except IntegrityError: # pragma: no cover
|
|
36
|
-
item = self.table.load(
|
|
37
|
-
self.db.execute(self.table.select_duplicate(item)).fetch_one()
|
|
38
|
-
)
|
|
39
|
-
self.table.duplicate(item).fire()
|
|
40
|
-
return item
|
|
41
|
-
|
|
42
|
-
def read(self, item_id: str) -> ItemT:
|
|
43
|
-
raw = self.db.execute(self.table.select(str(item_id))).fetch_one()
|
|
44
|
-
|
|
45
|
-
if not raw:
|
|
46
|
-
raise DoesNotExistError(item_id)
|
|
47
|
-
|
|
48
|
-
return self.table.load(raw)
|
|
49
|
-
|
|
50
|
-
def update(self, item: ItemT) -> None:
|
|
51
|
-
self.db.execute(self.table.update(item)).fetch_none()
|
|
52
|
-
|
|
53
|
-
def delete(self, item_id: str) -> None:
|
|
54
|
-
self.db.execute(self.table.delete(str(item_id))).fetch_none()
|
|
55
|
-
|
|
56
|
-
def delete_all(self) -> None:
|
|
57
|
-
self.db.execute(self.table.delete_all()).fetch_none()
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
class SqlTable(Generic[ItemT]): # pragma: no cover
|
|
61
|
-
def bind(self, **kwargs: Any) -> SqlTable[ItemT]:
|
|
62
|
-
return self
|
|
63
|
-
|
|
64
|
-
def count_all(self) -> DatabaseCommand:
|
|
65
|
-
raise NotImplementedError
|
|
66
|
-
|
|
67
|
-
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
68
|
-
raise NotImplementedError
|
|
69
|
-
|
|
70
|
-
def select(self, item_id: str) -> DatabaseCommand:
|
|
71
|
-
raise NotImplementedError
|
|
72
|
-
|
|
73
|
-
def select_duplicate(self, item: ItemT) -> DatabaseCommand:
|
|
74
|
-
raise NotImplementedError
|
|
75
|
-
|
|
76
|
-
def select_all(self) -> DatabaseCommand:
|
|
77
|
-
raise NotImplementedError
|
|
78
|
-
|
|
79
|
-
def update(self, item: ItemT) -> DatabaseCommand:
|
|
80
|
-
raise NotImplementedError
|
|
81
|
-
|
|
82
|
-
def delete(self, item_id: str) -> DatabaseCommand:
|
|
83
|
-
raise NotImplementedError
|
|
84
|
-
|
|
85
|
-
def delete_all(self) -> DatabaseCommand:
|
|
86
|
-
raise NotImplementedError
|
|
87
|
-
|
|
88
|
-
def load(self, data: dict[str, Any]) -> ItemT:
|
|
89
|
-
raise NotImplementedError
|
|
90
|
-
|
|
91
|
-
def duplicate(self, item: ItemT) -> ExistsError:
|
|
92
|
-
return ExistsError(item).with_duplicate(lambda i: "Unknown")
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
@dataclass
|
|
96
|
-
class UnknownError(Exception):
|
|
97
|
-
raw: dict[str, Any]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|