sentry-sdk 3.0.0a1__py2.py3-none-any.whl → 3.0.0a3__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sentry-sdk might be problematic. Click here for more details.

Files changed (157) hide show
  1. sentry_sdk/__init__.py +2 -0
  2. sentry_sdk/_compat.py +5 -12
  3. sentry_sdk/_init_implementation.py +7 -7
  4. sentry_sdk/_log_batcher.py +17 -29
  5. sentry_sdk/_lru_cache.py +7 -9
  6. sentry_sdk/_queue.py +2 -4
  7. sentry_sdk/_types.py +11 -18
  8. sentry_sdk/_werkzeug.py +5 -7
  9. sentry_sdk/ai/monitoring.py +44 -31
  10. sentry_sdk/ai/utils.py +3 -4
  11. sentry_sdk/api.py +75 -87
  12. sentry_sdk/attachments.py +10 -12
  13. sentry_sdk/client.py +137 -155
  14. sentry_sdk/consts.py +430 -174
  15. sentry_sdk/crons/api.py +16 -17
  16. sentry_sdk/crons/decorator.py +25 -27
  17. sentry_sdk/debug.py +4 -6
  18. sentry_sdk/envelope.py +46 -112
  19. sentry_sdk/feature_flags.py +9 -15
  20. sentry_sdk/integrations/__init__.py +24 -19
  21. sentry_sdk/integrations/_asgi_common.py +15 -18
  22. sentry_sdk/integrations/_wsgi_common.py +22 -33
  23. sentry_sdk/integrations/aiohttp.py +32 -30
  24. sentry_sdk/integrations/anthropic.py +42 -37
  25. sentry_sdk/integrations/argv.py +3 -4
  26. sentry_sdk/integrations/ariadne.py +16 -18
  27. sentry_sdk/integrations/arq.py +21 -29
  28. sentry_sdk/integrations/asgi.py +63 -37
  29. sentry_sdk/integrations/asyncio.py +14 -16
  30. sentry_sdk/integrations/atexit.py +6 -10
  31. sentry_sdk/integrations/aws_lambda.py +26 -36
  32. sentry_sdk/integrations/beam.py +10 -18
  33. sentry_sdk/integrations/boto3.py +18 -16
  34. sentry_sdk/integrations/bottle.py +25 -34
  35. sentry_sdk/integrations/celery/__init__.py +41 -61
  36. sentry_sdk/integrations/celery/beat.py +23 -27
  37. sentry_sdk/integrations/celery/utils.py +15 -17
  38. sentry_sdk/integrations/chalice.py +8 -10
  39. sentry_sdk/integrations/clickhouse_driver.py +21 -31
  40. sentry_sdk/integrations/cloud_resource_context.py +9 -16
  41. sentry_sdk/integrations/cohere.py +27 -33
  42. sentry_sdk/integrations/dedupe.py +5 -8
  43. sentry_sdk/integrations/django/__init__.py +57 -72
  44. sentry_sdk/integrations/django/asgi.py +26 -34
  45. sentry_sdk/integrations/django/caching.py +23 -19
  46. sentry_sdk/integrations/django/middleware.py +17 -20
  47. sentry_sdk/integrations/django/signals_handlers.py +11 -10
  48. sentry_sdk/integrations/django/templates.py +19 -16
  49. sentry_sdk/integrations/django/transactions.py +16 -11
  50. sentry_sdk/integrations/django/views.py +6 -10
  51. sentry_sdk/integrations/dramatiq.py +21 -21
  52. sentry_sdk/integrations/excepthook.py +10 -10
  53. sentry_sdk/integrations/executing.py +3 -4
  54. sentry_sdk/integrations/falcon.py +27 -42
  55. sentry_sdk/integrations/fastapi.py +13 -16
  56. sentry_sdk/integrations/flask.py +31 -38
  57. sentry_sdk/integrations/gcp.py +13 -16
  58. sentry_sdk/integrations/gnu_backtrace.py +4 -6
  59. sentry_sdk/integrations/gql.py +16 -17
  60. sentry_sdk/integrations/graphene.py +13 -12
  61. sentry_sdk/integrations/grpc/__init__.py +19 -1
  62. sentry_sdk/integrations/grpc/aio/server.py +15 -14
  63. sentry_sdk/integrations/grpc/client.py +19 -9
  64. sentry_sdk/integrations/grpc/consts.py +2 -0
  65. sentry_sdk/integrations/grpc/server.py +12 -8
  66. sentry_sdk/integrations/httpx.py +9 -12
  67. sentry_sdk/integrations/huey.py +13 -20
  68. sentry_sdk/integrations/huggingface_hub.py +18 -18
  69. sentry_sdk/integrations/langchain.py +203 -113
  70. sentry_sdk/integrations/launchdarkly.py +13 -10
  71. sentry_sdk/integrations/litestar.py +37 -35
  72. sentry_sdk/integrations/logging.py +52 -65
  73. sentry_sdk/integrations/loguru.py +127 -57
  74. sentry_sdk/integrations/modules.py +3 -4
  75. sentry_sdk/integrations/openai.py +100 -88
  76. sentry_sdk/integrations/openai_agents/__init__.py +49 -0
  77. sentry_sdk/integrations/openai_agents/consts.py +1 -0
  78. sentry_sdk/integrations/openai_agents/patches/__init__.py +4 -0
  79. sentry_sdk/integrations/openai_agents/patches/agent_run.py +152 -0
  80. sentry_sdk/integrations/openai_agents/patches/models.py +52 -0
  81. sentry_sdk/integrations/openai_agents/patches/runner.py +42 -0
  82. sentry_sdk/integrations/openai_agents/patches/tools.py +84 -0
  83. sentry_sdk/integrations/openai_agents/spans/__init__.py +5 -0
  84. sentry_sdk/integrations/openai_agents/spans/agent_workflow.py +20 -0
  85. sentry_sdk/integrations/openai_agents/spans/ai_client.py +46 -0
  86. sentry_sdk/integrations/openai_agents/spans/execute_tool.py +47 -0
  87. sentry_sdk/integrations/openai_agents/spans/handoff.py +24 -0
  88. sentry_sdk/integrations/openai_agents/spans/invoke_agent.py +41 -0
  89. sentry_sdk/integrations/openai_agents/utils.py +201 -0
  90. sentry_sdk/integrations/openfeature.py +11 -6
  91. sentry_sdk/integrations/pure_eval.py +6 -10
  92. sentry_sdk/integrations/pymongo.py +13 -17
  93. sentry_sdk/integrations/pyramid.py +31 -36
  94. sentry_sdk/integrations/quart.py +23 -28
  95. sentry_sdk/integrations/ray.py +73 -64
  96. sentry_sdk/integrations/redis/__init__.py +7 -4
  97. sentry_sdk/integrations/redis/_async_common.py +25 -12
  98. sentry_sdk/integrations/redis/_sync_common.py +19 -13
  99. sentry_sdk/integrations/redis/modules/caches.py +17 -8
  100. sentry_sdk/integrations/redis/modules/queries.py +9 -8
  101. sentry_sdk/integrations/redis/rb.py +3 -2
  102. sentry_sdk/integrations/redis/redis.py +4 -4
  103. sentry_sdk/integrations/redis/redis_cluster.py +21 -13
  104. sentry_sdk/integrations/redis/redis_py_cluster_legacy.py +3 -2
  105. sentry_sdk/integrations/redis/utils.py +23 -24
  106. sentry_sdk/integrations/rq.py +13 -16
  107. sentry_sdk/integrations/rust_tracing.py +9 -6
  108. sentry_sdk/integrations/sanic.py +34 -46
  109. sentry_sdk/integrations/serverless.py +22 -27
  110. sentry_sdk/integrations/socket.py +27 -15
  111. sentry_sdk/integrations/spark/__init__.py +1 -0
  112. sentry_sdk/integrations/spark/spark_driver.py +45 -83
  113. sentry_sdk/integrations/spark/spark_worker.py +7 -11
  114. sentry_sdk/integrations/sqlalchemy.py +22 -19
  115. sentry_sdk/integrations/starlette.py +86 -90
  116. sentry_sdk/integrations/starlite.py +28 -34
  117. sentry_sdk/integrations/statsig.py +5 -4
  118. sentry_sdk/integrations/stdlib.py +28 -24
  119. sentry_sdk/integrations/strawberry.py +62 -49
  120. sentry_sdk/integrations/sys_exit.py +7 -11
  121. sentry_sdk/integrations/threading.py +12 -14
  122. sentry_sdk/integrations/tornado.py +28 -32
  123. sentry_sdk/integrations/trytond.py +4 -3
  124. sentry_sdk/integrations/typer.py +8 -6
  125. sentry_sdk/integrations/unleash.py +5 -4
  126. sentry_sdk/integrations/wsgi.py +47 -46
  127. sentry_sdk/logger.py +41 -10
  128. sentry_sdk/monitor.py +16 -28
  129. sentry_sdk/opentelemetry/consts.py +11 -4
  130. sentry_sdk/opentelemetry/contextvars_context.py +26 -16
  131. sentry_sdk/opentelemetry/propagator.py +38 -21
  132. sentry_sdk/opentelemetry/sampler.py +51 -34
  133. sentry_sdk/opentelemetry/scope.py +36 -37
  134. sentry_sdk/opentelemetry/span_processor.py +48 -58
  135. sentry_sdk/opentelemetry/tracing.py +58 -14
  136. sentry_sdk/opentelemetry/utils.py +186 -194
  137. sentry_sdk/profiler/continuous_profiler.py +108 -97
  138. sentry_sdk/profiler/transaction_profiler.py +70 -97
  139. sentry_sdk/profiler/utils.py +11 -15
  140. sentry_sdk/scope.py +251 -273
  141. sentry_sdk/scrubber.py +22 -26
  142. sentry_sdk/serializer.py +40 -54
  143. sentry_sdk/session.py +44 -61
  144. sentry_sdk/sessions.py +35 -49
  145. sentry_sdk/spotlight.py +15 -21
  146. sentry_sdk/tracing.py +121 -187
  147. sentry_sdk/tracing_utils.py +104 -122
  148. sentry_sdk/transport.py +131 -157
  149. sentry_sdk/utils.py +232 -309
  150. sentry_sdk/worker.py +16 -28
  151. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/METADATA +3 -3
  152. sentry_sdk-3.0.0a3.dist-info/RECORD +168 -0
  153. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/WHEEL +1 -1
  154. sentry_sdk-3.0.0a1.dist-info/RECORD +0 -154
  155. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/entry_points.txt +0 -0
  156. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/licenses/LICENSE +0 -0
  157. {sentry_sdk-3.0.0a1.dist-info → sentry_sdk-3.0.0a3.dist-info}/top_level.txt +0 -0
