diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py index cfb1d9ea75..3cd2391200 100644 --- a/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/src/opentelemetry/exporter/prometheus_remote_write/__init__.py @@ -11,12 +11,13 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import logging import re from collections import defaultdict from itertools import chain -from typing import Dict, Mapping, Sequence +from typing import Mapping, Sequence import requests import snappy @@ -71,14 +72,14 @@ class PrometheusRemoteWriteMetricsExporter(MetricExporter): def __init__( self, endpoint: str, - basic_auth: Dict = None, - headers: Dict = None, + basic_auth: dict = None, + headers: dict = None, timeout: int = 30, - tls_config: Dict = None, - proxies: Dict = None, + tls_config: dict = None, + proxies: dict = None, resources_as_labels: bool = True, - preferred_temporality: Dict[type, AggregationTemporality] = None, - preferred_aggregation: Dict = None, + preferred_temporality: dict[type, AggregationTemporality] = None, + preferred_aggregation: dict = None, ): self.endpoint = endpoint self.basic_auth = basic_auth @@ -115,7 +116,7 @@ def basic_auth(self): return self._basic_auth @basic_auth.setter - def basic_auth(self, basic_auth: Dict): + def basic_auth(self, basic_auth: dict): if basic_auth: if "username" not in basic_auth: raise ValueError("username required in basic_auth") @@ -147,7 +148,7 @@ def tls_config(self): return self._tls_config @tls_config.setter - def tls_config(self, tls_config: Dict): + def tls_config(self, tls_config: dict): if tls_config: new_config = {} if "ca_file" in tls_config: @@ -170,7 +171,7 @@ def proxies(self): return self._proxies @proxies.setter - def proxies(self, proxies: Dict): + def proxies(self, proxies: dict): self._proxies = proxies @property @@ -178,7 +179,7 @@ def headers(self): return self._headers @headers.setter - def headers(self, headers: Dict): + def headers(self, headers: dict): self._headers = headers def export( @@ -355,7 +356,7 @@ def _build_message(timeseries: Sequence[TimeSeries]) -> bytes: serialized_message = write_request.SerializeToString() return snappy.compress(serialized_message) - def _build_headers(self) -> Dict: + def _build_headers(self) -> dict: headers = { "Content-Encoding": "snappy", "Content-Type": "application/x-protobuf", @@ -367,7 +368,7 @@ def _build_headers(self) -> Dict: return headers def _send_message( - self, message: bytes, headers: Dict + self, message: bytes, headers: dict ) -> MetricExportResult: auth = None if self.basic_auth: diff --git a/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py index 1c50344353..f86b072832 100644 --- a/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py +++ b/exporter/opentelemetry-exporter-prometheus-remote-write/tests/test_prometheus_remote_write_exporter.py @@ -314,18 +314,18 @@ def test_invalid_export(prom_rw): @patch("requests.post") def test_valid_send_message(mock_post, prom_rw): mock_post.return_value.configure_mock(**{"ok": True}) - result = prom_rw._send_message(bytes(), {}) + result = prom_rw._send_message(b"", {}) assert mock_post.call_count == 1 assert result == MetricExportResult.SUCCESS def test_invalid_send_message(prom_rw): - result = prom_rw._send_message(bytes(), {}) + result = prom_rw._send_message(b"", {}) assert result == MetricExportResult.FAILURE # Verifies that build_message calls snappy.compress and returns SerializedString -@patch("snappy.compress", return_value=bytes()) +@patch("snappy.compress", return_value=b"") def test_build_message(mock_compress, prom_rw): message = prom_rw._build_message([TimeSeries()]) assert mock_compress.call_count == 1 diff --git a/exporter/opentelemetry-exporter-richconsole/src/opentelemetry/exporter/richconsole/__init__.py b/exporter/opentelemetry-exporter-richconsole/src/opentelemetry/exporter/richconsole/__init__.py index 1e96df877b..a7c9d43fb2 100644 --- a/exporter/opentelemetry-exporter-richconsole/src/opentelemetry/exporter/richconsole/__init__.py +++ b/exporter/opentelemetry-exporter-richconsole/src/opentelemetry/exporter/richconsole/__init__.py @@ -50,11 +50,12 @@ .. _Rich: https://rich.readthedocs.io/ .. _OpenTelemetry: https://github.com/open-telemetry/opentelemetry-python/ """ + # pylint: disable=import-error +from __future__ import annotations import datetime import typing -from typing import Dict, Optional from rich.console import Console from rich.syntax import Syntax @@ -150,7 +151,7 @@ class RichConsoleSpanExporter(SpanExporter): def __init__( self, - service_name: Optional[str] = None, + service_name: str | None = None, ): self.service_name = service_name self.console = Console() @@ -165,7 +166,7 @@ def export(self, spans: typing.Sequence[ReadableSpan]) -> SpanExportResult: return SpanExportResult.SUCCESS @staticmethod - def spans_to_tree(spans: typing.Sequence[ReadableSpan]) -> Dict[str, Tree]: + def spans_to_tree(spans: typing.Sequence[ReadableSpan]) -> dict[str, Tree]: trees = {} parents = {} spans = list(spans) diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py index cd284473ce..115a1dd3f7 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/patch.py @@ -11,9 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - - -from typing import Optional +from __future__ import annotations from openai import Stream @@ -201,12 +199,12 @@ def append_tool_call(self, tool_call): class StreamWrapper: span: Span - response_id: Optional[str] = None - response_model: Optional[str] = None - service_tier: Optional[str] = None + response_id: str | None = None + response_model: str | None = None + service_tier: str | None = None finish_reasons: list = [] - prompt_tokens: Optional[int] = 0 - completion_tokens: Optional[int] = 0 + prompt_tokens: int | None = 0 + completion_tokens: int | None = 0 def __init__( self, diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py index f8a837259e..7d6e8bfe89 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/src/opentelemetry/instrumentation/openai_v2/utils.py @@ -11,9 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations from os import environ -from typing import Mapping, Optional, Union +from typing import Mapping from urllib.parse import urlparse from httpx import URL @@ -179,7 +180,7 @@ def is_streaming(kwargs): return non_numerical_value_is_set(kwargs.get("stream")) -def non_numerical_value_is_set(value: Optional[Union[bool, str]]): +def non_numerical_value_is_set(value: bool | str | None): return bool(value) and value != NOT_GIVEN diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py index 65c596796d..d49db4d39a 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_async_chat_completions.py @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable=too-many-locals - -from typing import Optional +from __future__ import annotations import pytest from openai import APIConnectionError, AsyncOpenAI, NotFoundError @@ -802,8 +801,8 @@ def assert_all_attributes( request_model: str, response_id: str = None, response_model: str = None, - input_tokens: Optional[int] = None, - output_tokens: Optional[int] = None, + input_tokens: int | None = None, + output_tokens: int | None = None, operation_name: str = "chat", server_address: str = "api.openai.com", ): diff --git a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py index 4677b7cb95..1e8683e9a2 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py +++ b/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/test_chat_completions.py @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # pylint: disable=too-many-locals - -from typing import Optional +from __future__ import annotations import pytest from openai import APIConnectionError, NotFoundError, OpenAI @@ -779,8 +778,8 @@ def assert_all_attributes( request_model: str, response_id: str = None, response_model: str = None, - input_tokens: Optional[int] = None, - output_tokens: Optional[int] = None, + input_tokens: int | None = None, + output_tokens: int | None = None, operation_name: str = "chat", server_address: str = "api.openai.com", ): diff --git a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py index f10415bdd2..3c891ecc08 100644 --- a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py +++ b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/callback_decorator.py @@ -11,7 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Any, Callable, Optional +from __future__ import annotations + +from typing import Any, Callable from aio_pika import Queue from aio_pika.abc import AbstractIncomingMessage @@ -28,7 +30,7 @@ def __init__(self, tracer: Tracer, queue: Queue): self._tracer = tracer self._queue = queue - def _get_span(self, message: AbstractIncomingMessage) -> Optional[Span]: + def _get_span(self, message: AbstractIncomingMessage) -> Span | None: builder = SpanBuilder(self._tracer) builder.set_as_consumer() builder.set_operation(MessagingOperationValues.RECEIVE) diff --git a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/publish_decorator.py b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/publish_decorator.py index 03937290ee..a79560b047 100644 --- a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/publish_decorator.py +++ b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/publish_decorator.py @@ -11,7 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable import aiormq from aio_pika import Exchange @@ -29,7 +31,7 @@ def __init__(self, tracer: Tracer, exchange: Exchange): def _get_publish_span( self, message: AbstractMessage, routing_key: str - ) -> Optional[Span]: + ) -> Span | None: builder = SpanBuilder(self._tracer) builder.set_as_producer() builder.set_destination(f"{self._exchange.name},{routing_key}") @@ -40,7 +42,7 @@ def _get_publish_span( def decorate(self, publish: Callable) -> Callable: async def decorated_publish( message: AbstractMessage, routing_key: str, **kwargs - ) -> Optional[aiormq.abc.ConfirmationFrameType]: + ) -> aiormq.abc.ConfirmationFrameType | None: span = self._get_publish_span(message, routing_key) if not span: return await publish(message, routing_key, **kwargs) diff --git a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/span_builder.py b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/span_builder.py index dd5433756c..aeba4e237b 100644 --- a/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/span_builder.py +++ b/instrumentation/opentelemetry-instrumentation-aio-pika/src/opentelemetry/instrumentation/aio_pika/span_builder.py @@ -11,7 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Optional +from __future__ import annotations from aio_pika.abc import AbstractChannel, AbstractMessage @@ -77,7 +77,7 @@ def set_message(self, message: AbstractMessage): properties.correlation_id ) - def build(self) -> Optional[Span]: + def build(self) -> Span | None: if not is_instrumentation_enabled(): return None if self._operation: diff --git a/instrumentation/opentelemetry-instrumentation-aio-pika/tests/test_publish_decorator.py b/instrumentation/opentelemetry-instrumentation-aio-pika/tests/test_publish_decorator.py index 90a029531d..40317b15b7 100644 --- a/instrumentation/opentelemetry-instrumentation-aio-pika/tests/test_publish_decorator.py +++ b/instrumentation/opentelemetry-instrumentation-aio-pika/tests/test_publish_decorator.py @@ -11,8 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import asyncio -from typing import Type from unittest import TestCase, mock, skipIf from unittest.mock import MagicMock @@ -70,7 +71,7 @@ def test_get_publish_span(self): attributes=self.EXPECTED_ATTRIBUTES, ) - def _test_publish(self, exchange_type: Type[Exchange]): + def _test_publish(self, exchange_type: type[Exchange]): exchange = exchange_type(CONNECTION_7, CHANNEL_7, EXCHANGE_NAME) with mock.patch.object( PublishDecorator, "_get_publish_span" @@ -149,7 +150,7 @@ def test_get_publish_span(self): attributes=self.EXPECTED_ATTRIBUTES, ) - def _test_publish(self, exchange_type: Type[Exchange]): + def _test_publish(self, exchange_type: type[Exchange]): exchange = exchange_type(CONNECTION_8, CHANNEL_8, EXCHANGE_NAME) with mock.patch.object( PublishDecorator, "_get_publish_span" diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py index c43522efe1..ecc6728889 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/src/opentelemetry/instrumentation/aiohttp_client/__init__.py @@ -80,6 +80,8 @@ def response_hook(span: Span, params: typing.Union[ --- """ +from __future__ import annotations + import types import typing from typing import Collection @@ -323,9 +325,7 @@ def _instrument( url_filter: _UrlFilterT = None, request_hook: _RequestHookT = None, response_hook: _ResponseHookT = None, - trace_configs: typing.Optional[ - typing.Sequence[aiohttp.TraceConfig] - ] = None, + trace_configs: typing.Sequence[aiohttp.TraceConfig] | None = None, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, ): """Enables tracing of all ClientSessions diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py index 62c837f88d..fa934a4ac8 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-client/tests/test_aiohttp_client_integration.py @@ -12,6 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import asyncio import contextlib import typing @@ -51,7 +53,7 @@ def run_with_test_server( runnable: typing.Callable, url: str, handler: typing.Callable -) -> typing.Tuple[str, int]: +) -> str | int: async def do_request(): app = aiohttp.web.Application() parsed_url = urllib.parse.urlparse(url) @@ -107,7 +109,7 @@ def _http_request( status_code: int = HTTPStatus.OK, request_handler: typing.Callable = None, **kwargs, - ) -> typing.Tuple[str, int]: + ) -> tuple[str, int]: """Helper to start an aiohttp test server and send an actual HTTP request to it.""" async def default_handler(request): @@ -269,10 +271,8 @@ def request_hook(span: Span, params: aiohttp.TraceRequestStartParams): def response_hook( span: Span, - params: typing.Union[ - aiohttp.TraceRequestEndParams, - aiohttp.TraceRequestExceptionParams, - ], + params: aiohttp.TraceRequestEndParams + | aiohttp.TraceRequestExceptionParams, ): span.set_attribute("response_hook_attr", "value") @@ -646,7 +646,7 @@ def tearDown(self): @staticmethod # pylint:disable=unused-argument async def default_handler(request): - return aiohttp.web.Response(status=int(200)) + return aiohttp.web.Response(status=200) @staticmethod def get_default_request(url: str = URL): @@ -861,10 +861,8 @@ def request_hook(span: Span, params: aiohttp.TraceRequestStartParams): def response_hook( span: Span, - params: typing.Union[ - aiohttp.TraceRequestEndParams, - aiohttp.TraceRequestExceptionParams, - ], + params: aiohttp.TraceRequestEndParams + | aiohttp.TraceRequestExceptionParams, ): span.set_attribute("response_hook_attr", "value") diff --git a/instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py b/instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py index 6db7719c76..751ed406e7 100644 --- a/instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-aiohttp-server/src/opentelemetry/instrumentation/aiohttp_server/__init__.py @@ -11,10 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import urllib from timeit import default_timer -from typing import Dict, List, Tuple, Union from aiohttp import web from multidict import CIMultiDictProxy @@ -75,7 +75,7 @@ def _parse_active_request_count_attrs(req_attrs): return active_requests_count_attrs -def get_default_span_details(request: web.Request) -> Tuple[str, dict]: +def get_default_span_details(request: web.Request) -> tuple[str, dict]: """Default implementation for get_default_span_details Args: request: the request object itself. @@ -99,7 +99,7 @@ def _get_view_func(request: web.Request) -> str: return "unknown" -def collect_request_attributes(request: web.Request) -> Dict: +def collect_request_attributes(request: web.Request) -> dict: """Collects HTTP request attributes from the ASGI scope and returns a dictionary to be used as span creation attributes.""" @@ -167,7 +167,7 @@ def set_status_code(span, status_code: int) -> None: class AiohttpGetter(Getter): """Extract current trace from headers""" - def get(self, carrier, key: str) -> Union[List, None]: + def get(self, carrier, key: str) -> list | None: """Getter implementation to retrieve an HTTP header value from the ASGI scope. @@ -183,7 +183,7 @@ def get(self, carrier, key: str) -> Union[List, None]: return None return headers.getall(key, None) - def keys(self, carrier: Dict) -> List: + def keys(self, carrier: dict) -> list: return list(carrier.keys()) diff --git a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py index cae0d97717..28590ffe98 100644 --- a/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-aiokafka/src/opentelemetry/instrumentation/aiokafka/utils.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import json from logging import getLogger -from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple, Union +from typing import Any, Awaitable, Callable, Dict, List, Optional, Tuple import aiokafka from aiokafka import ConsumerRecord @@ -18,7 +20,7 @@ def _extract_bootstrap_servers( client: aiokafka.AIOKafkaClient, -) -> Union[str, List[str]]: +) -> str | list[str]: return client._bootstrap_servers @@ -28,7 +30,7 @@ def _extract_client_id(client: aiokafka.AIOKafkaClient) -> str: def _extract_consumer_group( consumer: aiokafka.AIOKafkaConsumer, -) -> Optional[str]: +) -> str | None: return consumer._group_id @@ -36,43 +38,41 @@ def _extract_argument( key: str, position: int, default_value: Any, - args: Tuple[Any], - kwargs: Dict[str, Any], + args: tuple[Any], + kwargs: dict[str, Any], ) -> Any: if len(args) > position: return args[position] return kwargs.get(key, default_value) -def _extract_send_topic(args: Tuple[Any], kwargs: Dict[str, Any]) -> str: +def _extract_send_topic(args: tuple[Any], kwargs: dict[str, Any]) -> str: """extract topic from `send` method arguments in AIOKafkaProducer class""" return _extract_argument("topic", 0, "unknown", args, kwargs) def _extract_send_value( - args: Tuple[Any], kwargs: Dict[str, Any] -) -> Optional[Any]: + args: tuple[Any], kwargs: dict[str, Any] +) -> Any | None: """extract value from `send` method arguments in AIOKafkaProducer class""" return _extract_argument("value", 1, None, args, kwargs) -def _extract_send_key( - args: Tuple[Any], kwargs: Dict[str, Any] -) -> Optional[Any]: +def _extract_send_key(args: tuple[Any], kwargs: dict[str, Any]) -> Any | None: """extract key from `send` method arguments in AIOKafkaProducer class""" return _extract_argument("key", 2, None, args, kwargs) -def _extract_send_headers(args: Tuple[Any], kwargs: Dict[str, Any]): +def _extract_send_headers(args: tuple[Any], kwargs: dict[str, Any]): """extract headers from `send` method arguments in AIOKafkaProducer class""" return _extract_argument("headers", 5, None, args, kwargs) async def _extract_send_partition( instance: aiokafka.AIOKafkaProducer, - args: Tuple[Any], - kwargs: Dict[str, Any], -) -> Optional[int]: + args: tuple[Any], + kwargs: dict[str, Any], +) -> int | None: """extract partition `send` method arguments, using the `_partition` method in AIOKafkaProducer class""" try: topic = _extract_send_topic(args, kwargs) @@ -106,7 +106,7 @@ async def _extract_send_partition( class AIOKafkaContextGetter(textmap.Getter[HeadersT]): - def get(self, carrier: HeadersT, key: str) -> Optional[List[str]]: + def get(self, carrier: HeadersT, key: str) -> list[str] | None: if carrier is None: return None @@ -116,7 +116,7 @@ def get(self, carrier: HeadersT, key: str) -> Optional[List[str]]: return [value.decode()] return None - def keys(self, carrier: HeadersT) -> List[str]: + def keys(self, carrier: HeadersT) -> list[str]: if carrier is None: return [] return [key for (key, value) in carrier] @@ -124,7 +124,7 @@ def keys(self, carrier: HeadersT) -> List[str]: class AIOKafkaContextSetter(textmap.Setter[HeadersT]): def set( - self, carrier: HeadersT, key: Optional[str], value: Optional[str] + self, carrier: HeadersT, key: str | None, value: str | None ) -> None: if carrier is None or key is None: return @@ -142,11 +142,11 @@ def set( def _enrich_base_span( span: Span, *, - bootstrap_servers: Union[str, List[str]], + bootstrap_servers: str | list[str], client_id: str, topic: str, - partition: Optional[int], - key: Optional[Any], + partition: int | None, + key: Any | None, ) -> None: span.set_attribute( messaging_attributes.MESSAGING_SYSTEM, @@ -173,11 +173,11 @@ def _enrich_base_span( def _enrich_send_span( span: Span, *, - bootstrap_servers: Union[str, List[str]], + bootstrap_servers: str | list[str], client_id: str, topic: str, - partition: Optional[int], - key: Optional[str], + partition: int | None, + key: str | None, ) -> None: if not span.is_recording(): return @@ -201,12 +201,12 @@ def _enrich_send_span( def _enrich_anext_span( span: Span, *, - bootstrap_servers: Union[str, List[str]], + bootstrap_servers: str | list[str], client_id: str, - consumer_group: Optional[str], + consumer_group: str | None, topic: str, - partition: Optional[int], - key: Optional[str], + partition: int | None, + key: str | None, offset: int, ) -> None: if not span.is_recording(): @@ -257,8 +257,8 @@ def _wrap_send( async def _traced_send( func: Callable[..., Awaitable[None]], instance: aiokafka.AIOKafkaProducer, - args: Tuple[Any], - kwargs: Dict[str, Any], + args: tuple[Any], + kwargs: dict[str, Any], ) -> None: headers = _extract_send_headers(args, kwargs) if headers is None: @@ -303,11 +303,11 @@ async def _create_consumer_span( async_consume_hook: ConsumeHookT, record: ConsumerRecord, extracted_context: Context, - bootstrap_servers: Union[str, List[str]], + bootstrap_servers: str | list[str], client_id: str, - consumer_group: Optional[str], - args: Tuple[Any], - kwargs: Dict[str, Any], + consumer_group: str | None, + args: tuple[Any], + kwargs: dict[str, Any], ): span_name = _get_span_name("receive", record.topic) with tracer.start_as_current_span( @@ -341,8 +341,8 @@ def _wrap_getone( async def _traced_next( func: Callable[..., Awaitable[aiokafka.ConsumerRecord]], instance: aiokafka.AIOKafkaConsumer, - args: Tuple[Any], - kwargs: Dict[str, Any], + args: tuple[Any], + kwargs: dict[str, Any], ) -> aiokafka.ConsumerRecord: record = await func(*args, **kwargs) diff --git a/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_instrumentation.py index 8211566239..23bacc5c60 100644 --- a/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_instrumentation.py @@ -11,9 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import uuid -from typing import Any, List, Sequence, Tuple +from typing import Any, Sequence from unittest import IsolatedAsyncioTestCase, TestCase, mock from aiokafka import ( @@ -57,7 +58,7 @@ def test_instrument_api(self) -> None: class TestAIOKafkaInstrumentation(TestBase, IsolatedAsyncioTestCase): @staticmethod def consumer_record_factory( - number: int, headers: Tuple[Tuple[str, bytes], ...] + number: int, headers: tuple[tuple[str, bytes], ...] ) -> ConsumerRecord: return ConsumerRecord( f"topic_{number}", @@ -309,7 +310,7 @@ async def test_send_produce_hook(self) -> None: async_produce_hook_mock.assert_awaited_once() def _compare_spans( - self, spans: Sequence[ReadableSpan], expected_spans: List[dict] + self, spans: Sequence[ReadableSpan], expected_spans: list[dict] ) -> None: self.assertEqual(len(spans), len(expected_spans)) for span, expected_span in zip(spans, expected_spans): diff --git a/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_utils.py b/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_utils.py index 09a8655309..b89cfaa90d 100644 --- a/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_utils.py +++ b/instrumentation/opentelemetry-instrumentation-aiokafka/tests/test_utils.py @@ -42,7 +42,7 @@ def test_context_setter(self) -> None: carrier_list = [("key1", b"val1")] context_setter.set(carrier_list, "key2", "val2") - self.assertTrue(("key2", "val2".encode()) in carrier_list) + self.assertTrue(("key2", b"val2") in carrier_list) def test_context_getter(self) -> None: context_setter = AIOKafkaContextSetter() diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py index 4e6257fbb1..baf333b141 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/aiopg_integration.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import asyncio import typing from collections.abc import Coroutine @@ -34,8 +36,8 @@ class AiopgIntegration(DatabaseApiIntegration): async def wrapped_connection( self, connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): """Add object proxy to connection object.""" connection = await connect_method(*args, **kwargs) @@ -101,8 +103,8 @@ async def traced_execution( self, cursor, query_method: typing.Callable[..., typing.Any], - *args: typing.Tuple[typing.Any, typing.Any], - **kwargs: typing.Dict[typing.Any, typing.Any], + *args: tuple[typing.Any, typing.Any], + **kwargs: dict[typing.Any, typing.Any], ): name = "" if args: diff --git a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py index 06098ee7a0..abf4d20c59 100644 --- a/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py +++ b/instrumentation/opentelemetry-instrumentation-aiopg/src/opentelemetry/instrumentation/aiopg/wrappers.py @@ -30,6 +30,8 @@ --- """ +from __future__ import annotations + import logging import typing @@ -52,8 +54,8 @@ def trace_integration( database_system: str, - connection_attributes: typing.Dict = None, - tracer_provider: typing.Optional[TracerProvider] = None, + connection_attributes: dict = None, + tracer_provider: TracerProvider | None = None, ): """Integrate with aiopg library. based on dbapi integration, where replaced sync wrap methods to async @@ -79,9 +81,9 @@ def trace_integration( def wrap_connect( name: str, database_system: str, - connection_attributes: typing.Dict = None, + connection_attributes: dict = None, version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, + tracer_provider: TracerProvider | None = None, ): """Integrate with aiopg library. https://github.com/aio-libs/aiopg @@ -101,8 +103,8 @@ def wrap_connect( def wrap_connect_( wrapped: typing.Callable[..., typing.Any], instance: typing.Any, - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): db_integration = AiopgIntegration( name, @@ -133,9 +135,9 @@ def instrument_connection( name: str, connection, database_system: str, - connection_attributes: typing.Dict = None, + connection_attributes: dict = None, version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, + tracer_provider: TracerProvider | None = None, ): """Enable instrumentation in a database connection. @@ -187,16 +189,16 @@ def uninstrument_connection(connection): def wrap_create_pool( name: str, database_system: str, - connection_attributes: typing.Dict = None, + connection_attributes: dict = None, version: str = "", - tracer_provider: typing.Optional[TracerProvider] = None, + tracer_provider: TracerProvider | None = None, ): # pylint: disable=unused-argument def wrap_create_pool_( wrapped: typing.Callable[..., typing.Any], instance: typing.Any, - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): db_integration = AiopgIntegration( name, diff --git a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py index b060095160..542b87454b 100644 --- a/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-asgi/src/opentelemetry/instrumentation/asgi/__init__.py @@ -196,7 +196,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A from collections import defaultdict from functools import wraps from timeit import default_timer -from typing import Any, Awaitable, Callable, DefaultDict, Tuple +from typing import Any, Awaitable, Callable from asgiref.compatibility import guarantee_single_callable @@ -264,9 +264,7 @@ def client_response_hook(span: Span, scope: dict[str, Any], message: dict[str, A class ASGIGetter(Getter[dict]): - def get( - self, carrier: dict, key: str - ) -> typing.Optional[typing.List[str]]: + def get(self, carrier: dict, key: str) -> list[str] | None: """Getter implementation to retrieve a HTTP header value from the ASGI scope. @@ -292,7 +290,7 @@ def get( return None return decoded - def keys(self, carrier: dict) -> typing.List[str]: + def keys(self, carrier: dict) -> list[str]: headers = carrier.get("headers") or [] return [_decode_header_item(_key) for (_key, _value) in headers] @@ -403,7 +401,7 @@ def collect_custom_headers_attributes( Refer specifications: - https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/semantic_conventions/http.md#http-request-and-response-headers """ - headers: DefaultDict[str, list[str]] = defaultdict(list) + headers: defaultdict[str, list[str]] = defaultdict(list) raw_headers = scope_or_response_message.get("headers") if raw_headers: for key, value in raw_headers: @@ -460,7 +458,7 @@ def set_status_code( ) -def get_default_span_details(scope: dict) -> Tuple[str, dict]: +def get_default_span_details(scope: dict) -> tuple[str, dict]: """ Default span name is the HTTP method and URL path, or just the method. https://github.com/open-telemetry/opentelemetry-specification/pull/3165 @@ -483,8 +481,8 @@ def get_default_span_details(scope: dict) -> Tuple[str, dict]: def _collect_target_attribute( - scope: typing.Dict[str, typing.Any], -) -> typing.Optional[str]: + scope: dict[str, typing.Any], +) -> str | None: """ Returns the target path as defined by the Semantic Conventions. diff --git a/instrumentation/opentelemetry-instrumentation-asyncio/src/opentelemetry/instrumentation/asyncio/utils.py b/instrumentation/opentelemetry-instrumentation-asyncio/src/opentelemetry/instrumentation/asyncio/utils.py index 15c78ae1ce..b8109ca4e3 100644 --- a/instrumentation/opentelemetry-instrumentation-asyncio/src/opentelemetry/instrumentation/asyncio/utils.py +++ b/instrumentation/opentelemetry-instrumentation-asyncio/src/opentelemetry/instrumentation/asyncio/utils.py @@ -11,8 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import os -from typing import Set # pylint: disable=no-name-in-module from opentelemetry.instrumentation.asyncio.environment_variables import ( @@ -22,7 +23,7 @@ ) -def separate_coro_names_by_comma(coro_names: str) -> Set[str]: +def separate_coro_names_by_comma(coro_names: str) -> set[str]: """ Function to separate the coroutines to be traced by comma """ diff --git a/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py b/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py index 4ac1e9c873..bf43a6e7da 100644 --- a/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py +++ b/instrumentation/opentelemetry-instrumentation-aws-lambda/tests/test_aws_lambda_instrumentation_manual.py @@ -11,10 +11,12 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import os from dataclasses import dataclass from importlib import import_module, reload -from typing import Any, Callable, Dict +from typing import Any, Callable from unittest import mock from opentelemetry import propagate @@ -185,7 +187,7 @@ def test_parent_context_from_lambda_event(self): class TestCase: name: str custom_extractor: Callable[[Any], None] - context: Dict + context: dict expected_traceid: int expected_parentid: int xray_traceid: str diff --git a/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py b/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py index 83e5ed70bc..06445f61b0 100644 --- a/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-boto3sqs/src/opentelemetry/instrumentation/boto3sqs/__init__.py @@ -29,8 +29,10 @@ --- """ +from __future__ import annotations + import logging -from typing import Any, Collection, Dict, Generator, List, Mapping, Optional +from typing import Any, Collection, Generator, Mapping import boto3.session import botocore.client @@ -59,7 +61,7 @@ class Boto3SQSGetter(Getter[CarrierT]): - def get(self, carrier: CarrierT, key: str) -> Optional[List[str]]: + def get(self, carrier: CarrierT, key: str) -> list[str] | None: msg_attr = carrier.get(key) if not isinstance(msg_attr, Mapping): return None @@ -70,7 +72,7 @@ def get(self, carrier: CarrierT, key: str) -> Optional[List[str]]: return [value] - def keys(self, carrier: CarrierT) -> List[str]: + def keys(self, carrier: CarrierT) -> list[str]: return list(carrier.keys()) @@ -95,7 +97,7 @@ def set(self, carrier: CarrierT, key: str, value: str) -> None: # pylint: disable=attribute-defined-outside-init class Boto3SQSInstrumentor(BaseInstrumentor): - received_messages_spans: Dict[str, Span] = {} + received_messages_spans: dict[str, Span] = {} current_span_related_to_token: Span = None current_context_token = None @@ -145,9 +147,9 @@ def _enrich_span( span: Span, queue_name: str, queue_url: str, - conversation_id: Optional[str] = None, - operation: Optional[MessagingOperationValues] = None, - message_id: Optional[str] = None, + conversation_id: str | None = None, + operation: MessagingOperationValues | None = None, + message_id: str | None = None, ) -> None: if not span.is_recording(): return @@ -194,7 +196,7 @@ def _create_processing_span( queue_name: str, queue_url: str, receipt_handle: str, - message: Dict[str, Any], + message: dict[str, Any], ) -> None: message_attributes = message.get("MessageAttributes", {}) links = [] @@ -261,7 +263,7 @@ def send_batch_wrapper(wrapped, instance, args, kwargs): queue_name = Boto3SQSInstrumentor._extract_queue_name_from_url( queue_url ) - ids_to_spans: Dict[str, Span] = {} + ids_to_spans: dict[str, Span] = {} for entry in entries: entry_id = entry["Id"] span = self._tracer.start_span( @@ -418,8 +420,8 @@ def _un_decorate_sqs(sqs_class: type) -> None: setattr(sqs_class, _IS_SQS_INSTRUMENTED_ATTRIBUTE, False) - def _instrument(self, **kwargs: Dict[str, Any]) -> None: - self._tracer_provider: Optional[TracerProvider] = kwargs.get( + def _instrument(self, **kwargs: dict[str, Any]) -> None: + self._tracer_provider: TracerProvider | None = kwargs.get( "tracer_provider" ) self._tracer: Tracer = trace.get_tracer( @@ -433,7 +435,7 @@ def _instrument(self, **kwargs: Dict[str, Any]) -> None: for client_cls in botocore.client.BaseClient.__subclasses__(): self._decorate_sqs(client_cls) - def _uninstrument(self, **kwargs: Dict[str, Any]) -> None: + def _uninstrument(self, **kwargs: dict[str, Any]) -> None: unwrap(boto3.session.Session, "client") for client_cls in botocore.client.BaseClient.__subclasses__(): diff --git a/instrumentation/opentelemetry-instrumentation-boto3sqs/tests/test_boto3sqs_instrumentation.py b/instrumentation/opentelemetry-instrumentation-boto3sqs/tests/test_boto3sqs_instrumentation.py index 7f7f00cf0a..3020792840 100644 --- a/instrumentation/opentelemetry-instrumentation-boto3sqs/tests/test_boto3sqs_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-boto3sqs/tests/test_boto3sqs_instrumentation.py @@ -13,9 +13,10 @@ # limitations under the License. # pylint: disable=no-name-in-module +from __future__ import annotations from contextlib import contextmanager -from typing import Any, Dict +from typing import Any from unittest import TestCase, mock import boto3 @@ -213,7 +214,7 @@ def _mocked_endpoint(self, response): ): yield - def _assert_injected_span(self, msg_attrs: Dict[str, Any], span: Span): + def _assert_injected_span(self, msg_attrs: dict[str, Any], span: Span): trace_parent = msg_attrs["traceparent"]["StringValue"] ctx = span.get_span_context() self.assertEqual( @@ -251,7 +252,7 @@ def _make_message(message_id: str, body: str, receipt: str): } def _add_trace_parent( - self, message: Dict[str, Any], trace_id: int, span_id: int + self, message: dict[str, Any], trace_id: int, span_id: int ): message["MessageAttributes"]["traceparent"] = { "StringValue": self._to_trace_parent(trace_id, span_id), diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py index 0481b248aa..1e4a795d24 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/__init__.py @@ -78,8 +78,10 @@ def response_hook(span, service_name, operation_name, result): ec2.describe_instances() """ +from __future__ import annotations + import logging -from typing import Any, Callable, Collection, Dict, Optional, Tuple +from typing import Any, Callable, Collection from botocore.client import BaseClient from botocore.endpoint import Endpoint @@ -267,8 +269,8 @@ def _apply_response_attributes(span: Span, result): def _determine_call_context( - client: BaseClient, args: Tuple[str, Dict[str, Any]] -) -> Optional[_AwsSdkCallContext]: + client: BaseClient, args: tuple[str, dict[str, Any]] +) -> _AwsSdkCallContext | None: try: call_context = _AwsSdkCallContext(client, args) diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/dynamodb.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/dynamodb.py index 1a5f01b6ce..3170148976 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/dynamodb.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/dynamodb.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import abc import inspect @@ -35,15 +36,15 @@ # converter functions -def _conv_val_to_single_attr_tuple(value: str) -> Tuple[str]: +def _conv_val_to_single_attr_tuple(value: str) -> tuple[str]: return None if value is None else (value,) -def _conv_dict_to_key_tuple(value: Dict[str, Any]) -> Optional[Tuple[str]]: +def _conv_dict_to_key_tuple(value: dict[str, Any]) -> tuple[str] | None: return tuple(value.keys()) if isinstance(value, Dict) else None -def _conv_list_to_json_list(value: List) -> Optional[List[str]]: +def _conv_list_to_json_list(value: list) -> list[str] | None: return ( [json.dumps(item) for item in value] if isinstance(value, List) @@ -51,15 +52,15 @@ def _conv_list_to_json_list(value: List) -> Optional[List[str]]: ) -def _conv_val_to_single_json_tuple(value: str) -> Optional[Tuple[str]]: +def _conv_val_to_single_json_tuple(value: str) -> tuple[str] | None: return (json.dumps(value),) if value is not None else None -def _conv_dict_to_json_str(value: Dict) -> Optional[str]: +def _conv_dict_to_json_str(value: dict) -> str | None: return json.dumps(value) if isinstance(value, Dict) else None -def _conv_val_to_len(value) -> Optional[int]: +def _conv_val_to_len(value) -> int | None: return len(value) if value is not None else None @@ -393,8 +394,8 @@ def on_success(self, span: Span, result: _BotoResultT): def _add_attributes( self, - provider: Dict[str, Any], - attributes: Dict[str, _AttrSpecT], + provider: dict[str, Any], + attributes: dict[str, _AttrSpecT], setter: Callable[[str, AttributeValue], None], ): if attributes is None: @@ -412,7 +413,7 @@ def _add_attributes( setter(attr_key, value) @staticmethod - def _get_attr_value(provider: Dict[str, Any], attr_path: _AttributePathT): + def _get_attr_value(provider: dict[str, Any], attr_path: _AttributePathT): if isinstance(attr_path, str): return provider.get(attr_path) diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/lmbd.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/lmbd.py index 57fb8b6794..e107146524 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/lmbd.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/lmbd.py @@ -12,11 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import abc import inspect import json import re -from typing import Dict from opentelemetry.instrumentation.botocore.extensions.types import ( _AttributeMapT, @@ -99,7 +100,7 @@ def _inject_current_span(cls, call_context: _AwsSdkCallContext): # Lambda extension ################################################################################ -_OPERATION_MAPPING: Dict[str, _LambdaOperation] = { +_OPERATION_MAPPING: dict[str, _LambdaOperation] = { op.operation_name(): op for op in globals().values() if inspect.isclass(op) diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/sns.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/sns.py index 9c3df3a2bc..091027b729 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/sns.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/sns.py @@ -11,10 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import abc import inspect -from typing import Any, Dict, MutableMapping, Optional, Tuple +from typing import Any, MutableMapping from opentelemetry.instrumentation.botocore.extensions._messaging import ( inject_propagation_context, @@ -92,7 +93,7 @@ def extract_attributes( @classmethod def _extract_destination_name( cls, call_context: _AwsSdkCallContext - ) -> Tuple[str, bool]: + ) -> tuple[str, bool]: arn = cls._extract_input_arn(call_context) if arn: return arn.rsplit(":", 1)[-1], False @@ -107,7 +108,7 @@ def _extract_destination_name( @classmethod def _extract_input_arn( cls, call_context: _AwsSdkCallContext - ) -> Optional[str]: + ) -> str | None: for input_arn in cls._arn_arg_names: arn = call_context.params.get(input_arn) if arn: @@ -143,7 +144,7 @@ def before_service_call(cls, call_context: _AwsSdkCallContext, span: Span): # SNS extension ################################################################################ -_OPERATION_MAPPING: Dict[str, _SnsOperation] = { +_OPERATION_MAPPING: dict[str, _SnsOperation] = { op.operation_name(): op for op in globals().values() if inspect.isclass(op) diff --git a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/types.py b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/types.py index a3c73af65c..0e7a827823 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/types.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/src/opentelemetry/instrumentation/botocore/extensions/types.py @@ -11,9 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import logging -from typing import Any, Dict, Optional, Tuple +from typing import Any, Dict from opentelemetry.trace import SpanKind from opentelemetry.trace.span import Span @@ -46,7 +47,7 @@ class _AwsSdkCallContext: span_kind: the kind used to create the span. """ - def __init__(self, client: _BotoClientT, args: Tuple[str, Dict[str, Any]]): + def __init__(self, client: _BotoClientT, args: tuple[str, dict[str, Any]]): operation = args[0] try: params = args[1] @@ -64,12 +65,12 @@ def __init__(self, client: _BotoClientT, args: Tuple[str, Dict[str, Any]]): # 'operation' and 'service' are essential for instrumentation. # for all other attributes we extract them defensively. All of them should # usually exist unless some future botocore version moved things. - self.region: Optional[str] = self._get_attr(boto_meta, "region_name") - self.endpoint_url: Optional[str] = self._get_attr( + self.region: str | None = self._get_attr(boto_meta, "region_name") + self.endpoint_url: str | None = self._get_attr( boto_meta, "endpoint_url" ) - self.api_version: Optional[str] = self._get_attr( + self.api_version: str | None = self._get_attr( service_model, "api_version" ) # name of the service in proper casing diff --git a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_sns.py b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_sns.py index 5d6b94f145..2705f55572 100644 --- a/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_sns.py +++ b/instrumentation/opentelemetry-instrumentation-botocore/tests/test_botocore_sns.py @@ -12,8 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + import contextlib -from typing import Any, Dict +from typing import Any from unittest import mock import botocore.session @@ -83,7 +85,7 @@ def assert_span(self, name: str) -> Span: return span - def assert_injected_span(self, message_attrs: Dict[str, Any], span: Span): + def assert_injected_span(self, message_attrs: dict[str, Any], span: Span): # traceparent: --- trace_parent = message_attrs["traceparent"]["StringValue"].split("-") span_context = span.get_span_context() diff --git a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py index d7ca77af8a..8b4ab331f9 100644 --- a/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py +++ b/instrumentation/opentelemetry-instrumentation-celery/src/opentelemetry/instrumentation/celery/utils.py @@ -15,7 +15,7 @@ from __future__ import annotations import logging -from typing import TYPE_CHECKING, Optional, Tuple +from typing import TYPE_CHECKING from celery import registry # pylint: disable=no-name-in-module from celery.app.task import Task @@ -125,11 +125,11 @@ def set_attributes_from_context(span, context): def attach_context( - task: Optional[Task], + task: Task | None, task_id: str, span: Span, activation: AbstractContextManager[Span], - token: Optional[object], + token: object | None, is_publish: bool = False, ) -> None: """Helper to propagate a `Span`, `ContextManager` and context token @@ -176,7 +176,7 @@ def detach_context(task, task_id, is_publish=False) -> None: def retrieve_context( task, task_id, is_publish=False -) -> Optional[Tuple[Span, AbstractContextManager[Span], Optional[object]]]: +) -> tuple[Span, AbstractContextManager[Span], object | None] | None: """Helper to retrieve an active `Span`, `ContextManager` and context token stored in a `Task` instance """ diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py index 60dc13e675..f204bdfe98 100644 --- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/src/opentelemetry/instrumentation/confluent_kafka/utils.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from logging import getLogger -from typing import List, Optional from opentelemetry import context, propagate from opentelemetry.propagators import textmap @@ -38,7 +39,7 @@ def extract_produce_headers(args, kwargs): class KafkaContextGetter(textmap.Getter): - def get(self, carrier: textmap.CarrierT, key: str) -> Optional[List[str]]: + def get(self, carrier: textmap.CarrierT, key: str) -> list[str] | None: if carrier is None: return None @@ -53,7 +54,7 @@ def get(self, carrier: textmap.CarrierT, key: str) -> Optional[List[str]]: return None - def keys(self, carrier: textmap.CarrierT) -> List[str]: + def keys(self, carrier: textmap.CarrierT) -> list[str]: if carrier is None: return [] @@ -112,9 +113,9 @@ def _get_links_from_records(records): def _enrich_span( span, topic, - partition: Optional[int] = None, - offset: Optional[int] = None, - operation: Optional[MessagingOperationValues] = None, + partition: int | None = None, + offset: int | None = None, + operation: MessagingOperationValues | None = None, ): if not span.is_recording(): return diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/test_instrumentation.py b/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/test_instrumentation.py index 986116900d..413a7f1d54 100644 --- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/test_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/test_instrumentation.py @@ -89,12 +89,12 @@ def test_context_setter(self) -> None: carrier_dict = {"key1": "val1"} context_setter.set(carrier_dict, "key2", "val2") self.assertGreaterEqual( - carrier_dict.items(), {"key2": "val2".encode()}.items() + carrier_dict.items(), {"key2": b"val2"}.items() ) carrier_list = [("key1", "val1")] context_setter.set(carrier_list, "key2", "val2") - self.assertTrue(("key2", "val2".encode()) in carrier_list) + self.assertTrue(("key2", b"val2") in carrier_list) def test_context_getter(self) -> None: context_setter = KafkaContextSetter() diff --git a/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/utils.py b/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/utils.py index f87dbd6576..1f181b2553 100644 --- a/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/utils.py +++ b/instrumentation/opentelemetry-instrumentation-confluent-kafka/tests/utils.py @@ -1,4 +1,4 @@ -from typing import Optional +from __future__ import annotations from confluent_kafka import Consumer, Producer @@ -26,8 +26,8 @@ def __init__( partition: int, offset: int, headers, - key: Optional[str] = None, - value: Optional[str] = None, + key: str | None = None, + value: str | None = None, ): self._topic = topic self._partition = partition diff --git a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py index ef53d5dc38..2e6ff95759 100644 --- a/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py +++ b/instrumentation/opentelemetry-instrumentation-django/src/opentelemetry/instrumentation/django/middleware/sqlcommenter_middleware.py @@ -11,9 +11,11 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + from contextlib import ExitStack from logging import getLogger -from typing import Any, Type, TypeVar +from typing import Any, TypeVar # pylint: disable=no-name-in-module from django import conf, get_version @@ -58,7 +60,7 @@ class _QueryWrapper: def __init__(self, request) -> None: self.request = request - def __call__(self, execute: Type[T], sql, params, many, context) -> T: + def __call__(self, execute: type[T], sql, params, many, context) -> T: # pylint: disable-msg=too-many-locals with_framework = getattr( conf.settings, "SQLCOMMENTER_WITH_FRAMEWORK", True diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py index fdbad4effb..794b2e488d 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation.py @@ -140,7 +140,7 @@ def setUpClass(cls): f"{cls.__name__} is an abstract base class" ) - super(TestBaseFastAPI, cls).setUpClass() + super().setUpClass() def setUp(self): super().setUp() @@ -218,7 +218,7 @@ def setUpClass(cls): f"{cls.__name__} is an abstract base class" ) - super(TestBaseManualFastAPI, cls).setUpClass() + super().setUpClass() def test_sub_app_fastapi_call(self): """ @@ -271,7 +271,7 @@ def setUpClass(cls): f"{cls.__name__} is an abstract base class" ) - super(TestBaseAutoFastAPI, cls).setUpClass() + super().setUpClass() def test_sub_app_fastapi_call(self): """ diff --git a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation_custom_headers.py b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation_custom_headers.py index 0a1b20155e..03cbcc03d7 100644 --- a/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation_custom_headers.py +++ b/instrumentation/opentelemetry-instrumentation-fastapi/tests/test_fastapi_instrumentation_custom_headers.py @@ -1,5 +1,6 @@ +from __future__ import annotations + from collections.abc import Mapping -from typing import Tuple from unittest.mock import patch import fastapi @@ -18,7 +19,7 @@ class MultiMapping(Mapping): - def __init__(self, *items: Tuple[str, str]): + def __init__(self, *items: tuple[str, str]): self._items = items def __len__(self): diff --git a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py index ff0fa93902..0317fc7b20 100644 --- a/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-grpc/src/opentelemetry/instrumentation/grpc/__init__.py @@ -274,8 +274,10 @@ async def serve(): """ +from __future__ import annotations + import os -from typing import Callable, Collection, List, Union +from typing import Callable, Collection import grpc # pylint:disable=import-self from wrapt import wrap_function_wrapper as _wrap @@ -688,7 +690,7 @@ def aio_server_interceptor(tracer_provider=None, filter_=None): ) -def _excluded_service_filter() -> Union[Callable[[object], bool], None]: +def _excluded_service_filter() -> Callable[[object], bool] | None: services = _parse_services( os.environ.get("OTEL_PYTHON_GRPC_EXCLUDED_SERVICES", "") ) @@ -698,7 +700,7 @@ def _excluded_service_filter() -> Union[Callable[[object], bool], None]: return negate(any_of(*filters)) -def _parse_services(excluded_services: str) -> List[str]: +def _parse_services(excluded_services: str) -> list[str]: if excluded_services != "": excluded_service_list = [ s.strip() for s in excluded_services.split(",") diff --git a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py index 27bb3d639d..7e19b115a5 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/src/opentelemetry/instrumentation/httpx/__init__.py @@ -253,17 +253,15 @@ class RequestInfo(typing.NamedTuple): method: bytes url: httpx.URL headers: httpx.Headers | None - stream: typing.Optional[ - typing.Union[httpx.SyncByteStream, httpx.AsyncByteStream] - ] - extensions: typing.Optional[dict] + stream: httpx.SyncByteStream | httpx.AsyncByteStream | None + extensions: dict | None class ResponseInfo(typing.NamedTuple): status_code: int headers: httpx.Headers | None stream: typing.Iterable[bytes] - extensions: typing.Optional[dict] + extensions: dict | None def _get_default_span_name(method: str) -> str: @@ -274,7 +272,7 @@ def _get_default_span_name(method: str) -> str: return method -def _prepare_headers(headers: typing.Optional[Headers]) -> httpx.Headers: +def _prepare_headers(headers: Headers | None) -> httpx.Headers: return httpx.Headers(headers) @@ -311,10 +309,8 @@ def _inject_propagation_headers(headers, args, kwargs): def _extract_response( - response: typing.Union[ - httpx.Response, typing.Tuple[int, Headers, httpx.SyncByteStream, dict] - ], -) -> typing.Tuple[int, Headers, httpx.SyncByteStream, dict, str]: + response: httpx.Response | tuple[int, Headers, httpx.SyncByteStream, dict], +) -> tuple[int, Headers, httpx.SyncByteStream, dict, str]: if isinstance(response, httpx.Response): status_code = response.status_code headers = response.headers @@ -332,7 +328,7 @@ def _extract_response( def _apply_request_client_attributes_to_span( span_attributes: dict, - url: typing.Union[str, URL, httpx.URL], + url: str | URL | httpx.URL, method_original: str, semconv: _StabilityMode, ): @@ -407,9 +403,9 @@ class SyncOpenTelemetryTransport(httpx.BaseTransport): def __init__( self, transport: httpx.BaseTransport, - tracer_provider: typing.Optional[TracerProvider] = None, - request_hook: typing.Optional[RequestHook] = None, - response_hook: typing.Optional[ResponseHook] = None, + tracer_provider: TracerProvider | None = None, + request_hook: RequestHook | None = None, + response_hook: ResponseHook | None = None, ): _OpenTelemetrySemanticConventionStability._initialize() self._sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode( @@ -426,15 +422,15 @@ def __init__( self._request_hook = request_hook self._response_hook = response_hook - def __enter__(self) -> "SyncOpenTelemetryTransport": + def __enter__(self) -> SyncOpenTelemetryTransport: self._transport.__enter__() return self def __exit__( self, - exc_type: typing.Optional[typing.Type[BaseException]] = None, - exc_value: typing.Optional[BaseException] = None, - traceback: typing.Optional[TracebackType] = None, + exc_type: type[BaseException] | None = None, + exc_value: BaseException | None = None, + traceback: TracebackType | None = None, ) -> None: self._transport.__exit__(exc_type, exc_value, traceback) @@ -443,10 +439,7 @@ def handle_request( self, *args, **kwargs, - ) -> typing.Union[ - typing.Tuple[int, "Headers", httpx.SyncByteStream, dict], - httpx.Response, - ]: + ) -> tuple[int, Headers, httpx.SyncByteStream, dict] | httpx.Response: """Add request info to span.""" if not is_http_instrumentation_enabled(): return self._transport.handle_request(*args, **kwargs) @@ -532,9 +525,9 @@ class AsyncOpenTelemetryTransport(httpx.AsyncBaseTransport): def __init__( self, transport: httpx.AsyncBaseTransport, - tracer_provider: typing.Optional[TracerProvider] = None, - request_hook: typing.Optional[AsyncRequestHook] = None, - response_hook: typing.Optional[AsyncResponseHook] = None, + tracer_provider: TracerProvider | None = None, + request_hook: AsyncRequestHook | None = None, + response_hook: AsyncResponseHook | None = None, ): _OpenTelemetrySemanticConventionStability._initialize() self._sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode( @@ -551,25 +544,22 @@ def __init__( self._request_hook = request_hook self._response_hook = response_hook - async def __aenter__(self) -> "AsyncOpenTelemetryTransport": + async def __aenter__(self) -> AsyncOpenTelemetryTransport: await self._transport.__aenter__() return self async def __aexit__( self, - exc_type: typing.Optional[typing.Type[BaseException]] = None, - exc_value: typing.Optional[BaseException] = None, - traceback: typing.Optional[TracebackType] = None, + exc_type: type[BaseException] | None = None, + exc_value: BaseException | None = None, + traceback: TracebackType | None = None, ) -> None: await self._transport.__aexit__(exc_type, exc_value, traceback) # pylint: disable=R0914 async def handle_async_request( self, *args, **kwargs - ) -> typing.Union[ - typing.Tuple[int, "Headers", httpx.AsyncByteStream, dict], - httpx.Response, - ]: + ) -> tuple[int, Headers, httpx.AsyncByteStream, dict] | httpx.Response: """Add request info to span.""" if not is_http_instrumentation_enabled(): return await self._transport.handle_async_request(*args, **kwargs) @@ -872,14 +862,10 @@ async def _handle_async_request_wrapper( # pylint: disable=too-many-locals @classmethod def instrument_client( cls, - client: typing.Union[httpx.Client, httpx.AsyncClient], + client: httpx.Client | httpx.AsyncClient, tracer_provider: TracerProvider = None, - request_hook: typing.Union[ - typing.Optional[RequestHook], typing.Optional[AsyncRequestHook] - ] = None, - response_hook: typing.Union[ - typing.Optional[ResponseHook], typing.Optional[AsyncResponseHook] - ] = None, + request_hook: RequestHook | AsyncRequestHook | None = None, + response_hook: ResponseHook | AsyncResponseHook | None = None, ) -> None: """Instrument httpx Client or AsyncClient @@ -978,7 +964,7 @@ def instrument_client( @staticmethod def uninstrument_client( - client: typing.Union[httpx.Client, httpx.AsyncClient], + client: httpx.Client | httpx.AsyncClient, ): """Disables instrumentation for the given client instance diff --git a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py index 148fe27893..2d7c59af0c 100644 --- a/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py +++ b/instrumentation/opentelemetry-instrumentation-httpx/tests/test_httpx_integration.py @@ -13,6 +13,7 @@ # limitations under the License. # pylint: disable=too-many-lines +from __future__ import annotations import abc import asyncio @@ -75,7 +76,7 @@ HTTP_RESPONSE_BODY = "http.response.body" -def _is_url_tuple(request: "RequestInfo"): +def _is_url_tuple(request: RequestInfo): """Determine if request url format is for httpx versions < 0.20.0.""" return isinstance(request[1], tuple) and len(request[1]) == 4 @@ -85,7 +86,7 @@ def _async_call(coro: typing.Coroutine) -> asyncio.Task: return loop.run_until_complete(coro) -def _response_hook(span, request: "RequestInfo", response: "ResponseInfo"): +def _response_hook(span, request: RequestInfo, response: ResponseInfo): assert _is_url_tuple(request) or isinstance(request.url, httpx.URL) span.set_attribute( HTTP_RESPONSE_BODY, @@ -94,7 +95,7 @@ def _response_hook(span, request: "RequestInfo", response: "ResponseInfo"): async def _async_response_hook( - span: "Span", request: "RequestInfo", response: "ResponseInfo" + span: Span, request: RequestInfo, response: ResponseInfo ): assert _is_url_tuple(request) or isinstance(request.url, httpx.URL) span.set_attribute( @@ -103,23 +104,23 @@ async def _async_response_hook( ) -def _request_hook(span: "Span", request: "RequestInfo"): +def _request_hook(span: Span, request: RequestInfo): assert _is_url_tuple(request) or isinstance(request.url, httpx.URL) url = httpx.URL(request[1]) span.update_name("GET" + str(url)) -async def _async_request_hook(span: "Span", request: "RequestInfo"): +async def _async_request_hook(span: Span, request: RequestInfo): assert _is_url_tuple(request) or isinstance(request.url, httpx.URL) url = httpx.URL(request[1]) span.update_name("GET" + str(url)) -def _no_update_request_hook(span: "Span", request: "RequestInfo"): +def _no_update_request_hook(span: Span, request: RequestInfo): return 123 -async def _async_no_update_request_hook(span: "Span", request: "RequestInfo"): +async def _async_no_update_request_hook(span: Span, request: RequestInfo): return 123 @@ -175,7 +176,7 @@ def tearDown(self): HTTPXClientInstrumentor().uninstrument() def assert_span( - self, exporter: "SpanExporter" = None, num_spans: int = 1 + self, exporter: SpanExporter = None, num_spans: int = 1 ): if exporter is None: exporter = self.memory_exporter @@ -192,8 +193,8 @@ def perform_request( self, url: str, method: str = "GET", - headers: typing.Dict[str, str] = None, - client: typing.Union[httpx.Client, httpx.AsyncClient, None] = None, + headers: dict[str, str] = None, + client: httpx.Client | httpx.AsyncClient | None = None, ): pass @@ -583,9 +584,9 @@ class BaseManualTest(BaseTest, metaclass=abc.ABCMeta): @abc.abstractmethod def create_transport( self, - tracer_provider: typing.Optional["TracerProvider"] = None, - request_hook: typing.Optional["RequestHook"] = None, - response_hook: typing.Optional["ResponseHook"] = None, + tracer_provider: TracerProvider | None = None, + request_hook: RequestHook | None = None, + response_hook: ResponseHook | None = None, **kwargs, ): pass @@ -593,9 +594,9 @@ def create_transport( @abc.abstractmethod def create_client( self, - transport: typing.Union[ - SyncOpenTelemetryTransport, AsyncOpenTelemetryTransport, None - ] = None, + transport: SyncOpenTelemetryTransport + | AsyncOpenTelemetryTransport + | None = None, **kwargs, ): pass @@ -730,9 +731,9 @@ class BaseInstrumentorTest(BaseTest, metaclass=abc.ABCMeta): @abc.abstractmethod def create_client( self, - transport: typing.Union[ - SyncOpenTelemetryTransport, AsyncOpenTelemetryTransport, None - ] = None, + transport: SyncOpenTelemetryTransport + | AsyncOpenTelemetryTransport + | None = None, **kwargs, ): pass @@ -1095,9 +1096,9 @@ def tearDown(self): def create_transport( self, - tracer_provider: typing.Optional["TracerProvider"] = None, - request_hook: typing.Optional["RequestHook"] = None, - response_hook: typing.Optional["ResponseHook"] = None, + tracer_provider: TracerProvider | None = None, + request_hook: RequestHook | None = None, + response_hook: ResponseHook | None = None, **kwargs, ): transport = httpx.HTTPTransport(**kwargs) @@ -1111,7 +1112,7 @@ def create_transport( def create_client( self, - transport: typing.Optional[SyncOpenTelemetryTransport] = None, + transport: SyncOpenTelemetryTransport | None = None, **kwargs, ): return httpx.Client(transport=transport, **kwargs) @@ -1120,8 +1121,8 @@ def perform_request( self, url: str, method: str = "GET", - headers: typing.Dict[str, str] = None, - client: typing.Union[httpx.Client, httpx.AsyncClient, None] = None, + headers: dict[str, str] = None, + client: httpx.Client | httpx.AsyncClient | None = None, ): if client is None: return self.client.request(method, url, headers=headers) @@ -1147,9 +1148,9 @@ def setUp(self): def create_transport( self, - tracer_provider: typing.Optional["TracerProvider"] = None, - request_hook: typing.Optional["AsyncRequestHook"] = None, - response_hook: typing.Optional["AsyncResponseHook"] = None, + tracer_provider: TracerProvider | None = None, + request_hook: AsyncRequestHook | None = None, + response_hook: AsyncResponseHook | None = None, **kwargs, ): transport = httpx.AsyncHTTPTransport(**kwargs) @@ -1163,7 +1164,7 @@ def create_transport( def create_client( self, - transport: typing.Optional[AsyncOpenTelemetryTransport] = None, + transport: AsyncOpenTelemetryTransport | None = None, **kwargs, ): return httpx.AsyncClient(transport=transport, **kwargs) @@ -1172,8 +1173,8 @@ def perform_request( self, url: str, method: str = "GET", - headers: typing.Dict[str, str] = None, - client: typing.Union[httpx.Client, httpx.AsyncClient, None] = None, + headers: dict[str, str] = None, + client: httpx.Client | httpx.AsyncClient | None = None, ): async def _perform_request(): nonlocal client @@ -1207,7 +1208,7 @@ def test_credential_removal(self): class TestSyncInstrumentationIntegration(BaseTestCases.BaseInstrumentorTest): def create_client( self, - transport: typing.Optional[SyncOpenTelemetryTransport] = None, + transport: SyncOpenTelemetryTransport | None = None, **kwargs, ): return httpx.Client(**kwargs) @@ -1216,8 +1217,8 @@ def perform_request( self, url: str, method: str = "GET", - headers: typing.Dict[str, str] = None, - client: typing.Union[httpx.Client, httpx.AsyncClient, None] = None, + headers: dict[str, str] = None, + client: httpx.Client | httpx.AsyncClient | None = None, ): if client is None: return self.client.request(method, url, headers=headers) @@ -1257,7 +1258,7 @@ def setUp(self): def create_client( self, - transport: typing.Optional[AsyncOpenTelemetryTransport] = None, + transport: AsyncOpenTelemetryTransport | None = None, **kwargs, ): return httpx.AsyncClient(**kwargs) @@ -1266,8 +1267,8 @@ def perform_request( self, url: str, method: str = "GET", - headers: typing.Dict[str, str] = None, - client: typing.Union[httpx.Client, httpx.AsyncClient, None] = None, + headers: dict[str, str] = None, + client: httpx.Client | httpx.AsyncClient | None = None, ): async def _perform_request(): nonlocal client diff --git a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py index 3f9bd6f39c..b763845805 100644 --- a/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py +++ b/instrumentation/opentelemetry-instrumentation-kafka-python/src/opentelemetry/instrumentation/kafka/utils.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import json from logging import getLogger from typing import Callable, Dict, List, Optional @@ -92,7 +94,7 @@ def extract_send_partition(instance, args, kwargs): class KafkaContextGetter(textmap.Getter[textmap.CarrierT]): - def get(self, carrier: textmap.CarrierT, key: str) -> Optional[List[str]]: + def get(self, carrier: textmap.CarrierT, key: str) -> list[str] | None: if carrier is None: return None @@ -102,7 +104,7 @@ def get(self, carrier: textmap.CarrierT, key: str) -> Optional[List[str]]: return [value.decode()] return None - def keys(self, carrier: textmap.CarrierT) -> List[str]: + def keys(self, carrier: textmap.CarrierT) -> list[str]: if carrier is None: return [] return [key for (key, value) in carrier] @@ -123,7 +125,7 @@ def set(self, carrier: textmap.CarrierT, key: str, value: str) -> None: def _enrich_span( - span, bootstrap_servers: List[str], topic: str, partition: int + span, bootstrap_servers: list[str], topic: str, partition: int ): if span.is_recording(): span.set_attribute(SpanAttributes.MESSAGING_SYSTEM, "kafka") diff --git a/instrumentation/opentelemetry-instrumentation-logging/src/opentelemetry/instrumentation/logging/constants.py b/instrumentation/opentelemetry-instrumentation-logging/src/opentelemetry/instrumentation/logging/constants.py index 5eb6798231..2d07c2ec36 100644 --- a/instrumentation/opentelemetry-instrumentation-logging/src/opentelemetry/instrumentation/logging/constants.py +++ b/instrumentation/opentelemetry-instrumentation-logging/src/opentelemetry/instrumentation/logging/constants.py @@ -15,7 +15,7 @@ DEFAULT_LOGGING_FORMAT = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s:%(lineno)d] [trace_id=%(otelTraceID)s span_id=%(otelSpanID)s resource.service.name=%(otelServiceName)s trace_sampled=%(otelTraceSampled)s] - %(message)s" -_MODULE_DOC = """ +_MODULE_DOC = f""" The OpenTelemetry ``logging`` integration automatically injects tracing context into log statements. The integration registers a custom log record factory with the the standard library logging module that automatically inject @@ -33,7 +33,7 @@ .. code-block:: - {default_logging_format} + {DEFAULT_LOGGING_FORMAT} Enable trace context injection ------------------------------ @@ -77,7 +77,7 @@ .. code-block:: - {default_logging_format} + {DEFAULT_LOGGING_FORMAT} .. envvar:: OTEL_PYTHON_LOG_LEVEL @@ -136,4 +136,4 @@ are not injected into the log record objects. This means any attempted log statements made after setting the logging format and before enabling this integration will result in KeyError exceptions. Such exceptions are automatically swallowed by the logging module and do not result in crashes but you may still lose out on important log messages. -""".format(default_logging_format=DEFAULT_LOGGING_FORMAT) +""" diff --git a/instrumentation/opentelemetry-instrumentation-logging/tests/test_logging.py b/instrumentation/opentelemetry-instrumentation-logging/tests/test_logging.py index 4045a44204..b1d7ceb280 100644 --- a/instrumentation/opentelemetry-instrumentation-logging/tests/test_logging.py +++ b/instrumentation/opentelemetry-instrumentation-logging/tests/test_logging.py @@ -11,9 +11,9 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import logging -from typing import Optional from unittest import mock import pytest @@ -30,8 +30,8 @@ class FakeTracerProvider: def get_tracer( # pylint: disable=no-self-use self, instrumenting_module_name: str, - instrumenting_library_version: Optional[str] = None, - schema_url: Optional[str] = None, + instrumenting_library_version: str | None = None, + schema_url: str | None = None, ) -> ProxyTracer: return ProxyTracer( instrumenting_module_name, diff --git a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/pika_instrumentor.py b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/pika_instrumentor.py index f37f74e396..a856e81008 100644 --- a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/pika_instrumentor.py +++ b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/pika_instrumentor.py @@ -13,8 +13,10 @@ # limitations under the License. # pylint: disable=unnecessary-dunder-call +from __future__ import annotations + from logging import getLogger -from typing import Any, Collection, Dict, Optional +from typing import Any, Collection import pika import wrapt @@ -116,7 +118,7 @@ def _uninstrument_channel_functions(channel: BlockingChannel) -> None: # Make sure that the spans are created inside hash them set as parent and not as brothers def instrument_channel( channel: BlockingChannel, - tracer_provider: Optional[TracerProvider] = None, + tracer_provider: TracerProvider | None = None, publish_hook: utils.HookT = utils.dummy_callback, consume_hook: utils.HookT = utils.dummy_callback, ) -> None: @@ -163,7 +165,7 @@ def uninstrument_channel(channel: BlockingChannel) -> None: def _decorate_channel_function( self, - tracer_provider: Optional[TracerProvider], + tracer_provider: TracerProvider | None, publish_hook: utils.HookT = utils.dummy_callback, consume_hook: utils.HookT = utils.dummy_callback, ) -> None: @@ -182,7 +184,7 @@ def wrapper(wrapped, instance, args, kwargs): @staticmethod def _decorate_basic_consume( channel: BlockingChannel, - tracer: Optional[Tracer], + tracer: Tracer | None, consume_hook: utils.HookT = utils.dummy_callback, ) -> None: def wrapper(wrapped, instance, args, kwargs): @@ -196,7 +198,7 @@ def wrapper(wrapped, instance, args, kwargs): @staticmethod def _decorate_queue_consumer_generator( - tracer_provider: Optional[TracerProvider], + tracer_provider: TracerProvider | None, consume_hook: utils.HookT = utils.dummy_callback, ) -> None: tracer = trace.get_tracer(__name__, __version__, tracer_provider) @@ -212,7 +214,7 @@ def wrapper(wrapped, instance, args, kwargs): _QueueConsumerGeneratorInfo, "__init__", wrapper ) - def _instrument(self, **kwargs: Dict[str, Any]) -> None: + def _instrument(self, **kwargs: dict[str, Any]) -> None: tracer_provider: TracerProvider = kwargs.get("tracer_provider", None) publish_hook: utils.HookT = kwargs.get( "publish_hook", utils.dummy_callback @@ -232,7 +234,7 @@ def _instrument(self, **kwargs: Dict[str, Any]) -> None: tracer_provider, consume_hook=consume_hook ) - def _uninstrument(self, **kwargs: Dict[str, Any]) -> None: + def _uninstrument(self, **kwargs: dict[str, Any]) -> None: if hasattr(self, "__opentelemetry_tracer_provider"): delattr(self, "__opentelemetry_tracer_provider") unwrap(BlockingConnection, "channel") diff --git a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py index 2b4d1204ea..322d183dbb 100644 --- a/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py +++ b/instrumentation/opentelemetry-instrumentation-pika/src/opentelemetry/instrumentation/pika/utils.py @@ -1,5 +1,7 @@ +from __future__ import annotations + from logging import getLogger -from typing import Any, Callable, List, Optional +from typing import Any, Callable from pika.adapters.blocking_connection import ( _ConsumerDeliveryEvt, @@ -23,13 +25,13 @@ class _PikaGetter(Getter[CarrierT]): # type: ignore - def get(self, carrier: CarrierT, key: str) -> Optional[List[str]]: + def get(self, carrier: CarrierT, key: str) -> list[str] | None: value = carrier.get(key, None) if value is None: return None return [value] - def keys(self, carrier: CarrierT) -> List[str]: + def keys(self, carrier: CarrierT) -> list[str]: return [] @@ -132,13 +134,13 @@ def decorated_function( def _get_span( tracer: Tracer, - channel: Optional[Channel], + channel: Channel | None, properties: BasicProperties, task_name: str, destination: str, span_kind: SpanKind, - operation: Optional[MessagingOperationValues] = None, -) -> Optional[Span]: + operation: MessagingOperationValues | None = None, +) -> Span | None: if not is_instrumentation_enabled(): return None task_name = properties.type if properties.type else task_name @@ -152,7 +154,7 @@ def _get_span( def _generate_span_name( - task_name: str, operation: Optional[MessagingOperationValues] + task_name: str, operation: MessagingOperationValues | None ) -> str: if not operation: return f"{task_name} send" @@ -161,10 +163,10 @@ def _generate_span_name( def _enrich_span( span: Span, - channel: Optional[Channel], + channel: Channel | None, properties: BasicProperties, task_destination: str, - operation: Optional[MessagingOperationValues] = None, + operation: MessagingOperationValues | None = None, ) -> None: span.set_attribute(SpanAttributes.MESSAGING_SYSTEM, "rabbitmq") if operation: @@ -204,7 +206,7 @@ def __init__( self, wrapped, queue_consumer_generator: _QueueConsumerGeneratorInfo, - tracer: Optional[Tracer], + tracer: Tracer | None, consume_hook: HookT = dummy_callback, ): super().__init__(wrapped) diff --git a/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py index 81390ed48f..1921405eb3 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg/src/opentelemetry/instrumentation/psycopg/__init__.py @@ -137,6 +137,8 @@ --- """ +from __future__ import annotations + import logging import typing from typing import Collection @@ -282,8 +284,8 @@ class DatabaseApiIntegration(dbapi.DatabaseApiIntegration): def wrapped_connection( self, connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): """Add object proxy to connection object.""" base_cursor_factory = kwargs.pop("cursor_factory", None) @@ -300,8 +302,8 @@ class DatabaseApiAsyncIntegration(dbapi.DatabaseApiIntegration): async def wrapped_connection( self, connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): """Add object proxy to connection object.""" base_cursor_factory = kwargs.pop("cursor_factory", None) diff --git a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py index f03ad1de0d..86d6177e2b 100644 --- a/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-psycopg2/src/opentelemetry/instrumentation/psycopg2/__init__.py @@ -137,6 +137,8 @@ --- """ +from __future__ import annotations + import logging import typing from typing import Collection @@ -245,8 +247,8 @@ class DatabaseApiIntegration(dbapi.DatabaseApiIntegration): def wrapped_connection( self, connect_method: typing.Callable[..., typing.Any], - args: typing.Tuple[typing.Any, typing.Any], - kwargs: typing.Dict[typing.Any, typing.Any], + args: tuple[typing.Any, typing.Any], + kwargs: dict[typing.Any, typing.Any], ): """Add object proxy to connection object.""" base_cursor_factory = kwargs.pop("cursor_factory", None) diff --git a/instrumentation/opentelemetry-instrumentation-threading/tests/test_threading.py b/instrumentation/opentelemetry-instrumentation-threading/tests/test_threading.py index 15f67b8d61..40a45a6ff0 100644 --- a/instrumentation/opentelemetry-instrumentation-threading/tests/test_threading.py +++ b/instrumentation/opentelemetry-instrumentation-threading/tests/test_threading.py @@ -11,10 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import threading from concurrent.futures import ThreadPoolExecutor -from typing import List from opentelemetry import trace from opentelemetry.instrumentation.threading import ThreadingInstrumentor @@ -25,7 +25,7 @@ class TestThreading(TestBase): def setUp(self): super().setUp() self._tracer = self.tracer_provider.get_tracer(__name__) - self._mock_span_contexts: List[trace.SpanContext] = [] + self._mock_span_contexts: list[trace.SpanContext] = [] ThreadingInstrumentor().instrument() def tearDown(self): @@ -61,7 +61,7 @@ def test_trace_context_propagation_in_thread_pool_with_multiple_workers( max_workers = 10 executor = ThreadPoolExecutor(max_workers=max_workers) - expected_span_contexts: List[trace.SpanContext] = [] + expected_span_contexts: list[trace.SpanContext] = [] futures_list = [] for num in range(max_workers): with self._tracer.start_as_current_span(f"trace_{num}") as span: diff --git a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py index 3a19450433..c9096a3ab3 100644 --- a/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-tornado/src/opentelemetry/instrumentation/tornado/__init__.py @@ -152,12 +152,14 @@ def client_response_hook(span, future): --- """ +from __future__ import annotations + from collections import namedtuple from functools import partial from logging import getLogger from time import time_ns from timeit import default_timer -from typing import Collection, Dict +from typing import Collection import tornado.web import wrapt @@ -290,7 +292,7 @@ def _uninstrument(self, **kwargs): self.patched_handlers = [] -def _create_server_histograms(meter) -> Dict[str, Histogram]: +def _create_server_histograms(meter) -> dict[str, Histogram]: histograms = { MetricInstruments.HTTP_SERVER_DURATION: meter.create_histogram( name=MetricInstruments.HTTP_SERVER_DURATION, @@ -317,7 +319,7 @@ def _create_server_histograms(meter) -> Dict[str, Histogram]: return histograms -def _create_client_histograms(meter) -> Dict[str, Histogram]: +def _create_client_histograms(meter) -> dict[str, Histogram]: histograms = { MetricInstruments.HTTP_CLIENT_DURATION: meter.create_histogram( name=MetricInstruments.HTTP_CLIENT_DURATION, diff --git a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py index 9fe9996ba4..a0aa084429 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/src/opentelemetry/instrumentation/urllib/__init__.py @@ -74,12 +74,14 @@ def response_hook(span, request_obj, response) --- """ +from __future__ import annotations + import functools import types import typing from http import client from timeit import default_timer -from typing import Collection, Dict +from typing import Collection from urllib.request import ( # pylint: disable=no-name-in-module,import-error OpenerDirector, Request, @@ -205,7 +207,7 @@ def uninstrument_opener(self, opener: OpenerDirector): # pylint: disable=no-sel # pylint: disable=too-many-statements def _instrument( tracer, - histograms: Dict[str, Histogram], + histograms: dict[str, Histogram], request_hook: _RequestHookT = None, response_hook: _ResponseHookT = None, excluded_urls: ExcludeList = None, @@ -395,7 +397,7 @@ def _set_status_code_attribute( def _create_client_histograms( meter, sem_conv_opt_in_mode=_StabilityMode.DEFAULT -) -> Dict[str, Histogram]: +) -> dict[str, Histogram]: histograms = {} if _report_old(sem_conv_opt_in_mode): histograms[MetricInstruments.HTTP_CLIENT_DURATION] = ( @@ -436,7 +438,7 @@ def _create_client_histograms( def _record_histograms( - histograms: Dict[str, Histogram], + histograms: dict[str, Histogram], metric_attributes_old: dict, metric_attributes_new: dict, request_size: int, diff --git a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_metrics_instrumentation.py b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_metrics_instrumentation.py index 72fe6ef66f..629ea87d88 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib/tests/test_metrics_instrumentation.py +++ b/instrumentation/opentelemetry-instrumentation-urllib/tests/test_metrics_instrumentation.py @@ -406,12 +406,10 @@ def test_metric_uninstrument(self): with request.urlopen(self.URL): self.assertEqual( len( - ( - self.memory_metrics_reader.get_metrics_data() - .resource_metrics[0] - .scope_metrics[0] - .metrics - ) + self.memory_metrics_reader.get_metrics_data() + .resource_metrics[0] + .scope_metrics[0] + .metrics ), 3, ) @@ -453,12 +451,10 @@ def test_metric_uninstrument(self): with request.urlopen(self.URL): self.assertEqual( len( - ( - self.memory_metrics_reader.get_metrics_data() - .resource_metrics[0] - .scope_metrics[0] - .metrics - ) + self.memory_metrics_reader.get_metrics_data() + .resource_metrics[0] + .scope_metrics[0] + .metrics ), 3, ) @@ -502,12 +498,10 @@ def test_metric_uninstrument(self): with request.urlopen(self.URL): self.assertEqual( len( - ( - self.memory_metrics_reader.get_metrics_data() - .resource_metrics[0] - .scope_metrics[0] - .metrics - ) + self.memory_metrics_reader.get_metrics_data() + .resource_metrics[0] + .scope_metrics[0] + .metrics ), 3, ) diff --git a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py index 2d1cf4c1b0..cc9699a2b2 100644 --- a/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py +++ b/instrumentation/opentelemetry-instrumentation-urllib3/src/opentelemetry/instrumentation/urllib3/__init__.py @@ -83,6 +83,8 @@ def response_hook( --- """ +from __future__ import annotations + import collections.abc import io import typing @@ -151,10 +153,8 @@ class RequestInfo: # The type annotations here come from ``HTTPConnectionPool.urlopen()``. method: str url: str - headers: typing.Optional[typing.Mapping[str, str]] - body: typing.Union[ - bytes, typing.IO[typing.Any], typing.Iterable[bytes], str, None - ] + headers: typing.Mapping[str, str] | None + body: bytes | typing.IO[typing.Any] | typing.Iterable[bytes] | str | None _UrlFilterT = typing.Optional[typing.Callable[[str], str]] @@ -397,7 +397,7 @@ def instrumented_urlopen(wrapped, instance, args, kwargs): ) -def _get_url_open_arg(name: str, args: typing.List, kwargs: typing.Mapping): +def _get_url_open_arg(name: str, args: list, kwargs: typing.Mapping): arg_idx = _URL_OPEN_ARG_TO_INDEX_MAPPING.get(name) if arg_idx is not None: try: @@ -409,7 +409,7 @@ def _get_url_open_arg(name: str, args: typing.List, kwargs: typing.Mapping): def _get_url( instance: urllib3.connectionpool.HTTPConnectionPool, - args: typing.List, + args: list, kwargs: typing.Mapping, url_filter: _UrlFilterT, ) -> str: @@ -427,7 +427,7 @@ def _get_url( return url -def _get_body_size(body: object) -> typing.Optional[int]: +def _get_body_size(body: object) -> int | None: if body is None: return 0 if isinstance(body, collections.abc.Sized): @@ -437,7 +437,7 @@ def _get_body_size(body: object) -> typing.Optional[int]: return None -def _should_append_port(scheme: str, port: typing.Optional[int]) -> bool: +def _should_append_port(scheme: str, port: int | None) -> bool: if not port: return False if scheme == "http" and port == 80: @@ -447,7 +447,7 @@ def _should_append_port(scheme: str, port: typing.Optional[int]) -> bool: return True -def _prepare_headers(urlopen_kwargs: typing.Dict) -> typing.Dict: +def _prepare_headers(urlopen_kwargs: dict) -> dict: headers = urlopen_kwargs.get("headers") # avoid modifying original headers on inject @@ -547,7 +547,7 @@ def _record_metrics( response_size_histogram_old: Histogram, response_size_histogram_new: Histogram, duration_s: float, - request_size: typing.Optional[int], + request_size: int | None, response_size: int, sem_conv_opt_in_mode: _StabilityMode = _StabilityMode.DEFAULT, ): diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py index cc0ac68f1c..99199c967f 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/bootstrap.py @@ -11,6 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations import argparse import logging @@ -22,7 +23,6 @@ SubprocessError, check_call, ) -from typing import Optional from packaging.requirements import Requirement @@ -141,8 +141,8 @@ def _run_install(default_instrumentations, libraries): def run( - default_instrumentations: Optional[list] = None, - libraries: Optional[list] = None, + default_instrumentations: list | None = None, + libraries: list | None = None, ) -> None: action_install = "install" action_requirements = "requirements" diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py index 018595996f..bb8a93c74b 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/propagators.py @@ -23,7 +23,8 @@ https://w3c.github.io/trace-context/#trace-context-http-response-headers-format """ -import typing +from __future__ import annotations + from abc import ABC, abstractmethod from opentelemetry import trace @@ -91,7 +92,7 @@ class ResponsePropagator(ABC): def inject( self, carrier: textmap.CarrierT, - context: typing.Optional[Context] = None, + context: Context | None = None, setter: textmap.Setter = default_setter, ) -> None: """Injects SpanContext into the HTTP response carrier.""" @@ -103,7 +104,7 @@ class TraceResponsePropagator(ResponsePropagator): def inject( self, carrier: textmap.CarrierT, - context: typing.Optional[Context] = None, + context: Context | None = None, setter: textmap.Setter = default_setter, ) -> None: """Injects SpanContext into the HTTP response carrier.""" diff --git a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py index d5bf5db7fd..6fb3ad99fc 100644 --- a/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py +++ b/opentelemetry-instrumentation/src/opentelemetry/instrumentation/utils.py @@ -18,7 +18,7 @@ from contextlib import contextmanager from importlib import import_module from re import escape, sub -from typing import Any, Dict, Generator, Sequence +from typing import Any, Generator, Sequence from wrapt import ObjectProxy @@ -46,8 +46,8 @@ def extract_attributes_from_object( - obj: Any, attributes: Sequence[str], existing: Dict[str, str] | None = None -) -> Dict[str, str]: + obj: Any, attributes: Sequence[str], existing: dict[str, str] | None = None +) -> dict[str, str]: extracted: dict[str, str] = {} if existing: extracted.update(existing) diff --git a/processor/opentelemetry-processor-baggage/src/opentelemetry/processor/baggage/processor.py b/processor/opentelemetry-processor-baggage/src/opentelemetry/processor/baggage/processor.py index 7e09e591e0..ba9cd848a9 100644 --- a/processor/opentelemetry-processor-baggage/src/opentelemetry/processor/baggage/processor.py +++ b/processor/opentelemetry-processor-baggage/src/opentelemetry/processor/baggage/processor.py @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. -from typing import Callable, Optional +from __future__ import annotations + +from typing import Callable from opentelemetry.baggage import get_all as get_all_baggage from opentelemetry.context import Context @@ -54,7 +56,7 @@ def __init__(self, baggage_key_predicate: BaggageKeyPredicateT) -> None: self._baggage_key_predicate = baggage_key_predicate def on_start( - self, span: "Span", parent_context: Optional[Context] = None + self, span: Span, parent_context: Context | None = None ) -> None: baggage = get_all_baggage(parent_context) for key, value in baggage.items(): diff --git a/propagator/opentelemetry-propagator-aws-xray/src/opentelemetry/propagators/aws/aws_xray_propagator.py b/propagator/opentelemetry-propagator-aws-xray/src/opentelemetry/propagators/aws/aws_xray_propagator.py index d9b99f35ca..5d454b151f 100644 --- a/propagator/opentelemetry-propagator-aws-xray/src/opentelemetry/propagators/aws/aws_xray_propagator.py +++ b/propagator/opentelemetry-propagator-aws-xray/src/opentelemetry/propagators/aws/aws_xray_propagator.py @@ -56,8 +56,9 @@ .. _trace header: https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader """ +from __future__ import annotations + import logging -import typing from os import environ from opentelemetry import trace @@ -114,7 +115,7 @@ class AwsXRayPropagator(TextMapPropagator): def extract( self, carrier: CarrierT, - context: typing.Optional[Context] = None, + context: Context | None = None, getter: Getter[CarrierT] = default_getter, ) -> Context: if context is None: @@ -276,7 +277,7 @@ def _parse_sampled_flag(sampled_flag_str): def inject( self, carrier: CarrierT, - context: typing.Optional[Context] = None, + context: Context | None = None, setter: Setter[CarrierT] = default_setter, ) -> None: span = trace.get_current_span(context=context) @@ -337,7 +338,7 @@ class AwsXRayLambdaPropagator(AwsXRayPropagator): def extract( self, carrier: CarrierT, - context: typing.Optional[Context] = None, + context: Context | None = None, getter: Getter[CarrierT] = default_getter, ) -> Context: xray_context = super().extract(carrier, context=context, getter=getter) diff --git a/propagator/opentelemetry-propagator-ot-trace/src/opentelemetry/propagators/ot_trace/__init__.py b/propagator/opentelemetry-propagator-ot-trace/src/opentelemetry/propagators/ot_trace/__init__.py index 7924fe0b57..692d5daaac 100644 --- a/propagator/opentelemetry-propagator-ot-trace/src/opentelemetry/propagators/ot_trace/__init__.py +++ b/propagator/opentelemetry-propagator-ot-trace/src/opentelemetry/propagators/ot_trace/__init__.py @@ -12,8 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. +from __future__ import annotations + from re import compile as re_compile -from typing import Any, Iterable, Optional +from typing import Any, Iterable from opentelemetry.baggage import get_all, set_baggage from opentelemetry.context import Context @@ -52,7 +54,7 @@ class OTTracePropagator(TextMapPropagator): def extract( self, carrier: CarrierT, - context: Optional[Context] = None, + context: Context | None = None, getter: Getter[CarrierT] = default_getter, ) -> Context: if context is None: @@ -110,7 +112,7 @@ def extract( def inject( self, carrier: CarrierT, - context: Optional[Context] = None, + context: Context | None = None, setter: Setter[CarrierT] = default_setter, ) -> None: span_context = get_current_span(context).get_span_context() @@ -169,7 +171,7 @@ def fields(self): def _extract_first_element( items: Iterable[CarrierT], default: Any = None, -) -> Optional[CarrierT]: +) -> CarrierT | None: if items is None: return default return next(iter(items), None) diff --git a/pyproject.toml b/pyproject.toml index 6ba2e933c3..3dabcb4c0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,14 +12,16 @@ output-format = "concise" # https://docs.astral.sh/ruff/linter/#rule-selection # pylint: https://github.com/astral-sh/ruff/issues/970 select = [ - "I", # isort - "F", # pyflakes - "E", # pycodestyle errors - "W", # pycodestyle warnings - "PLC", # pylint convention - "PLE", # pylint error - "Q", # flake8-quotes - "A", # flake8-builtins + "I", # https://docs.astral.sh/ruff/rules/#isort-i + "F", # https://docs.astral.sh/ruff/rules/#pyflakes-f + "E", # https://docs.astral.sh/ruff/rules/#error-e + "W", # https://docs.astral.sh/ruff/rules/#warning-w + "PLC", # https://docs.astral.sh/ruff/rules/#convention-c + "PLE", # https://docs.astral.sh/ruff/rules/#error-e_1 + "Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q + "A", # https://docs.astral.sh/ruff/rules/#flake8-builtins-a + "UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up + "FA" # https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa ] ignore = [ "E501", # line-too-long diff --git a/resource/opentelemetry-resource-detector-azure/src/opentelemetry/resource/detector/azure/_utils.py b/resource/opentelemetry-resource-detector-azure/src/opentelemetry/resource/detector/azure/_utils.py index 62d00c5a6c..b7198e4489 100644 --- a/resource/opentelemetry-resource-detector-azure/src/opentelemetry/resource/detector/azure/_utils.py +++ b/resource/opentelemetry-resource-detector-azure/src/opentelemetry/resource/detector/azure/_utils.py @@ -11,8 +11,10 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +from __future__ import annotations + from os import environ -from typing import Optional from ._constants import ( _AKS_ARM_NAMESPACE_ID, @@ -39,7 +41,7 @@ def _can_ignore_vm_detect() -> bool: return _is_on_aks() or _is_on_app_service() or _is_on_functions() -def _get_azure_resource_uri() -> Optional[str]: +def _get_azure_resource_uri() -> str | None: website_site_name = environ.get(_WEBSITE_SITE_NAME) website_resource_group = environ.get(_WEBSITE_RESOURCE_GROUP) website_owner_name = environ.get(_WEBSITE_OWNER_NAME) diff --git a/scripts/eachdist.py b/scripts/eachdist.py index ca490546eb..5db9a5d4f5 100755 --- a/scripts/eachdist.py +++ b/scripts/eachdist.py @@ -588,11 +588,11 @@ def update_changelog(path, version, new_entry): def update_changelogs(version): today = datetime.now().strftime("%Y-%m-%d") - new_entry = """## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v{version}...HEAD) + new_entry = f"""## [Unreleased](https://github.com/open-telemetry/opentelemetry-python/compare/v{version}...HEAD) ## [{version}](https://github.com/open-telemetry/opentelemetry-python/releases/tag/v{version}) - {today} -""".format(version=version, today=today) +""" errors = False try: update_changelog("./CHANGELOG.md", version, new_entry) diff --git a/scripts/update_sha.py b/scripts/update_sha.py index c63b9eda9b..dff60eaf46 100644 --- a/scripts/update_sha.py +++ b/scripts/update_sha.py @@ -41,7 +41,7 @@ def update_sha(sha): yaml = YAML() yaml.preserve_quotes = True for workflow_file in workflow_files: - with open(workflow_file, "r") as file: + with open(workflow_file) as file: workflow = yaml.load(file) workflow["env"]["CORE_REPO_SHA"] = sha with open(workflow_file, "w") as file: diff --git a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py b/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py index 0b9cb3dac5..56a4476b00 100644 --- a/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py +++ b/tests/opentelemetry-docker-tests/tests/celery/test_celery_functional.py @@ -51,17 +51,21 @@ def fn_task(): assert run_span.parent.span_id == async_span.context.span_id assert run_span.context.trace_id == async_span.context.trace_id - assert async_span.instrumentation_info.name == "apply_async/{}".format( - opentelemetry.instrumentation.celery.__name__ + assert ( + async_span.instrumentation_info.name + == f"apply_async/{opentelemetry.instrumentation.celery.__name__}" ) - assert async_span.instrumentation_info.version == "apply_async/{}".format( - opentelemetry.instrumentation.celery.__version__ + assert ( + async_span.instrumentation_info.version + == f"apply_async/{opentelemetry.instrumentation.celery.__version__}" ) - assert run_span.instrumentation_info.name == "run/{}".format( - opentelemetry.instrumentation.celery.__name__ + assert ( + run_span.instrumentation_info.name + == f"run/{opentelemetry.instrumentation.celery.__name__}" ) - assert run_span.instrumentation_info.version == "run/{}".format( - opentelemetry.instrumentation.celery.__version__ + assert ( + run_span.instrumentation_info.version + == f"run/{opentelemetry.instrumentation.celery.__version__}" ) diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py index 48944d58e0..7dab8fb4e5 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_instrument.py @@ -38,9 +38,8 @@ def setUp(self): super().setUp() # create a traced engine with the given arguments SQLAlchemyInstrumentor().instrument() - dsn = ( - "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s" - % POSTGRES_CONFIG + dsn = "postgresql://{user}:{password}@{host}:{port}/{dbname}".format( + **POSTGRES_CONFIG ) self.engine = sqlalchemy.create_engine(dsn) diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mssql.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mssql.py index b92228c5cd..7012e932da 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mssql.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mssql.py @@ -41,8 +41,9 @@ class MssqlConnectorTestCase(SQLAlchemyTestMixin): VENDOR = "mssql" SQL_DB = "opentelemetry-tests" ENGINE_ARGS = { - "url": "mssql+pyodbc://%(user)s:%(password)s@%(host)s:%(port)s/%(database)s?driver=%(driver)s&TrustServerCertificate=%(trusted_connection)s" - % MSSQL_CONFIG + "url": "mssql+pyodbc://{user}:{password}@{host}:{port}/{database}?driver={driver}&TrustServerCertificate={trusted_connection}".format( + **MSSQL_CONFIG + ) } def check_meta(self, span): diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py index 6e4c85cd92..d7c9c5fdbc 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_mysql.py @@ -39,8 +39,9 @@ class MysqlConnectorTestCase(SQLAlchemyTestMixin): VENDOR = "mysql" SQL_DB = "opentelemetry-tests" ENGINE_ARGS = { - "url": "mysql+mysqlconnector://%(user)s:%(password)s@%(host)s:%(port)s/%(database)s" - % MYSQL_CONFIG + "url": "mysql+mysqlconnector://{user}:{password}@{host}:{port}/{database}".format( + **MYSQL_CONFIG + ) } def check_meta(self, span): diff --git a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py index ff664091c8..f071e5712c 100644 --- a/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py +++ b/tests/opentelemetry-docker-tests/tests/sqlalchemy_tests/test_postgres.py @@ -40,8 +40,9 @@ class PostgresTestCase(SQLAlchemyTestMixin): VENDOR = "postgresql" SQL_DB = "opentelemetry-tests" ENGINE_ARGS = { - "url": "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s" - % POSTGRES_CONFIG + "url": "postgresql://{user}:{password}@{host}:{port}/{dbname}".format( + **POSTGRES_CONFIG + ) } def check_meta(self, span): @@ -103,8 +104,9 @@ class PostgresMetricsTestCase(PostgresTestCase): VENDOR = "postgresql" SQL_DB = "opentelemetry-tests" ENGINE_ARGS = { - "url": "postgresql://%(user)s:%(password)s@%(host)s:%(port)s/%(dbname)s" - % POSTGRES_CONFIG + "url": "postgresql://{user}:{password}@{host}:{port}/{dbname}".format( + **POSTGRES_CONFIG + ) } def test_metrics_pool_name(self): diff --git a/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py b/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py index f375e2f7c8..3d0d0e0eca 100644 --- a/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py +++ b/util/opentelemetry-util-http/src/opentelemetry/util/http/httplib.py @@ -23,8 +23,7 @@ import http.client import logging import socket # pylint:disable=unused-import # Used for typing -import typing -from typing import Any, Callable, Collection, TypedDict, cast +from typing import Any, Callable, Collection, TypedDict, TypeVar, cast import wrapt @@ -38,7 +37,7 @@ logger = logging.getLogger(__name__) -R = typing.TypeVar("R") +R = TypeVar("R") class HttpClientInstrumentor(BaseInstrumentor): @@ -84,7 +83,7 @@ def trysetip( state = _getstate() if not state: return True - spanlist: typing.List[Span] = state.get("need_ip") + spanlist: list[Span] = state.get("need_ip") if not spanlist: return True @@ -94,7 +93,7 @@ def trysetip( sock = "" try: - sock: typing.Optional[socket.socket] = conn.sock + sock: socket.socket | None = conn.sock logger.debug("Got socket: %s", sock) if sock is None: return False