Skip to content

species/zmat: import vectors as a module to break import cycle#879

Merged
alongd merged 2 commits intomainfrom
zmat-vectors-cyclic-import
Apr 26, 2026
Merged

species/zmat: import vectors as a module to break import cycle#879
alongd merged 2 commits intomainfrom
zmat-vectors-cyclic-import

Conversation

@calvinp0
Copy link
Copy Markdown
Member

@calvinp0 calvinp0 commented Apr 25, 2026

Summary

  • arc.species.zmatarc.species.vectorsarc.species.converterarc.species.zmat was a real module-level import cycle, latent since 2023. It only stayed harmless because arc/species/__init__.py
    happened to load converter before anything reaching vectors. CodeQL flagged both ends: zmat.py:39 (cycle origin) and seven converter.py:33-39 "may not be defined" errors on the from-name imports of zmat
    symbols.
  • Commit 1 (f07d1f21): switches zmat.py to module-style from arc.species import vectors and prefixes the 17 call sites. This was a necessary but insufficient step — module imports tolerate partial
    initialization mid-cycle, but the structural cycle still existed.
  • Commit 2 (0f5d3ad9): actually breaks the cycle by removing vectors.py's module-level import of converter. The only call site (get_vector) was using converter.xyz_to_x_y_z(xyz) to build three
    full-length axis tuples just to read two atoms' coordinates — replaced with two direct xyz['coords'][i] lookups. Net: 6 lines → 3 lines, O(N) → O(1), and the heavy check_xyz_dict validation overhead is gone
    (caller passes a well-formed dict).
  • After this PR there is no module-level path from vectors back to zmat, so all 8 CodeQL alerts clear.

The cycle arc.species.vectors -> arc.species.converter -> arc.species.zmat
-> arc.species.vectors has existed since 2023 (when calculate_param and
get_vector_length were moved into arc.species.vectors). It only stays
latent because arc/species/__init__.py loads converter before anything
reaches vectors, and because vectors.py uses a module-style import for
converter.

Mirror that pattern in zmat.py: import vectors as a module rather than
pulling specific names out via from-import. Module imports tolerate
partial initialization during a cycle; from-name imports do not. This
clears the CodeQL "Module-level cyclic import" warnings on zmat.py and
removes a footgun for whoever next reorders the package init.
Copilot AI review requested due to automatic review settings April 25, 2026 14:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Resolves a latent module-level import cycle in arc.species by switching zmat.py from name-imports out of vectors to importing the vectors module and qualifying call sites, making imports resilient to partial initialization during cyclical imports.

Changes:

  • Replace from arc.species.vectors import ... with from arc.species import vectors in zmat.py.
  • Prefix all calculate_param / get_vector_length call sites with vectors. to match the new import style.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread arc/species/zmat.py Fixed
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 60.44%. Comparing base (d32a2e6) to head (0f5d3ad).
⚠️ Report is 3 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #879      +/-   ##
==========================================
- Coverage   60.47%   60.44%   -0.03%     
==========================================
  Files         102      102              
  Lines       31099    31096       -3     
  Branches     8103     8103              
==========================================
- Hits        18806    18796      -10     
- Misses       9951     9957       +6     
- Partials     2342     2343       +1     
Flag Coverage Δ
functionaltests 60.44% <ø> (-0.03%) ⬇️
unittests 60.44% <ø> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 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.

The previous commit changed zmat.py to a module-style import of
vectors but the structural cycle (zmat -> vectors -> converter -> zmat)
remained, so CodeQL kept flagging both edges.

vectors.py only used converter in get_vector, where it called
xyz_to_x_y_z(xyz) (O(N) per-axis split + check_xyz_dict validation)
just to read two atoms' coordinates. Inline the two coord lookups
directly and drop the module-level converter import. The cycle is
now fully broken at the import-graph level.
Copy link
Copy Markdown
Member

@alongd alongd left a comment

Choose a reason for hiding this comment

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

Excellent, thanks for getting to the bottom of this!

Comment thread arc/species/vectors.py
dy = y[anchor] - y[pivot]
dz = z[anchor] - z[pivot]
return [dx, dy, dz]
px, py, pz = xyz['coords'][pivot]
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.

And it's even more efficient now :)

@alongd alongd merged commit f30f9cc into main Apr 26, 2026
7 of 8 checks passed
@alongd alongd deleted the zmat-vectors-cyclic-import branch April 26, 2026 10:00
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.

4 participants