sentry_sdk/transport.py CHANGED
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from abc import ABC, abstractmethod
2
3
  import io
3
4
  import os
@@ -14,6 +15,14 @@ try:
14
15
  except ImportError:
15
16
  brotli = None
16
17
 
18
+ try:
19
+ import httpcore
20
+ import h2 # noqa: F401
21
+
22
+ HTTP2_ENABLED = True
23
+ except ImportError:
24
+ HTTP2_ENABLED = False
25
+
17
26
  import urllib3
18
27
  import certifi
19
28
 
@@ -22,20 +31,23 @@ from sentry_sdk.utils import Dsn, logger, capture_internal_exceptions
22
31
  from sentry_sdk.worker import BackgroundWorker
23
32
  from sentry_sdk.envelope import Envelope, Item, PayloadRef
24
33
 
25
- from typing import TYPE_CHECKING, cast, List, Dict
34
+ from typing import TYPE_CHECKING
26
35
 
27
36
  if TYPE_CHECKING:
28
- from typing import Any
29
- from typing import Callable
30
- from typing import DefaultDict
31
- from typing import Iterable
32
- from typing import Mapping
33
- from typing import Optional
34
- from typing import Self
35
- from typing import Tuple
36
- from typing import Type
37
- from typing import Union
38
-
37
+ from typing import (
38
+ List,
39
+ Dict,
40
+ Any,
41
+ Callable,
42
+ DefaultDict,
43
+ Iterable,
44
+ Mapping,
45
+ Optional,
46
+ Tuple,
47
+ Type,
48
+ Union,
49
+ Self,
50
+ )
39
51
  from urllib3.poolmanager import PoolManager
