From 4e497728af619fa772c4da719066a12a6b43a041 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 1 Sep 2026 11:09:11 +0200 Subject: [PATCH 1/2] ci: Add anthropic to uv typing group --- pyproject.toml | 1 + sentry_sdk/integrations/anthropic.py | 245 ++++++++++++++++++--------- uv.lock | 64 +++++++ 3 files changed, 232 insertions(+), 78 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f7a0035dab..c4c896efc9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -74,6 +74,7 @@ typing = [ "pydantic-ai-slim>=2.23.0", "langchain-core>=1.5.3", "huggingface-hub>=1.26.1", + "anthropic>=1.2.0", ] test = [ "dataclasses ; python_full_version < '3.7'", diff --git a/sentry_sdk/integrations/anthropic.py b/sentry_sdk/integrations/anthropic.py index 5aca42e4b7..120a1cdc60 100644 --- a/sentry_sdk/integrations/anthropic.py +++ b/sentry_sdk/integrations/anthropic.py @@ -2,7 +2,7 @@ import sys from collections.abc import Iterable from functools import wraps -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast import sentry_sdk from sentry_sdk.ai.monitoring import record_token_usage @@ -36,12 +36,12 @@ try: from anthropic import NotGiven except ImportError: - NotGiven = None + NotGiven = None # type: ignore[misc,assignment] try: from anthropic import Omit except ImportError: - Omit = None + Omit = None # type: ignore[misc,assignment] from anthropic import AsyncStream, Stream from anthropic.lib.streaming import ( @@ -49,6 +49,7 @@ AsyncMessageStreamManager, MessageStream, MessageStreamManager, + ParsedMessageStreamEvent, ) from anthropic.resources import AsyncMessages, Messages from anthropic.types import ( @@ -69,10 +70,11 @@ from typing import ( Any, AsyncIterator, - Awaitable, Callable, + Coroutine, Iterator, Optional, + TypeVar, Union, ) @@ -86,6 +88,74 @@ from sentry_sdk._types import TextPart + class _PatchedRawMessageStream(Stream[RawMessageStreamEvent]): + _span: Span + _integration: "AnthropicIntegration" + + _model: Optional[ModelParam] + _usage: "_RecordedUsage" + _content_blocks: list[Any] + _response_id: Optional[str] + _finish_reason: Optional[str] + + class _PatchedMessageStream(MessageStream): + _span: Span + _integration: "AnthropicIntegration" + + _model: Optional[ModelParam] + _usage: "_RecordedUsage" + _content_blocks: list[Any] + _response_id: Optional[str] + _finish_reason: Optional[str] + + class _PatchedRawAsyncMessageStream(AsyncStream[RawMessageStreamEvent]): + _span: Span + _integration: "AnthropicIntegration" + + _model: Optional[ModelParam] + _usage: "_RecordedUsage" + _content_blocks: list[Any] + _response_id: Optional[str] + _finish_reason: Optional[str] + + class _PatchedAsyncMessageStream(AsyncMessageStream): + _span: Span + _integration: "AnthropicIntegration" + + _model: Optional[ModelParam] + _usage: "_RecordedUsage" + _content_blocks: list[Any] + _response_id: Optional[str] + _finish_reason: Optional[str] + + class _PatchedMessageStreamManager(MessageStreamManager): + _span: Union[Span, StreamedSpan] + _integration: "AnthropicIntegration" + + _max_tokens: int + _messages: Iterable[MessageParam] + _model: Optional[ModelParam] + _system: Optional[Union[str, Iterable[TextBlockParam]]] + _temperature: Optional[float] + _top_k: Optional[int] + _top_p: Optional[float] + _tools: Optional[Iterable[ToolUnionParam]] + + class _PatchedAsyncMessageStreamManager(AsyncMessageStreamManager[Any]): + _span: Union[Span, StreamedSpan] + _integration: "AnthropicIntegration" + + _max_tokens: int + _messages: Iterable[MessageParam] + _model: Optional[ModelParam] + _system: Optional[Union[str, Iterable[TextBlockParam]]] + _temperature: Optional[float] + _top_k: Optional[int] + _top_p: Optional[float] + _tools: Optional[Iterable[ToolUnionParam]] + + _EventT = TypeVar("_EventT", RawMessageStreamEvent, "ParsedMessageStreamEvent[Any]") + class _RecordedUsage: output_tokens: int = 0 @@ -102,7 +172,7 @@ class _StreamSpanContext: def __init__( self, - stream: "Union[Stream, MessageStream, AsyncStream, AsyncMessageStream]", + stream: "Union[Stream[RawMessageStreamEvent], MessageStream, AsyncStream[RawMessageStreamEvent], AsyncMessageStream]", # Flag to avoid unreachable branches when the stream state is known to be initialized (stream._model, etc. are set). guaranteed_streaming_state: bool = False, ) -> None: @@ -122,25 +192,30 @@ def __exit__( if not hasattr(self._stream, "_span"): return + patched_stream = cast( + "Union[_PatchedRawMessageStream, _PatchedMessageStream, _PatchedRawAsyncMessageStream, _PatchedAsyncMessageStream]", + self._stream, + ) + if not self._guaranteed_streaming_state and not hasattr( - self._stream, "_model" + patched_stream, "_model" ): - self._stream._span.__exit__(exc_type, exc_val, exc_tb) - del self._stream._span + patched_stream._span.__exit__(exc_type, exc_val, exc_tb) + del patched_stream._span return _set_streaming_output_data( - span=self._stream._span, - integration=self._stream._integration, - model=self._stream._model, - usage=self._stream._usage, - content_blocks=self._stream._content_blocks, - response_id=self._stream._response_id, - finish_reason=self._stream._finish_reason, + span=patched_stream._span, + integration=patched_stream._integration, + model=patched_stream._model, + usage=patched_stream._usage, + content_blocks=patched_stream._content_blocks, + response_id=patched_stream._response_id, + finish_reason=patched_stream._finish_reason, ) - self._stream._span.__exit__(exc_type, exc_val, exc_tb) - del self._stream._span + patched_stream._span.__exit__(exc_type, exc_val, exc_tb) + del patched_stream._span class AnthropicIntegration(Integration): @@ -167,27 +242,27 @@ def setup_once() -> None: Both paths may run. For example, the context manager exit can follow iterator exhaustion. """ - Messages.create = _wrap_message_create(Messages.create) - Stream.close = _wrap_close(Stream.close) + Messages.create = _wrap_message_create(Messages.create) # type: ignore[method-assign] + Stream.close = _wrap_close(Stream.close) # type: ignore[method-assign] - AsyncMessages.create = _wrap_message_create_async(AsyncMessages.create) - AsyncStream.close = _wrap_async_close(AsyncStream.close) + AsyncMessages.create = _wrap_message_create_async(AsyncMessages.create) # type: ignore[method-assign] + AsyncStream.close = _wrap_async_close(AsyncStream.close) # type: ignore[method-assign] """ client.messages.stream() patches are analogous to the patches for client.messages.create(stream=True) described above. """ - Messages.stream = _wrap_message_stream(Messages.stream) - MessageStreamManager.__enter__ = _wrap_message_stream_manager_enter( + Messages.stream = _wrap_message_stream(Messages.stream) # type: ignore[method-assign] + MessageStreamManager.__enter__ = _wrap_message_stream_manager_enter( # type: ignore[method-assign] MessageStreamManager.__enter__ ) # Before https://github.com/anthropics/anthropic-sdk-python/commit/b1a1c0354a9aca450a7d512fdbdeb59c0ead688a # MessageStream inherits from Stream, so patching Stream is sufficient on these versions. if not issubclass(MessageStream, Stream): - MessageStream.close = _wrap_close(MessageStream.close) + MessageStream.close = _wrap_close(MessageStream.close) # type: ignore[method-assign] - AsyncMessages.stream = _wrap_async_message_stream(AsyncMessages.stream) - AsyncMessageStreamManager.__aenter__ = ( + AsyncMessages.stream = _wrap_async_message_stream(AsyncMessages.stream) # type: ignore[method-assign] + AsyncMessageStreamManager.__aenter__ = ( # type: ignore[method-assign] _wrap_async_message_stream_manager_aenter( AsyncMessageStreamManager.__aenter__ ) @@ -196,7 +271,7 @@ def setup_once() -> None: # Before https://github.com/anthropics/anthropic-sdk-python/commit/b1a1c0354a9aca450a7d512fdbdeb59c0ead688a # AsyncMessageStream inherits from AsyncStream, so patching Stream is sufficient on these versions. if not issubclass(AsyncMessageStream, AsyncStream): - AsyncMessageStream.close = _wrap_async_close(AsyncMessageStream.close) + AsyncMessageStream.close = _wrap_async_close(AsyncMessageStream.close) # type: ignore[method-assign] def _capture_exception(exc: "Any") -> None: @@ -376,7 +451,7 @@ def _set_common_input_data( integration: "AnthropicIntegration", max_tokens: "int", messages: "Iterable[MessageParam]", - model: "ModelParam", + model: "Optional[ModelParam]", system: "Optional[Union[str, Iterable[TextBlockParam]]]", temperature: "Optional[float]", top_k: "Optional[int]", @@ -434,7 +509,7 @@ def _set_common_input_data( json.dumps(_transform_system_instructions(system)), ) - normalized_messages = [] + normalized_messages: "list[Any]" = [] for message in messages: if ( message.get("role") == GEN_AI_ALLOWED_MESSAGE_ROLES.USER @@ -465,7 +540,7 @@ def _set_common_input_data( ) else: # Transform content for non-list messages or assistant messages - transformed_message = message.copy() + transformed_message: "dict[str, Any]" = dict(message) if "content" in transformed_message: content = transformed_message["content"] if isinstance(content, (list, tuple)): @@ -524,9 +599,9 @@ def _set_create_input_data( def _wrap_synchronous_message_iterator( - stream: "Union[Stream, MessageStream]", - iterator: "Iterator[Union[RawMessageStreamEvent, MessageStreamEvent]]", -) -> "Iterator[Union[RawMessageStreamEvent, MessageStreamEvent]]": + stream: "Union[_PatchedRawMessageStream, _PatchedMessageStream]", + iterator: "Iterator[_EventT]", +) -> "Iterator[_EventT]": """ Sets information received while iterating the response stream on the AI Client Span. Responsible for closing the AI Client Span unless the span has already been closed in the close() patch. @@ -554,9 +629,9 @@ def _wrap_synchronous_message_iterator( async def _wrap_asynchronous_message_iterator( - stream: "Union[AsyncStream, AsyncMessageStream]", - iterator: "AsyncIterator[Union[RawMessageStreamEvent, MessageStreamEvent]]", -) -> "AsyncIterator[Union[RawMessageStreamEvent, MessageStreamEvent]]": + stream: "Union[_PatchedRawAsyncMessageStream, _PatchedAsyncMessageStream]", + iterator: "AsyncIterator[_EventT]", +) -> "AsyncIterator[_EventT]": """ Sets information received while iterating the response stream on the AI Client Span. Responsible for closing the AI Client Span unless the span has already been closed in the close() patch. @@ -698,12 +773,12 @@ def _sentry_patched_create_sync(f: "Any", *args: "Any", **kwargs: "Any") -> "Any reraise(*exc_info) if isinstance(result, Stream): - result._span = span - result._integration = integration + result._span = span # type: ignore[attr-defined] + result._integration = integration # type: ignore[attr-defined] _initialize_data_accumulation_state(result) result._iterator = _wrap_synchronous_message_iterator( - result, + cast("_PatchedRawMessageStream", result), result._iterator, ) @@ -796,12 +871,12 @@ async def _sentry_patched_create_async( reraise(*exc_info) if isinstance(result, AsyncStream): - result._span = span - result._integration = integration + result._span = span # type: ignore[attr-defined] + result._integration = integration # type: ignore[attr-defined] _initialize_data_accumulation_state(result) result._iterator = _wrap_asynchronous_message_iterator( - result, + cast("_PatchedRawAsyncMessageStream", result), result._iterator, ) @@ -856,21 +931,23 @@ def _sentry_wrapped_create_sync(*args: "Any", **kwargs: "Any") -> "Any": return _sentry_wrapped_create_sync -def _initialize_data_accumulation_state(stream: "Union[Stream, MessageStream]") -> None: +def _initialize_data_accumulation_state( + stream: "Union[Stream[RawMessageStreamEvent], MessageStream, AsyncStream[RawMessageStreamEvent], AsyncMessageStream]", +) -> None: """ Initialize fields for accumulating output on the Stream instance. """ if not hasattr(stream, "_model"): - stream._model = None - stream._usage = _RecordedUsage() - stream._content_blocks = [] - stream._response_id = None - stream._finish_reason = None + stream._model = None # type: ignore[union-attr] + stream._usage = _RecordedUsage() # type: ignore[union-attr] + stream._content_blocks = [] # type: ignore[union-attr] + stream._response_id = None # type: ignore[union-attr] + stream._finish_reason = None # type: ignore[union-attr] def _accumulate_event_data( - stream: "Union[Stream, MessageStream]", - event: "Union[RawMessageStreamEvent, MessageStreamEvent]", + stream: "Union[_PatchedRawMessageStream, _PatchedMessageStream, _PatchedRawAsyncMessageStream, _PatchedAsyncMessageStream]", + event: "RawMessageStreamEvent", ) -> None: """ Update accumulated output from a single stream event. @@ -932,7 +1009,7 @@ def _wrap_close( Closes the AI Client Span unless the finally block in `_wrap_synchronous_message_iterator()` runs first. """ - def close(self: "Union[Stream, MessageStream]") -> None: + def close(self: "Union[Stream[RawMessageStreamEvent], MessageStream]") -> None: with _StreamSpanContext(self): return f(self) @@ -951,13 +1028,13 @@ async def _sentry_wrapped_create_async(*args: "Any", **kwargs: "Any") -> "Any": def _wrap_async_close( - f: "Callable[..., Awaitable[None]]", -) -> "Callable[..., Awaitable[None]]": + f: "Callable[..., Coroutine[Any, Any, None]]", +) -> "Callable[..., Coroutine[Any, Any, None]]": """ Closes the AI Client Span unless the finally block in `_wrap_asynchronous_message_iterator()` runs first. """ - async def close(self: "AsyncStream") -> None: + async def close(self: "AsyncStream[RawMessageStreamEvent]") -> None: with _StreamSpanContext(self): return await f(self) @@ -998,23 +1075,27 @@ def _sentry_patched_enter(self: "MessageStreamManager") -> "MessageStream": if not hasattr(self, "_max_tokens"): return f(self) + patched_self = cast("_PatchedMessageStreamManager", self) + client = sentry_sdk.get_client() integration = client.get_integration(AnthropicIntegration) if integration is None: return f(self) - if self._messages is None: + if patched_self._messages is None: return f(self) try: - iter(self._messages) + iter(patched_self._messages) except TypeError: return f(self) if has_span_streaming_enabled(client.options): span = sentry_sdk.traces.start_span( - name="chat" if self._model is None else f"chat {self._model}".strip(), + name="chat" + if patched_self._model is None + else f"chat {patched_self._model}".strip(), attributes={ "sentry.op": OP.GEN_AI_CHAT, "sentry.origin": AnthropicIntegration.origin, @@ -1024,7 +1105,9 @@ def _sentry_patched_enter(self: "MessageStreamManager") -> "MessageStream": else: span = get_start_span_function()( op=OP.GEN_AI_CHAT, - name="chat" if self._model is None else f"chat {self._model}".strip(), + name="chat" + if patched_self._model is None + else f"chat {patched_self._model}".strip(), origin=AnthropicIntegration.origin, ) span.__enter__() @@ -1034,14 +1117,14 @@ def _sentry_patched_enter(self: "MessageStreamManager") -> "MessageStream": _set_common_input_data( span=span, integration=integration, - max_tokens=self._max_tokens, - messages=self._messages, - model=self._model, - system=self._system, - temperature=self._temperature, - top_k=self._top_k, - top_p=self._top_p, - tools=self._tools, + max_tokens=patched_self._max_tokens, + messages=patched_self._messages, + model=patched_self._model, + system=patched_self._system, + temperature=patched_self._temperature, + top_k=patched_self._top_k, + top_p=patched_self._top_p, + tools=patched_self._tools, ) try: @@ -1105,23 +1188,27 @@ async def _sentry_patched_aenter( if not hasattr(self, "_max_tokens"): return await f(self) + patched_self = cast("_PatchedAsyncMessageStreamManager", self) + client = sentry_sdk.get_client() integration = client.get_integration(AnthropicIntegration) if integration is None: return await f(self) - if self._messages is None: + if patched_self._messages is None: return await f(self) try: - iter(self._messages) + iter(patched_self._messages) except TypeError: return await f(self) if has_span_streaming_enabled(client.options): span = sentry_sdk.traces.start_span( - name="chat" if self._model is None else f"chat {self._model}".strip(), + name="chat" + if patched_self._model is None + else f"chat {patched_self._model}".strip(), attributes={ "sentry.op": OP.GEN_AI_CHAT, "sentry.origin": AnthropicIntegration.origin, @@ -1131,7 +1218,9 @@ async def _sentry_patched_aenter( else: span = get_start_span_function()( op=OP.GEN_AI_CHAT, - name="chat" if self._model is None else f"chat {self._model}".strip(), + name="chat" + if patched_self._model is None + else f"chat {patched_self._model}".strip(), origin=AnthropicIntegration.origin, ) span.__enter__() @@ -1141,14 +1230,14 @@ async def _sentry_patched_aenter( _set_common_input_data( span=span, integration=integration, - max_tokens=self._max_tokens, - messages=self._messages, - model=self._model, - system=self._system, - temperature=self._temperature, - top_k=self._top_k, - top_p=self._top_p, - tools=self._tools, + max_tokens=patched_self._max_tokens, + messages=patched_self._messages, + model=patched_self._model, + system=patched_self._system, + temperature=patched_self._temperature, + top_k=patched_self._top_k, + top_p=patched_self._top_p, + tools=patched_self._tools, ) try: diff --git a/uv.lock b/uv.lock index bf2403cdd7..5773d1e5ee 100644 --- a/uv.lock +++ b/uv.lock @@ -40,6 +40,7 @@ toxgen = [ { name = "requests" }, ] typing = [ + { name = "anthropic", specifier = ">=1.2.0" }, { name = "botocore-stubs" }, { name = "certifi" }, { name = "httpcore", extras = ["asyncio", "http2"] }, @@ -99,6 +100,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/99/91/8acff4f5e50511b911bbccb72b8628a49c68ce14148cd9f6431094859a90/annotated_types-0.8.0-py3-none-any.whl", hash = "sha256:f072f4d804ea359e4eaf198b1af7a8b0943881a87f31bb764f8bf219bb9419e0", size = 13427, upload-time = "2026-07-23T20:16:12.938Z" }, ] +[[package]] +name = "anthropic" +version = "1.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "anyio" }, + { name = "docstring-parser" }, + { name = "httpx2" }, + { name = "jiter" }, + { name = "pydantic" }, + { name = "sniffio" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/95/1a/b5af41cc1fa14da277ec20ca5554dd2fcbc09b8523ac59b7a97fbb88e452/anthropic-1.2.0.tar.gz", hash = "sha256:12f8eedee7b7fb5685837b1371b7bfae1b281703f62355f4632598ec2fc53b34", size = 1137443, upload-time = "2026-08-27T20:29:12.68Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ed/78/3f8b52708b03309e511990700bb8d0ec7a0c9db3d2a1e0d1c3ca417a4604/anthropic-1.2.0-py3-none-any.whl", hash = "sha256:b60642b3e3cd6b8e3e328a2d3f2863ad2b6e743f1037e42cc0143f7df99f63c6", size = 1289535, upload-time = "2026-08-27T20:29:11.01Z" }, +] + [[package]] name = "anyio" version = "4.14.2" @@ -560,6 +579,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ba/5a/18ad964b0086c6e62e2e7500f7edc89e3faa45033c71c1893d34eed2b2de/dnspython-2.8.0-py3-none-any.whl", hash = "sha256:01d9bbc4a2d76bf0db7c1f729812ded6d912bd318d3b1cf81d30c0f845dbf3af", size = 331094, upload-time = "2025-09-07T18:57:58.071Z" }, ] +[[package]] +name = "docstring-parser" +version = "0.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/4d/f332313098c1de1b2d2ff91cf2674415cc7cddab2ca1b01ae29774bd5fdf/docstring_parser-0.18.0.tar.gz", hash = "sha256:292510982205c12b1248696f44959db3cdd1740237a968ea1e2e7a900eeb2015", size = 29341, upload-time = "2026-04-14T04:09:19.867Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/5f/ed01f9a3cdffbd5a008556fc7b2a08ddb1cc6ace7effa7340604b1d16699/docstring_parser-0.18.0-py3-none-any.whl", hash = "sha256:b3fcbed555c47d8479be0796ef7e19c2670d428d72e96da63f3a40122860374b", size = 22484, upload-time = "2026-04-14T04:09:18.638Z" }, +] + [[package]] name = "docutils" version = "0.21.2" @@ -1010,6 +1038,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] +[[package]] +name = "jiter" +version = "0.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1d/1f/10936e16d8860c70698a1aa939a46aa0224813b782bce4e000e637da0b2d/jiter-0.16.0.tar.gz", hash = "sha256:7b24c3492c5f4f84a37946ad9cf504910cf6a782d6a4e0689b6673c5894b4a1c", size = 176431, upload-time = "2026-06-29T13:05:13.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/89/bc4f1b57d5da938fd344a466396541e586d161320d70bffd929aaafcd8f4/jiter-0.16.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:b2c61484666ad42726029af0c00ef4541f0f3b5cdc550221f56c2343208018ee", size = 308239, upload-time = "2026-06-29T13:03:57.205Z" }, + { url = "https://files.pythonhosted.org/packages/65/7a/c415453e5213001bf3b411ff65dec3d303b0e76a4a2cfea9768cd4960994/jiter-0.16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:63efadc657488f45db1c676d81e704cac2abf3fdb892def1faea61db053127e2", size = 308928, upload-time = "2026-06-29T13:03:58.643Z" }, + { url = "https://files.pythonhosted.org/packages/11/fc/1f4fb7ebf9a724c7741994f4aae18fba1e2f3133df14521a79194952c34a/jiter-0.16.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf0d73f50e7b6935677854f6e8e31d499ca7064dd24734f703e060f5b237d883", size = 336998, upload-time = "2026-06-29T13:04:00.071Z" }, + { url = "https://files.pythonhosted.org/packages/a0/8d/72cadaac05ccfa7cc3a0a2232862e6c72443ca40cf300ba8b57f9f18b69b/jiter-0.16.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bf3ea07d9bc8e7d03a9fbc051295462e6dbc295b894fd72457c3136e3e43d898", size = 362112, upload-time = "2026-06-29T13:04:01.52Z" }, + { url = "https://files.pythonhosted.org/packages/58/4a/c4b0d5f651fda90a24ffce9f8d56cde462a2e09d31ae3de3c68cef34c04e/jiter-0.16.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:26798522707abb47d767db536e4148ceac1b14446bf028ee85e579a2e043cfe5", size = 459807, upload-time = "2026-06-29T13:04:03.214Z" }, + { url = "https://files.pythonhosted.org/packages/80/58/ef77879ea9aa56b50824edc5a445e226422c7a8d211f3fd2a56bcb9493cf/jiter-0.16.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc837c1b9631be10abfe0191537fe8009838204cec7e44827401ace390ddb567", size = 373181, upload-time = "2026-06-29T13:04:04.629Z" }, + { url = "https://files.pythonhosted.org/packages/49/2e/ffbc3f254e4d8a66da3062c624a7df4b7c2b2cf9e1fe43cf394b3e104041/jiter-0.16.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49060fd70737fad59d33ba9dcc0d83247dc9e77187de26053a19c16c9f32bd69", size = 344927, upload-time = "2026-06-29T13:04:06.067Z" }, + { url = "https://files.pythonhosted.org/packages/9a/f6/0be5dc6d64a89f80aa8fec984f94dedb2973e251edcae55841d60786d578/jiter-0.16.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:adbb8edeadd431bc4477879d5d371ece7cb1334486584e0f252656dd7ffada29", size = 352754, upload-time = "2026-06-29T13:04:07.477Z" }, + { url = "https://files.pythonhosted.org/packages/da/6e/7d31243b3b91cd261dd19e9d3557fc3251a80883d3d8049c86174e7ab7af/jiter-0.16.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:31aaee5b80f672c1dc21272bcfb9cbdcfc1ea04ff50f00ed5af500b80c44fa93", size = 390553, upload-time = "2026-06-29T13:04:08.92Z" }, + { url = "https://files.pythonhosted.org/packages/25/33/51ae371fde3c88897520f62b4d5f8b27ad7103e2bb10812ff52195609853/jiter-0.16.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:6722bcef4ffc86c835574b1b2fac6b33b9fb4a889c781e67950e891591f3c55a", size = 516900, upload-time = "2026-06-29T13:04:10.407Z" }, + { url = "https://files.pythonhosted.org/packages/a0/45/6449b3d123ea439ba79507c657288f461d55049e7bcbdc2cf8eb8210f491/jiter-0.16.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:5ab4f50ff971b611d656554ea10b75f80097392c827bc32923c6eeb6386c8b00", size = 548754, upload-time = "2026-06-29T13:04:12.046Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e7/fd2fb11ae3e2649333da3aa170d04d7b3000bbdc3b270f6513382fdf4e04/jiter-0.16.0-cp314-cp314-pyemscripten_2026_0_wasm32.whl", hash = "sha256:710cc51d4ebdcd3c1f70b232c1db1ea1344a075770422bbd4bede5708335acbe", size = 122381, upload-time = "2026-06-29T13:04:13.413Z" }, + { url = "https://files.pythonhosted.org/packages/26/80/f0b147a62c315a164ed2168908286ca302310824c218d3aae52b06c0c9a9/jiter-0.16.0-cp314-cp314-win32.whl", hash = "sha256:57b37fc887a32d44798e4d8ebfa7c9683ff3da1d5bf38f08d1bb3573ccb39106", size = 204578, upload-time = "2026-06-29T13:04:14.813Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/4758a14304b4523a6f5adb2419340086aa3593bd4327c2b25b5948a90548/jiter-0.16.0-cp314-cp314-win_amd64.whl", hash = "sha256:cbd18dd5e2df96b580487b5745adf57ef64ad89ba2d9662fc3c19386acce7db8", size = 198154, upload-time = "2026-06-29T13:04:16.272Z" }, + { url = "https://files.pythonhosted.org/packages/26/be/41fa54a2e7ea41d6c99f1dc5b1f0fd4cb474680304b5d268dd518e81da3a/jiter-0.16.0-cp314-cp314-win_arm64.whl", hash = "sha256:a32d2027a9fa67f109ff245a3252ece3ccc32cc56703e1deab6cc846a59e0585", size = 191458, upload-time = "2026-06-29T13:04:17.707Z" }, + { url = "https://files.pythonhosted.org/packages/81/6b/59127338b86d9fe4d99418f5a15118bea778103ee0fe9d9dd7e0af174e95/jiter-0.16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2577196f4474ef3fc4779a088a23b0897bbf86f9ea3679c372d45b8383b43207", size = 316739, upload-time = "2026-06-29T13:04:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/2d/95/49461034d5388196d3dabf98748935f017b7785d8f3f5349f834bcc4ed0d/jiter-0.16.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:616e89e008a93c01104161c75b4988e58716b01d62307ebfe161e52a56d2a818", size = 340911, upload-time = "2026-06-29T13:04:21.257Z" }, + { url = "https://files.pythonhosted.org/packages/cd/97/a4369f2fb82cb3dda13b98622f31249b2e014b223fe64ee534413ad72294/jiter-0.16.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0e2e9efbe042210df657bade597f66d6d75723e3d8f45a12ea6d8167ff8bbce3", size = 361747, upload-time = "2026-06-29T13:04:22.677Z" }, + { url = "https://files.pythonhosted.org/packages/28/51/49b6ed456261646e1906016a6760367a28aacd3c24805e4e5fe64116c1db/jiter-0.16.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f4d9e473a5ce7d27fef8b848df4dc16e283893d3f53b4a585e72c9595f3c284", size = 460225, upload-time = "2026-06-29T13:04:24.441Z" }, + { url = "https://files.pythonhosted.org/packages/33/b5/5689aff4f66c5b60be63106e591dbfcba2190df97d2c9c7cf052361ddb98/jiter-0.16.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d30a4a1c87713060c8d1cc59a7b6c8fb6b8ef0a6900368014c76c87922a2929", size = 373169, upload-time = "2026-06-29T13:04:25.884Z" }, + { url = "https://files.pythonhosted.org/packages/a2/96/3ae1b85ee0d6d6cab254fb7f8da018272b932bbf2d69b07e98aa2a96c746/jiter-0.16.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bae96332410f866e5900d809298b1ed82735932986c672495f9701daacd80620", size = 350332, upload-time = "2026-06-29T13:04:27.302Z" }, + { url = "https://files.pythonhosted.org/packages/15/32/c99d7bafd78986556c95bf60ce84c6cc98786eac56066c12d7f828bb6747/jiter-0.16.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:da3d7ec75dc83bb18bca888b5edfae0656a26849056c59e05a7728badd17e7af", size = 353377, upload-time = "2026-06-29T13:04:28.731Z" }, + { url = "https://files.pythonhosted.org/packages/0e/4b/f99a8e571287c3dec766bcc18528bbe8e8fb5365522ab5e6d64c93e87066/jiter-0.16.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ee6162b77d49a9939229df666dfa8af3e656b6701b54c4c84966d740e189264e", size = 387746, upload-time = "2026-06-29T13:04:30.319Z" }, + { url = "https://files.pythonhosted.org/packages/75/69/c78a5b3f71040e34eb5917df26fb7ae9a2174cad1ccbf277512507c53a6e/jiter-0.16.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:63ffdbdae7d4499f4cda14eadc12ddcabef0fc0c081191bdc2247489cb698077", size = 517292, upload-time = "2026-06-29T13:04:31.709Z" }, + { url = "https://files.pythonhosted.org/packages/c2/f7/095b38eda4c70d03651c403f29a5590f16d12ddc5d544aac9f9cddf72277/jiter-0.16.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:a111256a7193bea0759267b10385e5870949c239ed7b6ddbaaf57573edb38734", size = 549259, upload-time = "2026-06-29T13:04:33.721Z" }, + { url = "https://files.pythonhosted.org/packages/2e/c5/6a0207d90e5f656d95af98ebd0934f382d37674416f215aeda2ff8063e51/jiter-0.16.0-cp314-cp314t-win32.whl", hash = "sha256:de5ba8763e56b793561f43bed197c9ea55776daa5e9a6b91eed68a909bc9cdbf", size = 206523, upload-time = "2026-06-29T13:04:35.068Z" }, + { url = "https://files.pythonhosted.org/packages/a5/31/c757d5f30a8980fd945ce7b98be10be9e4ff59c7c42f5fd86804c2e87db8/jiter-0.16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b8a3f9a6008048fe9def7bf465180564a6e458047d2ce499149cfbe73c3ae9db", size = 200366, upload-time = "2026-06-29T13:04:36.61Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a2/d88de6d313d734a544a7901353ad5db67cb38dcfcd91713b7979dafc345d/jiter-0.16.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0fa25b09b13075c46f5bc174f2690525a925a4fc2f7c82969a2bbabff22386ce", size = 190516, upload-time = "2026-06-29T13:04:38.004Z" }, +] + [[package]] name = "jsonpatch" version = "1.33" From 81e7cae6d85c9d9457de70ece73757c9730a070a Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Tue, 1 Sep 2026 11:15:58 +0200 Subject: [PATCH 2/2] move import --- sentry_sdk/integrations/anthropic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sentry_sdk/integrations/anthropic.py b/sentry_sdk/integrations/anthropic.py index 120a1cdc60..4308415156 100644 --- a/sentry_sdk/integrations/anthropic.py +++ b/sentry_sdk/integrations/anthropic.py @@ -49,7 +49,6 @@ AsyncMessageStreamManager, MessageStream, MessageStreamManager, - ParsedMessageStreamEvent, ) from anthropic.resources import AsyncMessages, Messages from anthropic.types import ( @@ -78,6 +77,7 @@ Union, ) + from anthropic.lib.streaming import ParsedMessageStreamEvent from anthropic.types import ( MessageParam, ModelParam,