Skip to content

Fix ubuntu-24.04-arm wheel test failure (phreeqc engine) - #455

Merged
rkingsbury merged 3 commits into
mainfrom
rk/fix-phreeqc-arm-ci
Aug 4, 2026
Merged

Fix ubuntu-24.04-arm wheel test failure (phreeqc engine)#455
rkingsbury merged 3 commits into
mainfrom
rk/fix-phreeqc-arm-ci

Conversation

@rkingsbury

Copy link
Copy Markdown
Member

Summary

The v1.6.0 release wheel job failed only on ubuntu-24.04-arm while ubuntu-latest (x86_64) and macos-latest (arm64) built and tested cleanly.

Root cause: test_repeated_equilibrate (newly added since v1.5.0) lives in tests/test_engine_phreeqc2026.py — the file run inside the built wheel by cibuildwheel — but was the only test there using engine="phreeqc", the legacy engine backed by the third-party phreeqpython package. phreeqpython ships native libraries for x86_64 Linux (viphreeqc.so), Windows (.dll), and macOS universal (.dylib, incl. arm64), but no aarch64-Linux library. So on ubuntu-24.04-arm, PhreeqPython() raises OSError, and PhreeqcEOS was left in a broken state that crashed with a confusing ValueError: There is a problem with your input ... 'str' object has no attribute '_phreeqc'.

This is why the other platforms pass: x86_64 Linux loads its .so, and macOS arm loads the universal .dylib.

Changes

1. test(phreeqc)test_repeated_equilibrate now uses engine="phreeqc2026" (the in-tree compiled engine), matching every other test in this file. This is the fix that turns the arm wheel job green; the "phreeqc" was a copy-paste slip.

2. fix(PhreeqcEOS) — make the engine degrade cleanly when the phreeqpython backend can't load, honoring the documented contract ("pyEQL will work, but equilibrate() will have no effect"):

  • set self.pp = None in the OSError handler so state is well-defined (it had been left pointing at the wrong-typed in-tree wrapper inherited from super().__init__());
  • equilibrate() no-ops when self.pp is None;
  • _setup_ppsol() raises a clear ValueError when self.pp is None — already caught by the activity-coefficient fallback, so property reads keep working;
  • generalize the previously Apple-only diagnostic message to also mention aarch64 Linux.

The PhreeqcEOS OSError bug is pre-existing (identical at v1.5.0); the new test was simply the first to exercise it in the wheel build. Fix #2 does not change CI outcome — it just prevents the crash if anyone hits that path at runtime.

Verification

  • tests/test_engine_phreeqc2026.py → 20 passed (the wheel-tested file)
  • tests/test_engine_phreeqc.py → 19 passed (real phreeqpython path, unaffected)
  • Simulated the arm case (engine.pp = None): equilibrate() no-ops, get_activity_coefficient degrades to 1, _setup_ppsol raises the legible ValueError

The new guards are inert for engine="phreeqc2026" (its self.pp is never None), so that engine is untouched.

🤖 Generated with Claude Code

rkingsbury and others added 2 commits August 4, 2026 09:26
…brate

test_repeated_equilibrate lived in test_engine_phreeqc2026.py (the file run
inside the built wheel by cibuildwheel) but was the only test there using
engine="phreeqc", the legacy engine backed by the third-party phreeqpython
package. phreeqpython ships no aarch64-Linux native library, so on
ubuntu-24.04-arm PhreeqPython() raises OSError and the engine ends up in a
broken state, crashing the test. Every other test in this file exercises the
new in-tree engine via engine="phreeqc2026"; the "phreeqc" here was a slip.

Switch to engine="phreeqc2026" so the test runs against the engine this file
is meant to cover and passes on all wheel-build platforms.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…able

On platforms with no compatible phreeqpython binary (e.g. aarch64 Linux, where
phreeqpython ships no arm64 shared library, or Apple Silicon), PhreeqPython()
raises OSError. PhreeqcEOS.__init__ caught it and logged a warning but left
self.pp pointing at the in-tree Phreeqc wrapper set by super().__init__() -- the
wrong type for this phreeqpython-backed engine. A later equilibrate() then fed a
raw dict into that wrapper's add_solution(), which iterated the dict's string
keys and raised "AttributeError: 'str' object has no attribute '_phreeqc'",
re-raised as a confusing ValueError about "a problem with your input".

Make the failure mode match the documented contract ("pyEQL will work, but
equilibrate() will have no effect"):
  - set self.pp = None in the OSError handler so the state is well-defined
  - equilibrate() no-ops when self.pp is None
  - _setup_ppsol() raises a clear ValueError when self.pp is None; the
    activity-coefficient path already catches ValueError and falls back to unit
    activity coefficients, so property reads keep working
Also generalize the (previously Apple-only) diagnostic message, since the same
gap affects aarch64 Linux.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rkingsbury

Copy link
Copy Markdown
Member Author

@vineetbansal this is the problem I emailed you about - it turned out to be a result of a copy/paste error in a newly added test. All good now!

@rkingsbury
rkingsbury merged commit 033dbf5 into main Aug 4, 2026
2 checks passed
@codecov

codecov Bot commented Aug 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.54%. Comparing base (1e877c3) to head (dd1be5f).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
src/pyEQL/engines.py 0.00% 4 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #455      +/-   ##
==========================================
- Coverage   87.81%   87.54%   -0.28%     
==========================================
  Files          14       14              
  Lines        1945     1951       +6     
  Branches      338      340       +2     
==========================================
  Hits         1708     1708              
- Misses        188      192       +4     
- Partials       49       51       +2     

☔ 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

None yet

Development

Successfully merging this pull request may close these issues.

Add support for %by weight units to get_amount()

1 participant