async retry: validate | and & operands at the operator site#1
async retry: validate | and & operands at the operator site#1HrachShah wants to merge 5 commits into
Conversation
…exError (jd#646) Calling wait_chain() with no strategies stored an empty tuple in self.strategies. The first call to __call__ then evaluated min(max(1, 1), 0) == 0, so self.strategies[wait_func_no - 1] turned into self.strategies[-1] and raised IndexError, which is opaque for what is really a programmer error at construction time. Validate in __init__ and raise ValueError('wait_chain() requires at least one strategy') so the failure happens at the point where the bad configuration is created, not later when the wait function is first evaluated inside a running retry. Co-authored-by: Zo Bot <github-automation@zo.computer>
Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 6.0.3 to 7.0.0 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@v6.0.3...v7.0.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 7.0.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: github-actions ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
The sync retry_base operators | and & got a guard in jd#648 that rejects non-callable, non-retry_base operands with a clear TypeError at the construction site. The async_retry_base (and async retry_any.__ror__ / retry_all.__rand__ that override the inherited methods) define the same operator surface but did not call _validate_predicate, so the guard did not extend to the async path. Before this fix: True | retry_if_exception(...) # built silently ...later, inside the retry loop, awaited a bool and crashed with 'TypeError: object bool can t be used in await expression', far from the line that actually wrote the bad expression. After this fix the same misuse raises synchronously at the | / & site with a clear message naming the bad operand's type and repr, matching the sync behaviour. Adds four new tests in tests/test_asyncio.py: - test_async_retry_composition_rejects_non_callable: covers the four operator overloads (|, __ror__, &, __rand__) with bool/int/str/None. - test_async_retry_composition_accepts_valid_operands: regression guard for legitimate async | async, async | sync, async | callable compositions. - test_async_retry_any_ror_validates_leaf_operand: covers the override in retry_any that flattens nested retry_any groups; the leaf branch must still validate. - test_async_retry_all_rand_validates_leaf_operand: mirror of the above for retry_all.__rand__. 171 tests pass (was 167).
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Reviewer's GuideAdds operand validation for sync and async retry composition operators so non-callable, non-retry_base operands fail fast with clear TypeErrors, tightens async retry_any/all flattening behavior, makes wait_chain() reject empty strategies with a ValueError, and extends tests and release notes to cover these behaviors. Sequence diagram for async retry operator fast-fail validationsequenceDiagram
actor User
participant bool_operand as bool
participant async_predicate as async_retry_base
participant retry_any
User->>bool_operand: True | async_predicate
bool_operand-->>async_predicate: __ror__(other)
async_predicate->>async_predicate: _validate_predicate(other)
alt invalid_operand
async_predicate-->>User: TypeError
else valid_operand
async_predicate-->>retry_any: __ror__(other)
retry_any-->>User: composed_predicate
end
Flow diagram for wait_chain empty strategies validationflowchart LR
A[wait_chain] --> B[wait_chained.__init__ with strategies]
B --> C{strategies empty?}
C -->|yes| D[raise ValueError]
C -->|no| E[store strategies]
E --> F[wait_chained.__call__ with retry_state]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
The sync
retry_baseoperators|and&got a guard in jd#648 that rejects non-callable, non-retry_baseoperands with a clear TypeError at the construction site. Theasync_retry_base(and asyncretry_any.__ror__/retry_all.__rand__that override the inherited methods) define the same operator surface but did not call_validate_predicate, so the guard did not extend to the async path.Before this fix:
True | retry_if_exception(...)built silently, then crashed inside the retry loop withTypeError: object bool can t be used in await expression, far from the offending line.This change adds the same validation to the async operator methods so the error surfaces at the construction site as a clear TypeError naming the operand type, matching the sync behavior.
Summary by Sourcery
Validate retry operator operands for both sync and async paths and ensure wait_chain rejects empty strategy lists with clear errors.
Bug Fixes:
Documentation:
Tests: