apexdevkit 1.21.4__tar.gz → 1.21.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.
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/PKG-INFO +1 -1
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/connector.py +4 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/database.py +3 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/mssql.py +25 -165
- apexdevkit-1.21.6/apexdevkit/repository/repository.py +82 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/pyproject.toml +1 -1
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/LICENSE +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/README.md +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/error.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/request.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/id.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/sql.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/repository/sqlite.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/server.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.21.4 → apexdevkit-1.21.6}/apexdevkit/value.py +0 -0
|
@@ -77,6 +77,7 @@ class ConnectionContextManager(AbstractContextManager[Connection]):
|
|
|
77
77
|
|
|
78
78
|
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
|
|
79
79
|
self.connection.cursor().close()
|
|
80
|
+
self.connection.close()
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
@dataclass
|
|
@@ -86,6 +87,9 @@ class MsSqlConnectionAdapter:
|
|
|
86
87
|
def cursor(self) -> MsSqlCursorAdapter:
|
|
87
88
|
return MsSqlCursorAdapter(self.connection.cursor())
|
|
88
89
|
|
|
90
|
+
def close(self) -> None:
|
|
91
|
+
self.connection.close()
|
|
92
|
+
|
|
89
93
|
|
|
90
94
|
@dataclass
|
|
91
95
|
class MsSqlCursorAdapter:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
from typing import Any,
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Generic, Iterable, Iterator, Mapping, TypeVar
|
|
5
5
|
|
|
6
6
|
from pymssql.exceptions import DatabaseError
|
|
7
7
|
|
|
@@ -142,92 +142,35 @@ class UnknownError(Exception):
|
|
|
142
142
|
class MsSqlTableBuilder(Generic[ItemT]):
|
|
143
143
|
username: str | None = None
|
|
144
144
|
schema: str | None = None
|
|
145
|
-
|
|
145
|
+
table: str | None = None
|
|
146
146
|
formatter: Formatter[Mapping[str, Any], ItemT] | None = None
|
|
147
147
|
fields: list[_SqlField] | None = None
|
|
148
|
-
table_mapper: Callable[[ItemT], str] | None = None
|
|
149
|
-
table_id_mapper: Callable[[str], str] | None = None
|
|
150
|
-
id_transformer: Callable[[str], str] = lambda identifier: identifier
|
|
151
148
|
|
|
152
149
|
def with_username(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
153
150
|
return MsSqlTableBuilder[ItemT](
|
|
154
151
|
value,
|
|
155
152
|
self.schema,
|
|
156
|
-
self.
|
|
153
|
+
self.table,
|
|
157
154
|
self.formatter,
|
|
158
155
|
self.fields,
|
|
159
|
-
self.table_mapper,
|
|
160
|
-
self.table_id_mapper,
|
|
161
|
-
self.id_transformer,
|
|
162
156
|
)
|
|
163
157
|
|
|
164
158
|
def with_schema(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
165
159
|
return MsSqlTableBuilder[ItemT](
|
|
166
160
|
self.username,
|
|
167
161
|
value,
|
|
168
|
-
self.
|
|
162
|
+
self.table,
|
|
169
163
|
self.formatter,
|
|
170
164
|
self.fields,
|
|
171
|
-
self.table_mapper,
|
|
172
|
-
self.table_id_mapper,
|
|
173
|
-
self.id_transformer,
|
|
174
165
|
)
|
|
175
166
|
|
|
176
167
|
def with_table(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
177
168
|
return MsSqlTableBuilder[ItemT](
|
|
178
169
|
self.username,
|
|
179
170
|
self.schema,
|
|
180
|
-
self.tables + [value],
|
|
181
|
-
self.formatter,
|
|
182
|
-
self.fields,
|
|
183
|
-
self.table_mapper,
|
|
184
|
-
self.table_id_mapper,
|
|
185
|
-
self.id_transformer,
|
|
186
|
-
)
|
|
187
|
-
|
|
188
|
-
def and_table(self, value: str) -> MsSqlTableBuilder[ItemT]:
|
|
189
|
-
return self.with_table(value)
|
|
190
|
-
|
|
191
|
-
def with_table_mapper(
|
|
192
|
-
self, value: Callable[[ItemT], str]
|
|
193
|
-
) -> MsSqlTableBuilder[ItemT]:
|
|
194
|
-
return MsSqlTableBuilder[ItemT](
|
|
195
|
-
self.username,
|
|
196
|
-
self.schema,
|
|
197
|
-
self.tables,
|
|
198
|
-
self.formatter,
|
|
199
|
-
self.fields,
|
|
200
|
-
value,
|
|
201
|
-
self.table_id_mapper,
|
|
202
|
-
self.id_transformer,
|
|
203
|
-
)
|
|
204
|
-
|
|
205
|
-
def with_table_id_mapper(
|
|
206
|
-
self, value: Callable[[str], str]
|
|
207
|
-
) -> MsSqlTableBuilder[ItemT]:
|
|
208
|
-
return MsSqlTableBuilder[ItemT](
|
|
209
|
-
self.username,
|
|
210
|
-
self.schema,
|
|
211
|
-
self.tables,
|
|
212
|
-
self.formatter,
|
|
213
|
-
self.fields,
|
|
214
|
-
self.table_mapper,
|
|
215
171
|
value,
|
|
216
|
-
self.id_transformer,
|
|
217
|
-
)
|
|
218
|
-
|
|
219
|
-
def with_id_transformer(
|
|
220
|
-
self, value: Callable[[str], str]
|
|
221
|
-
) -> MsSqlTableBuilder[ItemT]:
|
|
222
|
-
return MsSqlTableBuilder[ItemT](
|
|
223
|
-
self.username,
|
|
224
|
-
self.schema,
|
|
225
|
-
self.tables,
|
|
226
172
|
self.formatter,
|
|
227
173
|
self.fields,
|
|
228
|
-
self.table_mapper,
|
|
229
|
-
self.table_id_mapper,
|
|
230
|
-
value,
|
|
231
174
|
)
|
|
232
175
|
|
|
233
176
|
def with_formatter(
|
|
@@ -236,12 +179,9 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
236
179
|
return MsSqlTableBuilder[ItemT](
|
|
237
180
|
self.username,
|
|
238
181
|
self.schema,
|
|
239
|
-
self.
|
|
182
|
+
self.table,
|
|
240
183
|
value,
|
|
241
184
|
self.fields,
|
|
242
|
-
self.table_mapper,
|
|
243
|
-
self.table_id_mapper,
|
|
244
|
-
self.id_transformer,
|
|
245
185
|
)
|
|
246
186
|
|
|
247
187
|
def with_fields(self, value: Iterable[_SqlField]) -> MsSqlTableBuilder[ItemT]:
|
|
@@ -264,67 +204,42 @@ class MsSqlTableBuilder(Generic[ItemT]):
|
|
|
264
204
|
return MsSqlTableBuilder[ItemT](
|
|
265
205
|
self.username,
|
|
266
206
|
self.schema,
|
|
267
|
-
self.
|
|
207
|
+
self.table,
|
|
268
208
|
self.formatter,
|
|
269
209
|
key_list,
|
|
270
|
-
self.table_mapper,
|
|
271
|
-
self.table_id_mapper,
|
|
272
|
-
self.id_transformer,
|
|
273
210
|
)
|
|
274
211
|
|
|
275
212
|
def build(self) -> SqlTable[ItemT]:
|
|
276
|
-
if
|
|
277
|
-
not self.schema
|
|
278
|
-
or len(self.tables) < 1
|
|
279
|
-
or not self.formatter
|
|
280
|
-
or not self.fields
|
|
281
|
-
):
|
|
213
|
+
if not self.schema or not self.table or not self.formatter or not self.fields:
|
|
282
214
|
raise ValueError("Cannot build sql table.")
|
|
283
215
|
|
|
284
216
|
return DefaultSqlTable(
|
|
285
217
|
self.schema,
|
|
286
|
-
self.
|
|
218
|
+
self.table,
|
|
287
219
|
self.formatter,
|
|
288
220
|
SqlFieldManager.Builder().with_fields(self.fields).for_mssql().build(),
|
|
289
221
|
self.username,
|
|
290
|
-
self.table_mapper,
|
|
291
|
-
self.table_id_mapper,
|
|
292
|
-
self.id_transformer,
|
|
293
222
|
)
|
|
294
223
|
|
|
295
224
|
|
|
296
225
|
@dataclass(frozen=True)
|
|
297
226
|
class DefaultSqlTable(SqlTable[ItemT]):
|
|
298
227
|
schema: str
|
|
299
|
-
|
|
228
|
+
table: str
|
|
300
229
|
formatter: Formatter[Mapping[str, Any], ItemT]
|
|
301
230
|
fields: SqlFieldManager
|
|
302
231
|
username: str | None = None
|
|
303
|
-
table_mapper: Callable[[ItemT], str] | None = None
|
|
304
|
-
table_id_mapper: Callable[[str], str] | None = None
|
|
305
|
-
id_transformer: Callable[[str], str] = lambda identifier: identifier
|
|
306
232
|
|
|
307
233
|
def count_all(self) -> DatabaseCommand:
|
|
308
|
-
selections = " + ".join(
|
|
309
|
-
[
|
|
310
|
-
f"""(
|
|
311
|
-
SELECT COUNT(*)
|
|
312
|
-
FROM [{self.schema}].[{table}]
|
|
313
|
-
{self.fields.where_statement(include_id=False)}
|
|
314
|
-
)"""
|
|
315
|
-
for table in self.tables
|
|
316
|
-
]
|
|
317
|
-
)
|
|
318
234
|
return DatabaseCommand(f"""
|
|
319
235
|
{self._user_check}
|
|
320
|
-
SELECT
|
|
321
|
-
{
|
|
236
|
+
SELECT count(*) AS n_items
|
|
237
|
+
FROM [{self.schema}].[{self.table}]
|
|
238
|
+
{self.fields.where_statement(include_id=False)}
|
|
322
239
|
REVERT
|
|
323
240
|
""").with_data(self.fields.with_fixed({}))
|
|
324
241
|
|
|
325
242
|
def insert(self, item: ItemT) -> DatabaseCommand:
|
|
326
|
-
self._require_mapper_if_necessary()
|
|
327
|
-
|
|
328
243
|
columns = ", ".join(
|
|
329
244
|
["[" + field.name + "]" for field in self.fields if field.include_in_insert]
|
|
330
245
|
)
|
|
@@ -337,7 +252,7 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
337
252
|
["[" + field.name + "] AS " + field.name for field in self.fields]
|
|
338
253
|
)
|
|
339
254
|
where_statement = f"""
|
|
340
|
-
FROM [{self.schema}].[{self.
|
|
255
|
+
FROM [{self.schema}].[{self.table}]
|
|
341
256
|
{self.fields.where_statement(include_id=True, read_id=True)}
|
|
342
257
|
"""
|
|
343
258
|
except ValueError:
|
|
@@ -348,7 +263,7 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
348
263
|
|
|
349
264
|
return DatabaseCommand(f"""
|
|
350
265
|
{self._user_check}
|
|
351
|
-
INSERT INTO [{self.schema}].[{self.
|
|
266
|
+
INSERT INTO [{self.schema}].[{self.table}] (
|
|
352
267
|
{columns}
|
|
353
268
|
)
|
|
354
269
|
VALUES (
|
|
@@ -361,45 +276,31 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
361
276
|
""").with_data(self.fields.with_fixed(self.formatter.dump(item)))
|
|
362
277
|
|
|
363
278
|
def select(self, item_id: str) -> DatabaseCommand:
|
|
364
|
-
self._require_id_mapper_if_necessary()
|
|
365
|
-
|
|
366
279
|
columns = ", ".join(["[" + field.name + "]" for field in self.fields])
|
|
367
|
-
table_identifier = self.id_transformer(item_id)
|
|
368
280
|
|
|
369
281
|
return DatabaseCommand(f"""
|
|
370
282
|
{self._user_check}
|
|
371
283
|
SELECT
|
|
372
284
|
{columns}
|
|
373
|
-
FROM [{self.schema}].[{self.
|
|
285
|
+
FROM [{self.schema}].[{self.table}]
|
|
374
286
|
{self.fields.where_statement(include_id=True)}
|
|
375
287
|
REVERT
|
|
376
|
-
""").with_data(self.fields.with_fixed({self.fields.id:
|
|
288
|
+
""").with_data(self.fields.with_fixed({self.fields.id: item_id}))
|
|
377
289
|
|
|
378
290
|
def select_all(self) -> DatabaseCommand:
|
|
379
291
|
columns = ", ".join(["[" + field.name + "]" for field in self.fields])
|
|
380
292
|
|
|
381
|
-
selections = """
|
|
382
|
-
UNION ALL
|
|
383
|
-
""".join(
|
|
384
|
-
[
|
|
385
|
-
f"""SELECT
|
|
386
|
-
{columns}
|
|
387
|
-
FROM [{self.schema}].[{table}]
|
|
388
|
-
{self.fields.where_statement(include_id=False)}"""
|
|
389
|
-
for table in self.tables
|
|
390
|
-
]
|
|
391
|
-
)
|
|
392
|
-
|
|
393
293
|
return DatabaseCommand(f"""
|
|
394
294
|
{self._user_check}
|
|
395
|
-
|
|
295
|
+
SELECT
|
|
296
|
+
{columns}
|
|
297
|
+
FROM [{self.schema}].[{self.table}]
|
|
298
|
+
{self.fields.where_statement(include_id=False)}
|
|
396
299
|
{self.fields.order}
|
|
397
300
|
REVERT
|
|
398
301
|
""").with_data(self.fields.with_fixed({}))
|
|
399
302
|
|
|
400
303
|
def update(self, item: ItemT) -> DatabaseCommand:
|
|
401
|
-
self._require_mapper_if_necessary()
|
|
402
|
-
|
|
403
304
|
updates = ", ".join(
|
|
404
305
|
[
|
|
405
306
|
f"{field.name} = %({field.name})s"
|
|
@@ -410,7 +311,7 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
410
311
|
|
|
411
312
|
return DatabaseCommand(f"""
|
|
412
313
|
{self._user_check}
|
|
413
|
-
UPDATE [{self.schema}].[{self.
|
|
314
|
+
UPDATE [{self.schema}].[{self.table}]
|
|
414
315
|
SET
|
|
415
316
|
{updates}
|
|
416
317
|
{self.fields.where_statement(include_id=True)}
|
|
@@ -418,28 +319,19 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
418
319
|
""").with_data(self.fields.with_fixed(self.formatter.dump(item)))
|
|
419
320
|
|
|
420
321
|
def delete(self, item_id: str) -> DatabaseCommand:
|
|
421
|
-
self._require_mapper_if_necessary()
|
|
422
|
-
|
|
423
|
-
table_identifier = self.id_transformer(item_id)
|
|
424
|
-
|
|
425
322
|
return DatabaseCommand(f"""
|
|
426
323
|
{self._user_check}
|
|
427
324
|
DELETE
|
|
428
|
-
FROM [{self.schema}].[{self.
|
|
325
|
+
FROM [{self.schema}].[{self.table}]
|
|
429
326
|
{self.fields.where_statement(include_id=True)}
|
|
430
327
|
REVERT
|
|
431
|
-
""").with_data(self.fields.with_fixed({self.fields.id:
|
|
328
|
+
""").with_data(self.fields.with_fixed({self.fields.id: item_id}))
|
|
432
329
|
|
|
433
330
|
def delete_all(self) -> DatabaseCommand:
|
|
434
|
-
if len(self.tables) > 1:
|
|
435
|
-
raise RuntimeError(
|
|
436
|
-
f"Deletion of multiple tables {self.tables} not supported"
|
|
437
|
-
)
|
|
438
|
-
|
|
439
331
|
return DatabaseCommand(f"""
|
|
440
332
|
{self._user_check}
|
|
441
333
|
DELETE
|
|
442
|
-
FROM [{self.schema}].[{self.
|
|
334
|
+
FROM [{self.schema}].[{self.table}]
|
|
443
335
|
{self.fields.where_statement(include_id=False)}
|
|
444
336
|
REVERT
|
|
445
337
|
""").with_data(self.fields.with_fixed({}))
|
|
@@ -453,38 +345,6 @@ class DefaultSqlTable(SqlTable[ItemT]):
|
|
|
453
345
|
lambda i: f"{self.fields.id}<{raw[self.fields.id]}>"
|
|
454
346
|
)
|
|
455
347
|
|
|
456
|
-
def _require_mapper_if_necessary(self) -> None:
|
|
457
|
-
if len(self.tables) > 1 and self.table_mapper is None:
|
|
458
|
-
raise RuntimeError(
|
|
459
|
-
f"Attempt to use multiple tables {self.tables} "
|
|
460
|
-
f"on insert or update when mapping not provided"
|
|
461
|
-
)
|
|
462
|
-
|
|
463
|
-
def _require_id_mapper_if_necessary(self) -> None:
|
|
464
|
-
if len(self.tables) > 1 and self.table_id_mapper is None:
|
|
465
|
-
raise RuntimeError(
|
|
466
|
-
f"Attempt to use multiple tables {self.tables} "
|
|
467
|
-
f"on read or delete when id mapping not provided"
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
def _determine_table_by_item(self, item: ItemT) -> str:
|
|
471
|
-
if len(self.tables) == 1 or self.table_mapper is None:
|
|
472
|
-
return self.tables[0]
|
|
473
|
-
else:
|
|
474
|
-
table = self.table_mapper(item)
|
|
475
|
-
if table not in self.tables:
|
|
476
|
-
raise RuntimeError(f"Illegal table {table} provided")
|
|
477
|
-
return table
|
|
478
|
-
|
|
479
|
-
def _determine_table_by_id(self, identifier: str) -> str:
|
|
480
|
-
if len(self.tables) == 1 or self.table_id_mapper is None:
|
|
481
|
-
return self.tables[0]
|
|
482
|
-
else:
|
|
483
|
-
table = self.table_id_mapper(identifier)
|
|
484
|
-
if table not in self.tables:
|
|
485
|
-
raise RuntimeError(f"Illegal table {table} provided")
|
|
486
|
-
return table
|
|
487
|
-
|
|
488
348
|
@property
|
|
489
349
|
def _user_check(self) -> str:
|
|
490
350
|
if self.username is not None:
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Callable, Generic, Iterator, TypeVar
|
|
5
|
+
|
|
6
|
+
from apexdevkit.error import DoesNotExistError
|
|
7
|
+
from apexdevkit.repository import Repository, RepositoryBase
|
|
8
|
+
|
|
9
|
+
ItemT = TypeVar("ItemT")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class MultipleRepository(RepositoryBase[ItemT]):
|
|
14
|
+
repositories: list[_InnerRepository[ItemT]]
|
|
15
|
+
|
|
16
|
+
def create(self, item: ItemT) -> ItemT:
|
|
17
|
+
for repository in self.repositories:
|
|
18
|
+
if repository.condition(item):
|
|
19
|
+
return repository.repository.create(item)
|
|
20
|
+
|
|
21
|
+
raise RuntimeError("Can not create as no table was found")
|
|
22
|
+
|
|
23
|
+
def read(self, item_id: str) -> ItemT:
|
|
24
|
+
for repository in self.repositories:
|
|
25
|
+
if item_id.startswith(repository.id_prefix):
|
|
26
|
+
return repository.repository.read(item_id)
|
|
27
|
+
|
|
28
|
+
raise DoesNotExistError(item_id)
|
|
29
|
+
|
|
30
|
+
def update(self, item: ItemT) -> None:
|
|
31
|
+
for repository in self.repositories:
|
|
32
|
+
if repository.condition(item):
|
|
33
|
+
return repository.repository.update(item)
|
|
34
|
+
|
|
35
|
+
raise RuntimeError("Can not update as no table was found")
|
|
36
|
+
|
|
37
|
+
def delete(self, item_id: str) -> None:
|
|
38
|
+
for repository in self.repositories:
|
|
39
|
+
if item_id.startswith(repository.id_prefix):
|
|
40
|
+
return repository.repository.delete(item_id)
|
|
41
|
+
|
|
42
|
+
raise DoesNotExistError(item_id)
|
|
43
|
+
|
|
44
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
45
|
+
for repository in self.repositories:
|
|
46
|
+
yield from repository.repository
|
|
47
|
+
|
|
48
|
+
def __len__(self) -> int:
|
|
49
|
+
return sum(len(repository.repository) for repository in self.repositories)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@dataclass(frozen=True)
|
|
53
|
+
class MultipleRepositoryBuilder(Generic[ItemT]):
|
|
54
|
+
repositories: list[_InnerRepository[ItemT]] = field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
def with_repository(
|
|
57
|
+
self,
|
|
58
|
+
repository: Repository[ItemT],
|
|
59
|
+
condition: Callable[[ItemT], bool] = lambda item: True,
|
|
60
|
+
id_prefix: str = "",
|
|
61
|
+
) -> MultipleRepositoryBuilder[ItemT]:
|
|
62
|
+
return MultipleRepositoryBuilder[ItemT](
|
|
63
|
+
self.repositories + [_InnerRepository(repository, condition, id_prefix)]
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def and_repository(
|
|
67
|
+
self,
|
|
68
|
+
repository: Repository[ItemT],
|
|
69
|
+
condition: Callable[[ItemT], bool] = lambda item: True,
|
|
70
|
+
id_prefix: str = "",
|
|
71
|
+
) -> MultipleRepositoryBuilder[ItemT]:
|
|
72
|
+
return self.with_repository(repository, condition, id_prefix)
|
|
73
|
+
|
|
74
|
+
def build(self) -> MultipleRepository[ItemT]:
|
|
75
|
+
return MultipleRepository[ItemT](self.repositories)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True)
|
|
79
|
+
class _InnerRepository(Generic[ItemT]):
|
|
80
|
+
repository: Repository[ItemT]
|
|
81
|
+
condition: Callable[[ItemT], bool] = lambda item: True
|
|
82
|
+
id_prefix: str = ""
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|