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.
Files changed (61) hide show
  1. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/PKG-INFO +1 -1
  2. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/service.py +5 -7
  3. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/__init__.py +2 -2
  4. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/__init__.py +8 -3
  5. apexdevkit-1.29.4/apexdevkit/repository/core/decorator.py +77 -0
  6. apexdevkit-1.29.4/apexdevkit/repository/core/interface.py +45 -0
  7. apexdevkit-1.29.4/apexdevkit/repository/core/mixin.py +24 -0
  8. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/multi.py +3 -2
  9. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/repository.py +2 -3
  10. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/mssql.py +10 -3
  11. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/sqlite.py +10 -4
  12. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/pyproject.toml +1 -1
  13. apexdevkit-1.29.2/apexdevkit/repository/core/decorator.py +0 -37
  14. apexdevkit-1.29.2/apexdevkit/repository/core/interface.py +0 -68
  15. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/LICENSE +0 -0
  16. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/README.md +0 -0
  17. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/__init__.py +0 -0
  18. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/annotation/__init__.py +0 -0
  19. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/annotation/deprecate.py +0 -0
  20. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/date.py +0 -0
  21. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/environment.py +0 -0
  22. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/error.py +0 -0
  23. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/__init__.py +0 -0
  24. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/builder.py +0 -0
  25. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/dependable.py +0 -0
  26. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/docs.py +0 -0
  27. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/name.py +0 -0
  28. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/resource.py +0 -0
  29. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/response.py +0 -0
  30. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/router.py +0 -0
  31. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fastapi/schema.py +0 -0
  32. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/fluent.py +0 -0
  33. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/formatter.py +0 -0
  34. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/__init__.py +0 -0
  35. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/fake.py +0 -0
  36. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/fluent.py +0 -0
  37. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/__init__.py +0 -0
  38. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/client.py +0 -0
  39. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/httpx/hooks.py +0 -0
  40. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/json.py +0 -0
  41. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/http/url.py +0 -0
  42. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/id.py +0 -0
  43. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/key_fn.py +0 -0
  44. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/py.typed +0 -0
  45. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/__init__.py +0 -0
  46. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/generator.py +0 -0
  47. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/query/query.py +0 -0
  48. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/core/database.py +0 -0
  49. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/__init__.py +0 -0
  50. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/mixin.py +0 -0
  51. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/in_memory/store.py +0 -0
  52. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/__init__.py +0 -0
  53. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/connector.py +0 -0
  54. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/repository/sql/field.py +0 -0
  55. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/server.py +0 -0
  56. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/synchronization.py +0 -0
  57. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/__init__.py +0 -0
  58. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/database.py +0 -0
  59. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/fake.py +0 -0
  60. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/testing/rest.py +0 -0
  61. {apexdevkit-1.29.2 → apexdevkit-1.29.4}/apexdevkit/value.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexdevkit
3
- Version: 1.29.2
3
+ Version: 1.29.4
4
4
  Summary: Apex Development Tools for python.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
@@ -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.create_many(
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.update_many(updates)
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.update_many([self.formatter.load(item) for item in items])
113
+ updated = self._batch.renew([self.formatter.load(item) for item in items])
116
114
 
117
- return items
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, Repository, RepositoryBase
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
- "RepositoryBase",
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 .interface import ItemT, Repository, RepositoryBase
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(RepositoryBase[ItemT]):
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, RepositoryBase
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(RepositoryBase[ItemT]):
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 Database, DatabaseCommand, ItemT, RepositoryBase
12
- from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
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(RepositoryBase[ItemT]):
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 Database, DatabaseCommand, RepositoryBase
11
- from apexdevkit.repository.core.interface import ItemT
12
- from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
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(RepositoryBase[ItemT]):
22
+ class SqliteRepository(ContainsMixin[ItemT], Repository[ItemT]):
17
23
  db: Database
18
24
  table: SqlTable[ItemT]
19
25
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "apexdevkit"
3
- version = "1.29.2"
3
+ version = "1.29.4"
4
4
  description = "Apex Development Tools for python."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -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