apexdevkit 1.28.2__tar.gz → 1.29.1__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 (62) hide show
  1. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/PKG-INFO +1 -1
  2. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/service.py +1 -2
  3. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/repository/__init__.py +15 -7
  4. apexdevkit-1.29.1/apexdevkit/repository/core/__init__.py +26 -0
  5. {apexdevkit-1.28.2/apexdevkit/repository → apexdevkit-1.29.1/apexdevkit/repository/core}/database.py +12 -0
  6. {apexdevkit-1.28.2/apexdevkit/repository → apexdevkit-1.29.1/apexdevkit/repository/core}/decorator.py +2 -5
  7. apexdevkit-1.29.1/apexdevkit/repository/core/interface.py +55 -0
  8. apexdevkit-1.28.2/apexdevkit/repository/repository.py → apexdevkit-1.29.1/apexdevkit/repository/core/multi.py +2 -3
  9. apexdevkit-1.29.1/apexdevkit/repository/in_memory/__init__.py +8 -0
  10. apexdevkit-1.29.1/apexdevkit/repository/in_memory/builder.py +62 -0
  11. apexdevkit-1.29.1/apexdevkit/repository/in_memory/multi_key.py +53 -0
  12. apexdevkit-1.29.1/apexdevkit/repository/in_memory/single_key.py +51 -0
  13. apexdevkit-1.29.1/apexdevkit/repository/in_memory/store.py +62 -0
  14. apexdevkit-1.29.1/apexdevkit/repository/sql/__init__.py +11 -0
  15. {apexdevkit-1.28.2/apexdevkit/repository → apexdevkit-1.29.1/apexdevkit/repository/sql}/connector.py +1 -12
  16. {apexdevkit-1.28.2/apexdevkit/repository → apexdevkit-1.29.1/apexdevkit/repository/sql}/mssql.py +1 -1
  17. {apexdevkit-1.28.2/apexdevkit/repository → apexdevkit-1.29.1/apexdevkit/repository/sql}/sqlite.py +2 -8
  18. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/pyproject.toml +2 -2
  19. apexdevkit-1.28.2/apexdevkit/repository/base.py +0 -27
  20. apexdevkit-1.28.2/apexdevkit/repository/in_memory.py +0 -209
  21. apexdevkit-1.28.2/apexdevkit/repository/interface.py +0 -37
  22. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/LICENSE +0 -0
  23. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/README.md +0 -0
  24. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/__init__.py +0 -0
  25. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/annotation/__init__.py +0 -0
  26. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/annotation/deprecate.py +0 -0
  27. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/date.py +0 -0
  28. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/environment.py +0 -0
  29. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/error.py +0 -0
  30. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/__init__.py +0 -0
  31. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/builder.py +0 -0
  32. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/dependable.py +0 -0
  33. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/docs.py +0 -0
  34. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/name.py +0 -0
  35. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/resource.py +0 -0
  36. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/response.py +0 -0
  37. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/router.py +0 -0
  38. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fastapi/schema.py +0 -0
  39. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/fluent.py +0 -0
  40. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/formatter.py +0 -0
  41. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/__init__.py +0 -0
  42. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/fake.py +0 -0
  43. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/fluent.py +0 -0
  44. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/httpx/__init__.py +0 -0
  45. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/httpx/client.py +0 -0
  46. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/httpx/hooks.py +0 -0
  47. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/json.py +0 -0
  48. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/http/url.py +0 -0
  49. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/id.py +0 -0
  50. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/key_fn.py +0 -0
  51. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/py.typed +0 -0
  52. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/query/__init__.py +0 -0
  53. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/query/generator.py +0 -0
  54. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/query/query.py +0 -0
  55. /apexdevkit-1.28.2/apexdevkit/repository/sql.py → /apexdevkit-1.29.1/apexdevkit/repository/sql/field.py +0 -0
  56. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/server.py +0 -0
  57. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/synchronization.py +0 -0
  58. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/testing/__init__.py +0 -0
  59. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/testing/database.py +0 -0
  60. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/testing/fake.py +0 -0
  61. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/testing/rest.py +0 -0
  62. {apexdevkit-1.28.2 → apexdevkit-1.29.1}/apexdevkit/value.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexdevkit
