apexdevkit 1.14.2__tar.gz → 1.14.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 (43) hide show
  1. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/PKG-INFO +1 -1
  2. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/builder.py +4 -2
  3. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/dependable.py +20 -22
  4. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/resource.py +1 -1
  5. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/response.py +1 -1
  6. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/schema.py +1 -1
  7. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/service.py +18 -14
  8. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fluent.py +1 -1
  9. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/fake.py +1 -1
  10. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/httpx.py +1 -1
  11. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/connector.py +3 -3
  12. apexdevkit-1.14.4/apexdevkit/repository/database.py +94 -0
  13. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/mongo.py +1 -1
  14. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/sqlite.py +1 -1
  15. apexdevkit-1.14.4/apexdevkit/synchronization.py +47 -0
  16. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/testing/database.py +6 -6
  17. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/testing/fake.py +2 -2
  18. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/testing/rest.py +3 -3
  19. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/pyproject.toml +1 -1
  20. apexdevkit-1.14.2/apexdevkit/repository/database.py +0 -90
  21. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/LICENSE +0 -0
  22. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/README.md +0 -0
  23. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/__init__.py +0 -0
  24. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/annotation/__init__.py +0 -0
  25. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/annotation/deprecate.py +0 -0
  26. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/environment.py +0 -0
  27. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/error.py +0 -0
  28. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/__init__.py +0 -0
  29. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/docs.py +0 -0
  30. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/fastapi/router.py +0 -0
  31. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/formatter.py +0 -0
  32. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/__init__.py +0 -0
  33. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/fluent.py +0 -0
  34. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/json.py +0 -0
  35. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/http/url.py +0 -0
  36. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/key_fn.py +0 -0
  37. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/py.typed +0 -0
  38. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/__init__.py +0 -0
  39. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/base.py +0 -0
  40. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/decorator.py +0 -0
  41. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/in_memory.py +0 -0
  42. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/repository/interface.py +0 -0
  43. {apexdevkit-1.14.2 → apexdevkit-1.14.4}/apexdevkit/testing/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apexdevkit
3
- Version: 1.14.2
3
+ Version: 1.14.4
4
4
  Summary: Apex Development Tools for python.
5
5
  Author: Apex Dev
6
6
  Author-email: dev@apex.ge
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from abc import ABC, abstractmethod
2
4
  from dataclasses import dataclass, field
3
5
  from typing import Any, Self
@@ -53,12 +55,12 @@ class RestfulServiceBuilder(ABC):
53
55
  parent_id: str = field(init=False)
54
56
  user: Any = field(init=False)
55
57
 
56
- def with_user(self, user: Any) -> "RestfulServiceBuilder":
58
+ def with_user(self, user: Any) -> RestfulServiceBuilder:
57
59
  self.user = user
58
60
 
59
61
  return self
60
62
 
61
- def with_parent(self, identity: str) -> "RestfulServiceBuilder":
63
+ def with_parent(self, identity: str) -> RestfulServiceBuilder:
62
64
  self.parent_id = identity
63
65
 
64
66
  return self
@@ -1,5 +1,5 @@
1
- from dataclasses import dataclass, field
2
- from typing import Annotated, Any, Callable, Protocol, Self
1
+ from dataclasses import dataclass
2
+ from typing import Annotated, Any, Callable, Protocol
3
3
 
4
4
  from fastapi import Depends, Path
5
5
  from fastapi.requests import Request
@@ -23,7 +23,7 @@ class _Dependency(Protocol):
23
23
  pass
24
24
 
25
25
 
26
- @dataclass
26
+ @dataclass(frozen=True)
27
27
  class ServiceDependency:
28
28
  dependency: _Dependency
29
29
 
@@ -36,7 +36,7 @@ class ServiceDependency:
36
36
  return Annotated[RestfulService, Depends(_)]
37
37
 
38
38
 
39
- @dataclass
39
+ @dataclass(frozen=True)
40
40
  class ParentDependency:
