Skip to content

fix(telemetry): keep staticmethods static under trace_class - #1430

Open
ShivamSharma43 wants to merge 1 commit into
a2aproject:mainfrom
ShivamSharma43:fix-trace-class-staticmethod
Open

ShivamSharma43 wants to merge 1 commit into
a2aproject:mainfrom
ShivamSharma43:fix-trace-class-staticmethod

Conversation

@ShivamSharma43

Copy link
Copy Markdown

Problem

trace_class turns a @staticmethod into an instance method. It collects methods with inspect.getmembers(cls, inspect.isfunction), which returns the plain function behind a staticmethod. The traced wrapper is then set back on the class with setattr, without the staticmethod wrapper, so calling the method on an instance passes self as its first argument:

from a2a.utils.telemetry import trace_class

@trace_class()
class Svc:
    @staticmethod
    def double(x: int) -> int:
        return x * 2

    def run(self) -> int:
        return self.double(21)

Svc().run()
# TypeError: Svc.double() takes 1 positional argument but 2 were given

None of the SDK's own traced classes has a staticmethod today, but trace_class is public and its docstring shows it applied to user classes.

Fix

After building the traced wrapper, check the class attribute with inspect.getattr_static. If it is a staticmethod, wrap the traced function in staticmethod again before setting it. This also covers a staticmethod inherited from a base class, which getmembers returns as well. Instance methods are unchanged, and classmethods stay untraced as before, because getmembers returns them as bound methods.

Tests

test_trace_class_keeps_staticmethod_static decorates a class with its own staticmethod and an inherited one. It calls them through an instance, through the class, and from another method, and it checks that both stay staticmethod objects and are still traced. On main it fails with the TypeError above. With the fix it passes.

  • uv run pytest tests/utils/test_telemetry.py: 22 passed
  • bash scripts/lint.sh: success. The 3 ruff diagnostics it prints are in client_factory.py and transports/__init__.py, which this change does not touch.
  • uv run pytest on Windows, Python 3.10, skipping tests/integration/cross_version and tests/integration/push_notifications because they need os.killpg and fork-based multiprocessing: 2549 passed, 207 skipped, 4 xfailed, 1 xpassed

🤖 Generated with Claude Code

trace_class collects methods with inspect.getmembers(cls,
inspect.isfunction), which unwraps a staticmethod into its plain
function. The traced wrapper was then set back on the class as a plain
function, so the method became an instance method: calling it on an
instance passed self as the first argument and raised TypeError.

Re-wrap the traced function in staticmethod when the class attribute
is a staticmethod, including one inherited from a base class.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ShivamSharma43
ShivamSharma43 requested a review from a team as a code owner November 5, 2026 18:45
Copilot AI balanced review requested due to automatic review settings November 5, 2026 18:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown

🧪 Code Coverage (vs main)

⬇️ Download Full Report

Base PR Delta
src/a2a/utils/telemetry.py 90.70% 91.04% 🟢 +0.35%
Total 93.53% 93.53% ⚪️ 0.00%

Generated by coverage-comment.yml

This branch has not been deployed

No deployments
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.

2 participants