apexdevkit 2.0.1__tar.gz → 2.1.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 (52) hide show
  1. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/PKG-INFO +3 -2
  2. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/connector.py +2 -18
  3. apexdevkit-2.1.1/apexdevkit/repository/sql/sqlite/__init__.py +8 -0
  4. apexdevkit-2.1.1/apexdevkit/testing.py +157 -0
  5. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/pyproject.toml +3 -3
  6. apexdevkit-2.0.1/apexdevkit/repository/sql/sqlite/__init__.py +0 -7
  7. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/LICENSE +0 -0
  8. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/README.md +0 -0
  9. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/__init__.py +0 -0
  10. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/annotation/__init__.py +0 -0
  11. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/annotation/deprecate.py +0 -0
  12. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/date.py +0 -0
  13. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/error.py +0 -0
  14. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/__init__.py +0 -0
  15. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/builder.py +0 -0
  16. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/dependable.py +0 -0
  17. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/docs.py +0 -0
  18. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/name.py +0 -0
  19. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/resource.py +0 -0
  20. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/response.py +0 -0
  21. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/router.py +0 -0
  22. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/schema.py +0 -0
  23. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/fastapi/service.py +0 -0
  24. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/formatter.py +0 -0
  25. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/key_fn.py +0 -0
  26. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/py.typed +0 -0
  27. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/query/__init__.py +0 -0
  28. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/query/generator.py +0 -0
  29. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/query/query.py +0 -0
  30. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/__init__.py +0 -0
  31. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/core/__init__.py +0 -0
  32. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/core/database.py +0 -0
  33. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/core/decorator.py +0 -0
  34. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/core/interface.py +0 -0
  35. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/core/mixin.py +0 -0
  36. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/in_memory/__init__.py +0 -0
  37. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/in_memory/mixin.py +0 -0
  38. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/in_memory/repository.py +0 -0
  39. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/in_memory/store.py +0 -0
  40. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/__init__.py +0 -0
  41. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/field.py +0 -0
  42. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/mssql/__init__.py +0 -0
  43. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/mssql/repository.py +0 -0
  44. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/mssql/table.py +0 -0
  45. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/sqlite/repository.py +0 -0
  46. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/repository/sql/sqlite/table.py +0 -0
  47. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/server.py +0 -0
  48. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/sync/__init__.py +0 -0
  49. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/sync/observer.py +0 -0
  50. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/sync/source.py +0 -0
  51. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/sync/sync.py +0 -0
  52. {apexdevkit-2.0.1 → apexdevkit-2.1.1}/apexdevkit/sync/target.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apexdevkit
3
- Version: 2.0.1
3
+ Version: 2.1.1
4
4
  Summary: Apex Development Tools for python.
5
5
  License-File: LICENSE
6
6
  Author: Apex Dev
@@ -10,10 +10,11 @@ Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Programming Language :: Python :: 3.12
11
11
  Classifier: Programming Language :: Python :: 3.13
12
12
  Classifier: Programming Language :: Python :: 3.14
13
+ Classifier: Programming Language :: Python :: 3.15
13
14
  Requires-Dist: fastapi
14
15
  Requires-Dist: pydantic
15
16
  Requires-Dist: pymssql (==2.*)
16
- Requires-Dist: pypebbles (==0.2.*)
17
+ Requires-Dist: pypebbles (==0.3.*)
17
18
  Requires-Dist: python-dotenv
18
19
  Requires-Dist: sentry-sdk[fastapi]
19
20
  Requires-Dist: uvicorn
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import sqlite3
4
4
  from contextlib import AbstractContextManager
5
5
  from dataclasses import dataclass
6
- from functools import cached_property
7
6
  from typing import Any
8
7
 
9
8
  import pymssql
@@ -18,25 +17,10 @@ class SqliteFileConnector:
18
17
  dsn: str = Environment().inject(variable="DSN")
19
18
 