41
41
  parent: RestfulName
42
42
  dependency: _Dependency
@@ -56,7 +56,7 @@ class ParentDependency:
56
56
  return Annotated[RestfulServiceBuilder, Depends(_)]
57
57
 
58
58
 
59
- @dataclass
59
+ @dataclass(frozen=True)
60
60
  class UserDependency:
61
61
  extract_user: Callable[..., Any]
62
62
  dependency: _Dependency
@@ -71,7 +71,7 @@ class UserDependency:
71
71
  return Annotated[RestfulServiceBuilder, Depends(_)]
72
72
 
73
73
 
74
- @dataclass
74
+ @dataclass(frozen=True)
75
75
  class InfraDependency:
76
76
  infra: RestfulServiceBuilder
77
77
 
@@ -82,26 +82,24 @@ class InfraDependency:
82
82
  return Annotated[RestfulServiceBuilder, Depends(_)]
83
83
 
84
84
 
85
- @dataclass
85
+ @dataclass(frozen=True)
86
86
  class DependableBuilder:
87
- dependency: _Dependency = field(init=False)
87
+ dependency: _Dependency | None = None
88
88
 
89
- def from_infra(self, value: RestfulServiceBuilder) -> Self:
90
- self.dependency = InfraDependency(value)
89
+ def from_infra(self, value: RestfulServiceBuilder) -> "DependableBuilder":
90
+ return DependableBuilder(InfraDependency(value))
91
91
 
92
- return self
92
+ def with_parent(self, value: RestfulName) -> "DependableBuilder":
93
+ if self.dependency is None:
94
+ raise RuntimeError("RestfulServiceBuilder type not set")
95
+ return DependableBuilder(ParentDependency(value, self.dependency))
93
96
 
94
- def with_parent(self, value: RestfulName) -> Self:
95
- dependable = DependableBuilder()
96
- dependable.dependency = ParentDependency(value, self.dependency)
97
-
98
- return dependable
99
-
100
- def with_user(self, extract_user: Callable[..., Any]) -> Self:
101
- dependable = DependableBuilder()
102
- dependable.dependency = UserDependency(extract_user, self.dependency)
103
-
104
- return dependable
97
+ def with_user(self, extract_user: Callable[..., Any]) -> "DependableBuilder":
98
+ if self.dependency is None:
99
+ raise RuntimeError("RestfulServiceBuilder type not set")
100
+ return DependableBuilder(UserDependency(extract_user, self.dependency))
105
101
 
106
102
  def as_dependable(self) -> type[RestfulService]:
103
+ if self.dependency is None:
104
+ raise RuntimeError("RestfulServiceBuilder type not set")
107
105
  return ServiceDependency(self.dependency).as_dependable()
@@ -10,7 +10,7 @@ _Response = JSONResponse | dict[str, Any]
10
10
  _Endpoint = Callable[..., _Response]
11
11
 
12
12
 
13
- @dataclass
13
+ @dataclass(frozen=True)
14
14
  class RestfulResource:
15
15
  response: RestfulResponse
16
16
 
@@ -7,7 +7,7 @@ from apexdevkit.error import DoesNotExistError, ExistsError, ForbiddenError
7
7
  from apexdevkit.testing import RestfulName
8
8
 
9
9
 
10
- @dataclass
10
+ @dataclass(frozen=True)
11
11
  class RestfulResponse:
12
12
  name: RestfulName
13
13
 
@@ -24,7 +24,7 @@ class SchemaFields(ABC):
24
24
  pass
25
25
 
26
26
 
27
- @dataclass
27
+ @dataclass(frozen=True)
28
28
  class RestfulSchema:
29
29
  name: RestfulName
30
30
  fields: SchemaFields
@@ -1,6 +1,8 @@
1
+ from __future__ import annotations
2
+
1
3
  from abc import ABC
