userver: en/testsuite/mockserver/magicargs.py Source File
Loading...
Searching...
No Matches
magicargs.py
1import typing
2
3import aiohttp.web
4
5from testsuite.utils import callinfo, http
6
7
8def magic_arg(func):
9 func.need_wrapped_request = False
10 return func
11
12
13def magic_arg_wrapped(func):
14 func.need_wrapped_request = True
15 return func
16
17
18@magic_arg_wrapped
19def arg_body_json(request: http.Request):
20 return request.json
21
22
23@magic_arg_wrapped
24def arg_body_binary(request: http.Request):
25 return request.get_data()
26
27
28@magic_arg_wrapped
29def arg_form(request: http.Request):
30 return request.form
31
32
33@magic_arg
34def arg_cookies(request: aiohttp.web.BaseRequest):
35 return request.cookies
36
37
38@magic_arg
39def arg_method(request: aiohttp.web.BaseRequest):
40 return request.method
41
42
43@magic_arg
44def arg_path(request: aiohttp.web.BaseRequest):
45 return request.path
46
47
48@magic_arg
49def arg_headers(request: aiohttp.web.BaseRequest):
50 return request.headers
51
52
53@magic_arg
54def arg_query(request: aiohttp.web.BaseRequest):
55 return request.query
56
57
58@magic_arg
59def arg_content_type(request: aiohttp.web.BaseRequest):
60 return request.content_type
61
62
64 magic_args_handlers = {
65 'body_binary': arg_body_binary,
66 'body_json': arg_body_json,
67 'content_type': arg_content_type,
68 'cookies': arg_cookies,
69 'form': arg_form,
70 'headers': arg_headers,
71 'method': arg_method,
72 'path': arg_path,
73 'query': arg_query,
74 }
75 has_request = False
76
77 def __init__(self, func: typing.Callable, *, raw_request: bool) -> None:
78 signature = callinfo.getfullargspec(func)
79 self.magic_args: list = []
80 self.raw_request = raw_request
81 if signature.args:
82 self.has_request = True
83 request_arg = signature.args[0]
84 if request_arg in signature.annotations:
85 self._infer_request_type(signature.annotations[request_arg])
86 for arg in signature.args[1:]:
87 self._handle_arg(arg)
88 elif signature.varargs:
89 self.has_request = True
90 if signature.kwonlyargs:
91 for arg in signature.kwonlyargs:
92 self._handle_arg(arg)
93
94 def _infer_request_type(self, request_type: type) -> None:
95 if request_type is aiohttp.web.BaseRequest:
96 self.raw_request = True
97 elif request_type is http.Request:
98 self.raw_request = False
99
100 def _handle_arg(self, arg: str) -> None:
101 if arg in self.magic_args_handlers:
102 self.magic_args.append((arg, self.magic_args_handlers[arg]))
103
104 async def build_args(
105 self,
106 request: aiohttp.web.BaseRequest,
107 orig_kwargs: dict[str, object],
108 ) -> tuple:
109 wrapped_request: http.Request | None
110 if self.has_request and not self.raw_request:
111 wrapped_request = await http.wrap_request(request)
112 else:
113 wrapped_request = None
114
115 kwargs = orig_kwargs.copy()
116 for arg, handler in self.magic_args:
117 if arg in kwargs:
118 continue
119 if handler.need_wrapped_request:
120 if wrapped_request is None:
121 wrapped_request = await http.wrap_request(request)
122 kwargs[arg] = handler(wrapped_request)
123 else:
124 kwargs[arg] = handler(request)
125
126 args: tuple
127 if self.has_request:
128 if self.raw_request:
129 args = (request,)
130 else:
131 args = (wrapped_request,)
132 else:
133 args = ()
134 return args, kwargs