3
- Version: 1.28.2
3
+ Version: 1.29.1
4
4
  Summary: Apex Development Tools for python.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
@@ -6,8 +6,7 @@ from functools import cached_property
6
6
  from typing import Any, Generic, TypeVar
7
7
 
8
8
  from apexdevkit.formatter import Formatter
9
- from apexdevkit.repository.decorator import BruteForceBatch
10
- from apexdevkit.repository.interface import Repository
9
+ from apexdevkit.repository import BruteForceBatch, Repository
11
10
 
12
11
  RawItem = Mapping[str, Any]
13
12
  RawCollection = Iterable[RawItem]
@@ -1,29 +1,37 @@
1
- from apexdevkit.repository.base import RepositoryBase
2
- from apexdevkit.repository.database import (
1
+ from apexdevkit.repository.core import (
2
+ BruteForceBatch,
3
3
  Connection,
4
4
  Connector,
5
5
  Cursor,
6
6
  Database,
7
7
  DatabaseCommand,
8
+ Repository,
9
+ RepositoryBase,
10
+ RepositoryDecorator,
8
11
  )
9
12
  from apexdevkit.repository.in_memory import (
10
13
  InMemoryByteStore,
11
14
  InMemoryRepository,
12
15
  KeyValueStore,
13
16
  )
14
- from apexdevkit.repository.interface import Repository
15
- from apexdevkit.repository.mssql import MsSqlRepository
17
+ from apexdevkit.repository.sql import MsSqlRepository, SqliteRepository
16
18
 
17
19
  __all__ = [
20
+ # Core
21
+ "BruteForceBatch",
18
22
  "Connection",
19
23
  "Connector",
20
24
  "Cursor",
21
25
  "Database",
22
26
  "DatabaseCommand",
23
- "InMemoryRepository",
24
- "InMemoryByteStore",
25
- "KeyValueStore",
26
27
  "Repository",
27
28
  "RepositoryBase",
29
+ "RepositoryDecorator",
30
+ # In-memory
31
+ "InMemoryByteStore",
32
+ "InMemoryRepository",
33
+ "KeyValueStore",
34
+ # SQL
28
35
  "MsSqlRepository",
36
+ "SqliteRepository",
29
37
  ]
@@ -0,0 +1,26 @@
1
+ from .database import (
2
+ Connection,
3
+ ConnectionContextManager,
4
+ Connector,
5
+ Cursor,
6
+ Database,
7
+ DatabaseCommand,
8
+ )
9
+ from .decorator import BruteForceBatch, RepositoryDecorator
10
+ from .interface import Repository, RepositoryBase
11
+
12
+ __all__ = [
13
+ # Database
14
+ "Connection",
15
+ "ConnectionContextManager",
16
+ "Connector",
17
+ "Cursor",
18
+ "Database",
19
+ "DatabaseCommand",
20
+ # Decorator
21
+ "RepositoryDecorator",
22
+ "BruteForceBatch",
23
+ # Interface
24
+ "Repository",
25
+ "RepositoryBase",
26
+ ]
@@ -97,3 +97,15 @@ class DatabaseCommand:
97
97
 
98
98
  def __str__(self) -> str: # pragma: no cover
99
99
  return self.value % self.payload
100
+
101
+
102
+ class ConnectionContextManager(AbstractContextManager[Connection]):
103
+ def __init__(self, connection: Connection) -> None:
104
+ self.connection = connection
105
+
106
+ def __enter__(self) -> Connection:
107
+ return self.connection
108
+
109
+ def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
110
+ self.connection.cursor().close()
111
+ self.connection.close()
@@ -1,8 +1,8 @@
1
1
  from collections.abc import Iterable, Iterator
2
2
  from dataclasses import dataclass
3
- from typing import Any, Generic
3
+ from typing import Generic
4
4
 
5
- from apexdevkit.repository.interface import ItemT, Repository
5
+ from .interface import ItemT, Repository
6
6
 
7
7
 
8
8
  @dataclass
@@ -21,9 +21,6 @@ class RepositoryDecorator(Generic[ItemT]): # pragma: no cover
21
21
  def delete(self, item_id: str) -> None:
22
22
  self.inner.delete(item_id)
23
23
 
24
- def bind(self, **kwargs: Any) -> Repository[ItemT]:
25
- return self.inner.bind(**kwargs)
26
-
27
24
  def __iter__(self) -> Iterator[ItemT]:
28
25
  return self.inner.__iter__()
29
26
 
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Callable, Iterable, Iterator
4
+ from typing import Generic, Protocol, TypeVar
5
+
6
+ ItemT = TypeVar("ItemT")
7
+ KeyFn = Callable[[ItemT], str]
8
+
9
+
10
+ class Repository(Protocol[ItemT]): # pragma: no cover
11
+ def create(self, item: ItemT) -> ItemT:
12
+ pass
13
+
14
+ def read(self, item_id: str) -> ItemT:
15
+ pass
16
+
17
+ def update(self, item: ItemT) -> None:
18
+ pass
19
+
20
+ def delete(self, item_id: str) -> None:
21
+ pass
22
+
23
+ def __iter__(self) -> Iterator[ItemT]:
24
+ pass
25
+
26
+ def __len__(self) -> int:
27
+ pass
28
+
29
+
30
+ class BatchRepository(Repository[ItemT], Protocol[ItemT]): # pragma: no cover
31
+ def create_many(self, items: Iterable[ItemT]) -> Iterable[ItemT]:
32
+ pass
33
+
34
+ def update_many(self, items: Iterable[ItemT]) -> None:
35
+ pass
36
+
37
+
38
+ class RepositoryBase(Generic[ItemT]): # pragma: no cover
39
+ def create(self, item: ItemT) -> ItemT:
40
+ raise NotImplementedError
41
+
42
+ def read(self, item_id: str) -> ItemT:
43
+ raise NotImplementedError
44
+
45
+ def update(self, item: ItemT) -> None:
46
+ raise NotImplementedError
47
+
48
+ def delete(self, item_id: str) -> None:
49
+ raise NotImplementedError
50
+
51
+ def __iter__(self) -> Iterator[ItemT]:
52
+ raise NotImplementedError
53
+
54
+ def __len__(self) -> int:
55
+ raise NotImplementedError
@@ -2,13 +2,12 @@ from __future__ import annotations
2
2
 
3
3
  from collections.abc import Callable, Iterator
4
4
  from dataclasses import dataclass, field
5
- from typing import Generic, TypeVar
5
+ from typing import Generic
6
6
 
7
7
  from apexdevkit.error import DoesNotExistError
8
8
  from apexdevkit.formatter import Formatter
9
- from apexdevkit.repository import Repository, RepositoryBase
10
9
 
11
- ItemT = TypeVar("ItemT")
10
+ from .interface import ItemT, Repository, RepositoryBase
12
11
 
13
12
 
14
13
  @dataclass(frozen=True)
@@ -0,0 +1,8 @@
1
+ from apexdevkit.repository.in_memory.builder import InMemoryRepository
2
+ from apexdevkit.repository.in_memory.store import InMemoryByteStore, KeyValueStore
3
+
4
+ __all__ = [
5
+ "InMemoryRepository",
6
+ "InMemoryByteStore",
7
+ "KeyValueStore",
8
+ ]
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from contextlib import suppress
4
+ from dataclasses import dataclass, field
5
+ from typing import Generic
6
+
7
+ from apexdevkit.error import ExistsError
8
+ from apexdevkit.key_fn import AttributeKey
9
+ from apexdevkit.repository.core.interface import ItemT, KeyFn, Repository
10
+
11
+ from .multi_key import MultiKeyRepository
12
+ from .single_key import SingleKeyRepository
13
+ from .store import InMemoryByteStore, KeyValueStore
14
+
15
+
16
+ @dataclass(frozen=True)
17
+ class InMemoryRepository(Generic[ItemT]):
18
+ store: KeyValueStore[ItemT] = field(default_factory=lambda: InMemoryByteStore())
19
+ keys: list[KeyFn[ItemT]] = field(default_factory=list)
20
+ seeds: frozenset[ItemT] = field(default_factory=frozenset)
21
+
22
+ def with_store(self, value: KeyValueStore[ItemT]) -> InMemoryRepository[ItemT]:
23
+ return InMemoryRepository(store=value, keys=self.keys, seeds=self.seeds)
24
+
25
+ def and_key(self, function: KeyFn[ItemT]) -> InMemoryRepository[ItemT]:
26
+ return self.with_key(function)
27
+
28
+ def with_key(self, function: KeyFn[ItemT]) -> InMemoryRepository[ItemT]:
29
+ return InMemoryRepository(
30
+ store=self.store,
31
+ keys=[*self.keys, function],
32
+ seeds=self.seeds,
33
+ )
34
+
35
+ def and_seeded(self, *items: ItemT) -> InMemoryRepository[ItemT]:
36
+ return self.with_seeded(*items)
37
+
38
+ def with_seeded(self, *items: ItemT) -> InMemoryRepository[ItemT]:
39
+ return InMemoryRepository(
40
+ store=self.store,
41
+ keys=self.keys,
42
+ seeds=self.seeds.union(set(items)),
43
+ )
44
+
45
+ def build(self) -> Repository[ItemT]:
46
+ return self._seed(self._create())
47
+
48
+ def _seed(self, repository: Repository[ItemT]) -> Repository[ItemT]:
49
+ for seed in self.seeds:
50
+ with suppress(ExistsError):
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 MultiKeyRepository(self.store, keys=self.keys)
@@ -0,0 +1,53 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterator
4
+ from dataclasses import dataclass, field
5
+
6
+ from apexdevkit.error import DoesNotExistError, ExistsError
7
+ from apexdevkit.repository.core.interface import ItemT, KeyFn, RepositoryBase
8
+
9
+ from .store import KeyValueStore
10
+
11
+
12
+ @dataclass
13
+ class MultiKeyRepository(RepositoryBase[ItemT]):
14
+ store: KeyValueStore[ItemT]
15
+
16
+ keys: list[KeyFn[ItemT]] = field(default_factory=list)
17
+
18
+ def create(self, item: ItemT) -> ItemT:
19
+ self._ensure_does_not_exist(item)
20
+ self.store.set(self._pk(item), item)
21
+
22
+ return item
23
+
24
+ def _ensure_does_not_exist(self, new: ItemT) -> None:
25
+ for existing in self:
26
+ for key in self.keys:
27
+ if key(new) == key(existing):
28
+ ExistsError(existing).with_duplicate(key).fire()
29
+
30
+ def _pk(self, item: ItemT) -> str:
31
+ return self.keys[0](item)
32
+
33
+ def update(self, item: ItemT) -> None:
34
+ self.delete(self._pk(item))
35
+ self.create(item)
36
+
37
+ def delete(self, item_id: str) -> None:
38
+ item = self.read(item_id)
39
+ self.store.drop(self._pk(item))
40
+
41
+ def read(self, item_id: str) -> ItemT:
42
+ for key in self.keys:
43
+ for item in self:
44
+ if key(item) == str(item_id):
45
+ return item
46
+
47
+ raise DoesNotExistError(item_id)
48
+
49
+ def __iter__(self) -> Iterator[ItemT]:
50
+ return iter(self.store.values())
51
+
52
+ def __len__(self) -> int:
53
+ return self.store.count()
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterator
4
+ from dataclasses import dataclass
5
+
6
+ from apexdevkit.error import DoesNotExistError, ExistsError
7
+ from apexdevkit.repository.core.interface import ItemT, KeyFn, RepositoryBase
8
+
9
+ from .store import KeyValueStore
10
+
11
+
12
+ @dataclass
13
+ class SingleKeyRepository(RepositoryBase[ItemT]):
14
+ store: KeyValueStore[ItemT]
15
+ pk: KeyFn[ItemT]
16
+
17
+ def create(self, item: ItemT) -> ItemT:
18
+ self._ensure_does_not_exist(item)
19
+ self.store.set(self.pk(item), item)
20
+
21
+ return item
22
+
23
+ def _ensure_does_not_exist(self, new: ItemT) -> None:
24
+ try:
25
+ existing = self.store.get(self.pk(new))
26
+ except KeyError:
27
+ return
28
+
29
+ ExistsError(existing).with_duplicate(self.pk).fire()
30
+
31
+ def update(self, item: ItemT) -> None:
32
+ self.delete(self.pk(item))
33
+ self.create(item)
34
+
35
+ def delete(self, item_id: str) -> None:
36
+ try:
37
+ self.store.drop(item_id)
38
+ except KeyError as e:
39
+ raise DoesNotExistError(item_id) from e
40
+
41
+ def read(self, item_id: str) -> ItemT:
42
+ try:
43
+ return self.store.get(item_id)
44
+ except KeyError as e:
45
+ raise DoesNotExistError(item_id) from e
46
+
47
+ def __iter__(self) -> Iterator[ItemT]:
48
+ return iter(self.store.values())
49
+
50
+ def __len__(self) -> int:
51
+ return self.store.count()
@@ -0,0 +1,62 @@
1
+ from __future__ import annotations
2
+
3
+ from collections import defaultdict
4
+ from collections.abc import Iterable, MutableMapping
5
+ from dataclasses import dataclass, field
6
+ from typing import Any, Generic, Protocol
7
+
8
+ from apexdevkit.formatter import Formatter, PickleFormatter
9
+ from apexdevkit.repository.core.interface import ItemT
10
+
11
+
12
+ class KeyValueStore(Protocol[ItemT]): # pragma: no cover
13
+ def count(self) -> int:
14
+ pass
15
+
16
+ def set(self, key: str, value: ItemT) -> None:
17
+ pass
18
+
19
+ def get(self, key: str) -> ItemT:
20
+ pass
21
+
22
+ def drop(self, key: str) -> None:
23
+ pass
24
+
25
+ def values(self) -> Iterable[ItemT]:
26
+ pass
27
+
28
+
29
+ @dataclass
30
+ class InMemoryByteStore(Generic[ItemT]):
31
+ formatter: Formatter[bytes, ItemT] = field(default_factory=PickleFormatter)
32
+
33
+ items: dict[str, bytes] = field(default_factory=dict)
34
+
35
+ def count(self) -> int:
36
+ return len(self.items)
37
+
38
+ def set(self, key: str, value: ItemT) -> None:
39
+ self.items[key] = self.formatter.dump(value)
40
+
41
+ def get(self, key: str) -> ItemT:
42
+ return self.formatter.load(self.items[key])
43
+
44
+ def drop(self, key: str) -> None:
45
+ del self.items[key]
46
+
47
+ def values(self) -> Iterable[ItemT]:
48
+ for raw in self.items.values():
49
+ yield self.formatter.load(raw)
50
+
51
+ @dataclass
52
+ class Cache:
53
+ items: MutableMapping[str, InMemoryByteStore[Any]] = field(init=False)
54
+
55
+ def __post_init__(self) -> None:
56
+ self.items = defaultdict(InMemoryByteStore)
57
+
58
+ def store_for(self, name: str) -> InMemoryByteStore[Any]:
59
+ return self.items[name]
60
+
61
+ def clear(self) -> None:
62
+ self.items.clear()
@@ -0,0 +1,11 @@
1
+ from .field import NotNone, SqlFieldBuilder, SqlFieldManager
2
+ from .mssql import MsSqlRepository
3
+ from .sqlite import SqliteRepository
4
+
5
+ __all__ = [
6
+ "NotNone",
7
+ "SqlFieldBuilder",
8
+ "SqlFieldManager",
9
+ "MsSqlRepository",
10
+ "SqliteRepository",
11
+ ]
@@ -9,6 +9,7 @@ from typing import Any
9
9
  import pymssql
10
10
 
11
11
  from apexdevkit.repository import Connection
12
+ from apexdevkit.repository.core.database import ConnectionContextManager
12
13
 
13
14
 
14
15
  @dataclass(frozen=True)
@@ -63,18 +64,6 @@ class MsSqlConnector:
63
64
  )