2
- from dataclasses import dataclass, field
3
- from typing import Any, Dict, Generic, Iterable, Self, TypeVar
4
+ from dataclasses import dataclass
5
+ from typing import Any, Dict, Generic, Iterable, TypeVar
4
6
 
5
7
  from apexdevkit.formatter import Formatter
6
8
  from apexdevkit.repository.decorator import BatchRepositoryDecorator
@@ -50,26 +52,28 @@ class RestfulService(ABC): # pragma: no cover
50
52
  ItemT = TypeVar("ItemT")
51
53
 
52
54
 
53
- @dataclass
55
+ @dataclass(frozen=True)
54
56
  class RestfulRepositoryBuilder(Generic[ItemT]):
55
- formatter: Formatter[dict[str, Any], ItemT] = field(init=False)
56
- repository: Repository[ItemT] = field(init=False)
57
-
58
- def with_formatter(self, formatter: Formatter[dict[str, Any], ItemT]) -> Self:
59
- self.formatter = formatter
60
-
61
- return self
57
+ formatter: Formatter[dict[str, Any], ItemT] | None = None
58
+ repository: Repository[ItemT] | None = None
62
59
 
63
- def with_repository(self, repository: Repository[ItemT]) -> Self:
64
- self.repository = repository
60
+ def with_formatter(
61
+ self, formatter: Formatter[dict[str, Any], ItemT]
62
+ ) -> RestfulRepositoryBuilder[ItemT]:
63
+ return RestfulRepositoryBuilder[ItemT](formatter, self.repository)
65
64
 
66
- return self
65
+ def with_repository(
66
+ self, repository: Repository[ItemT]
67
+ ) -> RestfulRepositoryBuilder[ItemT]:
68
+ return RestfulRepositoryBuilder[ItemT](self.formatter, repository)
67
69
 
68
70
  def build(self) -> RestfulService:
71
+ if self.formatter is None or self.repository is None:
72
+ raise RuntimeError("Formatter or repository not provided.")
69
73
  return _RestfulRepository(self.formatter, self.repository)
70
74
 
71
75
 
72
- @dataclass
76
+ @dataclass(frozen=True)
73
77
  class _RestfulRepository(RestfulService, Generic[ItemT]):
74
78
  formatter: Formatter[dict[str, Any], ItemT]
75
79
  repository: Repository[ItemT]
@@ -26,7 +26,7 @@ class FluentDict(dict[str, ItemT]):
26
26
  return FluentDict[ItemT]({k: v for k, v in self.items() if k in keys})
27
27
 
28
28
 
29
- @dataclass
29
+ @dataclass(frozen=True)
30
30
  class FluentElement(Generic[ItemT]):
31
31
  value: ItemT
32
32
 
@@ -7,7 +7,7 @@ from apexdevkit.http.fluent import HttpMethod, HttpResponse
7
7
  from apexdevkit.http.json import JsonDict
8
8
 
9
9
 
10
- @dataclass
10
+ @dataclass(frozen=True)
11
11
  class FakeResponse:
12
12
  content: Any = field(default_factory=dict)
13
13
  status_code: int = 200
@@ -46,7 +46,7 @@ class Httpx:
46
46
  )
47
47
 
48
48
 
49
- @dataclass
49
+ @dataclass(frozen=True)
50
50
  class _HttpxResponse:
51
51
  inner: httpx.Response
52
52
 
@@ -8,7 +8,7 @@ from pymongo import MongoClient
8
8
  from apexdevkit.repository import Connection
9
9
 
10
10
 
11
- @dataclass
11
+ @dataclass(frozen=True)
12
12
  class SqliteFileConnector:
13
13
  dsn: str
14
14
 
@@ -19,7 +19,7 @@ class SqliteFileConnector:
19
19
  return connection
20
20
 
21
21
 
22
- @dataclass
22
+ @dataclass(frozen=True)
23
23
  class SqliteInMemoryConnector:
24
24
  dsn: str = ":memory:"
25
25
 
