Coverage for src/lexigram/web/dependencies/strategies.py: 19%
32 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
1"""Resolution strategies for web-related dependencies."""
3from __future__ import annotations
5from typing import Any
7from lexigram.di.extensions.strategies import ResolutionStrategy
10class WebParameterStrategy(ResolutionStrategy):
11 """Resolves path params, query params, headers from the request.
13 This strategy is used by lexigram-web to inject web parameters
14 (path, query, headers) alongside DI services.
15 """
17 def __init__(
18 self,
19 path_params: dict[str, str] | None = None,
20 query_params: dict[str, str | list[str]] | None = None,
21 headers: dict[str, str] | None = None,
22 request: Any = None,
23 ):
24 self._path = path_params or {}
25 self._query = query_params or {}
26 self._headers = headers or {}
27 self._request = request
29 async def resolve(
30 self,
31 param_name: str,
32 param_type: type,
33 default: Any,
34 ) -> tuple[bool, Any]:
35 # Path parameters
36 if param_name in self._path:
37 try:
38 return True, param_type(self._path[param_name])
39 except (ValueError, TypeError):
40 return True, self._path[param_name]
42 # Query parameters (handle both single and list values)
43 if param_name in self._query:
44 value = self._query[param_name]
45 if isinstance(value, list):
46 try:
47 return True, [param_type(v) for v in value]
48 except (ValueError, TypeError):
49 return True, value
50 else:
51 try:
52 return True, param_type(value)
53 except (ValueError, TypeError):
54 return True, value
56 # Header parameters (case-insensitive)
57 header_key = param_name.lower().replace("_", "-")
58 if header_key in self._headers:
59 return True, self._headers[header_key]
61 # Request object - check if param_type matches
62 if self._request is not None and (
63 param_type is type(self._request)
64 or (
65 hasattr(param_type, "__name__")
66 and param_type.__name__ == type(self._request).__name__
67 )
68 ):
69 return True, self._request
71 return False, None