@@ -59,7 +59,7 @@ def _acquire_bearer_token(resource: str) -> str:
5959 return credential .get_token (scope ).token
6060
6161
62- def builtin_http_activity (input : dict ) -> dict :
62+ def builtin_http_activity (input : dict [ str , Any ] ) -> dict [ str , Any ] :
6363 """Execute a single HTTP request and return the response payload.
6464
6565 ``input`` is the JSON form of a
@@ -68,14 +68,14 @@ def builtin_http_activity(input: dict) -> dict:
6868 return value is the JSON form of a
6969 :class:`~azure.durable_functions.http.models.DurableHttpResponse`.
7070
71- The parameter and return are annotated with the plain ``dict`` type on
72- purpose. The Azure Functions Python worker inspects trigger annotations
73- during indexing and requires them to be a real ``type`` (it rejects
71+ The parameter and return are declared as ``dict[str, Any]`` for static type
72+ checking, but the *runtime* annotations are reset to the bare ``dict`` type
73+ just below the function. The Azure Functions Python worker inspects trigger
74+ annotations during indexing and requires a real ``type`` -- it rejects
7475 parameterized generics such as ``dict[str, Any]`` with
7576 ``FunctionLoadError: ... invalid non-type annotation`` and, for a
7677 ``typing.Union`` origin like ``Optional[...]``, raises
77- ``TypeError: issubclass() arg 1 must be a class``). A bare ``dict`` keeps
78- worker indexing happy while the body still defends against ``None`` below.
78+ ``TypeError: issubclass() arg 1 must be a class``.
7979 """
8080 request = input or {}
8181 method = str (request .get ("method" , "GET" )).upper ()
@@ -113,6 +113,13 @@ def builtin_http_activity(input: dict) -> dict:
113113 status_code = status , headers = resp_headers , content = body ).to_json ()
114114
115115
116+ # The Azure Functions worker reads a trigger function's runtime ``__annotations__``
117+ # during indexing and rejects parameterized generics (it requires a bare
118+ # ``dict``). The signature above is typed ``dict[str, Any]`` for static analysis;
119+ # reset the runtime annotations to the bare ``dict`` the worker accepts.
120+ builtin_http_activity .__annotations__ = {"input" : dict , "return" : dict }
121+
122+
116123def _get_header (headers : dict [str , str ], name : str ) -> Optional [str ]:
117124 """Case-insensitively look up ``name`` in ``headers``."""
118125 lowered = name .lower ()
@@ -135,11 +142,9 @@ def _retry_after_seconds(headers: dict[str, str]) -> int:
135142 if raw .isdigit ():
136143 return max (int (raw ), 0 )
137144 try :
138- retry_at = parsedate_to_datetime (raw )
145+ parsedate_to_datetime (raw )
139146 except (TypeError , ValueError ):
140147 return _DEFAULT_POLL_INTERVAL_SECONDS
141- if retry_at is None :
142- return _DEFAULT_POLL_INTERVAL_SECONDS
143148 return _DEFAULT_POLL_INTERVAL_SECONDS
144149
145150
@@ -156,7 +161,7 @@ def builtin_http_poll_orchestrator(context: Any) -> Generator[Any, Any, dict[str
156161 BUILTIN_HTTP_ACTIVITY_NAME , request )
157162
158163 while response .get ("status_code" ) == 202 :
159- headers = response .get ("headers" ) or {}
164+ headers : dict [ str , str ] = response .get ("headers" ) or {}
160165 location = _get_header (headers , "Location" )
161166 if not location :
162167 # Cannot poll without a Location; return the 202 as-is.
0 commit comments