Skip to content

Commit 52871b8

Browse files
authored
Add type hints to HTTPX (#3098)
1 parent e54256d commit 52871b8

File tree

2 files changed

+73
-70
lines changed
  • instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx

2 files changed

+73
-70
lines changed

instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py

Lines changed: 73 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -230,15 +230,13 @@ async def async_response_hook(span, request, response):
230230
NETWORK_PEER_ADDRESS,
231231
NETWORK_PEER_PORT,
232232
)
233-
from opentelemetry.trace import SpanKind, TracerProvider, get_tracer
233+
from opentelemetry.trace import SpanKind, Tracer, TracerProvider, get_tracer
234234
from opentelemetry.trace.span import Span
235235
from opentelemetry.trace.status import StatusCode
236236
from opentelemetry.util.http import remove_url_credentials, sanitize_method
237237

238238
_logger = logging.getLogger(__name__)
239239

240-
URL = typing.Tuple[bytes, bytes, typing.Optional[int], bytes]
241-
Headers = typing.List[typing.Tuple[bytes, bytes]]
242240
RequestHook = typing.Callable[[Span, "RequestInfo"], None]
243241
ResponseHook = typing.Callable[[Span, "RequestInfo", "ResponseInfo"], None]
244242
AsyncRequestHook = typing.Callable[
@@ -253,17 +251,15 @@ class RequestInfo(typing.NamedTuple):
253251
method: bytes
254252
url: httpx.URL
255253
headers: httpx.Headers | None
256-
stream: typing.Optional[
257-
typing.Union[httpx.SyncByteStream, httpx.AsyncByteStream]
258-
]
259-
extensions: typing.Optional[dict]
254+
stream: httpx.SyncByteStream | httpx.AsyncByteStream | None
255+
extensions: dict[str, typing.Any] | None
260256

261257

262258
class ResponseInfo(typing.NamedTuple):
263259
status_code: int
264260
headers: httpx.Headers | None
265-
stream: typing.Iterable[bytes]
266-
extensions: typing.Optional[dict]
261+
stream: httpx.SyncByteStream | httpx.AsyncByteStream
262+
extensions: dict[str, typing.Any] | None
267263

268264

269265
def _get_default_span_name(method: str) -> str:
@@ -274,11 +270,19 @@ def _get_default_span_name(method: str) -> str:
274270
return method
275271

276272

277-
def _prepare_headers(headers: typing.Optional[Headers]) -> httpx.Headers:
273+
def _prepare_headers(headers: httpx.Headers | None) -> httpx.Headers:
278274
return httpx.Headers(headers)
279275

280276

281-
def _extract_parameters(args, kwargs):
277+
def _extract_parameters(
278+
args: tuple[typing.Any, ...], kwargs: dict[str, typing.Any]
279+
) -> tuple[
280+
bytes,
281+
httpx.URL,
282+
httpx.Headers | None,
283+
httpx.SyncByteStream | httpx.AsyncByteStream | None,
284+
dict[str, typing.Any],
285+
]:
282286
if isinstance(args[0], httpx.Request):
283287
# In httpx >= 0.20.0, handle_request receives a Request object
284288
request: httpx.Request = args[0]
@@ -311,10 +315,15 @@ def _inject_propagation_headers(headers, args, kwargs):
311315

312316

313317
def _extract_response(
314-
response: typing.Union[
315-
httpx.Response, typing.Tuple[int, Headers, httpx.SyncByteStream, dict]
316-
],
317-
) -> typing.Tuple[int, Headers, httpx.SyncByteStream, dict, str]:
318+
response: httpx.Response
319+
| tuple[int, httpx.Headers, httpx.SyncByteStream, dict[str, typing.Any]],
320+
) -> tuple[
321+
int,
322+
httpx.Headers,
323+
httpx.SyncByteStream | httpx.AsyncByteStream,
324+
dict[str, typing.Any],
325+
str,
326+
]:
318327
if isinstance(response, httpx.Response):
319328
status_code = response.status_code
320329
headers = response.headers
@@ -331,8 +340,8 @@ def _extract_response(
331340

332341

333342
def _apply_request_client_attributes_to_span(
334-
span_attributes: dict,
335-
url: typing.Union[str, URL, httpx.URL],
343+
span_attributes: dict[str, typing.Any],
344+
url: str | httpx.URL,
336345
method_original: str,
337346
semconv: _StabilityMode,
338347
):
@@ -407,9 +416,9 @@ class SyncOpenTelemetryTransport(httpx.BaseTransport):
407416
def __init__(
408417
self,
409418
transport: httpx.BaseTransport,
410-
tracer_provider: typing.Optional[TracerProvider] = None,
411-
request_hook: typing.Optional[RequestHook] = None,
412-
response_hook: typing.Optional[ResponseHook] = None,
419+
tracer_provider: TracerProvider | None = None,
420+
request_hook: RequestHook | None = None,
421+
response_hook: ResponseHook | None = None,
413422
):
414423
_OpenTelemetrySemanticConventionStability._initialize()
415424
self._sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
@@ -426,27 +435,27 @@ def __init__(
426435
self._request_hook = request_hook
427436
self._response_hook = response_hook
428437

429-
def __enter__(self) -> "SyncOpenTelemetryTransport":
438+
def __enter__(self) -> SyncOpenTelemetryTransport:
430439
self._transport.__enter__()
431440
return self
432441

433442
def __exit__(
434443
self,
435-
exc_type: typing.Optional[typing.Type[BaseException]] = None,
436-
exc_value: typing.Optional[BaseException] = None,
437-
traceback: typing.Optional[TracebackType] = None,
444+
exc_type: type[BaseException] | None = None,
445+
exc_value: BaseException | None = None,
446+
traceback: TracebackType | None = None,
438447
) -> None:
439448
self._transport.__exit__(exc_type, exc_value, traceback)
440449

441450
# pylint: disable=R0914
442451
def handle_request(
443452
self,
444-
*args,
445-
**kwargs,
446-
) -> typing.Union[
447-
typing.Tuple[int, "Headers", httpx.SyncByteStream, dict],
448-
httpx.Response,
449-
]:
453+
*args: typing.Any,
454+
**kwargs: typing.Any,
455+
) -> (
456+
tuple[int, httpx.Headers, httpx.SyncByteStream, dict[str, typing.Any]]
457+
| httpx.Response
458+
):
450459
"""Add request info to span."""
451460
if not is_http_instrumentation_enabled():
452461
return self._transport.handle_request(*args, **kwargs)
@@ -532,9 +541,9 @@ class AsyncOpenTelemetryTransport(httpx.AsyncBaseTransport):
532541
def __init__(
533542
self,
534543
transport: httpx.AsyncBaseTransport,
535-
tracer_provider: typing.Optional[TracerProvider] = None,
536-
request_hook: typing.Optional[AsyncRequestHook] = None,
537-
response_hook: typing.Optional[AsyncResponseHook] = None,
544+
tracer_provider: TracerProvider | None = None,
545+
request_hook: AsyncRequestHook | None = None,
546+
response_hook: AsyncResponseHook | None = None,
538547
):
539548
_OpenTelemetrySemanticConventionStability._initialize()
540549
self._sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
@@ -557,19 +566,19 @@ async def __aenter__(self) -> "AsyncOpenTelemetryTransport":
557566

558567
async def __aexit__(
559568
self,
560-
exc_type: typing.Optional[typing.Type[BaseException]] = None,
561-
exc_value: typing.Optional[BaseException] = None,
562-
traceback: typing.Optional[TracebackType] = None,
569+
exc_type: typing.Type[BaseException] | None = None,
570+
exc_value: BaseException | None = None,
571+
traceback: TracebackType | None = None,
563572
) -> None:
564573
await self._transport.__aexit__(exc_type, exc_value, traceback)
565574

566575
# pylint: disable=R0914
567576
async def handle_async_request(
568-
self, *args, **kwargs
569-
) -> typing.Union[
570-
typing.Tuple[int, "Headers", httpx.AsyncByteStream, dict],
571-
httpx.Response,
572-
]:
577+
self, *args: typing.Any, **kwargs: typing.Any
578+
) -> (
579+
tuple[int, httpx.Headers, httpx.AsyncByteStream, dict[str, typing.Any]]
580+
| httpx.Response
581+
):
573582
"""Add request info to span."""
574583
if not is_http_instrumentation_enabled():
575584
return await self._transport.handle_async_request(*args, **kwargs)
@@ -653,7 +662,7 @@ class HTTPXClientInstrumentor(BaseInstrumentor):
653662
def instrumentation_dependencies(self) -> typing.Collection[str]:
654663
return _instruments
655664

