Skip to content

refactor!: retire EnForce_ANI's type-switched second parameter - #136

Merged
isayev merged 1 commit into
mainfrom
phase21/retire-legacy-enforce-api
Aug 3, 2026
Merged

refactor!: retire EnForce_ANI's type-switched second parameter#136
isayev merged 1 commit into
mainfrom
phase21/retire-legacy-enforce-api

Conversation

@isayev

@isayev isayev commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

One of the three M53 entries left unresolved by #135 — and the clearest of them, since the deprecation window had demonstrably expired.

What was there

name_or_batchsize: str | int | None = None

One parameter, two meanings, switched on type: a model name (the pre-adapter API) or a batch size. Passing a string warned it would be "removed in Auto3D v2.0". The package reached 3.0.0 with it still in place — two majors past its own removal notice — along with _legacy_forward, 55 lines dispatching on self.name.

Verified before acting

Per the practice this backlog now requires, the three production callers were checked rather than assumed:

caller form
batch_opt/batchopt.py:319 positional int
ASE/thermo.py:590 adapter only
SPE.py:148 adapter only

None uses the string form, and the positional-int call keeps working unchanged against the new two-parameter signature — so no call site needed editing.

The trap removing it would have left

EnForce_ANI(adapter, "AIMNET") — the exact shape a migrating caller would write — would have silently assigned a string to batchsize_atoms and failed much later inside batching, as a comparison error naming neither the parameter nor the removal.

It now raises TypeError on the spot, saying what the parameter is for and where to get an adapter. That guard is the difference between a breaking change and a confusing one.

Signature

EnForce_ANI(model_adapter, batchsize_atoms=16384)

Migration: build an adapter with Auto3D.model_factory.create_model and pass it first.

Tests

Two tests asserted _use_legacy_forward is False while actually testing batch-size handling — they keep their real assertions and lose the one about a deleted attribute. The test of the removed feature is replaced by one asserting the old call shape is rejected; mutation-verified, dropping the guard fails it.

I also caught myself here: my first edit blind-replaced the deleted assertion, appending == 1024 to tests that already asserted == 512 and == 256. The suite failed immediately and it was fixed before commit, but a blind string replace across tests was the wrong tool.

1273 passed, 9 skipped; ruff clean.

Still open from M53

ASE/thermo's unread model_name parameter, and exceptions.py's "4 classes never raised" — the latter needs finding by content, since line 41 is OptimizationError, raised three times.

BREAKING CHANGE: EnForce_ANI's signature is now
(model_adapter, batchsize_atoms=16384). The second parameter used to be
`name_or_batchsize: str | int | None`, switching between a model name and a batch
size; passing a string warned it would be "removed in Auto3D v2.0". The package
reached 3.0.0 with it still there -- two majors past its own removal notice -- and
no caller in src/ ever passed one. `_legacy_forward`, 55 lines dispatching on
`self.name`, is deleted with it.

Verified before acting, per the practice this backlog now requires: the three
production callers are batchopt.py:319 (positional int), ASE/thermo.py:590 and
SPE.py:148 (adapter only). None uses the string form, and the positional int call
keeps working unchanged against the two-parameter signature.

Removing the union on its own would have left a trap for exactly the callers the
removal affects: `EnForce_ANI(adapter, "AIMNET")` would assign a string to
batchsize_atoms and surface much later inside batching as a comparison error
naming neither the parameter nor the removal. It now raises TypeError on the spot,
saying what the parameter is for and where to get an adapter.

Two tests asserted `_use_legacy_forward is False` while actually testing batch-size
handling; they keep their real assertions and lose the one about a deleted
attribute. The test of the removed feature is replaced by one asserting the old
call shape is now rejected. Mutation-verified: dropping the guard fails it.

Verified: 1273 passed, 9 skipped; ruff clean.
@isayev
isayev merged commit c73173d into main Aug 3, 2026
8 checks passed
@isayev
isayev deleted the phase21/retire-legacy-enforce-api branch August 3, 2026 22:10
isayev added a commit that referenced this pull request Aug 3, 2026
No code change. Both remaining dead-code claims were checked against source and
neither holds.

ASE/thermo's `model_name` parameter is read: Calculator stores it and passes it to
to_model_species at thermo.py:536. It was genuinely unused when the audit was
written; the C3/C4 species-conversion work made it live.

exceptions.py's "4 classes never raised" is wrong, and the shape of the claim is
why. Only ModelError is never raised directly, and that is deliberate:
ModelLoadError and NumericalError subclass it, and cli/errors.py maps ModelError to
exit code 5 precisely so both subclasses inherit that code. Deleting it would break
the exit-code scheme this release documents. "Never raised" is not "unused" for a
base class, and an audit that greps for `raise X` cannot tell the two apart.

Final tally for M53: of 13 entries, 4 were real. Three had already been done, six
were wrong on re-check, and the four real ones were removed in #135 and #136.
Nothing further to delete.

The lesson worth keeping is that a dead-code finding decays faster than any other
kind. The same work that fixes defects revives symbols the audit recorded as dead
-- mol2atoms, STANDARD_PRESSURE, FailedMolecule, print_failures and now model_name
were all dead when written up and are all live now. A mechanical sweep of this list
would have deleted five live symbols, two of which vib_hessian depends on.

Both corrections are also written inline in the audit manifest, so neither can be
re-derived from its finding ID.
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.

1 participant