apexdevkit 1.29.2__tar.gz → 1.29.4__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.29.2 → apexdevkit-1.29.4}/PKG-INFO +1 -1
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/service.py +5 -7
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/__init__.py +2 -2
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/__init__.py +8 -3
- apexdevkit-1.29.4/apexdevkit/repository/core/decorator.py +77 -0
- apexdevkit-1.29.4/apexdevkit/repository/core/interface.py +45 -0
- apexdevkit-1.29.4/apexdevkit/repository/core/mixin.py +24 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/multi.py +3 -2
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/repository.py +2 -3
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/mssql.py +10 -3
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/sqlite.py +10 -4
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/pyproject.toml +1 -1
- apexdevkit-1.29.2/apexdevkit/repository/core/decorator.py +0 -37
- apexdevkit-1.29.2/apexdevkit/repository/core/interface.py +0 -68
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/LICENSE +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/README.md +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/date.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/error.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/name.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/router.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/formatter.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/client.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/hooks.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/id.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/key_fn.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/generator.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/query.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/database.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/mixin.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/store.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/connector.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/field.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/server.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/synchronization.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/rest.py +0 -0
- {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/value.py +0 -0
|
@@ -67,7 +67,7 @@ class RestfulRepository(RestfulService, Generic[ItemT]):
|
|
|
67
67
|
|
|
68
68
|
@cached_property
|
|
69
69
|
def _batch(self) -> BruteForceBatch[ItemT]:
|
|
70
|
-
return BruteForceBatch(self.repository)
|
|
70
|
+
return BruteForceBatch(inner=self.repository)
|
|
71
71
|
|
|
72
72
|
def create_one(self, item: RawItem) -> RawItem:
|
|
73
73
|
return self.formatter.dump(self.repository.create(self.formatter.load(item)))
|
|
@@ -75,7 +75,7 @@ class RestfulRepository(RestfulService, Generic[ItemT]):
|
|
|
75
75
|
def create_many(self, items: RawCollection) -> RawCollection:
|
|
76
76
|
return [
|
|
77
77
|
self.formatter.dump(item)
|
|
78
|
-
for item in self._batch.
|
|
78
|
+
for item in self._batch.load(
|
|
79
79
|
[self.formatter.load(fields) for fields in items]
|
|
80
80
|
)
|
|
81
81
|
]
|
|
@@ -102,9 +102,7 @@ class RestfulRepository(RestfulService, Generic[ItemT]):
|
|
|
102
102
|
|
|
103
103
|
updates.append(self.formatter.load(data))
|
|
104
104
|
|
|
105
|
-
self._batch.
|
|
106
|
-
|
|
107
|
-
return [self.formatter.dump(item) for item in updates]
|
|
105
|
+
return [self.formatter.dump(item) for item in self._batch.renew(updates)]
|
|
108
106
|
|
|
109
107
|
def replace_one(self, item: RawItem) -> RawItem:
|
|
110
108
|
self.repository.update(self.formatter.load(item))
|
|
@@ -112,9 +110,9 @@ class RestfulRepository(RestfulService, Generic[ItemT]):
|
|
|
112
110
|
return item
|
|
113
111
|
|
|
114
112
|
def replace_many(self, items: RawCollection) -> RawCollection:
|
|
115
|
-
self._batch.
|
|
113
|
+
updated = self._batch.renew([self.formatter.load(item) for item in items])
|
|
116
114
|
|
|
117
|
-
return
|
|
115
|
+
return [self.formatter.dump(item) for item in updated]
|
|
118
116
|
|
|
119
117
|
def delete_one(self, item_id: str) -> None:
|
|
120
118
|
self.repository.delete(item_id)
|
|
@@ -5,8 +5,8 @@ from .core import (
|
|
|
5
5
|
Cursor,
|
|
6
6
|
Database,
|
|
7
7
|
DatabaseCommand,
|
|
8
|
+
NoRepository,
|
|
8
9
|
Repository,
|
|
9
|
-
RepositoryBase,
|
|
10
10
|
RepositoryDecorator,
|
|
11
11
|
)
|
|
12
12
|
from .core.interface import Entity
|
|
@@ -27,8 +27,8 @@ __all__ = [
|
|
|
27
27
|
"Cursor",
|
|
28
28
|
"Database",
|
|
29
29
|
"DatabaseCommand",
|
|
30
|
+
"NoRepository",
|
|
30
31
|
"Repository",
|
|
31
|
-
"RepositoryBase",
|
|
32
32
|
"RepositoryDecorator",
|
|
33
33
|
# In-memory
|
|
34
34
|
"CacheMixin",
|
|
@@ -6,8 +6,9 @@ from .database import (
|
|
|
6
6
|
Database,
|
|
7
7
|
DatabaseCommand,
|
|
8
8
|
)
|
|
9
|
-
from .decorator import BruteForceBatch, RepositoryDecorator
|
|
10
|
-
from .interface import ItemT,
|
|
9
|
+
from .decorator import BruteForceBatch, NoRepository, RepositoryDecorator
|
|
10
|
+
from .interface import Entity, ItemT, KeyFn, Repository
|
|
11
|
+
from .mixin import ContainsMixin
|
|
11
12
|
|
|
12
13
|
__all__ = [
|
|
13
14
|
# Database
|
|
@@ -21,7 +22,11 @@ __all__ = [
|
|
|
21
22
|
"RepositoryDecorator",
|
|
22
23
|
"BruteForceBatch",
|
|
23
24
|
# Interface
|
|
25
|
+
"Entity",
|
|
24
26
|
"ItemT",
|
|
27
|
+
"KeyFn",
|
|
25
28
|
"Repository",
|
|
26
|
-
"
|
|
29
|
+
"NoRepository",
|
|
30
|
+
# Mixin
|
|
31
|
+
"ContainsMixin",
|
|
27
32
|
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from collections.abc import Container, Iterable, Iterator
|
|
2
|
+
from contextlib import suppress
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
|
|
5
|
+
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
6
|
+
|
|
7
|
+
from .interface import ItemT, Repository
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class NoRepository(Repository[ItemT]): # pragma: no cover
|
|
11
|
+
def create(self, item: ItemT) -> ItemT:
|
|
12
|
+
raise NotImplementedError
|
|
13
|
+
|
|
14
|
+
def read(self, item_id: str) -> ItemT:
|
|
15
|
+
raise NotImplementedError
|
|
16
|
+
|
|
17
|
+
def update(self, item: ItemT) -> None:
|
|
18
|
+
raise NotImplementedError
|
|
19
|
+
|
|
20
|
+
def delete(self, item_id: str) -> None:
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
|
|
23
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
24
|
+
raise NotImplementedError
|
|
25
|
+
|
|
26
|
+
def __len__(self) -> int:
|
|
27
|
+
raise NotImplementedError
|
|
28
|
+
|
|
29
|
+
def __contains__(self, item: object) -> bool:
|
|
30
|
+
raise NotImplementedError
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True, kw_only=True)
|
|
34
|
+
class RepositoryDecorator(Repository[ItemT]): # pragma: no cover
|
|
35
|
+
inner: Repository[ItemT] = field(default_factory=NoRepository)
|
|
36
|
+
|
|
37
|
+
def create(self, item: ItemT) -> ItemT:
|
|
38
|
+
return self.inner.create(item)
|
|
39
|
+
|
|
40
|
+
def read(self, item_id: str) -> ItemT:
|
|
41
|
+
return self.inner.read(item_id)
|
|
42
|
+
|
|
43
|
+
def update(self, item: ItemT) -> None:
|
|
44
|
+
self.inner.update(item)
|
|
45
|
+
|
|
46
|
+
def delete(self, item_id: str) -> None:
|
|
47
|
+
self.inner.delete(item_id)
|
|
48
|
+
|
|
49
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
50
|
+
return iter(self.inner)
|
|
51
|
+
|
|
52
|
+
def __len__(self) -> int:
|
|
53
|
+
return len(self.inner)
|
|
54
|
+
|
|
55
|
+
def __contains__(self, item: object) -> bool:
|
|
56
|
+
return item in self.inner
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass(frozen=True, kw_only=True)
|
|
60
|
+
class BruteForceBatch(RepositoryDecorator[ItemT]):
|
|
61
|
+
def load(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
62
|
+
for item in list(source):
|
|
63
|
+
with suppress(ExistsError):
|
|
64
|
+
yield self.inner.create(item)
|
|
65
|
+
|
|
66
|
+
def prune(self, source: Container[ItemT]) -> Iterable[ItemT]:
|
|
67
|
+
for item in list(self.inner):
|
|
68
|
+
if item not in source:
|
|
69
|
+
with suppress(DoesNotExistError):
|
|
70
|
+
self.inner.delete(item.id)
|
|
71
|
+
yield item
|
|
72
|
+
|
|
73
|
+
def renew(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
74
|
+
for item in list(source):
|
|
75
|
+
with suppress(DoesNotExistError):
|
|
76
|
+
self.inner.update(item)
|
|
77
|
+
yield item
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Collection, Container, Iterable
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from typing import Protocol, TypeVar
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _uuid() -> str:
|
|
10
|
+
return str(uuid4())
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True, kw_only=True)
|
|
14
|
+
class Entity:
|
|
15
|
+
id: str = field(default_factory=_uuid)
|
|
16
|
+
idempotency_id: str | None = field(default=None)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
ItemT = TypeVar("ItemT", bound=Entity)
|
|
20
|
+
KeyFn = Callable[[ItemT], str]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class Repository(Collection[ItemT], Protocol[ItemT]): # pragma: no cover
|
|
24
|
+
def create(self, item: ItemT) -> ItemT:
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
def read(self, item_id: str) -> ItemT:
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
def update(self, item: ItemT) -> None:
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
def delete(self, item_id: str) -> None:
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class BatchRepository(Repository[ItemT], Protocol[ItemT]): # pragma: no cover
|
|
38
|
+
def load(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
def prune(self, source: Container[ItemT]) -> Iterable[ItemT]:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
def renew(self, source: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
45
|
+
pass
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
from typing import Generic
|
|
2
|
+
|
|
3
|
+
from apexdevkit.error import DoesNotExistError
|
|
4
|
+
from apexdevkit.repository.core import Entity, ItemT
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class ContainsMixin(Generic[ItemT]):
|
|
8
|
+
def __contains__(self, item: object) -> bool:
|
|
9
|
+
match item:
|
|
10
|
+
case Entity():
|
|
11
|
+
return self.contains_id(item.id)
|
|
12
|
+
case _:
|
|
13
|
+
return False
|
|
14
|
+
|
|
15
|
+
def contains_id(self, value: str) -> bool:
|
|
16
|
+
try:
|
|
17
|
+
self.read(value)
|
|
18
|
+
except DoesNotExistError:
|
|
19
|
+
return False
|
|
20
|
+
|
|
21
|
+
return True
|
|
22
|
+
|
|
23
|
+
def read(self, item_id: str) -> ItemT:
|
|
24
|
+
raise NotImplementedError
|
|
@@ -7,7 +7,8 @@ from typing import Generic
|
|
|
7
7
|
from apexdevkit.error import DoesNotExistError
|
|
8
8
|
from apexdevkit.formatter import Formatter
|
|
9
9
|
|
|
10
|
-
from .
|
|
10
|
+
from . import ContainsMixin
|
|
11
|
+
from .interface import ItemT, Repository
|
|
11
12
|
|
|
12
13
|
|
|
13
14
|
@dataclass(frozen=True)
|
|
@@ -20,7 +21,7 @@ class NoFormatter(Generic[ItemT]):
|
|
|
20
21
|
|
|
21
22
|
|
|
22
23
|
@dataclass(frozen=True)
|
|
23
|
-
class MultipleRepository(
|
|
24
|
+
class MultipleRepository(ContainsMixin[ItemT], Repository[ItemT]):
|
|
24
25
|
repositories: list[_InnerRepository[ItemT]]
|
|
25
26
|
|
|
26
27
|
def create(self, item: ItemT) -> ItemT:
|
|
@@ -6,14 +6,13 @@ from dataclasses import dataclass, field
|
|
|
6
6
|
|
|
7
7
|
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
8
8
|
from apexdevkit.key_fn import AttributeKey
|
|
9
|
-
from apexdevkit.repository.core import ItemT,
|
|
10
|
-
from apexdevkit.repository.core.interface import KeyFn
|
|
9
|
+
from apexdevkit.repository.core import ContainsMixin, ItemT, KeyFn, Repository
|
|
11
10
|
|
|
12
11
|
from .store import InMemoryByteStore, KeyValueStore
|
|
13
12
|
|
|
14
13
|
|
|
15
14
|
@dataclass(frozen=True)
|
|
16
|
-
class InMemoryRepository(
|
|
15
|
+
class InMemoryRepository(ContainsMixin[ItemT], Repository[ItemT]):
|
|
17
16
|
store: KeyValueStore[ItemT] = field(default_factory=InMemoryByteStore)
|
|
18
17
|
keys: list[KeyFn[ItemT]] = field(default_factory=lambda: [AttributeKey("id")])
|
|
19
18
|
|
|
@@ -8,12 +8,19 @@ from pymssql.exceptions import DatabaseError, OperationalError
|
|
|
8
8
|
|
|
9
9
|
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
10
10
|
from apexdevkit.formatter import Formatter
|
|
11
|
-
from apexdevkit.repository.core import
|
|
12
|
-
|
|
11
|
+
from apexdevkit.repository.core import (
|
|
12
|
+
ContainsMixin,
|
|
13
|
+
Database,
|
|
14
|
+
DatabaseCommand,
|
|
15
|
+
ItemT,
|
|
16
|
+
Repository,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from .field import NotNone, SqlFieldManager, _SqlField
|
|
13
20
|
|
|
14
21
|
|
|
15
22
|
@dataclass
|
|
16
|
-
class MsSqlRepository(
|
|
23
|
+
class MsSqlRepository(ContainsMixin[ItemT], Repository[ItemT]):
|
|
17
24
|
db: Database
|
|
18
25
|
table: SqlTable[ItemT]
|
|
19
26
|
|
|
@@ -7,13 +7,19 @@ from typing import Any, Generic
|
|
|
7
7
|
|
|
8
8
|
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
9
9
|
from apexdevkit.formatter import Formatter
|
|
10
|
-
from apexdevkit.repository import
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
from apexdevkit.repository.core import (
|
|
11
|
+
ContainsMixin,
|
|
12
|
+
Database,
|
|
13
|
+
DatabaseCommand,
|
|
14
|
+
ItemT,
|
|
15
|
+
Repository,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from .field import NotNone, SqlFieldManager, _SqlField
|
|
13
19
|
|
|
14
20
|
|
|
15
21
|
@dataclass(frozen=True)
|
|
16
|
-
class SqliteRepository(
|
|
22
|
+
class SqliteRepository(ContainsMixin[ItemT], Repository[ItemT]):
|
|
17
23
|
db: Database
|
|
18
24
|
table: SqlTable[ItemT]
|
|
19
25
|
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from collections.abc import Iterable, Iterator
|
|
2
|
-
from dataclasses import dataclass
|
|
3
|
-
from typing import Generic
|
|
4
|
-
|
|
5
|
-
from .interface import ItemT, Repository
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@dataclass
|
|
9
|
-
class RepositoryDecorator(Generic[ItemT]): # pragma: no cover
|
|
10
|
-
inner: Repository[ItemT]
|
|
11
|
-
|
|
12
|
-
def create(self, item: ItemT) -> ItemT:
|
|
13
|
-
return self.inner.create(item)
|
|
14
|
-
|
|
15
|
-
def read(self, item_id: str) -> ItemT:
|
|
16
|
-
return self.inner.read(item_id)
|
|
17
|
-
|
|
18
|
-
def update(self, item: ItemT) -> None:
|
|
19
|
-
self.inner.update(item)
|
|
20
|
-
|
|
21
|
-
def delete(self, item_id: str) -> None:
|
|
22
|
-
self.inner.delete(item_id)
|
|
23
|
-
|
|
24
|
-
def __iter__(self) -> Iterator[ItemT]:
|
|
25
|
-
return self.inner.__iter__()
|
|
26
|
-
|
|
27
|
-
def __len__(self) -> int:
|
|
28
|
-
return self.inner.__len__()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class BruteForceBatch(RepositoryDecorator[ItemT]):
|
|
32
|
-
def create_many(self, items: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
33
|
-
return [self.inner.create(item) for item in items]
|
|
34
|
-
|
|
35
|
-
def update_many(self, items: Iterable[ItemT]) -> None:
|
|
36
|
-
for item in items:
|
|
37
|
-
self.inner.update(item)
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from collections.abc import Callable, Iterable, Iterator
|
|
4
|
-
from dataclasses import dataclass, field
|
|
5
|
-
from typing import Generic, Protocol, TypeVar
|
|
6
|
-
from uuid import uuid4
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def _uuid() -> str:
|
|
10
|
-
return str(uuid4())
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@dataclass(frozen=True, kw_only=True)
|
|
14
|
-
class Entity:
|
|
15
|
-
id: str = field(default_factory=_uuid)
|
|
16
|
-
idempotency_id: str | None = field(default=None)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ItemT = TypeVar("ItemT", bound=Entity)
|
|
20
|
-
KeyFn = Callable[[ItemT], str]
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class Repository(Protocol[ItemT]): # pragma: no cover
|
|
24
|
-
def create(self, item: ItemT) -> ItemT:
|
|
25
|
-
pass
|
|
26
|
-
|
|
27
|
-
def read(self, item_id: str) -> ItemT:
|
|
28
|
-
pass
|
|
29
|
-
|
|
30
|
-
def update(self, item: ItemT) -> None:
|
|
31
|
-
pass
|
|
32
|
-
|
|
33
|
-
def delete(self, item_id: str) -> None:
|
|
34
|
-
pass
|
|
35
|
-
|
|
36
|
-
def __iter__(self) -> Iterator[ItemT]:
|
|
37
|
-
pass
|
|
38
|
-
|
|
39
|
-
def __len__(self) -> int:
|
|
40
|
-
pass
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class BatchRepository(Repository[ItemT], Protocol[ItemT]): # pragma: no cover
|
|
44
|
-
def create_many(self, items: Iterable[ItemT]) -> Iterable[ItemT]:
|
|
45
|
-
pass
|
|
46
|
-
|
|
47
|
-
def update_many(self, items: Iterable[ItemT]) -> None:
|
|
48
|
-
pass
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class RepositoryBase(Generic[ItemT]): # pragma: no cover
|
|
52
|
-
def create(self, item: ItemT) -> ItemT:
|
|
53
|
-
raise NotImplementedError
|
|
54
|
-
|
|
55
|
-
def read(self, item_id: str) -> ItemT:
|
|
56
|
-
raise NotImplementedError
|
|
57
|
-
|
|
58
|
-
def update(self, item: ItemT) -> None:
|
|
59
|
-
raise NotImplementedError
|
|
60
|
-
|
|
61
|
-
def delete(self, item_id: str) -> None:
|
|
62
|
-
raise NotImplementedError
|
|
63
|
-
|
|
64
|
-
def __iter__(self) -> Iterator[ItemT]:
|
|
65
|
-
raise NotImplementedError
|
|
66
|
-
|
|
67
|
-
def __len__(self) -> int:
|
|
68
|
-
raise NotImplementedError
|
|
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
|