20
19
  def connect(self) -> AbstractContextManager[Connection]:
21
- connection = sqlite3.connect(self.dsn)
20
+ connection = sqlite3.connect(self.dsn, autocommit=True)
22
21
  connection.row_factory = sqlite3.Row
23
22
 
24
- return connection
25
-
26
-
27
- @dataclass(frozen=True)
28
- class SqliteInMemoryConnector:
29
- dsn: str = ":memory:"
30
-
31
- def connect(self) -> AbstractContextManager[Connection]:
32
- return self._connection
33
-
34
- @cached_property
35
- def _connection(self) -> AbstractContextManager[Connection]:
36
- connection = sqlite3.connect(self.dsn, check_same_thread=False)
37
- connection.row_factory = sqlite3.Row
38
-
39
- return connection
23
+ return ConnectionContextManager(connection)
40
24
 
41
25
 
42
26
  @dataclass(frozen=True)
@@ -0,0 +1,8 @@
1
+ from .repository import SqliteRepository
2
+ from .table import SqliteTableBuilder, SqlTable
3
+
4
+ __all__ = [
5
+ "SqliteRepository",
6
+ "SqliteTableBuilder",
7
+ "SqlTable",
8
+ ]
@@ -0,0 +1,157 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Collection
4
+ from dataclasses import dataclass, field, replace
5
+ from typing import Any, Self
6
+
7
+ from pypebbles import JsonDict
8
+ from pypebbles.http import (
9
+ HttpDispatcher,
10
+ HttpMethod,
11
+ HttpRequest,
12
+ HttpResponse,
13
+ HttpTransport,
14
+ )
15
+
16
+ from apexdevkit.fastapi.name import RestfulName
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class RestRequest:
21
+ request: HttpRequest = HttpRequest()
22
+
23
+ def with_params(self, **params: Any) -> RestRequest:
24
+ return replace(self, request=self.request.with_params(params))
25
+
26
+ def with_data(self, value: JsonDict) -> RestRequest:
27
+ return replace(self, request=self.request.with_json(value))
28
+
29
+ def sub_resource(self, name: RestfulName) -> RestRequest:
30
+ return replace(self, request=self.request.with_endpoint(name.plural))
31
+
32
+ def item(self, with_id: Any) -> RestRequest:
33
+ return replace(self, request=self.request.with_endpoint(str(with_id)))
34
+
35
+ def using(self, transport: RestTransport) -> RestDispatcher:
36
+ return RestDispatcher(request=self.request, transport=transport)
37
+
38
+
39
+ @dataclass(frozen=True)
40
+ class RestTransport:
41
+ resource: RestfulName
42
+ transport: HttpTransport[HttpResponse]
43
+
44
+ def deliver(self, request: HttpRequest, using: HttpMethod) -> StatusProbe:
45
+ return StatusProbe(
46
+ resource=self.resource,
47
+ response=self.transport.deliver(request, using),
48
+ )
49
+
50
+
51
+ @dataclass(frozen=True)
52
+ class RestResponse:
53
+ resource: RestfulName
54
+
55
+ raw: JsonDict = field(default_factory=JsonDict)
56
+
57
+ def __call__(self, raw: JsonDict) -> RestResponse:
58
+ return replace(self, raw=raw)
59
+
60
+ def status(self) -> str:
61
+ return self.raw.value_of("status").to(str)
62
+
63
+ def code(self) -> int:
64
+ return self.raw.value_of("code").to(int)
65
+
66
+ def message(self) -> str:
67
+ return self.error().value_of("message").to(str)
68
+
69
+ def error(self) -> JsonDict:
70
+ return self.raw.value_of("error").to(JsonDict)
71
+
72
+ def item(self) -> JsonDict:
73
+ return self.data().value_of(self.resource.singular).to(JsonDict)
74
+
75
+ def collection(self) -> Collection[JsonDict]:
76
+ return self.data().value_of(self.resource.plural).to(list)
77
+
78
+ def count(self) -> int:
79
+ return self.data().value_of("count").to(int)
80
+
81
+ def data(self) -> JsonDict:
82
+ return self.raw.value_of("data").to(JsonDict)
83
+
84
+
85
+ @dataclass(frozen=True)
86
+ class StatusProbe:
87
+ resource: RestfulName
88
+ response: HttpResponse
89
+
90
+ def ensure(self, http_code: int) -> ResponseProbe:
91
+ assert self.response.status == http_code
92
+
93
+ return ResponseProbe(self.response.load(RestResponse(self.resource)))
94
+
95
+
96
+ @dataclass(frozen=True)
97
+ class ResponseProbe:
98
+ response: RestResponse
99
+
100
+ def and_api_fail(self) -> Self:
101
+ return self.with_status("fail")
102
+
103
+ def and_api_success(self) -> Self:
104
+ return self.with_status("success")
105
+
106
+ def with_status(self, value: str) -> Self:
107
+ assert self.response.status() == value
108
+
109
+ return self
110
+
111
+ def with_code(self, value: int) -> Self:
112
+ assert self.response.code() == value
113
+
114
+ return self
115
+
116
+ def and_message(self, value: str) -> Self:
117
+ return self.with_message(value)
118
+
119
+ def with_message(self, value: str) -> Self:
120
+ assert self.response.message() == value, self.response.raw
121
+
122
+ return self
123
+
124
+ def and_item(self, value: Any) -> Self:
125
+ return self.with_item(value)
126
+
127
+ def with_item(self, value: Any) -> Self:
128
+ assert self.response.item() == value, self.response.raw
129
+
130
+ return self
131
+
132
+ def and_collection(self, values: Collection[Any]) -> Self:
133
+ return self.with_collection(values)
134
+
135
+ def with_collection(self, values: Collection[Any]) -> Self:
136
+ assert self.response.collection() == values, self.response.raw
137
+ assert self.response.count() == len(values)
138
+
139
+ return self
140
+
141
+
142
+ @dataclass(frozen=True)
143
+ class RestDispatcher(HttpDispatcher[StatusProbe]):
144
+ def create(self) -> StatusProbe:
145
+ return self.dispatch(HttpMethod.post)
146
+
147
+ def read(self) -> StatusProbe:
148
+ return self.dispatch(HttpMethod.get)
149
+
150
+ def update(self) -> StatusProbe:
151
+ return self.dispatch(HttpMethod.patch)
152
+
153
+ def delete(self) -> StatusProbe:
154
+ return self.dispatch(HttpMethod.delete)
155
+
156
+ def replace(self) -> StatusProbe:
157
+ return self.dispatch(HttpMethod.put)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "apexdevkit"
3
- version = "2.0.1"
3
+ version = "2.1.1"
4
4
  description = "Apex Development Tools for python."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -16,7 +16,7 @@ pymssql = "2.*"
16
16
  pydantic = "*"
17
17
  sentry-sdk = { extras = ["fastapi"], version = "*" }
18
18
  uvicorn = "*"
19
- pypebbles = "0.2.*"
19
+ pypebbles = "0.3.*"
20
20
 
21
21
  [tool.poetry.group.dev.dependencies]
22
22
  apexcodexpy = "0.7.1"
@@ -79,5 +79,5 @@ show_missing = true
79
79
 
80
80
  [tool.pytest]
81
81
  env = [
82
- "ECHO_SERVER=http://localhost:8080"
82
+ "ECHO_SERVER=http://localhost:8080",
83
83
  ]
@@ -1,7 +0,0 @@
1
- from apexdevkit.repository.sql.sqlite.repository import SqliteRepository
2
- from apexdevkit.repository.sql.sqlite.table import SqliteTableBuilder
3
-
4
- __all__ = [
5
- "SqliteRepository",
6
- "SqliteTableBuilder",
7
- ]
File without changes
File without changes