apexdevkit 1.2.3__tar.gz → 1.3.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.
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/PKG-INFO +1 -1
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/router.py +21 -23
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/schema.py +42 -25
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/pyproject.toml +1 -1
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/LICENSE +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/README.md +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/annotation/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/annotation/deprecate.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/error.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/builder.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/dependable.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/docs.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/response.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/fastapi/service.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/fake.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/fluent.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/httpx.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/json.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/http/url.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/py.typed +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/repository/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/repository/connector.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/repository/database.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/repository/in_memory.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/repository/interface.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/testing/__init__.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/testing/database.py +0 -0
- {apexdevkit-1.2.3 → apexdevkit-1.3.1}/apexdevkit/testing/rest.py +0 -0
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
from dataclasses import dataclass, field
|
|
2
|
+
from functools import cached_property
|
|
2
3
|
from typing import Annotated, Any, Iterable, Self, TypeVar
|
|
3
4
|
|
|
4
5
|
from fastapi import APIRouter, Depends
|
|
5
6
|
from fastapi.responses import JSONResponse
|
|
6
7
|
|
|
7
8
|
from apexdevkit.error import DoesNotExistError, ExistsError
|
|
8
|
-
from apexdevkit.fastapi.schema import RestfulSchema
|
|
9
|
+
from apexdevkit.fastapi.schema import DataclassFields, RestfulSchema, SchemaFields
|
|
9
10
|
from apexdevkit.fastapi.service import RawCollection, RawItem, RestfulService
|
|
10
11
|
from apexdevkit.testing import RestfulName
|
|
11
12
|
|
|
@@ -16,10 +17,6 @@ _Response = JSONResponse | dict[str, Any]
|
|
|
16
17
|
class RestfulResponse:
|
|
17
18
|
name: RestfulName
|
|
18
19
|
|
|
19
|
-
@classmethod
|
|
20
|
-
def from_dataclass(cls, value: type[Any]) -> "RestfulResponse":
|
|
21
|
-
return cls(name=RestfulName(value.__name__.lower()))
|
|
22
|
-
|
|
23
20
|
def _response(self, code: int, data: Any, error: str = "") -> dict[str, Any]:
|
|
24
21
|
content: dict[str, Any] = {"code": code, "status": "success"}
|
|
25
22
|
|
|
@@ -76,32 +73,33 @@ T = TypeVar("T")
|
|
|
76
73
|
|
|
77
74
|
@dataclass
|
|
78
75
|
class RestfulRouter:
|
|
79
|
-
|
|
80
|
-
response: RestfulResponse = field(init=False)
|
|
81
|
-
service: RestfulService = field(init=False)
|
|
76
|
+
service: RestfulService
|
|
82
77
|
|
|
83
|
-
router: APIRouter = field(
|
|
78
|
+
router: APIRouter = field(default_factory=APIRouter)
|
|
84
79
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return (
|
|
88
|
-
cls()
|
|
89
|
-
.with_schema(RestfulSchema.from_dataclass(value))
|
|
90
|
-
.with_response(RestfulResponse.from_dataclass(value))
|
|
91
|
-
)
|
|
80
|
+
name: RestfulName = field(init=False)
|
|
81
|
+
fields: SchemaFields = field(init=False)
|
|
92
82
|
|
|
93
|
-
|
|
94
|
-
|
|
83
|
+
@cached_property
|
|
84
|
+
def response(self) -> RestfulResponse:
|
|
85
|
+
return RestfulResponse(name=self.name)
|
|
95
86
|
|
|
96
|
-
|
|
87
|
+
@cached_property
|
|
88
|
+
def schema(self) -> RestfulSchema:
|
|
89
|
+
return RestfulSchema(name=self.name, fields=self.fields)
|
|
90
|
+
|
|
91
|
+
def with_dataclass(self, value: Any) -> Self:
|
|
92
|
+
return self.with_name(RestfulName(value.__name__.lower())).with_fields(
|
|
93
|
+
DataclassFields(value)
|
|
94
|
+
)
|
|
97
95
|
|
|
98
|
-
def
|
|
99
|
-
self.
|
|
96
|
+
def with_name(self, value: RestfulName) -> Self:
|
|
97
|
+
self.name = value
|
|
100
98
|
|
|
101
99
|
return self
|
|
102
100
|
|
|
103
|
-
def
|
|
104
|
-
self.
|
|
101
|
+
def with_fields(self, value: SchemaFields) -> Self:
|
|
102
|
+
self.fields = value
|
|
105
103
|
|
|
106
104
|
return self
|
|
107
105
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
from
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from functools import cached_property
|
|
2
4
|
from typing import Any, Callable, Iterable, List
|
|
3
5
|
|
|
4
6
|
from pydantic import BaseModel, create_model
|
|
@@ -7,17 +9,35 @@ from apexdevkit.http import JsonDict
|
|
|
7
9
|
from apexdevkit.testing import RestfulName
|
|
8
10
|
|
|
9
11
|
|
|
12
|
+
class SchemaFields(ABC):
|
|
13
|
+
def writable(self) -> JsonDict:
|
|
14
|
+
return self.editable()
|
|
15
|
+
|
|
16
|
+
def editable(self) -> JsonDict:
|
|
17
|
+
return self.readable().drop("id")
|
|
18
|
+
|
|
19
|
+
@abstractmethod
|
|
20
|
+
def readable(self) -> JsonDict:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class DataclassFields(SchemaFields):
|
|
26
|
+
source: Any
|
|
27
|
+
|
|
28
|
+
def readable(self) -> JsonDict:
|
|
29
|
+
return JsonDict(self.source.__annotations__)
|
|
30
|
+
|
|
31
|
+
|
|
10
32
|
@dataclass
|
|
11
33
|
class RestfulSchema:
|
|
12
34
|
name: RestfulName
|
|
13
|
-
fields:
|
|
14
|
-
|
|
15
|
-
schemas: dict[str, type[BaseModel]] = field(default_factory=dict)
|
|
35
|
+
fields: SchemaFields
|
|
16
36
|
|
|
17
37
|
def __post_init__(self) -> None:
|
|
18
|
-
schema = self._schema_for("", self.fields)
|
|
19
|
-
create_schema = self._schema_for("Create", self.fields.
|
|
20
|
-
self._schema_for("Update", self.fields.
|
|
38
|
+
schema = self._schema_for("", self.fields.readable())
|
|
39
|
+
create_schema = self._schema_for("Create", self.fields.writable())
|
|
40
|
+
self._schema_for("Update", self.fields.editable())
|
|
21
41
|
|
|
22
42
|
self._schema_for(
|
|
23
43
|
"Item",
|
|
@@ -37,12 +57,21 @@ class RestfulSchema:
|
|
|
37
57
|
JsonDict({self.name.plural: List[schema]}),
|
|
38
58
|
)
|
|
39
59
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
def _schema_for(self, action: str, fields: dict[str, Any]) -> type[BaseModel]:
|
|
61
|
+
if action not in self.schemas:
|
|
62
|
+
self.schemas[action] = create_model(
|
|
63
|
+
self.name.singular.capitalize() + action,
|
|
64
|
+
**{
|
|
65
|
+
field_name: (field_type, ...)
|
|
66
|
+
for field_name, field_type in fields.items()
|
|
67
|
+
},
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
return self.schemas[action]
|
|
71
|
+
|
|
72
|
+
@cached_property
|
|
73
|
+
def schemas(self) -> dict[str, type[BaseModel]]:
|
|
74
|
+
return {}
|
|
46
75
|
|
|
47
76
|
def for_no_data(self) -> type[BaseModel]:
|
|
48
77
|
class NoData(BaseModel):
|
|
@@ -102,15 +131,3 @@ class RestfulSchema:
|
|
|
102
131
|
return [dict(item) for item in request.model_dump()[self.name.plural]]
|
|
103
132
|
|
|
104
133
|
return _
|
|
105
|
-
|
|
106
|
-
def _schema_for(self, action: str, fields: dict[str, Any]) -> type[BaseModel]:
|
|
107
|
-
if action not in self.schemas:
|
|
108
|
-
self.schemas[action] = create_model(
|
|
109
|
-
self.name.singular.capitalize() + action,
|
|
110
|
-
**{
|
|
111
|
-
field_name: (field_type, ...)
|
|
112
|
-
for field_name, field_type in fields.items()
|
|
113
|
-
},
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
return self.schemas[action]
|
|
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
|