656-
def _instrument(self, **kwargs):
665+
def _instrument(self, **kwargs: typing.Any):
657666
"""Instruments httpx Client and AsyncClient
658667
659668
Args:
@@ -716,20 +725,20 @@ def _instrument(self, **kwargs):
716725
),
717726
)
718727

719-
def _uninstrument(self, **kwargs):
728+
def _uninstrument(self, **kwargs: typing.Any):
720729
unwrap(httpx.HTTPTransport, "handle_request")
721730
unwrap(httpx.AsyncHTTPTransport, "handle_async_request")
722731

723732
@staticmethod
724733
def _handle_request_wrapper( # pylint: disable=too-many-locals
725-
wrapped,
726-
instance,
727-
args,
728-
kwargs,
729-
tracer,
730-
sem_conv_opt_in_mode,
731-
request_hook,
732-
response_hook,
734+
wrapped: typing.Callable[..., typing.Any],
735+
instance: httpx.HTTPTransport,
736+
args: tuple[typing.Any, ...],
737+
kwargs: dict[str, typing.Any],
738+
tracer: Tracer,
739+
sem_conv_opt_in_mode: _StabilityMode,
740+
request_hook: RequestHook,
741+
response_hook: ResponseHook,
733742
):
734743
if not is_http_instrumentation_enabled():
735744
return wrapped(*args, **kwargs)
@@ -796,14 +805,14 @@ def _handle_request_wrapper( # pylint: disable=too-many-locals
796805

797806
@staticmethod
798807
async def _handle_async_request_wrapper( # pylint: disable=too-many-locals
799-
wrapped,
800-
instance,
801-
args,
802-
kwargs,
803-
tracer,
804-
sem_conv_opt_in_mode,
805-
async_request_hook,
806-
async_response_hook,
808+
wrapped: typing.Callable[..., typing.Awaitable[typing.Any]],
809+
instance: httpx.AsyncHTTPTransport,
810+
args: tuple[typing.Any, ...],
811+
kwargs: dict[str, typing.Any],
812+
tracer: Tracer,
813+
sem_conv_opt_in_mode: _StabilityMode,
814+
async_request_hook: AsyncRequestHook,
815+
async_response_hook: AsyncResponseHook,
807816
):
808817
if not is_http_instrumentation_enabled():
809818
return await wrapped(*args, **kwargs)
@@ -872,14 +881,10 @@ async def _handle_async_request_wrapper( # pylint: disable=too-many-locals
872881
@classmethod
873882
def instrument_client(
874883
cls,
875-
client: typing.Union[httpx.Client, httpx.AsyncClient],
876-
tracer_provider: TracerProvider = None,
877-
request_hook: typing.Union[
878-
typing.Optional[RequestHook], typing.Optional[AsyncRequestHook]
879-
] = None,
880-
response_hook: typing.Union[
881-
typing.Optional[ResponseHook], typing.Optional[AsyncResponseHook]
882-
] = None,
884+
client: httpx.Client | httpx.AsyncClient,
885+
tracer_provider: TracerProvider | None = None,
886+
request_hook: RequestHook | AsyncRequestHook | None = None,
887+
response_hook: ResponseHook | AsyncResponseHook | None = None,
883888
) -> None:
884889
"""Instrument httpx Client or AsyncClient
885890
@@ -977,9 +982,7 @@ def instrument_client(
977982
client._is_instrumented_by_opentelemetry = True
978983

979984
@staticmethod
980-
def uninstrument_client(
981-
client: typing.Union[httpx.Client, httpx.AsyncClient],
982-
):
985+
def uninstrument_client(client: httpx.Client | httpx.AsyncClient) -> None:
983986
"""Disables instrumentation for the given client instance
984987
985988
Args:

instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/py.typed

Whitespace-only changes.

0 commit comments

Comments
 (0)