Skip to content

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

Merged
trexfeathers merged 2 commits into
SciTools:mainfrom
gaoflow:fix/constraint-bool-typeerror
Jun 16, 2026
Merged

Raise TypeError when a Constraint is used in a boolean context (#4337)#7121
trexfeathers merged 2 commits into
SciTools:mainfrom
gaoflow:fix/constraint-bool-typeerror

Conversation

@gaoflow

@gaoflow gaoflow commented Jun 1, 2026

Copy link
Copy Markdown
Contributor

🚀 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.

@trexfeathers trexfeathers left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @gaoflow!

@trexfeathers trexfeathers enabled auto-merge (squash) June 16, 2026 17:32
@trexfeathers trexfeathers merged commit aea2ece into SciTools:main Jun 16, 2026
21 checks passed
@codecov

codecov Bot commented Jun 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 90.15%. Comparing base (832a0d0) to head (76a40c0).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7121   +/-   ##
=======================================
  Coverage   90.15%   90.15%           
=======================================
  Files          91       91           
  Lines       24981    24983    +2     
  Branches     4685     4685           
=======================================
+ Hits        22522    22524    +2     
  Misses       1682     1682           
  Partials      777      777           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

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

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Applying logical OR to a constraint "fails" silently

2 participants