64
65
 
65
66
 
66
- class ConnectionContextManager(AbstractContextManager[Connection]):
67
- def __init__(self, connection: Connection) -> None:
68
- self.connection = connection
69
-
70
- def __enter__(self) -> Connection:
71
- return self.connection
72
-
73
- def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
74
- self.connection.cursor().close()
75
- self.connection.close()
76
-
77
-
78
67
  @dataclass
79
68
  class MsSqlConnectionAdapter:
80
69
  connection: pymssql.Connection[pymssql.DictRow]
@@ -9,7 +9,7 @@ from pymssql.exceptions import DatabaseError, OperationalError
9
9
  from apexdevkit.error import DoesNotExistError, ExistsError
10
10
  from apexdevkit.formatter import Formatter
11
11
  from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
12
- from apexdevkit.repository.sql import NotNone, SqlFieldManager, _SqlField
12
+ from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
13
13
 
14
14
  ItemT = TypeVar("ItemT")
15
15
 
@@ -8,8 +8,8 @@ from typing import Any, Generic
8
8
  from apexdevkit.error import DoesNotExistError, ExistsError
9
9
  from apexdevkit.formatter import Formatter
10
10
  from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
11
- from apexdevkit.repository.interface import ItemT
12
- from apexdevkit.repository.sql import NotNone, SqlFieldManager, _SqlField
11
+ from apexdevkit.repository.core.interface import ItemT
12
+ from apexdevkit.repository.sql.field import NotNone, SqlFieldManager, _SqlField
13
13
 