@@ -34,7 +34,7 @@ class SqliteInMemoryConnector:
34
34
  return connection
35
35
 
36
36
 
37
- @dataclass
37
+ @dataclass(frozen=True)
38
38
  class PyMongoConnector:
39
39
  dsn: str
40
40
 
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+
3
+ from copy import deepcopy
4
+ from dataclasses import dataclass, field
5
+ from typing import Any, ContextManager, Iterable, Protocol
6
+
7
+ _RawData = dict[str, Any]
8
+
9
+
10
+ @dataclass(frozen=True)
11
+ class Database:
12
+ connector: Connector
13
+
14
+ def execute(self, command: DatabaseCommand) -> _CommandExecutor:
15
+ return Database._CommandExecutor(self.connector, command)
16
+
17
+ @dataclass(frozen=True)
18
+ class _CommandExecutor:
19
+ connector: Connector
20
+ command: DatabaseCommand
21
+
22
+ def fetch_none(self) -> None:
23
+ with self.connector.connect() as connection:
24
+ cursor: Cursor = connection.cursor()
25
+ cursor.execute(self.command.value, self.command.payload)
26
+ cursor.close()
27
+
28
+ def fetch_one(self) -> _RawData:
29
+ with self.connector.connect() as connection:
30
+ cursor: Cursor = connection.cursor()
31
+ cursor.execute(self.command.value, self.command.payload)
32
+ raw = cursor.fetchone()
33
+ cursor.close()
34
+
35
+ return dict(raw or {})
36
+
37
+ def fetch_all(self) -> Iterable[_RawData]:
38
+ with self.connector.connect() as connection:
39
+ cursor: Cursor = connection.cursor()
40
+ cursor.execute(self.command.value, self.command.payload)
41
+ raw = cursor.fetchall()
42
+ cursor.close()
43
+
44
+ return [dict(raw or {}) for raw in raw]
45
+
46
+
47
+ class Connector(Protocol): # pragma: no cover
48
+ def connect(self) -> ContextManager[Connection]:
49
+ pass
50
+
51
+
52
+ class Connection(Protocol): # pragma: no cover
53
+ def cursor(self) -> Cursor:
54
+ pass
55
+
56
+
57
+ class Cursor(Protocol): # pragma: no cover
58
+ def execute(self, *args: Any, **kwargs: Any) -> Any:
59
+ pass
60
+
61
+ def executemany(self, *args: Any, **kwargs: Any) -> Any:
62
+ pass
63
+
64
+ def fetchone(self, *args: Any, **kwargs: Any) -> Any:
65
+ pass
66
+
67
+ def fetchall(self, *args: Any, **kwargs: Any) -> Any:
68
+ pass
69
+
70
+ def close(self) -> None:
71
+ pass
72
+
73
+
74
+ @dataclass(frozen=True)
75
+ class DatabaseCommand:
76
+ value: str = field(default_factory=str)
77
+ payload: _RawData | list[_RawData] = field(default_factory=dict)
78
+
79
+ def with_data(
80
+ self, value: _RawData | None = None, **fields: Any
81
+ ) -> DatabaseCommand:
82
+ assert isinstance(self.payload, dict)
83
+
84
+ payload = deepcopy(self.payload)
85
+ payload.update(value or {})
86
+ payload.update(fields)
87
+
88
+ return DatabaseCommand(self.value, payload)
89
+
90
+ def with_collection(self, value: list[_RawData]) -> DatabaseCommand:
91
+ return DatabaseCommand(self.value, value)
92
+
93
+ def __str__(self) -> str: # pragma: no cover
94
+ return self.value
@@ -19,7 +19,7 @@ class _Item(Protocol): # pragma: no cover
19
19
  ItemT = TypeVar("ItemT", bound=_Item)
20
20
 
21
21
 
22
- @dataclass
22
+ @dataclass(frozen=True)
23
23
  class MongoRepository(Generic[ItemT]):
24
24
  connector: MongoConnector
