Skip to content

Raise TypeError when a Constraint is used in a boolean context (#4337)#7121

Open
gaoflow wants to merge 1 commit into
SciTools:mainfrom
gaoflow:fix/constraint-bool-typeerror
Open

Raise TypeError when a Constraint is used in a boolean context (#4337)#7121
gaoflow wants to merge 1 commit into
SciTools:mainfrom
gaoflow:fix/constraint-bool-typeerror

Conversation

@gaoflow
Copy link
Copy Markdown

@gaoflow gaoflow commented Jun 1, 2026

🚀 Pull Request

Description

Closes #4337.

A :class:iris.Constraint has no truth value, but it also had no __bool__, so Python treated it as always-truthy. That meant combining constraints with the and/or/not keywords failed silently — the expression evaluated to one operand and quietly discarded the other:

>>> import iris
>>> c1 = iris.Constraint('air_temperature')
>>> c2 = iris.Constraint('time')
>>> c1 or c2
Constraint(name='air_temperature')   # c2 silently lost!
>>> bool(c1)
True

So cube.extract(c1 or c2) would silently ignore c2, which is exactly the support query that prompted this issue.

Approach

As agreed by @SciTools/peloton on the issue ("the Constraint class should include the appropriate override to prevent it being used in boolean statements ... to raise TypeError. A unit test for this error should also be added"), this adds Constraint.__bool__ raising an informative TypeError that points users at the supported & operator — mirroring how numpy rejects truth-testing of multi-element arrays:

>>> c1 or c2
TypeError: The truth value of a Constraint is ambiguous. Constraints cannot
be combined with the 'and', 'or' and 'not' keywords; use the '&' operator
instead, e.g. 'constraint1 & constraint2'.
>>> c1 & c2          # supported combination, unchanged
ConstraintCombination(...)

Because __bool__ lives on the base Constraint, it also covers ConstraintCombination, :class:~iris.AttributeConstraint and :class:~iris.NameConstraint.

Per the issue discussion this is not considered a breaking change: any code it stops was already relying on an anti-pattern that produced wrong results, and the docs already direct users to &.

Verification

  • New unit tests tests/unit/constraints/test_Constraint__bool__.py covering bool(), the and/or/not keywords, ConstraintCombination/AttributeConstraint/NameConstraint (all raise), and a control asserting & still returns a ConstraintCombination. The raising cases fail on main and pass here.
  • Full tests/unit/constraints/ + tests/test_constraints.py (67 passed) and the PP/netCDF constraint-conversion + cube extract tests all pass, confirming no internal code relied on constraint truthiness.
  • ruff check / ruff format clean.

Combining constraints with the Python 'and'/'or'/'not' keywords silently
returned one of the operands and discarded the other, because Constraint
had no __bool__ and so was always truthy. Add a __bool__ that raises an
informative TypeError directing users to the '&' operator, mirroring the
way numpy rejects the truth-testing of multi-element arrays.

As agreed on the issue, this is not a breaking change: any code it stops
was already relying on an anti-pattern that produced wrong results.

Fixes SciTools#4337.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Applying logical OR to a constraint "fails" silently

1 participant