14
14
 
15
15
  @dataclass(frozen=True)
@@ -17,9 +17,6 @@ class SqliteRepository(RepositoryBase[ItemT]):
17
17
  db: Database
18
18
  table: SqlTable[ItemT]
19
19
 
20
- def bind(self, **kwargs: Any) -> SqliteRepository[ItemT]:
21
- return SqliteRepository(self.db, self.table.bind(**kwargs))
22
-
23
20
  def __iter__(self) -> Iterator[ItemT]:
24
21
  for raw in self.db.execute(self.table.select_all()).fetch_all():
25
22
  yield self.table.load(raw)
@@ -61,9 +58,6 @@ class SqliteRepository(RepositoryBase[ItemT]):
61
58
 
62
59
 
63
60
  class SqlTable(Generic[ItemT]): # pragma: no cover
64
- def bind(self, **_: Any) -> SqlTable[ItemT]:
65
- return self
66
-
67
61
  def count_all(self) -> DatabaseCommand:
68
62
  raise NotImplementedError
69
63
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "apexdevkit"
3
- version = "1.28.2"
3
+ version = "1.29.1"
4
4
  description = "Apex Development Tools for python."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -30,7 +30,7 @@ faker = "*"
30
30
 
31
31
 
32
32
  [tool.poetry.group.lint.dependencies]