25
25
  database_name: str
@@ -9,7 +9,7 @@ from apexdevkit.repository import Database, DatabaseCommand, RepositoryBase
9
9
  from apexdevkit.repository.interface import ItemT
10
10
 
11
11
 
12
- @dataclass
12
+ @dataclass(frozen=True)
13
13
  class SqliteRepository(RepositoryBase[ItemT]):
14
14
  db: Database
15
15
  table: SqlTable[ItemT]
@@ -0,0 +1,47 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Generic, Iterable, Iterator, Protocol, TypeVar
5
+
6
+ ItemT = TypeVar("ItemT")
7
+
8
+
9
+ @dataclass(frozen=True)
10
+ class Sync(Generic[ItemT]):
11
+ source: _Source[ItemT]
12
+ target: _Target[ItemT]
13
+
14
+ def sync(self) -> None:
15
+ items = self.source.value_of(list(self.target))
16
+ self.target.update_many(list(items))
17
+
18
+
19
+ class _Source(Protocol[ItemT]):
20
+ def value_of(self, items: Iterable[ItemT]) -> Iterable[ItemT]:
21
+ pass
22
+
23
+
24
+ class _Target(Protocol[ItemT]):
25
+ def __iter__(self) -> Iterator[ItemT]:
26
+ pass
27
+
28
+ def update_many(self, items: Iterable[ItemT]) -> None:
29
+ pass
30
+
31
+
32
+ @dataclass(frozen=True)
33
+ class FullSync(Generic[ItemT]):
34
+ source: Iterable[ItemT]
35
+ target: _FullTarget[ItemT]
36
+
37
+ def sync(self) -> None:
38
+ items = list(self.source)
39
+ self.target.update_many(items)
40
+
41
+
42
+ ItemR = TypeVar("ItemR", contravariant=True)
43
+
44
+
45
+ class _FullTarget(Protocol[ItemR]):
46
+ def update_many(self, items: Iterable[ItemR]) -> None:
47
+ pass
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from contextlib import nullcontext
2
4
  from dataclasses import dataclass, field
3
5
  from typing import Any, ContextManager, Self
@@ -5,15 +7,13 @@ from typing import Any, ContextManager, Self
5
7
  from apexdevkit.repository import DatabaseCommand
6
8
 
7
9
 
8
- @dataclass
10
+ @dataclass(frozen=True)
9
11
  class FakeConnector:
10
12
  commands: list[tuple[str, Any]] = field(default_factory=list)
11
- results: list[Any] = field(init=False, default_factory=list)
12
-
13
- def with_result(self, values: Any) -> Self:
14
- self.results = [values, *self.results]
13
+ results: list[Any] = field(default_factory=list)
15
14
 
16
- return self
15
+ def with_result(self, values: Any) -> FakeConnector:
16
+ return FakeConnector(self.commands, [values, *self.results])
17
17
 
18
18
  def execute(self, command: str, data: Any) -> None:
19
19
  self.commands.append((command, data))
@@ -9,7 +9,7 @@ from apexdevkit.http import JsonDict
9
9
  ItemT = TypeVar("ItemT")
10
10
 
11
11
 
12
- @dataclass
12
+ @dataclass(frozen=True)
13
13
  class Fake:
14
14
  faker: Faker = field(default_factory=Faker)
15
15
 
@@ -50,7 +50,7 @@ class Fake:
50
50
  return bool(self.faker.boolean())
51
51
 
52
52
 
53
- @dataclass
53
+ @dataclass(frozen=True)
54
54
  class FakeResource(Generic[ItemT]):
55
55
  item_type: Type[ItemT] = field()
56
56
  fake: Fake = field(default_factory=Fake)
@@ -8,7 +8,7 @@ from apexdevkit.http import Http, HttpUrl, JsonDict
8
8
  from apexdevkit.http.fluent import HttpMethod, HttpResponse
9
9
 
10
10
 