40
52
  from urllib3.poolmanager import ProxyManager
41
53
 
@@ -62,10 +74,9 @@ class Transport(ABC):
62
74
  A transport is used to send an event to sentry.
63
75
  """
64
76
 
65
- parsed_dsn = None # type: Optional[Dsn]
77
+ parsed_dsn: Optional[Dsn] = None
66
78
 
67
- def __init__(self, options=None):
68
- # type: (Self, Optional[Dict[str, Any]]) -> None
79
+ def __init__(self: Self, options: Optional[Dict[str, Any]] = None) -> None:
69
80
  self.options = options
70
81
  if options and options["dsn"] is not None and options["dsn"]:
71
82
  self.parsed_dsn = Dsn(options["dsn"])
@@ -73,8 +84,7 @@ class Transport(ABC):
73
84
  self.parsed_dsn = None
74
85
 
75
86
  @abstractmethod
76
- def capture_envelope(self, envelope):
77
- # type: (Self, Envelope) -> None
87
+ def capture_envelope(self: Self, envelope: Envelope) -> None:
78
88
  """
79
89
  Send an envelope to Sentry.
80
90
 
@@ -85,11 +95,10 @@ class Transport(ABC):
85
95
  pass
86
96
 
87
97
  def flush(
88
- self,
89
- timeout,
90
- callback=None,
91
- ):
92
- # type: (Self, float, Optional[Any]) -> None
98
+ self: Self,
99
+ timeout: float,
100
+ callback: Optional[Any] = None,
101
+ ) -> None:
93
102
  """
94
103
  Wait `timeout` seconds for the current events to be sent out.
95
104
 
@@ -98,8 +107,7 @@ class Transport(ABC):
98
107
  """
