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/crons/api.py CHANGED
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import uuid
2
3
 
3
4
  import sentry_sdk
@@ -10,17 +11,16 @@ if TYPE_CHECKING:
10
11
 
11
12
 
12
13
  def _create_check_in_event(
13
- monitor_slug=None, # type: Optional[str]
14
- check_in_id=None, # type: Optional[str]
15
- status=None, # type: Optional[str]
16
- duration_s=None, # type: Optional[float]
17
- monitor_config=None, # type: Optional[MonitorConfig]
18
- ):
19
- # type: (...) -> Event
14
+ monitor_slug: Optional[str] = None,
15
+ check_in_id: Optional[str] = None,
16
+ status: Optional[str] = None,
17
+ duration_s: Optional[float] = None,
18
+ monitor_config: Optional[MonitorConfig] = None,
19
+ ) -> Event:
20
20
  options = sentry_sdk.get_client().options
21
- check_in_id = check_in_id or uuid.uuid4().hex # type: str
21
+ check_in_id = check_in_id or uuid.uuid4().hex
22
22
 
23
- check_in = {
23
+ check_in: Event = {
24
24
  "type": "check_in",
25
25
  "monitor_slug": monitor_slug,
26
26
  "check_in_id": check_in_id,
@@ -28,7 +28,7 @@ def _create_check_in_event(
28
28
  "duration": duration_s,
29
29
  "environment": options.get("environment", None),
30
30
  "release": options.get("release", None),
31
- } # type: Event
31
+ }
32
32
 
33
33
  if monitor_config:
34
34
  check_in["monitor_config"] = monitor_config
@@ -37,13 +37,12 @@ def _create_check_in_event(
37
37
 
38
38
 
39
39
  def capture_checkin(
40
- monitor_slug=None, # type: Optional[str]
41
- check_in_id=None, # type: Optional[str]
42
- status=None, # type: Optional[str]
43
- duration=None, # type: Optional[float]
44
- monitor_config=None, # type: Optional[MonitorConfig]
45
- ):
46
- # type: (...) -> str
40
+ monitor_slug: Optional[str] = None,
41
+ check_in_id: Optional[str] = None,
42
+ status: Optional[str] = None,
43
+ duration: Optional[float] = None,
44
+ monitor_config: Optional[MonitorConfig] = None,
45
+ ) -> str:
47
46
  check_in_event = _create_check_in_event(
48
47
  monitor_slug=monitor_slug,
49
48
  check_in_id=check_in_id,
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from functools import wraps
2
3
  from inspect import iscoroutinefunction
3
4
 
@@ -16,8 +17,6 @@ if TYPE_CHECKING:
16
17
  ParamSpec,
17
18
  Type,
18
19
  TypeVar,
19
- Union,
20
- cast,
21
20
  overload,
22
21
  )
23
22
  from sentry_sdk._types import MonitorConfig
@@ -55,13 +54,15 @@ class monitor: # noqa: N801
55
54
  ```
56
55
  """
57
56
 
58
- def __init__(self, monitor_slug=None, monitor_config=None):
59
- # type: (Optional[str], Optional[MonitorConfig]) -> None
57
+ def __init__(
58
+ self,
59
+ monitor_slug: Optional[str] = None,
60
+ monitor_config: Optional[MonitorConfig] = None,
61
+ ) -> None:
60
62
  self.monitor_slug = monitor_slug
61
63
  self.monitor_config = monitor_config
62
64
 
63
- def __enter__(self):
64
- # type: () -> None
65
+ def __enter__(self) -> None:
65
66
  self.start_timestamp = now()
66
67
  self.check_in_id = capture_checkin(
67
68
  monitor_slug=self.monitor_slug,
@@ -69,8 +70,12 @@ class monitor: # noqa: N801
69
70
  monitor_config=self.monitor_config,
70
71
  )
71
72
 
72
- def __exit__(self, exc_type, exc_value, traceback):
73
- # type: (Optional[Type[BaseException]], Optional[BaseException], Optional[TracebackType]) -> None
73
+ def __exit__(
74
+ self,
75
+ exc_type: Optional[Type[BaseException]],
76
+ exc_value: Optional[BaseException],
77
+ traceback: Optional[TracebackType],
78
+ ) -> None:
74
79
  duration_s = now() - self.start_timestamp
75
80
 
76
81
  if exc_type is None and exc_value is None and traceback is None:
@@ -89,46 +94,39 @@ class monitor: # noqa: N801
89
94
  if TYPE_CHECKING:
90
95
 
91
96
  @overload
92
- def __call__(self, fn):
93
- # type: (Callable[P, Awaitable[Any]]) -> Callable[P, Awaitable[Any]]
97
+ def __call__(
98
+ self, fn: Callable[P, Awaitable[Any]]
99
+ ) -> Callable[P, Awaitable[Any]]:
94
100
  # Unfortunately, mypy does not give us any reliable way to type check the
95
101
  # return value of an Awaitable (i.e. async function) for this overload,
96
102
  # since calling iscouroutinefunction narrows the type to Callable[P, Awaitable[Any]].
97
103
  ...
98
104
 
99
105
  @overload
100
- def __call__(self, fn):
101
- # type: (Callable[P, R]) -> Callable[P, R]
102
- ...
106
+ def __call__(self, fn: Callable[P, R]) -> Callable[P, R]: ...
103
107
 
104
108
  def __call__(
105
109
  self,
106
- fn, # type: Union[Callable[P, R], Callable[P, Awaitable[Any]]]
107
- ):
108
- # type: (...) -> Union[Callable[P, R], Callable[P, Awaitable[Any]]]
110
+ fn: Callable[..., Any],
111
+ ) -> Callable[..., Any]:
109
112
  if iscoroutinefunction(fn):
110
113
  return self._async_wrapper(fn)
111
-
112
114
  else:
113
- if TYPE_CHECKING:
114
- fn = cast("Callable[P, R]", fn)
115
115
  return self._sync_wrapper(fn)
116
116
 
117
- def _async_wrapper(self, fn):
118
- # type: (Callable[P, Awaitable[Any]]) -> Callable[P, Awaitable[Any]]
117
+ def _async_wrapper(
118
+ self, fn: Callable[P, Awaitable[Any]]
119
+ ) -> Callable[P, Awaitable[Any]]:
119
120
  @wraps(fn)
120
- async def inner(*args: "P.args", **kwargs: "P.kwargs"):
121
- # type: (...) -> R
121
+ async def inner(*args: P.args, **kwargs: P.kwargs) -> R:
122
122
  with self:
123
123
  return await fn(*args, **kwargs)
124
124
 
125
125
  return inner
126
126
 
127
- def _sync_wrapper(self, fn):
128
- # type: (Callable[P, R]) -> Callable[P, R]
127
+ def _sync_wrapper(self, fn: Callable[P, R]) -> Callable[P, R]:
129
128
  @wraps(fn)
130
- def inner(*args: "P.args", **kwargs: "P.kwargs"):
131
- # type: (...) -> R
129
+ def inner(*args: P.args, **kwargs: P.kwargs) -> R:
132
130
  with self:
133
131
  return fn(*args, **kwargs)
134
132
 
sentry_sdk/debug.py CHANGED
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import sys
2
3
  import logging
3
4
 
@@ -8,22 +9,19 @@ from logging import LogRecord
8
9
 
9
10
 
10
11
  class _DebugFilter(logging.Filter):
11
- def filter(self, record):
12
- # type: (LogRecord) -> bool
12
+ def filter(self, record: LogRecord) -> bool:
13
13
  if _client_init_debug.get(False):
14
14
  return True
15
15
 
16
16
  return get_client().options["debug"]
17
17
 
18
18
 
19
- def init_debug_support():
20
- # type: () -> None
19
+ def init_debug_support() -> None:
21
20
  if not logger.handlers:
22
21
  configure_logger()
23
22
 
24
23
 
25
- def configure_logger():
26
- # type: () -> None
24
+ def configure_logger() -> None:
27
25
  _handler = logging.StreamHandler(sys.stderr)
28
26
  _handler.setFormatter(logging.Formatter(" [sentry] %(levelname)s: %(message)s"))
29
27
  logger.addHandler(_handler)
sentry_sdk/envelope.py CHANGED
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  import io
2
3
  import json
3
4
  import mimetypes
@@ -8,18 +9,11 @@ from sentry_sdk.utils import json_dumps, capture_internal_exceptions
8
9
  from typing import TYPE_CHECKING
9
10
 
10
11
  if TYPE_CHECKING:
11
- from typing import Any
12
- from typing import Optional
13
- from typing import Union
14
- from typing import Dict
15
- from typing import List
16
- from typing import Iterator
17
-
18
12
  from sentry_sdk._types import Event, EventDataCategory
13
+ from typing import Any, Optional, Union, Dict, List, Iterator
19
14
 
20
15
 
21
- def parse_json(data):
22
- # type: (Union[bytes, str]) -> Any
16
+ def parse_json(data: Union[bytes, str]) -> Any:
23
17
  # on some python 3 versions this needs to be bytes
24
18
  if isinstance(data, bytes):
25
19
  data = data.decode("utf-8", "replace")
@@ -35,10 +29,9 @@ class Envelope:
35
29
 
36
30
  def __init__(
37
31
  self,
38
- headers=None, # type: Optional[Dict[str, Any]]
39
- items=None, # type: Optional[List[Item]]
40
- ):
41
- # type: (...) -> None
32
+ headers: Optional[Dict[str, Any]] = None,
33
+ items: Optional[List[Item]] = None,
34
+ ) -> None:
42
35
  if headers is not None:
43
36
  headers = dict(headers)
44
37
  self.headers = headers or {}
@@ -49,35 +42,22 @@ class Envelope:
49
42
  self.items = items
50
43
 
51
44
  @property
52
- def description(self):
53
- # type: (...) -> str
45
+ def description(self) -> str:
54
46
  return "envelope with %s items (%s)" % (
55
47
  len(self.items),
56
48
  ", ".join(x.data_category for x in self.items),
57
49
  )
58
50
 
59
- def add_event(
60
- self, event # type: Event
61
- ):
62
- # type: (...) -> None
51
+ def add_event(self, event: Event) -> None:
63
52
  self.add_item(Item(payload=PayloadRef(json=event), type="event"))
64
53
 
65
- def add_transaction(
66
- self, transaction # type: Event
67
- ):
68
- # type: (...) -> None
54
+ def add_transaction(self, transaction: Event) -> None:
69
55
  self.add_item(Item(payload=PayloadRef(json=transaction), type="transaction"))
70
56
 
71
- def add_profile(
72
- self, profile # type: Any
73
- ):
74
- # type: (...) -> None
57
+ def add_profile(self, profile: Any) -> None:
75
58
  self.add_item(Item(payload=PayloadRef(json=profile), type="profile"))
76
59
 
77
- def add_profile_chunk(
78
- self, profile_chunk # type: Any
79
- ):
80
- # type: (...) -> None
60
+ def add_profile_chunk(self, profile_chunk: Any) -> None:
81
61
  self.add_item(
82
62
  Item(
83
63
  payload=PayloadRef(json=profile_chunk),
@@ -86,72 +66,50 @@ class Envelope:
86
66
  )
87
67
  )
88
68
 
89
- def add_checkin(
90
- self, checkin # type: Any
91
- ):
92
- # type: (...) -> None
69
+ def add_checkin(self, checkin: Any) -> None:
93
70
  self.add_item(Item(payload=PayloadRef(json=checkin), type="check_in"))
94
71
 
95
- def add_session(
96
- self, session # type: Union[Session, Any]
97
- ):
98
- # type: (...) -> None
72
+ def add_session(self, session: Union[Session, Any]) -> None:
99
73
  if isinstance(session, Session):
100
74
  session = session.to_json()
101
75
  self.add_item(Item(payload=PayloadRef(json=session), type="session"))
102
76
 
103
- def add_sessions(
104
- self, sessions # type: Any
105
- ):
106
- # type: (...) -> None
77
+ def add_sessions(self, sessions: Any) -> None:
107
78
  self.add_item(Item(payload=PayloadRef(json=sessions), type="sessions"))
108
79
 
109
- def add_item(
110
- self, item # type: Item
111
- ):
112
- # type: (...) -> None
80
+ def add_item(self, item: Item) -> None:
113
81
  self.items.append(item)
114
82
 
115
- def get_event(self):
116
- # type: (...) -> Optional[Event]
83
+ def get_event(self) -> Optional[Event]:
117
84
  for items in self.items:
118
85
  event = items.get_event()
119
86
  if event is not None:
120
87
  return event
121
88
  return None
122
89
 
123
- def get_transaction_event(self):
124
- # type: (...) -> Optional[Event]
90
+ def get_transaction_event(self) -> Optional[Event]:
125
91
  for item in self.items:
126
92
  event = item.get_transaction_event()
127
93
  if event is not None:
128
94
  return event
129
95
  return None
130
96
 
131
- def __iter__(self):
132
- # type: (...) -> Iterator[Item]
97
+ def __iter__(self) -> Iterator[Item]:
133
98
  return iter(self.items)
134
99
 
135
- def serialize_into(
136
- self, f # type: Any
137
- ):
138
- # type: (...) -> None
100
+ def serialize_into(self, f: Any) -> None:
139
101
  f.write(json_dumps(self.headers))
140
102
  f.write(b"\n")
141
103
  for item in self.items:
142
104
  item.serialize_into(f)
143
105
 
144
- def serialize(self):
145
- # type: (...) -> bytes
106
+ def serialize(self) -> bytes:
146
107
  out = io.BytesIO()
147
108
  self.serialize_into(out)
148
109
  return out.getvalue()
149
110
 
150
111
  @classmethod
151
- def deserialize_from(
152
- cls, f # type: Any
153
- ):
154
- # type: (...) -> Envelope
112
+ def deserialize_from(cls, f: Any) -> Envelope:
155
113
  headers = parse_json(f.readline())
156
114
  items = []
157
115
  while 1:
@@ -162,31 +120,25 @@ class Envelope:
162
120
  return cls(headers=headers, items=items)
163
121
 
164
122
  @classmethod
165
- def deserialize(
166
- cls, bytes # type: bytes
167
- ):
168
- # type: (...) -> Envelope
123
+ def deserialize(cls, bytes: bytes) -> Envelope:
169
124
  return cls.deserialize_from(io.BytesIO(bytes))
170
125
 
171
- def __repr__(self):
172
- # type: (...) -> str
126
+ def __repr__(self) -> str:
173
127
  return "<Envelope headers=%r items=%r>" % (self.headers, self.items)
174
128
 
175
129
 
176
130
  class PayloadRef:
177
131
  def __init__(
178
132
  self,
179
- bytes=None, # type: Optional[bytes]
180
- path=None, # type: Optional[Union[bytes, str]]
181
- json=None, # type: Optional[Any]
182
- ):
183
- # type: (...) -> None
133
+ bytes: Optional[bytes] = None,
134
+ path: Optional[Union[bytes, str]] = None,
135
+ json: Optional[Any] = None,
136
+ ) -> None:
184
137
  self.json = json
185
138
  self.bytes = bytes
186
139
  self.path = path
187
140
 
188
- def get_bytes(self):
189
- # type: (...) -> bytes
141
+ def get_bytes(self) -> bytes:
190
142
  if self.bytes is None:
191
143
  if self.path is not None:
192
144
  with capture_internal_exceptions():
@@ -197,8 +149,7 @@ class PayloadRef:
197
149
  return self.bytes or b""
198
150
 
199
151
  @property
200
- def inferred_content_type(self):
201
- # type: (...) -> str
152
+ def inferred_content_type(self) -> str:
202
153
  if self.json is not None:
203
154
  return "application/json"
204
155
  elif self.path is not None:
@@ -210,20 +161,19 @@ class PayloadRef:
210
161
  return ty
211
162
  return "application/octet-stream"
212
163
 
213
- def __repr__(self):
214
- # type: (...) -> str
164
+ def __repr__(self) -> str:
215
165
  return "<Payload %r>" % (self.inferred_content_type,)
216
166
 
217
167
 
218
168
  class Item:
219
169
  def __init__(
220
170
  self,
221
- payload, # type: Union[bytes, str, PayloadRef]
222
- headers=None, # type: Optional[Dict[str, Any]]
223
- type=None, # type: Optional[str]
224
- content_type=None, # type: Optional[str]
225
- filename=None, # type: Optional[str]
226
- ):
171
+ payload: Union[bytes, str, PayloadRef],
172
+ headers: Optional[Dict[str, Any]] = None,
173
+ type: Optional[str] = None,
174
+ content_type: Optional[str] = None,
175
+ filename: Optional[str] = None,
176
+ ) -> None:
227
177
  if headers is not None:
228
178
  headers = dict(headers)
229
179
  elif headers is None:
@@ -247,8 +197,7 @@ class Item:
247
197
 
248
198
  self.payload = payload
249
199
 
250
- def __repr__(self):
251
- # type: (...) -> str
200
+ def __repr__(self) -> str:
252
201
  return "<Item headers=%r payload=%r data_category=%r>" % (
253
202
  self.headers,
254
203
  self.payload,
@@ -256,13 +205,11 @@ class Item:
256
205
  )
257
206
 
258
207
  @property
259
- def type(self):
260
- # type: (...) -> Optional[str]
208
+ def type(self) -> Optional[str]:
261
209
  return self.headers.get("type")
262
210
 
263
211
  @property
264
- def data_category(self):
265
- # type: (...) -> EventDataCategory
212
+ def data_category(self) -> EventDataCategory:
266
213
  ty = self.headers.get("type")
267
214
  if ty == "session" or ty == "sessions":
268
215
  return "session"
@@ -285,12 +232,10 @@ class Item:
285
232
  else:
286
233
  return "default"
287
234
 
288
- def get_bytes(self):
289
- # type: (...) -> bytes
235
+ def get_bytes(self) -> bytes:
290
236
  return self.payload.get_bytes()
291
237
 
292
- def get_event(self):
293
- # type: (...) -> Optional[Event]
238
+ def get_event(self) -> Optional[Event]:
294
239
  """
295
240
  Returns an error event if there is one.
296
241
  """
@@ -298,16 +243,12 @@ class Item:
298
243
  return self.payload.json
299
244
  return None
300
245
 
301
- def get_transaction_event(self):
302
- # type: (...) -> Optional[Event]
246
+ def get_transaction_event(self) -> Optional[Event]:
303
247
  if self.type == "transaction" and self.payload.json is not None:
304
248
  return self.payload.json
305
249
  return None
306
250
 
307
- def serialize_into(
308
- self, f # type: Any
309
- ):
310
- # type: (...) -> None
251
+ def serialize_into(self, f: Any) -> None:
311
252
  headers = dict(self.headers)
312
253
  bytes = self.get_bytes()
313
254
  headers["length"] = len(bytes)
@@ -316,17 +257,13 @@ class Item:
316
257
  f.write(bytes)
317
258
  f.write(b"\n")
318
259
 
319
- def serialize(self):
320
- # type: (...) -> bytes
260
+ def serialize(self) -> bytes:
321
261
  out = io.BytesIO()
322
262
  self.serialize_into(out)
323
263
  return out.getvalue()
324
264
 
325
265
  @classmethod
326
- def deserialize_from(
327
- cls, f # type: Any
328
- ):
329
- # type: (...) -> Optional[Item]
266
+ def deserialize_from(cls, f: Any) -> Optional[Item]:
330
267
  line = f.readline().rstrip()
331
268
  if not line:
332
269
  return None
@@ -346,8 +283,5 @@ class Item:
346
283
  return rv
347
284
 
348
285
  @classmethod
349
- def deserialize(
350
- cls, bytes # type: bytes
351
- ):
352
- # type: (...) -> Optional[Item]
286
+ def deserialize(cls, bytes: bytes) -> Optional[Item]:
353
287
  return cls.deserialize_from(io.BytesIO(bytes))
@@ -1,23 +1,22 @@
1
+ from __future__ import annotations
1
2
  import copy
2
3
  import sentry_sdk
3
4
  from sentry_sdk._lru_cache import LRUCache
4
5
  from threading import Lock
5
6
 
6
- from typing import TYPE_CHECKING, Any
7
+ from typing import TYPE_CHECKING
7
8
 
8
9
  if TYPE_CHECKING:
9
- from typing import TypedDict
10
+ from typing import Any, TypedDict
10
11
 
11
12
  FlagData = TypedDict("FlagData", {"flag": str, "result": bool})
12
13
 
13
-
14
14
  DEFAULT_FLAG_CAPACITY = 100
15
15
 
16
16
 
17
17
  class FlagBuffer:
18
18
 
19
- def __init__(self, capacity):
20
- # type: (int) -> None
19
+ def __init__(self, capacity: int) -> None:
21
20
  self.capacity = capacity
22
21
  self.lock = Lock()
23
22
 
@@ -25,26 +24,22 @@ class FlagBuffer:
25
24
  # directly you're on your own!
26
25
  self.__buffer = LRUCache(capacity)
27
26
 
28
- def clear(self):
29
- # type: () -> None
27
+ def clear(self) -> None:
30
28
  self.__buffer = LRUCache(self.capacity)
31
29
 
32
- def __deepcopy__(self, memo):
33
- # type: (dict[int, Any]) -> FlagBuffer
30
+ def __deepcopy__(self, memo: dict[int, Any]) -> FlagBuffer:
34
31
  with self.lock:
35
32
  buffer = FlagBuffer(self.capacity)
36
33
  buffer.__buffer = copy.deepcopy(self.__buffer, memo)
37
34
  return buffer
38
35
 
39
- def get(self):
40
- # type: () -> list[FlagData]
36
+ def get(self) -> list[FlagData]:
41
37
  with self.lock:
42
38
  return [
43
39
  {"flag": key, "result": value} for key, value in self.__buffer.get_all()
44
40
  ]
45
41
 
46
- def set(self, flag, result):
47
- # type: (str, bool) -> None
42
+ def set(self, flag: str, result: bool) -> None:
48
43
  if isinstance(result, FlagBuffer):
49
44
  # If someone were to insert `self` into `self` this would create a circular dependency
50
45
  # on the lock. This is of course a deadlock. However, this is far outside the expected
@@ -58,8 +53,7 @@ class FlagBuffer:
58
53
  self.__buffer.set(flag, result)
59
54
 
60
55
 
61
- def add_feature_flag(flag, result):
62
- # type: (str, bool) -> None
56
+ def add_feature_flag(flag: str, result: bool) -> None:
63
57
  """
64
58
  Records a flag and its value to be sent on subsequent error events.
65
59
  We recommend you do this on flag evaluations. Flags are buffered per Sentry scope.
@@ -1,3 +1,4 @@
1
+ from __future__ import annotations
1
2
  from abc import ABC, abstractmethod
2
3
  from threading import Lock
3
4
 
@@ -23,20 +24,20 @@ _DEFAULT_FAILED_REQUEST_STATUS_CODES = frozenset(range(500, 600))
23
24
  _installer_lock = Lock()
24
25
 
25
26
  # Set of all integration identifiers we have attempted to install
26
- _processed_integrations = set() # type: Set[str]
27
+ _processed_integrations: Set[str] = set()
27
28
 
28
29
  # Set of all integration identifiers we have actually installed
29
- _installed_integrations = set() # type: Set[str]
30
+ _installed_integrations: Set[str] = set()
30
31
 
31
32
 
32
33
  def _generate_default_integrations_iterator(
33
- integrations, # type: List[str]
34
- auto_enabling_integrations, # type: List[str]
35
- ):
36
- # type: (...) -> Callable[[bool], Iterator[Type[Integration]]]
34
+ integrations: List[str],
35
+ auto_enabling_integrations: List[str],
36
+ ) -> Callable[[bool], Iterator[Type[Integration]]]:
37
37
 
38
- def iter_default_integrations(with_auto_enabling_integrations):
39
- # type: (bool) -> Iterator[Type[Integration]]
38
+ def iter_default_integrations(
39
+ with_auto_enabling_integrations: bool,
40
+ ) -> Iterator[Type[Integration]]:
40
41
  """Returns an iterator of the default integration classes:"""
41
42
  from importlib import import_module
42
43
 
@@ -146,6 +147,7 @@ _MIN_VERSIONS = {
146
147
  "launchdarkly": (9, 8, 0),
147
148
  "loguru": (0, 7, 0),
148
149
  "openai": (1, 0, 0),
150
+ "openai_agents": (0, 0, 19),
149
151
  "openfeature": (0, 7, 1),
150
152
  "quart": (0, 16, 0),
151
153
  "ray": (2, 7, 0),
@@ -165,12 +167,13 @@ _MIN_VERSIONS = {
165
167
 
166
168
 
167
169
  def setup_integrations(
168
- integrations,
169
- with_defaults=True,
170
- with_auto_enabling_integrations=False,
171
- disabled_integrations=None,
172
- ):
173
- # type: (Sequence[Integration], bool, bool, Optional[Sequence[Union[type[Integration], Integration]]]) -> Dict[str, Integration]
170
+ integrations: Sequence[Integration],
171
+ with_defaults: bool = True,
172
+ with_auto_enabling_integrations: bool = False,
173
+ disabled_integrations: Optional[
174
+ Sequence[Union[type[Integration], Integration]]
175
+ ] = None,
176
+ ) -> Dict[str, Integration]:
174
177
  """
175
178
  Given a list of integration instances, this installs them all.
176
179
 
@@ -239,8 +242,11 @@ def setup_integrations(
239
242
  return integrations
240
243
 
241
244
 
242
- def _check_minimum_version(integration, version, package=None):
243
- # type: (type[Integration], Optional[tuple[int, ...]], Optional[str]) -> None
245
+ def _check_minimum_version(
246
+ integration: type[Integration],
247
+ version: Optional[tuple[int, ...]],
248
+ package: Optional[str] = None,
249
+ ) -> None:
244
250
  package = package or integration.identifier
245
251
 
246
252
  if version is None:
@@ -276,13 +282,12 @@ class Integration(ABC):
276
282
  install = None
277
283
  """Legacy method, do not implement."""
278
284
 
279
- identifier = None # type: str
285
+ identifier: str
280
286
  """String unique ID of integration type"""
281
287
 
282
288
  @staticmethod
283
289
  @abstractmethod
284
- def setup_once():
285
- # type: () -> None
290
+ def setup_once() -> None:
286
291
  """
287
292
  Initialize the integration.
288
293