33
- apexcodexpy = "*"
33
+ apexcodexpy = "0.3.1"
34
34
 
35
35
  [tool.mypy]
36
36
  ignore_missing_imports = true
@@ -1,27 +0,0 @@
1
- from collections.abc import Iterator
2
- from typing import Any, Generic
3
-
4
- from apexdevkit.repository.interface import ItemT, Repository
5
-
6
-
7
- class RepositoryBase(Generic[ItemT]): # pragma: no cover
8
- def create(self, item: ItemT) -> ItemT:
9
- raise NotImplementedError
10
-
11
- def read(self, item_id: str) -> ItemT:
12
- raise NotImplementedError
13
-
14
- def update(self, item: ItemT) -> None:
15
- raise NotImplementedError
16
-
17
- def delete(self, item_id: str) -> None:
18
- raise NotImplementedError
19
-
20
- def bind(self, **kwargs: Any) -> Repository[ItemT]:
21
- raise NotImplementedError
22
-
23
- def __iter__(self) -> Iterator[ItemT]:
24
- raise NotImplementedError
25
-
26
- def __len__(self) -> int:
27
- raise NotImplementedError
@@ -1,209 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from collections import defaultdict
4
- from collections.abc import Callable, Iterable, Iterator, MutableMapping
5
- from contextlib import suppress
6
- from dataclasses import dataclass, field
7
- from typing import Any, Generic, Protocol, Self
8
-
9
- from apexdevkit.error import DoesNotExistError, ExistsError
10
- from apexdevkit.formatter import Formatter, PickleFormatter
11
- from apexdevkit.key_fn import AttributeKey
12
- from apexdevkit.repository import RepositoryBase
13
- from apexdevkit.repository.interface import ItemT, Repository
14
-
15
- _KeyFunction = Callable[[ItemT], str]
16
-
17
-
18
- @dataclass(frozen=True)
19
- class InMemoryRepository(Generic[ItemT]):
20
- store: KeyValueStore[ItemT] = field(default_factory=lambda: InMemoryByteStore())
21
- keys: list[_KeyFunction[ItemT]] = field(default_factory=list)
22
- seeds: frozenset[ItemT] = field(default_factory=frozenset)
23
-
24
- def with_store(self, value: KeyValueStore[ItemT]) -> InMemoryRepository[ItemT]:
25
- return InMemoryRepository(store=value, keys=self.keys, seeds=self.seeds)
26
-
27
- def and_key(self, function: _KeyFunction[ItemT]) -> InMemoryRepository[ItemT]:
28
- return self.with_key(function)
29
-
30
- def with_key(self, function: _KeyFunction[ItemT]) -> InMemoryRepository[ItemT]:
31
- return InMemoryRepository(
32
- store=self.store,
33
- keys=[*self.keys, function],
34
- seeds=self.seeds,
35
- )
36
-
37
- def and_seeded(self, *items: ItemT) -> InMemoryRepository[ItemT]:
38
- return self.with_seeded(*items)
39
-
40
- def with_seeded(self, *items: ItemT) -> InMemoryRepository[ItemT]:
41
- return InMemoryRepository(
42
- store=self.store,
43
- keys=self.keys,
44
- seeds=self.seeds.union(set(items)),
45
- )
46
-
47
- def build(self) -> Repository[ItemT]:
48
- return self._seed(self._create())
49
-
50
- def _seed(self, repository: Repository[ItemT]) -> Repository[ItemT]:
51
- for seed in self.seeds:
52
- with suppress(ExistsError):
53
- repository.create(seed)
54
-
55
- return repository
56
-
57
- def _create(self) -> Repository[ItemT]:
58
- match len(self.keys):
59
- case 0:
60
- return _SingleKeyRepository(self.store, pk=AttributeKey("id"))
61
- case 1:
62
- return _SingleKeyRepository(self.store, pk=self.keys[0])
63
- case _:
64
- return _ManyKeyRepository(self.store, keys=self.keys)
65
-
66
-
67
- class KeyValueStore(Protocol[ItemT]): # pragma: no cover
68
- def count(self) -> int:
69
- pass
70
-
71
- def set(self, key: str, value: ItemT) -> None:
72
- pass
73
-
74
- def get(self, key: str) -> ItemT:
75
- pass
76
-
77
- def drop(self, key: str) -> None:
78
- pass
79
-
80
- def values(self) -> Iterable[ItemT]:
81
- pass
82
-
83
-
84
- @dataclass
85
- class InMemoryByteStore(Generic[ItemT]):
86
- formatter: Formatter[bytes, ItemT] = field(default_factory=PickleFormatter)
87
-
88
- items: dict[str, bytes] = field(default_factory=dict)
89
-
90
- def count(self) -> int:
91
- return len(self.items)
92
-
93
- def set(self, key: str, value: ItemT) -> None:
94
- self.items[key] = self.formatter.dump(value)
95
-
96
- def get(self, key: str) -> ItemT:
97
- return self.formatter.load(self.items[key])
98
-
99
- def drop(self, key: str) -> None:
100
- del self.items[key]
101
-
102
- def values(self) -> Iterable[ItemT]:
103
- for raw in self.items.values():
104
- yield self.formatter.load(raw)
105
-
106
- @dataclass
107
- class Cache:
108
- items: MutableMapping[str, InMemoryByteStore[Any]] = field(init=False)
109
-
110
- def __post_init__(self) -> None:
111
- self.items = defaultdict(InMemoryByteStore)
112
-
113
- def store_for(self, name: str) -> InMemoryByteStore[Any]:
114
- return self.items[name]
115
-
116
- def clear(self) -> None:
117
- self.items.clear()
118
-
119
-
120
- @dataclass
121
- class _SingleKeyRepository(RepositoryBase[ItemT]):
122
- store: KeyValueStore[ItemT]
123
- pk: _KeyFunction[ItemT]
124
-
125
- def bind(self, **_: Any) -> Self: # pragma: no cover
126
- return self
127
-
128
- def create(self, item: ItemT) -> ItemT:
129
- self._ensure_does_not_exist(item)
130
- self.store.set(self.pk(item), item)
131
-
132
- return item
133
-
134
- def _ensure_does_not_exist(self, new: ItemT) -> None:
135
- try:
136
- existing = self.store.get(self.pk(new))
137
- except KeyError:
138
- return
139
-
140
- ExistsError(existing).with_duplicate(self.pk).fire()
141
-
142
- def update(self, item: ItemT) -> None:
143
- self.delete(self.pk(item))
144
- self.create(item)
145
-
146
- def delete(self, item_id: str) -> None:
147
- try:
148
- self.store.drop(item_id)
149
- except KeyError as e:
150
- raise DoesNotExistError(item_id) from e
151
-
152
- def read(self, item_id: str) -> ItemT:
153
- try:
154
- return self.store.get(item_id)
155
- except KeyError as e:
156
- raise DoesNotExistError(item_id) from e
157
-
158
- def __iter__(self) -> Iterator[ItemT]:
159
- return iter(self.store.values())
160
-
161
- def __len__(self) -> int:
162
- return self.store.count()
163
-
164
-
165
- @dataclass
166
- class _ManyKeyRepository(RepositoryBase[ItemT]):
167
- store: KeyValueStore[ItemT]
168
-
169
- keys: list[_KeyFunction[ItemT]] = field(default_factory=list)
170
-
171
- def bind(self, **_: Any) -> Self: # pragma: no cover
172
- return self
173
-
174
- def create(self, item: ItemT) -> ItemT:
175
- self._ensure_does_not_exist(item)
176
- self.store.set(self._pk(item), item)
177
-
178
- return item
179
-
180
- def _ensure_does_not_exist(self, new: ItemT) -> None:
181
- for existing in self:
182
- for key in self.keys:
183
- if key(new) == key(existing):
184
- ExistsError(existing).with_duplicate(key).fire()
185
-
186
- def _pk(self, item: ItemT) -> str:
187
- return self.keys[0](item)
188
-
189
- def update(self, item: ItemT) -> None:
190
- self.delete(self._pk(item))
191
- self.create(item)
192
-
193
- def delete(self, item_id: str) -> None:
194
- item = self.read(item_id)
195
- self.store.drop(self._pk(item))
196
-
197
- def read(self, item_id: str) -> ItemT:
198
- for key in self.keys:
199
- for item in self:
200
- if key(item) == str(item_id):
201
- return item
202
-
203
- raise DoesNotExistError(item_id)
204
-
205
- def __iter__(self) -> Iterator[ItemT]:
206
- return iter(self.store.values())
207
-
208
- def __len__(self) -> int:
209
- return self.store.count()
@@ -1,37 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from collections.abc import Iterable, Iterator
4
- from typing import Any, Protocol, TypeVar
5
-
6
- ItemT = TypeVar("ItemT")
7
-
8
-
9
- class Repository(Protocol[ItemT]): # pragma: no cover
10
- def create(self, item: ItemT) -> ItemT:
11
- pass
12
-
13
- def read(self, item_id: str) -> ItemT:
14
- pass
15
-
16
- def update(self, item: ItemT) -> None:
17
- pass
18
-
19
- def delete(self, item_id: str) -> None:
20
- pass
21
-
22
- def bind(self, **kwargs: Any) -> Repository[ItemT]:
23
- pass
24
-
25
- def __iter__(self) -> Iterator[ItemT]:
26
- pass
27
-
28
- def __len__(self) -> int:
29
- pass
30
-
31
-
32
- class BatchRepository(Repository[ItemT], Protocol[ItemT]): # pragma: no cover
33
- def create_many(self, items: Iterable[ItemT]) -> Iterable[ItemT]:
34
- pass
35
-
36
- def update_many(self, items: Iterable[ItemT]) -> None:
37
- pass
File without changes
File without changes