apexdevkit 1.13.7__tar.gz → 1.13.9__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.13.7 → apexdevkit-1.13.9}/PKG-INFO +1 -1
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/router.py +0 -1
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/formatter.py +9 -0
- apexdevkit-1.13.9/apexdevkit/key_fn.py +12 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/__init__.py +7 -1
- apexdevkit-1.13.9/apexdevkit/repository/in_memory.py +197 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/pyproject.toml +1 -1
- apexdevkit-1.13.7/apexdevkit/repository/alternative/__init__.py +0 -7
- apexdevkit-1.13.7/apexdevkit/repository/alternative/base.py +0 -49
- apexdevkit-1.13.7/apexdevkit/repository/alternative/formatter_repository.py +0 -50
- apexdevkit-1.13.7/apexdevkit/repository/in_memory.py +0 -90
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/LICENSE +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/README.md +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/environment.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/error.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/resource.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/schema.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/fluent.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/base.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/decorator.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/mongo.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/repository/sqlite.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/testing/fake.py +0 -0
- {apexdevkit-1.13.7 → apexdevkit-1.13.9}/apexdevkit/testing/rest.py +0 -0
|
@@ -14,6 +14,15 @@ class Formatter(Protocol[_SourceT, _TargetT]): # pragma: no cover
|
|
|
14
14
|
pass
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
@dataclass
|
|
18
|
+
class NoFormatter(Formatter[Any, Any]):
|
|
19
|
+
def load(self, source: Any) -> Any:
|
|
20
|
+
return source
|
|
21
|
+
|
|
22
|
+
def dump(self, target: Any) -> Any:
|
|
23
|
+
return target
|
|
24
|
+
|
|
25
|
+
|
|
17
26
|
@dataclass
|
|
18
27
|
class ListFormatter(Generic[_SourceT, _TargetT]):
|
|
19
28
|
inner: Formatter[_SourceT, _TargetT]
|
|
@@ -6,7 +6,11 @@ from apexdevkit.repository.database import (
|
|
|
6
6
|
Database,
|
|
7
7
|
DatabaseCommand,
|
|
8
8
|
)
|
|
9
|
-
from apexdevkit.repository.in_memory import
|
|
9
|
+
from apexdevkit.repository.in_memory import (
|
|
10
|
+
InMemoryKeyValueStore,
|
|
11
|
+
InMemoryRepository,
|
|
12
|
+
KeyValueStore,
|
|
13
|
+
)
|
|
10
14
|
from apexdevkit.repository.interface import Repository
|
|
11
15
|
|
|
12
16
|
__all__ = [
|
|
@@ -16,6 +20,8 @@ __all__ = [
|
|
|
16
20
|
"Database",
|
|
17
21
|
"DatabaseCommand",
|
|
18
22
|
"InMemoryRepository",
|
|
23
|
+
"InMemoryKeyValueStore",
|
|
24
|
+
"KeyValueStore",
|
|
19
25
|
"Repository",
|
|
20
26
|
"RepositoryBase",
|
|
21
27
|
]
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any, Callable, Generic, Iterable, Iterator, Protocol, Self
|
|
5
|
+
|
|
6
|
+
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
7
|
+
from apexdevkit.formatter import Formatter, NoFormatter
|
|
8
|
+
from apexdevkit.key_fn import AttributeKey
|
|
9
|
+
from apexdevkit.repository import RepositoryBase
|
|
10
|
+
from apexdevkit.repository.interface import ItemT, Repository
|
|
11
|
+
|
|
12
|
+
KeyFunction = Callable[[Any], str]
|
|
13
|
+
_Raw = dict[str, Any]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class InMemoryRepository(Generic[ItemT]):
|
|
18
|
+
store: KeyValueStore[ItemT] = field(default_factory=lambda: InMemoryKeyValueStore())
|
|
19
|
+
keys: list[KeyFunction] = field(default_factory=list)
|
|
20
|
+
seeds: list[ItemT] = field(default_factory=list)
|
|
21
|
+
|
|
22
|
+
def with_formatter(self, value: Formatter[_Raw, ItemT]) -> Self:
|
|
23
|
+
return self.with_store(InMemoryKeyValueStore(value))
|
|
24
|
+
|
|
25
|
+
def with_store(self, value: KeyValueStore[ItemT]) -> Self:
|
|
26
|
+
self.store = value
|
|
27
|
+
|
|
28
|
+
return self
|
|
29
|
+
|
|
30
|
+
def and_key(self, function: KeyFunction) -> Self:
|
|
31
|
+
return self.with_key(function)
|
|
32
|
+
|
|
33
|
+
def with_key(self, function: KeyFunction) -> Self:
|
|
34
|
+
self.keys.append(function)
|
|
35
|
+
|
|
36
|
+
return self
|
|
37
|
+
|
|
38
|
+
def and_seeded(self, *items: ItemT) -> Self:
|
|
39
|
+
return self.with_seeded(*items)
|
|
40
|
+
|
|
41
|
+
def with_seeded(self, *items: ItemT) -> Self:
|
|
42
|
+
self.seeds.extend(items)
|
|
43
|
+
|
|
44
|
+
return self
|
|
45
|
+
|
|
46
|
+
def build(self) -> Repository[ItemT]:
|
|
47
|
+
return self._seed(self._create())
|
|
48
|
+
|
|
49
|
+
def _seed(self, repository: Repository[ItemT]) -> Repository[ItemT]:
|
|
50
|
+
for seed in self.seeds:
|
|
51
|
+
repository.create(seed)
|
|
52
|
+
|
|
53
|
+
return repository
|
|
54
|
+
|
|
55
|
+
def _create(self) -> Repository[ItemT]:
|
|
56
|
+
match len(self.keys):
|
|
57
|
+
case 0:
|
|
58
|
+
return _SingleKeyRepository(self.store, pk=AttributeKey("id"))
|
|
59
|
+
case 1:
|
|
60
|
+
return _SingleKeyRepository(self.store, pk=self.keys[0])
|
|
61
|
+
case _:
|
|
62
|
+
return _ManyKeyRepository(self.store, keys=self.keys)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class KeyValueStore(Protocol[ItemT]): # pragma: no cover
|
|
66
|
+
def count(self) -> int:
|
|
67
|
+
pass
|
|
68
|
+
|
|
69
|
+
def set(self, key: str, value: ItemT) -> None:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
def get(self, key: str) -> ItemT:
|
|
73
|
+
pass
|
|
74
|
+
|
|
75
|
+
def drop(self, key: str) -> None:
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
def values(self) -> Iterable[ItemT]:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class InMemoryKeyValueStore(Generic[ItemT]):
|
|
84
|
+
formatter: Formatter[_Raw, ItemT] = field(default_factory=NoFormatter)
|
|
85
|
+
items: dict[str, _Raw] = field(default_factory=dict)
|
|
86
|
+
|
|
87
|
+
def count(self) -> int:
|
|
88
|
+
return len(self.items)
|
|
89
|
+
|
|
90
|
+
def set(self, key: str, value: ItemT) -> None:
|
|
91
|
+
self.items[key] = self.formatter.dump(value)
|
|
92
|
+
|
|
93
|
+
def get(self, key: str) -> ItemT:
|
|
94
|
+
return self.formatter.load(self.items[key])
|
|
95
|
+
|
|
96
|
+
def drop(self, key: str) -> None:
|
|
97
|
+
del self.items[key]
|
|
98
|
+
|
|
99
|
+
def values(self) -> Iterable[ItemT]:
|
|
100
|
+
for raw in self.items.values():
|
|
101
|
+
yield self.formatter.load(raw)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@dataclass
|
|
105
|
+
class _SingleKeyRepository(RepositoryBase[ItemT]):
|
|
106
|
+
store: KeyValueStore[ItemT]
|
|
107
|
+
pk: KeyFunction
|
|
108
|
+
|
|
109
|
+
def bind(self, **kwargs: Any) -> Self: # pragma: no cover
|
|
110
|
+
return self
|
|
111
|
+
|
|
112
|
+
def create(self, item: ItemT) -> ItemT:
|
|
113
|
+
self._ensure_does_not_exist(item)
|
|
114
|
+
self.store.set(self.pk(item), item)
|
|
115
|
+
|
|
116
|
+
return item
|
|
117
|
+
|
|
118
|
+
def _ensure_does_not_exist(self, new: ItemT) -> None:
|
|
119
|
+
try:
|
|
120
|
+
existing = self.store.get(self.pk(new))
|
|
121
|
+
except KeyError:
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
ExistsError(existing).with_duplicate(self.pk).fire()
|
|
125
|
+
|
|
126
|
+
def update(self, item: ItemT) -> None:
|
|
127
|
+
self.delete(self.pk(item))
|
|
128
|
+
self.create(item)
|
|
129
|
+
|
|
130
|
+
def delete(self, item_id: str) -> None:
|
|
131
|
+
try:
|
|
132
|
+
self.store.drop(item_id)
|
|
133
|
+
except KeyError:
|
|
134
|
+
raise DoesNotExistError(item_id)
|
|
135
|
+
|
|
136
|
+
def read(self, item_id: str) -> ItemT:
|
|
137
|
+
try:
|
|
138
|
+
return self.store.get(item_id)
|
|
139
|
+
except KeyError:
|
|
140
|
+
raise DoesNotExistError(item_id)
|
|
141
|
+
|
|
142
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
143
|
+
return iter(self.store.values())
|
|
144
|
+
|
|
145
|
+
def __len__(self) -> int:
|
|
146
|
+
return self.store.count()
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
@dataclass
|
|
150
|
+
class _ManyKeyRepository(RepositoryBase[ItemT]):
|
|
151
|
+
store: KeyValueStore[ItemT]
|
|
152
|
+
|
|
153
|
+
keys: list[KeyFunction] = field(default_factory=list)
|
|
154
|
+
|
|
155
|
+
def bind(self, **kwargs: Any) -> Self: # pragma: no cover
|
|
156
|
+
return self
|
|
157
|
+
|
|
158
|
+
def create(self, item: ItemT) -> ItemT:
|
|
159
|
+
self._ensure_does_not_exist(item)
|
|
160
|
+
self.store.set(self._pk(item), item)
|
|
161
|
+
|
|
162
|
+
return item
|
|
163
|
+
|
|
164
|
+
def _ensure_does_not_exist(self, new: ItemT) -> None:
|
|
165
|
+
for existing in self:
|
|
166
|
+
error = ExistsError(existing)
|
|
167
|
+
|
|
168
|
+
for key in self.keys:
|
|
169
|
+
if key(new) == key(existing):
|
|
170
|
+
error.with_duplicate(key)
|
|
171
|
+
|
|
172
|
+
error.fire()
|
|
173
|
+
|
|
174
|
+
def _pk(self, item: ItemT) -> Any:
|
|
175
|
+
return self.keys[0](item)
|
|
176
|
+
|
|
177
|
+
def update(self, item: ItemT) -> None:
|
|
178
|
+
self.delete(self._pk(item))
|
|
179
|
+
self.create(item)
|
|
180
|
+
|
|
181
|
+
def delete(self, item_id: str) -> None:
|
|
182
|
+
item = self.read(item_id)
|
|
183
|
+
self.store.drop(self._pk(item))
|
|
184
|
+
|
|
185
|
+
def read(self, item_id: str) -> ItemT:
|
|
186
|
+
for key in self.keys:
|
|
187
|
+
for item in self:
|
|
188
|
+
if key(item) == str(item_id):
|
|
189
|
+
return item
|
|
190
|
+
|
|
191
|
+
raise DoesNotExistError(item_id)
|
|
192
|
+
|
|
193
|
+
def __iter__(self) -> Iterator[ItemT]:
|
|
194
|
+
return iter(self.store.values())
|
|
195
|
+
|
|
196
|
+
def __len__(self) -> int:
|
|
197
|
+
return self.store.count()
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Any, Iterator
|
|
3
|
-
|
|
4
|
-
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
5
|
-
|
|
6
|
-
_Raw = dict[str, Any]
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
@dataclass
|
|
10
|
-
class MemoryPersistence: # pragma: no cover
|
|
11
|
-
items: dict[str, _Raw] = field(init=False, default_factory=dict)
|
|
12
|
-
|
|
13
|
-
def create(self, item: _Raw) -> _Raw:
|
|
14
|
-
self._ensure_does_not_exist(item)
|
|
15
|
-
self.items[item["id"]] = item
|
|
16
|
-
|
|
17
|
-
return item
|
|
18
|
-
|
|
19
|
-
def _ensure_does_not_exist(self, new: _Raw) -> None:
|
|
20
|
-
if new["id"] in self.items.keys():
|
|
21
|
-
error = ExistsError(self.items[new["id"]])
|
|
22
|
-
error.with_duplicate(lambda item: f"id<{item['id']}>")
|
|
23
|
-
error.fire()
|
|
24
|
-
|
|
25
|
-
def read(self, item_id: str) -> _Raw:
|
|
26
|
-
self._ensure_exists(item_id)
|
|
27
|
-
|
|
28
|
-
return self.items[item_id]
|
|
29
|
-
|
|
30
|
-
def _ensure_exists(self, item_id: str) -> None:
|
|
31
|
-
if item_id not in self.items.keys():
|
|
32
|
-
raise DoesNotExistError(item_id)
|
|
33
|
-
|
|
34
|
-
def update(self, item: _Raw) -> None:
|
|
35
|
-
self._ensure_exists(item["id"])
|
|
36
|
-
|
|
37
|
-
self.delete(item["id"])
|
|
38
|
-
self.create(item)
|
|
39
|
-
|
|
40
|
-
def delete(self, item_id: str) -> None:
|
|
41
|
-
self._ensure_exists(item_id)
|
|
42
|
-
|
|
43
|
-
self.items.pop(item_id)
|
|
44
|
-
|
|
45
|
-
def __iter__(self) -> Iterator[_Raw]:
|
|
46
|
-
yield from self.items.values()
|
|
47
|
-
|
|
48
|
-
def __len__(self) -> int:
|
|
49
|
-
return len(self.items)
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass
|
|
2
|
-
from typing import Any, Generic, Iterator, Self
|
|
3
|
-
|
|
4
|
-
from apexdevkit.formatter import Formatter
|
|
5
|
-
from apexdevkit.repository.alternative import MemoryPersistence
|
|
6
|
-
from apexdevkit.repository.interface import ItemT
|
|
7
|
-
|
|
8
|
-
_Raw = dict[str, Any]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass
|
|
12
|
-
class FormatterRepository(Generic[ItemT]):
|
|
13
|
-
base: MemoryPersistence
|
|
14
|
-
formatter: Formatter[_Raw, ItemT]
|
|
15
|
-
|
|
16
|
-
def create(self, item: ItemT) -> ItemT:
|
|
17
|
-
return self.formatter.load(self.base.create(self.formatter.dump(item)))
|
|
18
|
-
|
|
19
|
-
def create_many(self, items: list[ItemT]) -> list[ItemT]:
|
|
20
|
-
return [
|
|
21
|
-
self.formatter.load(
|
|
22
|
-
self.base.create(
|
|
23
|
-
self.formatter.dump(item),
|
|
24
|
-
),
|
|
25
|
-
)
|
|
26
|
-
for item in items
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
def read(self, item_id: str) -> ItemT:
|
|
30
|
-
return self.formatter.load(self.base.read(item_id))
|
|
31
|
-
|
|
32
|
-
def update(self, item: ItemT) -> None:
|
|
33
|
-
self.base.update(self.formatter.dump(item))
|
|
34
|
-
|
|
35
|
-
def update_many(self, items: list[ItemT]) -> None:
|
|
36
|
-
for item in items:
|
|
37
|
-
self.base.update(self.formatter.dump(item))
|
|
38
|
-
|
|
39
|
-
def delete(self, item_id: str) -> None:
|
|
40
|
-
self.base.delete(item_id)
|
|
41
|
-
|
|
42
|
-
def bind(self, **kwargs: Any) -> Self:
|
|
43
|
-
return self
|
|
44
|
-
|
|
45
|
-
def __iter__(self) -> Iterator[ItemT]:
|
|
46
|
-
for raw in self.base:
|
|
47
|
-
yield self.formatter.load(raw)
|
|
48
|
-
|
|
49
|
-
def __len__(self) -> int:
|
|
50
|
-
return len(self.base)
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Any, Callable, Iterable, Iterator, Self
|
|
3
|
-
|
|
4
|
-
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
5
|
-
from apexdevkit.formatter import Formatter
|
|
6
|
-
from apexdevkit.repository import RepositoryBase
|
|
7
|
-
from apexdevkit.repository.interface import ItemT
|
|
8
|
-
|
|
9
|
-
KeyFunction = Callable[[Any], str]
|
|
10
|
-
_Raw = dict[str, Any]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@dataclass
|
|
14
|
-
class AttributeKey:
|
|
15
|
-
name: str
|
|
16
|
-
|
|
17
|
-
def __call__(self, item: Any) -> str:
|
|
18
|
-
return str(getattr(item, self.name))
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
@dataclass
|
|
22
|
-
class InMemoryRepository(RepositoryBase[ItemT]):
|
|
23
|
-
formatter: Formatter[_Raw, ItemT]
|
|
24
|
-
items: dict[str, _Raw] = field(default_factory=dict)
|
|
25
|
-
|
|
26
|
-
_keys: list[KeyFunction] = field(init=False, default_factory=list)
|
|
27
|
-
|
|
28
|
-
def bind(self, **kwargs: Any) -> Self:
|
|
29
|
-
return self
|
|
30
|
-
|
|
31
|
-
def with_key(self, function: KeyFunction) -> Self:
|
|
32
|
-
self._keys.append(function)
|
|
33
|
-
|
|
34
|
-
return self
|
|
35
|
-
|
|
36
|
-
def with_seeded(self, *items: ItemT) -> Self:
|
|
37
|
-
for item in items:
|
|
38
|
-
self.create(item)
|
|
39
|
-
|
|
40
|
-
return self
|
|
41
|
-
|
|
42
|
-
def create(self, item: ItemT) -> ItemT:
|
|
43
|
-
self._ensure_does_not_exist(item)
|
|
44
|
-
self.items[self._pk(item)] = self.formatter.dump(item)
|
|
45
|
-
|
|
46
|
-
return item
|
|
47
|
-
|
|
48
|
-
def _ensure_does_not_exist(self, new: ItemT) -> None:
|
|
49
|
-
for existing in self:
|
|
50
|
-
error = ExistsError(existing)
|
|
51
|
-
|
|
52
|
-
for key in self._keys:
|
|
53
|
-
if key(new) == key(existing):
|
|
54
|
-
error.with_duplicate(key)
|
|
55
|
-
|
|
56
|
-
error.fire()
|
|
57
|
-
|
|
58
|
-
def _pk(self, item: ItemT) -> Any:
|
|
59
|
-
return self._keys[0](item)
|
|
60
|
-
|
|
61
|
-
def update(self, item: ItemT) -> None:
|
|
62
|
-
self.delete(self._pk(item))
|
|
63
|
-
self.create(item)
|
|
64
|
-
|
|
65
|
-
def delete(self, item_id: str) -> None:
|
|
66
|
-
item = self.read(item_id)
|
|
67
|
-
del self.items[self._pk(item)]
|
|
68
|
-
|
|
69
|
-
def read(self, item_id: str) -> ItemT:
|
|
70
|
-
for key in self._keys:
|
|
71
|
-
for item in self:
|
|
72
|
-
if key(item) == str(item_id):
|
|
73
|
-
return item
|
|
74
|
-
|
|
75
|
-
raise DoesNotExistError(item_id)
|
|
76
|
-
|
|
77
|
-
def __iter__(self) -> Iterator[ItemT]:
|
|
78
|
-
yield from [self.formatter.load(raw) for raw in self.items.values()]
|
|
79
|
-
|
|
80
|
-
def __len__(self) -> int:
|
|
81
|
-
return len(self.items)
|
|
82
|
-
|
|
83
|
-
def search(self, **kwargs: Any) -> Iterable[ItemT]:
|
|
84
|
-
items = []
|
|
85
|
-
|
|
86
|
-
for item in self.items.values():
|
|
87
|
-
if kwargs.items() <= item.items():
|
|
88
|
-
items.append(self.formatter.load(item))
|
|
89
|
-
|
|
90
|
-
return items
|
|
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
|