Skip to content

Add __str__ methods to content blocks and message types#833

Open
yuribodo wants to merge 1 commit intoanthropics:mainfrom
yuribodo:feature/message-types-str-repr
Open

Add __str__ methods to content blocks and message types#833
yuribodo wants to merge 1 commit intoanthropics:mainfrom
yuribodo:feature/message-types-str-repr

Conversation

@yuribodo
Copy link
Copy Markdown

@yuribodo yuribodo commented Apr 17, 2026

Summary

Closes #78. Adds __str__ methods to user-facing content-block and message dataclasses so print(msg) produces readable output out of the box, removing the need for custom display_message helpers like the one in examples/streaming_mode.py.

Before

Users had to write their own isinstance ladder:

if isinstance(msg, UserMessage):
    for block in msg.content:
        if isinstance(block, TextBlock):
            print(f"User: {block.text}")
elif isinstance(msg, AssistantMessage):
    ...

After

print(msg)
# User: hi
# Claude: sure, [Tool use: Read] {'path': '/tmp/x'}
# [Task progress] Refactor tests (task_id=tsk_1, tokens=1200)
# [RateLimit: allowed_warning] five_hour @ 85%
# [Result: success] duration=1230ms, cost=$0.0015

Covered types

  • Content blocks: TextBlock, ThinkingBlock, ToolUseBlock, ToolResultBlock
  • Messages: UserMessage, AssistantMessage, SystemMessage, ResultMessage
  • System-message subclasses: TaskStartedMessage, TaskProgressMessage, TaskNotificationMessage (override the parent __str__ so their description / status / summary isn't lost)
  • Events: StreamEvent, RateLimitEvent

Hook-related types and MCP status types are TypedDict, not dataclasses, so they're out of scope here.

Design notes

  • __str__ only — the dataclass-generated __repr__ is left alone. Python convention is str() for end users, repr() for developers, and keeping the default repr preserves useful debugging output in the REPL, logging, and pytest assertion messages. The issue title says "reprs" but the body clearly asks for print-friendly display, so __str__ felt like the conservative call. Happy to switch if maintainers prefer overriding __repr__ instead.
  • Truncation: ToolUseBlock.input and ToolResultBlock.content are truncated to 200 chars (with ...) so a large Write/Edit payload doesn't blow up terminal output. The dataclass __repr__ still renders the full payload for debugging.
  • Empty content: UserMessage / AssistantMessage with no content render as "User:" / "Claude:" — no trailing space.
  • None content on ToolResultBlock: renders as "[Tool result]", not "[Tool result] None".

Test plan

  • python -m pytest tests/ — 510 passed (26 new in TestMessageStr, covering truncation, empty/None content, mixed-block ordering, task subclasses, stream events, rate-limit events)
  • python -m ruff check src/ tests/ — clean
  • python -m ruff format --check src/ tests/ — clean
  • python -m mypy src/ — no issues

Makes messages pretty-printable by default, so users can call print(msg)
without writing custom display helpers like the ones in examples/.

- TextBlock prints text verbatim; ThinkingBlock, ToolUseBlock, and
  ToolResultBlock print with a labeled prefix.
- ToolUseBlock.input and ToolResultBlock.content are truncated to 200
  chars so a large Write/Edit payload doesn't blow up terminal output.
- UserMessage / AssistantMessage join their content blocks; empty
  content yields "User:" / "Claude:" without a trailing space.
- SystemMessage shows its subtype. TaskStartedMessage,
  TaskProgressMessage, and TaskNotificationMessage override it to
  surface their description/status/summary instead of inheriting the
  lossy parent format.
- StreamEvent shows the event type; RateLimitEvent shows status,
  window, and utilization.
- ResultMessage surfaces duration and cost when available.

__repr__ remains the dataclass default so debugging output (REPL,
logging, pytest assertion reprs) is unchanged — this PR adds __str__
only, per Python's str-for-users / repr-for-developers convention.

Closes anthropics#78
@yuribodo yuribodo force-pushed the feature/message-types-str-repr branch from 86cf611 to edc4522 Compare April 17, 2026 01:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support reprs for message types

1 participant