2# +==== BEGIN CatFeeder =================+
5# ...............)..(.')
7# ...............\(__)|
8# Inspired by Joan Stark
9# source https://www.asciiart.eu/
14# CREATION DATE: 23-01-2026
15# LAST Modified: 1:12:8 24-01-2026
17# This is the project in charge of making the connected cat feeder project work.
19# COPYRIGHT: (c) Cat Feeder
20# PURPOSE: Parameter decorators for API endpoint metadata management.
22# Provides decorators for documenting request parameters, headers, and body content.
25# +==== END CatFeeder =================+
27from typing
import Callable, Optional, Dict, Any, Union
28from functools
import wraps
32 """Helper function to preserve existing metadata attributes."""
34 '_requires_auth',
'_requires_admin',
'_public',
'_testing_only',
35 '_security_level',
'_environment',
'_description',
'_summary',
36 '_response_model',
'_tags',
'_requires_body',
'_body_model',
37 '_requires_headers',
'_header_names',
'_requires_auth_header',
38 '_auth_header_name',
'_requires_bearer_auth',
'_requires_basic_auth',
39 '_requires_api_key',
'_auth_scheme',
'_requires_query_params',
40 '_query_params',
'_requires_path_params',
'_path_params',
41 '_accepts_json_body',
'_accepts_form_data',
'_accepts_file_upload',
42 '_json_body_description',
'_json_body_example'
45 for attr
in metadata_attrs:
46 if hasattr(func, attr):
47 setattr(wrapper, attr, getattr(func, attr))
52 """Mark endpoint as requiring query parameters (legacy API).
55 description: Description of the query parameters.
60 def decorator(func: Callable) -> Callable:
62 def wrapper(*args, **kwargs):
63 return func(*args, **kwargs)
65 setattr(wrapper,
"_requires_query_params",
True)
66 setattr(wrapper,
"_query_params_description", description)
73def inject_json_body(description: str =
"JSON request body", example: Union[str, Dict[str, Any],
None] =
None) -> Callable:
74 """Mark endpoint as accepting JSON body content (legacy API).
77 description: Description of the JSON body content.
78 example: Example JSON content (as dict or JSON string).
83 def decorator(func: Callable) -> Callable:
85 def wrapper(*args, **kwargs):
86 return func(*args, **kwargs)
88 setattr(wrapper,
"_accepts_json_body",
True)
89 setattr(wrapper,
"_json_body_description", description)
90 if example
is not None:
91 setattr(wrapper,
"_json_body_example", example)
99 """Mark endpoint as receiving HTTP request (legacy API).
102 description: Description of the request.
107 def decorator(func: Callable) -> Callable:
109 def wrapper(*args, **kwargs):
110 return func(*args, **kwargs)
112 setattr(wrapper,
"_accepts_request",
True)
113 setattr(wrapper,
"_request_description", description)
120def requires_body(model_class: Any =
None, description: str =
"Request body") -> Callable:
121 """Mark endpoint as requiring a request body with optional Pydantic model.
124 model_class: Optional Pydantic model class for validation.
125 description: Description of the request body.
130 def decorator(func: Callable) -> Callable:
132 def wrapper(*args, **kwargs):
133 return func(*args, **kwargs)
135 setattr(wrapper,
"_requires_body",
True)
136 setattr(wrapper,
"_body_model", model_class)
137 setattr(wrapper,
"_body_description", description)
144def requires_headers(*header_names: str, description: str =
"Required headers") -> Callable:
145 """Mark endpoint as requiring specific headers.
148 header_names: Names of required headers.
149 description: Description of the headers.
154 def decorator(func: Callable) -> Callable:
156 def wrapper(*args, **kwargs):
157 return func(*args, **kwargs)
159 setattr(wrapper,
"_requires_headers",
True)
160 setattr(wrapper,
"_header_names", list(header_names))
161 setattr(wrapper,
"_headers_description", description)
170 """Mark endpoint as requiring authentication header.
173 header_name: Name of the auth header (default: Authorization).
174 scheme: Optional auth scheme (e.g., "Bearer", "Basic").
179 def decorator(func: Callable) -> Callable:
181 def wrapper(*args, **kwargs):
182 return func(*args, **kwargs)
184 setattr(wrapper,
"_requires_auth_header",
True)
185 setattr(wrapper,
"_auth_header_name", header_name)
187 setattr(wrapper,
"_auth_scheme", scheme)
195 """Mark endpoint as requiring Bearer token authentication.
197 Specifically expects: Authorization: Bearer <token>
202 def decorator(func: Callable) -> Callable:
204 def wrapper(*args, **kwargs):
205 return func(*args, **kwargs)
207 setattr(wrapper,
"_requires_bearer_auth",
True)
208 setattr(wrapper,
"_auth_scheme",
"Bearer")
209 setattr(wrapper,
"_auth_header_name",
"Authorization")
217 """Mark endpoint as requiring Basic authentication.
219 Specifically expects: Authorization: Basic <credentials>
224 def decorator(func: Callable) -> Callable:
226 def wrapper(*args, **kwargs):
227 return func(*args, **kwargs)
229 setattr(wrapper,
"_requires_basic_auth",
True)
230 setattr(wrapper,
"_auth_scheme",
"Basic")
231 setattr(wrapper,
"_auth_header_name",
"Authorization")
239 """Mark endpoint as requiring API key authentication.
242 header_name: Name of the API key header (default: X-API-Key).
247 def decorator(func: Callable) -> Callable:
249 def wrapper(*args, **kwargs):
250 return func(*args, **kwargs)
252 setattr(wrapper,
"_requires_api_key",
True)
253 setattr(wrapper,
"_auth_scheme",
"API-Key")
254 setattr(wrapper,
"_auth_header_name", header_name)
262 """Mark endpoint as requiring specific query parameters.
265 params: Query parameter names and their descriptions.
270 def decorator(func: Callable) -> Callable:
272 def wrapper(*args, **kwargs):
273 return func(*args, **kwargs)
275 setattr(wrapper,
"_requires_query_params",
True)
276 setattr(wrapper,
"_query_params", dict(params))
284 """Mark endpoint as requiring specific path parameters.
287 params: Path parameter names and their descriptions.
292 def decorator(func: Callable) -> Callable:
294 def wrapper(*args, **kwargs):
295 return func(*args, **kwargs)
297 setattr(wrapper,
"_requires_path_params",
True)
298 setattr(wrapper,
"_path_params", dict(params))
306def json_body(description: str =
"JSON request body", example: Union[str, Dict[str, Any],
None] =
None) -> Callable:
307 """Mark endpoint as accepting JSON body content (alias for inject_json_body).
310 description: Description of the JSON body content.
311 example: Example JSON content (as dict or JSON string).
319def form_data(description: str =
"Form data") -> Callable:
320 """Mark endpoint as accepting form data.
323 description: Description of the form data.
328 def decorator(func: Callable) -> Callable:
330 def wrapper(*args, **kwargs):
331 return func(*args, **kwargs)
333 setattr(wrapper,
"_accepts_form_data",
True)
334 setattr(wrapper,
"_form_data_description", description)
342 """Mark endpoint as accepting file uploads.
345 description: Description of the file upload.
350 def decorator(func: Callable) -> Callable:
352 def wrapper(*args, **kwargs):
353 return func(*args, **kwargs)
355 setattr(wrapper,
"_accepts_file_upload",
True)
356 setattr(wrapper,
"_file_upload_description", description)
Callable json_body(str description="JSON request body", Union[str, Dict[str, Any], None] example=None)
Callable file_upload(str description="File upload")
Callable requires_auth_header(str header_name="Authorization", Optional[str] scheme=None)
Callable requires_query_params(**str params)
Callable requires_api_key(str header_name="X-API-Key")
Callable requires_headers(*str header_names, str description="Required headers")
Callable requires_bearer_auth()
Callable requires_basic_auth()
Callable inject_json_body(str description="JSON request body", Union[str, Dict[str, Any], None] example=None)
Callable requires_path_params(**str params)
Callable form_data(str description="Form data")
None _preserve_metadata(Callable func, Callable wrapper)
Callable inject_request(str description="HTTP request")
Callable requires_body(Any model_class=None, str description="Request body")
Callable inject_query_params(str description="Query parameters")