Skip to content

Fix algo option type conversion being silently skipped with postponed annotations#691

Open
janosg wants to merge 1 commit into
mainfrom
fix-algo-option-type-conversion
Open

Fix algo option type conversion being silently skipped with postponed annotations#691
janosg wants to merge 1 commit into
mainfrom
fix-algo-option-type-conversion

Conversation

@janosg

@janosg janosg commented Jul 5, 2026

Copy link
Copy Markdown
Member

Problem

Algorithm.__post_init__ converts and validates algo option values by looking up each dataclass field's type in TYPE_CONVERTERS, which is keyed by type objects (PositiveInt, int, ...). In modules with from __future__ import annotations — which the how-to-document-optimizers guide requires so that autodoc renders type aliases readably — field.type is the annotation string ("PositiveInt"), so the lookup never matched and coercion/validation was silently skipped.

This already affected every optimizer module that uses the import on main (scipy, gfo, nevergrad, pyswarms, pygad, bayesian, pygmo, tranquilo, iminuit) and surfaced as a test failure in #690 when ipopt.py gained the import: test_ipopt_algo_options passes 5.5 for an integer-typed Ipopt option and relies on coercion to int.

Fix

  • TYPE_CONVERTERS_BY_NAME in type_conversion.py: a string-keyed companion table with the same converters.
  • Algorithm.__post_init__ branches on whether field.type is a string and uses the matching table, so coercion works identically with and without the future import.

Tests

  • test_algorithm_future_annotations.py (new): a dummy algorithm defined under postponed annotations, mirroring the existing type conversion tests in test_algorithm.py, plus a guard test asserting the field types really are annotation strings.
  • test_algorithm.py: a mirror guard asserting the existing dummy's field types are type objects (so the two modules keep covering both code paths), a float→int coercion test, and test_int_options_are_coerced_for_all_algorithms, which passes floats for all int-typed options of every algorithm in ALL_ALGORITHMS and asserts they come back as ints.

Without the fix, 97 of the new tests fail (the postponed-annotations module and the registry-wide test for ~90 algorithms); with it, everything passes.

#690 is rebased on top of this branch.

🤖 Generated with Claude Code

… annotations.

With `from __future__ import annotations`, dataclass field types are
annotation strings rather than type objects, so the TYPE_CONVERTERS lookup
in Algorithm.__post_init__ never matched and option coercion/validation was
silently skipped for all optimizer modules using the import.

Adds a string-keyed TYPE_CONVERTERS_BY_NAME lookup so coercion works
identically with and without the import, plus regression tests: a dummy
algorithm defined under postponed annotations mirroring the existing type
conversion tests, and a registry-wide test that passes floats for all
int-typed options of every algorithm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
src/optimagic/optimization/algorithm.py 95.04% <100.00%> (+0.07%) ⬆️
src/optimagic/type_conversion.py 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

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

1 participant