Skip to content

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

Merged
Pierre-Sassoulas merged 7 commits into
pytest-dev:mainfrom
EternalRights:fix-approx-timedelta-rel
May 12, 2026
Merged

fix approx rel for timedelta: accept float, compute rel * expected#14466
Pierre-Sassoulas merged 7 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)
@Pierre-Sassoulas Pierre-Sassoulas added the topic: approx related to pytest.approx function label May 12, 2026
Comment thread changelog/14462.bugfix.rst Outdated
@@ -0,0 +1 @@
Fixed ``rel`` parameter in :func:`pytest.approx` for :class:`~datetime.timedelta` comparisons -- it was being treated as an absolute tolerance instead of a relative one.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think it was released, so no need for a changelog.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good point, removed the changelog entry. Thanks!

The rel parameter for timedelta never worked correctly in a released
version, so there is no bug to document.
@Pierre-Sassoulas Pierre-Sassoulas added the skip news used on prs to opt out of the changelog requirement label May 12, 2026
Copy link
Copy Markdown
Member

@Pierre-Sassoulas Pierre-Sassoulas left a comment

Choose a reason for hiding this comment

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

Thank you for catching that !

@Pierre-Sassoulas Pierre-Sassoulas enabled auto-merge (squash) May 12, 2026 09:23
@Pierre-Sassoulas Pierre-Sassoulas merged commit 2c555d6 into pytest-dev:main May 12, 2026
33 checks passed
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 skip news used on prs to opt out of the changelog requirement topic: approx related to pytest.approx function

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

3 participants