Skip to content

fix approx rel for timedelta: accept float, compute rel * expected#14466

Open
EternalRights wants to merge 6 commits into
pytest-dev:mainfrom
EternalRights:fix-approx-timedelta-rel
Open

fix approx rel for timedelta: accept float, compute rel * expected#14466
EternalRights wants to merge 6 commits into
pytest-dev:mainfrom
EternalRights:fix-approx-timedelta-rel

Conversation

@EternalRights
Copy link
Copy Markdown
Contributor

Was looking into #14462 and noticed that the rel param for timedelta in approx was being treated as an absolute tolerance -- merged with abs via max() instead of being scaled by the expected value. So approx(timedelta(seconds=100), rel=timedelta(seconds=5)) gave you a flat 5-second tolerance, not 5% of 100 seconds.

The fix makes rel accept a float for timedelta comparisons, same as it works for numbers. Now approx(td, rel=0.05) means "within 5% of the expected timedelta", which is what you'd naturally expect from a parameter called rel. The tolerance is computed as rel * abs(expected), which works because timedelta * float returns a timedelta in Python.

When both rel and abs are provided, the larger tolerance wins (same as ApproxScalar).

rel for datetime is still rejected with the same TypeError as before.

Closes #14462

@psf-chronographer psf-chronographer Bot added the bot:chronographer:provided (automation) changelog entry is part of PR label May 12, 2026
EternalRights and others added 5 commits May 12, 2026 12:45
The PR forgot to validate rel and abs for timedelta the same way
ApproxScalar does. Without these checks, a negative rel produces a
negative timedelta tolerance that makes every comparison silently
return False, and NaN rel throws a confusing error message.

- Raise ValueError for negative rel
- Raise ValueError for NaN rel
- Raise ValueError for negative abs (timedelta)
- Add corresponding tests
…comparisons

_approx_scalar only knew about Decimal vs scalar, so
approx([timedelta(...)], rel=0.05) silently fell back to
strict equality. Route datetime/timedelta elements through
ApproxTimedelta instead.

Also mention rel in the "requires tolerance" error message
and fix the return type annotation.
…atetime

The isinstance(expected, datetime) check inside the rel block was
unreachable because the same condition is already caught earlier at
the top of __init__. Removing it fixes the codecov/patch failure.

Also add tests for two uncovered branches in _approx_scalar:
- timedelta in mapping with abs tolerance (only rel was tested)
- datetime in sequence and mapping (not tested at all)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bot:chronographer:provided (automation) changelog entry is part of PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

approx with timedelta: rel parameter treated as absolute tolerance despite its name

2 participants