99
108
  return None
100
109
 
101
- def kill(self):
102
- # type: (Self) -> None
110
+ def kill(self: Self) -> None:
103
111
  """
104
112
  Forcefully kills the transport.
105
113
 
@@ -109,14 +117,13 @@ class Transport(ABC):
109
117
  return None
110
118
 
111
119
  def record_lost_event(
112
- self,
113
- reason, # type: str
114
- data_category=None, # type: Optional[EventDataCategory]
115
- item=None, # type: Optional[Item]
120
+ self: Self,
121
+ reason: str,
122
+ data_category: Optional[EventDataCategory] = None,
123
+ item: Optional[Item] = None,
116
124
  *,
117
- quantity=1, # type: int
118
- ):
119
- # type: (...) -> None
125
+ quantity: int = 1,
126
+ ) -> None:
120
127
  """This increments a counter for event loss by reason and
121
128
  data category by the given positive-int quantity (default 1).
122
129
 
@@ -133,20 +140,13 @@ class Transport(ABC):
133
140
  """
134
141
  return None
135
142
 
136
- def is_healthy(self):
137
- # type: (Self) -> bool
143
+ def is_healthy(self: Self) -> bool:
138
144
  return True
139
145
 
140
- def __del__(self):
141
- # type: (Self) -> None
142
- try:
143
- self.kill()
144
- except Exception:
145
- pass
146
-
147
146
 
148
- def _parse_rate_limits(header, now=None):
149
- # type: (str, Optional[datetime]) -> Iterable[Tuple[Optional[EventDataCategory], datetime]]
147
+ def _parse_rate_limits(
148
+ header: str, now: Optional[datetime] = None
149
+ ) -> Iterable[Tuple[Optional[str], datetime]]:
150
150
  if now is None:
151
151
  now = datetime.now(timezone.utc)
152
152
 
@@ -157,7 +157,6 @@ def _parse_rate_limits(header, now=None):
157
157
 
158
158
  retry_after = now + timedelta(seconds=int(retry_after_val))
159
159
  for category in categories and categories.split(";") or (None,):
160
- category = cast("Optional[EventDataCategory]", category)
161
160
  yield category, retry_after
162
161
  except (LookupError, ValueError):
163
162
  continue
@@ -168,21 +167,20 @@ class BaseHttpTransport(Transport):
168
167
 
169
168
  TIMEOUT = 30 # seconds
170
169
 
171
- def __init__(self, options):
172
- # type: (Self, Dict[str, Any]) -> None
170
+ def __init__(self: Self, options: Dict[str, Any]) -> None:
173
171
  from sentry_sdk.consts import VERSION
174
172
 
175
173
  Transport.__init__(self, options)
176
174
  assert self.parsed_dsn is not None
177
- self.options = options # type: Dict[str, Any]
175
+ self.options: Dict[str, Any] = options
178
176
  self._worker = BackgroundWorker(queue_size=options["transport_queue_size"])
179
177
  self._auth = self.parsed_dsn.to_auth("sentry.python/%s" % VERSION)
180
- self._disabled_until = {} # type: Dict[Optional[EventDataCategory], datetime]
178
+ self._disabled_until: Dict[Optional[str], datetime] = {}
181
179
  # We only use this Retry() class for the `get_retry_after` method it exposes
182
180
  self._retry = urllib3.util.Retry()
183
- self._discarded_events = defaultdict(
184
- int
185
- ) # type: DefaultDict[Tuple[EventDataCategory, str], int]
181
+ self._discarded_events: DefaultDict[Tuple[EventDataCategory, str], int] = (
182
+ defaultdict(int)
183
+ )
186
184
  self._last_client_report_sent = time.time()
187
185
 
188
186
  self._pool = self._make_pool()
@@ -227,14 +225,13 @@ class BaseHttpTransport(Transport):
227
225
  self._compression_level = 4
228
226
 
229
227
  def record_lost_event(
230
- self,
231
- reason, # type: str
232
- data_category=None, # type: Optional[EventDataCategory]
233
- item=None, # type: Optional[Item]
228
+ self: Self,
229
+ reason: str,
230
+ data_category: Optional[EventDataCategory] = None,
231
+ item: Optional[Item] = None,
234
232
  *,
235
- quantity=1, # type: int
236
- ):
237
- # type: (...) -> None
233
+ quantity: int = 1,
234
+ ) -> None:
238
235
  if not self.options["send_client_reports"]:
239
236
  return
240
237
 
@@ -247,9 +244,7 @@ class BaseHttpTransport(Transport):
247
244
  event = item.get_transaction_event() or {}
248
245
 
249
246
  # +1 for the transaction itself
250
- span_count = (
251
- len(cast(List[Dict[str, object]], event.get("spans") or [])) + 1
252
- )
247
+ span_count = len(event.get("spans") or []) + 1
253
248
  self.record_lost_event(reason, "span", quantity=span_count)
254
249
 
255
250
  elif data_category == "attachment":
@@ -262,12 +257,12 @@ class BaseHttpTransport(Transport):
262
257
 
263
258
  self._discarded_events[data_category, reason] += quantity
264
259
 
265
- def _get_header_value(self, response, header):
266
- # type: (Self, Any, str) -> Optional[str]
260
+ def _get_header_value(self: Self, response: Any, header: str) -> Optional[str]:
267
261
  return response.headers.get(header)
268
262
 
269
- def _update_rate_limits(self, response):
270
- # type: (Self, Union[urllib3.BaseHTTPResponse, httpcore.Response]) -> None
263
+ def _update_rate_limits(
264
+ self: Self, response: Union[urllib3.BaseHTTPResponse, httpcore.Response]
265
+ ) -> None:
271
266
 
272
267
  # new sentries with more rate limit insights. We honor this header
273
268
  # no matter of the status code to update our internal rate limits.
@@ -292,16 +287,13 @@ class BaseHttpTransport(Transport):
292
287
  )
293
288
 
294
289
  def _send_request(
295
- self,
296
- body,
297
- headers,
298
- endpoint_type=EndpointType.ENVELOPE,
299
- envelope=None,
300
- ):
301
- # type: (Self, bytes, Dict[str, str], EndpointType, Optional[Envelope]) -> None
302
-
303
- def record_loss(reason):
304
- # type: (str) -> None
290
+ self: Self,
291
+ body: bytes,
292
+ headers: Dict[str, str],
293
+ endpoint_type: EndpointType = EndpointType.ENVELOPE,
294
+ envelope: Optional[Envelope] = None,
295
+ ) -> None:
296
+ def record_loss(reason: str) -> None:
305
297
  if envelope is None:
306
298
  self.record_lost_event(reason, data_category="error")
307
299
  else:
@@ -348,12 +340,12 @@ class BaseHttpTransport(Transport):
348
340
  finally:
349
341
  response.close()
350
342
 
351
- def on_dropped_event(self, _reason):
352
- # type: (Self, str) -> None
343
+ def on_dropped_event(self: Self, _reason: str) -> None:
353
344
  return None
354
345
 
355
- def _fetch_pending_client_report(self, force=False, interval=60):
356
- # type: (Self, bool, int) -> Optional[Item]
346
+ def _fetch_pending_client_report(
347
+ self: Self, force: bool = False, interval: int = 60
348
+ ) -> Optional[Item]:
357
349
  if not self.options["send_client_reports"]:
358
350
  return None
359
351
 
@@ -383,37 +375,30 @@ class BaseHttpTransport(Transport):
383
375
  type="client_report",
384
376
  )
385
377
 
386
- def _flush_client_reports(self, force=False):
387
- # type: (Self, bool) -> None
378
+ def _flush_client_reports(self: Self, force: bool = False) -> None:
388
379
  client_report = self._fetch_pending_client_report(force=force, interval=60)
389
380
  if client_report is not None:
390
381
  self.capture_envelope(Envelope(items=[client_report]))
391
382
 
392
- def _check_disabled(self, category):
393
- # type: (str) -> bool
394
- def _disabled(bucket):
395
- # type: (Any) -> bool
383
+ def _check_disabled(self: Self, category: EventDataCategory) -> bool:
384
+ def _disabled(bucket: Optional[EventDataCategory]) -> bool:
396
385
  ts = self._disabled_until.get(bucket)
397
386
  return ts is not None and ts > datetime.now(timezone.utc)
398
387
 
399
388
  return _disabled(category) or _disabled(None)
400
389
 
401
- def _is_rate_limited(self):
402
- # type: (Self) -> bool
390
+ def _is_rate_limited(self: Self) -> bool:
403
391
  return any(
404
392
  ts > datetime.now(timezone.utc) for ts in self._disabled_until.values()
405
393
  )
406
394
 
407
- def _is_worker_full(self):
408
- # type: (Self) -> bool
395
+ def _is_worker_full(self: Self) -> bool:
409
396
  return self._worker.full()
410
397
 
411
- def is_healthy(self):
412
- # type: (Self) -> bool
398
+ def is_healthy(self: Self) -> bool:
413
399
  return not (self._is_worker_full() or self._is_rate_limited())
414
400
 
415
- def _send_envelope(self, envelope):
416
- # type: (Self, Envelope) -> None
401
+ def _send_envelope(self: Self, envelope: Envelope) -> None:
417
402
 
418
403
  # remove all items from the envelope which are over quota
419
404
  new_items = []
@@ -465,8 +450,9 @@ class BaseHttpTransport(Transport):
465
450
  )
466
451
  return None
467
452
 
468
- def _serialize_envelope(self, envelope):
469
- # type: (Self, Envelope) -> tuple[Optional[str], io.BytesIO]
453
+ def _serialize_envelope(
454
+ self: Self, envelope: Envelope
455
+ ) -> tuple[Optional[str], io.BytesIO]:
470
456
  content_encoding = None
471
457
  body = io.BytesIO()
472
458
  if self._compression_level == 0 or self._compression_algo is None:
@@ -487,12 +473,10 @@ class BaseHttpTransport(Transport):
487
473
 
488
474
  return content_encoding, body
489
475
 
490
- def _get_pool_options(self):
491
- # type: (Self) -> Dict[str, Any]
476
+ def _get_pool_options(self: Self) -> Dict[str, Any]:
492
477
  raise NotImplementedError()
493
478
 
494
- def _in_no_proxy(self, parsed_dsn):
495
- # type: (Self, Dsn) -> bool
479
+ def _in_no_proxy(self: Self, parsed_dsn: Dsn) -> bool:
496
480
  no_proxy = getproxies().get("no")
497
481
  if not no_proxy:
498
482
  return False
@@ -502,26 +486,28 @@ class BaseHttpTransport(Transport):
502
486
  return True
503
487
  return False
504
488
 
505
- def _make_pool(self):
506
- # type: (Self) -> Union[PoolManager, ProxyManager, httpcore.SOCKSProxy, httpcore.HTTPProxy, httpcore.ConnectionPool]
489
+ def _make_pool(
490
+ self: Self,
491
+ ) -> Union[
492
+ PoolManager,
493
+ ProxyManager,
494
+ httpcore.SOCKSProxy,
495
+ httpcore.HTTPProxy,
496
+ httpcore.ConnectionPool,
497
+ ]:
507
498
  raise NotImplementedError()
508
499
 
509
500
  def _request(
510
- self,
511
- method,
512
- endpoint_type,
513
- body,
514
- headers,
515
- ):
516
- # type: (Self, str, EndpointType, Any, Mapping[str, str]) -> Union[urllib3.BaseHTTPResponse, httpcore.Response]
501
+ self: Self,
502
+ method: str,
503
+ endpoint_type: EndpointType,
504
+ body: Any,
505
+ headers: Mapping[str, str],
506
+ ) -> Union[urllib3.BaseHTTPResponse, httpcore.Response]:
517
507
  raise NotImplementedError()
518
508
 
519
- def capture_envelope(
520
- self, envelope # type: Envelope
521
- ):
522
- # type: (...) -> None
523
- def send_envelope_wrapper():
524
- # type: () -> None
509
+ def capture_envelope(self: Self, envelope: Envelope) -> None:
510
+ def send_envelope_wrapper() -> None:
525
511
  with capture_internal_exceptions():
526
512
  self._send_envelope(envelope)
527
513
  self._flush_client_reports()
@@ -532,19 +518,17 @@ class BaseHttpTransport(Transport):
532
518
  self.record_lost_event("queue_overflow", item=item)
533
519
 
534
520
  def flush(
535
- self,
536
- timeout,
537
- callback=None,
538
- ):
539
- # type: (Self, float, Optional[Callable[[int, float], None]]) -> None
521
+ self: Self,
522
+ timeout: float,
523
+ callback: Optional[Callable[[int, float], None]] = None,
524
+ ) -> None:
540
525
  logger.debug("Flushing HTTP transport")
541
526
 
542
527
  if timeout > 0:
543
528
  self._worker.submit(lambda: self._flush_client_reports(force=True))
544
529
  self._worker.flush(timeout, callback)
545
530
 
546
- def kill(self):
547
- # type: (Self) -> None
531
+ def kill(self: Self) -> None:
548
532
  logger.debug("Killing HTTP transport")
549
533
  self._worker.kill()
550
534
 
@@ -553,8 +537,7 @@ class HttpTransport(BaseHttpTransport):
553
537
  if TYPE_CHECKING:
554
538
  _pool: Union[PoolManager, ProxyManager]
555
539
 
556
- def _get_pool_options(self):
557
- # type: (Self) -> Dict[str, Any]
540
+ def _get_pool_options(self: Self) -> Dict[str, Any]:
558
541
 
559
542
  num_pools = self.options.get("_experiments", {}).get("transport_num_pools")
560
543
  options = {
@@ -563,7 +546,7 @@ class HttpTransport(BaseHttpTransport):
563
546
  "timeout": urllib3.Timeout(total=self.TIMEOUT),
564
547
  }
565
548
 
566
- socket_options = None # type: Optional[List[Tuple[int, int, int | bytes]]]
549
+ socket_options: Optional[List[Tuple[int, int, int | bytes]]] = None
567
550
 
568
551
  if self.options["socket_options"] is not None:
569
552
  socket_options = self.options["socket_options"]
@@ -596,8 +579,7 @@ class HttpTransport(BaseHttpTransport):
596
579
 
597
580
  return options
598
581
 
599
- def _make_pool(self):
600
- # type: (Self) -> Union[PoolManager, ProxyManager]
582
+ def _make_pool(self: Self) -> Union[PoolManager, ProxyManager]:
601
583
  if self.parsed_dsn is None:
602
584
  raise ValueError("Cannot create HTTP-based transport without valid DSN")
603
585
 
@@ -643,13 +625,12 @@ class HttpTransport(BaseHttpTransport):
643
625
  return urllib3.PoolManager(**opts)
644
626
 
645
627
  def _request(
646
- self,
647
- method,
648
- endpoint_type,
649
- body,
650
- headers,
651
- ):
652
- # type: (Self, str, EndpointType, Any, Mapping[str, str]) -> urllib3.BaseHTTPResponse
628
+ self: Self,
629
+ method: str,
630
+ endpoint_type: EndpointType,
631
+ body: Any,
632
+ headers: Mapping[str, str],
633
+ ) -> urllib3.BaseHTTPResponse:
653
634
  return self._pool.request(
654
635
  method,
655
636
  self._auth.get_api_url(endpoint_type),
@@ -658,14 +639,10 @@ class HttpTransport(BaseHttpTransport):
658
639
  )
659
640
 
660
641
 
661
- try:
662
- import httpcore
663
- import h2 # noqa: F401
664
- except ImportError:
642
+ if not HTTP2_ENABLED:
665
643
  # Sorry, no Http2Transport for you
666
644
  class Http2Transport(HttpTransport):
667
- def __init__(self, options):
668
- # type: (Self, Dict[str, Any]) -> None
645
+ def __init__(self: Self, options: Dict[str, Any]) -> None:
669
646
  super().__init__(options)
670
647
  logger.warning(
671
648
  "You tried to use HTTP2Transport but don't have httpcore[http2] installed. Falling back to HTTPTransport."
@@ -683,8 +660,7 @@ else:
683
660
  httpcore.SOCKSProxy, httpcore.HTTPProxy, httpcore.ConnectionPool
684
661
  ]
685
662
 
686
- def _get_header_value(self, response, header):
687
- # type: (Self, httpcore.Response, str) -> Optional[str]
663
+ def _get_header_value(self: Self, response: Any, header: str) -> Optional[str]:
688
664
  return next(
689
665
  (
690
666
  val.decode("ascii")
@@ -695,13 +671,12 @@ else:
695
671
  )
696
672
 
697
673
  def _request(
698
- self,
699
- method,
700
- endpoint_type,
701
- body,
702
- headers,
703
- ):
704
- # type: (Self, str, EndpointType, Any, Mapping[str, str]) -> httpcore.Response
674
+ self: Self,
675
+ method: str,
676
+ endpoint_type: EndpointType,
677
+ body: Any,
678
+ headers: Mapping[str, str],
679
+ ) -> httpcore.Response:
705
680
  response = self._pool.request(
706
681
  method,
707
682
  self._auth.get_api_url(endpoint_type),
@@ -718,13 +693,12 @@ else:
718
693
  )
719
694
  return response
720
695
 
721
- def _get_pool_options(self):
722
- # type: (Self) -> Dict[str, Any]
723
- options = {
696
+ def _get_pool_options(self: Self) -> Dict[str, Any]:
697
+ options: Dict[str, Any] = {
724
698
  "http2": self.parsed_dsn is not None
725
699
  and self.parsed_dsn.scheme == "https",
726
700
  "retries": 3,
727
- } # type: Dict[str, Any]
701
+ }
728
702
 
729
703
  socket_options = (
730
704
  self.options["socket_options"]
@@ -755,8 +729,9 @@ else:
755
729
 
756
730
  return options
757
731
 
758
- def _make_pool(self):
759
- # type: (Self) -> Union[httpcore.SOCKSProxy, httpcore.HTTPProxy, httpcore.ConnectionPool]
732
+ def _make_pool(
733
+ self: Self,
734
+ ) -> Union[httpcore.SOCKSProxy, httpcore.HTTPProxy, httpcore.ConnectionPool]:
760
735
  if self.parsed_dsn is None:
761
736
  raise ValueError("Cannot create HTTP-based transport without valid DSN")
762
737
  proxy = None
@@ -799,16 +774,15 @@ else:
799
774
  return httpcore.ConnectionPool(**opts)
800
775
 
801
776
 
802
- def make_transport(options):
803
- # type: (Dict[str, Any]) -> Optional[Transport]
777
+ def make_transport(options: Dict[str, Any]) -> Optional[Transport]:
804
778
  ref_transport = options["transport"]
805
779
 
806
780
  use_http2_transport = options.get("_experiments", {}).get("transport_http2", False)
807
781
 
808
782
  # By default, we use the http transport class
809
- transport_cls = (
783
+ transport_cls: Type[Transport] = (
810
784
  Http2Transport if use_http2_transport else HttpTransport
811
- ) # type: Type[Transport]
785
+ )
812
786
 
813
787
  if isinstance(ref_transport, Transport):
814
788
  return ref_transport