From 24b04abf65582b546946c3510f8476e340960369 Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Thu, 23 Apr 2026 09:57:49 +0200 Subject: [PATCH 01/15] chore: add ty configuration to pyproject toml file --- pixi.lock | 59 +++++++++++++- pyproject.toml | 205 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 247 insertions(+), 17 deletions(-) diff --git a/pixi.lock b/pixi.lock index 4f9960725..3d43f2ddd 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9641,6 +9641,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.24-h4e94fc0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -9942,6 +9943,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.24-ha73ee7d_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -10227,6 +10229,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.24-hc21aad4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -19402,8 +19405,8 @@ packages: timestamp: 1733688053334 - pypi: ./ name: optimagic - version: 0.5.4.dev5+g8654d6292.d20260312 - sha256: 72e7ed28837a3da869c13448a83bee607a85ab9f1e2d9dc5b5e7604d8ce2bf94 + version: 0.1.dev474+ga11d368b0.d20260423 + sha256: 81c3db4593f38cb4620ecc64202e001cb4ee43846632e53ebe0c09122816954e requires_dist: - annotated-types>=0.4 - cloudpickle>=2.2 @@ -25728,6 +25731,58 @@ packages: - pkg:pypi/tranquilo?source=hash-mapping size: 73744 timestamp: 1772093378917 +- conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.24-h4e94fc0_0.conda + noarch: python + sha256: 3de56413211bcb07c8df0a66eaaed996f0d14a6dbd9cee0b42a0b275c0e464e0 + md5: db52fd98c2edb81ba0f81a1b0aecc8cc + depends: + - python + - libgcc >=14 + - __glibc >=2.17,<3.0.a0 + - _python_abi3_support 1.* + - cpython >=3.10 + constrains: + - __glibc >=2.17 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ty?source=hash-mapping + size: 9207623 + timestamp: 1773948239539 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.24-ha73ee7d_0.conda + noarch: python + sha256: c6924afb9d541bed15f159389c08ab5ae492bb69f4e660ae608add0498834703 + md5: 39c996ee15024882153fd31b502b6572 + depends: + - python + - __osx >=11.0 + - _python_abi3_support 1.* + - cpython >=3.10 + constrains: + - __osx >=11.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ty?source=hash-mapping + size: 8304066 + timestamp: 1773948334333 +- conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.24-hc21aad4_0.conda + noarch: python + sha256: 754cd686b04cebdb019d64481f4e3affdbf2fad05e34410ecf6d266c5463e2d5 + md5: b8a33290eda47d529ed05976ec5b0128 + depends: + - python + - vc >=14.3,<15 + - vc14_runtime >=14.44.35208 + - ucrt >=10.0.20348.0 + - _python_abi3_support 1.* + - cpython >=3.10 + license: MIT + license_family: MIT + purls: + - pkg:pypi/ty?source=hash-mapping + size: 9232166 + timestamp: 1773948344148 - pypi: https://files.pythonhosted.org/packages/c8/15/4564f173d031f64bf56964d192b6b705e679fc23c02704b84ccbcb809396/types_cffi-1.17.0.20260307-py3-none-any.whl name: types-cffi version: 1.17.0.20260307 diff --git a/pyproject.toml b/pyproject.toml index af1ac9a23..59dccb126 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,6 +123,9 @@ select = [ "ISC", # pydocstyle "D", + # For enforcing disallow_incomplete_defs and disallow_untyped_defs from mypy + "ANN001", + "ANN201", ] extend-ignore = [ @@ -164,9 +167,115 @@ extend-ignore = [ [tool.ruff.lint.per-file-ignores] "docs/source/conf.py" = ["E501", "ERA001", "DTZ005"] -"src/optimagic/parameters/kernel_transformations.py" = ["ARG001", "N806"] +"src/optimagic/parameters/kernel_transformations.py" = ["ARG001", "N806", "ANN001", "ANN201"] "docs/source/*" = ["B018"] "src/optimagic/algorithms.py" = ["E501"] +"docs/*" = ["ANN001", "ANN201"] +"tests/*" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/benchmark_reports.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/cartis_roberts.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/get_benchmark_problems.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/more_wild.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/noise_distributions.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/process_benchmark_results.py" = ["ANN001", "ANN201"] +"src/optimagic/benchmarking/run_benchmark.py" = ["ANN001", "ANN201"] + +"src/optimagic/differentiation/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/differentiation/derivatives.py" = ["ANN001", "ANN201"] +"src/optimagic/differentiation/finite_differences.py" = ["ANN001", "ANN201"] +"src/optimagic/differentiation/generate_steps.py" = ["ANN001", "ANN201"] +"src/optimagic/differentiation/richardson_extrapolation.py" = ["ANN001", "ANN201"] + +"src/optimagic/examples/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/examples/numdiff_functions.py" = ["ANN001", "ANN201"] + +"src/optimagic/optimization/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/algo_options.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/convergence_report.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/optimization_logging.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/optimize_result.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/optimize.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/multistart.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/scipy_aliases.py" = ["ANN001", "ANN201"] +"src/optimagic/optimization/create_optimization_problem.py" = ["ANN001", "ANN201"] + +"src/optimagic/optimizers/_pounders/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/pounders_auxiliary.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/pounders_history.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/_conjugate_gradient.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/_steihaug_toint.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/_trsbox.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/bntr.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/gqtpar.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/_pounders/linear_subsolvers.py" = ["ANN001", "ANN201"] + +"src/optimagic/optimizers/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/tranquilo.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/pygmo_optimizers.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/scipy_optimizers.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/nag_optimizers.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/neldermead.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/nlopt_optimizers.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/ipopt.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/fides.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/pounders.py" = ["ANN001", "ANN201"] +"src/optimagic/optimizers/tao_optimizers.py" = ["ANN001", "ANN201"] + + +"src/optimagic/parameters/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/block_trees.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/check_constraints.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/consolidate_constraints.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/constraint_tools.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/conversion.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/nonlinear_constraints.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/process_constraints.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/process_selectors.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/space_conversion.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/tree_conversion.py" = ["ANN001", "ANN201"] +"src/optimagic/parameters/tree_registry.py" = ["ANN001", "ANN201"] + + +"src/optimagic/shared/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/shared/check_option_dicts.py" = ["ANN001", "ANN201"] +"src/optimagic/shared/compat.py" = ["ANN001", "ANN201"] +"src/optimagic/shared/process_user_function.py" = ["ANN001", "ANN201"] + +"src/optimagic/visualization/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/convergence_plot.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/backend.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/deviation_plot.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/history_plots.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/plotting_utilities.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/profile_plot.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/slice_plot.py" = ["ANN001", "ANN201"] + +"src/optimagic/__init__.py" = ["ANN001", "ANN201"] +"src/optimagic/decorators.py" = ["ANN001", "ANN201"] +"src/optimagic/exceptions.py" = ["ANN001", "ANN201"] +"src/optimagic/utilities.py" = ["ANN001", "ANN201"] +"src/optimagic/deprecations.py" = ["ANN001", "ANN201"] + +"src/estimagic/__init__.py" = ["ANN001", "ANN201"] +"src/estimagic/examples/__init__.py" = ["ANN001", "ANN201"] +"src/estimagic/examples/logit.py" = ["ANN001", "ANN201"] +"src/estimagic/estimate_ml.py" = ["ANN001", "ANN201"] +"src/estimagic/estimate_msm.py" = ["ANN001", "ANN201"] +"src/estimagic/estimation_summaries.py" = ["ANN001", "ANN201"] +"src/estimagic/msm_weighting.py" = ["ANN001", "ANN201"] +"src/estimagic/bootstrap_ci.py" = ["ANN001", "ANN201"] +"src/estimagic/bootstrap_helpers.py" = ["ANN001", "ANN201"] +"src/estimagic/bootstrap_outcomes.py" = ["ANN001", "ANN201"] +"src/estimagic/bootstrap_samples.py" = ["ANN001", "ANN201"] +"src/estimagic/bootstrap.py" = ["ANN001", "ANN201"] +"src/estimagic/ml_covs.py" = ["ANN001", "ANN201"] +"src/estimagic/msm_covs.py" = ["ANN001", "ANN201"] +"src/estimagic/shared_covs.py" = ["ANN001", "ANN201"] +"src/estimagic/msm_sensitivity.py" = ["ANN001", "ANN201"] +"src/estimagic/estimation_table.py" = ["ANN001", "ANN201"] +"src/estimagic/lollipop_plot.py" = ["ANN001", "ANN201"] +"src/optimagic/visualization/slice_plot_3d.py" = ["ANN001", "ANN201"] [tool.ruff.lint.pydocstyle] convention = "google" @@ -220,14 +329,17 @@ none_representation = "null" # Mypy configuration # ====================================================================================== [tool.mypy] -files = ["src", "tests", ".tools"] -check_untyped_defs = true -disallow_any_generics = true -disallow_untyped_defs = true -disallow_incomplete_defs = true -no_implicit_optional = true -warn_redundant_casts = true -warn_unused_ignores = true +files = ["src", "tests", ".tools"] # ty src include +check_untyped_defs = true # Is default behaviour on ty +disallow_any_generics = true # No ty equivalent +disallow_untyped_defs = true # Enforced via ANN20 +disallow_incomplete_defs = true # Enforced via Ruff ANN001 +no_implicit_optional = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#invalid-parameter-default +warn_redundant_casts = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#redundant-cast +warn_unused_ignores = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#unused-ignore-comment, https://docs.astral.sh/ty/reference/rules/#unused-type-ignore-comment + +[tool.ty] +src.include = ["src", ".tools", "tests"] [[tool.mypy.overrides]] module = [ @@ -337,15 +449,15 @@ module = [ "estimagic.lollipop_plot", ] -check_untyped_defs = false -disallow_any_generics = false -disallow_untyped_defs = false - +check_untyped_defs = false # handled by ruff added a skip for it +disallow_any_generics = false # Is false by default because no way to handle this in ty. +disallow_untyped_defs = false # handled by ruff added a skip for it [[tool.mypy.overrides]] module = "tests.*" -disallow_untyped_defs = false -ignore_errors = true +disallow_untyped_defs = false # handled by ruff added a skip for it +ignore_errors = true # This flag doesnt exist rules must be explicitly added + [[tool.mypy.overrides]] module = [ @@ -407,6 +519,66 @@ module = [ ] ignore_missing_imports = true +[tool.ty.analysis] +replace-imports-with-any = [ + "pybaum", + "scipy", + "scipy.linalg", + "scipy.linalg.lapack", + "scipy.linalg.lapack.dpotrf", + "scipy.stats", + "scipy.optimize", + "scipy.ndimage", + "scipy.optimize._trustregion_exact", + "plotly", + "plotly.graph_objects", + "plotly.express", + "plotly.subplots", + "matplotlib", + "matplotlib.pyplot", + "cyipopt", + "nlopt", + "bokeh", + "bokeh.layouts", + "bokeh.models", + "bokeh.plotting", + "bokeh.application", + "bokeh.application.handlers", + "bokeh.application.handlers.function", + "bokeh.server", + "bokeh.server.server", + "bokeh.command", + "bokeh.command.util", + "fides", + "petsc4py", + "petsc4py.PETSc", + "tranquilo", + "tranquilo.tranquilo", + "tranquilo.options", + "tranquilo.process_arguments", + "dfols", + "pybobyqa", + "pygmo", + "jax", + "joblib", + "cloudpickle", + "numba", + "pathos", + "pathos.pools", + "optimagic._version", + "annotated_types", + "pdbp", + "iminuit", + "nevergrad", + "nevergrad.optimization.base", + "pygad", + "pyswarms", + "pyswarms.backend.topology", + "yaml", + "gradient_free_optimizers", + "gradient_free_optimizers.optimizers.base_optimizer", + ] + # ====================================================================================== # Pixi configuration @@ -473,6 +645,7 @@ tests-with-cov = { cmd = "pytest --cov-report=xml --cov=src", description = "Run # --- Feature: type-checking (mypy + type stubs) -------------------------------------- [tool.pixi.feature.type-checking.dependencies] mypy = "==1.19.1" +ty = ">=0.0.24,<0.0.25" [tool.pixi.feature.type-checking.pypi-dependencies] pandas-stubs = "*" @@ -483,6 +656,8 @@ sqlalchemy-stubs = "*" [tool.pixi.feature.type-checking.tasks] mypy = { cmd = "mypy", description = "Run mypy type checker" } +ty = { cmd = "ty check", description = "Run ty type checker" } +ty-concise = { cmd = "ty check --output-format concise", description = "Run ty type checker with concise output" } # --- Feature: linux (Linux-only deps) ------------------------------------------------ [tool.pixi.feature.linux] From 0385e94edaacff8c50893657576d0b16ecc07e50 Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Thu, 23 Apr 2026 13:54:19 +0200 Subject: [PATCH 02/15] chore: remove mypy and type: ignore statements --- .github/workflows/main.yml | 8 +- .tools/create_algo_selection_code.py | 20 +- pixi.lock | 234 ++++++++---------- pyproject.toml | 213 +--------------- src/optimagic/algorithms.py | 6 +- src/optimagic/differentiation/derivatives.py | 2 +- .../differentiation/numdiff_options.py | 4 +- src/optimagic/logging/read_log.py | 2 +- src/optimagic/logging/sqlalchemy.py | 10 +- src/optimagic/mark.py | 20 +- src/optimagic/optimization/error_penalty.py | 2 +- src/optimagic/optimization/history.py | 6 +- .../internal_optimization_problem.py | 2 +- .../optimization/multistart_options.py | 2 +- src/optimagic/parameters/bounds.py | 6 +- src/optimagic/visualization/backends.py | 4 +- src/optimagic/visualization/history_plots.py | 20 +- src/optimagic/visualization/slice_plot.py | 2 +- src/optimagic/visualization/slice_plot_3d.py | 34 ++- tests/optimagic/logging/test_sqlalchemy.py | 2 +- 20 files changed, 181 insertions(+), 418 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 027bc75f5..7dabaef6e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -119,8 +119,8 @@ jobs: run: >- pixi run -e tests-linux-py314 python -m doctest -v docs/source/how_to/how_to_constraints.md - run-mypy: - name: Run mypy + run-ty: + name: Run ty runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -131,6 +131,6 @@ jobs: cache-write: ${{ github.event_name == 'push' && github.ref_name == 'main' }} frozen: true environments: type-checking - - name: Run mypy + - name: Run ty shell: bash -el {0} - run: pixi run -e type-checking mypy + run: pixi run -e type-checking ty --output-format github diff --git a/.tools/create_algo_selection_code.py b/.tools/create_algo_selection_code.py index 17e79989f..5c74f8eb4 100644 --- a/.tools/create_algo_selection_code.py +++ b/.tools/create_algo_selection_code.py @@ -119,7 +119,7 @@ def _get_algorithms_in_module(module: ModuleType) -> dict[str, Type[Algorithm]]: # Functions to filter algorithms by selectors # ====================================================================================== def _is_gradient_based(algo: Type[Algorithm]) -> bool: - return algo.algo_info.needs_jac # type: ignore + return algo.algo_info.needs_jac def _is_gradient_free(algo: Type[Algorithm]) -> bool: @@ -127,7 +127,7 @@ def _is_gradient_free(algo: Type[Algorithm]) -> bool: def _is_global(algo: Type[Algorithm]) -> bool: - return algo.algo_info.is_global # type: ignore + return algo.algo_info.is_global def _is_local(algo: Type[Algorithm]) -> bool: @@ -135,31 +135,31 @@ def _is_local(algo: Type[Algorithm]) -> bool: def _is_bounded(algo: Type[Algorithm]) -> bool: - return algo.algo_info.supports_bounds # type: ignore + return algo.algo_info.supports_bounds def _is_linear_constrained(algo: Type[Algorithm]) -> bool: - return algo.algo_info.supports_linear_constraints # type: ignore + return algo.algo_info.supports_linear_constraints def _is_nonlinear_constrained(algo: Type[Algorithm]) -> bool: - return algo.algo_info.supports_nonlinear_constraints # type: ignore + return algo.algo_info.supports_nonlinear_constraints def _is_scalar(algo: Type[Algorithm]) -> bool: - return algo.algo_info.solver_type == AggregationLevel.SCALAR # type: ignore + return algo.algo_info.solver_type == AggregationLevel.SCALAR def _is_least_squares(algo: Type[Algorithm]) -> bool: - return algo.algo_info.solver_type == AggregationLevel.LEAST_SQUARES # type: ignore + return algo.algo_info.solver_type == AggregationLevel.LEAST_SQUARES def _is_likelihood(algo: Type[Algorithm]) -> bool: - return algo.algo_info.solver_type == AggregationLevel.LIKELIHOOD # type: ignore + return algo.algo_info.solver_type == AggregationLevel.LIKELIHOOD def _is_parallel(algo: Type[Algorithm]) -> bool: - return algo.algo_info.supports_parallelism # type: ignore + return algo.algo_info.supports_parallelism def _get_filters() -> dict[str, Callable[[Type[Algorithm]], bool]]: @@ -385,7 +385,7 @@ def _all(self) -> list[Type[Algorithm]]: def _available(self) -> list[Type[Algorithm]]: _all = self._all() return [ - a for a in _all if a.algo_info.is_available # type: ignore + a for a in _all if a.algo_info.is_available ] @property diff --git a/pixi.lock b/pixi.lock index 3d43f2ddd..4ca141936 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9548,8 +9548,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-include-5.8.2-h5a610fb_2.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/mumps-seq-5.8.2-hc1b3267_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.19.1-py314h5bd0f2a_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.17.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda @@ -9571,7 +9569,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/pandas-2.3.3-py314ha0b5721_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pcre2-10.47-haa7fec5_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda @@ -9601,7 +9598,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.8.1-py314h0f05182_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/pytorch-2.10.0-cpu_mkl_py314_h6018c46_103.conda @@ -9691,9 +9687,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -9852,8 +9852,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mumps-include-5.8.2-h2ca763e_2.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mumps-seq-5.8.2-h49d0c1d_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.19.1-py314hbdd0d06_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.17.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda @@ -9875,7 +9873,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pandas-2.3.3-py314ha3d490a_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pexpect-4.9.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pillow-12.1.1-py314hab283cf_0.conda @@ -9904,7 +9901,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-librt-0.8.1-py314ha14b1ff_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/pytorch-2.10.0-cpu_generic_py314_he36690f_3.conda @@ -9972,9 +9968,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -10139,8 +10139,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/mpmath-1.3.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/mumps-seq-5.8.2-h607cc0b_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/munkres-1.1.4-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.19.1-py314h5a2d7ad_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/narwhals-2.17.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbclient-0.10.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nbconvert-core-7.17.0-pyhcf101f3_0.conda @@ -10160,7 +10158,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/win-64/pandas-2.3.3-py314hd8fd7ce_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/pandocfilters-1.5.0-pyhd8ed1ab_0.tar.bz2 - conda: https://conda.anaconda.org/conda-forge/noarch/parso-0.8.6-pyhcf101f3_0.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pcre2-10.47-hd2b5f0e_0.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pillow-12.1.1-py314h61b30b5_0.conda @@ -10188,7 +10185,6 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/python-fastjsonschema-2.21.2-pyhe01879c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-gil-3.14.3-h4df99d1_101.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-json-logger-2.0.7-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/python-librt-0.8.1-py314hc5dbbe4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/python_abi-3.14-8_cp314.conda - conda: https://conda.anaconda.org/conda-forge/win-64/pytorch-2.10.0-cpu_mkl_py314_hf6ce55f_103.conda @@ -10264,9 +10260,13 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl + - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -16351,6 +16351,21 @@ packages: purls: [] size: 211099 timestamp: 1762397758105 +- pypi: https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl + name: librt + version: 0.9.0 + sha256: b8bd70d5d816566a580d193326912f4a76ec2d28a97dc4cd4cc831c0af8e330e + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: librt + version: 0.9.0 + sha256: f3fd278f5e6bf7c75ccd6d12344eb686cc020712683363b66f46ac79d37c799f + requires_python: '>=3.9' +- pypi: https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl + name: librt + version: 0.9.0 + sha256: 1c587494461ebd42229d0f1739f3aa34237dd9980623ecf1be8d3bcba79f4499 + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/libscotch-7.0.11-int64_hfcc3fd4_2.conda sha256: 2c2030d8dc2a4af1bbeac2c25de74fd3269afaf72d3ba666b6bd5af6f4b534ba md5: 263641cd867b74db096f6f30752bd502 @@ -18297,75 +18312,65 @@ packages: - pkg:pypi/munkres?source=hash-mapping size: 15851 timestamp: 1749895533014 -- conda: https://conda.anaconda.org/conda-forge/linux-64/mypy-1.19.1-py314h5bd0f2a_0.conda - sha256: 4e607095b92cac2ec6dbb8de348d8e006408291c9c2805926f01e4a30e94edbb - md5: 0490f2b08d179719201fdb9514d67157 - depends: - - __glibc >=2.17,<3.0.a0 - - libgcc >=14 - - mypy_extensions >=1.0.0 - - pathspec >=0.9.0 - - psutil >=4.0 - - python >=3.14,<3.15.0a0 - - python-librt >=0.6.2 - - python_abi 3.14.* *_cp314 - - typing_extensions >=4.6.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy?source=hash-mapping - size: 18632958 - timestamp: 1765795548407 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/mypy-1.19.1-py314hbdd0d06_0.conda - sha256: c5c9a691dc00ce9a726426f971fbe21d0501ec8c6228513b945210898f26c761 - md5: 584f58048dc4af70f6c647b40a7049a6 - depends: - - __osx >=11.0 - - mypy_extensions >=1.0.0 - - pathspec >=0.9.0 - - psutil >=4.0 - - python >=3.14,<3.15.0a0 - - python >=3.14,<3.15.0a0 *_cp314 - - python-librt >=0.6.2 - - python_abi 3.14.* *_cp314 - - typing_extensions >=4.6.0 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy?source=hash-mapping - size: 11320681 - timestamp: 1765795843941 -- conda: https://conda.anaconda.org/conda-forge/win-64/mypy-1.19.1-py314h5a2d7ad_0.conda - sha256: 59c5f9046ad3ab9a449dee682392799d9589c12e470f0c6fed7f2aaa9b8e8ca2 - md5: 4ca21331a3962c4fcf658d6d47df4c0b - depends: - - mypy_extensions >=1.0.0 - - pathspec >=0.9.0 - - psutil >=4.0 - - python >=3.14,<3.15.0a0 - - python-librt >=0.6.2 - - python_abi 3.14.* *_cp314 - - typing_extensions >=4.6.0 - - ucrt >=10.0.20348.0 - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy?source=hash-mapping - size: 9114684 - timestamp: 1765795714379 -- conda: https://conda.anaconda.org/conda-forge/noarch/mypy_extensions-1.1.0-pyha770c72_0.conda - sha256: 6ed158e4e5dd8f6a10ad9e525631e35cee8557718f83de7a4e3966b1f772c4b1 - md5: e9c622e0d00fa24a6292279af3ab6d06 - depends: - - python >=3.9 - license: MIT - license_family: MIT - purls: - - pkg:pypi/mypy-extensions?source=hash-mapping - size: 11766 - timestamp: 1745776666688 +- pypi: https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl + name: mypy + version: 1.20.2 + sha256: 5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc + requires_dist: + - typing-extensions>=4.6.0 ; python_full_version < '3.15' + - typing-extensions>=4.14.0 ; python_full_version >= '3.15' + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl + name: mypy + version: 1.20.2 + sha256: e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924 + requires_dist: + - typing-extensions>=4.6.0 ; python_full_version < '3.15' + - typing-extensions>=4.14.0 ; python_full_version >= '3.15' + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl + name: mypy + version: 1.20.2 + sha256: 913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8 + requires_dist: + - typing-extensions>=4.6.0 ; python_full_version < '3.15' + - typing-extensions>=4.14.0 ; python_full_version >= '3.15' + - mypy-extensions>=1.0.0 + - pathspec>=1.0.0 + - tomli>=1.1.0 ; python_full_version < '3.11' + - librt>=0.8.0 ; platform_python_implementation != 'PyPy' + - psutil>=4.0 ; extra == 'dmypy' + - setuptools>=50 ; extra == 'mypyc' + - lxml ; extra == 'reports' + - pip ; extra == 'install-types' + - orjson ; extra == 'faster-cache' + - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' + requires_python: '>=3.10' +- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl + name: mypy-extensions + version: 1.1.0 + sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 + requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda sha256: c81d0c8c74c3da66808f8da09d8e48f2af2d173d357d45239defaf466838edba md5: da07c7b1588ad0a44118d28aeb31b6a6 @@ -19405,8 +19410,8 @@ packages: timestamp: 1733688053334 - pypi: ./ name: optimagic - version: 0.1.dev474+ga11d368b0.d20260423 - sha256: 81c3db4593f38cb4620ecc64202e001cb4ee43846632e53ebe0c09122816954e + version: 0.1.dev474+ge123e7949.d20260423 + sha256: bd0884351f9fd38a6d678bd108399fe6af0aebbe971cf0d58924a8221e2bf439 requires_dist: - annotated-types>=0.4 - cloudpickle>=2.2 @@ -20202,17 +20207,15 @@ packages: - pkg:pypi/parso?source=hash-mapping size: 82287 timestamp: 1770676243987 -- conda: https://conda.anaconda.org/conda-forge/noarch/pathspec-1.0.4-pyhd8ed1ab_0.conda - sha256: 29ea20d0faf20374fcd61c25f6d32fb8e9a2c786a7f1473a0c3ead359470fbe1 - md5: 2908273ac396d2cd210a8127f5f1c0d6 - depends: - - python >=3.10 - license: MPL-2.0 - license_family: MOZILLA - purls: - - pkg:pypi/pathspec?source=hash-mapping - size: 53739 - timestamp: 1769677743677 +- pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl + name: pathspec + version: 1.1.0 + sha256: 574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42 + requires_dist: + - hyperscan>=0.7 ; extra == 'hyperscan' + - typing-extensions>=4 ; extra == 'optional' + - google-re2>=1.1 ; extra == 're2' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda sha256: 9678f4745e6b82b36fab9657a19665081862268cb079cf9acf878ab2c4fadee9 md5: 8678577a52161cc4e1c93fcc18e8a646 @@ -22115,49 +22118,6 @@ packages: - pkg:pypi/python-json-logger?source=hash-mapping size: 13383 timestamp: 1677079727691 -- conda: https://conda.anaconda.org/conda-forge/linux-64/python-librt-0.8.1-py314h0f05182_0.conda - sha256: 53a19b531000edd487bfba24a04a341d49088a39a4abe9be858edaff05a1d065 - md5: 9a021120e52c4b44761c30d950e6a8c6 - depends: - - python - - libgcc >=14 - - __glibc >=2.17,<3.0.a0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/librt?source=hash-mapping - size: 76241 - timestamp: 1771423015190 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/python-librt-0.8.1-py314ha14b1ff_0.conda - sha256: 10667ff7dec7aa0a4c1e7cc0d0fb16c168e4128ffeba57fdd247810f1a71d247 - md5: 8c322be8d5466a35f48d5559def4c225 - depends: - - python - - python 3.14.* *_cp314 - - __osx >=11.0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/librt?source=hash-mapping - size: 72731 - timestamp: 1771423079377 -- conda: https://conda.anaconda.org/conda-forge/win-64/python-librt-0.8.1-py314hc5dbbe4_0.conda - sha256: 25d152c9354a8a95eca1f9754cfe4e3bf8f85dec6229c692d7bc8bcd1613f02f - md5: 29edadadd2768a75eff4788fd105cc46 - depends: - - python - - vc >=14.3,<15 - - vc14_runtime >=14.44.35208 - - ucrt >=10.0.20348.0 - - python_abi 3.14.* *_cp314 - license: MIT - license_family: MIT - purls: - - pkg:pypi/librt?source=hash-mapping - size: 50410 - timestamp: 1771423050838 - conda: https://conda.anaconda.org/conda-forge/noarch/python-tzdata-2025.3-pyhd8ed1ab_0.conda sha256: 467134ef39f0af2dbb57d78cb3e4821f01003488d331a8dd7119334f4f47bfbd md5: 7ead57407430ba33f681738905278d03 diff --git a/pyproject.toml b/pyproject.toml index 59dccb126..8306ae2e1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -123,8 +123,9 @@ select = [ "ISC", # pydocstyle "D", - # For enforcing disallow_incomplete_defs and disallow_untyped_defs from mypy + # Checks that function arguments have type annotations "ANN001", + # Checks that public functions and methods have return type annotations "ANN201", ] @@ -326,207 +327,24 @@ none_representation = "null" # ====================================================================================== -# Mypy configuration +# Ty configuration # ====================================================================================== -[tool.mypy] -files = ["src", "tests", ".tools"] # ty src include -check_untyped_defs = true # Is default behaviour on ty -disallow_any_generics = true # No ty equivalent -disallow_untyped_defs = true # Enforced via ANN20 -disallow_incomplete_defs = true # Enforced via Ruff ANN001 -no_implicit_optional = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#invalid-parameter-default -warn_redundant_casts = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#redundant-cast -warn_unused_ignores = true # Default behaviour on ty https://docs.astral.sh/ty/reference/rules/#unused-ignore-comment, https://docs.astral.sh/ty/reference/rules/#unused-type-ignore-comment - [tool.ty] src.include = ["src", ".tools", "tests"] -[[tool.mypy.overrides]] -module = [ - "optimagic.benchmarking", - "optimagic.benchmarking.benchmark_reports", - "optimagic.benchmarking.cartis_roberts", - "optimagic.benchmarking.get_benchmark_problems", - "optimagic.benchmarking.more_wild", - "optimagic.benchmarking.noise_distributions", - "optimagic.benchmarking.process_benchmark_results", - "optimagic.benchmarking.run_benchmark", - - "optimagic.differentiation", - "optimagic.differentiation.derivatives", - "optimagic.differentiation.finite_differences", - "optimagic.differentiation.generate_steps", - "optimagic.differentiation.richardson_extrapolation", - - "optimagic.examples", - "optimagic.examples.numdiff_functions", - - "optimagic.optimization", - "optimagic.optimization.algo_options", - "optimagic.optimization.convergence_report", - "optimagic.optimization.optimization_logging", - "optimagic.optimization.optimize_result", - "optimagic.optimization.optimize", - "optimagic.optimization.multistart", - "optimagic.optimization.scipy_aliases", - "optimagic.optimization.create_optimization_problem", - - "optimagic.optimizers._pounders", - "optimagic.optimizers._pounders.pounders_auxiliary", - "optimagic.optimizers._pounders.pounders_history", - "optimagic.optimizers._pounders._conjugate_gradient", - "optimagic.optimizers._pounders._steihaug_toint", - "optimagic.optimizers._pounders._trsbox", - "optimagic.optimizers._pounders.bntr", - "optimagic.optimizers._pounders.gqtpar", - "optimagic.optimizers._pounders.linear_subsolvers", - - "optimagic.optimizers", - "optimagic.optimizers.tranquilo", - "optimagic.optimizers.pygmo_optimizers", - "optimagic.optimizers.scipy_optimizers", - "optimagic.optimizers.nag_optimizers", - "optimagic.optimizers.neldermead", - "optimagic.optimizers.nlopt_optimizers", - "optimagic.optimizers.ipopt", - "optimagic.optimizers.fides", - "optimagic.optimizers.pounders", - "optimagic.optimizers.tao_optimizers", - - - "optimagic.parameters", - "optimagic.parameters.block_trees", - "optimagic.parameters.check_constraints", - "optimagic.parameters.consolidate_constraints", - "optimagic.parameters.constraint_tools", - "optimagic.parameters.conversion", - "optimagic.parameters.kernel_transformations", - "optimagic.parameters.nonlinear_constraints", - "optimagic.parameters.process_constraints", - "optimagic.parameters.process_selectors", - "optimagic.parameters.space_conversion", - "optimagic.parameters.tree_conversion", - "optimagic.parameters.tree_registry", - - - "optimagic.shared", - "optimagic.shared.check_option_dicts", - "optimagic.shared.compat", - "optimagic.shared.process_user_function", - - "optimagic.visualization", - "optimagic.visualization.convergence_plot", - "optimagic.visualization.backends", - "optimagic.visualization.deviation_plot", - "optimagic.visualization.history_plots", - "optimagic.visualization.plotting_utilities", - "optimagic.visualization.profile_plot", - "optimagic.visualization.slice_plot", - - "optimagic", - "optimagic.decorators", - "optimagic.exceptions", - "optimagic.utilities", - "optimagic.deprecations", - - "estimagic", - "estimagic.examples", - "estimagic.examples.logit", - "estimagic.estimate_ml", - "estimagic.estimate_msm", - "estimagic.estimation_summaries", - "estimagic.msm_weighting", - "estimagic.bootstrap_ci", - "estimagic.bootstrap_helpers", - "estimagic.bootstrap_outcomes", - "estimagic.bootstrap_samples", - "estimagic.bootstrap", - "estimagic.ml_covs", - "estimagic.msm_covs", - "estimagic.shared_covs", - "estimagic.msm_sensitivity", - "estimagic.estimation_table", - "estimagic.lollipop_plot", - -] -check_untyped_defs = false # handled by ruff added a skip for it -disallow_any_generics = false # Is false by default because no way to handle this in ty. -disallow_untyped_defs = false # handled by ruff added a skip for it - -[[tool.mypy.overrides]] -module = "tests.*" -disallow_untyped_defs = false # handled by ruff added a skip for it -ignore_errors = true # This flag doesnt exist rules must be explicitly added - - -[[tool.mypy.overrides]] -module = [ - "pybaum", - "scipy", - "scipy.linalg", - "scipy.linalg.lapack", - "scipy.stats", - "scipy.optimize", - "scipy.ndimage", - "scipy.optimize._trustregion_exact", - "plotly", - "plotly.graph_objects", - "plotly.express", - "plotly.subplots", - "matplotlib", - "matplotlib.pyplot", - "cyipopt", - "nlopt", - "bokeh", - "bokeh.layouts", - "bokeh.models", - "bokeh.plotting", - "bokeh.application", - "bokeh.application.handlers", - "bokeh.application.handlers.function", - "bokeh.server", - "bokeh.server.server", - "bokeh.command", - "bokeh.command.util", - "fides", - "petsc4py", - "petsc4py.PETSc", - "tranquilo", - "tranquilo.tranquilo", - "tranquilo.options", - "tranquilo.process_arguments", - "dfols", - "pybobyqa", - "pygmo", - "jax", - "joblib", - "cloudpickle", - "numba", - "pathos", - "pathos.pools", - "optimagic._version", - "annotated_types", - "pdbp", - "iminuit", - "nevergrad", - "nevergrad.optimization.base", - "pygad", - "pyswarms", - "pyswarms.backend.topology", - "yaml", - "gradient_free_optimizers", - "gradient_free_optimizers.optimizers.base_optimizer", - ] -ignore_missing_imports = true - [tool.ty.analysis] +allowed-unresolved-imports = [ + "petsc4py.**", + "jax.**", + "pathos.**", + "nevergrad.**", +] replace-imports-with-any = [ "pybaum", "scipy", "scipy.linalg", "scipy.linalg.lapack", - "scipy.linalg.lapack.dpotrf", - "scipy.stats", + "scipy.stats", "scipy.optimize", "scipy.ndimage", "scipy.optimize._trustregion_exact", @@ -550,8 +368,6 @@ replace-imports-with-any = [ "bokeh.command", "bokeh.command.util", "fides", - "petsc4py", - "petsc4py.PETSc", "tranquilo", "tranquilo.tranquilo", "tranquilo.options", @@ -559,18 +375,13 @@ replace-imports-with-any = [ "dfols", "pybobyqa", "pygmo", - "jax", "joblib", "cloudpickle", "numba", - "pathos", - "pathos.pools", "optimagic._version", "annotated_types", "pdbp", "iminuit", - "nevergrad", - "nevergrad.optimization.base", "pygad", "pyswarms", "pyswarms.backend.topology", @@ -642,9 +453,8 @@ tests = { cmd = "pytest", description = "Run the full test suite" } tests-fast = { cmd = "pytest -m 'not slow and not jax'", description = "Run tests excluding slow and jax tests" } tests-with-cov = { cmd = "pytest --cov-report=xml --cov=src", description = "Run tests with XML coverage report" } -# --- Feature: type-checking (mypy + type stubs) -------------------------------------- +# --- Feature: type-checking (ty + type stubs) -------------------------------------- [tool.pixi.feature.type-checking.dependencies] -mypy = "==1.19.1" ty = ">=0.0.24,<0.0.25" [tool.pixi.feature.type-checking.pypi-dependencies] @@ -655,7 +465,6 @@ types-jinja2 = "*" sqlalchemy-stubs = "*" [tool.pixi.feature.type-checking.tasks] -mypy = { cmd = "mypy", description = "Run mypy type checker" } ty = { cmd = "ty check", description = "Run ty type checker" } ty-concise = { cmd = "ty check --output-format concise", description = "Run ty type checker with concise output" } diff --git a/src/optimagic/algorithms.py b/src/optimagic/algorithms.py index ed68c9e34..139476489 100644 --- a/src/optimagic/algorithms.py +++ b/src/optimagic/algorithms.py @@ -124,11 +124,7 @@ def _all(self) -> list[Type[Algorithm]]: def _available(self) -> list[Type[Algorithm]]: _all = self._all() - return [ - a - for a in _all - if a.algo_info.is_available # type: ignore - ] + return [a for a in _all if a.algo_info.is_available] @property def All(self) -> list[Type[Algorithm]]: diff --git a/src/optimagic/differentiation/derivatives.py b/src/optimagic/differentiation/derivatives.py index e2caf5daf..e6a70f19d 100644 --- a/src/optimagic/differentiation/derivatives.py +++ b/src/optimagic/differentiation/derivatives.py @@ -585,7 +585,7 @@ def second_derivative( step_size = cast(NDArray[np.float64], step_size) # generate parameter vectors at which func has to be evaluated as numpy arrays - evaluation_points = { # type: ignore + evaluation_points = { "one_step": [], "two_step": [], "cross_step": [], diff --git a/src/optimagic/differentiation/numdiff_options.py b/src/optimagic/differentiation/numdiff_options.py index d6c2ff3c2..4ad1a5348 100644 --- a/src/optimagic/differentiation/numdiff_options.py +++ b/src/optimagic/differentiation/numdiff_options.py @@ -39,7 +39,7 @@ class NumdiffOptions: scaling_factor: float = 1 min_steps: float | None = None n_cores: int = DEFAULT_N_CORES - batch_evaluator: BatchEvaluatorLiteral | Callable = "joblib" # type: ignore + batch_evaluator: BatchEvaluatorLiteral | Callable = "joblib" def __post_init__(self) -> None: _validate_attribute_types_and_values(self) @@ -53,7 +53,7 @@ class NumdiffOptionsDict(TypedDict): scaling_factor: NotRequired[float] min_steps: NotRequired[float | None] n_cores: NotRequired[int] - batch_evaluator: NotRequired[BatchEvaluatorLiteral | Callable] # type: ignore + batch_evaluator: NotRequired[BatchEvaluatorLiteral | Callable] def pre_process_numdiff_options( diff --git a/src/optimagic/logging/read_log.py b/src/optimagic/logging/read_log.py index bd4253773..477f7e249 100644 --- a/src/optimagic/logging/read_log.py +++ b/src/optimagic/logging/read_log.py @@ -20,7 +20,7 @@ @dataclass class OptimizeLogReader: - def __new__(cls, *args, **kwargs): # type: ignore + def __new__(cls, *args, **kwargs): warnings.warn( "OptimizeLogReader is deprecated and will be removed in a future " "version. Please use optimagic.logging.SQLiteLogReader instead.", diff --git a/src/optimagic/logging/sqlalchemy.py b/src/optimagic/logging/sqlalchemy.py index a21f4fc45..4a9a12e9c 100644 --- a/src/optimagic/logging/sqlalchemy.py +++ b/src/optimagic/logging/sqlalchemy.py @@ -82,7 +82,7 @@ def _setup_pickletype( inspector: Any, table: sql.Table, column_info: dict[str, Any] ) -> None: # noqa: ARG001 if isinstance(column_info["type"], sql.BLOB): - column_info["type"] = sql.PickleType(pickler=RobustPickler) # type:ignore + column_info["type"] = sql.PickleType(pickler=RobustPickler) @dataclass @@ -230,7 +230,7 @@ def __init__( super().__init__(input_type, output_type, primary_key) columns = [ sql.Column(primary_key, sql.Integer, primary_key=True, autoincrement=True), - sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), # type:ignore + sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), ] table_config = TableConfig(table_name, columns, self.primary_key) @@ -280,7 +280,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # type:ignore + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: output_list = [] for row in results: row_dict = {self.primary_key: row[0]} @@ -370,7 +370,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # type:ignore + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: return [ self._output_type(**dict(zip(self.column_names, row, strict=False))) for row in results @@ -460,7 +460,7 @@ def __init__( columns = [ Column(self._PRIMARY_KEY, Integer, primary_key=True, autoincrement=True), Column("direction", String), - Column("params", PickleType(pickler=RobustPickler)), # type:ignore + Column("params", PickleType(pickler=RobustPickler)), ] table_config = TableConfig( diff --git a/src/optimagic/mark.py b/src/optimagic/mark.py index 94a3850ec..a05696dd5 100644 --- a/src/optimagic/mark.py +++ b/src/optimagic/mark.py @@ -15,16 +15,16 @@ def scalar(func: ScalarFuncT) -> ScalarFuncT: """Mark a function as a scalar function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.SCALAR # type: ignore + wrapper._problem_type = AggregationLevel.SCALAR except (KeyboardInterrupt, SystemExit): raise except Exception: @wraps(func) - def wrapper(*args, **kwargs): # type: ignore + def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.SCALAR # type: ignore + wrapper._problem_type = AggregationLevel.SCALAR return wrapper @@ -32,16 +32,16 @@ def least_squares(func: VectorFuncT) -> VectorFuncT: """Mark a function as a least squares function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.LEAST_SQUARES # type: ignore + wrapper._problem_type = AggregationLevel.LEAST_SQUARES except (KeyboardInterrupt, SystemExit): raise except Exception: @wraps(func) - def wrapper(*args, **kwargs): # type: ignore + def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.LEAST_SQUARES # type: ignore + wrapper._problem_type = AggregationLevel.LEAST_SQUARES return wrapper @@ -49,16 +49,16 @@ def likelihood(func: VectorFuncT) -> VectorFuncT: """Mark a function as a likelihood function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.LIKELIHOOD # type: ignore + wrapper._problem_type = AggregationLevel.LIKELIHOOD except (KeyboardInterrupt, SystemExit): raise except Exception: @wraps(func) - def wrapper(*args, **kwargs): # type: ignore + def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.LIKELIHOOD # type: ignore + wrapper._problem_type = AggregationLevel.LIKELIHOOD return wrapper @@ -137,7 +137,7 @@ def decorator(cls: AlgorithmSubclass) -> AlgorithmSubclass: disable_history=disable_history, experimental=experimental, ) - cls.__algo_info__ = algo_info # type: ignore + cls.__algo_info__ = algo_info return cls return decorator diff --git a/src/optimagic/optimization/error_penalty.py b/src/optimagic/optimization/error_penalty.py index cf260ca82..c040cf1b7 100644 --- a/src/optimagic/optimization/error_penalty.py +++ b/src/optimagic/optimization/error_penalty.py @@ -78,7 +78,7 @@ def get_error_penalty_function( dim_out = ( 1 if solver_type == AggregationLevel.SCALAR - else len(start_criterion.internal_value(solver_type)) # type: ignore + else len(start_criterion.internal_value(solver_type)) ) _penalty: Callable[ diff --git a/src/optimagic/optimization/history.py b/src/optimagic/optimization/history.py index 73bea2d93..a5a426635 100644 --- a/src/optimagic/optimization/history.py +++ b/src/optimagic/optimization/history.py @@ -136,7 +136,7 @@ def fun_data(self, cost_model: CostModel, monotone: bool = False) -> pd.DataFram fun = _apply_reduction_to_batches( data=fun, batch_ids=self.batches, - reduction_function=min_or_max, # type: ignore[arg-type] + reduction_function=min_or_max, ) # Verify that tasks are homogeneous in each batch, and select first if true. @@ -449,7 +449,7 @@ def _validate_args_are_all_none_or_lists_of_same_length( if not all_none: if all_list: - unique_list_lengths = set(map(len, args)) # type: ignore[arg-type] + unique_list_lengths = set(map(len, args)) if len(unique_list_lengths) != 1: raise ValueError("All list arguments must have the same length.") @@ -517,7 +517,7 @@ def _apply_reduction_to_batches( ) raise ValueError(msg) - batch_results.append(float(reduced)) # type: ignore[arg-type,unused-ignore] + batch_results.append(float(reduced)) return np.array(batch_results, dtype=np.float64) diff --git a/src/optimagic/optimization/internal_optimization_problem.py b/src/optimagic/optimization/internal_optimization_problem.py index 5216bbda5..c15025c33 100644 --- a/src/optimagic/optimization/internal_optimization_problem.py +++ b/src/optimagic/optimization/internal_optimization_problem.py @@ -624,7 +624,7 @@ def func(x: NDArray[np.float64]) -> SpecificFunctionValue: ) algo_fun_value, hist_fun_value = _process_fun_value( - value=fun_value, # type: ignore + value=fun_value, solver_type=self._solver_type, direction=self._direction, ) diff --git a/src/optimagic/optimization/multistart_options.py b/src/optimagic/optimization/multistart_options.py index 450c2a951..aacc2f671 100644 --- a/src/optimagic/optimization/multistart_options.py +++ b/src/optimagic/optimization/multistart_options.py @@ -370,7 +370,7 @@ def get_internal_multistart_options_from_public( n_samples = len(options.sample) else: sample = None - n_samples = options.n_samples # type: ignore + n_samples = options.n_samples batch_size = options.n_cores if options.batch_size is None else options.batch_size batch_evaluator = process_batch_evaluator(options.batch_evaluator) diff --git a/src/optimagic/parameters/bounds.py b/src/optimagic/parameters/bounds.py index 344dca4f4..33dea6cfc 100644 --- a/src/optimagic/parameters/bounds.py +++ b/src/optimagic/parameters/bounds.py @@ -152,9 +152,9 @@ def get_internal_bounds( raise InvalidBoundsError(msg) if np.isinf(lower_flat).all(): - lower_flat = None # type: ignore[assignment] + lower_flat = None if np.isinf(upper_flat).all(): - upper_flat = None # type: ignore[assignment] + upper_flat = None return lower_flat, upper_flat @@ -189,7 +189,7 @@ def _update_bounds_and_flatten( flat_nan_dict = dict(zip(params_names, flat_nan_tree, strict=False)) - invalid = {"names": [], "bounds": []} # type: ignore + invalid = {"names": [], "bounds": []} for bounds_name, bounds_leaf in zip(bounds_names, flat_bounds, strict=False): # if a bounds leaf is None we treat it as saying the the corresponding # subtree of params has no bounds. diff --git a/src/optimagic/visualization/backends.py b/src/optimagic/visualization/backends.py index 01e5bc644..0e9d23bbf 100644 --- a/src/optimagic/visualization/backends.py +++ b/src/optimagic/visualization/backends.py @@ -493,7 +493,7 @@ def _line_plot_bokeh( ) if line.show_in_legend: - _legend_items.append(LegendItem(label=line.name, renderers=[glyph])) # type: ignore[list-item] + _legend_items.append(LegendItem(label=line.name, renderers=[glyph])) if horizontal_line is not None: span = Span( @@ -606,7 +606,7 @@ def _grid_line_plot_bokeh( subplot_row.append(p) plots.append(subplot_row) - grid = gridplot( # type: ignore[call-overload] + grid = gridplot( plots, height=height // n_rows if height else None, width=width // n_cols if width else None, diff --git a/src/optimagic/visualization/history_plots.py b/src/optimagic/visualization/history_plots.py index 72dc7ab07..bf0327665 100644 --- a/src/optimagic/visualization/history_plots.py +++ b/src/optimagic/visualization/history_plots.py @@ -360,10 +360,10 @@ def _retrieve_optimization_data_from_result_object( fun=fun, params=params, # TODO: This needs to be fixed - start_time=len(fun) * [None], # type: ignore - stop_time=len(fun) * [None], # type: ignore - batches=len(fun) * [None], # type: ignore - task=len(fun) * [None], # type: ignore + start_time=len(fun) * [None], + stop_time=len(fun) * [None], + batches=len(fun) * [None], + task=len(fun) * [None], ) else: stacked = None @@ -416,8 +416,8 @@ def _retrieve_optimization_data_from_database( if stack_multistart and local_histories is not None: stacked = _get_stacked_local_histories(local_histories, direction, _history) if show_exploration: - stacked["params"] = exploration["params"][::-1] + stacked["params"] # type: ignore - stacked["criterion"] = exploration["criterion"][::-1] + stacked["criterion"] # type: ignore + stacked["params"] = exploration["params"][::-1] + stacked["params"] + stacked["criterion"] = exploration["criterion"][::-1] + stacked["criterion"] else: stacked = None @@ -428,8 +428,8 @@ def _retrieve_optimization_data_from_database( start_time=_history["time"], # TODO (@janosg): Retrieve `stop_time` from `hist` once it is available. # https://github.com/optimagic-dev/optimagic/pull/553 - stop_time=len(_history["fun"]) * [None], # type: ignore - task=len(_history["fun"]) * [None], # type: ignore + stop_time=len(_history["fun"]) * [None], + task=len(_history["fun"]) * [None], batches=list(range(len(_history["fun"]))), ) @@ -476,8 +476,8 @@ def _get_stacked_local_histories( # TODO (@janosg): Retrieve `stop_time` from `hist` once it is available for the # IterationHistory. # https://github.com/optimagic-dev/optimagic/pull/553 - stop_time=len(stacked["criterion"]) * [None], # type: ignore - task=len(stacked["criterion"]) * [None], # type: ignore + stop_time=len(stacked["criterion"]) * [None], + task=len(stacked["criterion"]) * [None], batches=list(range(len(stacked["criterion"]))), ) diff --git a/src/optimagic/visualization/slice_plot.py b/src/optimagic/visualization/slice_plot.py index 92802cf3f..72ade9397 100644 --- a/src/optimagic/visualization/slice_plot.py +++ b/src/optimagic/visualization/slice_plot.py @@ -292,7 +292,7 @@ def _get_plot_data( metadata.append(meta) plot_data = pd.DataFrame(metadata) - plot_data["Function Value"] = func_values # type: ignore[assignment] + plot_data["Function Value"] = func_values return plot_data, internal_params diff --git a/src/optimagic/visualization/slice_plot_3d.py b/src/optimagic/visualization/slice_plot_3d.py index 1b6a7fc90..9546a2249 100644 --- a/src/optimagic/visualization/slice_plot_3d.py +++ b/src/optimagic/visualization/slice_plot_3d.py @@ -25,7 +25,7 @@ from optimagic.typing import AggregationLevel -def slice_plot_3d( # type: ignore[no-untyped-def] +def slice_plot_3d( func, params, bounds=None, @@ -342,7 +342,7 @@ def slice_plot_3d( # type: ignore[no-untyped-def] fig = plot_contour( x, y, - z, # type: ignore[arg-type] + z, scatter_point, plot_kwargs, layout_kwargs, @@ -360,7 +360,7 @@ def slice_plot_3d( # type: ignore[no-untyped-def] return combine_plots(plots, make_subplot_kwargs, layout_kwargs, expand_yrange) -def generate_evaluation_points( # type: ignore[no-untyped-def] +def generate_evaluation_points( projection, selected, internal_params, params_data, converter ): """Create the list of parameter sets for function evaluation. @@ -413,9 +413,7 @@ def generate_evaluation_points( # type: ignore[no-untyped-def] return evaluation_points -def plot_data_cache( # type: ignore[no-untyped-def] - projection, selected, internal_params, func_values, n_gridpoints -): +def plot_data_cache(projection, selected, internal_params, func_values, n_gridpoints): """Caches and maps evaluated function values to their parameters. This function takes the flat array of criterion function outputs and maps @@ -471,7 +469,7 @@ def plot_data_cache( # type: ignore[no-untyped-def] return plot_data -def plot_line( # type: ignore[no-untyped-def] +def plot_line( x: list[float], y: list[float], display_name: str, @@ -525,7 +523,7 @@ def plot_line( # type: ignore[no-untyped-def] return fig -def plot_surface( # type: ignore[no-untyped-def] +def plot_surface( x: NDArray[np.float64], y: NDArray[np.float64], z, @@ -567,7 +565,7 @@ def plot_surface( # type: ignore[no-untyped-def] return fig -def plot_contour( # type: ignore[no-untyped-def] +def plot_contour( x: NDArray[np.float64], y: NDArray[np.float64], z: list[float], @@ -617,7 +615,7 @@ class ProjectionConfig(str, Enum): SURFACE = "surface" @classmethod - def validate(cls, value): # type: ignore[no-untyped-def] + def validate(cls, value): if value is None: return None if isinstance(value, str): @@ -649,14 +647,14 @@ class Projection: """ - def __init__(self, value): # type: ignore[no-untyped-def] + def __init__(self, value): self._univariate = False self.lower = None self.upper = None self._parse(value) - def _parse(self, value): # type: ignore[no-untyped-def] + def _parse(self, value): if isinstance(value, str): value = value.lower() if value == ProjectionConfig.UNIVARIATE: @@ -683,7 +681,7 @@ def is_univariate(self) -> bool: def is_dict(self) -> bool: return not self._univariate - def get_config(self): # type: ignore[no-untyped-def] + def get_config(self): if self._univariate: return ProjectionConfig.UNIVARIATE return {"lower": self.lower, "upper": self.upper} @@ -696,7 +694,7 @@ def compute_yaxis_range(y: list[float], expand_yrange: float) -> list[float]: return [y_min - expand_yrange * y_range, y_max + expand_yrange * y_range] -def combine_plots( # type: ignore[no-untyped-def] +def combine_plots( plots: dict[tuple[int, int], go.Figure], make_subplot_kwargs, layout_kwargs, @@ -808,7 +806,7 @@ def combine_plots( # type: ignore[no-untyped-def] return fig -def _get_subplot_spec( # type: ignore[no-untyped-def] +def _get_subplot_spec( i: int, j: int, projection, n_selected: int ) -> dict[str | None, str | None]: # Determine subplot spec type (xy, scene, contour) for a given subplot position. @@ -832,7 +830,7 @@ def _get_subplot_spec( # type: ignore[no-untyped-def] return {} -def evaluate_plot_kwargs(plot_kwargs): # type: ignore[no-untyped-def] +def evaluate_plot_kwargs(plot_kwargs): # Set default styling for plots if not provided by the user. if plot_kwargs is None: plot_kwargs = {} @@ -862,7 +860,7 @@ def evaluate_plot_kwargs(plot_kwargs): # type: ignore[no-untyped-def] return plot_kwargs_defaults -def evaluate_make_subplot_kwargs( # type: ignore[no-untyped-def] +def evaluate_make_subplot_kwargs( make_subplot_kwargs, n_selected: int, projection, @@ -916,7 +914,7 @@ def evaluate_make_subplot_kwargs( # type: ignore[no-untyped-def] # mypy: disable-error-code="dict-item" -def evaluate_layout_kwargs( # type: ignore[no-untyped-def] +def evaluate_layout_kwargs( layout_kwargs, projection, subplot_config, diff --git a/tests/optimagic/logging/test_sqlalchemy.py b/tests/optimagic/logging/test_sqlalchemy.py index 5d1ae4d2d..9c3665622 100644 --- a/tests/optimagic/logging/test_sqlalchemy.py +++ b/tests/optimagic/logging/test_sqlalchemy.py @@ -70,7 +70,7 @@ def test_update_raise(self, store): store.update(key=1, value=updated_result) with pytest.raises(AttributeError): - store.sellect_typo # type:ignore # noqa: B018 + store.sellect_typo # noqa: B018 def test_serialization(self, store): """Test the serialization and deserialization of the IterationStore.""" From c5e6012a1baa5c63269c5e4b47920a994dbd1b55 Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Thu, 23 Apr 2026 13:57:19 +0200 Subject: [PATCH 03/15] chore: add ty: ignore statements --- .tools/create_algo_selection_code.py | 4 +-- src/estimagic/__init__.py | 2 +- src/estimagic/estimate_ml.py | 2 +- src/estimagic/estimate_msm.py | 2 +- src/estimagic/estimation_table.py | 10 +++--- .../benchmarking/benchmark_reports.py | 2 +- .../benchmarking/get_benchmark_problems.py | 8 ++--- .../benchmarking/process_benchmark_results.py | 2 +- src/optimagic/config.py | 2 +- src/optimagic/logging/sqlalchemy.py | 10 +++--- src/optimagic/mark.py | 14 ++++---- src/optimagic/optimization/algorithm.py | 12 +++---- src/optimagic/optimization/error_penalty.py | 2 +- src/optimagic/optimization/history.py | 16 +++++----- .../internal_optimization_problem.py | 7 ++-- src/optimagic/optimization/multistart.py | 4 +-- .../optimization/optimization_logging.py | 2 +- src/optimagic/optimization/optimize_result.py | 2 +- src/optimagic/optimizers/_pounders/gqtpar.py | 4 +-- .../optimizers/_pounders/pounders_history.py | 8 ++--- src/optimagic/optimizers/iminuit_migrad.py | 2 +- src/optimagic/optimizers/neldermead.py | 2 +- .../parameters/consolidate_constraints.py | 2 +- src/optimagic/parameters/constraint_tools.py | 2 +- src/optimagic/parameters/process_selectors.py | 4 +-- src/optimagic/visualization/backends.py | 2 +- src/optimagic/visualization/history_plots.py | 20 ++++++------ src/optimagic/visualization/slice_plot.py | 2 +- src/optimagic/visualization/slice_plot_3d.py | 2 +- tests/estimagic/test_estimation_table.py | 8 ++--- tests/estimagic/test_msm_sensitivity.py | 2 +- tests/estimagic/test_shared.py | 4 +-- .../differentiation/test_derivatives.py | 6 ++-- .../differentiation/test_numdiff_options.py | 10 +++--- tests/optimagic/logging/test_base.py | 14 ++++---- .../optimagic/optimization/test_algorithm.py | 14 ++++---- .../optimization/test_convergence_report.py | 4 +-- .../optimization/test_error_penalty.py | 4 +-- .../optimization/test_function_formats_ls.py | 4 +-- tests/optimagic/optimization/test_history.py | 14 ++++---- .../optimization/test_history_collection.py | 8 ++--- .../test_internal_optimization_problem.py | 4 +-- .../optimization/test_jax_derivatives.py | 2 +- .../optimagic/optimization/test_multistart.py | 6 ++-- .../optimization/test_multistart_options.py | 20 ++++++------ tests/optimagic/optimization/test_optimize.py | 4 +-- .../optimization/test_params_versions.py | 2 +- .../optimization/test_scipy_aliases.py | 4 +-- .../test_with_advanced_constraints.py | 2 +- .../optimization/test_with_constraints.py | 10 +++--- .../optimization/test_with_multistart.py | 24 +++++++------- .../test_with_nonlinear_constraints.py | 2 +- .../_pounders/test_pounders_history.py | 10 +++--- .../optimizers/test_bayesian_optimizer.py | 2 +- tests/optimagic/optimizers/test_bhhh.py | 2 +- .../optimizers/test_gfo_optimizers.py | 2 +- .../optimizers/test_iminuit_migrad.py | 4 +-- .../optimizers/test_pyswarms_optimizers.py | 4 +-- tests/optimagic/parameters/test_bounds.py | 8 ++--- .../parameters/test_process_selectors.py | 4 +-- .../parameters/test_scale_conversion.py | 4 +-- tests/optimagic/parameters/test_scaling.py | 12 +++---- .../parameters/test_space_conversion.py | 2 +- tests/optimagic/test_batch_evaluators.py | 6 ++-- tests/optimagic/test_deprecations.py | 24 +++++++------- tests/optimagic/test_timing.py | 2 +- .../optimagic/visualization/test_backends.py | 2 +- .../visualization/test_convergence_plot.py | 2 +- .../visualization/test_history_plots.py | 32 +++++++++---------- 69 files changed, 226 insertions(+), 221 deletions(-) diff --git a/.tools/create_algo_selection_code.py b/.tools/create_algo_selection_code.py index 5c74f8eb4..0fb917a4d 100644 --- a/.tools/create_algo_selection_code.py +++ b/.tools/create_algo_selection_code.py @@ -109,7 +109,7 @@ def _get_algorithms_in_module(module: ModuleType) -> dict[str, Type[Algorithm]]: } algos = {} for candidate in candidate_dict.values(): - name = candidate.algo_info.name + name = candidate.algo_info.name # ty:ignore[unresolved-attribute] if issubclass(candidate, Algorithm) and candidate is not Algorithm: algos[name] = candidate return algos @@ -223,7 +223,7 @@ def _generate_category_combinations(categories: list[str]) -> list[tuple[str, .. result: list[tuple[str, ...]] = [] for r in range(len(categories) + 1): result.extend(map(tuple, map(sorted, combinations(categories, r)))) - return sorted(result, key=len, reverse=True) + return sorted(result, key=len, reverse=True) # ty:ignore[invalid-return-type] def _apply_filters( diff --git a/src/estimagic/__init__.py b/src/estimagic/__init__.py index 44a640486..677ccf86c 100644 --- a/src/estimagic/__init__.py +++ b/src/estimagic/__init__.py @@ -68,7 +68,7 @@ def __init__(self, path): " 0.6.0.", FutureWarning, ) - super().__init__(path) + super().__init__(path) # ty:ignore[too-many-positional-arguments] @dataclass diff --git a/src/estimagic/estimate_ml.py b/src/estimagic/estimate_ml.py index a4f4882ef..3b6f69f6e 100644 --- a/src/estimagic/estimate_ml.py +++ b/src/estimagic/estimate_ml.py @@ -170,7 +170,7 @@ def estimate_ml( if hessian_numdiff_options is None: hessian_numdiff_options = numdiff_options - deprecations.throw_dict_constraints_future_warning_if_required(constraints) + deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] # ================================================================================== # Check and process inputs diff --git a/src/estimagic/estimate_msm.py b/src/estimagic/estimate_msm.py index bf17d8f73..8059a29f9 100644 --- a/src/estimagic/estimate_msm.py +++ b/src/estimagic/estimate_msm.py @@ -177,7 +177,7 @@ def estimate_msm( if jacobian_numdiff_options is not None: jacobian_numdiff_options = numdiff_options - deprecations.throw_dict_constraints_future_warning_if_required(constraints) + deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] # ================================================================================== # Check and process inputs diff --git a/src/estimagic/estimation_table.py b/src/estimagic/estimation_table.py index 731d925ac..983e8ebf0 100644 --- a/src/estimagic/estimation_table.py +++ b/src/estimagic/estimation_table.py @@ -9,7 +9,7 @@ from optimagic.shared.compat import pd_df_map -suppress_performance_warnings = np.testing.suppress_warnings() +suppress_performance_warnings = np.testing.suppress_warnings() # ty:ignore[deprecated] suppress_performance_warnings.filter(category=pd.errors.PerformanceWarning) @@ -227,7 +227,7 @@ def estimation_table( if return_type.suffix not in (".html", ".tex"): return out else: - return_type.write_text(out) + return_type.write_text(out) # ty:ignore[invalid-argument-type] @suppress_performance_warnings @@ -952,7 +952,7 @@ def _customize_col_groups(default_col_groups, custom_col_groups): else: raise TypeError( f"""Invalid type for custom_col_groups. Can be either list - or dictionary, or NoneType. Not: {type(col_groups)}.""" + or dictionary, or NoneType. Not: {type(col_groups)}.""" # ty:ignore[unresolved-reference] ) else: col_groups = default_col_groups @@ -989,7 +989,7 @@ def _customize_col_names(default_col_names, custom_col_names): else: raise TypeError( f"""Invalid type for custom_col_names. - Can be either list or dictionary, or NoneType. Not: {col_names}.""" + Can be either list or dictionary, or NoneType. Not: {col_names}.""" # ty:ignore[unresolved-reference] ) return col_names @@ -1180,7 +1180,7 @@ def _create_statistics_sr( stat_ind = np.concatenate( [stat_sr.index.values.reshape(len(stat_sr), 1), stat_ind], axis=1 ).T - stat_sr.index = pd.MultiIndex.from_arrays(stat_ind) + stat_sr.index = pd.MultiIndex.from_arrays(stat_ind) # ty:ignore[invalid-argument-type] return stat_sr.astype("str").replace("nan", "") diff --git a/src/optimagic/benchmarking/benchmark_reports.py b/src/optimagic/benchmarking/benchmark_reports.py index 2698aecc5..003761ba9 100644 --- a/src/optimagic/benchmarking/benchmark_reports.py +++ b/src/optimagic/benchmarking/benchmark_reports.py @@ -180,7 +180,7 @@ def traceback_report(problems, results, return_type="dataframe"): tracebacks[algorithm_name] = tracebacks.setdefault(algorithm_name, {}) tracebacks[algorithm_name][problem_name] = result["solution"] - report = pd.DataFrame.from_dict(tracebacks, orient="index").stack().to_frame() + report = pd.DataFrame.from_dict(tracebacks, orient="index").stack().to_frame() # ty:ignore[call-non-callable] report.index.set_names(["algorithm", "problem"], inplace=True) report.columns = ["traceback"] report["dimensionality"] = 0 diff --git a/src/optimagic/benchmarking/get_benchmark_problems.py b/src/optimagic/benchmarking/get_benchmark_problems.py index 340599e43..211261e45 100644 --- a/src/optimagic/benchmarking/get_benchmark_problems.py +++ b/src/optimagic/benchmarking/get_benchmark_problems.py @@ -197,7 +197,7 @@ def _get_raw_problems(name): problem = v.copy() raw_func = problem["fun"] - problem["fun"] = wraps(raw_func)(partial(_step_func, raw_func=raw_func)) + problem["fun"] = wraps(raw_func)(partial(_step_func, raw_func=raw_func)) # ty:ignore[invalid-argument-type, invalid-assignment] raw_problems[f"{k}_with_steps"] = problem for k, v in CARTIS_ROBERTS_PROBLEMS.items(): @@ -345,16 +345,16 @@ def _process_noise_options(options, is_multiplicative): ) std = processed["std"] - if std < 0: + if std < 0: # ty:ignore[unsupported-operator] raise ValueError(f"std must be non-negative. Not: {std}") corr = processed["correlation"] - if corr < 0: + if corr < 0: # ty:ignore[unsupported-operator] raise ValueError(f"corr must be non-negative. Not: {corr}") if is_multiplicative: clipping_value = processed["clipping_value"] - if clipping_value < 0: + if clipping_value < 0: # ty:ignore[unsupported-operator] raise ValueError( f"clipping_value must be non-negative. Not: {clipping_value}" ) diff --git a/src/optimagic/benchmarking/process_benchmark_results.py b/src/optimagic/benchmarking/process_benchmark_results.py index df443f7b0..e7d493400 100644 --- a/src/optimagic/benchmarking/process_benchmark_results.py +++ b/src/optimagic/benchmarking/process_benchmark_results.py @@ -67,7 +67,7 @@ def process_benchmark_results( histories = pd.concat(histories, ignore_index=True) infos = pd.DataFrame(infos).set_index(["problem", "algorithm"]).unstack() - infos.columns = [tup[1] for tup in infos.columns] + infos.columns = [tup[1] for tup in infos.columns] # ty:ignore[invalid-assignment] return histories, infos diff --git a/src/optimagic/config.py b/src/optimagic/config.py index 859ef3803..079236265 100644 --- a/src/optimagic/config.py +++ b/src/optimagic/config.py @@ -59,7 +59,7 @@ def _is_installed(module_name: str) -> bool: # so if nevergrad is installed, bayes_opt will not work and vice-versa. IS_BAYESOPT_INSTALLED_AND_VERSION_NEWER_THAN_2 = ( _is_installed("bayes_opt") - and importlib.metadata.version("bayesian_optimization") > "2.0.0" + and importlib.metadata.version("bayesian_optimization") > "2.0.0" # ty:ignore[possibly-missing-submodule] ) IS_GRADIENT_FREE_OPTIMIZERS_INSTALLED = _is_installed("gradient_free_optimizers") IS_PYGAD_INSTALLED = _is_installed("pygad") diff --git a/src/optimagic/logging/sqlalchemy.py b/src/optimagic/logging/sqlalchemy.py index 4a9a12e9c..a71e182a1 100644 --- a/src/optimagic/logging/sqlalchemy.py +++ b/src/optimagic/logging/sqlalchemy.py @@ -82,7 +82,7 @@ def _setup_pickletype( inspector: Any, table: sql.Table, column_info: dict[str, Any] ) -> None: # noqa: ARG001 if isinstance(column_info["type"], sql.BLOB): - column_info["type"] = sql.PickleType(pickler=RobustPickler) + column_info["type"] = sql.PickleType(pickler=RobustPickler) # ty:ignore[invalid-argument-type] @dataclass @@ -230,7 +230,7 @@ def __init__( super().__init__(input_type, output_type, primary_key) columns = [ sql.Column(primary_key, sql.Integer, primary_key=True, autoincrement=True), - sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), + sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), # ty:ignore[invalid-argument-type] ] table_config = TableConfig(table_name, columns, self.primary_key) @@ -280,7 +280,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # ty:ignore[unresolved-attribute] output_list = [] for row in results: row_dict = {self.primary_key: row[0]} @@ -370,7 +370,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # ty:ignore[unresolved-attribute] return [ self._output_type(**dict(zip(self.column_names, row, strict=False))) for row in results @@ -460,7 +460,7 @@ def __init__( columns = [ Column(self._PRIMARY_KEY, Integer, primary_key=True, autoincrement=True), Column("direction", String), - Column("params", PickleType(pickler=RobustPickler)), + Column("params", PickleType(pickler=RobustPickler)), # ty:ignore[invalid-argument-type] ] table_config = TableConfig( diff --git a/src/optimagic/mark.py b/src/optimagic/mark.py index a05696dd5..ba0677137 100644 --- a/src/optimagic/mark.py +++ b/src/optimagic/mark.py @@ -24,8 +24,8 @@ def scalar(func: ScalarFuncT) -> ScalarFuncT: def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.SCALAR - return wrapper + wrapper._problem_type = AggregationLevel.SCALAR # ty:ignore[unresolved-attribute] + return wrapper # ty:ignore[invalid-return-type] def least_squares(func: VectorFuncT) -> VectorFuncT: @@ -41,8 +41,8 @@ def least_squares(func: VectorFuncT) -> VectorFuncT: def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.LEAST_SQUARES - return wrapper + wrapper._problem_type = AggregationLevel.LEAST_SQUARES # ty:ignore[unresolved-attribute] + return wrapper # ty:ignore[invalid-return-type] def likelihood(func: VectorFuncT) -> VectorFuncT: @@ -58,8 +58,8 @@ def likelihood(func: VectorFuncT) -> VectorFuncT: def wrapper(*args, **kwargs): return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.LIKELIHOOD - return wrapper + wrapper._problem_type = AggregationLevel.LIKELIHOOD # ty:ignore[unresolved-attribute] + return wrapper # ty:ignore[invalid-return-type] # TODO: I get an error when adding bound=Algorithm to AlgorithmSubclass. Why? @@ -137,7 +137,7 @@ def decorator(cls: AlgorithmSubclass) -> AlgorithmSubclass: disable_history=disable_history, experimental=experimental, ) - cls.__algo_info__ = algo_info + cls.__algo_info__ = algo_info # ty:ignore[unresolved-attribute] return cls return decorator diff --git a/src/optimagic/optimization/algorithm.py b/src/optimagic/optimization/algorithm.py index 334c40daf..37619e738 100644 --- a/src/optimagic/optimization/algorithm.py +++ b/src/optimagic/optimization/algorithm.py @@ -176,7 +176,7 @@ class AlgorithmMeta(ABCMeta): def __repr__(self) -> str: if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - out = f"om.algos.{self.__algo_info__.name}" + out = f"om.algos.{self.__algo_info__.name}" # ty:ignore[unresolved-attribute] else: out = self.__class__.__name__ return out @@ -184,7 +184,7 @@ def __repr__(self) -> str: @property def name(self) -> str: if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - out = self.__algo_info__.name + out = self.__algo_info__.name # ty:ignore[unresolved-attribute] else: out = self.__class__.__name__ return out @@ -198,7 +198,7 @@ def algo_info(self) -> AlgoInfo: ) raise AttributeError(msg) - return self.__algo_info__ + return self.__algo_info__ # ty:ignore[invalid-return-type] @dataclass(frozen=True) @@ -222,7 +222,7 @@ def __post_init__(self) -> None: target_type = typing.cast(type, self.__dataclass_fields__[field].type) if target_type in TYPE_CONVERTERS: try: - value = TYPE_CONVERTERS[target_type](raw_value) + value = TYPE_CONVERTERS[target_type](raw_value) # ty:ignore[invalid-argument-type] except (KeyboardInterrupt, SystemExit): raise except Exception as e: @@ -317,7 +317,7 @@ def name(self) -> str: """The name of the algorithm.""" # cannot call algo_info here because it would be an infinite recursion if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - return self.__algo_info__.name + return self.__algo_info__.name # ty:ignore[unresolved-attribute] return self.__class__.__name__ @property @@ -330,4 +330,4 @@ def algo_info(self) -> AlgoInfo: ) raise AttributeError(msg) - return self.__algo_info__ + return self.__algo_info__ # ty:ignore[invalid-return-type] diff --git a/src/optimagic/optimization/error_penalty.py b/src/optimagic/optimization/error_penalty.py index c040cf1b7..eab3463af 100644 --- a/src/optimagic/optimization/error_penalty.py +++ b/src/optimagic/optimization/error_penalty.py @@ -78,7 +78,7 @@ def get_error_penalty_function( dim_out = ( 1 if solver_type == AggregationLevel.SCALAR - else len(start_criterion.internal_value(solver_type)) + else len(start_criterion.internal_value(solver_type)) # ty:ignore[invalid-argument-type] ) _penalty: Callable[ diff --git a/src/optimagic/optimization/history.py b/src/optimagic/optimization/history.py index a5a426635..2b29cfdc4 100644 --- a/src/optimagic/optimization/history.py +++ b/src/optimagic/optimization/history.py @@ -136,7 +136,7 @@ def fun_data(self, cost_model: CostModel, monotone: bool = False) -> pd.DataFram fun = _apply_reduction_to_batches( data=fun, batch_ids=self.batches, - reduction_function=min_or_max, + reduction_function=min_or_max, # ty:ignore[invalid-argument-type] ) # Verify that tasks are homogeneous in each batch, and select first if true. @@ -167,7 +167,7 @@ def monotone_fun(self) -> NDArray[np.float64]: # ---------------------------------------------------------------------------------- @property - def is_accepted(self) -> NDArray[np.bool_]: + def is_accepted(self) -> NDArray[np.bool_]: # ty:ignore[invalid-return-type] """Boolean indicator whether a function value is accepted. A function value is accepted if it is smaller (or equal) than the monotone @@ -449,7 +449,7 @@ def _validate_args_are_all_none_or_lists_of_same_length( if not all_none: if all_list: - unique_list_lengths = set(map(len, args)) + unique_list_lengths = set(map(len, args)) # ty:ignore[invalid-argument-type] if len(unique_list_lengths) != 1: raise ValueError("All list arguments must have the same length.") @@ -500,9 +500,9 @@ def _apply_reduction_to_batches( reduced = reduction_function(batch_data) except Exception as e: msg = ( - f"Calling function {reduction_function.__name__} on batch {batch_id} " + f"Calling function {reduction_function.__name__} on batch {batch_id} " # ty:ignore[unresolved-attribute] "of the History raised an Exception. Please verify that " - f"{reduction_function.__name__} is well-defined, takes an iterable of " + f"{reduction_function.__name__} is well-defined, takes an iterable of " # ty:ignore[unresolved-attribute] "floats as input and returns a scalar. The function must be able to " "handle NaN's." ) @@ -510,14 +510,14 @@ def _apply_reduction_to_batches( if not np.isscalar(reduced): msg = ( - f"Function {reduction_function.__name__} did not return a scalar for " - f"batch {batch_id}. Please verify that {reduction_function.__name__} " + f"Function {reduction_function.__name__} did not return a scalar for " # ty:ignore[unresolved-attribute] + f"batch {batch_id}. Please verify that {reduction_function.__name__} " # ty:ignore[unresolved-attribute] "returns a scalar when called on an iterable of floats. The function " "must be able to handle NaN's." ) raise ValueError(msg) - batch_results.append(float(reduced)) + batch_results.append(float(reduced)) # ty:ignore[invalid-argument-type] return np.array(batch_results, dtype=np.float64) diff --git a/src/optimagic/optimization/internal_optimization_problem.py b/src/optimagic/optimization/internal_optimization_problem.py index c15025c33..83ab88b11 100644 --- a/src/optimagic/optimization/internal_optimization_problem.py +++ b/src/optimagic/optimization/internal_optimization_problem.py @@ -539,7 +539,10 @@ def _pure_evaluate_jac( _, jac_value = self._error_penalty_func(x) out_jac = _process_jac_value( - value=jac_value, direction=self._direction, converter=self._converter, x=x + value=jac_value, # ty:ignore[invalid-argument-type] + direction=self._direction, + converter=self._converter, + x=x, ) _assert_finite_jac( out_jac=out_jac, jac_value=jac_value, params=params, origin="jac" @@ -624,7 +627,7 @@ def func(x: NDArray[np.float64]) -> SpecificFunctionValue: ) algo_fun_value, hist_fun_value = _process_fun_value( - value=fun_value, + value=fun_value, # ty:ignore[invalid-argument-type] solver_type=self._solver_type, direction=self._direction, ) diff --git a/src/optimagic/optimization/multistart.py b/src/optimagic/optimization/multistart.py index 6048eb779..47ec38c2a 100644 --- a/src/optimagic/optimization/multistart.py +++ b/src/optimagic/optimization/multistart.py @@ -176,7 +176,7 @@ def single_optimization(x0, step_id): } raw_res = state["best_res"] - res = replace(raw_res, multistart_info=multistart_info) + res = replace(raw_res, multistart_info=multistart_info) # ty:ignore[invalid-argument-type] return res @@ -445,7 +445,7 @@ def update_convergence_state( # array as solution_criterion. for res in valid_results: if np.isscalar(res.fun): - fun = float(res.fun) + fun = float(res.fun) # ty:ignore[invalid-argument-type] elif solver_type == AggregationLevel.LIKELIHOOD: fun = float(np.sum(res.fun)) elif solver_type == AggregationLevel.LEAST_SQUARES: diff --git a/src/optimagic/optimization/optimization_logging.py b/src/optimagic/optimization/optimization_logging.py index 59946eaae..24c2b0e8a 100644 --- a/src/optimagic/optimization/optimization_logging.py +++ b/src/optimagic/optimization/optimization_logging.py @@ -23,7 +23,7 @@ def log_scheduled_steps_and_get_ids( default_row = {"status": StepStatus.SCHEDULED.value} if logger: for row in steps: - data = StepResult(**{**default_row, **row}) + data = StepResult(**{**default_row, **row}) # ty:ignore[invalid-argument-type] logger.step_store.insert(data) last_steps = logger.step_store.select_last_rows(len(steps)) diff --git a/src/optimagic/optimization/optimize_result.py b/src/optimagic/optimization/optimize_result.py index f2895cf53..feb71bc6d 100644 --- a/src/optimagic/optimization/optimize_result.py +++ b/src/optimagic/optimization/optimize_result.py @@ -61,7 +61,7 @@ class OptimizeResult: history: History | None = None - convergence_report: Dict | None = None + convergence_report: Dict | None = None # ty:ignore[unsupported-operator] multistart_info: Optional["MultistartInfo"] = None algorithm_output: Dict[str, Any] | None = None diff --git a/src/optimagic/optimizers/_pounders/gqtpar.py b/src/optimagic/optimizers/_pounders/gqtpar.py index 7b03c9ba6..4da498674 100644 --- a/src/optimagic/optimizers/_pounders/gqtpar.py +++ b/src/optimagic/optimizers/_pounders/gqtpar.py @@ -203,8 +203,8 @@ def _get_initial_guess_for_lambdas( lambdas = DampingFactors( candidate=lambda_candidate, - lower_bound=lambda_lower_bound, - upper_bound=lambda_upper_bound, + lower_bound=lambda_lower_bound, # ty:ignore[invalid-argument-type] + upper_bound=lambda_upper_bound, # ty:ignore[invalid-argument-type] ) return lambdas diff --git a/src/optimagic/optimizers/_pounders/pounders_history.py b/src/optimagic/optimizers/_pounders/pounders_history.py index 643b23995..eb71fb4e3 100644 --- a/src/optimagic/optimizers/_pounders/pounders_history.py +++ b/src/optimagic/optimizers/_pounders/pounders_history.py @@ -117,7 +117,7 @@ def get_xs(self, index=None): np.ndarray: 1d or 2d array with parameter vectors """ - out = self.xs[: self.n_fun] + out = self.xs[: self.n_fun] # ty:ignore[not-subscriptable] out = out[index] if index is not None else out return out @@ -133,7 +133,7 @@ def get_residuals(self, index=None): np.ndarray: 1d or 2d array with residuals. """ - out = self.residuals[: self.n_fun] + out = self.residuals[: self.n_fun] # ty:ignore[not-subscriptable] out = out[index] if index is not None else out return out @@ -149,7 +149,7 @@ def get_critvals(self, index=None): np.ndarray: Float or 1d array with criterion values. """ - out = self.critvals[: self.n_fun] + out = self.critvals[: self.n_fun] # ty:ignore[not-subscriptable] out = out[index] if index is not None else out return out @@ -251,7 +251,7 @@ def get_best_critval(self): return self.get_critvals(index=self.best_index) def get_best_centered_entries(self, center_info): - return self.get_centered_entries(self, center_info, index=self.best_index) + return self.get_centered_entries(self, center_info, index=self.best_index) # ty:ignore[parameter-already-assigned] def _add_entries_to_array(arr, new, position): diff --git a/src/optimagic/optimizers/iminuit_migrad.py b/src/optimagic/optimizers/iminuit_migrad.py index 6ee25b034..c8560b68d 100644 --- a/src/optimagic/optimizers/iminuit_migrad.py +++ b/src/optimagic/optimizers/iminuit_migrad.py @@ -83,7 +83,7 @@ class IminuitMigrad(Algorithm): def _solve_internal_problem( self, problem: InternalOptimizationProblem, params: NDArray[np.float64] - ) -> InternalOptimizeResult: + ) -> InternalOptimizeResult: # ty:ignore[invalid-method-override] if not IS_IMINUIT_INSTALLED: raise NotInstalledError( # pragma: no cover "To use the 'iminuit_migrad` optimizer you need to install iminuit. " diff --git a/src/optimagic/optimizers/neldermead.py b/src/optimagic/optimizers/neldermead.py index ab5ddce84..9d08f1297 100644 --- a/src/optimagic/optimizers/neldermead.py +++ b/src/optimagic/optimizers/neldermead.py @@ -267,7 +267,7 @@ def func_parallel(args): m, ) for i in range(p) - ), + ), # ty:ignore[invalid-argument-type] n_cores=p, ) ), diff --git a/src/optimagic/parameters/consolidate_constraints.py b/src/optimagic/parameters/consolidate_constraints.py index f942c8b56..950dbd260 100644 --- a/src/optimagic/parameters/consolidate_constraints.py +++ b/src/optimagic/parameters/consolidate_constraints.py @@ -474,7 +474,7 @@ def _plug_equality_constraints_into_linear_weights(weights, post_replacements): """ w = weights.T plugged_iloc = pd.Series(post_replacements) - plugged_iloc = plugged_iloc.where(plugged_iloc >= 0, np.arange(len(plugged_iloc))) + plugged_iloc = plugged_iloc.where(plugged_iloc >= 0, np.arange(len(plugged_iloc))) # ty:ignore[invalid-argument-type] w["plugged_iloc"] = plugged_iloc plugged_weights = w.groupby("plugged_iloc").sum() diff --git a/src/optimagic/parameters/constraint_tools.py b/src/optimagic/parameters/constraint_tools.py index 7bf2f8eeb..ad779ef7a 100644 --- a/src/optimagic/parameters/constraint_tools.py +++ b/src/optimagic/parameters/constraint_tools.py @@ -35,7 +35,7 @@ def count_free_params( upper_bounds=upper_bounds, ) - deprecations.throw_dict_constraints_future_warning_if_required(constraints) + deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] bounds = pre_process_bounds(bounds) constraints = deprecations.pre_process_constraints(constraints) diff --git a/src/optimagic/parameters/process_selectors.py b/src/optimagic/parameters/process_selectors.py index 8a9276852..76afc1e1d 100644 --- a/src/optimagic/parameters/process_selectors.py +++ b/src/optimagic/parameters/process_selectors.py @@ -72,13 +72,13 @@ def process_selectors(constraints, params, tree_converter, param_names): if np.isscalar(selected): selected = [selected] selected = np.array(selected).astype(int) - _fail_if_duplicates(selected, constr, param_names) + _fail_if_duplicates(selected, constr, param_names) # ty:ignore[invalid-argument-type] else: selected = [[sel] if np.isscalar(sel) else sel for sel in selected] _fail_if_selections_are_incompatible(selected, constr) selected = [np.array(sel).astype(int) for sel in selected] for sel in selected: - _fail_if_duplicates(sel, constr, param_names) + _fail_if_duplicates(sel, constr, param_names) # ty:ignore[invalid-argument-type] new_constr = constr.copy() if selector_case == "one selector": diff --git a/src/optimagic/visualization/backends.py b/src/optimagic/visualization/backends.py index 0e9d23bbf..f5c94741f 100644 --- a/src/optimagic/visualization/backends.py +++ b/src/optimagic/visualization/backends.py @@ -651,7 +651,7 @@ def _line_plot_altair( if template is None: template = "default" - alt.theme.enable(template) + alt.theme.enable(template) # ty:ignore[invalid-argument-type] dfs = [] for line in lines: diff --git a/src/optimagic/visualization/history_plots.py b/src/optimagic/visualization/history_plots.py index bf0327665..2b4c33e3f 100644 --- a/src/optimagic/visualization/history_plots.py +++ b/src/optimagic/visualization/history_plots.py @@ -360,10 +360,10 @@ def _retrieve_optimization_data_from_result_object( fun=fun, params=params, # TODO: This needs to be fixed - start_time=len(fun) * [None], - stop_time=len(fun) * [None], - batches=len(fun) * [None], - task=len(fun) * [None], + start_time=len(fun) * [None], # ty:ignore[invalid-argument-type] + stop_time=len(fun) * [None], # ty:ignore[invalid-argument-type] + batches=len(fun) * [None], # ty:ignore[invalid-argument-type] + task=len(fun) * [None], # ty:ignore[invalid-argument-type] ) else: stacked = None @@ -416,8 +416,8 @@ def _retrieve_optimization_data_from_database( if stack_multistart and local_histories is not None: stacked = _get_stacked_local_histories(local_histories, direction, _history) if show_exploration: - stacked["params"] = exploration["params"][::-1] + stacked["params"] - stacked["criterion"] = exploration["criterion"][::-1] + stacked["criterion"] + stacked["params"] = exploration["params"][::-1] + stacked["params"] # ty:ignore[invalid-assignment] + stacked["criterion"] = exploration["criterion"][::-1] + stacked["criterion"] # ty:ignore[invalid-assignment] else: stacked = None @@ -428,8 +428,8 @@ def _retrieve_optimization_data_from_database( start_time=_history["time"], # TODO (@janosg): Retrieve `stop_time` from `hist` once it is available. # https://github.com/optimagic-dev/optimagic/pull/553 - stop_time=len(_history["fun"]) * [None], - task=len(_history["fun"]) * [None], + stop_time=len(_history["fun"]) * [None], # ty:ignore[invalid-argument-type] + task=len(_history["fun"]) * [None], # ty:ignore[invalid-argument-type] batches=list(range(len(_history["fun"]))), ) @@ -476,8 +476,8 @@ def _get_stacked_local_histories( # TODO (@janosg): Retrieve `stop_time` from `hist` once it is available for the # IterationHistory. # https://github.com/optimagic-dev/optimagic/pull/553 - stop_time=len(stacked["criterion"]) * [None], - task=len(stacked["criterion"]) * [None], + stop_time=len(stacked["criterion"]) * [None], # ty:ignore[invalid-argument-type] + task=len(stacked["criterion"]) * [None], # ty:ignore[invalid-argument-type] batches=list(range(len(stacked["criterion"]))), ) diff --git a/src/optimagic/visualization/slice_plot.py b/src/optimagic/visualization/slice_plot.py index 72ade9397..a6b0227d2 100644 --- a/src/optimagic/visualization/slice_plot.py +++ b/src/optimagic/visualization/slice_plot.py @@ -292,7 +292,7 @@ def _get_plot_data( metadata.append(meta) plot_data = pd.DataFrame(metadata) - plot_data["Function Value"] = func_values + plot_data["Function Value"] = func_values # ty:ignore[invalid-assignment] return plot_data, internal_params diff --git a/src/optimagic/visualization/slice_plot_3d.py b/src/optimagic/visualization/slice_plot_3d.py index 9546a2249..24475580c 100644 --- a/src/optimagic/visualization/slice_plot_3d.py +++ b/src/optimagic/visualization/slice_plot_3d.py @@ -908,7 +908,7 @@ def evaluate_make_subplot_kwargs( "horizontal_spacing": 1 / (make_subplot_defaults["cols"] * 5), "vertical_spacing": (1 / max(make_subplot_defaults["rows"] - 1, 1)) / 5, } - ) + ) # ty:ignore[no-matching-overload] make_subplot_defaults.update(make_subplot_kwargs) return make_subplot_defaults diff --git a/tests/estimagic/test_estimation_table.py b/tests/estimagic/test_estimation_table.py index e7a935182..2c6c98bfb 100644 --- a/tests/estimagic/test_estimation_table.py +++ b/tests/estimagic/test_estimation_table.py @@ -134,7 +134,7 @@ def test_estimation_table(): _get_models_multiindex_multi_column(), ] PARAMETRIZATION = [("latex", render_latex, models) for models in MODELS] -PARAMETRIZATION += [("html", render_html, models) for models in MODELS] +PARAMETRIZATION += [("html", render_html, models) for models in MODELS] # ty:ignore[unsupported-operator] @pytest.mark.parametrize("return_type, render_func,models", PARAMETRIZATION) @@ -250,7 +250,7 @@ def test_convert_model_to_series_without_inference(): # test create stat series def test_create_statistics_sr(): df = pd.DataFrame(np.empty((10, 3)), columns=["a", "b", "c"]) - df.index = pd.MultiIndex.from_arrays(np.array([np.arange(10), np.arange(10)])) + df.index = pd.MultiIndex.from_arrays(np.array([np.arange(10), np.arange(10)])) # ty:ignore[invalid-argument-type] info = {"rsquared": 0.45, "n_obs": 400, "rsquared_adj": 0.0002} number_format = ("{0:.3g}", "{0:.5f}", "{0:.4g}") add_trailing_zeros = True @@ -273,7 +273,7 @@ def test_create_statistics_sr(): ) exp = pd.Series(["0.4500", "0.0002", "400"]) exp.index = pd.MultiIndex.from_arrays( - np.array([np.array(["R2", "R2 Adj.", "Observations"]), np.array(["", "", ""])]) + np.array([np.array(["R2", "R2 Adj.", "Observations"]), np.array(["", "", ""])]) # ty:ignore[invalid-argument-type] ) ase(exp.sort_index(), res.sort_index()) @@ -282,7 +282,7 @@ def test_create_statistics_sr(): def test_process_frame_indices_index(): df = pd.DataFrame(np.ones((3, 3)), columns=["", "", ""]) df.index = pd.MultiIndex.from_arrays( - np.array([["today", "today", "today"], ["var1", "var2", "var3"]]) + np.array([["today", "today", "today"], ["var1", "var2", "var3"]]) # ty:ignore[invalid-argument-type] ) df.index.names = ["l1", "l2"] par_name_map = {"today": "tomorrow", "var1": "1stvar"} diff --git a/tests/estimagic/test_msm_sensitivity.py b/tests/estimagic/test_msm_sensitivity.py index fd2d0c1da..35332e2de 100644 --- a/tests/estimagic/test_msm_sensitivity.py +++ b/tests/estimagic/test_msm_sensitivity.py @@ -78,7 +78,7 @@ def func_kwargs(): @pytest.fixture() def jac(params, func_kwargs): derivative_dict = first_derivative( - func=simulate_aggregated_moments, + func=simulate_aggregated_moments, # ty:ignore[invalid-argument-type] params=params, func_kwargs=func_kwargs, ) diff --git a/tests/estimagic/test_shared.py b/tests/estimagic/test_shared.py index 9a4240c74..0fc2e314e 100644 --- a/tests/estimagic/test_shared.py +++ b/tests/estimagic/test_shared.py @@ -53,7 +53,7 @@ def _from_internal(x, return_type="flat"): # noqa: ARG001 class FakeConverter(NamedTuple): has_transforming_constraints: bool = True - params_from_internal: callable = _from_internal + params_from_internal: callable = _from_internal # ty:ignore[invalid-type-form] class FakeInternalParams(NamedTuple): @@ -211,7 +211,7 @@ def test_get_derivative_case(): def test_to_numpy_invalid(): with pytest.raises(TypeError): - _to_numpy(15) + _to_numpy(15) # ty:ignore[missing-argument] def test_calculate_estimation_summary(): diff --git a/tests/optimagic/differentiation/test_derivatives.py b/tests/optimagic/differentiation/test_derivatives.py index 670c1c0ab..20805095d 100644 --- a/tests/optimagic/differentiation/test_derivatives.py +++ b/tests/optimagic/differentiation/test_derivatives.py @@ -240,7 +240,7 @@ def test_convert_evaluation_data_to_frame(): arr = np.arange(4).reshape(2, 2) arr2 = arr.reshape(2, 1, 2) steps = Steps(pos=arr, neg=-arr) - evals = Evals(pos=arr2, neg=-arr2) + evals = Evals(pos=arr2, neg=-arr2) # ty:ignore[invalid-argument-type] expected = [ [1, 0, 0, 0, 0, 0], [1, 0, 1, 0, 1, 1], @@ -393,8 +393,8 @@ def test_numdiff_result_getitem(): ) assert res["derivative"] == res.derivative assert res["func_value"] == res.func_value - assert_frame_equal(res["_func_evals"], res._func_evals) - assert_frame_equal(res["_derivative_candidates"], res._derivative_candidates) + assert_frame_equal(res["_func_evals"], res._func_evals) # ty:ignore[invalid-argument-type] + assert_frame_equal(res["_derivative_candidates"], res._derivative_candidates) # ty:ignore[invalid-argument-type] def test_first_and_second_derivative_have_same_type_hints(): diff --git a/tests/optimagic/differentiation/test_numdiff_options.py b/tests/optimagic/differentiation/test_numdiff_options.py index 796e27c61..ba3c46b93 100644 --- a/tests/optimagic/differentiation/test_numdiff_options.py +++ b/tests/optimagic/differentiation/test_numdiff_options.py @@ -34,22 +34,22 @@ def test_pre_process_numdiff_options_dict_case(): def test_pre_process_numdiff_options_invalid_type(): with pytest.raises(InvalidNumdiffOptionsError): - pre_process_numdiff_options(numdiff_options="invalid") + pre_process_numdiff_options(numdiff_options="invalid") # ty:ignore[invalid-argument-type] def test_pre_process_numdiff_options_invalid_dict_key(): with pytest.raises(InvalidNumdiffOptionsError, match="Invalid numdiff options"): - pre_process_numdiff_options(numdiff_options={"wrong_key": "central"}) + pre_process_numdiff_options(numdiff_options={"wrong_key": "central"}) # ty:ignore[invalid-argument-type, invalid-key] def test_pre_process_numdiff_options_invalid_dict_value(): with pytest.raises(InvalidNumdiffOptionsError, match="Invalid numdiff `method`:"): - pre_process_numdiff_options(numdiff_options={"method": "invalid"}) + pre_process_numdiff_options(numdiff_options={"method": "invalid"}) # ty:ignore[invalid-argument-type] def test_numdiff_options_invalid_method(): with pytest.raises(InvalidNumdiffOptionsError, match="Invalid numdiff `method`:"): - NumdiffOptions(method="invalid") + NumdiffOptions(method="invalid") # ty:ignore[invalid-argument-type] def test_numdiff_options_invalid_step_size(): @@ -82,4 +82,4 @@ def test_numdiff_options_invalid_batch_evaluator(): with pytest.raises( InvalidNumdiffOptionsError, match="Invalid batch evaluator: invalid" ): - NumdiffOptions(batch_evaluator="invalid") + NumdiffOptions(batch_evaluator="invalid") # ty:ignore[invalid-argument-type] diff --git a/tests/optimagic/logging/test_base.py b/tests/optimagic/logging/test_base.py index 1d903cecd..02381195d 100644 --- a/tests/optimagic/logging/test_base.py +++ b/tests/optimagic/logging/test_base.py @@ -9,18 +9,18 @@ def test_key_value_store_raise_errors(): class NoDataClass(NonUpdatableKeyValueStore): def __init__(self): - super().__init__({1}, [], "key") + super().__init__({1}, [], "key") # ty:ignore[invalid-argument-type] def insert(self, value: InputType) -> None: pass - def _select_by_key(self, key: int) -> list[OutputType]: + def _select_by_key(self, key: int) -> list[OutputType]: # ty:ignore[empty-body] pass - def _select_all(self) -> list[OutputType]: + def _select_all(self) -> list[OutputType]: # ty:ignore[empty-body] pass - def select_last_rows(self, n_rows: int) -> list[OutputType]: + def select_last_rows(self, n_rows: int) -> list[OutputType]: # ty:ignore[empty-body] pass class WrongPrimaryKey(NonUpdatableKeyValueStore): @@ -41,13 +41,13 @@ def __init__(self): def insert(self, value: InputType) -> None: pass - def _select_by_key(self, key: int) -> list[OutputType]: + def _select_by_key(self, key: int) -> list[OutputType]: # ty:ignore[empty-body] pass - def _select_all(self) -> list[OutputType]: + def _select_all(self) -> list[OutputType]: # ty:ignore[empty-body] pass - def select_last_rows(self, n_rows: int) -> list[OutputType]: + def select_last_rows(self, n_rows: int) -> list[OutputType]: # ty:ignore[empty-body] pass with pytest.raises(ValueError): diff --git a/tests/optimagic/optimization/test_algorithm.py b/tests/optimagic/optimization/test_algorithm.py index 71bae8a79..0d7eca34e 100644 --- a/tests/optimagic/optimization/test_algorithm.py +++ b/tests/optimagic/optimization/test_algorithm.py @@ -56,7 +56,7 @@ def test_algo_info_validation(kwargs): combined_kwargs = {**valid_kwargs, **kwargs} msg = "The following arguments to AlgoInfo or `mark.minimizer` are invalid" with pytest.raises(InvalidAlgoInfoError, match=msg): - AlgoInfo(**combined_kwargs) + AlgoInfo(**combined_kwargs) # ty:ignore[invalid-argument-type] # ====================================================================================== @@ -102,7 +102,7 @@ def test_internal_optimize_result_validation(kwargs): combined_kwargs = {**valid_kwargs, **kwargs} msg = "The following arguments to InternalOptimizeResult are invalid" with pytest.raises(TypeError, match=msg): - InternalOptimizeResult(**combined_kwargs) + InternalOptimizeResult(**combined_kwargs) # ty:ignore[invalid-argument-type] # ====================================================================================== @@ -123,7 +123,7 @@ def _solve_internal_problem(self, problem, x0): fun=0.0, start_time=0.0, task=EvalTask.FUN, - ) + ) # ty:ignore[missing-argument] problem.history.add_entry(hist_entry) return InternalOptimizeResult(x=x0, fun=0.0, success=True) @@ -200,10 +200,10 @@ def test_with_option_if_applicable(): def test_algorithm_does_type_conversion(): algo = DummyAlgorithm( - initial_radius="1.0", - max_radius="10.0", - convergence_ftol_rel="1e-6", - stopping_maxiter="1000", + initial_radius="1.0", # ty:ignore[invalid-argument-type] + max_radius="10.0", # ty:ignore[invalid-argument-type] + convergence_ftol_rel="1e-6", # ty:ignore[invalid-argument-type] + stopping_maxiter="1000", # ty:ignore[invalid-argument-type] ) assert isinstance(algo.initial_radius, float) diff --git a/tests/optimagic/optimization/test_convergence_report.py b/tests/optimagic/optimization/test_convergence_report.py index ea527f2bc..a6de220b1 100644 --- a/tests/optimagic/optimization/test_convergence_report.py +++ b/tests/optimagic/optimization/test_convergence_report.py @@ -18,7 +18,7 @@ def test_get_convergence_report_minimize(): batches=[0, 1, 2, 3], ) - calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) + calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) # ty:ignore[invalid-argument-type] expected = np.array([[0.025, 0.25], [0.05, 1.0], [0.1, 1], [0.1, 2.0]]) aaae(calculated.to_numpy(), expected) @@ -35,7 +35,7 @@ def test_get_convergence_report_maximize(): batches=[0, 1, 2, 3], ) - calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) + calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) # ty:ignore[invalid-argument-type] expected = np.array([[0.025, 0.25], [0.05, 1.0], [0.1, 1], [0.1, 2.0]]) aaae(calculated.to_numpy(), expected) diff --git a/tests/optimagic/optimization/test_error_penalty.py b/tests/optimagic/optimization/test_error_penalty.py index d1100cf31..4fc4ac168 100644 --- a/tests/optimagic/optimization/test_error_penalty.py +++ b/tests/optimagic/optimization/test_error_penalty.py @@ -101,5 +101,5 @@ def test_penalty_aggregations_via_get_error_penalty(seed): contribs, _ = contribs_func(x) root_contribs, _ = root_contribs_func(x) - assert np.isclose(scalar.value, contribs.value.sum()) - assert np.isclose(scalar.value, (root_contribs.value**2).sum()) + assert np.isclose(scalar.value, contribs.value.sum()) # ty:ignore[unresolved-attribute] + assert np.isclose(scalar.value, (root_contribs.value**2).sum()) # ty:ignore[unresolved-attribute] diff --git a/tests/optimagic/optimization/test_function_formats_ls.py b/tests/optimagic/optimization/test_function_formats_ls.py index 83e087404..ac3924ccf 100644 --- a/tests/optimagic/optimization/test_function_formats_ls.py +++ b/tests/optimagic/optimization/test_function_formats_ls.py @@ -80,7 +80,7 @@ def fun_and_jac_ls(x): params=start_params, algorithm=algorithm, jac=jac, - fun_and_jac=fun_and_jac, + fun_and_jac=fun_and_jac, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -137,7 +137,7 @@ def fun_and_jac_dict_ls(params): params=start_params, algorithm=algorithm, jac=jac, - fun_and_jac=fun_and_jac, + fun_and_jac=fun_and_jac, # ty:ignore[invalid-argument-type] ) for key in start_params: diff --git a/tests/optimagic/optimization/test_history.py b/tests/optimagic/optimization/test_history.py index cb03bc253..9f00cdc6c 100644 --- a/tests/optimagic/optimization/test_history.py +++ b/tests/optimagic/optimization/test_history.py @@ -67,7 +67,7 @@ def test_history_add_entry(history_entries): ] assert history.task == [EvalTask.FUN, EvalTask.FUN, EvalTask.FUN] assert history.batches == [0, 1, 2] - aaae(history.fun, [1, 3, 2]) + aaae(history.fun, [1, 3, 2]) # ty:ignore[invalid-argument-type] aaae(history.start_time, [0.1, 0.2, 0.3]) aaae(history.stop_time, [0.2, 0.3, 0.4]) @@ -90,7 +90,7 @@ def test_history_add_batch(history_entries): ] assert history.task == [EvalTask.FUN, EvalTask.FUN, EvalTask.FUN] assert history.batches == [0, 0, 0] - aaae(history.fun, [1, 3, 2]) + aaae(history.fun, [1, 3, 2]) # ty:ignore[invalid-argument-type] aaae(history.start_time, [0.1, 0.2, 0.3]) aaae(history.stop_time, [0.2, 0.3, 0.4]) @@ -112,7 +112,7 @@ def test_history_from_data(): history = History( direction=Direction.MAXIMIZE, - **data, + **data, # ty:ignore[invalid-argument-type] ) assert history.direction == Direction.MAXIMIZE @@ -120,7 +120,7 @@ def test_history_from_data(): assert history.params == data["params"] assert history.task == data["task"] assert history.batches == data["batches"] - aaae(history.fun, data["fun"]) + aaae(history.fun, data["fun"]) # ty:ignore[invalid-argument-type] aaae(history.start_time, data["start_time"]) aaae(history.stop_time, data["stop_time"]) @@ -496,7 +496,7 @@ def test_get_total_timings_invalid_cost_model(history: History): with pytest.raises( TypeError, match="cost_model must be a CostModel or 'wall_time'." ): - history._get_total_timings(cost_model="invalid") + history._get_total_timings(cost_model="invalid") # ty:ignore[invalid-argument-type] def test_start_time_property(history: History): @@ -576,14 +576,14 @@ def test_get_flat_param_names_fast_path(): def test_calculate_monotone_sequence_maximize(): sequence = [0, 1, 0, 0, 2, 10, 0] exp = [0, 1, 1, 1, 2, 10, 10] - got = _calculate_monotone_sequence(sequence, direction=Direction.MAXIMIZE) + got = _calculate_monotone_sequence(sequence, direction=Direction.MAXIMIZE) # ty:ignore[invalid-argument-type] assert_array_equal(exp, got) def test_calculate_monotone_sequence_minimize(): sequence = [10, 11, 8, 12, 0, 5] exp = [10, 10, 8, 8, 0, 0] - got = _calculate_monotone_sequence(sequence, direction=Direction.MINIMIZE) + got = _calculate_monotone_sequence(sequence, direction=Direction.MINIMIZE) # ty:ignore[invalid-argument-type] assert_array_equal(exp, got) diff --git a/tests/optimagic/optimization/test_history_collection.py b/tests/optimagic/optimization/test_history_collection.py index 0adb6a521..e5fbfa7ad 100644 --- a/tests/optimagic/optimization/test_history_collection.py +++ b/tests/optimagic/optimization/test_history_collection.py @@ -53,7 +53,7 @@ def test_history_collection_with_parallelization(algorithm, tmp_path): log_hist = reader.read_history() # We cannot expect the order to be the same - aaae(sorted(collected_hist.fun), sorted(log_hist.fun)) + aaae(sorted(collected_hist.fun), sorted(log_hist.fun)) # ty:ignore[unresolved-attribute] @mark.minimizer( @@ -150,6 +150,6 @@ def test_history_collection_with_dummy_optimizer(n_cores, batch_size): expected_history = _get_fake_history(batch_size) - aae(got_history.batches, expected_history["batches"]) - assert got_history.fun == expected_history["criterion"][: len(got_history.fun)] - aaae(got_history.params, expected_history["params"][: len(got_history.params)]) + aae(got_history.batches, expected_history["batches"]) # ty:ignore[unresolved-attribute] + assert got_history.fun == expected_history["criterion"][: len(got_history.fun)] # ty:ignore[unresolved-attribute] + aaae(got_history.params, expected_history["params"][: len(got_history.params)]) # ty:ignore[unresolved-attribute] diff --git a/tests/optimagic/optimization/test_internal_optimization_problem.py b/tests/optimagic/optimization/test_internal_optimization_problem.py index 0a8f7bc72..598a6c006 100644 --- a/tests/optimagic/optimization/test_internal_optimization_problem.py +++ b/tests/optimagic/optimization/test_internal_optimization_problem.py @@ -69,7 +69,7 @@ def fun_and_jac(params): bounds=bounds, numdiff_options=numdiff_options, error_handling=error_handling, - error_penalty_func=None, + error_penalty_func=None, # ty:ignore[invalid-argument-type] batch_evaluator=batch_evaluator, linear_constraints=linear_constraints, nonlinear_constraints=nonlinear_constraints, @@ -476,7 +476,7 @@ def derivative_flatten(tree, x): bounds=bounds, numdiff_options=numdiff_options, error_handling=error_handling, - error_penalty_func=None, + error_penalty_func=None, # ty:ignore[invalid-argument-type] batch_evaluator=batch_evaluator, linear_constraints=linear_constraints, nonlinear_constraints=nonlinear_constraints, diff --git a/tests/optimagic/optimization/test_jax_derivatives.py b/tests/optimagic/optimization/test_jax_derivatives.py index 92433afae..6605fda5b 100644 --- a/tests/optimagic/optimization/test_jax_derivatives.py +++ b/tests/optimagic/optimization/test_jax_derivatives.py @@ -92,7 +92,7 @@ def ls_wrapper(x): fun=criterion, params=jnp.array([1.0, 2.0, 3.0]), algorithm=algorithm, - jac=deriv_dict, + jac=deriv_dict, # ty:ignore[invalid-argument-type] ) assert isinstance(res.params, jnp.ndarray) diff --git a/tests/optimagic/optimization/test_multistart.py b/tests/optimagic/optimization/test_multistart.py index a6a2f90e2..6fa1fa89f 100644 --- a/tests/optimagic/optimization/test_multistart.py +++ b/tests/optimagic/optimization/test_multistart.py @@ -75,8 +75,8 @@ def with_step_id(self, step_id): return self calculated = run_explorations( - internal_problem=Dummy(), - sample=np.arange(6).reshape(3, 2), + internal_problem=Dummy(), # ty:ignore[invalid-argument-type] + sample=np.arange(6).reshape(3, 2), # ty:ignore[invalid-argument-type] n_cores=1, step_id=0, ) @@ -130,7 +130,7 @@ def starts(): @pytest.fixture() def results(): res = InternalOptimizeResult( - x=np.arange(3) + 1e-10, + x=np.arange(3) + 1e-10, # ty:ignore[invalid-argument-type] fun=4, ) return [res] diff --git a/tests/optimagic/optimization/test_multistart_options.py b/tests/optimagic/optimization/test_multistart_options.py index a8f356fb8..cf3b3d439 100644 --- a/tests/optimagic/optimization/test_multistart_options.py +++ b/tests/optimagic/optimization/test_multistart_options.py @@ -40,17 +40,17 @@ def test_pre_process_multistart_dict_case(): def test_pre_process_multistart_invalid_type(): with pytest.raises(InvalidMultistartError, match="Invalid multistart options"): - pre_process_multistart(multistart="invalid") + pre_process_multistart(multistart="invalid") # ty:ignore[invalid-argument-type] def test_pre_process_multistart_invalid_dict_key(): with pytest.raises(InvalidMultistartError, match="Invalid multistart options"): - pre_process_multistart(multistart={"invalid": "invalid"}) + pre_process_multistart(multistart={"invalid": "invalid"}) # ty:ignore[invalid-argument-type, invalid-key] def test_pre_process_multistart_invalid_dict_value(): with pytest.raises(InvalidMultistartError, match="Invalid number of samples"): - pre_process_multistart(multistart={"n_samples": "invalid"}) + pre_process_multistart(multistart={"n_samples": "invalid"}) # ty:ignore[invalid-argument-type] @pytest.mark.parametrize("value", ["invalid", -1]) @@ -72,17 +72,17 @@ def test_multistart_options_stopping_maxopt_less_than_n_samples(): def test_multistart_options_invalid_sampling_distribution(): with pytest.raises(InvalidMultistartError, match="Invalid sampling distribution"): - MultistartOptions(sampling_distribution="invalid") + MultistartOptions(sampling_distribution="invalid") # ty:ignore[invalid-argument-type] def test_multistart_options_invalid_sampling_method(): with pytest.raises(InvalidMultistartError, match="Invalid sampling method"): - MultistartOptions(sampling_method="invalid") + MultistartOptions(sampling_method="invalid") # ty:ignore[invalid-argument-type] def test_multistart_options_invalid_mixing_weight_method(): with pytest.raises(InvalidMultistartError, match="Invalid mixing weight method"): - MultistartOptions(mixing_weight_method="invalid") + MultistartOptions(mixing_weight_method="invalid") # ty:ignore[invalid-argument-type] @pytest.mark.parametrize("value", [("a", "b"), (1, 2, 3), {"a": 1.0, "b": 3.0}]) @@ -93,7 +93,7 @@ def test_multistart_options_invalid_mixing_weight_bounds(value): def test_multistart_options_invalid_convergence_xtol_rel(): with pytest.raises(InvalidMultistartError, match="Invalid relative params"): - MultistartOptions(convergence_xtol_rel="invalid") + MultistartOptions(convergence_xtol_rel="invalid") # ty:ignore[invalid-argument-type] @pytest.mark.parametrize("value", ["invalid", -1]) @@ -121,17 +121,17 @@ def test_multistart_options_batch_size_smaller_than_n_cores(): def test_multistart_options_invalid_batch_evaluator(): with pytest.raises(InvalidMultistartError, match="Invalid batch evaluator"): - MultistartOptions(batch_evaluator="invalid") + MultistartOptions(batch_evaluator="invalid") # ty:ignore[invalid-argument-type] def test_multistart_options_invalid_seed(): with pytest.raises(InvalidMultistartError, match="Invalid seed"): - MultistartOptions(seed="invalid") + MultistartOptions(seed="invalid") # ty:ignore[invalid-argument-type] def test_multistart_options_invalid_error_handling(): with pytest.raises(InvalidMultistartError, match="Invalid error handling"): - MultistartOptions(error_handling="invalid") + MultistartOptions(error_handling="invalid") # ty:ignore[invalid-argument-type] def test_linear_weights(): diff --git a/tests/optimagic/optimization/test_optimize.py b/tests/optimagic/optimization/test_optimize.py index b666f2ac2..eb44c698f 100644 --- a/tests/optimagic/optimization/test_optimize.py +++ b/tests/optimagic/optimization/test_optimize.py @@ -43,7 +43,7 @@ def test_with_invalid_numdiff_options(): fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb", - numdiff_options={"bla": 15}, + numdiff_options={"bla": 15}, # ty:ignore[invalid-argument-type, invalid-key] ) @@ -61,7 +61,7 @@ def test_with_optional_fun_argument(): def test_fun_and_jac_list(): with pytest.raises(NotImplementedError): minimize( - fun_and_jac=[lambda x: (x @ x, 2 * x)], + fun_and_jac=[lambda x: (x @ x, 2 * x)], # ty:ignore[invalid-argument-type] params=np.arange(5), algorithm="scipy_lbfgsb", ) diff --git a/tests/optimagic/optimization/test_params_versions.py b/tests/optimagic/optimization/test_params_versions.py index f3399cb12..fcdcbbe4f 100644 --- a/tests/optimagic/optimization/test_params_versions.py +++ b/tests/optimagic/optimization/test_params_versions.py @@ -84,7 +84,7 @@ def test_tree_params_sos_ls(params, algorithm): derivatives = [sos_gradient, sos_ls_jacobian] res = minimize( fun=sos_ls, - jac=derivatives, + jac=derivatives, # ty:ignore[invalid-argument-type] params=params, algorithm=algorithm, ) diff --git a/tests/optimagic/optimization/test_scipy_aliases.py b/tests/optimagic/optimization/test_scipy_aliases.py index 113221674..909fe7e72 100644 --- a/tests/optimagic/optimization/test_scipy_aliases.py +++ b/tests/optimagic/optimization/test_scipy_aliases.py @@ -189,7 +189,7 @@ def test_jac_equal_true_works_in_minimize(): fun=lambda x: (x @ x, 2 * x), params=np.arange(3), algorithm="scipy_lbfgsb", - jac=True, + jac=True, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -199,6 +199,6 @@ def test_jac_equal_true_works_in_maximize(): fun=lambda x: (-x @ x, -2 * x), params=np.arange(3), algorithm="scipy_lbfgsb", - jac=True, + jac=True, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) diff --git a/tests/optimagic/optimization/test_with_advanced_constraints.py b/tests/optimagic/optimization/test_with_advanced_constraints.py index df3372199..b30459652 100644 --- a/tests/optimagic/optimization/test_with_advanced_constraints.py +++ b/tests/optimagic/optimization/test_with_advanced_constraints.py @@ -62,7 +62,7 @@ def test_with_covariance_constraint_bounds_distance(derivative, constr_name): params=params, algorithm="scipy_lbfgsb", jac=derivative, - constraints=CONSTR_INFO[constr_name], + constraints=CONSTR_INFO[constr_name], # ty:ignore[invalid-argument-type] ) assert res.success, "scipy_lbfgsb did not converge." diff --git a/tests/optimagic/optimization/test_with_constraints.py b/tests/optimagic/optimization/test_with_constraints.py index f943c728f..b6c483eb1 100644 --- a/tests/optimagic/optimization/test_with_constraints.py +++ b/tests/optimagic/optimization/test_with_constraints.py @@ -169,7 +169,7 @@ def logit_loglike(params, y, x): (crit_name, "scipy_lbfgsb", deriv, constr_name, ptype) ) - if "root_contributions" in FUNC_INFO[crit_name]["entries"]: + if "root_contributions" in FUNC_INFO[crit_name]["entries"]: # ty:ignore[unsupported-operator] for deriv in [FUNC_INFO[crit_name].get("ls_jacobian"), None]: test_cases.append( (crit_name, "scipy_ls_dogbox", deriv, constr_name, ptype) @@ -191,7 +191,7 @@ def test_constrained_minimization( params = np.array(START_INFO[constraint_name]) res = minimize( - fun=criterion, + fun=criterion, # ty:ignore[invalid-argument-type] params=params, algorithm=algorithm, jac=derivative, @@ -208,7 +208,7 @@ def test_constrained_minimization( f"{constraint_name}_result", FUNC_INFO[criterion_name]["default_result"] ) - aaae(calculated, expected, decimal=4) + aaae(calculated, expected, decimal=4) # ty:ignore[invalid-argument-type] @pytest.mark.filterwarnings("ignore:Specifying constraints as a dictionary is") @@ -239,7 +239,7 @@ def test_three_independent_constraints(): fun=lambda x: x @ x, params=params, algorithm="scipy_lbfgsb", - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] algo_options={"convergence.ftol_rel": 1e-12}, ) expected = np.array([0] * 4 + [4, 5] + [0] + [7.5] * 2 + [0]) @@ -325,7 +325,7 @@ def selector(x, loc=loc): fun=lambda x: x @ x, params=np.array([0.1, 0.9, 0.9, 0.1]), algorithm="scipy_lbfgsb", - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] ) aaae(res.params, [0.5] * 4) diff --git a/tests/optimagic/optimization/test_with_multistart.py b/tests/optimagic/optimization/test_with_multistart.py index bc4d083b1..d415d1d92 100644 --- a/tests/optimagic/optimization/test_with_multistart.py +++ b/tests/optimagic/optimization/test_with_multistart.py @@ -79,12 +79,12 @@ def test_multistart_optimization_with_sum_of_squares_at_defaults( assert hasattr(res, "multistart_info") ms_info = res.multistart_info - assert len(ms_info.exploration_sample) == 400 - assert isinstance(ms_info.exploration_results, list) - assert len(ms_info.exploration_results) == 400 - assert all(isinstance(entry, float) for entry in ms_info.exploration_results) - assert all(isinstance(entry, OptimizeResult) for entry in ms_info.local_optima) - assert all(isinstance(entry, pd.DataFrame) for entry in ms_info.start_parameters) + assert len(ms_info.exploration_sample) == 400 # ty:ignore[unresolved-attribute] + assert isinstance(ms_info.exploration_results, list) # ty:ignore[unresolved-attribute] + assert len(ms_info.exploration_results) == 400 # ty:ignore[unresolved-attribute] + assert all(isinstance(entry, float) for entry in ms_info.exploration_results) # ty:ignore[unresolved-attribute] + assert all(isinstance(entry, OptimizeResult) for entry in ms_info.local_optima) # ty:ignore[unresolved-attribute] + assert all(isinstance(entry, pd.DataFrame) for entry in ms_info.start_parameters) # ty:ignore[unresolved-attribute] assert np.allclose(res.fun, 0) aaae(res.params["value"], np.zeros(4)) @@ -103,7 +103,9 @@ def test_multistart_with_existing_sample(params): assert all( got.equals(expected) for expected, got in zip( - sample, res.multistart_info.exploration_sample, strict=False + sample, + res.multistart_info.exploration_sample, # ty:ignore[unresolved-attribute] + strict=False, ) ) @@ -121,7 +123,7 @@ def test_convergence_via_max_discoveries_works(params): multistart=options, ) - assert len(res.multistart_info.local_optima) == 2 + assert len(res.multistart_info.local_optima) == 2 # ty:ignore[unresolved-attribute] def test_steps_are_logged_as_skipped_if_convergence(tmp_path, params): @@ -146,7 +148,7 @@ def test_steps_are_logged_as_skipped_if_convergence(tmp_path, params): def test_all_steps_occur_in_optimization_iterations_if_no_convergence(params): options = om.MultistartOptions( - convergence_max_discoveries=np.inf, + convergence_max_discoveries=np.inf, # ty:ignore[invalid-argument-type] n_samples=10 * len(params), ) @@ -261,7 +263,7 @@ def ackley(x): } minimize( - **kwargs, + **kwargs, # ty:ignore[invalid-argument-type] algorithm="scipy_lbfgsb", multistart=om.MultistartOptions( n_samples=200, @@ -303,7 +305,7 @@ def ackley(x): } minimize( - **kwargs, + **kwargs, # ty:ignore[invalid-argument-type] algorithm="scipy_lbfgsb", multistart={ "n_samples": 200, diff --git a/tests/optimagic/optimization/test_with_nonlinear_constraints.py b/tests/optimagic/optimization/test_with_nonlinear_constraints.py index 6a5012a4b..b0f9a9412 100644 --- a/tests/optimagic/optimization/test_with_nonlinear_constraints.py +++ b/tests/optimagic/optimization/test_with_nonlinear_constraints.py @@ -161,7 +161,7 @@ def test_documentation_example(algorithm): selector=lambda x: x[:-1], value=1.0, ), - **kwargs, + **kwargs, # ty:ignore[invalid-argument-type] ) diff --git a/tests/optimagic/optimizers/_pounders/test_pounders_history.py b/tests/optimagic/optimizers/_pounders/test_pounders_history.py index f02d7df99..ffaa28230 100644 --- a/tests/optimagic/optimizers/_pounders/test_pounders_history.py +++ b/tests/optimagic/optimizers/_pounders/test_pounders_history.py @@ -24,7 +24,7 @@ def test_add_entries_not_initialized(entries, is_center): if is_center: c_info = {"x": np.zeros(3), "residuals": np.zeros(5), "radius": 1} - history.add_centered_entries(*entries, c_info) + history.add_centered_entries(*entries, c_info) # ty:ignore[too-many-positional-arguments] else: history.add_entries(*entries) @@ -51,7 +51,7 @@ def test_add_entries_initialized_with_space(entries, is_center): if is_center: c_info = {"x": np.zeros(3), "residuals": np.zeros(5), "radius": 1} - history.add_centered_entries(*entries, c_info) + history.add_centered_entries(*entries, c_info) # ty:ignore[too-many-positional-arguments] else: history.add_entries(*entries) @@ -74,9 +74,9 @@ def test_add_entries_initialized_with_space(entries, is_center): def test_add_entries_initialized_extension_needed(): history = LeastSquaresHistory() history.add_entries(np.ones((4, 3)), np.zeros((4, 5))) - history.xs = history.xs[:5] - history.residuals = history.residuals[:5] - history.critvals = history.critvals[:5] + history.xs = history.xs[:5] # ty:ignore[not-subscriptable] + history.residuals = history.residuals[:5] # ty:ignore[not-subscriptable] + history.critvals = history.critvals[:5] # ty:ignore[not-subscriptable] history.add_entries(np.arange(12).reshape(4, 3), np.arange(20).reshape(4, 5)) diff --git a/tests/optimagic/optimizers/test_bayesian_optimizer.py b/tests/optimagic/optimizers/test_bayesian_optimizer.py index 39bab2df5..1e4d69712 100644 --- a/tests/optimagic/optimizers/test_bayesian_optimizer.py +++ b/tests/optimagic/optimizers/test_bayesian_optimizer.py @@ -149,7 +149,7 @@ def test_process_acquisition_function_invalid_type(): """Test processing invalid acquisition function type.""" with pytest.raises(TypeError, match="acquisition_function must be None, a string"): _process_acquisition_function( - acquisition_function=123, + acquisition_function=123, # ty:ignore[invalid-argument-type] kappa=2.576, xi=0.01, exploration_decay=None, diff --git a/tests/optimagic/optimizers/test_bhhh.py b/tests/optimagic/optimizers/test_bhhh.py index 14bdd0f31..0c32aab16 100644 --- a/tests/optimagic/optimizers/test_bhhh.py +++ b/tests/optimagic/optimizers/test_bhhh.py @@ -154,7 +154,7 @@ def test_maximum_likelihood_external_interfaace( result_bhhh = minimize( fun=mark.likelihood(criterion_and_derivative), - jac=True, + jac=True, # ty:ignore[invalid-argument-type] params=x, algorithm="bhhh", ) diff --git a/tests/optimagic/optimizers/test_gfo_optimizers.py b/tests/optimagic/optimizers/test_gfo_optimizers.py index 4601bf0c2..9d9a31532 100644 --- a/tests/optimagic/optimizers/test_gfo_optimizers.py +++ b/tests/optimagic/optimizers/test_gfo_optimizers.py @@ -48,7 +48,7 @@ def test_get_search_space_gfo(): "x0": 5, "x1": 5, } - got = _get_search_space_gfo(bounds, n_grid_points, problem.converter) + got = _get_search_space_gfo(bounds, n_grid_points, problem.converter) # ty:ignore[invalid-argument-type] expected = { "x0": np.array([-10.0, -5.0, 0.0, 5.0, 10.0]), "x1": np.array([-10.0, -5.0, 0.0, 5.0, 10.0]), diff --git a/tests/optimagic/optimizers/test_iminuit_migrad.py b/tests/optimagic/optimizers/test_iminuit_migrad.py index 48e435ef4..848f8e6e8 100644 --- a/tests/optimagic/optimizers/test_iminuit_migrad.py +++ b/tests/optimagic/optimizers/test_iminuit_migrad.py @@ -91,5 +91,5 @@ def test_iminuit_migrad(): assert res.success aaae(res.x, np.zeros(3), decimal=6) - assert res.n_fun_evals > 0 - assert res.n_jac_evals > 0 + assert res.n_fun_evals > 0 # ty:ignore[unsupported-operator] + assert res.n_jac_evals > 0 # ty:ignore[unsupported-operator] diff --git a/tests/optimagic/optimizers/test_pyswarms_optimizers.py b/tests/optimagic/optimizers/test_pyswarms_optimizers.py index 02ce85a8c..d3c3bb22b 100644 --- a/tests/optimagic/optimizers/test_pyswarms_optimizers.py +++ b/tests/optimagic/optimizers/test_pyswarms_optimizers.py @@ -181,11 +181,11 @@ def test_resolve_topology_config_by_instance( def test_resolve_topology_config_invalid_string(): """Test topology resolution with invalid string.""" with pytest.raises(ValueError, match="Unknown topology string: 'invalid'"): - _resolve_topology_config("invalid") + _resolve_topology_config("invalid") # ty:ignore[invalid-argument-type] @pytest.mark.skipif(not IS_PYSWARMS_INSTALLED, reason="PySwarms not installed") def test_resolve_topology_config_invalid_type(): """Test topology resolution with invalid type.""" with pytest.raises(TypeError, match="Unsupported topology configuration type"): - _resolve_topology_config(123) + _resolve_topology_config(123) # ty:ignore[invalid-argument-type] diff --git a/tests/optimagic/parameters/test_bounds.py b/tests/optimagic/parameters/test_bounds.py index 3c2ae9a62..fb87da9ed 100644 --- a/tests/optimagic/parameters/test_bounds.py +++ b/tests/optimagic/parameters/test_bounds.py @@ -42,8 +42,8 @@ def test_pre_process_bounds_none_case(): def test_pre_process_bounds_sequence(): got = pre_process_bounds([(0, 1), (None, 1)]) expected = Bounds(lower=[0, -np.inf], upper=[1, 1]) - assert_array_equal(got.lower, expected.lower) - assert_array_equal(got.upper, expected.upper) + assert_array_equal(got.lower, expected.lower) # ty:ignore[unresolved-attribute] + assert_array_equal(got.upper, expected.upper) # ty:ignore[unresolved-attribute] def test_pre_process_bounds_invalid_type(): @@ -64,8 +64,8 @@ def test_get_bounds_subdataframe(pytree_params): lb, ub = get_internal_bounds(pytree_params, bounds=bounds) - assert np.all(lb[1:3] == np.ones(2)) - assert np.all(ub[2:4] == 2 * np.ones(2)) + assert np.all(lb[1:3] == np.ones(2)) # ty:ignore[not-subscriptable] + assert np.all(ub[2:4] == 2 * np.ones(2)) # ty:ignore[not-subscriptable] TEST_CASES = [ diff --git a/tests/optimagic/parameters/test_process_selectors.py b/tests/optimagic/parameters/test_process_selectors.py index 7ad9c78e6..a8a27f62c 100644 --- a/tests/optimagic/parameters/test_process_selectors.py +++ b/tests/optimagic/parameters/test_process_selectors.py @@ -41,7 +41,7 @@ def tree_params_converter(tree_params): params_unflatten=lambda x: tree_unflatten( treedef, x.tolist(), registry=registry ), - derivative_flatten=None, + derivative_flatten=None, # ty:ignore[invalid-argument-type] ) return converter @@ -68,7 +68,7 @@ def df_params_converter(df_params): converter = TreeConverter( lambda x: x["value"].to_numpy(), lambda x: df_params.assign(value=x), - None, + None, # ty:ignore[invalid-argument-type] ) return converter diff --git a/tests/optimagic/parameters/test_scale_conversion.py b/tests/optimagic/parameters/test_scale_conversion.py index 0b64da03a..58b577c2b 100644 --- a/tests/optimagic/parameters/test_scale_conversion.py +++ b/tests/optimagic/parameters/test_scale_conversion.py @@ -47,8 +47,8 @@ def test_get_scale_converter_active(method, expected): ) aaae(scaled.values, expected.values) - aaae(scaled.lower_bounds, expected.lower_bounds) - aaae(scaled.upper_bounds, expected.upper_bounds) + aaae(scaled.lower_bounds, expected.lower_bounds) # ty:ignore[invalid-argument-type] + aaae(scaled.upper_bounds, expected.upper_bounds) # ty:ignore[invalid-argument-type] aaae(converter.params_to_internal(params.values), expected.values) aaae(converter.params_from_internal(expected.values), params.values) diff --git a/tests/optimagic/parameters/test_scaling.py b/tests/optimagic/parameters/test_scaling.py index 13be92823..a91db082b 100644 --- a/tests/optimagic/parameters/test_scaling.py +++ b/tests/optimagic/parameters/test_scaling.py @@ -39,32 +39,32 @@ def test_pre_process_scaling_dict_case(): def test_pre_process_scaling_invalid_type(): with pytest.raises(InvalidScalingError, match="Invalid scaling options"): - pre_process_scaling(scaling="invalid") + pre_process_scaling(scaling="invalid") # ty:ignore[invalid-argument-type] def test_pre_process_scaling_invalid_dict_key(): with pytest.raises(InvalidScalingError, match="Invalid scaling options of type:"): - pre_process_scaling(scaling={"wrong_key": "start_values"}) + pre_process_scaling(scaling={"wrong_key": "start_values"}) # ty:ignore[invalid-argument-type, invalid-key] def test_pre_process_scaling_invalid_dict_value(): with pytest.raises(InvalidScalingError, match="Invalid clipping value:"): - pre_process_scaling(scaling={"clipping_value": "invalid"}) + pre_process_scaling(scaling={"clipping_value": "invalid"}) # ty:ignore[invalid-argument-type] def test_scaling_options_invalid_method_value(): with pytest.raises(InvalidScalingError, match="Invalid scaling method:"): - ScalingOptions(method="invalid") + ScalingOptions(method="invalid") # ty:ignore[invalid-argument-type] def test_scaling_options_invalid_clipping_value_type(): with pytest.raises(InvalidScalingError, match="Invalid clipping value:"): - ScalingOptions(clipping_value="invalid") + ScalingOptions(clipping_value="invalid") # ty:ignore[invalid-argument-type] def test_scaling_options_invalid_magnitude_value_type(): with pytest.raises(InvalidScalingError, match="Invalid scaling magnitude:"): - ScalingOptions(magnitude="invalid") + ScalingOptions(magnitude="invalid") # ty:ignore[invalid-argument-type] def test_scaling_options_invalid_magnitude_value_range(): diff --git a/tests/optimagic/parameters/test_space_conversion.py b/tests/optimagic/parameters/test_space_conversion.py index 0c4b22365..30143078e 100644 --- a/tests/optimagic/parameters/test_space_conversion.py +++ b/tests/optimagic/parameters/test_space_conversion.py @@ -214,7 +214,7 @@ def _get_test_case_normalized_covariance(): internal = InternalParams( values=np.array([0.05, 1.4133294025, 0.1, 0.2087269956, 1.7165177078, 10]), - lower_bounds=[-np.inf, 0, -np.inf, -np.inf, 0, -np.inf], + lower_bounds=[-np.inf, 0, -np.inf, -np.inf, 0, -np.inf], # ty:ignore[invalid-argument-type] upper_bounds=np.full(6, np.inf), names=None, ) diff --git a/tests/optimagic/test_batch_evaluators.py b/tests/optimagic/test_batch_evaluators.py index aa17cce6c..d71791ede 100644 --- a/tests/optimagic/test_batch_evaluators.py +++ b/tests/optimagic/test_batch_evaluators.py @@ -101,13 +101,13 @@ def test_batch_evaluator_with_dict_unpacking(batch_evaluator, n_cores): def test_get_batch_evaluator_invalid_value(): with pytest.raises(ValueError): - process_batch_evaluator("bla") + process_batch_evaluator("bla") # ty:ignore[invalid-argument-type] def test_get_batch_evaluator_invalid_type(): with pytest.raises(TypeError): - process_batch_evaluator(3) + process_batch_evaluator(3) # ty:ignore[invalid-argument-type] def test_get_batch_evaluator_with_callable(): - assert callable(process_batch_evaluator(lambda x: x)) + assert callable(process_batch_evaluator(lambda x: x)) # ty:ignore[invalid-argument-type] diff --git a/tests/optimagic/test_deprecations.py b/tests/optimagic/test_deprecations.py index b7fcbeb71..39b2d327e 100644 --- a/tests/optimagic/test_deprecations.py +++ b/tests/optimagic/test_deprecations.py @@ -562,8 +562,8 @@ def test_old_bounds_are_deprecated_in_slice_plot(): om.slice_plot( lambda x: x @ x, np.arange(3), - lower_bounds=np.full(3, -1), - upper_bounds=np.full(3, 2), + lower_bounds=np.full(3, -1), # ty:ignore[invalid-argument-type] + upper_bounds=np.full(3, 2), # ty:ignore[invalid-argument-type] ) @@ -704,7 +704,7 @@ def test_deprecated_dict_access_of_multistart_info(): ) msg = "The dictionary access for 'local_optima' is deprecated and will be removed" with pytest.warns(FutureWarning, match=msg): - _ = res.multistart_info["local_optima"] + _ = res.multistart_info["local_optima"] # ty:ignore[not-subscriptable] def test_base_steps_in_first_derivatives_is_deprecated(): @@ -805,7 +805,7 @@ def test_jac_dicts_are_deprecated_in_minimize(): lambda x: x @ x, np.arange(3), algorithm="scipy_lbfgsb", - jac={"value": lambda x: 2 * x}, + jac={"value": lambda x: 2 * x}, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -817,7 +817,7 @@ def test_jac_dicts_are_deprecated_in_maximize(): lambda x: -x @ x, np.arange(3), algorithm="scipy_lbfgsb", - jac={"value": lambda x: -2 * x}, + jac={"value": lambda x: -2 * x}, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -829,7 +829,7 @@ def test_fun_and_jac_dicts_are_deprecated_in_minimize(): lambda x: x @ x, np.arange(3), algorithm="scipy_lbfgsb", - fun_and_jac={"value": lambda x: (x @ x, 2 * x)}, + fun_and_jac={"value": lambda x: (x @ x, 2 * x)}, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -841,7 +841,7 @@ def test_fun_and_jac_dicts_are_deprecated_in_maximize(): lambda x: -x @ x, np.arange(3), algorithm="scipy_lbfgsb", - fun_and_jac={"value": lambda x: (-x @ x, -2 * x)}, + fun_and_jac={"value": lambda x: (-x @ x, -2 * x)}, # ty:ignore[invalid-argument-type] ) aaae(res.params, np.zeros(3)) @@ -1079,7 +1079,7 @@ def test_pre_process_constraints_list_of_constraints(dummy_func): {"type": "fixed", "selector": dummy_func}, {"type": "increasing", "selector": dummy_func}, ] - assert pre_process_constraints(constraints) == expected + assert pre_process_constraints(constraints) == expected # ty:ignore[invalid-argument-type] def test_pre_process_constraints_none_case(): @@ -1095,7 +1095,7 @@ def test_pre_process_constraints_mixed_case(dummy_func): {"type": "fixed", "selector": dummy_func}, {"type": "increasing", "selector": dummy_func}, ] - assert pre_process_constraints(constraints) == expected + assert pre_process_constraints(constraints) == expected # ty:ignore[invalid-argument-type] def test_pre_process_constraints_dict_case(dummy_func): @@ -1108,7 +1108,7 @@ def test_pre_process_constraints_invalid_case(): constraints = "invalid" msg = "Invalid constraint type: " with pytest.raises(InvalidConstraintError, match=msg): - pre_process_constraints(constraints) + pre_process_constraints(constraints) # ty:ignore[invalid-argument-type] def test_pre_process_constraints_invalid_mixed_case(): @@ -1119,13 +1119,13 @@ def test_pre_process_constraints_invalid_mixed_case(): ] msg = "Invalid constraint types: {}" with pytest.raises(InvalidConstraintError, match=msg): - pre_process_constraints(constraints) + pre_process_constraints(constraints) # ty:ignore[invalid-argument-type] def test_deprecated_log_reader(example_db): with pytest.warns(FutureWarning, match="SQLiteLogReader"): reader = OptimizeLogReader(example_db) - res = reader.read_start_params() + res = reader.read_start_params() # ty:ignore[unresolved-attribute] assert res == {"a": 1, "b": 2, "c": 3} diff --git a/tests/optimagic/test_timing.py b/tests/optimagic/test_timing.py index fd2edfc3c..a45a0441b 100644 --- a/tests/optimagic/test_timing.py +++ b/tests/optimagic/test_timing.py @@ -10,5 +10,5 @@ def test_invalid_aggregate_batch_time(): jac=None, fun_and_jac=None, label="label", - aggregate_batch_time="Not callable", + aggregate_batch_time="Not callable", # ty:ignore[invalid-argument-type] ) diff --git a/tests/optimagic/visualization/test_backends.py b/tests/optimagic/visualization/test_backends.py index a46fd59c9..862abb285 100644 --- a/tests/optimagic/visualization/test_backends.py +++ b/tests/optimagic/visualization/test_backends.py @@ -25,7 +25,7 @@ def test_line_plot_all_backends(sample_lines, backend, close_mpl_figures): def test_line_plot_invalid_backend(sample_lines): with pytest.raises(InvalidPlottingBackendError): - line_plot(sample_lines, backend="bla") + line_plot(sample_lines, backend="bla") # ty:ignore[invalid-argument-type] def test_line_plot_unavailable_backend(sample_lines, monkeypatch): diff --git a/tests/optimagic/visualization/test_convergence_plot.py b/tests/optimagic/visualization/test_convergence_plot.py index 931786e30..28290ef68 100644 --- a/tests/optimagic/visualization/test_convergence_plot.py +++ b/tests/optimagic/visualization/test_convergence_plot.py @@ -80,7 +80,7 @@ def test_convergence_plot_stopping_criterion_none(benchmark_results): problems=problems, results=results, problem_subset=["bard_good_start"], - stopping_criterion=None, + stopping_criterion=None, # ty:ignore[invalid-argument-type] ) diff --git a/tests/optimagic/visualization/test_history_plots.py b/tests/optimagic/visualization/test_history_plots.py index 1680b66e7..b2d4ead08 100644 --- a/tests/optimagic/visualization/test_history_plots.py +++ b/tests/optimagic/visualization/test_history_plots.py @@ -41,7 +41,7 @@ def minimize_result(): om.MultistartOptions(n_samples=1000, convergence_max_discoveries=5) if multistart else None - ), + ), # ty:ignore[invalid-argument-type] ) res.append(_res) out[multistart] = res @@ -109,7 +109,7 @@ def test_criterion_plot_name_input(minimize_result): def test_criterion_plot_wrong_results(): with pytest.raises(TypeError): - criterion_plot([10, np.array([1, 2, 3])]) + criterion_plot([10, np.array([1, 2, 3])]) # ty:ignore[invalid-argument-type] def test_criterion_plot_different_input_types(): @@ -134,17 +134,17 @@ def test_criterion_plot_different_input_types(): results = ["test.db", res] - criterion_plot(results) - criterion_plot(results, monotone=True) - criterion_plot(results, stack_multistart=True) - criterion_plot(results, monotone=True, stack_multistart=True) - criterion_plot(results, show_exploration=True) + criterion_plot(results) # ty:ignore[invalid-argument-type] + criterion_plot(results, monotone=True) # ty:ignore[invalid-argument-type] + criterion_plot(results, stack_multistart=True) # ty:ignore[invalid-argument-type] + criterion_plot(results, monotone=True, stack_multistart=True) # ty:ignore[invalid-argument-type] + criterion_plot(results, show_exploration=True) # ty:ignore[invalid-argument-type] criterion_plot("test.db") def test_criterion_plot_wrong_inputs(): with pytest.raises(ValueError): - criterion_plot("bla", names=[1, 2]) + criterion_plot("bla", names=[1, 2]) # ty:ignore[invalid-argument-type] with pytest.raises(ValueError): criterion_plot(["bla", "bla"], names="blub") @@ -175,7 +175,7 @@ def test_harmonize_inputs_to_dict_single_result_with_name(): def test_harmonize_inputs_to_dict_list_results(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = [res, res] - assert _harmonize_inputs_to_dict(results=results, names=None) == { + assert _harmonize_inputs_to_dict(results=results, names=None) == { # ty:ignore[invalid-argument-type] "0": res, "1": res, } @@ -184,7 +184,7 @@ def test_harmonize_inputs_to_dict_list_results(): def test_harmonize_inputs_to_dict_dict_input(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = {"bla": res, om.algos.scipy_lbfgsb(): res, om.algos.scipy_neldermead: res} - got = _harmonize_inputs_to_dict(results=results, names=None) + got = _harmonize_inputs_to_dict(results=results, names=None) # ty:ignore[invalid-argument-type] expected = {"bla": res, "scipy_lbfgsb": res, "scipy_neldermead": res} assert got == expected @@ -192,7 +192,7 @@ def test_harmonize_inputs_to_dict_dict_input(): def test_harmonize_inputs_to_dict_dict_input_with_names(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = {"bla": res, "blub": res} - got = _harmonize_inputs_to_dict(results=results, names=["a", "b"]) + got = _harmonize_inputs_to_dict(results=results, names=["a", "b"]) # ty:ignore[invalid-argument-type] expected = {"a": res, "b": res} assert got == expected @@ -201,7 +201,7 @@ def test_harmonize_inputs_to_dict_invalid_names(): results = [None] names = ["a", "b"] with pytest.raises(ValueError): - _harmonize_inputs_to_dict(results=results, names=names) + _harmonize_inputs_to_dict(results=results, names=names) # ty:ignore[invalid-argument-type] def test_harmonize_inputs_to_dict_str_input(): @@ -216,7 +216,7 @@ def test_harmonize_inputs_to_dict_path_input(): def _compare_plotting_multistart_history_with_result( data: _PlottingMultistartHistory, res: om.OptimizeResult, res_name: str ): - assert_array_equal(data.history.fun, res.history.fun) + assert_array_equal(data.history.fun, res.history.fun) # ty:ignore[unresolved-attribute] assert data.name == res_name assert_array_equal(data.start_params, res.start_params) assert data.is_multistart == (res.multistart_info is not None) @@ -272,12 +272,12 @@ def test_retrieve_data_from_multistart_result(minimize_result, stack_multistart) assert isinstance(data, list) and len(data) == 1 assert data[0].is_multistart - assert len(data[0].local_histories) == 5 + assert len(data[0].local_histories) == 5 # ty:ignore[invalid-argument-type] if stack_multistart: assert_array_equal( - data[0].stacked_local_histories.fun, - np.concatenate([hist.fun for hist in data[0].local_histories]), + data[0].stacked_local_histories.fun, # ty:ignore[unresolved-attribute] + np.concatenate([hist.fun for hist in data[0].local_histories]), # ty:ignore[no-matching-overload, not-iterable] ) else: assert data[0].stacked_local_histories is None From 9f8278897989c57ed2bb67856258a9d3f266a2fe Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Thu, 23 Apr 2026 14:02:30 +0200 Subject: [PATCH 04/15] chore: remove sqlalchemy stubs --- pixi.lock | 109 +--------------------------- pyproject.toml | 1 - src/optimagic/logging/logger.py | 1 + src/optimagic/logging/sqlalchemy.py | 21 +++--- 4 files changed, 14 insertions(+), 118 deletions(-) diff --git a/pixi.lock b/pixi.lock index 4ca141936..8a429351f 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9687,13 +9687,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f1/16/d905e7f53e661ce2c24686c38048d8e2b750ffc4350009d41c4e6c6c9826/h5py-3.16.0-cp314-cp314-manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/8b/ecdad52d0b38d4b8f514be603e69ccd5eacf4e7241f972e37e79792212ec/orjson-3.11.7-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -9702,7 +9698,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/05/5b/83e1ff87eb60ca706972f7e02e15c0b33396e7bdbd080069a5d1b53cf0d8/simplejson-3.20.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/ae/cb215ab25b76228bc90c90444b87e323ffba58c212321a53d5bc92903098/sqlalchemy_stubs-0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/44/bb509c3d2c0b5a87e7a5af1d5917a402a32ff026f777a6d7cb6990746cbb/tabcompleter-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c8/15/4564f173d031f64bf56964d192b6b705e679fc23c02704b84ccbcb809396/types_cffi-1.17.0.20260307-py3-none-any.whl @@ -9968,13 +9963,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/b7/9366ed44ced9b7ef357ab48c94205280276db9d7f064aa3012a97227e966/h5py-3.16.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/e9/1e/745565dca749813db9a093c5ebc4bac1a9475c64d54b95654336ac3ed961/orjson-3.11.7-cp314-cp314-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -9983,7 +9974,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/05/5b/83e1ff87eb60ca706972f7e02e15c0b33396e7bdbd080069a5d1b53cf0d8/simplejson-3.20.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/ae/cb215ab25b76228bc90c90444b87e323ffba58c212321a53d5bc92903098/sqlalchemy_stubs-0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/44/bb509c3d2c0b5a87e7a5af1d5917a402a32ff026f777a6d7cb6990746cbb/tabcompleter-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c8/15/4564f173d031f64bf56964d192b6b705e679fc23c02704b84ccbcb809396/types_cffi-1.17.0.20260307-py3-none-any.whl @@ -10260,13 +10250,9 @@ environments: - pypi: https://files.pythonhosted.org/packages/af/d0/0c2aaa6173accca6507d25a82c266af8c01d94138058e99712153d4296a6/gradient_free_optimizers-1.10.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/3e/14/615a450205e1b56d16c6783f5ccd116cde05550faad70ae077c955654a75/h5py-3.16.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/4b/97/f6de8d4af54d6401d6581a686cce3e3e2371a79ba459a449104e026c08bc/kaleido-1.2.0-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/54/20/6aa79ba3570bddd1bf7e951c6123f806751e58e8cce736bad77b2cf348d7/logistro-2.0.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/12/df/172771902943af54bf661a8d102bdf2e7f932127968080632bda6054b62c/orjson-3.11.7-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/7c/2f/f91e4eee21585ff548e83358332d5632ee49f6b2dcd96cb5dca4e0468951/pandas_stubs-3.0.0.260204-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/51/fe/53ac0cd932db5dcaf55961bc7cb7afdca8d80d8cc7406ed661f0c7dc111a/pdbp-1.8.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/52/d2/c6e44dba74f17c6216ce1b56044a9b93a929f1c2d5bdaff892512b260f5e/plotly-6.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/f4/1e/0d44a4e3a291c009a357fbd1d61511d9306c2c4db9a7ceb6e8104d8d385f/Py_BOBYQA-1.5.0-py3-none-any.whl @@ -10276,7 +10262,6 @@ environments: - pypi: https://files.pythonhosted.org/packages/fa/b6/3127540ecdf1464a00e5a01ee60a1b09175f6913f0644ac748494d9c4b21/pytest_timeout-2.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/05/5b/83e1ff87eb60ca706972f7e02e15c0b33396e7bdbd080069a5d1b53cf0d8/simplejson-3.20.2-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/62/ae/cb215ab25b76228bc90c90444b87e323ffba58c212321a53d5bc92903098/sqlalchemy_stubs-0.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/65/44/bb509c3d2c0b5a87e7a5af1d5917a402a32ff026f777a6d7cb6990746cbb/tabcompleter-1.4.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c8/15/4564f173d031f64bf56964d192b6b705e679fc23c02704b84ccbcb809396/types_cffi-1.17.0.20260307-py3-none-any.whl @@ -16351,21 +16336,6 @@ packages: purls: [] size: 211099 timestamp: 1762397758105 -- pypi: https://files.pythonhosted.org/packages/24/ed/c22ca4db0ca3cbc285e4d9206108746beda561a9792289c3c31281d7e9df/librt-0.9.0-cp314-cp314-win_amd64.whl - name: librt - version: 0.9.0 - sha256: b8bd70d5d816566a580d193326912f4a76ec2d28a97dc4cd4cc831c0af8e330e - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f2/94/a2025fe442abedf8b038038dab3dba942009ad42b38ea064a1a9e6094241/librt-0.9.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: librt - version: 0.9.0 - sha256: f3fd278f5e6bf7c75ccd6d12344eb686cc020712683363b66f46ac79d37c799f - requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/f3/ad/23399bdcb7afca819acacdef31b37ee59de261bd66b503a7995c03c4b0dc/librt-0.9.0-cp314-cp314-macosx_11_0_arm64.whl - name: librt - version: 0.9.0 - sha256: 1c587494461ebd42229d0f1739f3aa34237dd9980623ecf1be8d3bcba79f4499 - requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/linux-64/libscotch-7.0.11-int64_hfcc3fd4_2.conda sha256: 2c2030d8dc2a4af1bbeac2c25de74fd3269afaf72d3ba666b6bd5af6f4b534ba md5: 263641cd867b74db096f6f30752bd502 @@ -18312,65 +18282,6 @@ packages: - pkg:pypi/munkres?source=hash-mapping size: 15851 timestamp: 1749895533014 -- pypi: https://files.pythonhosted.org/packages/19/65/0cd9285ab010ee8214c83d67c6b49417c40d86ce46f1aa109457b5a9b8d7/mypy-1.20.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - name: mypy - version: 1.20.2 - sha256: 5a65aa591af023864fd08a97da9974e919452cfe19cb146c8a5dc692626445dc - requires_dist: - - typing-extensions>=4.6.0 ; python_full_version < '3.15' - - typing-extensions>=4.14.0 ; python_full_version >= '3.15' - - mypy-extensions>=1.0.0 - - pathspec>=1.0.0 - - tomli>=1.1.0 ; python_full_version < '3.11' - - librt>=0.8.0 ; platform_python_implementation != 'PyPy' - - psutil>=4.0 ; extra == 'dmypy' - - setuptools>=50 ; extra == 'mypyc' - - lxml ; extra == 'reports' - - pip ; extra == 'install-types' - - orjson ; extra == 'faster-cache' - - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/3a/63/d2c2ff4fa66bc49477d32dfa26e8a167ba803ea6a69c5efb416036909d30/mypy-1.20.2-cp314-cp314-macosx_11_0_arm64.whl - name: mypy - version: 1.20.2 - sha256: e73c07f23009962885c197ccb9b41356a30cc0e5a1d0c2ea8fd8fb1362d7f924 - requires_dist: - - typing-extensions>=4.6.0 ; python_full_version < '3.15' - - typing-extensions>=4.14.0 ; python_full_version >= '3.15' - - mypy-extensions>=1.0.0 - - pathspec>=1.0.0 - - tomli>=1.1.0 ; python_full_version < '3.11' - - librt>=0.8.0 ; platform_python_implementation != 'PyPy' - - psutil>=4.0 ; extra == 'dmypy' - - setuptools>=50 ; extra == 'mypyc' - - lxml ; extra == 'reports' - - pip ; extra == 'install-types' - - orjson ; extra == 'faster-cache' - - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/fd/a1/1b4233d255bdd0b38a1f284feeb1c143ca508c19184964e22f8d837ec851/mypy-1.20.2-cp314-cp314-win_amd64.whl - name: mypy - version: 1.20.2 - sha256: 913485a03f1bcf5d279409a9d2b9ed565c151f61c09f29991e5faa14033da4c8 - requires_dist: - - typing-extensions>=4.6.0 ; python_full_version < '3.15' - - typing-extensions>=4.14.0 ; python_full_version >= '3.15' - - mypy-extensions>=1.0.0 - - pathspec>=1.0.0 - - tomli>=1.1.0 ; python_full_version < '3.11' - - librt>=0.8.0 ; platform_python_implementation != 'PyPy' - - psutil>=4.0 ; extra == 'dmypy' - - setuptools>=50 ; extra == 'mypyc' - - lxml ; extra == 'reports' - - pip ; extra == 'install-types' - - orjson ; extra == 'faster-cache' - - ast-serialize>=0.1.1,<1.0.0 ; extra == 'native-parser' - requires_python: '>=3.10' -- pypi: https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl - name: mypy-extensions - version: 1.1.0 - sha256: 1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 - requires_python: '>=3.8' - conda: https://conda.anaconda.org/conda-forge/noarch/myst-nb-1.4.0-pyhcf101f3_0.conda sha256: c81d0c8c74c3da66808f8da09d8e48f2af2d173d357d45239defaf466838edba md5: da07c7b1588ad0a44118d28aeb31b6a6 @@ -19410,8 +19321,8 @@ packages: timestamp: 1733688053334 - pypi: ./ name: optimagic - version: 0.1.dev474+ge123e7949.d20260423 - sha256: bd0884351f9fd38a6d678bd108399fe6af0aebbe971cf0d58924a8221e2bf439 + version: 0.1.dev475+gc5e6012a1.d20260423 + sha256: 71263c11d276085203c19f5e6af3e045bb96d3e90779d10495cad5397fac1653 requires_dist: - annotated-types>=0.4 - cloudpickle>=2.2 @@ -20207,15 +20118,6 @@ packages: - pkg:pypi/parso?source=hash-mapping size: 82287 timestamp: 1770676243987 -- pypi: https://files.pythonhosted.org/packages/fa/c9/8eed0486f074e9f1ca7f8ce5ad663e65f12fdab344028d658fa1b03d35e0/pathspec-1.1.0-py3-none-any.whl - name: pathspec - version: 1.1.0 - sha256: 574b128f7456bd899045ccd142dd446af7e6cfd0072d63ad73fbc55fbb4aaa42 - requires_dist: - - hyperscan>=0.7 ; extra == 'hyperscan' - - typing-extensions>=4 ; extra == 'optional' - - google-re2>=1.1 ; extra == 're2' - requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/patsy-1.0.2-pyhcf101f3_0.conda sha256: 9678f4745e6b82b36fab9657a19665081862268cb079cf9acf878ab2c4fadee9 md5: 8678577a52161cc4e1c93fcc18e8a646 @@ -25066,13 +24968,6 @@ packages: - pkg:pypi/sqlalchemy?source=compressed-mapping size: 3979804 timestamp: 1771967329879 -- pypi: https://files.pythonhosted.org/packages/62/ae/cb215ab25b76228bc90c90444b87e323ffba58c212321a53d5bc92903098/sqlalchemy_stubs-0.4-py3-none-any.whl - name: sqlalchemy-stubs - version: '0.4' - sha256: 5eec7aa110adf9b957b631799a72fef396b23ff99fe296df726645d01e312aa5 - requires_dist: - - mypy>=0.790 - - typing-extensions>=3.7.4 - conda: https://conda.anaconda.org/conda-forge/noarch/stack_data-0.6.3-pyhd8ed1ab_1.conda sha256: 570da295d421661af487f1595045760526964f41471021056e993e73089e9c41 md5: b1b505328da7a6b246787df4b5a49fbc diff --git a/pyproject.toml b/pyproject.toml index 8306ae2e1..0b189828e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -462,7 +462,6 @@ pandas-stubs = "*" types-cffi = "*" types-openpyxl = "*" types-jinja2 = "*" -sqlalchemy-stubs = "*" [tool.pixi.feature.type-checking.tasks] ty = { cmd = "ty check", description = "Run ty type checker" } diff --git a/src/optimagic/logging/logger.py b/src/optimagic/logging/logger.py index f1a02ef85..a66122d84 100644 --- a/src/optimagic/logging/logger.py +++ b/src/optimagic/logging/logger.py @@ -8,6 +8,7 @@ import numpy as np import pandas as pd import sqlalchemy as sql +import sqlalchemy.event from sqlalchemy.engine import Engine from optimagic.logging.base import ( diff --git a/src/optimagic/logging/sqlalchemy.py b/src/optimagic/logging/sqlalchemy.py index a71e182a1..a3d3c9512 100644 --- a/src/optimagic/logging/sqlalchemy.py +++ b/src/optimagic/logging/sqlalchemy.py @@ -7,7 +7,8 @@ from typing import Any, Sequence, Type, cast import sqlalchemy as sql -from sqlalchemy import Column, Integer, PickleType, String +import sqlalchemy.event +from sqlalchemy import Column, Integer, PickleType, Row, String from sqlalchemy.engine.base import Engine from sqlalchemy.sql.base import Executable from sqlalchemy.sql.schema import MetaData @@ -82,7 +83,7 @@ def _setup_pickletype( inspector: Any, table: sql.Table, column_info: dict[str, Any] ) -> None: # noqa: ARG001 if isinstance(column_info["type"], sql.BLOB): - column_info["type"] = sql.PickleType(pickler=RobustPickler) # ty:ignore[invalid-argument-type] + column_info["type"] = sql.PickleType(pickler=RobustPickler) @dataclass @@ -160,17 +161,17 @@ def table(self) -> sql.Table: def engine(self) -> Engine: return self._engine - def _select_row_by_key(self, key: int) -> list[Any]: + def _select_row_by_key(self, key: int) -> Sequence[Row[Any]]: stmt = self._table.select().where( getattr(self._table.c, self._table_config.primary_key) == key ) return self._execute_read_statement(stmt) - def _select_all_rows(self) -> list[Any]: + def _select_all_rows(self) -> Sequence[Row[Any]]: stmt = self._table.select() return self._execute_read_statement(stmt) - def _select_last_rows(self, n_rows: int) -> list[Any]: + def _select_last_rows(self, n_rows: int) -> Sequence[Row[Any]]: stmt = ( self._table.select() .order_by(getattr(self._table.c, self._table_config.primary_key).desc()) @@ -183,7 +184,7 @@ def _insert(self, insert_values: dict[str, Any]) -> None: stmt = self._table.insert().values(**insert_values) self._execute_write_statement(stmt) - def _execute_read_statement(self, statement: Executable) -> list[Any]: + def _execute_read_statement(self, statement: Executable) -> Sequence[Row[Any]]: with self._engine.connect() as connection: return connection.execute(statement).fetchall() @@ -230,7 +231,7 @@ def __init__( super().__init__(input_type, output_type, primary_key) columns = [ sql.Column(primary_key, sql.Integer, primary_key=True, autoincrement=True), - sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), # ty:ignore[invalid-argument-type] + sql.Column(self._value_column, sql.PickleType(pickler=RobustPickler)), ] table_config = TableConfig(table_name, columns, self.primary_key) @@ -280,7 +281,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # ty:ignore[unresolved-attribute] + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: output_list = [] for row in results: row_dict = {self.primary_key: row[0]} @@ -370,7 +371,7 @@ def select_last_rows(self, n_rows: int) -> list[OutputType]: result = self._select_last_rows(n_rows) return self._post_process(result) - def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: # ty:ignore[unresolved-attribute] + def _post_process(self, results: Sequence[sql.Row]) -> list[OutputType]: return [ self._output_type(**dict(zip(self.column_names, row, strict=False))) for row in results @@ -460,7 +461,7 @@ def __init__( columns = [ Column(self._PRIMARY_KEY, Integer, primary_key=True, autoincrement=True), Column("direction", String), - Column("params", PickleType(pickler=RobustPickler)), # ty:ignore[invalid-argument-type] + Column("params", PickleType(pickler=RobustPickler)), ] table_config = TableConfig( From 63a1f142464e9a3bc26daecaa1d53af21ad278b7 Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Thu, 23 Apr 2026 14:06:17 +0200 Subject: [PATCH 05/15] chore: remove mypy comments and add replace mypy with on contribution guide --- docs/source/development/how_to_contribute.md | 2 +- src/optimagic/optimization/history.py | 2 -- src/optimagic/visualization/slice_plot_3d.py | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/source/development/how_to_contribute.md b/docs/source/development/how_to_contribute.md index 91f07dd07..a281e4af5 100644 --- a/docs/source/development/how_to_contribute.md +++ b/docs/source/development/how_to_contribute.md @@ -64,7 +64,7 @@ For regular contributors: **Clone** the [repository](https://github.com/optimagi use: ```console - $ pixi run mypy + $ pixi run ty ``` To see all available pixi tasks, run: diff --git a/src/optimagic/optimization/history.py b/src/optimagic/optimization/history.py index 2b29cfdc4..17fbad0e7 100644 --- a/src/optimagic/optimization/history.py +++ b/src/optimagic/optimization/history.py @@ -407,8 +407,6 @@ def _get_flat_params(params: list[PyTree]) -> list[list[float]]: def _get_flat_param_names(param: PyTree) -> list[str]: fast_path = _is_1d_array(param) if fast_path: - # Mypy raises an error here because .tolist() returns a str for zero-dimensional - # arrays, but the fast path is only taken for 1d arrays, so it can be ignored. return np.arange(param.size).astype(str).tolist() registry = get_registry(extended=True) diff --git a/src/optimagic/visualization/slice_plot_3d.py b/src/optimagic/visualization/slice_plot_3d.py index 24475580c..e2acdd8ae 100644 --- a/src/optimagic/visualization/slice_plot_3d.py +++ b/src/optimagic/visualization/slice_plot_3d.py @@ -913,7 +913,6 @@ def evaluate_make_subplot_kwargs( return make_subplot_defaults -# mypy: disable-error-code="dict-item" def evaluate_layout_kwargs( layout_kwargs, projection, From ba2d96023f4c401098c47d2a6e5a8df464d17016 Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Mon, 13 Jul 2026 12:03:51 +0200 Subject: [PATCH 06/15] chore: add ty ignore comments --- .../parameters/constraints/test_resolution.py | 20 +++++++++---------- tests/optimagic/test_constraints.py | 12 +++++------ tests/optimagic/test_deprecations.py | 6 +++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/tests/optimagic/parameters/constraints/test_resolution.py b/tests/optimagic/parameters/constraints/test_resolution.py index 4453485ef..55cea1f62 100644 --- a/tests/optimagic/parameters/constraints/test_resolution.py +++ b/tests/optimagic/parameters/constraints/test_resolution.py @@ -38,7 +38,7 @@ def tree_params_converter(tree_params): params_unflatten=lambda x: tree_unflatten( treedef, x.tolist(), registry=registry ), - derivative_flatten=None, + derivative_flatten=None, # ty:ignore[invalid-argument-type] ) return converter @@ -82,7 +82,7 @@ def test_tree_selectors_pairwise(tree_params, tree_params_converter): om.PairwiseEqualityConstraint(selectors=[lambda x: x[1], lambda x: x[0][1][0]]) ] calculated = resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=tree_params, tree_converter=tree_params_converter, param_names=PARAM_NAMES, @@ -109,15 +109,15 @@ def test_provenance_is_attached(np_params_converter): om.EqualityConstraint(selector=lambda x: x[[1, 2]]), ] calculated = resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, ) for position, resolved in enumerate(calculated): - assert len(resolved.sources) == 1 - assert resolved.sources[0].position == position - assert resolved.sources[0].constraint is constraints[position] + assert len(resolved.sources) == 1 # ty:ignore[unresolved-attribute] + assert resolved.sources[0].position == position # ty:ignore[unresolved-attribute] + assert resolved.sources[0].constraint is constraints[position] # ty:ignore[unresolved-attribute] def test_empty_selections_are_dropped(np_params_converter): @@ -131,7 +131,7 @@ def test_empty_selections_are_dropped(np_params_converter): ), ] calculated = resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -143,7 +143,7 @@ def test_duplicates_raise(np_params_converter): constraints = [om.EqualityConstraint(selector=lambda x: x[[0, 0, 1]])] with pytest.raises(InvalidConstraintError, match="duplicates"): resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -154,7 +154,7 @@ def test_failing_selector_raises_invalid_constraint_error(np_params_converter): constraints = [om.FixedConstraint(selector=lambda x: x["invalid"])] with pytest.raises(InvalidConstraintError, match="select parameters"): resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -177,7 +177,7 @@ def test_to_legacy_dicts_shapes(np_params_converter): om.LinearConstraint(selector=lambda x: x[[4, 5]], weights=1, upper_bound=5), ] resolved = resolve_constraints( - constraints=constraints, + constraints=constraints, # ty:ignore[invalid-argument-type] params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, diff --git a/tests/optimagic/test_constraints.py b/tests/optimagic/test_constraints.py index 432d45623..73ea7aa84 100644 --- a/tests/optimagic/test_constraints.py +++ b/tests/optimagic/test_constraints.py @@ -257,7 +257,7 @@ def test_resolve_empty_selection_returns_none(constraint): def test_resolve_fixed_constraint_has_no_explicit_value(): constr = FixedConstraint(selector=lambda x: x[[0, 2]]) resolved = constr._resolve(make_context(constr)) - assert resolved.value is None + assert resolved.value is None # ty:ignore[unresolved-attribute] def test_resolve_pairwise_equality_constraint(): @@ -306,16 +306,16 @@ def test_resolve_linear_constraint_aligns_weight_sequence(): selector=lambda x: x[[0, 2, 4]], weights=[1, 2, 3], upper_bound=5 ) resolved = constr._resolve(make_context(constr)) - aae(resolved.index, np.array([0, 2, 4])) - aae(resolved.weights, np.array([1.0, 2.0, 3.0])) + aae(resolved.index, np.array([0, 2, 4])) # ty:ignore[unresolved-attribute] + aae(resolved.weights, np.array([1.0, 2.0, 3.0])) # ty:ignore[unresolved-attribute] def test_resolve_linear_constraint_fills_absent_bounds_with_sentinels(): constr = LinearConstraint(selector=lambda x: x[[0, 2]], weights=1, lower_bound=1) resolved = constr._resolve(make_context(constr)) - assert resolved.lower_bound == 1 - assert resolved.upper_bound == np.inf - assert np.isnan(resolved.value) + assert resolved.lower_bound == 1 # ty:ignore[unresolved-attribute] + assert resolved.upper_bound == np.inf # ty:ignore[unresolved-attribute] + assert np.isnan(resolved.value) # ty:ignore[unresolved-attribute] def test_resolve_linear_constraint_with_misaligned_weights_raises(): diff --git a/tests/optimagic/test_deprecations.py b/tests/optimagic/test_deprecations.py index 3aa55cb55..511342356 100644 --- a/tests/optimagic/test_deprecations.py +++ b/tests/optimagic/test_deprecations.py @@ -1206,7 +1206,7 @@ def test_nonlinear_dict_without_selection_field_selects_all_params(): func = lambda x: x @ x # noqa: E731 got = pre_process_constraints([{"type": "nonlinear", "func": func, "value": 1}]) params = np.arange(3) - assert got[0].selector(params) is params + assert got[0].selector(params) is params # ty:ignore[unresolved-attribute] def test_nonlinear_dict_loc_selector_has_no_value_indexing(df_params): @@ -1221,7 +1221,7 @@ def test_nonlinear_dict_loc_selector_has_no_value_indexing(df_params): } ] ) - selected = got[0].selector(df_params) + selected = got[0].selector(df_params) # ty:ignore[unresolved-attribute] pd.testing.assert_frame_equal(selected, df_params.loc[["b", "e"]]) @@ -1230,7 +1230,7 @@ def test_pairwise_equality_dict_with_selectors_is_converted(): got = pre_process_constraints( [{"type": "pairwise_equality", "selectors": selectors}] ) - assert got == [om.PairwiseEqualityConstraint(selectors=selectors)] + assert got == [om.PairwiseEqualityConstraint(selectors=selectors)] # ty:ignore[invalid-argument-type] def test_loc_on_numpy_params(): From dd45ad2a0e13a8eb01a3b8d331fd1a27a37f826b Mon Sep 17 00:00:00 2001 From: Abel Abate Date: Mon, 13 Jul 2026 15:25:02 +0200 Subject: [PATCH 07/15] bump ty to latest version --- .tools/create_algo_selection_code.py | 2 +- pixi.lock | 45 +++++++++---------- pyproject.toml | 3 +- src/optimagic/deprecations.py | 2 +- src/optimagic/differentiation/derivatives.py | 4 +- src/optimagic/mark.py | 6 +-- src/optimagic/optimization/history.py | 2 +- tests/optimagic/optimization/test_history.py | 4 +- .../optimagic/optimization/test_multistart.py | 2 +- .../parameters/test_nonlinear_constraints.py | 2 +- .../visualization/test_history_plots.py | 2 +- 11 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.tools/create_algo_selection_code.py b/.tools/create_algo_selection_code.py index 0fb917a4d..22e9340e0 100644 --- a/.tools/create_algo_selection_code.py +++ b/.tools/create_algo_selection_code.py @@ -223,7 +223,7 @@ def _generate_category_combinations(categories: list[str]) -> list[tuple[str, .. result: list[tuple[str, ...]] = [] for r in range(len(categories) + 1): result.extend(map(tuple, map(sorted, combinations(categories, r)))) - return sorted(result, key=len, reverse=True) # ty:ignore[invalid-return-type] + return sorted(result, key=len, reverse=True) def _apply_filters( diff --git a/pixi.lock b/pixi.lock index b51d4c1ea..c04bdfb4a 100644 --- a/pixi.lock +++ b/pixi.lock @@ -9637,7 +9637,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.24-h4e94fc0_0.conda + - conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.59-h4e94fc0_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -9934,7 +9934,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyh8f84b5b_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.24-ha73ee7d_0.conda + - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.59-hdfcc030_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -10215,7 +10215,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tqdm-4.67.3-pyha7b4d00_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/traitlets-5.14.3-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/tranquilo-0.1.1-pyhd8ed1ab_0.conda - - conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.24-hc21aad4_0.conda + - conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.59-hc21aad4_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing-extensions-4.15.0-h396c80c_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.15.0-pyhcf101f3_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/typing_utils-0.1.0-pyhd8ed1ab_1.conda @@ -19321,8 +19321,8 @@ packages: timestamp: 1733688053334 - pypi: ./ name: optimagic - version: 0.5.4.dev11+g63a1f1424.d20260713 - sha256: 71263c11d276085203c19f5e6af3e045bb96d3e90779d10495cad5397fac1653 + version: 0.5.4.dev17+gba2d96023.d20260713 + sha256: 55d7e0df3114e4d13000ef78e37609f4203eaf56ae6c039d81f9f14c7995bd71 requires_dist: - annotated-types>=0.4 - cloudpickle>=2.2 @@ -25586,28 +25586,27 @@ packages: - pkg:pypi/tranquilo?source=hash-mapping size: 73744 timestamp: 1772093378917 -- conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.24-h4e94fc0_0.conda +- conda: https://conda.anaconda.org/conda-forge/linux-64/ty-0.0.59-h4e94fc0_0.conda noarch: python - sha256: 3de56413211bcb07c8df0a66eaaed996f0d14a6dbd9cee0b42a0b275c0e464e0 - md5: db52fd98c2edb81ba0f81a1b0aecc8cc + sha256: 7cf135185dee0b985520985d5e626d04a9c8d085a041418104b7ccf646dbd9f7 + md5: c2ba304bba1fbf79906b3312677edb5d depends: - python - - libgcc >=14 - __glibc >=2.17,<3.0.a0 + - libgcc >=14 - _python_abi3_support 1.* - cpython >=3.10 constrains: - __glibc >=2.17 license: MIT - license_family: MIT purls: - pkg:pypi/ty?source=hash-mapping - size: 9207623 - timestamp: 1773948239539 -- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.24-ha73ee7d_0.conda + size: 10303828 + timestamp: 1783908696596 +- conda: https://conda.anaconda.org/conda-forge/osx-arm64/ty-0.0.59-hdfcc030_0.conda noarch: python - sha256: c6924afb9d541bed15f159389c08ab5ae492bb69f4e660ae608add0498834703 - md5: 39c996ee15024882153fd31b502b6572 + sha256: 4026d41475ebf53f3810913e80618cecd4459b4d497839ba044ad5a2f89183da + md5: 5e6c3112ca11b9c047a60a2b17f3bf1c depends: - python - __osx >=11.0 @@ -25616,15 +25615,14 @@ packages: constrains: - __osx >=11.0 license: MIT - license_family: MIT purls: - pkg:pypi/ty?source=hash-mapping - size: 8304066 - timestamp: 1773948334333 -- conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.24-hc21aad4_0.conda + size: 9330666 + timestamp: 1783908711033 +- conda: https://conda.anaconda.org/conda-forge/win-64/ty-0.0.59-hc21aad4_0.conda noarch: python - sha256: 754cd686b04cebdb019d64481f4e3affdbf2fad05e34410ecf6d266c5463e2d5 - md5: b8a33290eda47d529ed05976ec5b0128 + sha256: 83ecfac9ac09d73f3325714f67551e4b32af6c1840f15b056204b13c24ede597 + md5: d35c871f7af02f796e3ec32d9c1b3451 depends: - python - vc >=14.3,<15 @@ -25633,11 +25631,10 @@ packages: - _python_abi3_support 1.* - cpython >=3.10 license: MIT - license_family: MIT purls: - pkg:pypi/ty?source=hash-mapping - size: 9232166 - timestamp: 1773948344148 + size: 10435580 + timestamp: 1783908745042 - pypi: https://files.pythonhosted.org/packages/c8/15/4564f173d031f64bf56964d192b6b705e679fc23c02704b84ccbcb809396/types_cffi-1.17.0.20260307-py3-none-any.whl name: types-cffi version: 1.17.0.20260307 diff --git a/pyproject.toml b/pyproject.toml index 0b189828e..6bc0ac41b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -455,7 +455,7 @@ tests-with-cov = { cmd = "pytest --cov-report=xml --cov=src", description = "Run # --- Feature: type-checking (ty + type stubs) -------------------------------------- [tool.pixi.feature.type-checking.dependencies] -ty = ">=0.0.24,<0.0.25" +ty = ">=0.0.59,<0.0.60" [tool.pixi.feature.type-checking.pypi-dependencies] pandas-stubs = "*" @@ -466,6 +466,7 @@ types-jinja2 = "*" [tool.pixi.feature.type-checking.tasks] ty = { cmd = "ty check", description = "Run ty type checker" } ty-concise = { cmd = "ty check --output-format concise", description = "Run ty type checker with concise output" } +ty-fix = { cmd = "ty check --fix", description = "Run ty type checker and apply safe fixes" } # --- Feature: linux (Linux-only deps) ------------------------------------------------ [tool.pixi.feature.linux] diff --git a/src/optimagic/deprecations.py b/src/optimagic/deprecations.py index 12e34b766..2067f7304 100644 --- a/src/optimagic/deprecations.py +++ b/src/optimagic/deprecations.py @@ -563,7 +563,7 @@ def handle_log_options_throw_deprecated_warning( log_options = { k: v for k, v in log_options.items() if k != "if_table_exists" } - return SQLiteLogOptions(cast(str | Path, logger), **log_options) + return SQLiteLogOptions(cast(str | Path, logger), **log_options) # ty:ignore[redundant-cast] elif not log_options_is_compatible: raise ValueError( f"Found string or path for logger argument, but parameter" diff --git a/src/optimagic/differentiation/derivatives.py b/src/optimagic/differentiation/derivatives.py index e6a70f19d..7af8495e0 100644 --- a/src/optimagic/differentiation/derivatives.py +++ b/src/optimagic/differentiation/derivatives.py @@ -382,7 +382,7 @@ def first_derivative( step_size, evals, updated_candidates, target="first_derivative" ) result = {**result, **info} - return NumdiffResult(**result) + return NumdiffResult(**result) # ty:ignore[invalid-argument-type] def second_derivative( @@ -718,7 +718,7 @@ def second_derivative( step_size, evals, updated_candidates, target="second_derivative" ) result = {**result, **info} - return NumdiffResult(**result) + return NumdiffResult(**result) # ty:ignore[invalid-argument-type] def _is_1d_array(candidate: Any) -> bool: diff --git a/src/optimagic/mark.py b/src/optimagic/mark.py index ba0677137..a7ffaf406 100644 --- a/src/optimagic/mark.py +++ b/src/optimagic/mark.py @@ -15,7 +15,7 @@ def scalar(func: ScalarFuncT) -> ScalarFuncT: """Mark a function as a scalar function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.SCALAR + wrapper._problem_type = AggregationLevel.SCALAR # ty:ignore[unresolved-attribute] except (KeyboardInterrupt, SystemExit): raise except Exception: @@ -32,7 +32,7 @@ def least_squares(func: VectorFuncT) -> VectorFuncT: """Mark a function as a least squares function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.LEAST_SQUARES + wrapper._problem_type = AggregationLevel.LEAST_SQUARES # ty:ignore[unresolved-attribute] except (KeyboardInterrupt, SystemExit): raise except Exception: @@ -49,7 +49,7 @@ def likelihood(func: VectorFuncT) -> VectorFuncT: """Mark a function as a likelihood function.""" wrapper = func try: - wrapper._problem_type = AggregationLevel.LIKELIHOOD + wrapper._problem_type = AggregationLevel.LIKELIHOOD # ty:ignore[unresolved-attribute] except (KeyboardInterrupt, SystemExit): raise except Exception: diff --git a/src/optimagic/optimization/history.py b/src/optimagic/optimization/history.py index 17fbad0e7..991df7f01 100644 --- a/src/optimagic/optimization/history.py +++ b/src/optimagic/optimization/history.py @@ -167,7 +167,7 @@ def monotone_fun(self) -> NDArray[np.float64]: # ---------------------------------------------------------------------------------- @property - def is_accepted(self) -> NDArray[np.bool_]: # ty:ignore[invalid-return-type] + def is_accepted(self) -> NDArray[np.bool_]: """Boolean indicator whether a function value is accepted. A function value is accepted if it is smaller (or equal) than the monotone diff --git a/tests/optimagic/optimization/test_history.py b/tests/optimagic/optimization/test_history.py index 9f00cdc6c..79b0f2a55 100644 --- a/tests/optimagic/optimization/test_history.py +++ b/tests/optimagic/optimization/test_history.py @@ -640,5 +640,7 @@ def test_apply_to_batch_func_with_non_scalar_return(): batch_ids = [0, 0, 1, 1, 2] with pytest.raises(ValueError, match="Function did not return a scalar"): _apply_reduction_to_batches( - data, batch_ids, reduction_function=lambda _list: _list + data, + batch_ids, + reduction_function=lambda _list: _list, # ty:ignore[invalid-argument-type] ) diff --git a/tests/optimagic/optimization/test_multistart.py b/tests/optimagic/optimization/test_multistart.py index 6fa1fa89f..3edb14108 100644 --- a/tests/optimagic/optimization/test_multistart.py +++ b/tests/optimagic/optimization/test_multistart.py @@ -104,7 +104,7 @@ def test_get_batched_optimization_sample(): assert isinstance(calc_batch, list) for calc_entry, exp_entry in zip(calc_batch, exp_batch, strict=False): assert isinstance(calc_entry, np.ndarray) - assert calc_entry.tolist() == exp_entry + assert calc_entry.tolist() == exp_entry # ty:ignore[no-matching-overload] @pytest.fixture() diff --git a/tests/optimagic/parameters/test_nonlinear_constraints.py b/tests/optimagic/parameters/test_nonlinear_constraints.py index 2d0eeaa1c..64a8d4ff9 100644 --- a/tests/optimagic/parameters/test_nonlinear_constraints.py +++ b/tests/optimagic/parameters/test_nonlinear_constraints.py @@ -259,7 +259,7 @@ def test_process_nonlinear_constraints(): assert g["n_constr"] == e["n_constr"] for value in [0.1, 0.2, 1.2, -2.0]: x = np.array([value]) - assert_array_equal(g["fun"](x), e["fun"](x)) + assert_array_equal(g["fun"](x), e["fun"](x)) # ty:ignore[call-non-callable] assert "jac" in g assert "tol" in g diff --git a/tests/optimagic/visualization/test_history_plots.py b/tests/optimagic/visualization/test_history_plots.py index b2d4ead08..937926e2a 100644 --- a/tests/optimagic/visualization/test_history_plots.py +++ b/tests/optimagic/visualization/test_history_plots.py @@ -277,7 +277,7 @@ def test_retrieve_data_from_multistart_result(minimize_result, stack_multistart) if stack_multistart: assert_array_equal( data[0].stacked_local_histories.fun, # ty:ignore[unresolved-attribute] - np.concatenate([hist.fun for hist in data[0].local_histories]), # ty:ignore[no-matching-overload, not-iterable] + np.concatenate([hist.fun for hist in data[0].local_histories]), # ty:ignore[not-iterable] ) else: assert data[0].stacked_local_histories is None From 23ef5a49a8cac6ea21bf2f4d4dbd02bec5059457 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Fri, 25 Sep 2026 18:27:52 +0200 Subject: [PATCH 08/15] Fix bugs hidden by ty ignores and accept Sequence inputs Bugs: - estimation_table: error messages referenced undefined variables, raising UnboundLocalError instead of the intended TypeError. - estimagic.OptimizeLogReader: the deprecation warning never fired because the parent class returns a SQLiteLogReader from __new__, so __init__ never ran. - pounders_history: remove unused get_best_centered_entries, which passed self twice and always raised. - config: import importlib.metadata explicitly and compare the bayesian_optimization major version numerically instead of as a string. Typing: - Accept any Sequence of constraints in minimize/maximize and the constraint pre-processing, and any Sequence/Mapping of results in criterion_plot. List invariance rejected e.g. list[FixedConstraint] where list[Constraint] was expected. Removes 22 ty:ignore comments. Co-Authored-By: Claude Opus 5.5 --- src/estimagic/__init__.py | 7 ++- src/estimagic/estimate_ml.py | 2 +- src/estimagic/estimate_msm.py | 2 +- src/estimagic/estimation_table.py | 6 +- src/optimagic/config.py | 3 +- src/optimagic/deprecations.py | 60 +++++++++++-------- src/optimagic/optimization/optimize.py | 2 +- .../optimizers/_pounders/pounders_history.py | 3 - src/optimagic/parameters/constraint_tools.py | 2 +- .../parameters/constraints/resolution.py | 3 +- src/optimagic/visualization/history_plots.py | 12 ++-- tests/estimagic/test_estimation_table.py | 12 ++++ .../test_with_advanced_constraints.py | 2 +- .../optimization/test_with_constraints.py | 19 +++++- .../parameters/constraints/test_resolution.py | 12 ++-- tests/optimagic/test_deprecations.py | 21 +++++-- .../visualization/test_history_plots.py | 22 ++++--- 17 files changed, 123 insertions(+), 67 deletions(-) diff --git a/src/estimagic/__init__.py b/src/estimagic/__init__.py index 677ccf86c..bc68707ed 100644 --- a/src/estimagic/__init__.py +++ b/src/estimagic/__init__.py @@ -32,6 +32,7 @@ from optimagic import slice_plot as _slice_plot from optimagic import traceback_report as _traceback_report from optimagic.decorators import deprecated +from optimagic.logging import SQLiteLogReader as _SQLiteLogReader MSG = ( "estimagic.{name} has been deprecated in version 0.5.0. Use optimagic.{name} " @@ -61,14 +62,16 @@ class OptimizeLogReader(_OptimizeLogReader): - def __init__(self, path): + # The parent class returns a SQLiteLogReader from __new__, so __init__ of this + # class would never run. Hence, the warning needs to be raised in __new__. + def __new__(cls, *args, **kwargs) -> _SQLiteLogReader: warnings.warn( "estimagic.OptimizeLogReader has been deprecated in version 0.5.0. Use " "optimagic.OptimizeLogReader instead. This class will be removed in version" " 0.6.0.", FutureWarning, ) - super().__init__(path) # ty:ignore[too-many-positional-arguments] + return super().__new__(cls, *args, **kwargs) @dataclass diff --git a/src/estimagic/estimate_ml.py b/src/estimagic/estimate_ml.py index dbc38156f..cb25e2924 100644 --- a/src/estimagic/estimate_ml.py +++ b/src/estimagic/estimate_ml.py @@ -170,7 +170,7 @@ def estimate_ml( if hessian_numdiff_options is None: hessian_numdiff_options = numdiff_options - deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] + deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ================================================================================== # Check and process inputs diff --git a/src/estimagic/estimate_msm.py b/src/estimagic/estimate_msm.py index b989891f7..b850f5994 100644 --- a/src/estimagic/estimate_msm.py +++ b/src/estimagic/estimate_msm.py @@ -180,7 +180,7 @@ def estimate_msm( if jacobian_numdiff_options is not None: jacobian_numdiff_options = numdiff_options - deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] + deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ================================================================================== # Check and process inputs diff --git a/src/estimagic/estimation_table.py b/src/estimagic/estimation_table.py index 983e8ebf0..80928bcbb 100644 --- a/src/estimagic/estimation_table.py +++ b/src/estimagic/estimation_table.py @@ -952,7 +952,7 @@ def _customize_col_groups(default_col_groups, custom_col_groups): else: raise TypeError( f"""Invalid type for custom_col_groups. Can be either list - or dictionary, or NoneType. Not: {type(col_groups)}.""" # ty:ignore[unresolved-reference] + or dictionary, or NoneType. Not: {type(custom_col_groups)}.""" ) else: col_groups = default_col_groups @@ -988,8 +988,8 @@ def _customize_col_names(default_col_names, custom_col_names): col_names = custom_col_names else: raise TypeError( - f"""Invalid type for custom_col_names. - Can be either list or dictionary, or NoneType. Not: {col_names}.""" # ty:ignore[unresolved-reference] + f"""Invalid type for custom_col_names. Can be either list or + dictionary, or NoneType. Not: {type(custom_col_names)}.""" ) return col_names diff --git a/src/optimagic/config.py b/src/optimagic/config.py index 079236265..4eced1e4b 100644 --- a/src/optimagic/config.py +++ b/src/optimagic/config.py @@ -1,3 +1,4 @@ +import importlib.metadata import importlib.util from pathlib import Path @@ -59,7 +60,7 @@ def _is_installed(module_name: str) -> bool: # so if nevergrad is installed, bayes_opt will not work and vice-versa. IS_BAYESOPT_INSTALLED_AND_VERSION_NEWER_THAN_2 = ( _is_installed("bayes_opt") - and importlib.metadata.version("bayesian_optimization") > "2.0.0" # ty:ignore[possibly-missing-submodule] + and int(importlib.metadata.version("bayesian_optimization").split(".")[0]) >= 2 ) IS_GRADIENT_FREE_OPTIMIZERS_INSTALLED = _is_installed("gradient_free_optimizers") IS_PYGAD_INSTALLED = _is_installed("pygad") diff --git a/src/optimagic/deprecations.py b/src/optimagic/deprecations.py index 2067f7304..7b6219298 100644 --- a/src/optimagic/deprecations.py +++ b/src/optimagic/deprecations.py @@ -1,5 +1,6 @@ import logging import warnings +from collections.abc import Sequence from dataclasses import dataclass, replace from functools import wraps from pathlib import Path @@ -384,7 +385,10 @@ def throw_key_warning_in_derivatives(): def throw_dict_constraints_future_warning_if_required( - constraints: list[dict[str, Any]] | dict[str, Any], + constraints: Constraint + | dict[str, Any] + | Sequence[Constraint | dict[str, Any]] + | None, ) -> None: replacements = { "fixed": "optimagic.FixedConstraint", @@ -399,12 +403,13 @@ def throw_dict_constraints_future_warning_if_required( "nonlinear": "optimagic.NonlinearConstraint", } - if not isinstance(constraints, list): - constraints = [constraints] + candidates: list[Any] = ( + list(constraints) if isinstance(constraints, Sequence) else [constraints] + ) types_or_none = [ constraint.get("type", None) if isinstance(constraint, dict) else None - for constraint in constraints + for constraint in candidates ] types = [t for t in types_or_none if t is not None] @@ -575,7 +580,10 @@ def handle_log_options_throw_deprecated_warning( def pre_process_constraints( - constraints: list[Constraint | dict[str, Any]] | Constraint | dict[str, Any] | None, + constraints: Constraint + | dict[str, Any] + | Sequence[Constraint | dict[str, Any]] + | None, ) -> list[Constraint]: """Convert all ways of specifying constraints to a list of Constraint objects. @@ -589,27 +597,12 @@ def pre_process_constraints( if constraints is None: return [] + # The types of the elements are validated below. + candidates: list[Any] if isinstance(constraints, dict | Constraint): - constraints = [constraints] - - if isinstance(constraints, list): - out = [] - invalid_types: list[type] = [] - for constr in constraints: - if isinstance(constr, Constraint): - out.append(constr) - elif isinstance(constr, dict): - out.append(_constraint_from_dict(constr)) - else: - invalid_types.append(type(constr)) - - if invalid_types: - msg = ( - f"Invalid constraint types: {set(invalid_types)}. Must be a constraint " - "object imported from `optimagic`." - ) - raise InvalidConstraintError(msg) - + candidates = [constraints] + elif isinstance(constraints, Sequence) and not isinstance(constraints, str): + candidates = list(constraints) else: msg = ( f"Invalid constraint type: {type(constraints)}. Must be a constraint " @@ -619,6 +612,23 @@ def pre_process_constraints( ) raise InvalidConstraintError(msg) + out = [] + invalid_types: list[type] = [] + for constr in candidates: + if isinstance(constr, Constraint): + out.append(constr) + elif isinstance(constr, dict): + out.append(_constraint_from_dict(constr)) + else: + invalid_types.append(type(constr)) + + if invalid_types: + msg = ( + f"Invalid constraint types: {set(invalid_types)}. Must be a constraint " + "object imported from `optimagic`." + ) + raise InvalidConstraintError(msg) + return out diff --git a/src/optimagic/optimization/optimize.py b/src/optimagic/optimization/optimize.py index a98203885..cf59f9950 100644 --- a/src/optimagic/optimization/optimize.py +++ b/src/optimagic/optimization/optimize.py @@ -72,7 +72,7 @@ FunType = Callable[..., float | PyTree | FunctionValue] AlgorithmType = str | Algorithm | Type[Algorithm] -ConstraintsType = Constraint | list[Constraint] | dict[str, Any] | list[dict[str, Any]] +ConstraintsType = Constraint | dict[str, Any] | Sequence[Constraint | dict[str, Any]] JacType = Callable[..., PyTree] FunAndJacType = Callable[..., tuple[float | PyTree | FunctionValue, PyTree]] HessType = Callable[..., PyTree] diff --git a/src/optimagic/optimizers/_pounders/pounders_history.py b/src/optimagic/optimizers/_pounders/pounders_history.py index eb71fb4e3..d890af355 100644 --- a/src/optimagic/optimizers/_pounders/pounders_history.py +++ b/src/optimagic/optimizers/_pounders/pounders_history.py @@ -250,9 +250,6 @@ def get_best_residuals(self): def get_best_critval(self): return self.get_critvals(index=self.best_index) - def get_best_centered_entries(self, center_info): - return self.get_centered_entries(self, center_info, index=self.best_index) # ty:ignore[parameter-already-assigned] - def _add_entries_to_array(arr, new, position): if arr is None: diff --git a/src/optimagic/parameters/constraint_tools.py b/src/optimagic/parameters/constraint_tools.py index ad779ef7a..7bf2f8eeb 100644 --- a/src/optimagic/parameters/constraint_tools.py +++ b/src/optimagic/parameters/constraint_tools.py @@ -35,7 +35,7 @@ def count_free_params( upper_bounds=upper_bounds, ) - deprecations.throw_dict_constraints_future_warning_if_required(constraints) # ty:ignore[invalid-argument-type] + deprecations.throw_dict_constraints_future_warning_if_required(constraints) bounds = pre_process_bounds(bounds) constraints = deprecations.pre_process_constraints(constraints) diff --git a/src/optimagic/parameters/constraints/resolution.py b/src/optimagic/parameters/constraints/resolution.py index 713ba99d3..ec787d4e9 100644 --- a/src/optimagic/parameters/constraints/resolution.py +++ b/src/optimagic/parameters/constraints/resolution.py @@ -17,6 +17,7 @@ import warnings from collections import Counter +from collections.abc import Sequence from dataclasses import dataclass from typing import Any, Callable @@ -98,7 +99,7 @@ def _fail_if_duplicates(self, index: IntArray) -> None: def resolve_constraints( - constraints: list[Constraint], + constraints: Sequence[Constraint], params: PyTree, tree_converter: TreeConverter, param_names: list[str], diff --git a/src/optimagic/visualization/history_plots.py b/src/optimagic/visualization/history_plots.py index e86d4cddf..3fe4483fc 100644 --- a/src/optimagic/visualization/history_plots.py +++ b/src/optimagic/visualization/history_plots.py @@ -1,5 +1,6 @@ import inspect import itertools +from collections.abc import Mapping, Sequence from dataclasses import dataclass from pathlib import Path from typing import Any, Callable, Literal @@ -44,7 +45,7 @@ def criterion_plot( - results: ResultOrPath | list[ResultOrPath] | dict[str, ResultOrPath], + results: ResultOrPath | Sequence[ResultOrPath] | Mapping[Any, ResultOrPath], names: list[str] | str | None = None, max_evaluations: int | None = None, backend: Literal["plotly", "matplotlib", "bokeh", "altair"] = "plotly", @@ -118,7 +119,7 @@ def criterion_plot( def _harmonize_inputs_to_dict( - results: ResultOrPath | list[ResultOrPath] | dict[str, ResultOrPath], + results: ResultOrPath | Sequence[ResultOrPath] | Mapping[Any, ResultOrPath], names: list[str] | str | None, ) -> dict[str, ResultOrPath]: """Convert all valid inputs for results and names to dict[str, OptimizeResult].""" @@ -133,11 +134,10 @@ def _harmonize_inputs_to_dict( raise ValueError("len(results) needs to be equal to len(names).") # handle dict case - if isinstance(results, dict): + if isinstance(results, Mapping): + results_dict = dict(results) if names is not None: - results_dict = dict(zip(names, list(results.values()), strict=False)) - else: - results_dict = results + results_dict = dict(zip(names, results_dict.values(), strict=False)) # unlabeled iterable of results else: diff --git a/tests/estimagic/test_estimation_table.py b/tests/estimagic/test_estimation_table.py index 2c6c98bfb..d7ea830e2 100644 --- a/tests/estimagic/test_estimation_table.py +++ b/tests/estimagic/test_estimation_table.py @@ -433,6 +433,18 @@ def test_customize_col_names_list(): assert exp == res +def test_customize_col_groups_invalid_type(): + default = ["a_name", "a_name", "third_name"] + with pytest.raises(TypeError, match="Invalid type for custom_col_groups"): + _customize_col_groups(default, "invalid") + + +def test_customize_col_names_invalid_type(): + default = list("abc") + with pytest.raises(TypeError, match="Invalid type for custom_col_names"): + _customize_col_names(default_col_names=default, custom_col_names="invalid") + + def test_get_params_frames_with_common_index(): m1 = { "params": pd.DataFrame(np.ones(5), index=list("abcde")), diff --git a/tests/optimagic/optimization/test_with_advanced_constraints.py b/tests/optimagic/optimization/test_with_advanced_constraints.py index b30459652..df3372199 100644 --- a/tests/optimagic/optimization/test_with_advanced_constraints.py +++ b/tests/optimagic/optimization/test_with_advanced_constraints.py @@ -62,7 +62,7 @@ def test_with_covariance_constraint_bounds_distance(derivative, constr_name): params=params, algorithm="scipy_lbfgsb", jac=derivative, - constraints=CONSTR_INFO[constr_name], # ty:ignore[invalid-argument-type] + constraints=CONSTR_INFO[constr_name], ) assert res.success, "scipy_lbfgsb did not converge." diff --git a/tests/optimagic/optimization/test_with_constraints.py b/tests/optimagic/optimization/test_with_constraints.py index 2a6d103e4..0f76dfd88 100644 --- a/tests/optimagic/optimization/test_with_constraints.py +++ b/tests/optimagic/optimization/test_with_constraints.py @@ -239,7 +239,7 @@ def test_three_independent_constraints(): fun=lambda x: x @ x, params=params, algorithm="scipy_lbfgsb", - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, algo_options={"convergence.ftol_rel": 1e-12}, ) expected = np.array([0] * 4 + [4, 5] + [0] + [7.5] * 2 + [0]) @@ -250,6 +250,21 @@ def test_three_independent_constraints(): aaae(res.params, expected, decimal=3) +def test_constraints_as_tuple(): + constraints = ( + om.FixedConstraint(lambda x: x[[0]]), + om.IncreasingConstraint(lambda x: x[[1, 2]]), + ) + + res = minimize( + fun=lambda x: x @ x, + params=np.array([1.0, 2.0, 3.0]), + algorithm="scipy_lbfgsb", + constraints=constraints, + ) + aaae(res.params, [1, 0, 0], decimal=4) + + INVALID_CONSTRAINT_COMBIS = [ [ om.FlatCovConstraint(lambda x: x[[1, 0, 2]]), @@ -325,7 +340,7 @@ def selector(x, loc=loc): fun=lambda x: x @ x, params=np.array([0.1, 0.9, 0.9, 0.1]), algorithm="scipy_lbfgsb", - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, ) aaae(res.params, [0.5] * 4) diff --git a/tests/optimagic/parameters/constraints/test_resolution.py b/tests/optimagic/parameters/constraints/test_resolution.py index 88603fe0d..48087214b 100644 --- a/tests/optimagic/parameters/constraints/test_resolution.py +++ b/tests/optimagic/parameters/constraints/test_resolution.py @@ -83,7 +83,7 @@ def test_tree_selectors_pairwise(tree_params, tree_params_converter): om.PairwiseEqualityConstraint(selectors=[lambda x: x[1], lambda x: x[0][1][0]]) ] calculated = resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=tree_params, tree_converter=tree_params_converter, param_names=PARAM_NAMES, @@ -110,7 +110,7 @@ def test_provenance_is_attached(np_params_converter): om.EqualityConstraint(selector=lambda x: x[[1, 2]]), ] calculated = resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -132,7 +132,7 @@ def test_empty_selections_are_dropped(np_params_converter): ), ] calculated = resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -144,7 +144,7 @@ def test_duplicates_raise(np_params_converter): constraints = [om.EqualityConstraint(selector=lambda x: x[[0, 0, 1]])] with pytest.raises(InvalidConstraintError, match="duplicates"): resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -155,7 +155,7 @@ def test_failing_selector_raises_invalid_constraint_error(np_params_converter): constraints = [om.FixedConstraint(selector=lambda x: x["invalid"])] with pytest.raises(InvalidConstraintError, match="select parameters"): resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, @@ -178,7 +178,7 @@ def test_to_legacy_dicts_shapes(np_params_converter): om.LinearConstraint(selector=lambda x: x[[4, 5]], weights=1, upper_bound=5), ] resolved = resolve_constraints( - constraints=constraints, # ty:ignore[invalid-argument-type] + constraints=constraints, params=np.arange(6) + 10.0, tree_converter=np_params_converter, param_names=PARAM_NAMES, diff --git a/tests/optimagic/test_deprecations.py b/tests/optimagic/test_deprecations.py index 511342356..a21bd0fbd 100644 --- a/tests/optimagic/test_deprecations.py +++ b/tests/optimagic/test_deprecations.py @@ -160,8 +160,7 @@ def _crit(params): def test_estimagic_log_reader_is_deprecated(example_db): - msg = "OptimizeLogReader is deprecated and will be removed in a future " - "version. Please use optimagic.logging.SQLiteLogger instead." + msg = "estimagic.OptimizeLogReader has been deprecated" with pytest.warns(FutureWarning, match=msg): OptimizeLogReader(example_db) @@ -1082,7 +1081,19 @@ def test_pre_process_constraints_list_of_constraints(dummy_func): om.FixedConstraint(selector=dummy_func), om.IncreasingConstraint(selector=dummy_func), ] - assert pre_process_constraints(constraints) == expected # ty:ignore[invalid-argument-type] + assert pre_process_constraints(constraints) == expected + + +def test_pre_process_constraints_tuple_of_constraints(dummy_func): + constraints = ( + om.FixedConstraint(selector=dummy_func), + {"type": "increasing", "selector": dummy_func}, + ) + expected = [ + om.FixedConstraint(selector=dummy_func), + om.IncreasingConstraint(selector=dummy_func), + ] + assert pre_process_constraints(constraints) == expected def test_pre_process_constraints_none_case(): @@ -1098,7 +1109,7 @@ def test_pre_process_constraints_mixed_case(dummy_func): om.FixedConstraint(selector=dummy_func), om.IncreasingConstraint(selector=dummy_func), ] - assert pre_process_constraints(constraints) == expected # ty:ignore[invalid-argument-type] + assert pre_process_constraints(constraints) == expected def test_pre_process_constraints_dict_case(dummy_func): @@ -1427,7 +1438,7 @@ def test_different_lengths_in_locs_raise(): def test_deprecated_log_reader(example_db): with pytest.warns(FutureWarning, match="SQLiteLogReader"): reader = OptimizeLogReader(example_db) - res = reader.read_start_params() # ty:ignore[unresolved-attribute] + res = reader.read_start_params() assert res == {"a": 1, "b": 2, "c": 3} diff --git a/tests/optimagic/visualization/test_history_plots.py b/tests/optimagic/visualization/test_history_plots.py index 937926e2a..9cd52670e 100644 --- a/tests/optimagic/visualization/test_history_plots.py +++ b/tests/optimagic/visualization/test_history_plots.py @@ -134,11 +134,11 @@ def test_criterion_plot_different_input_types(): results = ["test.db", res] - criterion_plot(results) # ty:ignore[invalid-argument-type] - criterion_plot(results, monotone=True) # ty:ignore[invalid-argument-type] - criterion_plot(results, stack_multistart=True) # ty:ignore[invalid-argument-type] - criterion_plot(results, monotone=True, stack_multistart=True) # ty:ignore[invalid-argument-type] - criterion_plot(results, show_exploration=True) # ty:ignore[invalid-argument-type] + criterion_plot(results) + criterion_plot(results, monotone=True) + criterion_plot(results, stack_multistart=True) + criterion_plot(results, monotone=True, stack_multistart=True) + criterion_plot(results, show_exploration=True) criterion_plot("test.db") @@ -175,16 +175,22 @@ def test_harmonize_inputs_to_dict_single_result_with_name(): def test_harmonize_inputs_to_dict_list_results(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = [res, res] - assert _harmonize_inputs_to_dict(results=results, names=None) == { # ty:ignore[invalid-argument-type] + assert _harmonize_inputs_to_dict(results=results, names=None) == { "0": res, "1": res, } +def test_harmonize_inputs_to_dict_tuple_results(): + res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") + got = _harmonize_inputs_to_dict(results=(res, res), names=["a", "b"]) + assert got == {"a": res, "b": res} + + def test_harmonize_inputs_to_dict_dict_input(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = {"bla": res, om.algos.scipy_lbfgsb(): res, om.algos.scipy_neldermead: res} - got = _harmonize_inputs_to_dict(results=results, names=None) # ty:ignore[invalid-argument-type] + got = _harmonize_inputs_to_dict(results=results, names=None) expected = {"bla": res, "scipy_lbfgsb": res, "scipy_neldermead": res} assert got == expected @@ -192,7 +198,7 @@ def test_harmonize_inputs_to_dict_dict_input(): def test_harmonize_inputs_to_dict_dict_input_with_names(): res = minimize(fun=lambda x: x @ x, params=np.arange(5), algorithm="scipy_lbfgsb") results = {"bla": res, "blub": res} - got = _harmonize_inputs_to_dict(results=results, names=["a", "b"]) # ty:ignore[invalid-argument-type] + got = _harmonize_inputs_to_dict(results=results, names=["a", "b"]) expected = {"a": res, "b": res} assert got == expected From 584fd44986928ed8c3be9031b10bb6073737c41e Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Fri, 25 Sep 2026 18:40:55 +0200 Subject: [PATCH 09/15] Reinstall optimagic in algo selection hook env on every run; note ty in EP-02 The hook installed optimagic only if it was not importable, so dependencies added later (e.g. optree in #679) were never installed and the hook failed with ModuleNotFoundError for existing hook environments. Co-Authored-By: Claude Opus 5.5 --- .tools/update_algo_selection_hook.py | 10 +++++----- docs/source/development/ep-02-typing.md | 7 +++++++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/.tools/update_algo_selection_hook.py b/.tools/update_algo_selection_hook.py index 91715414d..b5d5f0dbd 100644 --- a/.tools/update_algo_selection_hook.py +++ b/.tools/update_algo_selection_hook.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -import importlib.util import subprocess import sys from pathlib import Path @@ -15,13 +14,14 @@ def run(cmd: list[str], **kwargs: Any) -> None: subprocess.check_call(cmd, cwd=ROOT, **kwargs) -def ensure_optimagic_is_locally_installed() -> None: - if importlib.util.find_spec("optimagic") is None: - run(["uv", "pip", "install", "--python", sys.executable, "-e", "."]) +def install_optimagic_locally() -> None: + # Always (re)install so that dependencies added after the hook environment was + # created are picked up. This is fast if nothing changed. + run(["uv", "pip", "install", "--quiet", "--python", sys.executable, "-e", "."]) def main() -> int: - ensure_optimagic_is_locally_installed() + install_optimagic_locally() run(PYTHON + [".tools/create_algo_selection_code.py"]) ruff_args = [ diff --git a/docs/source/development/ep-02-typing.md b/docs/source/development/ep-02-typing.md index dd9af67e4..0d8c2dcb3 100644 --- a/docs/source/development/ep-02-typing.md +++ b/docs/source/development/ep-02-typing.md @@ -1653,6 +1653,13 @@ access to currently internal objects such as the MSM objective function. We choose mypy as static type checker and run it as part of our continuous integration. +```{note} +We have since replaced mypy by [ty](https://docs.astral.sh/ty/). ty is much faster and +also checks the bodies of unannotated functions and our tests. Its configuration lives +in the `[tool.ty]` section of `pyproject.toml`. The mypy settings below are kept for +reference. +``` + Once this enhancement proposal is fully implemented, we want to use the following settings: From c0d945bf2d7cff6ce380153456a3b2250bed6c76 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Fri, 25 Sep 2026 18:44:55 +0200 Subject: [PATCH 10/15] Narrow optional results in tests instead of ignoring ty errors Assert that optional attributes such as res.history and res.multistart_info are not None (or isinstance for resolved constraints) before using them. Co-Authored-By: Claude Opus 5.5 --- tests/optimagic/optimization/test_callback.py | 3 ++- .../optimization/test_convergence_report.py | 8 ++++++-- .../optimization/test_history_collection.py | 10 ++++++---- .../optimization/test_with_multistart.py | 19 +++++++++++-------- .../optimizers/test_iminuit_migrad.py | 4 ++-- tests/optimagic/parameters/test_bounds.py | 11 +++++++---- .../parameters/test_scale_conversion.py | 6 ++++-- tests/optimagic/test_constraints.py | 15 +++++++++------ tests/optimagic/test_deprecations.py | 3 ++- .../visualization/test_history_plots.py | 15 +++++++++------ 10 files changed, 58 insertions(+), 36 deletions(-) diff --git a/tests/optimagic/optimization/test_callback.py b/tests/optimagic/optimization/test_callback.py index 7685c65c3..16fe86004 100644 --- a/tests/optimagic/optimization/test_callback.py +++ b/tests/optimagic/optimization/test_callback.py @@ -103,7 +103,8 @@ def test_callback_not_called_on_jac(): ) aae(xs, [np.arange(3) + 2.0]) - assert len(res.history.params) == 3 # ty:ignore[unresolved-attribute] + assert res.history is not None + assert len(res.history.params) == 3 def test_invalid_callback_too_few_arguments(): diff --git a/tests/optimagic/optimization/test_convergence_report.py b/tests/optimagic/optimization/test_convergence_report.py index a6de220b1..d3c0c3a7a 100644 --- a/tests/optimagic/optimization/test_convergence_report.py +++ b/tests/optimagic/optimization/test_convergence_report.py @@ -18,7 +18,9 @@ def test_get_convergence_report_minimize(): batches=[0, 1, 2, 3], ) - calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) # ty:ignore[invalid-argument-type] + report = get_convergence_report(hist) + assert report is not None + calculated = pd.DataFrame.from_dict(report) expected = np.array([[0.025, 0.25], [0.05, 1.0], [0.1, 1], [0.1, 2.0]]) aaae(calculated.to_numpy(), expected) @@ -35,7 +37,9 @@ def test_get_convergence_report_maximize(): batches=[0, 1, 2, 3], ) - calculated = pd.DataFrame.from_dict(get_convergence_report(hist)) # ty:ignore[invalid-argument-type] + report = get_convergence_report(hist) + assert report is not None + calculated = pd.DataFrame.from_dict(report) expected = np.array([[0.025, 0.25], [0.05, 1.0], [0.1, 1], [0.1, 2.0]]) aaae(calculated.to_numpy(), expected) diff --git a/tests/optimagic/optimization/test_history_collection.py b/tests/optimagic/optimization/test_history_collection.py index e5fbfa7ad..c51a94d4e 100644 --- a/tests/optimagic/optimization/test_history_collection.py +++ b/tests/optimagic/optimization/test_history_collection.py @@ -53,7 +53,8 @@ def test_history_collection_with_parallelization(algorithm, tmp_path): log_hist = reader.read_history() # We cannot expect the order to be the same - aaae(sorted(collected_hist.fun), sorted(log_hist.fun)) # ty:ignore[unresolved-attribute] + assert collected_hist is not None + aaae(sorted(collected_hist.fun), sorted(log_hist.fun)) @mark.minimizer( @@ -147,9 +148,10 @@ def test_history_collection_with_dummy_optimizer(n_cores, batch_size): ) got_history = res.history + assert got_history is not None expected_history = _get_fake_history(batch_size) - aae(got_history.batches, expected_history["batches"]) # ty:ignore[unresolved-attribute] - assert got_history.fun == expected_history["criterion"][: len(got_history.fun)] # ty:ignore[unresolved-attribute] - aaae(got_history.params, expected_history["params"][: len(got_history.params)]) # ty:ignore[unresolved-attribute] + aae(got_history.batches, expected_history["batches"]) + assert got_history.fun == expected_history["criterion"][: len(got_history.fun)] + aaae(got_history.params, expected_history["params"][: len(got_history.params)]) diff --git a/tests/optimagic/optimization/test_with_multistart.py b/tests/optimagic/optimization/test_with_multistart.py index d415d1d92..f6007c665 100644 --- a/tests/optimagic/optimization/test_with_multistart.py +++ b/tests/optimagic/optimization/test_with_multistart.py @@ -79,12 +79,13 @@ def test_multistart_optimization_with_sum_of_squares_at_defaults( assert hasattr(res, "multistart_info") ms_info = res.multistart_info - assert len(ms_info.exploration_sample) == 400 # ty:ignore[unresolved-attribute] - assert isinstance(ms_info.exploration_results, list) # ty:ignore[unresolved-attribute] - assert len(ms_info.exploration_results) == 400 # ty:ignore[unresolved-attribute] - assert all(isinstance(entry, float) for entry in ms_info.exploration_results) # ty:ignore[unresolved-attribute] - assert all(isinstance(entry, OptimizeResult) for entry in ms_info.local_optima) # ty:ignore[unresolved-attribute] - assert all(isinstance(entry, pd.DataFrame) for entry in ms_info.start_parameters) # ty:ignore[unresolved-attribute] + assert ms_info is not None + assert len(ms_info.exploration_sample) == 400 + assert isinstance(ms_info.exploration_results, list) + assert len(ms_info.exploration_results) == 400 + assert all(isinstance(entry, float) for entry in ms_info.exploration_results) + assert all(isinstance(entry, OptimizeResult) for entry in ms_info.local_optima) + assert all(isinstance(entry, pd.DataFrame) for entry in ms_info.start_parameters) assert np.allclose(res.fun, 0) aaae(res.params["value"], np.zeros(4)) @@ -100,11 +101,12 @@ def test_multistart_with_existing_sample(params): multistart=options, ) + assert res.multistart_info is not None assert all( got.equals(expected) for expected, got in zip( sample, - res.multistart_info.exploration_sample, # ty:ignore[unresolved-attribute] + res.multistart_info.exploration_sample, strict=False, ) ) @@ -123,7 +125,8 @@ def test_convergence_via_max_discoveries_works(params): multistart=options, ) - assert len(res.multistart_info.local_optima) == 2 # ty:ignore[unresolved-attribute] + assert res.multistart_info is not None + assert len(res.multistart_info.local_optima) == 2 def test_steps_are_logged_as_skipped_if_convergence(tmp_path, params): diff --git a/tests/optimagic/optimizers/test_iminuit_migrad.py b/tests/optimagic/optimizers/test_iminuit_migrad.py index 848f8e6e8..89dc56a4e 100644 --- a/tests/optimagic/optimizers/test_iminuit_migrad.py +++ b/tests/optimagic/optimizers/test_iminuit_migrad.py @@ -91,5 +91,5 @@ def test_iminuit_migrad(): assert res.success aaae(res.x, np.zeros(3), decimal=6) - assert res.n_fun_evals > 0 # ty:ignore[unsupported-operator] - assert res.n_jac_evals > 0 # ty:ignore[unsupported-operator] + assert res.n_fun_evals is not None and res.n_fun_evals > 0 + assert res.n_jac_evals is not None and res.n_jac_evals > 0 diff --git a/tests/optimagic/parameters/test_bounds.py b/tests/optimagic/parameters/test_bounds.py index fb87da9ed..a6c3f487a 100644 --- a/tests/optimagic/parameters/test_bounds.py +++ b/tests/optimagic/parameters/test_bounds.py @@ -42,8 +42,9 @@ def test_pre_process_bounds_none_case(): def test_pre_process_bounds_sequence(): got = pre_process_bounds([(0, 1), (None, 1)]) expected = Bounds(lower=[0, -np.inf], upper=[1, 1]) - assert_array_equal(got.lower, expected.lower) # ty:ignore[unresolved-attribute] - assert_array_equal(got.upper, expected.upper) # ty:ignore[unresolved-attribute] + assert got is not None + assert_array_equal(got.lower, expected.lower) + assert_array_equal(got.upper, expected.upper) def test_pre_process_bounds_invalid_type(): @@ -64,8 +65,10 @@ def test_get_bounds_subdataframe(pytree_params): lb, ub = get_internal_bounds(pytree_params, bounds=bounds) - assert np.all(lb[1:3] == np.ones(2)) # ty:ignore[not-subscriptable] - assert np.all(ub[2:4] == 2 * np.ones(2)) # ty:ignore[not-subscriptable] + assert lb is not None + assert ub is not None + assert np.all(lb[1:3] == np.ones(2)) + assert np.all(ub[2:4] == 2 * np.ones(2)) TEST_CASES = [ diff --git a/tests/optimagic/parameters/test_scale_conversion.py b/tests/optimagic/parameters/test_scale_conversion.py index 58b577c2b..c7fdd9cc9 100644 --- a/tests/optimagic/parameters/test_scale_conversion.py +++ b/tests/optimagic/parameters/test_scale_conversion.py @@ -47,8 +47,10 @@ def test_get_scale_converter_active(method, expected): ) aaae(scaled.values, expected.values) - aaae(scaled.lower_bounds, expected.lower_bounds) # ty:ignore[invalid-argument-type] - aaae(scaled.upper_bounds, expected.upper_bounds) # ty:ignore[invalid-argument-type] + assert scaled.lower_bounds is not None + assert scaled.upper_bounds is not None + aaae(scaled.lower_bounds, expected.lower_bounds) + aaae(scaled.upper_bounds, expected.upper_bounds) aaae(converter.params_to_internal(params.values), expected.values) aaae(converter.params_from_internal(expected.values), params.values) diff --git a/tests/optimagic/test_constraints.py b/tests/optimagic/test_constraints.py index e466c4488..b45b126f7 100644 --- a/tests/optimagic/test_constraints.py +++ b/tests/optimagic/test_constraints.py @@ -257,7 +257,8 @@ def test_resolve_empty_selection_returns_none(constraint): def test_resolve_fixed_constraint_has_no_explicit_value(): constr = FixedConstraint(selector=lambda x: x[[0, 2]]) resolved = constr._resolve(make_context(constr)) - assert resolved.value is None # ty:ignore[unresolved-attribute] + assert isinstance(resolved, ResolvedFixedConstraint) + assert resolved.value is None def test_resolve_pairwise_equality_constraint(): @@ -306,16 +307,18 @@ def test_resolve_linear_constraint_aligns_weight_sequence(): selector=lambda x: x[[0, 2, 4]], weights=[1, 2, 3], upper_bound=5 ) resolved = constr._resolve(make_context(constr)) - aae(resolved.index, np.array([0, 2, 4])) # ty:ignore[unresolved-attribute] - aae(resolved.weights, np.array([1.0, 2.0, 3.0])) # ty:ignore[unresolved-attribute] + assert isinstance(resolved, ResolvedLinearConstraint) + aae(resolved.index, np.array([0, 2, 4])) + aae(resolved.weights, np.array([1.0, 2.0, 3.0])) def test_resolve_linear_constraint_fills_absent_bounds_with_sentinels(): constr = LinearConstraint(selector=lambda x: x[[0, 2]], weights=1, lower_bound=1) resolved = constr._resolve(make_context(constr)) - assert resolved.lower_bound == 1 # ty:ignore[unresolved-attribute] - assert resolved.upper_bound == np.inf # ty:ignore[unresolved-attribute] - assert np.isnan(resolved.value) # ty:ignore[unresolved-attribute] + assert isinstance(resolved, ResolvedLinearConstraint) + assert resolved.lower_bound == 1 + assert resolved.upper_bound == np.inf + assert np.isnan(resolved.value) def test_resolve_linear_constraint_with_misaligned_weights_raises(): diff --git a/tests/optimagic/test_deprecations.py b/tests/optimagic/test_deprecations.py index a21bd0fbd..9f95ffd8d 100644 --- a/tests/optimagic/test_deprecations.py +++ b/tests/optimagic/test_deprecations.py @@ -705,8 +705,9 @@ def test_deprecated_dict_access_of_multistart_info(): bounds=om.Bounds(lower=np.full(3, -1), upper=np.full(3, 2)), ) msg = "The dictionary access for 'local_optima' is deprecated and will be removed" + assert res.multistart_info is not None with pytest.warns(FutureWarning, match=msg): - _ = res.multistart_info["local_optima"] # ty:ignore[not-subscriptable] + _ = res.multistart_info["local_optima"] def test_base_steps_in_first_derivatives_is_deprecated(): diff --git a/tests/optimagic/visualization/test_history_plots.py b/tests/optimagic/visualization/test_history_plots.py index 9cd52670e..924bd7248 100644 --- a/tests/optimagic/visualization/test_history_plots.py +++ b/tests/optimagic/visualization/test_history_plots.py @@ -40,8 +40,8 @@ def minimize_result(): multistart=( om.MultistartOptions(n_samples=1000, convergence_max_discoveries=5) if multistart - else None - ), # ty:ignore[invalid-argument-type] + else False + ), ) res.append(_res) out[multistart] = res @@ -222,7 +222,8 @@ def test_harmonize_inputs_to_dict_path_input(): def _compare_plotting_multistart_history_with_result( data: _PlottingMultistartHistory, res: om.OptimizeResult, res_name: str ): - assert_array_equal(data.history.fun, res.history.fun) # ty:ignore[unresolved-attribute] + assert res.history is not None + assert_array_equal(data.history.fun, res.history.fun) assert data.name == res_name assert_array_equal(data.start_params, res.start_params) assert data.is_multistart == (res.multistart_info is not None) @@ -278,12 +279,14 @@ def test_retrieve_data_from_multistart_result(minimize_result, stack_multistart) assert isinstance(data, list) and len(data) == 1 assert data[0].is_multistart - assert len(data[0].local_histories) == 5 # ty:ignore[invalid-argument-type] + assert data[0].local_histories is not None + assert len(data[0].local_histories) == 5 if stack_multistart: + assert data[0].stacked_local_histories is not None assert_array_equal( - data[0].stacked_local_histories.fun, # ty:ignore[unresolved-attribute] - np.concatenate([hist.fun for hist in data[0].local_histories]), # ty:ignore[not-iterable] + data[0].stacked_local_histories.fun, + np.concatenate([hist.fun for hist in data[0].local_histories]), ) else: assert data[0].stacked_local_histories is None From 8d6224174c601a9a459220ee0a94e808e2607e7d Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Fri, 25 Sep 2026 18:47:07 +0200 Subject: [PATCH 11/15] Fix small type errors instead of ignoring them - iminuit_migrad: name the start values x0 as in the Algorithm base class. - history: do not assume that the reduction function has a __name__. - get_benchmark_problems: annotate the mixed-type noise options. - deprecations: remove a redundant cast. - OptimizeResult: use dict instead of typing.Dict. - estimation_table: replace the deprecated np.testing.suppress_warnings by a decorator based on warnings.catch_warnings. - LeastSquaresHistory: annotate the lazily created arrays and raise a clear error when entries are requested before any were added. Co-Authored-By: Claude Opus 5.5 --- src/estimagic/estimation_table.py | 16 ++++++++-- .../benchmarking/get_benchmark_problems.py | 14 ++++++--- src/optimagic/deprecations.py | 4 +-- src/optimagic/optimization/history.py | 10 +++--- src/optimagic/optimization/optimize_result.py | 6 ++-- .../optimizers/_pounders/pounders_history.py | 31 +++++++++++++------ src/optimagic/optimizers/iminuit_migrad.py | 6 ++-- tests/estimagic/test_estimation_table.py | 15 ++++++++- .../_pounders/test_pounders_history.py | 16 ++++++++-- 9 files changed, 85 insertions(+), 33 deletions(-) diff --git a/src/estimagic/estimation_table.py b/src/estimagic/estimation_table.py index 80928bcbb..fc8f94275 100644 --- a/src/estimagic/estimation_table.py +++ b/src/estimagic/estimation_table.py @@ -1,6 +1,7 @@ import re +import warnings from copy import deepcopy -from functools import partial +from functools import partial, wraps from pathlib import Path from warnings import warn @@ -9,8 +10,17 @@ from optimagic.shared.compat import pd_df_map -suppress_performance_warnings = np.testing.suppress_warnings() # ty:ignore[deprecated] -suppress_performance_warnings.filter(category=pd.errors.PerformanceWarning) + +def suppress_performance_warnings(func): + """Suppress pandas PerformanceWarnings raised while calling func.""" + + @wraps(func) + def wrapper(*args, **kwargs): + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=pd.errors.PerformanceWarning) + return func(*args, **kwargs) + + return wrapper @suppress_performance_warnings diff --git a/src/optimagic/benchmarking/get_benchmark_problems.py b/src/optimagic/benchmarking/get_benchmark_problems.py index 211261e45..2986891ed 100644 --- a/src/optimagic/benchmarking/get_benchmark_problems.py +++ b/src/optimagic/benchmarking/get_benchmark_problems.py @@ -1,4 +1,5 @@ from functools import partial, wraps +from typing import Any import numpy as np @@ -328,7 +329,12 @@ def _sample_from_distribution(distribution, mean, std, size, rng, correlation=0) def _process_noise_options(options, is_multiplicative): options = {} if options is None else options - defaults = {"std": 0.01, "distribution": "normal", "correlation": 0, "mean": 0} + defaults: dict[str, Any] = { + "std": 0.01, + "distribution": "normal", + "correlation": 0, + "mean": 0, + } if is_multiplicative: defaults["clipping_value"] = 1 @@ -345,16 +351,16 @@ def _process_noise_options(options, is_multiplicative): ) std = processed["std"] - if std < 0: # ty:ignore[unsupported-operator] + if std < 0: raise ValueError(f"std must be non-negative. Not: {std}") corr = processed["correlation"] - if corr < 0: # ty:ignore[unsupported-operator] + if corr < 0: raise ValueError(f"corr must be non-negative. Not: {corr}") if is_multiplicative: clipping_value = processed["clipping_value"] - if clipping_value < 0: # ty:ignore[unsupported-operator] + if clipping_value < 0: raise ValueError( f"clipping_value must be non-negative. Not: {clipping_value}" ) diff --git a/src/optimagic/deprecations.py b/src/optimagic/deprecations.py index 7b6219298..81819395f 100644 --- a/src/optimagic/deprecations.py +++ b/src/optimagic/deprecations.py @@ -4,7 +4,7 @@ from dataclasses import dataclass, replace from functools import wraps from pathlib import Path -from typing import TYPE_CHECKING, Any, Callable, ParamSpec, cast +from typing import TYPE_CHECKING, Any, Callable, ParamSpec import numpy as np import pandas as pd @@ -568,7 +568,7 @@ def handle_log_options_throw_deprecated_warning( log_options = { k: v for k, v in log_options.items() if k != "if_table_exists" } - return SQLiteLogOptions(cast(str | Path, logger), **log_options) # ty:ignore[redundant-cast] + return SQLiteLogOptions(logger, **log_options) elif not log_options_is_compatible: raise ValueError( f"Found string or path for logger argument, but parameter" diff --git a/src/optimagic/optimization/history.py b/src/optimagic/optimization/history.py index 50ea6ddf5..c0cc7cafa 100644 --- a/src/optimagic/optimization/history.py +++ b/src/optimagic/optimization/history.py @@ -485,6 +485,8 @@ def _apply_reduction_to_batches( """ batch_starts, batch_stops = _get_batch_starts_and_stops(batch_ids) + func_name = getattr(reduction_function, "__name__", repr(reduction_function)) + batch_results: list[float] = [] for start, stop in zip(batch_starts, batch_stops, strict=True): @@ -498,9 +500,9 @@ def _apply_reduction_to_batches( reduced = reduction_function(batch_data) except Exception as e: msg = ( - f"Calling function {reduction_function.__name__} on batch {batch_id} " # ty:ignore[unresolved-attribute] + f"Calling function {func_name} on batch {batch_id} " "of the History raised an Exception. Please verify that " - f"{reduction_function.__name__} is well-defined, takes an iterable of " # ty:ignore[unresolved-attribute] + f"{func_name} is well-defined, takes an iterable of " "floats as input and returns a scalar. The function must be able to " "handle NaN's." ) @@ -508,8 +510,8 @@ def _apply_reduction_to_batches( if not np.isscalar(reduced): msg = ( - f"Function {reduction_function.__name__} did not return a scalar for " # ty:ignore[unresolved-attribute] - f"batch {batch_id}. Please verify that {reduction_function.__name__} " # ty:ignore[unresolved-attribute] + f"Function {func_name} did not return a scalar for " + f"batch {batch_id}. Please verify that {func_name} " "returns a scalar when called on an iterable of floats. The function " "must be able to handle NaN's." ) diff --git a/src/optimagic/optimization/optimize_result.py b/src/optimagic/optimization/optimize_result.py index feb71bc6d..231b491ef 100644 --- a/src/optimagic/optimization/optimize_result.py +++ b/src/optimagic/optimization/optimize_result.py @@ -1,6 +1,6 @@ import warnings from dataclasses import dataclass -from typing import Any, Dict, Optional +from typing import Any, Optional import numpy as np import pandas as pd @@ -61,10 +61,10 @@ class OptimizeResult: history: History | None = None - convergence_report: Dict | None = None # ty:ignore[unsupported-operator] + convergence_report: dict[str, Any] | None = None multistart_info: Optional["MultistartInfo"] = None - algorithm_output: Dict[str, Any] | None = None + algorithm_output: dict[str, Any] | None = None logger: LogReader | None = None # ================================================================================== diff --git a/src/optimagic/optimizers/_pounders/pounders_history.py b/src/optimagic/optimizers/_pounders/pounders_history.py index d890af355..50a6d190a 100644 --- a/src/optimagic/optimizers/_pounders/pounders_history.py +++ b/src/optimagic/optimizers/_pounders/pounders_history.py @@ -1,6 +1,7 @@ """History class for pounders and similar optimizers.""" import numpy as np +from numpy.typing import NDArray class LeastSquaresHistory: @@ -24,11 +25,13 @@ class LeastSquaresHistory: """ def __init__(self): - self.xs = None - self.best_x = None - self.residuals = None - self.best_residuals = None - self.critvals = None + # The arrays are created when the first entries are added because their + # shape is only known then. + self.xs: NDArray[np.float64] | None = None + self.best_x: NDArray[np.float64] | None = None + self.residuals: NDArray[np.float64] | None = None + self.best_residuals: NDArray[np.float64] | None = None + self.critvals: NDArray[np.float64] | None = None self.n_fun = 0 self.best_index = 0 self.best_critval = np.inf @@ -96,9 +99,9 @@ def get_entries(self, index=None): np.ndarray: Float or 1d array with criterion values. """ - names = ["xs", "residuals", "critvals"] + arrays = [self.xs, self.residuals, self.critvals] - out = (getattr(self, name)[: self.n_fun] for name in names) + out = (_get_first_n_entries(arr, self.n_fun) for arr in arrays) # Reducing arrays to length n_fun ensures that invalid indices raise IndexError if index is not None: @@ -117,7 +120,7 @@ def get_xs(self, index=None): np.ndarray: 1d or 2d array with parameter vectors """ - out = self.xs[: self.n_fun] # ty:ignore[not-subscriptable] + out = _get_first_n_entries(self.xs, self.n_fun) out = out[index] if index is not None else out return out @@ -133,7 +136,7 @@ def get_residuals(self, index=None): np.ndarray: 1d or 2d array with residuals. """ - out = self.residuals[: self.n_fun] # ty:ignore[not-subscriptable] + out = _get_first_n_entries(self.residuals, self.n_fun) out = out[index] if index is not None else out return out @@ -149,7 +152,7 @@ def get_critvals(self, index=None): np.ndarray: Float or 1d array with criterion values. """ - out = self.critvals[: self.n_fun] # ty:ignore[not-subscriptable] + out = _get_first_n_entries(self.critvals, self.n_fun) out = out[index] if index is not None else out return out @@ -251,6 +254,14 @@ def get_best_critval(self): return self.get_critvals(index=self.best_index) +def _get_first_n_entries( + arr: NDArray[np.float64] | None, n: int +) -> NDArray[np.float64]: + if arr is None: + raise ValueError("No entries have been added to the history yet.") + return arr[:n] + + def _add_entries_to_array(arr, new, position): if arr is None: shape = 100_000 if new.ndim == 1 else (100_000, new.shape[1]) diff --git a/src/optimagic/optimizers/iminuit_migrad.py b/src/optimagic/optimizers/iminuit_migrad.py index c8560b68d..666308e02 100644 --- a/src/optimagic/optimizers/iminuit_migrad.py +++ b/src/optimagic/optimizers/iminuit_migrad.py @@ -82,8 +82,8 @@ class IminuitMigrad(Algorithm): """ def _solve_internal_problem( - self, problem: InternalOptimizationProblem, params: NDArray[np.float64] - ) -> InternalOptimizeResult: # ty:ignore[invalid-method-override] + self, problem: InternalOptimizationProblem, x0: NDArray[np.float64] + ) -> InternalOptimizeResult: if not IS_IMINUIT_INSTALLED: raise NotInstalledError( # pragma: no cover "To use the 'iminuit_migrad` optimizer you need to install iminuit. " @@ -96,7 +96,7 @@ def _solve_internal_problem( def wrapped_objective(x: NDArray[np.float64]) -> float: return float(problem.fun(x)) - m = Minuit(wrapped_objective, params, grad=problem.jac) + m = Minuit(wrapped_objective, x0, grad=problem.jac) bounds = _convert_bounds_to_minuit_limits( problem.bounds.lower, problem.bounds.upper diff --git a/tests/estimagic/test_estimation_table.py b/tests/estimagic/test_estimation_table.py index d7ea830e2..4c4351e3b 100644 --- a/tests/estimagic/test_estimation_table.py +++ b/tests/estimagic/test_estimation_table.py @@ -1,5 +1,6 @@ import io import textwrap +import warnings import numpy as np import pandas as pd @@ -27,6 +28,7 @@ estimation_table, render_html, render_latex, + suppress_performance_warnings, ) @@ -134,7 +136,7 @@ def test_estimation_table(): _get_models_multiindex_multi_column(), ] PARAMETRIZATION = [("latex", render_latex, models) for models in MODELS] -PARAMETRIZATION += [("html", render_html, models) for models in MODELS] # ty:ignore[unsupported-operator] +PARAMETRIZATION += [("html", render_html, models) for models in MODELS] @pytest.mark.parametrize("return_type, render_func,models", PARAMETRIZATION) @@ -507,3 +509,14 @@ def test_manual_extra_info(): for i, r in footer.iterrows(): res = _center_align_integers_and_non_numeric_strings(r) ase(exp.loc[i], res) + + +def test_suppress_performance_warnings(): + @suppress_performance_warnings + def raise_performance_warning(): + warnings.warn("slow", pd.errors.PerformanceWarning) + return 1 + + with warnings.catch_warnings(): + warnings.simplefilter("error") + assert raise_performance_warning() == 1 diff --git a/tests/optimagic/optimizers/_pounders/test_pounders_history.py b/tests/optimagic/optimizers/_pounders/test_pounders_history.py index ffaa28230..bd8bd69de 100644 --- a/tests/optimagic/optimizers/_pounders/test_pounders_history.py +++ b/tests/optimagic/optimizers/_pounders/test_pounders_history.py @@ -74,9 +74,12 @@ def test_add_entries_initialized_with_space(entries, is_center): def test_add_entries_initialized_extension_needed(): history = LeastSquaresHistory() history.add_entries(np.ones((4, 3)), np.zeros((4, 5))) - history.xs = history.xs[:5] # ty:ignore[not-subscriptable] - history.residuals = history.residuals[:5] # ty:ignore[not-subscriptable] - history.critvals = history.critvals[:5] # ty:ignore[not-subscriptable] + assert history.xs is not None + assert history.residuals is not None + assert history.critvals is not None + history.xs = history.xs[:5] + history.residuals = history.residuals[:5] + history.critvals = history.critvals[:5] history.add_entries(np.arange(12).reshape(4, 3), np.arange(20).reshape(4, 5)) @@ -131,3 +134,10 @@ def test_get_centered_entries(): aaae(residuals, np.arange(1, -4, -1)) assert critvals == 15 assert history.get_n_fun() == 4 + + +@pytest.mark.parametrize("getter", ["get_entries", "get_xs", "get_residuals"]) +def test_get_entries_from_empty_history_raises(getter): + history = LeastSquaresHistory() + with pytest.raises(ValueError, match="No entries have been added"): + getattr(history, getter)() From 9a51e4fc466260e530a7f4f5bdecb041fc10c571 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Fri, 25 Sep 2026 18:53:43 +0200 Subject: [PATCH 12/15] Declare __algo_info__ and _problem_type instead of ignoring ty errors - Algorithm declares __algo_info__ as a ClassVar defaulting to None, and AlgorithmMeta declares it for the class-level properties. This makes the hasattr checks unnecessary. - The mark decorators share one helper that sets _problem_type through a Protocol, so the returned function keeps the input type. Co-Authored-By: Claude Opus 5.5 --- .tools/create_algo_selection_code.py | 12 +++--- src/optimagic/mark.py | 54 +++++++++---------------- src/optimagic/optimization/algorithm.py | 27 ++++++++----- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/.tools/create_algo_selection_code.py b/.tools/create_algo_selection_code.py index 22e9340e0..1000ca64f 100644 --- a/.tools/create_algo_selection_code.py +++ b/.tools/create_algo_selection_code.py @@ -104,14 +104,14 @@ def _get_all_algorithms(modules: list[ModuleType]) -> dict[str, Type[Algorithm]] def _get_algorithms_in_module(module: ModuleType) -> dict[str, Type[Algorithm]]: """Collect all algorithms in a single module.""" candidate_dict = dict(inspect.getmembers(module, inspect.isclass)) - candidate_dict = { - k: v for k, v in candidate_dict.items() if hasattr(v, "__algo_info__") - } algos = {} for candidate in candidate_dict.values(): - name = candidate.algo_info.name # ty:ignore[unresolved-attribute] - if issubclass(candidate, Algorithm) and candidate is not Algorithm: - algos[name] = candidate + if ( + issubclass(candidate, Algorithm) + and candidate is not Algorithm + and candidate.__algo_info__ is not None + ): + algos[candidate.__algo_info__.name] = candidate return algos diff --git a/src/optimagic/mark.py b/src/optimagic/mark.py index cefd76a71..f6d7b7ec4 100644 --- a/src/optimagic/mark.py +++ b/src/optimagic/mark.py @@ -1,5 +1,5 @@ from functools import wraps -from typing import Any, Callable, ParamSpec, TypeVar, cast +from typing import Any, Callable, ParamSpec, Protocol, TypeVar, cast import pydantic @@ -16,57 +16,43 @@ ScalarFuncT = TypeVar("ScalarFuncT", bound=Callable[..., Any]) VectorFuncT = TypeVar("VectorFuncT", bound=Callable[..., Any]) +FuncT = TypeVar("FuncT", bound=Callable[..., Any]) def scalar(func: ScalarFuncT) -> ScalarFuncT: """Mark a function as a scalar function.""" - wrapper = func - try: - wrapper._problem_type = AggregationLevel.SCALAR # ty:ignore[unresolved-attribute] - except (KeyboardInterrupt, SystemExit): - raise - except Exception: - - @wraps(func) - def wrapper(*args, **kwargs): - return func(*args, **kwargs) - - wrapper._problem_type = AggregationLevel.SCALAR # ty:ignore[unresolved-attribute] - return wrapper # ty:ignore[invalid-return-type] + return _mark_problem_type(func, AggregationLevel.SCALAR) def least_squares(func: VectorFuncT) -> VectorFuncT: """Mark a function as a least squares function.""" - wrapper = func - try: - wrapper._problem_type = AggregationLevel.LEAST_SQUARES # ty:ignore[unresolved-attribute] - except (KeyboardInterrupt, SystemExit): - raise - except Exception: - - @wraps(func) - def wrapper(*args, **kwargs): - return func(*args, **kwargs) - - wrapper._problem_type = AggregationLevel.LEAST_SQUARES # ty:ignore[unresolved-attribute] - return wrapper # ty:ignore[invalid-return-type] + return _mark_problem_type(func, AggregationLevel.LEAST_SQUARES) def likelihood(func: VectorFuncT) -> VectorFuncT: """Mark a function as a likelihood function.""" - wrapper = func + return _mark_problem_type(func, AggregationLevel.LIKELIHOOD) + + +class _MarkedFunction(Protocol): + """A callable that carries the problem type set by the mark decorators.""" + + _problem_type: AggregationLevel + + +def _mark_problem_type(func: FuncT, problem_type: AggregationLevel) -> FuncT: + """Attach problem_type to func or, if that fails, to a wrapper around func.""" try: - wrapper._problem_type = AggregationLevel.LIKELIHOOD # ty:ignore[unresolved-attribute] - except (KeyboardInterrupt, SystemExit): - raise + cast(_MarkedFunction, func)._problem_type = problem_type except Exception: @wraps(func) - def wrapper(*args, **kwargs): + def wrapper(*args: Any, **kwargs: Any) -> Any: return func(*args, **kwargs) - wrapper._problem_type = AggregationLevel.LIKELIHOOD # ty:ignore[unresolved-attribute] - return wrapper # ty:ignore[invalid-return-type] + cast(_MarkedFunction, wrapper)._problem_type = problem_type + return cast(FuncT, wrapper) + return func # TODO: I get an error when adding bound=Algorithm to AlgorithmSubclass. Why? diff --git a/src/optimagic/optimization/algorithm.py b/src/optimagic/optimization/algorithm.py index a7e0162e1..c66e55808 100644 --- a/src/optimagic/optimization/algorithm.py +++ b/src/optimagic/optimization/algorithm.py @@ -2,7 +2,7 @@ import warnings from abc import ABC, ABCMeta, abstractmethod from dataclasses import dataclass, replace -from typing import Any +from typing import Any, ClassVar import numpy as np import pydantic @@ -98,31 +98,33 @@ class InternalOptimizeResult: class AlgorithmMeta(ABCMeta): """Metaclass to get repr, algo_info and name for classes, not just instances.""" + __algo_info__: AlgoInfo | None + def __repr__(self) -> str: - if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - out = f"om.algos.{self.__algo_info__.name}" # ty:ignore[unresolved-attribute] + if self.__algo_info__ is not None: + out = f"om.algos.{self.__algo_info__.name}" else: out = self.__class__.__name__ return out @property def name(self) -> str: - if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - out = self.__algo_info__.name # ty:ignore[unresolved-attribute] + if self.__algo_info__ is not None: + out = self.__algo_info__.name else: out = self.__class__.__name__ return out @property def algo_info(self) -> AlgoInfo: - if not hasattr(self, "__algo_info__") or self.__algo_info__ is None: + if self.__algo_info__ is None: msg = ( f"The algorithm {self.name} does not have have the __algo_info__ " "attribute. Use the `mark.minimizer` decorator to add this attribute." ) raise AttributeError(msg) - return self.__algo_info__ # ty:ignore[invalid-return-type] + return self.__algo_info__ @dataclass(frozen=True) @@ -134,6 +136,9 @@ class Algorithm(ABC, metaclass=AlgorithmMeta): """ + __algo_info__: ClassVar[AlgoInfo | None] = None + """Information about the algorithm; set by the `mark.minimizer` decorator.""" + @abstractmethod def _solve_internal_problem( self, problem: InternalOptimizationProblem, x0: NDArray[np.float64] @@ -222,18 +227,18 @@ def with_option_if_applicable(self, **kwargs: Any) -> Self: def name(self) -> str: """The name of the algorithm.""" # cannot call algo_info here because it would be an infinite recursion - if hasattr(self, "__algo_info__") and self.__algo_info__ is not None: - return self.__algo_info__.name # ty:ignore[unresolved-attribute] + if self.__algo_info__ is not None: + return self.__algo_info__.name return self.__class__.__name__ @property def algo_info(self) -> AlgoInfo: """Information about the algorithm.""" - if not hasattr(self, "__algo_info__") or self.__algo_info__ is None: + if self.__algo_info__ is None: msg = ( f"The algorithm {self.name} does not have have the __algo_info__ " "attribute. Use the `mark.minimizer` decorator to add this attribute." ) raise AttributeError(msg) - return self.__algo_info__ # ty:ignore[invalid-return-type] + return self.__algo_info__ From eb1a34e738949b9a648e03a296d1253608253fd6 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Mon, 28 Sep 2026 16:35:16 +0200 Subject: [PATCH 13/15] Fix criterion_plot crash when stacking exploration samples from a database criterion_plot(path, stack_multistart=True, show_exploration=True) raised TypeError because it tried to assign items on a History object. Both the result and the database branch now use one helper that prepends the exploration samples. Co-Authored-By: Claude Opus 5.5 --- src/optimagic/visualization/history_plots.py | 50 +++++++++++++------ .../visualization/test_history_plots.py | 1 + 2 files changed, 36 insertions(+), 15 deletions(-) diff --git a/src/optimagic/visualization/history_plots.py b/src/optimagic/visualization/history_plots.py index 3fe4483fc..23a649ab5 100644 --- a/src/optimagic/visualization/history_plots.py +++ b/src/optimagic/visualization/history_plots.py @@ -356,18 +356,10 @@ def _retrieve_optimization_data_from_result_object( if stack_multistart: stacked = _get_stacked_local_histories(local_histories, res.direction) if show_exploration: - fun = res.multistart_info.exploration_results[::-1] + stacked.fun - params = res.multistart_info.exploration_sample[::-1] + stacked.params - - stacked = History( - direction=stacked.direction, - fun=fun, - params=params, - # TODO: This needs to be fixed - start_time=len(fun) * [None], # ty:ignore[invalid-argument-type] - stop_time=len(fun) * [None], # ty:ignore[invalid-argument-type] - batches=len(fun) * [None], # ty:ignore[invalid-argument-type] - task=len(fun) * [None], # ty:ignore[invalid-argument-type] + stacked = _prepend_exploration( + stacked, + exploration_fun=res.multistart_info.exploration_results, + exploration_params=res.multistart_info.exploration_sample, ) else: stacked = None @@ -419,9 +411,12 @@ def _retrieve_optimization_data_from_database( if stack_multistart and local_histories is not None: stacked = _get_stacked_local_histories(local_histories, direction, _history) - if show_exploration: - stacked["params"] = exploration["params"][::-1] + stacked["params"] # ty:ignore[invalid-assignment] - stacked["criterion"] = exploration["criterion"][::-1] + stacked["criterion"] # ty:ignore[invalid-assignment] + if show_exploration and exploration is not None: + stacked = _prepend_exploration( + stacked, + exploration_fun=exploration.fun, + exploration_params=exploration.params, + ) else: stacked = None @@ -486,6 +481,31 @@ def _get_stacked_local_histories( ) +def _prepend_exploration( + history: History, + exploration_fun: list[float], + exploration_params: list[PyTree], +) -> History: + """Prepend the exploration samples in reverse order to a stacked history. + + The exploration samples are sorted from best to worst, so reversing them puts the + best samples right before the local optimizations. + + """ + fun = exploration_fun[::-1] + history.fun + params = exploration_params[::-1] + history.params + return History( + direction=history.direction, + fun=fun, + params=params, + # TODO: This needs to be fixed + start_time=len(fun) * [None], # ty:ignore[invalid-argument-type] + stop_time=len(fun) * [None], # ty:ignore[invalid-argument-type] + batches=len(fun) * [None], # ty:ignore[invalid-argument-type] + task=len(fun) * [None], # ty:ignore[invalid-argument-type] + ) + + def _extract_criterion_plot_lines( data: list[_PlottingMultistartHistory], max_evaluations: int | None, diff --git a/tests/optimagic/visualization/test_history_plots.py b/tests/optimagic/visualization/test_history_plots.py index 924bd7248..7078223c9 100644 --- a/tests/optimagic/visualization/test_history_plots.py +++ b/tests/optimagic/visualization/test_history_plots.py @@ -139,6 +139,7 @@ def test_criterion_plot_different_input_types(): criterion_plot(results, stack_multistart=True) criterion_plot(results, monotone=True, stack_multistart=True) criterion_plot(results, show_exploration=True) + criterion_plot(results, stack_multistart=True, show_exploration=True) criterion_plot("test.db") From f14abbdddb33d0ee913e65a42afbba338dd78ff3 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Mon, 28 Sep 2026 16:36:38 +0200 Subject: [PATCH 14/15] Type jac=True and derivative sequences; drop None from multistart docs - jac accepts Literal[True] (scipy style) and any sequence of derivatives; fun_and_jac accepts a sequence of callables. Both already worked at runtime. - The docstrings of minimize and maximize describe these options and no longer claim that multistart=None disables multistart. Co-Authored-By: Claude Opus 5.5 --- .../create_optimization_problem.py | 5 ++- src/optimagic/optimization/optimize.py | 40 +++++++++++++------ .../optimization/test_function_formats_ls.py | 4 +- tests/optimagic/optimization/test_optimize.py | 5 ++- .../optimization/test_params_versions.py | 2 +- .../optimization/test_scipy_aliases.py | 4 +- tests/optimagic/optimizers/test_bhhh.py | 2 +- 7 files changed, 39 insertions(+), 23 deletions(-) diff --git a/src/optimagic/optimization/create_optimization_problem.py b/src/optimagic/optimization/create_optimization_problem.py index 7fd95c100..a74ee918d 100644 --- a/src/optimagic/optimization/create_optimization_problem.py +++ b/src/optimagic/optimization/create_optimization_problem.py @@ -1,4 +1,5 @@ import warnings +from collections.abc import Sequence from dataclasses import dataclass from pathlib import Path from typing import Any, Callable, Type @@ -164,9 +165,9 @@ def create_optimization_problem( raise MissingInputError(msg) if fun_and_jac is not None and fun is None and criterion is None: - if isinstance(fun_and_jac, list): + if isinstance(fun_and_jac, Sequence): raise NotImplementedError( - "If `fun_and_jac` is a list of callables, `fun` is not optional. " + "If `fun_and_jac` is a sequence of callables, `fun` is not optional. " ) fun = split_fun_and_jac(fun_and_jac, target="fun") diff --git a/src/optimagic/optimization/optimize.py b/src/optimagic/optimization/optimize.py index cf59f9950..cfefb8e6f 100644 --- a/src/optimagic/optimization/optimize.py +++ b/src/optimagic/optimization/optimize.py @@ -15,7 +15,7 @@ from __future__ import annotations from pathlib import Path -from typing import Any, Callable, Sequence, Type, cast +from typing import Any, Callable, Literal, Sequence, Type, cast import numpy as np from scipy.optimize import Bounds as ScipyBounds @@ -94,9 +94,12 @@ def maximize( constraints: ConstraintsType | None = None, fun_kwargs: dict[str, Any] | None = None, algo_options: dict[str, Any] | None = None, - jac: JacType | list[JacType] | None = None, + jac: JacType | Sequence[JacType] | Literal[True] | None = None, jac_kwargs: dict[str, Any] | None = None, - fun_and_jac: FunAndJacType | CriterionAndDerivativeType | None = None, + fun_and_jac: FunAndJacType + | CriterionAndDerivativeType + | Sequence[FunAndJacType] + | None = None, fun_and_jac_kwargs: dict[str, Any] | None = None, numdiff_options: NumdiffOptions | NumdiffOptionsDict | None = None, # TODO: add typed-dict support? @@ -167,12 +170,16 @@ def maximize( jac: The first derivative of `fun`. Providing a closed form derivative can be a great way to speed up your optimization. The easiest way to get a derivative for your objective function are autodiff frameworks like - JAX. For details and examples see :ref:`how-to-jac`. + JAX. If you provide a sequence of derivatives, the one that matches the + aggregation level of the algorithm is used. For compatibility with scipy, + `jac=True` means that `fun` returns a tuple of the function value and its + derivative. For details and examples see :ref:`how-to-jac`. jac_kwargs: Additional keyword arguments for `jac`. fun_and_jac: A function that returns both the objective value and the derivative. This can be used do exploit synergies in the calculation of the - function value and its derivative. For details and examples see - :ref:`how-to-jac`. + function value and its derivative. If you provide a sequence, the element + that matches the aggregation level of the algorithm is used and `fun` must + also be provided. For details and examples see :ref:`how-to-jac`. fun_and_jac_kwargs: Additional keyword arguments for `fun_and_jac`. numdiff_options: Options for numerical differentiation. Can be a dictionary or an instance of :class:`optimagic.NumdiffOptions`. @@ -197,7 +204,7 @@ def maximize( To choose which heuristic is used and to customize the scaling, provide a dictionary or an instance of :class:`optimagic.ScalingOptions`. For details and examples see :ref:`scaling`. - multistart: If None or False, no multistart approach is used. If True, the + multistart: If False, no multistart approach is used. If True, the optimization is restarted from multiple starting points. Note that this requires finite bounds or soft bounds for all parameters. To customize the multistart approach, provide a dictionary or an instance of @@ -298,9 +305,12 @@ def minimize( constraints: ConstraintsType | None = None, fun_kwargs: dict[str, Any] | None = None, algo_options: dict[str, Any] | None = None, - jac: JacType | list[JacType] | None = None, + jac: JacType | Sequence[JacType] | Literal[True] | None = None, jac_kwargs: dict[str, Any] | None = None, - fun_and_jac: FunAndJacType | CriterionAndDerivativeType | None = None, + fun_and_jac: FunAndJacType + | CriterionAndDerivativeType + | Sequence[FunAndJacType] + | None = None, fun_and_jac_kwargs: dict[str, Any] | None = None, numdiff_options: NumdiffOptions | NumdiffOptionsDict | None = None, # TODO: add typed-dict support? @@ -371,12 +381,16 @@ def minimize( jac: The first derivative of `fun`. Providing a closed form derivative can be a great way to speed up your optimization. The easiest way to get a derivative for your objective function are autodiff frameworks like - JAX. For details and examples see :ref:`how-to-jac`. + JAX. If you provide a sequence of derivatives, the one that matches the + aggregation level of the algorithm is used. For compatibility with scipy, + `jac=True` means that `fun` returns a tuple of the function value and its + derivative. For details and examples see :ref:`how-to-jac`. jac_kwargs: Additional keyword arguments for `jac`. fun_and_jac: A function that returns both the objective value and the derivative. This can be used do exploit synergies in the calculation of the - function value and its derivative. For details and examples see - :ref:`how-to-jac`. + function value and its derivative. If you provide a sequence, the element + that matches the aggregation level of the algorithm is used and `fun` must + also be provided. For details and examples see :ref:`how-to-jac`. fun_and_jac_kwargs: Additional keyword arguments for `fun_and_jac`. numdiff_options: Options for numerical differentiation. Can be a dictionary or an instance of :class:`optimagic.NumdiffOptions`. @@ -401,7 +415,7 @@ def minimize( To choose which heuristic is used and to customize the scaling, provide a dictionary or an instance of :class:`optimagic.ScalingOptions`. For details and examples see :ref:`scaling`. - multistart: If None or False, no multistart approach is used. If True, the + multistart: If False, no multistart approach is used. If True, the optimization is restarted from multiple starting points. Note that this requires finite bounds or soft bounds for all parameters. To customize the multistart approach, provide a dictionary or an instance of diff --git a/tests/optimagic/optimization/test_function_formats_ls.py b/tests/optimagic/optimization/test_function_formats_ls.py index ac3924ccf..83e087404 100644 --- a/tests/optimagic/optimization/test_function_formats_ls.py +++ b/tests/optimagic/optimization/test_function_formats_ls.py @@ -80,7 +80,7 @@ def fun_and_jac_ls(x): params=start_params, algorithm=algorithm, jac=jac, - fun_and_jac=fun_and_jac, # ty:ignore[invalid-argument-type] + fun_and_jac=fun_and_jac, ) aaae(res.params, np.zeros(3)) @@ -137,7 +137,7 @@ def fun_and_jac_dict_ls(params): params=start_params, algorithm=algorithm, jac=jac, - fun_and_jac=fun_and_jac, # ty:ignore[invalid-argument-type] + fun_and_jac=fun_and_jac, ) for key in start_params: diff --git a/tests/optimagic/optimization/test_optimize.py b/tests/optimagic/optimization/test_optimize.py index eb44c698f..f74c307df 100644 --- a/tests/optimagic/optimization/test_optimize.py +++ b/tests/optimagic/optimization/test_optimize.py @@ -58,10 +58,11 @@ def test_with_optional_fun_argument(): aaae(res.x, expected) -def test_fun_and_jac_list(): +@pytest.mark.parametrize("container", [list, tuple]) +def test_fun_and_jac_sequence_without_fun(container): with pytest.raises(NotImplementedError): minimize( - fun_and_jac=[lambda x: (x @ x, 2 * x)], # ty:ignore[invalid-argument-type] + fun_and_jac=container([lambda x: (x @ x, 2 * x)]), params=np.arange(5), algorithm="scipy_lbfgsb", ) diff --git a/tests/optimagic/optimization/test_params_versions.py b/tests/optimagic/optimization/test_params_versions.py index c64def22a..08ea4da81 100644 --- a/tests/optimagic/optimization/test_params_versions.py +++ b/tests/optimagic/optimization/test_params_versions.py @@ -82,7 +82,7 @@ def test_tree_params_sos_ls(params, algorithm): derivatives = [sos_gradient, sos_ls_jacobian] res = minimize( fun=sos_ls, - jac=derivatives, # ty:ignore[invalid-argument-type] + jac=derivatives, params=params, algorithm=algorithm, ) diff --git a/tests/optimagic/optimization/test_scipy_aliases.py b/tests/optimagic/optimization/test_scipy_aliases.py index 2c523a06d..6720c5ebe 100644 --- a/tests/optimagic/optimization/test_scipy_aliases.py +++ b/tests/optimagic/optimization/test_scipy_aliases.py @@ -178,7 +178,7 @@ def test_jac_equal_true_works_in_minimize(): fun=lambda x: (x @ x, 2 * x), params=np.arange(3), algorithm="scipy_lbfgsb", - jac=True, # ty:ignore[invalid-argument-type] + jac=True, ) aaae(res.params, np.zeros(3)) @@ -188,6 +188,6 @@ def test_jac_equal_true_works_in_maximize(): fun=lambda x: (-x @ x, -2 * x), params=np.arange(3), algorithm="scipy_lbfgsb", - jac=True, # ty:ignore[invalid-argument-type] + jac=True, ) aaae(res.params, np.zeros(3)) diff --git a/tests/optimagic/optimizers/test_bhhh.py b/tests/optimagic/optimizers/test_bhhh.py index 0c32aab16..14bdd0f31 100644 --- a/tests/optimagic/optimizers/test_bhhh.py +++ b/tests/optimagic/optimizers/test_bhhh.py @@ -154,7 +154,7 @@ def test_maximum_likelihood_external_interfaace( result_bhhh = minimize( fun=mark.likelihood(criterion_and_derivative), - jac=True, # ty:ignore[invalid-argument-type] + jac=True, params=x, algorithm="bhhh", ) From 711f69954a980282767fc1aaff77fa581688a393 Mon Sep 17 00:00:00 2001 From: Janos Gabler Date: Tue, 29 Sep 2026 08:32:29 +0200 Subject: [PATCH 15/15] Enforce all ruff ANN rules and prune stale annotation exemptions ANN001 and ANN201 alone cover less than mypy's disallow_untyped_defs: they skip private function returns, *args/**kwargs and special methods. Select the full ANN set (minus ANN401) with mypy-init-return, and drop exemptions for files that already pass or no longer exist. Annotate the two non-exempt signatures this uncovers in optimagic.logging. Co-Authored-By: Claude Opus 5.5 --- pyproject.toml | 208 ++++++++++++++---------------- src/estimagic/__init__.py | 5 +- src/optimagic/logging/logger.py | 2 +- src/optimagic/logging/read_log.py | 5 +- 4 files changed, 104 insertions(+), 116 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7902ad926..234170da6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -124,10 +124,8 @@ select = [ "ISC", # pydocstyle "D", - # Checks that function arguments have type annotations - "ANN001", - # Checks that public functions and methods have return type annotations - "ANN201", + # flake8-annotations: require type annotations on all function signatures + "ANN", ] extend-ignore = [ @@ -167,123 +165,111 @@ extend-ignore = [ "B028", # Incompatible with formatting "ISC001", + # Dynamically typed expressions (typing.Any) are disallowed + "ANN401", ] [tool.ruff.lint.per-file-ignores] "docs/source/conf.py" = ["E501", "ERA001", "DTZ005"] -"src/optimagic/parameters/kernel_transformations.py" = ["ARG001", "N806", "ANN001", "ANN201"] +"src/optimagic/parameters/kernel_transformations.py" = ["ARG001", "N806", "ANN"] "docs/source/*" = ["B018"] "src/optimagic/algorithms.py" = ["E501"] -"docs/*" = ["ANN001", "ANN201"] -"tests/*" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/benchmark_reports.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/cartis_roberts.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/get_benchmark_problems.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/more_wild.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/noise_distributions.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/process_benchmark_results.py" = ["ANN001", "ANN201"] -"src/optimagic/benchmarking/run_benchmark.py" = ["ANN001", "ANN201"] - -"src/optimagic/differentiation/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/differentiation/derivatives.py" = ["ANN001", "ANN201"] -"src/optimagic/differentiation/finite_differences.py" = ["ANN001", "ANN201"] -"src/optimagic/differentiation/generate_steps.py" = ["ANN001", "ANN201"] -"src/optimagic/differentiation/richardson_extrapolation.py" = ["ANN001", "ANN201"] - -"src/optimagic/examples/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/examples/numdiff_functions.py" = ["ANN001", "ANN201"] - -"src/optimagic/optimization/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/algo_options.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/convergence_report.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/optimization_logging.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/optimize_result.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/optimize.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/multistart.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/scipy_aliases.py" = ["ANN001", "ANN201"] -"src/optimagic/optimization/create_optimization_problem.py" = ["ANN001", "ANN201"] - -"src/optimagic/optimizers/_pounders/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/pounders_auxiliary.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/pounders_history.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/_conjugate_gradient.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/_steihaug_toint.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/_trsbox.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/bntr.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/gqtpar.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/_pounders/linear_subsolvers.py" = ["ANN001", "ANN201"] - -"src/optimagic/optimizers/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/tranquilo.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/pygmo_optimizers.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/scipy_optimizers.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/nag_optimizers.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/neldermead.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/nlopt_optimizers.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/ipopt.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/fides.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/pounders.py" = ["ANN001", "ANN201"] -"src/optimagic/optimizers/tao_optimizers.py" = ["ANN001", "ANN201"] - - -"src/optimagic/parameters/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/block_trees.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/check_constraints.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/consolidate_constraints.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/constraint_tools.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/conversion.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/nonlinear_constraints.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/process_constraints.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/process_selectors.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/space_conversion.py" = ["ANN001", "ANN201"] -"src/optimagic/parameters/tree_conversion.py" = ["ANN001", "ANN201"] - - -"src/optimagic/shared/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/shared/check_option_dicts.py" = ["ANN001", "ANN201"] -"src/optimagic/shared/compat.py" = ["ANN001", "ANN201"] -"src/optimagic/shared/process_user_function.py" = ["ANN001", "ANN201"] - -"src/optimagic/visualization/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/convergence_plot.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/backend.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/deviation_plot.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/history_plots.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/plotting_utilities.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/profile_plot.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/slice_plot.py" = ["ANN001", "ANN201"] - -"src/optimagic/__init__.py" = ["ANN001", "ANN201"] -"src/optimagic/decorators.py" = ["ANN001", "ANN201"] -"src/optimagic/exceptions.py" = ["ANN001", "ANN201"] -"src/optimagic/utilities.py" = ["ANN001", "ANN201"] -"src/optimagic/pytree.py" = ["ANN001", "ANN201"] -"src/optimagic/deprecations.py" = ["ANN001", "ANN201"] - -"src/estimagic/__init__.py" = ["ANN001", "ANN201"] -"src/estimagic/examples/__init__.py" = ["ANN001", "ANN201"] -"src/estimagic/examples/logit.py" = ["ANN001", "ANN201"] -"src/estimagic/estimate_ml.py" = ["ANN001", "ANN201"] -"src/estimagic/estimate_msm.py" = ["ANN001", "ANN201"] -"src/estimagic/estimation_summaries.py" = ["ANN001", "ANN201"] -"src/estimagic/msm_weighting.py" = ["ANN001", "ANN201"] -"src/estimagic/bootstrap_ci.py" = ["ANN001", "ANN201"] -"src/estimagic/bootstrap_helpers.py" = ["ANN001", "ANN201"] -"src/estimagic/bootstrap_outcomes.py" = ["ANN001", "ANN201"] -"src/estimagic/bootstrap_samples.py" = ["ANN001", "ANN201"] -"src/estimagic/bootstrap.py" = ["ANN001", "ANN201"] -"src/estimagic/ml_covs.py" = ["ANN001", "ANN201"] -"src/estimagic/msm_covs.py" = ["ANN001", "ANN201"] -"src/estimagic/shared_covs.py" = ["ANN001", "ANN201"] -"src/estimagic/msm_sensitivity.py" = ["ANN001", "ANN201"] -"src/estimagic/estimation_table.py" = ["ANN001", "ANN201"] -"src/estimagic/lollipop_plot.py" = ["ANN001", "ANN201"] -"src/optimagic/visualization/slice_plot_3d.py" = ["ANN001", "ANN201"] +"docs/*" = ["ANN"] +"tests/*" = ["ANN"] +"src/optimagic/benchmarking/benchmark_reports.py" = ["ANN"] +"src/optimagic/benchmarking/cartis_roberts.py" = ["ANN"] +"src/optimagic/benchmarking/get_benchmark_problems.py" = ["ANN"] +"src/optimagic/benchmarking/more_wild.py" = ["ANN"] +"src/optimagic/benchmarking/noise_distributions.py" = ["ANN"] +"src/optimagic/benchmarking/process_benchmark_results.py" = ["ANN"] +"src/optimagic/benchmarking/run_benchmark.py" = ["ANN"] + +"src/optimagic/differentiation/derivatives.py" = ["ANN"] +"src/optimagic/differentiation/finite_differences.py" = ["ANN"] +"src/optimagic/differentiation/generate_steps.py" = ["ANN"] +"src/optimagic/differentiation/richardson_extrapolation.py" = ["ANN"] + +"src/optimagic/examples/numdiff_functions.py" = ["ANN"] + +"src/optimagic/optimization/algo_options.py" = ["ANN"] +"src/optimagic/optimization/optimize_result.py" = ["ANN"] +"src/optimagic/optimization/multistart.py" = ["ANN"] +"src/optimagic/optimization/scipy_aliases.py" = ["ANN"] +"src/optimagic/optimization/create_optimization_problem.py" = ["ANN"] + +"src/optimagic/optimizers/_pounders/pounders_auxiliary.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/pounders_history.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/_conjugate_gradient.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/_steihaug_toint.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/_trsbox.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/bntr.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/gqtpar.py" = ["ANN"] +"src/optimagic/optimizers/_pounders/linear_subsolvers.py" = ["ANN"] + +"src/optimagic/optimizers/pygmo_optimizers.py" = ["ANN"] +"src/optimagic/optimizers/scipy_optimizers.py" = ["ANN"] +"src/optimagic/optimizers/nag_optimizers.py" = ["ANN"] +"src/optimagic/optimizers/neldermead.py" = ["ANN"] +"src/optimagic/optimizers/nlopt_optimizers.py" = ["ANN"] +"src/optimagic/optimizers/ipopt.py" = ["ANN"] +"src/optimagic/optimizers/fides.py" = ["ANN"] +"src/optimagic/optimizers/pounders.py" = ["ANN"] +"src/optimagic/optimizers/tao_optimizers.py" = ["ANN"] + + +"src/optimagic/parameters/block_trees.py" = ["ANN"] +"src/optimagic/parameters/check_constraints.py" = ["ANN"] +"src/optimagic/parameters/consolidate_constraints.py" = ["ANN"] +"src/optimagic/parameters/constraint_tools.py" = ["ANN"] +"src/optimagic/parameters/conversion.py" = ["ANN"] +"src/optimagic/parameters/nonlinear_constraints.py" = ["ANN"] +"src/optimagic/parameters/process_constraints.py" = ["ANN"] +"src/optimagic/parameters/space_conversion.py" = ["ANN"] +"src/optimagic/parameters/tree_conversion.py" = ["ANN"] + + +"src/optimagic/shared/check_option_dicts.py" = ["ANN"] +"src/optimagic/shared/compat.py" = ["ANN"] +"src/optimagic/shared/process_user_function.py" = ["ANN"] + +"src/optimagic/visualization/convergence_plot.py" = ["ANN"] +"src/optimagic/visualization/deviation_plot.py" = ["ANN"] +"src/optimagic/visualization/history_plots.py" = ["ANN"] +"src/optimagic/visualization/plotting_utilities.py" = ["ANN"] +"src/optimagic/visualization/profile_plot.py" = ["ANN"] +"src/optimagic/visualization/slice_plot.py" = ["ANN"] + +"src/optimagic/decorators.py" = ["ANN"] +"src/optimagic/exceptions.py" = ["ANN"] +"src/optimagic/utilities.py" = ["ANN"] +"src/optimagic/pytree.py" = ["ANN"] +"src/optimagic/deprecations.py" = ["ANN"] + +"src/estimagic/__init__.py" = ["ANN"] +"src/estimagic/examples/logit.py" = ["ANN"] +"src/estimagic/estimate_ml.py" = ["ANN"] +"src/estimagic/estimate_msm.py" = ["ANN"] +"src/estimagic/msm_weighting.py" = ["ANN"] +"src/estimagic/bootstrap_ci.py" = ["ANN"] +"src/estimagic/bootstrap_helpers.py" = ["ANN"] +"src/estimagic/bootstrap_outcomes.py" = ["ANN"] +"src/estimagic/bootstrap_samples.py" = ["ANN"] +"src/estimagic/bootstrap.py" = ["ANN"] +"src/estimagic/ml_covs.py" = ["ANN"] +"src/estimagic/msm_covs.py" = ["ANN"] +"src/estimagic/shared_covs.py" = ["ANN"] +"src/estimagic/msm_sensitivity.py" = ["ANN"] +"src/estimagic/estimation_table.py" = ["ANN"] +"src/estimagic/lollipop_plot.py" = ["ANN"] +"src/optimagic/visualization/slice_plot_3d.py" = ["ANN"] [tool.ruff.lint.pydocstyle] convention = "google" +[tool.ruff.lint.flake8-annotations] +# Like mypy, allow omitting `-> None` on `__init__` if an argument is annotated. +mypy-init-return = true + # ====================================================================================== # Pytest configuration diff --git a/src/estimagic/__init__.py b/src/estimagic/__init__.py index bc68707ed..e9dc5f361 100644 --- a/src/estimagic/__init__.py +++ b/src/estimagic/__init__.py @@ -32,7 +32,8 @@ from optimagic import slice_plot as _slice_plot from optimagic import traceback_report as _traceback_report from optimagic.decorators import deprecated -from optimagic.logging import SQLiteLogReader as _SQLiteLogReader +from optimagic.logging import SQLiteLogOptions as _SQLiteLogOptions +from optimagic.logging.logger import LogReader as _LogReader MSG = ( "estimagic.{name} has been deprecated in version 0.5.0. Use optimagic.{name} " @@ -64,7 +65,7 @@ class OptimizeLogReader(_OptimizeLogReader): # The parent class returns a SQLiteLogReader from __new__, so __init__ of this # class would never run. Hence, the warning needs to be raised in __new__. - def __new__(cls, *args, **kwargs) -> _SQLiteLogReader: + def __new__(cls, *args, **kwargs) -> _LogReader[_SQLiteLogOptions]: warnings.warn( "estimagic.OptimizeLogReader has been deprecated in version 0.5.0. Use " "optimagic.OptimizeLogReader instead. This class will be removed in version" diff --git a/src/optimagic/logging/logger.py b/src/optimagic/logging/logger.py index a66122d84..0e92ec682 100644 --- a/src/optimagic/logging/logger.py +++ b/src/optimagic/logging/logger.py @@ -52,7 +52,7 @@ class LogOptions: def __init_subclass__( cls: Type[LogOptions], abstract: bool = False, **kwargs: dict[Any, Any] - ): + ) -> None: if not abstract: LogOptions._subclass_registry.append(cls) super().__init_subclass__(**kwargs) diff --git a/src/optimagic/logging/read_log.py b/src/optimagic/logging/read_log.py index 477f7e249..4e75a51da 100644 --- a/src/optimagic/logging/read_log.py +++ b/src/optimagic/logging/read_log.py @@ -14,13 +14,14 @@ import warnings from dataclasses import dataclass +from typing import Any -from optimagic.logging.logger import SQLiteLogOptions, SQLiteLogReader +from optimagic.logging.logger import LogReader, SQLiteLogOptions, SQLiteLogReader @dataclass class OptimizeLogReader: - def __new__(cls, *args, **kwargs): + def __new__(cls, *args: Any, **kwargs: Any) -> LogReader[SQLiteLogOptions]: warnings.warn( "OptimizeLogReader is deprecated and will be removed in a future " "version. Please use optimagic.logging.SQLiteLogReader instead.",