Potential edge case in _is_async_callable detection for callable objects #10581

Open
opened 2026-04-18 17:48:59 +00:00 by HAL9000 · 0 comments
Owner

Metadata

Commit Message: Investigate _is_async_callable edge cases with decorated callable objects
Branch Name: investigate/async-callable-edge-cases

Background and Context

The _is_async_callable function in src/cleveragents/core/retry_service_patterns.py may not correctly detect all types of async callable objects, particularly those that are instances of classes with async __call__ methods that are wrapped or decorated in certain ways.

This detection logic is critical for the retry_service_operation function to correctly classify whether a callable is async or sync. Incorrect classification can lead to TypeError exceptions when the function is actually async but is treated as sync.

Expected Behavior

The _is_async_callable function should correctly detect all async callable objects, including:

  • Callable objects wrapped with functools.wraps or similar decorators
  • Callable objects that inherit async __call__ from a parent class
  • Callable objects with metaclasses that override __call__
  • Callable objects with decorated async __call__ methods

Actual Behavior

Some async callable objects may be incorrectly classified as sync callables due to limitations in the current detection logic. The function currently checks:

  1. asyncio.iscoroutinefunction(func)
  2. isinstance(func, partial) and checks the wrapped function
  3. asyncio.iscoroutinefunction(type(func).__call__)

This approach may fail for callable objects that have been wrapped with decorators that don't preserve the async __call__ method signature.

Acceptance Criteria

  • Identify all edge cases where _is_async_callable fails to detect async callables
  • Create test cases covering:
    • Callable objects with async __call__ wrapped with functools.wraps
    • Callable objects inheriting async __call__ from parent classes
    • Callable objects with metaclasses overriding __call__
    • Callable objects with decorated async __call__ methods
  • Update _is_async_callable to handle all identified edge cases
  • Verify that retry_service_operation correctly classifies all async callables
  • All tests pass with coverage >= 97%

Subtasks

  • Research and document all edge cases for async callable detection
  • Create comprehensive test suite for _is_async_callable
  • Implement improved detection logic in _is_async_callable
  • Update documentation for retry_service_operation with examples
  • Verify fix with integration tests

Definition of Done

This issue is complete when:

  1. All identified edge cases are covered by tests
  2. _is_async_callable correctly detects async callables in all scenarios
  3. retry_service_operation correctly classifies async vs sync callables
  4. No regressions in existing tests
  5. Test coverage remains >= 97%
  6. Code review approved

Automated by CleverAgents Bot
Agent: new-issue-creator

## Metadata **Commit Message:** Investigate _is_async_callable edge cases with decorated callable objects **Branch Name:** investigate/async-callable-edge-cases ## Background and Context The `_is_async_callable` function in `src/cleveragents/core/retry_service_patterns.py` may not correctly detect all types of async callable objects, particularly those that are instances of classes with async `__call__` methods that are wrapped or decorated in certain ways. This detection logic is critical for the `retry_service_operation` function to correctly classify whether a callable is async or sync. Incorrect classification can lead to `TypeError` exceptions when the function is actually async but is treated as sync. ## Expected Behavior The `_is_async_callable` function should correctly detect all async callable objects, including: - Callable objects wrapped with `functools.wraps` or similar decorators - Callable objects that inherit async `__call__` from a parent class - Callable objects with metaclasses that override `__call__` - Callable objects with decorated async `__call__` methods ## Actual Behavior Some async callable objects may be incorrectly classified as sync callables due to limitations in the current detection logic. The function currently checks: 1. `asyncio.iscoroutinefunction(func)` 2. `isinstance(func, partial)` and checks the wrapped function 3. `asyncio.iscoroutinefunction(type(func).__call__)` This approach may fail for callable objects that have been wrapped with decorators that don't preserve the async `__call__` method signature. ## Acceptance Criteria - [ ] Identify all edge cases where `_is_async_callable` fails to detect async callables - [ ] Create test cases covering: - Callable objects with async `__call__` wrapped with `functools.wraps` - Callable objects inheriting async `__call__` from parent classes - Callable objects with metaclasses overriding `__call__` - Callable objects with decorated async `__call__` methods - [ ] Update `_is_async_callable` to handle all identified edge cases - [ ] Verify that `retry_service_operation` correctly classifies all async callables - [ ] All tests pass with coverage >= 97% ## Subtasks - [ ] Research and document all edge cases for async callable detection - [ ] Create comprehensive test suite for `_is_async_callable` - [ ] Implement improved detection logic in `_is_async_callable` - [ ] Update documentation for `retry_service_operation` with examples - [ ] Verify fix with integration tests ## Definition of Done This issue is complete when: 1. All identified edge cases are covered by tests 2. `_is_async_callable` correctly detects async callables in all scenarios 3. `retry_service_operation` correctly classifies async vs sync callables 4. No regressions in existing tests 5. Test coverage remains >= 97% 6. Code review approved --- **Automated by CleverAgents Bot** Agent: new-issue-creator
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
cleveragents/cleveragents-core#10581
No description provided.