optimization (WIP)
This commit is contained in:
@@ -2,4 +2,5 @@ eclipse.preferences.version=1
|
||||
encoding//src/pyrestresource/__init__.py=utf-8
|
||||
encoding//src/pyrestresource/__metadata__.py=utf-8
|
||||
encoding//src/pyrestresource/rest_resource.py=utf-8
|
||||
encoding//src/pyrestresource/rest_resource_handler_walker.py=utf-8
|
||||
encoding/<project>=UTF-8
|
||||
|
||||
@@ -62,22 +62,24 @@ class RequestFactory(
|
||||
return RestRequest[RestRequestParams_DELETE](self.cls_RestRequestParams_DELETE, url, verb, data, query_string)
|
||||
raise RuntimeError("Invalid Verb")
|
||||
|
||||
def update_RestRequest(self, origin_request: RestRequest) -> RestRequest:
|
||||
def update_RestRequest(self, request: RestRequest) -> None:
|
||||
"""create an updated copy of a RestRequest object based on a different LUT_verb configuration
|
||||
Args:
|
||||
origin_request: the original request
|
||||
"""
|
||||
|
||||
# /!\ mypy seems not being able to propagate typevar to composed classes
|
||||
if origin_request.verb is rsrc_verb.GET:
|
||||
return RestRequest[RestRequestParams_GET](self.cls_RestRequestParams_GET, None, None, None, None, origin_request)
|
||||
if origin_request.verb is rsrc_verb.PUT:
|
||||
return RestRequest[RestRequestParams_PUT](self.cls_RestRequestParams_PUT, None, None, None, None, origin_request)
|
||||
if origin_request.verb is rsrc_verb.POST:
|
||||
return RestRequest[RestRequestParams_POST](self.cls_RestRequestParams_POST, None, None, None, None, origin_request)
|
||||
if origin_request.verb is rsrc_verb.DELETE:
|
||||
return RestRequest[RestRequestParams_DELETE](self.cls_RestRequestParams_DELETE, None, None, None, None, origin_request)
|
||||
raise RuntimeError("Invalid Verb")
|
||||
if request.verb is rsrc_verb.GET:
|
||||
request.update_ReqParams(self.cls_RestRequestParams_GET)
|
||||
elif request.verb is rsrc_verb.PUT:
|
||||
request.update_ReqParams(self.cls_RestRequestParams_PUT)
|
||||
elif request.verb is rsrc_verb.POST:
|
||||
request.update_ReqParams(self.cls_RestRequestParams_POST)
|
||||
elif request.verb is rsrc_verb.DELETE:
|
||||
request.update_ReqParams(self.cls_RestRequestParams_DELETE)
|
||||
else:
|
||||
raise RuntimeError("Invalid Verb")
|
||||
return
|
||||
|
||||
|
||||
class RestRequest(Generic[_T_RestRequestParams]):
|
||||
@@ -87,21 +89,22 @@ class RestRequest(Generic[_T_RestRequestParams]):
|
||||
def __init__(
|
||||
self,
|
||||
type_request_params: type[_T_RestRequestParams],
|
||||
url: Optional[str] = None,
|
||||
verb: Optional[rsrc_verb] = None,
|
||||
url: str,
|
||||
verb: rsrc_verb,
|
||||
data: Optional[dict[str, T_SupportedRESTFields]] = None,
|
||||
query_string: Optional[str] = None,
|
||||
origin_request: Optional[RestRequest] = None,
|
||||
incoming_cookie: dict[str, str] = {},
|
||||
outgoing_cookie: dict[str, str] = {},
|
||||
) -> None:
|
||||
"""class to handle a request context, that will be kept and updated while walking url parts
|
||||
|
||||
Args:
|
||||
type_request_params: type of the request param
|
||||
url: http url of the request
|
||||
verb: http verb received
|
||||
data: data associated with the request
|
||||
type_request_params: type of the request param
|
||||
origin_request: orginial request in case of updates.
|
||||
In this case, all other argument - but type_request_params - are ignored and inherited from the origin_request
|
||||
query_string: query arguments after url (eg: ?arg1=value1&arg2=value2 ...)
|
||||
"""
|
||||
|
||||
# defining all types
|
||||
@@ -113,14 +116,8 @@ class RestRequest(Generic[_T_RestRequestParams]):
|
||||
self.url_stack: list[str]
|
||||
self._saved_url_stack: list[str]
|
||||
self.url_stack_index: int
|
||||
|
||||
# = updating request from a previous one =
|
||||
if origin_request:
|
||||
self.__dict__ = origin_request.__dict__.copy()
|
||||
if type_request_params:
|
||||
self.ReqParams = type_request_params(**self._saved_url_params)
|
||||
# print("request updated")
|
||||
return
|
||||
self.incoming_cookie: dict[str, str] = incoming_cookie
|
||||
self.outgoing_cookie: dict[str, str] = outgoing_cookie
|
||||
|
||||
# = or create a fresh one =
|
||||
if url is None or verb is None or data is None:
|
||||
@@ -144,6 +141,9 @@ class RestRequest(Generic[_T_RestRequestParams]):
|
||||
self._saved_url_stack = self.url_stack.copy()
|
||||
self.url_stack_index = 0
|
||||
|
||||
def update_ReqParams(self, type_request_params: type[_T_RestRequestParams]):
|
||||
self.ReqParams = type_request_params(**self._saved_url_params)
|
||||
|
||||
def _parse_url(self, url: str) -> None:
|
||||
# remove repeated slash ('/')
|
||||
url = sub(r"\/{2,}", "/", url)
|
||||
|
||||
@@ -23,7 +23,7 @@ from typing import (
|
||||
TYPE_CHECKING,
|
||||
)
|
||||
import json
|
||||
from pydantic.fields import FieldInfo
|
||||
from pydantic.fields import FieldInfo, Field
|
||||
from pydantic import BaseModel
|
||||
|
||||
from .helpers import _JSONEncoder
|
||||
@@ -43,6 +43,8 @@ from .rest_resource_walker import (
|
||||
RestResourceWalker_Sub_RestResourceBase,
|
||||
)
|
||||
|
||||
from .rest_request import RestRequest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .rest_types import (
|
||||
T_ListIndex,
|
||||
@@ -95,34 +97,6 @@ class RestResourceWalker_Root__tree_exclude(RestResourceWalker_Root):
|
||||
]
|
||||
|
||||
|
||||
class pluginCTX:
|
||||
cookies: dict[str, str] = dict()
|
||||
|
||||
|
||||
class RestResourceWalker_Sub_RestResourceBase__init_pluginCTX(RestResourceWalker_Sub_RestResourceBase):
|
||||
_pluginCTX: pluginCTX = pluginCTX()
|
||||
|
||||
def process(self):
|
||||
# import pprint
|
||||
|
||||
# print(f"hey: {self.resource}")
|
||||
# pprint.pprint(self.resource)
|
||||
# print(type(self.resource))
|
||||
# print(self.annotation._plugins_)
|
||||
|
||||
for plugin in self.annotation._plugins_.values():
|
||||
# print("SET COOKIE")
|
||||
plugin.cookies = self._pluginCTX.cookies
|
||||
|
||||
|
||||
class RestResourceWalker_Root__init_pluginCTX(RestResourceWalker_Root):
|
||||
cls_RestResourceWalker_Sub = [
|
||||
RestResourceWalker_Sub_T_Dict,
|
||||
RestResourceWalker_Sub_RestFields,
|
||||
RestResourceWalker_Sub_RestResourceBase__init_pluginCTX,
|
||||
]
|
||||
|
||||
|
||||
class RestResourceWalker_Sub_T_Dict__tree_init(RestResourceWalker_Sub_T_Dict):
|
||||
def process(self) -> None:
|
||||
datatype = get_args(self.annotation)
|
||||
@@ -139,6 +113,9 @@ class RestResourceWalker_Sub_T_Dict__tree_init(RestResourceWalker_Sub_T_Dict):
|
||||
self.parent.annotation._dict_value_type_[self.resource_name] = datatype[1] # pylint: disable=protected-access
|
||||
self.parent.annotation._model_dump_excluded_[self.resource_name] = True # pylint: disable=protected-access
|
||||
|
||||
self.resource.exclude = True
|
||||
self.parent.resource.model_rebuild(force=True)
|
||||
|
||||
if (
|
||||
isinstance(self.resource, FieldInfo)
|
||||
and self.resource.json_schema_extra is not None
|
||||
@@ -158,11 +135,19 @@ class RestResourceWalker_Sub_T_Dict__tree_init(RestResourceWalker_Sub_T_Dict):
|
||||
class RestResourceWalker_Sub_RestFields__tree_init(RestResourceWalker_Sub_RestFields):
|
||||
def process(self) -> None:
|
||||
if self.parent is not None and isinstance(self.parent, RestResourceWalker_Sub_RestResourceBase):
|
||||
import pprint
|
||||
|
||||
# print("1aaaaaaaaaa")
|
||||
# pprint.pprint(self.resource.json_schema_extra)
|
||||
# pprint.pprint(self.annotation)
|
||||
# pprint.pprint(self.resource.exclude)
|
||||
if (
|
||||
isinstance(self.resource, FieldInfo)
|
||||
and self.resource.json_schema_extra is not None
|
||||
and type(self.resource.json_schema_extra) is dict
|
||||
):
|
||||
# print("aaaaaaaaaa")
|
||||
|
||||
if "primary_key" in self.resource.json_schema_extra and self.resource.json_schema_extra["primary_key"] is True:
|
||||
if self.parent.annotation._primary_key_ is not None:
|
||||
raise RuntimeError(f"Only one primary key is allowed {self.parent.resource_name}.{self.resource_name}")
|
||||
@@ -190,6 +175,8 @@ class RestResourceWalker_Sub_RestResourceBase__tree_init(RestResourceWalker_Sub_
|
||||
# preprocessing types / structure
|
||||
if self.parent is not None and isinstance(self.parent, RestResourceWalker_Sub_RestResourceBase):
|
||||
self.parent.annotation._model_dump_excluded_[self.resource_name] = True
|
||||
self.resource.exclude = True
|
||||
self.parent.resource.model_rebuild(force=True)
|
||||
|
||||
if (
|
||||
isinstance(self.resource, FieldInfo)
|
||||
@@ -229,6 +216,7 @@ class RestResourceBase(ABC, BaseModel, validate_assignment=True):
|
||||
ResourcePlugin_field | ResourcePlugin_RestResourceBase | ResourcePlugin_dict,
|
||||
]
|
||||
] = {}
|
||||
_request: Optional[RestRequest] = None
|
||||
|
||||
def update(self, **new_data):
|
||||
for field, value in new_data.items():
|
||||
@@ -263,12 +251,13 @@ class RestResourceBase(ABC, BaseModel, validate_assignment=True):
|
||||
body = await self.read_body(receive)
|
||||
verb = rsrc_verb[scope["method"]]
|
||||
|
||||
type(self)._resp_cookies = dict()
|
||||
|
||||
self._request = None
|
||||
result = self.process_request(
|
||||
scope["path"], rsrc_verb[scope["method"]], body.decode("utf-8"), scope["query_string"].decode("utf-8")
|
||||
)
|
||||
|
||||
assert self._request != None
|
||||
|
||||
status = 200
|
||||
if verb in (rsrc_verb.POST, rsrc_verb.PUT):
|
||||
status = 201
|
||||
@@ -281,7 +270,7 @@ class RestResourceBase(ABC, BaseModel, validate_assignment=True):
|
||||
],
|
||||
}
|
||||
|
||||
for name, value in type(self)._resp_cookies.items():
|
||||
for name, value in self._request.outgoing_cookie.items():
|
||||
header_resp["headers"].append(["Set-Cookie", f"{name}={value}"])
|
||||
|
||||
# print("----SENT HEADER ---")
|
||||
@@ -315,10 +304,9 @@ class RestResourceBase(ABC, BaseModel, validate_assignment=True):
|
||||
if data_json:
|
||||
data = json.loads(data_json)
|
||||
|
||||
RestResourceWalker_Sub_RestResourceBase__init_pluginCTX._pluginCTX.cookies = type(self)._resp_cookies
|
||||
RestResourceWalker_Root__init_pluginCTX(self).process()
|
||||
|
||||
ressource: ResourceHandler = ResourceHandler_RestResourceBase(self, url, verb, data, query_string)
|
||||
self._request = ressource.get_request()
|
||||
|
||||
result = ressource.process_verb()
|
||||
|
||||
# print("OOO")
|
||||
@@ -326,10 +314,11 @@ class RestResourceBase(ABC, BaseModel, validate_assignment=True):
|
||||
# print("OOO2")
|
||||
|
||||
if isinstance(result, RestResourceBase):
|
||||
exclude: Optional[dict[str, bool]] = None
|
||||
raw_exclude = RestResourceWalker_Root__tree_exclude(result).process()
|
||||
exclude = next(iter(raw_exclude.values()))
|
||||
return json.dumps(result.model_dump(mode="json", exclude=exclude))
|
||||
# exclude: Optional[dict[str, bool]] = None
|
||||
# raw_exclude = RestResourceWalker_Root__tree_exclude(result).process()
|
||||
# exclude = next(iter(raw_exclude.values()))
|
||||
# return json.dumps(result.model_dump(mode="json", exclude=exclude))
|
||||
return json.dumps(result.model_dump(mode="json"))
|
||||
|
||||
if result is not None:
|
||||
return json.dumps(result, cls=_JSONEncoder)
|
||||
|
||||
@@ -95,7 +95,9 @@ class ResourceHandler(
|
||||
self.req: RestRequest
|
||||
if prev_handler is not None:
|
||||
self.prev_handler = prev_handler
|
||||
self.req = self._request_factory.update_RestRequest(self.prev_handler.req)
|
||||
self.req = prev_handler.get_request()
|
||||
self._request_factory.update_RestRequest(self.req)
|
||||
|
||||
elif None in [url, verb]:
|
||||
raise RuntimeError("if req not set, url,verb must be setted")
|
||||
else:
|
||||
@@ -129,6 +131,9 @@ class ResourceHandler(
|
||||
cls._ar_resource_handler_cls_.append(other_cls)
|
||||
return other_cls
|
||||
|
||||
def get_request(self) -> RestRequest:
|
||||
return self.req
|
||||
|
||||
def process_verb(
|
||||
self,
|
||||
) -> Optional[_T_Resource | T_DictKey | list[T_DictKey]]:
|
||||
@@ -455,10 +460,14 @@ class ResourceHandler_RestResourceBase(
|
||||
if self.req.get_resource_origin(0) == "/":
|
||||
return
|
||||
|
||||
if (
|
||||
self.req.get_resource_origin(0) not in self.resource.model_fields
|
||||
or self.resource.model_fields[self.req.get_resource_origin(0)].exclude is True
|
||||
):
|
||||
# print("======")
|
||||
# print(self.req.get_resource_origin(0))
|
||||
# print(len(self.req.get_url_stack()))
|
||||
# print(self.resource._model_dump_excluded_)
|
||||
# print(type(self.resource))
|
||||
# print(self.resource.exclude)
|
||||
|
||||
if self.req.get_resource_origin(0) not in self.resource.model_fields:
|
||||
raise RuntimeError(f"Unknown or not allowed field access detected: {self.req.get_url_stack()}")
|
||||
|
||||
def _handle_process_get(self, params) -> RestResourceBase:
|
||||
@@ -471,11 +480,11 @@ class ResourceHandler_RestResourceBase(
|
||||
for key, attr in self.resource.model_fields.items():
|
||||
if key in self.resource._plugins_:
|
||||
if isinstance(self.resource._plugins_[key], ResourcePlugin_field):
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_field, self.resource._plugins_[key])
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_field, self.resource._plugins_[key](self.req))
|
||||
value = getattr(self.resource, key)
|
||||
setattr(self.resource, key, plugin_field.handle_field_get(value, params))
|
||||
elif isinstance(self.resource._plugins_[key], ResourcePlugin_RestResourceBase):
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_RestResourceBase, self.resource._plugins_[key])
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_RestResourceBase, self.resource._plugins_[key](self.req))
|
||||
value = getattr(self.resource, key)
|
||||
setattr(self.resource, key, plugin_field.handle_resource_get(value, params))
|
||||
|
||||
@@ -496,14 +505,14 @@ class ResourceHandler_RestResourceBase(
|
||||
if isinstance(self.resource._plugins_[key], ResourcePlugin_field):
|
||||
plugin_rsrc: ResourcePlugin_RestResourceBase = cast(
|
||||
ResourcePlugin_RestResourceBase,
|
||||
self.resource._plugins_[key],
|
||||
self.resource._plugins_[key](self.req),
|
||||
)
|
||||
value = plugin_rsrc.handle_field_get(value, params)
|
||||
|
||||
elif isinstance(self.resource._plugins_[key], ResourcePlugin_RestResourceBase):
|
||||
plugin_rsrc: ResourcePlugin_RestResourceBase = cast(
|
||||
ResourcePlugin_RestResourceBase,
|
||||
self.resource._plugins_[key],
|
||||
self.resource._plugins_[key](self.req),
|
||||
)
|
||||
value = plugin_rsrc.handle_resource_get(value, params)
|
||||
|
||||
@@ -523,7 +532,7 @@ class ResourceHandler_RestResourceBase(
|
||||
for key, attr in _new_resrc.model_fields.items():
|
||||
if key in _new_resrc._plugins_:
|
||||
if isinstance(_new_resrc._plugins_[key], ResourcePlugin_field):
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_field, _new_resrc._plugins_[key])
|
||||
plugin_field: ResourcePlugin_field = cast(ResourcePlugin_field, _new_resrc._plugins_[key](self.req))
|
||||
value = getattr(_new_resrc, key)
|
||||
setattr(_new_resrc, key, plugin_field.handle_field_put(value, params))
|
||||
|
||||
@@ -539,7 +548,7 @@ class ResourceHandler_RestResourceBase(
|
||||
if key in self.prev_handler.prev_handler.resource._plugins_:
|
||||
plugin_rsrc: ResourcePlugin_RestResourceBase = cast(
|
||||
ResourcePlugin_RestResourceBase,
|
||||
self.prev_handler.prev_handler.resource._plugins_[key],
|
||||
self.prev_handler.prev_handler.resource._plugins_[key](self.req),
|
||||
)
|
||||
_new_resrc = plugin_rsrc.handle_dict_elem_put(_new_resrc, params)
|
||||
# element is within a RestResourceBase
|
||||
@@ -548,7 +557,7 @@ class ResourceHandler_RestResourceBase(
|
||||
if key in self.prev_handler.resource._plugins_:
|
||||
plugin_rsrc: ResourcePlugin_RestResourceBase = cast(
|
||||
ResourcePlugin_RestResourceBase,
|
||||
self.prev_handler.resource._plugins_[key],
|
||||
self.prev_handler.resource._plugins_[key](self.req),
|
||||
)
|
||||
_new_resrc = plugin_rsrc.handle_resource_put(_new_resrc, params)
|
||||
|
||||
@@ -597,7 +606,7 @@ class ResourceHandler_simple(
|
||||
if self.req.get_resource_origin(1) in self.prev_handler.resource._plugins_:
|
||||
plugin_simple: ResourcePlugin_field = cast(
|
||||
ResourcePlugin_field,
|
||||
self.prev_handler.resource._plugins_[self.req.get_resource_origin(1)],
|
||||
self.prev_handler.resource._plugins_[self.req.get_resource_origin(1)](self.req),
|
||||
)
|
||||
return plugin_simple.handle_field_get(self.resource, params)
|
||||
|
||||
@@ -616,7 +625,7 @@ class ResourceHandler_simple(
|
||||
# print("PLUGIN FOUND")
|
||||
plugin_simple: ResourcePlugin_field = cast(
|
||||
ResourcePlugin_field,
|
||||
self.prev_handler.resource._plugins_[self.req.get_resource_origin(1)],
|
||||
self.prev_handler.resource._plugins_[self.req.get_resource_origin(1)](self.req),
|
||||
)
|
||||
# print(value)
|
||||
value = plugin_simple.handle_field_put(value, params)
|
||||
|
||||
@@ -10,6 +10,7 @@ from .rest_types import (
|
||||
TV_RestResourceBase,
|
||||
)
|
||||
|
||||
from .rest_request import RestRequest
|
||||
|
||||
if TYPE_CHECKING or True:
|
||||
from .rest_request_opt import (
|
||||
@@ -26,15 +27,16 @@ if TYPE_CHECKING or True:
|
||||
|
||||
|
||||
class ResourcePlugin(Protocol):
|
||||
cookies: dict[str, str] = dict()
|
||||
def __init__(self, request: RestRequest) -> None:
|
||||
self.request: RestRequest = request
|
||||
|
||||
def set_cookie(self, name: str, value: str):
|
||||
def set_resp_cookie(self, name: str, value: str):
|
||||
# print("AAA")
|
||||
# print(name)
|
||||
# print(value)
|
||||
# print(self.cookies)
|
||||
# print(type(self.cookies))
|
||||
self.cookies[name] = value
|
||||
self.request.outgoing_cookie[name] = value
|
||||
|
||||
|
||||
@runtime_checkable
|
||||
|
||||
@@ -55,12 +55,13 @@ class RestResourceWalker_Sub(ABC, Generic[TV_RestResourceWalkerFutureResult]):
|
||||
resource_name: str,
|
||||
resource: FieldInfo | Type["RestResourceBase"],
|
||||
parent: Optional[RestResourceWalker_Sub] = None,
|
||||
argument: Optional[any] = None,
|
||||
) -> Optional[RestResourceWalker_Sub]:
|
||||
for sub in subs:
|
||||
_is_valid, _anno, _optional = sub.check_type(resource)
|
||||
|
||||
if _is_valid is True:
|
||||
return sub(resource_name, resource, parent, _anno, _optional)
|
||||
return sub(resource_name, resource, parent, _anno, _optional, argument)
|
||||
raise RuntimeError(f"Incompatible Field Found: {type(resource).__name__}")
|
||||
return None
|
||||
|
||||
@@ -70,8 +71,10 @@ class RestResourceWalker_Sub(ABC, Generic[TV_RestResourceWalkerFutureResult]):
|
||||
resource: FieldInfo | Type["RestResourceBase"],
|
||||
parent: Optional[RestResourceWalker_Sub] = None,
|
||||
annotation: Optional[type["RestResourceBase"]] = None,
|
||||
optional: Optional[bool] = None,
|
||||
_optional: Optional[bool] = None,
|
||||
argument: Optional[any] = None,
|
||||
):
|
||||
self.argument: any = argument
|
||||
self.resource_name: str = resource_name
|
||||
self.resource: FieldInfo | Type["RestResourceBase"] = resource
|
||||
self.parent: Optional[RestResourceWalker_Sub] = parent
|
||||
@@ -84,11 +87,11 @@ class RestResourceWalker_Sub(ABC, Generic[TV_RestResourceWalkerFutureResult]):
|
||||
|
||||
self.annotation: type["RestResourceBase"]
|
||||
self.optional: bool
|
||||
if annotation is None or optional is None:
|
||||
if annotation is None or _optional is None:
|
||||
self.annotation, self.optional = self.ProcessAnnotation(resource)
|
||||
else:
|
||||
self.annotation = annotation
|
||||
self.optional = optional
|
||||
self.optional = _optional
|
||||
|
||||
if self.annotation is None:
|
||||
raise RuntimeError("Only annotated types are allowed in RestResourceBase derived classes")
|
||||
@@ -120,10 +123,6 @@ class RestResourceWalker_Sub(ABC, Generic[TV_RestResourceWalkerFutureResult]):
|
||||
print("-------------------")
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def init_sub(cls, walker: RestResourceWalker_Root) -> None:
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_future(self) -> Optional[RestResourceWalkerFutureResult]:
|
||||
return self.future_result
|
||||
@@ -238,6 +237,7 @@ class RestResourceWalker_Root:
|
||||
]
|
||||
|
||||
def __init__(self, resource: "RestResourceBase" | Type["RestResourceBase"]) -> None:
|
||||
self.subwalker_argument: any = None
|
||||
from .rest_resource import RestResourceBase
|
||||
|
||||
self.resource: Type["RestResourceBase"]
|
||||
@@ -246,14 +246,11 @@ class RestResourceWalker_Root:
|
||||
else:
|
||||
self.resource = resource
|
||||
|
||||
def process(self, deep_limit: Optional[int] = None) -> Optional[TV_RestResourceWalkerFutureResult]:
|
||||
def process(self, argument: Optional[any] = None, deep_limit: Optional[int] = None) -> Optional[TV_RestResourceWalkerFutureResult]:
|
||||
current_deep: int = 0
|
||||
for cls_Sub in self.cls_RestResourceWalker_Sub:
|
||||
_self = self
|
||||
cls_Sub.init_sub(_self)
|
||||
|
||||
sub_walker_initial: Optional[RestResourceWalker_Sub] = RestResourceWalker_Sub.get(
|
||||
self.cls_RestResourceWalker_Sub, "/", self.resource, None
|
||||
self.cls_RestResourceWalker_Sub, "/", self.resource, None, argument
|
||||
)
|
||||
|
||||
if sub_walker_initial is not None:
|
||||
@@ -270,10 +267,7 @@ class RestResourceWalker_Root:
|
||||
new_resource_list = []
|
||||
for resource_name, resource, parent_sub_walker in resource_list:
|
||||
sub_walker = RestResourceWalker_Sub.get(
|
||||
self.cls_RestResourceWalker_Sub,
|
||||
resource_name,
|
||||
resource,
|
||||
parent_sub_walker,
|
||||
self.cls_RestResourceWalker_Sub, resource_name, resource, parent_sub_walker, argument
|
||||
)
|
||||
if sub_walker is not None:
|
||||
sub_walker.process()
|
||||
|
||||
@@ -65,7 +65,7 @@ def init_classes():
|
||||
if _UserLogin.username == resource.username and _UserLogin.secret == resource.secret:
|
||||
print("user connected")
|
||||
_UserLogin.token = token_hex(16)
|
||||
self.set_cookie("test", _UserLogin.token)
|
||||
self.set_resp_cookie("test", _UserLogin.token)
|
||||
print(f"generated token: {_UserLogin.token}")
|
||||
return resource
|
||||
print("login NOT found")
|
||||
@@ -84,7 +84,7 @@ def init_classes():
|
||||
class RootApp(RestResourceBase):
|
||||
login: Login = Field(
|
||||
default=Login(),
|
||||
plugin=ResourcePlugin_Login(),
|
||||
plugin=ResourcePlugin_Login,
|
||||
)
|
||||
|
||||
# this add the classes to globals to allow using them later on
|
||||
@@ -155,8 +155,8 @@ class Test_RestAPI_LOGIN_Web(unittest.TestCase):
|
||||
self.assertEqual(response.status_code, 201)
|
||||
|
||||
response = s.get(f"http://{ip}:{port}/login")
|
||||
response = s.get(f"http://{ip}:{port}/login")
|
||||
response = s.get(f"http://{ip}:{port}/login")
|
||||
|
||||
response = s.get(f"http://{ip}:{port}/")
|
||||
|
||||
finally:
|
||||
proc.terminate()
|
||||
|
||||
@@ -47,13 +47,13 @@ def init_classes():
|
||||
class Info_get(RestResourceBase):
|
||||
# test plugin injection within annotation
|
||||
# + test plugin on a simple field
|
||||
version: Annotated[str, Field(plugin=ResourcePlugin_version_get())]
|
||||
version: Annotated[str, Field(plugin=ResourcePlugin_version_get)]
|
||||
api_version: str
|
||||
|
||||
class Info_put(RestResourceBase):
|
||||
# test plugin injection within annotation
|
||||
# + test plugin on a simple field
|
||||
version: Annotated[str, Field(plugin=ResourcePlugin_version_put())]
|
||||
version: Annotated[str, Field(plugin=ResourcePlugin_version_put)]
|
||||
api_version: str
|
||||
|
||||
@register_rest_rootpoint
|
||||
@@ -62,7 +62,7 @@ def init_classes():
|
||||
# + test plugin on a RestResourceBase field
|
||||
info: Info_get = Field(
|
||||
default=Info_get(version="0.0.1", api_version="0.0.2"),
|
||||
plugin=ResourcePlugin_Info(),
|
||||
plugin=ResourcePlugin_Info,
|
||||
)
|
||||
info_put: Info_put = Field(
|
||||
default=Info_put(version="0.0.1", api_version="0.0.2"),
|
||||
@@ -83,7 +83,7 @@ def init_bad_plugin1():
|
||||
return resource
|
||||
|
||||
class TestResource(RestResourceBase):
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource())]
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource)]
|
||||
|
||||
@register_rest_rootpoint
|
||||
class RootApp2(RestResourceBase):
|
||||
@@ -99,7 +99,7 @@ def init_bad_plugin2():
|
||||
return resource
|
||||
|
||||
class TestResource(RestResourceBase):
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource())]
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource)]
|
||||
|
||||
@register_rest_rootpoint
|
||||
class RootApp2(RestResourceBase):
|
||||
@@ -114,7 +114,7 @@ def init_bad_plugin3():
|
||||
pass
|
||||
|
||||
class TestResource(RestResourceBase):
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource())]
|
||||
tetvaluestr: Annotated[str, Field(plugin=ResourcePlugin_TestResource)]
|
||||
|
||||
@register_rest_rootpoint
|
||||
class RootApp2(RestResourceBase):
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import annotations
|
||||
import unittest
|
||||
|
||||
from typing import Annotated, Optional
|
||||
from typing import Optional, cast
|
||||
|
||||
from os import chdir
|
||||
from pathlib import Path
|
||||
@@ -28,50 +28,39 @@ chdir(testdir_path.parent.resolve())
|
||||
|
||||
|
||||
class RestResourceWalker_Sub_T_Dict_TEST_Print(RestResourceWalker_Sub_T_Dict):
|
||||
counter: dict[str, int] = {}
|
||||
|
||||
@classmethod
|
||||
def init_sub(cls, walker: RestResourceWalker_Root) -> None:
|
||||
cls.counter = {}
|
||||
cls_counter: dict[str, int] = {}
|
||||
|
||||
def process(self) -> None:
|
||||
if self.resource_name not in self.counter:
|
||||
self.counter[self.resource_name] = 0
|
||||
self.counter[self.resource_name] = self.counter[self.resource_name] + 1
|
||||
counter = self.cls_counter
|
||||
if self.resource_name not in counter:
|
||||
counter[self.resource_name] = 0
|
||||
counter[self.resource_name] = counter[self.resource_name] + 1
|
||||
|
||||
print(f"DICT {self.resource_name} {self.counter[self.resource_name]}")
|
||||
print(f"DICT {self.resource_name} {counter[self.resource_name]}")
|
||||
|
||||
|
||||
class RestResourceWalker_Sub_RestFields_TEST_Print(RestResourceWalker_Sub_RestFields):
|
||||
counter: dict[str, int] = {}
|
||||
|
||||
@classmethod
|
||||
def init_sub(cls, walker: RestResourceWalker_Root) -> None:
|
||||
cls.counter = {}
|
||||
cls_counter: dict[str, int] = {}
|
||||
|
||||
def process(self) -> None:
|
||||
if self.resource_name not in self.counter:
|
||||
self.counter[self.resource_name] = 0
|
||||
self.counter[self.resource_name] = self.counter[self.resource_name] + 1
|
||||
counter = self.cls_counter
|
||||
if self.resource_name not in counter:
|
||||
counter[self.resource_name] = 0
|
||||
counter[self.resource_name] = counter[self.resource_name] + 1
|
||||
|
||||
print(f"FIELD {self.resource_name} {self.counter[self.resource_name]}")
|
||||
print(f"FIELD {self.resource_name} {counter[self.resource_name]}")
|
||||
|
||||
|
||||
class RestResourceWalker_Sub_RestResourceBase_TEST_Print(
|
||||
RestResourceWalker_Sub_RestResourceBase
|
||||
):
|
||||
counter: dict[str, int] = {}
|
||||
|
||||
@classmethod
|
||||
def init_sub(cls, walker: RestResourceWalker_Root) -> None:
|
||||
cls.counter = {}
|
||||
class RestResourceWalker_Sub_RestResourceBase_TEST_Print(RestResourceWalker_Sub_RestResourceBase):
|
||||
cls_counter: dict[str, int] = {}
|
||||
|
||||
def process(self) -> None:
|
||||
if self.resource_name not in self.counter:
|
||||
self.counter[self.resource_name] = 0
|
||||
self.counter[self.resource_name] = self.counter[self.resource_name] + 1
|
||||
counter = self.cls_counter
|
||||
if self.resource_name not in counter:
|
||||
counter[self.resource_name] = 0
|
||||
counter[self.resource_name] = counter[self.resource_name] + 1
|
||||
|
||||
print(f"RestResource {self.resource_name} {self.counter[self.resource_name]}")
|
||||
print(f"RestResource {self.resource_name} {counter[self.resource_name]}")
|
||||
|
||||
|
||||
class RestResourceWalker_Root_TEST_Print(RestResourceWalker_Root):
|
||||
@@ -114,11 +103,12 @@ class Test_Walker(unittest.TestCase):
|
||||
init_classes()
|
||||
|
||||
def test_walk_class(self):
|
||||
RestResourceWalker_Sub_T_Dict_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestFields_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestResourceBase_TEST_Print.cls_counter = {}
|
||||
test = RestResourceWalker_Root_TEST_Print(RootApp)
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(
|
||||
StringIO()
|
||||
) as capted_stderr:
|
||||
test.process()
|
||||
with redirect_stdout(StringIO()) as capted_stdout:
|
||||
test.process({})
|
||||
self.assertIn("RestResource info 1", capted_stdout.getvalue())
|
||||
self.assertIn("RestResource info2 1", capted_stdout.getvalue())
|
||||
self.assertIn("DICT peoples 1", capted_stdout.getvalue())
|
||||
@@ -133,12 +123,13 @@ class Test_Walker(unittest.TestCase):
|
||||
self.assertIn("FIELD last_name 1", capted_stdout.getvalue())
|
||||
|
||||
def test_walk_obj(self):
|
||||
RestResourceWalker_Sub_T_Dict_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestFields_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestResourceBase_TEST_Print.cls_counter = {}
|
||||
instRootApp = RootApp()
|
||||
test = RestResourceWalker_Root_TEST_Print(instRootApp)
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(
|
||||
StringIO()
|
||||
) as capted_stderr:
|
||||
test.process()
|
||||
with redirect_stdout(StringIO()) as capted_stdout:
|
||||
test.process({})
|
||||
self.assertIn("RestResource info 1", capted_stdout.getvalue())
|
||||
self.assertIn("RestResource info2 1", capted_stdout.getvalue())
|
||||
self.assertIn("DICT peoples 1", capted_stdout.getvalue())
|
||||
@@ -153,11 +144,12 @@ class Test_Walker(unittest.TestCase):
|
||||
self.assertIn("FIELD last_name 1", capted_stdout.getvalue())
|
||||
|
||||
def test_walk_obj_nested_RestResource(self):
|
||||
RestResourceWalker_Sub_T_Dict_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestFields_TEST_Print.cls_counter = {}
|
||||
RestResourceWalker_Sub_RestResourceBase_TEST_Print.cls_counter = {}
|
||||
instRootApp = RootApp()
|
||||
test = RestResourceWalker_Root_TEST_Print(instRootApp.info)
|
||||
with redirect_stdout(StringIO()) as capted_stdout, redirect_stderr(
|
||||
StringIO()
|
||||
) as capted_stderr:
|
||||
test.process()
|
||||
with redirect_stdout(StringIO()) as capted_stdout:
|
||||
test.process({})
|
||||
self.assertIn("FIELD version 1", capted_stdout.getvalue())
|
||||
self.assertIn("FIELD api_version 1", capted_stdout.getvalue())
|
||||
|
||||
Reference in New Issue
Block a user