Skip to content

Commit 7bd7ed4

Browse files
version check and typing
1 parent e3cc76d commit 7bd7ed4

File tree

2 files changed

+48
-37
lines changed

2 files changed

+48
-37
lines changed

sentry_sdk/integrations/anthropic.py

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,13 @@ def setup_once() -> None:
120120
MessageStreamManager.__enter__ = _wrap_message_stream_manager_enter(
121121
MessageStreamManager.__enter__
122122
)
123-
MessageStream.__iter__ = _wrap_message_stream_iter(MessageStream.__iter__)
124-
MessageStream.__next__ = _wrap_message_stream_next(MessageStream.__next__)
125-
MessageStream.close = _wrap_message_stream_close(MessageStream.close)
123+
124+
# Before https://github.com/anthropics/anthropic-sdk-python/commit/b1a1c0354a9aca450a7d512fdbdeb59c0ead688a
125+
# MessageStream inherits from Stream, so patching Stream is sufficient on these versions.
126+
if version >= (0, 26, 2):
127+
MessageStream.__iter__ = _wrap_message_stream_iter(MessageStream.__iter__)
128+
MessageStream.__next__ = _wrap_message_stream_next(MessageStream.__next__)
129+
MessageStream.close = _wrap_message_stream_close(MessageStream.close)
126130

127131
AsyncMessages.stream = _wrap_async_message_stream(AsyncMessages.stream)
128132
AsyncMessageStreamManager.__aenter__ = (
@@ -779,7 +783,7 @@ def _wrap_stream_iter(
779783
output attributes on the AI Client Span and end the span.
780784
"""
781785

782-
def __iter__(self) -> "Iterator[RawMessageStreamEvent]":
786+
def __iter__(self: "Stream") -> "Iterator[RawMessageStreamEvent]":
783787
if not hasattr(self, "_span"):
784788
for event in f(self):
785789
yield event
@@ -801,24 +805,26 @@ def _wrap_stream_next(
801805
Accumulates output data from the returned event.
802806
"""
803807

804-
def __next__(self) -> "RawMessageStreamEvent":
808+
def __next__(self: "Stream") -> "RawMessageStreamEvent":
805809
_initialize_data_accumulation_state(self)
806810
try:
807811
event = f(self)
808812
except StopIteration:
809-
if not hasattr(self, "_span"):
810-
raise
811-
812-
_finish_streaming_span(
813-
self._span,
814-
self._integration,
815-
self._model,
816-
self._usage,
817-
self._content_blocks,
818-
self._response_id,
819-
)
820-
del self._span
821-
raise
813+
exc_info = sys.exc_info()
814+
with capture_internal_exceptions():
815+
if not hasattr(self, "_span"):
816+
raise
817+
818+
_finish_streaming_span(
819+
self._span,
820+
self._integration,
821+
self._model,
822+
self._usage,
823+
self._content_blocks,
824+
self._response_id,
825+
)
826+
del self._span
827+
reraise(*exc_info)
822828

823829
_accumulate_event_data(self, event)
824830
return event
@@ -833,7 +839,7 @@ def _wrap_stream_close(
833839
Closes the AI Client Span, unless the finally block in `_wrap_synchronous_message_iterator()` runs first.
834840
"""
835841

836-
def close(self) -> None:
842+
def close(self: "Stream") -> None:
837843
if not hasattr(self, "_span"):
838844
return f(self)
839845

@@ -979,7 +985,7 @@ def _wrap_message_stream_iter(
979985
output attributes on the AI Client Span and end the span.
980986
"""
981987

982-
def __iter__(self) -> "Iterator[MessageStreamEvent]":
988+
def __iter__(self: "MessageStream") -> "Iterator[MessageStreamEvent]":
983989
if not hasattr(self, "_span"):
984990
for event in f(self):
985991
yield event
@@ -1001,24 +1007,26 @@ def _wrap_message_stream_next(
10011007
Accumulates output data from the returned event.
10021008
"""
10031009

1004-
def __next__(self) -> "MessageStreamEvent":
1010+
def __next__(self: "MessageStream") -> "MessageStreamEvent":
10051011
_initialize_data_accumulation_state(self)
10061012
try:
10071013
event = f(self)
10081014
except StopIteration:
1009-
if not hasattr(self, "_span"):
1010-
raise
1011-
1012-
_finish_streaming_span(
1013-
self._span,
1014-
self._integration,
1015-
self._model,
1016-
self._usage,
1017-
self._content_blocks,
1018-
self._response_id,
1019-
)
1020-
del self._span
1021-
raise
1015+
exc_info = sys.exc_info()
1016+
with capture_internal_exceptions():
1017+
if not hasattr(self, "_span"):
1018+
raise
1019+
1020+
_finish_streaming_span(
1021+
self._span,
1022+
self._integration,
1023+
self._model,
1024+
self._usage,
1025+
self._content_blocks,
1026+
self._response_id,
1027+
)
1028+
del self._span
1029+
reraise(*exc_info)
10221030

10231031
_accumulate_event_data(self, event)
10241032
return event
@@ -1033,7 +1041,7 @@ def _wrap_message_stream_close(
10331041
Closes the AI Client Span, unless the finally block in `_wrap_synchronous_message_iterator()` runs first.
10341042
"""
10351043

1036-
def close(self) -> None:
1044+
def close(self: "MessageStream") -> None:
10371045
if not hasattr(self, "_span"):
10381046
return f(self)
10391047

tests/integrations/anthropic/test_anthropic.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ async def __call__(self, *args, **kwargs):
1313

1414

1515
from anthropic import Anthropic, AnthropicError, AsyncAnthropic
16+
from anthropic.lib.streaming import TextEvent
1617
from anthropic.types import MessageDeltaUsage, TextDelta, Usage
1718
from anthropic.types.content_block_delta_event import ContentBlockDeltaEvent
1819
from anthropic.types.content_block_start_event import ContentBlockStartEvent
@@ -815,8 +816,10 @@ def test_stream_messages_iterator_methods(
815816
) as stream:
816817
next(stream)
817818
next(stream)
818-
list(islice(stream, 2))
819-
next(stream)
819+
list(islice(stream, 1))
820+
# New versions add TextEvent, so consume one more event.
821+
if isinstance(next(stream), TextEvent):
822+
next(stream)
820823
stream.close()
821824

822825
assert len(events) == 1

0 commit comments

Comments
 (0)