Skip to content

Python: reject @executor on staticmethod/classmethod with clear error message - #1719

Merged
Evan Mattson (moonbox3) merged 3 commits into
microsoft:mainfrom
moonbox3:fix-1678
Oct 27, 2025
Merged

Python: reject @executor on staticmethod/classmethod with clear error message#1719
Evan Mattson (moonbox3) merged 3 commits into
microsoft:mainfrom
moonbox3:fix-1678

Conversation

@moonbox3

Copy link
Copy Markdown
Contributor

Motivation and Context

Addresses the underlying issue from a bug report about @executor being used with @staticmethod. While this is not a supported use case, the decorator now properly detects and rejects this pattern with a clear, actionable error message.

The @executor decorator is designed for standalone module-level functions only. When mistakenly used with @staticmethod or @classmethod, it would previously fail with confusing errors or incorrect behavior because:

  1. When decorators are stacked (@executor then @staticmethod), the executor receives a descriptor object, not the function
  2. asyncio.iscoroutinefunction() returns False for descriptor objects, even if the wrapped function is async
  3. No validation prevented this misuse

The fix is to have:

  • Detection and Clear Error Messages:
    • Added isinstance() check to detect staticmethod and classmethod descriptors
    • Raises ValueError with actionable guidance directing users to the correct pattern:
      • Use @executor for standalone functions
      • Use Executor subclass with @handler on instance methods

Defensive Unwrapping:

  • Added _unwrap_descriptor() helper to extract underlying callables from descriptors
  • Makes sure async detection works correctly even in edge cases
  • Applied unwrapping before signature validation and async checks

Description

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Copilot AI review requested due to automatic review settings October 27, 2025 02:24
@moonbox3 Evan Mattson (moonbox3) added python Usage: [Issues, PRs], Target: Python workflows Usage: [Issues, PRs], Target: Workflows labels Oct 27, 2025

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull Request Overview

This PR enhances the Python @executor decorator to properly detect and reject its misuse with @staticmethod and @classmethod through clear, actionable error messages. Previously, using @executor with these descriptors would fail with confusing errors because the decorator received a descriptor object instead of the actual function, causing async detection to fail.

Key Changes:

  • Added explicit validation to reject @staticmethod/@classmethod usage with helpful error messages
  • Introduced _unwrap_descriptor() helper for defensive unwrapping in edge cases
  • Enhanced documentation to clarify the intended usage pattern (standalone functions vs. class-based executors)

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
python/packages/core/agent_framework/_workflows/_function_executor.py Added descriptor detection/rejection logic, unwrapping helper, and updated documentation to clarify supported usage patterns
python/packages/core/tests/workflow/test_function_executor.py Added comprehensive tests validating rejection of @staticmethod/@classmethod and documenting async detection behavior with descriptors

Comment thread python/packages/core/agent_framework/_workflows/_function_executor.py Outdated
@markwallace-microsoft

Mark Wallace (markwallace-microsoft) commented Oct 27, 2025

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework/_workflows
   _function_executor.py44490%101, 107, 113, 129
TOTAL12296200483% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
1404 98 💤 0 ❌ 0 🔥 27.847s ⏱️

@moonbox3
Evan Mattson (moonbox3) added this pull request to the merge queue Oct 27, 2025
@moonbox3
Evan Mattson (moonbox3) removed this pull request from the merge queue due to a manual request Oct 27, 2025
@moonbox3
Evan Mattson (moonbox3) added this pull request to the merge queue Oct 27, 2025
Merged via the queue into microsoft:main with commit e2d1ba3 Oct 27, 2025
20 checks passed
Reuben Bond (ReubenBond) pushed a commit to ReubenBond/agent-framework that referenced this pull request Oct 28, 2025
… message (microsoft#1719)

* reject executor on static method w clear error

* Simplify

* Cleanup
Aris Nguyen (arisng) pushed a commit to arisng/agent-framework that referenced this pull request Feb 2, 2026
… message (microsoft#1719)

* reject executor on static method w clear error

* Simplify

* Cleanup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

python Usage: [Issues, PRs], Target: Python workflows Usage: [Issues, PRs], Target: Workflows

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Python: @executor incorrectly treats @staticmethod async def as sync functions

5 participants