Fix issues with bounds - #269
Open
llucax wants to merge 3 commits into
Open
Conversation
`Bounds.__post_init__` only checked `lower > upper`, but every
comparison against `NaN` is `False`, so `Bounds(lower=float("nan"),
upper=10.0)` — and any other `NaN` endpoint — was accepted as a
well-formed bound. That let malformed wire data through as a valid
`Bounds`, bypassing the new invalid-bounds type and the semantic
accessor checks, even though a `NaN` endpoint can never satisfy the
range invariant.
Reject `NaN` in either present endpoint before the ordering check.
Because `bounds_from_proto2` catches the `ValueError` and falls back to
`InvalidBounds`, a `NaN` bound now flows through to `InvalidBounds` /
`InvalidBoundsSet` at every layer (bounds, metric samples, electrical
component config bounds) instead of masquerading as valid.
`InvalidBounds` intentionally still accepts `NaN`: its whole purpose is to
preserve malformed wire data verbatim for inspection.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
`math.isnan()` converts its argument to a `float`, so calling it on an
`int` too large to fit in a `float` (a legitimate `FloatInt` endpoint or
membership value) raised `OverflowError`:
10**1000 in Bounds() # OverflowError
10**1000 in BoundsSet() # OverflowError
Bounds(lower=10**1000) # OverflowError
Only a `float` can be `NaN`, so guard every `math.isnan()` call with an
`isinstance(x, float)` check. This covers membership on `Bounds` and
`BoundsSet` and the endpoint validation in `Bounds.__post_init__`, so
large integers now compare and sort as ordinary finite values.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
A `-inf` lower bound and a `+inf` upper bound denote the unbounded
direction, which the library already represents with `None`. Keeping the
infinite form gave the same interval two spellings, so equality, hashing
and `is_bounded()` disagreed for sets that already cover the whole space:
Bounds(lower=-math.inf, upper=math.inf) == Bounds() # was False
bool(BoundsSet(bounds=(Bounds(-math.inf, math.inf),))) # was True
Canonicalize a `-inf` lower and a `+inf` upper to `None` in
`Bounds.__post_init__`, so an all-covering bound collapses to the empty,
falsy unbounded set as documented. A wrong-side infinity (`+inf` lower or
`-inf` upper) is not the unbounded direction, so it is kept as a real
endpoint and a contradictory pair still raises. The check uses `==`
rather than `math.isinf()` to stay overflow-safe on large `int`
endpoints.
Signed-off-by: Leandro Lucarella <luca-frequenz@llucax.com>
llucax
requested review from
ela-kotulska-frequenz,
shsms and
tiyash-basu-frequenz
and removed request for
a team
August 14, 2026 19:21
llucax
enabled auto-merge
August 14, 2026 19:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR fixes a few issues found in the review of the PRs introducing bounds.