11
- @dataclass
11
+ @dataclass(frozen=True)
12
12
  class RestResource:
13
13
  http: Http
14
14
  name: RestfulName
@@ -95,13 +95,13 @@ class RestResource:
95
95
  )
96
96
 
97
97
 
98
- @dataclass
98
+ @dataclass(frozen=True)
99
99
  class RestCollection(RestResource):
100
100
  def sub_resource(self, name: str) -> RestItem:
101
101
  return RestItem(self.http.with_endpoint(self.name.plural), RestfulName(name))
102
102
 
103
103
 
104
- @dataclass
104
+ @dataclass(frozen=True)
105
105
  class RestItem(RestResource):
106
106
  def sub_resource(self, name: str) -> RestItem:
107
107
  return RestItem(self.http.with_endpoint(self.name.singular), RestfulName(name))
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apexdevkit"
3
- version = "1.14.2"
3
+ version = "1.14.4"
4
4
  description = "Apex Development Tools for python."
5
5
  authors = ["Apex Dev <dev@apex.ge>"]
6
6
  readme = "README.md"
@@ -1,90 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from dataclasses import dataclass, field
4
- from typing import Any, ContextManager, Iterable, Protocol, Self
5
-
6
- _RawData = dict[str, Any]
7
-
8
-
9
- @dataclass
10
- class Database:
11
- connector: Connector
12
-
13
- command: DatabaseCommand = field(init=False)
14
-
15
- def execute(self, command: DatabaseCommand) -> Self:
16
- self.command = command
17
-
18
- return self
19
-
20
- def fetch_none(self) -> None:
21
- with self.connector.connect() as connection:
22
- cursor: Cursor = connection.cursor()
23
- cursor.execute(self.command.value, self.command.payload)
24
- cursor.close()
25
-
26
- def fetch_one(self) -> _RawData:
27
- with self.connector.connect() as connection:
28
- cursor: Cursor = connection.cursor()
29
- cursor.execute(self.command.value, self.command.payload)
30
- raw = cursor.fetchone()
31
- cursor.close()
32
-
33
- return dict(raw or {})
34
-
35
- def fetch_all(self) -> Iterable[_RawData]:
36
- with self.connector.connect() as connection:
37
- cursor: Cursor = connection.cursor()
38
- cursor.execute(self.command.value, self.command.payload)
39
- raw = cursor.fetchall()
40
- cursor.close()
41
-
42
- return [dict(raw or {}) for raw in raw]
43
-
44
-
45
- class Connector(Protocol): # pragma: no cover
46
- def connect(self) -> ContextManager[Connection]:
47
- pass
48
-
49
-
50
- class Connection(Protocol): # pragma: no cover
51
- def cursor(self) -> Cursor:
52
- pass
53
-
54
-
55
- class Cursor(Protocol): # pragma: no cover
56
- def execute(self, *args: Any, **kwargs: Any) -> Any:
57
- pass
58
-
59
- def executemany(self, *args: Any, **kwargs: Any) -> Any:
60
- pass
61
-
62
- def fetchone(self, *args: Any, **kwargs: Any) -> Any:
63
- pass
64
-
65
- def fetchall(self, *args: Any, **kwargs: Any) -> Any:
66
- pass
67
-
68
- def close(self) -> None:
69
- pass
70
-
71
-
72
- @dataclass
73
- class DatabaseCommand:
74
- value: str
75
- payload: _RawData | list[_RawData] = field(init=False, default_factory=dict)
76
-
77
- def with_data(self, value: _RawData | None = None, **fields: Any) -> Self:
78
- assert isinstance(self.payload, dict)
79
- self.payload.update(value or {})
80
- self.payload.update(fields)
81
-
82
- return self
83
-
84
- def with_collection(self, value: list[_RawData]) -> Self:
85
- self.payload = value
86
-
87
- return self
88
-
89
- def __str__(self) -> str: # pragma: no cover
90
- return self.value
File without changes
File without changes