From fb332d0c1357f65dc08468f8d087dd19478a5dda Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 09:54:40 +0100 Subject: [PATCH 01/12] dependency bumps --- pyproject.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1c02ad57..d9354b85 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -58,7 +58,7 @@ dependencies = [ "numpy >= 2.0", "pandas >= 2.0", "matplotlib >=3.7", - "scipy >= 1.6", + "scipy >= 1.10", "tfs-pandas >= 3.8", "loguru < 1.0", "cpymad >= 1.16", @@ -71,22 +71,22 @@ dependencies = [ [project.optional-dependencies] test = [ "pytest >= 8.0", - "pytest-cov >= 5.0", + "pytest-cov >= 6.0", "pytest-xdist >= 3.0", "numba >= 0.60.0", "flaky >= 3.5", - "pytest-randomly >= 3.3", + "pytest-randomly >= 3.10", "coverage[toml] >= 7.0", "pytest-mpl >= 0.14", ] dev = [ - "ruff >= 0.5", + "ruff >= 0.12", ] docs = [ "joblib >= 1.0", - "Sphinx >= 7.0", - "sphinx-rtd-theme >= 2.0", - "sphinx-issues >= 4.0", + "Sphinx >= 8.0", + "sphinx-rtd-theme >= 3.0", + "sphinx-issues >= 5.0", "sphinx_copybutton < 1.0", "sphinxcontrib-bibtex >= 2.4", "sphinx-design >= 0.6", From bfa2b69d9184f4fd674fef8ed3fa551cedca0c05 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 09:56:15 +0100 Subject: [PATCH 02/12] update lockfile --- uv.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/uv.lock b/uv.lock index de5b718a..9d578d76 100644 --- a/uv.lock +++ b/uv.lock @@ -1318,20 +1318,20 @@ requires-dist = [ { name = "pydantic", specifier = ">=2.0" }, { name = "pytest", marker = "extra == 'all'", specifier = ">=8.0" }, { name = "pytest", marker = "extra == 'test'", specifier = ">=8.0" }, - { name = "pytest-cov", marker = "extra == 'all'", specifier = ">=5.0" }, - { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=5.0" }, + { name = "pytest-cov", marker = "extra == 'all'", specifier = ">=6.0" }, + { name = "pytest-cov", marker = "extra == 'test'", specifier = ">=6.0" }, { name = "pytest-mpl", marker = "extra == 'all'", specifier = ">=0.14" }, { name = "pytest-mpl", marker = "extra == 'test'", specifier = ">=0.14" }, - { name = "pytest-randomly", marker = "extra == 'all'", specifier = ">=3.3" }, - { name = "pytest-randomly", marker = "extra == 'test'", specifier = ">=3.3" }, + { name = "pytest-randomly", marker = "extra == 'all'", specifier = ">=3.10" }, + { name = "pytest-randomly", marker = "extra == 'test'", specifier = ">=3.10" }, { name = "pytest-xdist", marker = "extra == 'all'", specifier = ">=3.0" }, { name = "pytest-xdist", marker = "extra == 'test'", specifier = ">=3.0" }, { name = "rich", specifier = ">=13.0" }, - { name = "ruff", marker = "extra == 'all'", specifier = ">=0.5" }, - { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.5" }, - { name = "scipy", specifier = ">=1.6" }, - { name = "sphinx", marker = "extra == 'all'", specifier = ">=7.0" }, - { name = "sphinx", marker = "extra == 'docs'", specifier = ">=7.0" }, + { name = "ruff", marker = "extra == 'all'", specifier = ">=0.12" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.12" }, + { name = "scipy", specifier = ">=1.10" }, + { name = "sphinx", marker = "extra == 'all'", specifier = ">=8.0" }, + { name = "sphinx", marker = "extra == 'docs'", specifier = ">=8.0" }, { name = "sphinx-codeautolink", marker = "extra == 'all'", specifier = ">=0.14" }, { name = "sphinx-codeautolink", marker = "extra == 'docs'", specifier = ">=0.14" }, { name = "sphinx-copybutton", marker = "extra == 'all'", specifier = "<1.0" }, @@ -1340,12 +1340,12 @@ requires-dist = [ { name = "sphinx-design", marker = "extra == 'docs'", specifier = ">=0.6" }, { name = "sphinx-gallery", marker = "extra == 'all'", specifier = "<1.0" }, { name = "sphinx-gallery", marker = "extra == 'docs'", specifier = "<1.0" }, - { name = "sphinx-issues", marker = "extra == 'all'", specifier = ">=4.0" }, - { name = "sphinx-issues", marker = "extra == 'docs'", specifier = ">=4.0" }, + { name = "sphinx-issues", marker = "extra == 'all'", specifier = ">=5.0" }, + { name = "sphinx-issues", marker = "extra == 'docs'", specifier = ">=5.0" }, { name = "sphinx-prompt", marker = "extra == 'all'", specifier = ">=1.5" }, { name = "sphinx-prompt", marker = "extra == 'docs'", specifier = ">=1.5" }, - { name = "sphinx-rtd-theme", marker = "extra == 'all'", specifier = ">=2.0" }, - { name = "sphinx-rtd-theme", marker = "extra == 'docs'", specifier = ">=2.0" }, + { name = "sphinx-rtd-theme", marker = "extra == 'all'", specifier = ">=3.0" }, + { name = "sphinx-rtd-theme", marker = "extra == 'docs'", specifier = ">=3.0" }, { name = "sphinxcontrib-bibtex", marker = "extra == 'all'", specifier = ">=2.4" }, { name = "sphinxcontrib-bibtex", marker = "extra == 'docs'", specifier = ">=2.4" }, { name = "tfs-pandas", specifier = ">=3.8" }, From 6a23a27dfe802160e9ff69a0ff8784cb6f03b92d Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:05:44 +0100 Subject: [PATCH 03/12] adapted for 2026 --- tests/inputs/utils/correct_user_tasks.pkl | Bin 1143 -> 1055 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/inputs/utils/correct_user_tasks.pkl b/tests/inputs/utils/correct_user_tasks.pkl index 75ec3b649d70313ab049365e56d62689217b2640..ba28833ebcfcccdc4853d18ddfa59a69feb472f4 100644 GIT binary patch delta 219 zcmey)F`t8_fn}=5M3#AsuO=>j#V?z|ouQJUoFSjVmBEprIC&1E8KcbPmy8A&GIN5?mvASd^W;jni&n%D4Twd=C*$gG1>uiCl VY$iLh$cv-7ctVDzUujaR9ss~wJc|GT delta 292 zcmbQw@tuREfn{pWM3#AsFDEX3#V?=1oxzd8m7$U$o1vJYJb4bInK++@?@M-X7H?4? zWbtP3X2_5#nG!T*@?}N?4E4L26OK&8LN7T<$26f mtX@F(drt0UmdEA{gfd5 Date: Mon, 5 Jan 2026 10:08:50 +0100 Subject: [PATCH 04/12] make linter sleep better at night --- tests/test_utils.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 5f6145ad..b8332227 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -45,7 +45,7 @@ def test_check_pid(self): assert CommandLine.check_pid_exists(0) is True assert CommandLine.check_pid_exists(int(1e6)) is False # default max PID is 32768 on linux, 99999 on macOS with pytest.raises(TypeError): - CommandLine.check_pid_exists("not_an_integer") + CommandLine.check_pid_exists("not_an_integer") # ty:ignore[invalid-argument-type] def test_run_cmd(self): assert isinstance(CommandLine.run("echo hello"), tuple) @@ -105,7 +105,7 @@ def test_tasks_table_creation(self, _condor_q_output, _taskless_condor_q_output) tasks_table = _make_tasks_table(user_tasks) assert isinstance(tasks_table, Table) - user_tasks, cluster_info = read_condor_q(_taskless_condor_q_output) + user_tasks, _ = read_condor_q(_taskless_condor_q_output) tasks_table = _make_tasks_table(user_tasks) assert isinstance(tasks_table, Table) @@ -133,7 +133,7 @@ def test_query_betastar_from_opticsfile(self): def test_query_betastar_from_opticsfile_raises_on_invalid_symmetry_if_required(self): with pytest.raises( - AssertionError, match="The betastar values for IP1 and IP5 are not the same in both planes." + AssertionError, match=r"The betastar values for IP1 and IP5 are not the same in both planes." ): _misc.get_betastar_from_opticsfile(INPUTS_DIR / "madx" / "opticsfile.asymmetric", check_symmetry=True) @@ -256,7 +256,7 @@ def _correct_cluster_summary() -> ClusterSummary: def _complex_columns_df() -> pd.DataFrame: rng = np.random.default_rng() array = rng.random(size=(50, 5)) + 1j * rng.random(size=(50, 5)) - return pd.DataFrame(data=array, columns=["A", "B", "C", "D", "E"]) + return pd.DataFrame(data=array, columns=["A", "B", "C", "D", "E"]) # ty:ignore[invalid-argument-type] @pytest.fixture From d1e42f0e29636fc6505c40e401d28382a4cd82e2 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:14:50 +0100 Subject: [PATCH 05/12] typing and yielding --- tests/test_utils.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index b8332227..7f2441f8 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -5,6 +5,7 @@ import subprocess import sys import time +from collections.abc import Iterator import numpy as np import pandas as pd @@ -239,17 +240,17 @@ def _taskless_condor_q_output() -> str: @pytest.fixture -def _correct_user_tasks() -> list[HTCTaskSummary]: +def _correct_user_tasks() -> Iterator[list[HTCTaskSummary]]: pickle_file_path = INPUTS_DIR / "utils" / "correct_user_tasks.pkl" with pickle_file_path.open("rb") as file: - return pickle.load(file) + yield pickle.load(file) @pytest.fixture -def _correct_cluster_summary() -> ClusterSummary: +def _correct_cluster_summary() -> Iterator[ClusterSummary]: pickle_file_path = INPUTS_DIR / "utils" / "correct_cluster_summary.pkl" with pickle_file_path.open("rb") as file: - return pickle.load(file) + yield pickle.load(file) @pytest.fixture From f23863f3e8f972e14a4ceb633b787726ce52ab1a Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:16:51 +0100 Subject: [PATCH 06/12] wait for termination of killed process --- tests/test_utils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/test_utils.py b/tests/test_utils.py index 7f2441f8..08b01dfe 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -71,7 +71,10 @@ def test_terminate_nonexistent_pid(self, pid): @pytest.mark.parametrize("sleep_time", list(range(10, 60))) # each one will spawn a different process def test_terminate_pid(self, sleep_time): sacrificed_process = subprocess.Popen(f"sleep {sleep_time}", shell=True) - assert CommandLine.terminate(sacrificed_process.pid) is True + try: + assert CommandLine.terminate(sacrificed_process.pid) is True + finally: # the process would hang, we make sure to cleanup + sacrificed_process.wait() class TestHTCMonitor: From ee8121b7441192ab5f7a8475ea307ef421f9f5c8 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:21:52 +0100 Subject: [PATCH 07/12] type hint signature of decorated function itself --- pyhdtoolkit/utils/decorators.py | 8 ++++++-- tests/test_utils.py | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pyhdtoolkit/utils/decorators.py b/pyhdtoolkit/utils/decorators.py index df735ba9..7bf96f55 100644 --- a/pyhdtoolkit/utils/decorators.py +++ b/pyhdtoolkit/utils/decorators.py @@ -13,7 +13,7 @@ import inspect import traceback import warnings -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, ParamSpec, TypeVar if TYPE_CHECKING: from collections.abc import Callable @@ -72,8 +72,12 @@ def function_wrapper(*args, **kwargs): # ----- Utility JIT Compilation decorator ----- # +P = ParamSpec("P") # for params +R = TypeVar("R") # for returns -def maybe_jit(func: Callable, **kwargs) -> Callable: +# We type hint to specify we return a function with the same +# signature as the input function. +def maybe_jit(func: Callable[P, R], **kwargs) -> Callable[P, R]: """ .. versionadded:: 1.7.0 diff --git a/tests/test_utils.py b/tests/test_utils.py index 08b01dfe..0207c0ba 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -105,7 +105,7 @@ def test_cluster_table_creation(self, _condor_q_output): assert isinstance(cluster_table, Table) def test_tasks_table_creation(self, _condor_q_output, _taskless_condor_q_output): - user_tasks, cluster_info = read_condor_q(_condor_q_output) + user_tasks, _ = read_condor_q(_condor_q_output) tasks_table = _make_tasks_table(user_tasks) assert isinstance(tasks_table, Table) From df928d0713352f6fa188c5d69fd176a115e02db2 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:28:56 +0100 Subject: [PATCH 08/12] cleaner decoration types for linter --- pyhdtoolkit/utils/decorators.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pyhdtoolkit/utils/decorators.py b/pyhdtoolkit/utils/decorators.py index 7bf96f55..b0939eb2 100644 --- a/pyhdtoolkit/utils/decorators.py +++ b/pyhdtoolkit/utils/decorators.py @@ -19,10 +19,13 @@ from collections.abc import Callable +P = ParamSpec("P") # for params +R = TypeVar("R") # for returns + # ----- Utility deprecation decorator ----- # -def deprecated(message: str = "") -> Callable: +def deprecated(message: str = "") -> Callable[[Callable[P, R]], Callable[P, R]]: """ Decorator to mark a function as deprecated. It will result in an informative `DeprecationWarning` being issued with the provided @@ -49,22 +52,23 @@ def old_function(): return "I am old!" """ - def decorator_wrapper(func): + def decorator_wrapper(func: Callable[P, R]) -> Callable[P, R]: + last_call_sources: set[str] = set() + @functools.wraps(func) - def function_wrapper(*args, **kwargs): + def function_wrapper(*args: P.args, **kwargs: P.kwargs) -> R: current_call_source = "|".join(traceback.format_stack(inspect.currentframe())) - if current_call_source not in function_wrapper.last_call_source: + + if current_call_source not in last_call_sources: warnings.warn( - f"Function {func.__name__} is now deprecated and will be removed in a future release! {message}", + f"Function {func.__name__} is now deprecated and will be removed in a future release! {message}", # ty:ignore[unresolved-attribute] category=DeprecationWarning, stacklevel=2, ) - function_wrapper.last_call_source.add(current_call_source) + last_call_sources.add(current_call_source) return func(*args, **kwargs) - function_wrapper.last_call_source = set() - return function_wrapper return decorator_wrapper @@ -72,8 +76,6 @@ def function_wrapper(*args, **kwargs): # ----- Utility JIT Compilation decorator ----- # -P = ParamSpec("P") # for params -R = TypeVar("R") # for returns # We type hint to specify we return a function with the same # signature as the input function. From 587bda7c88232b698a4215d38f1995870bf09e80 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:30:36 +0100 Subject: [PATCH 09/12] make matched patterns raw due to metacharacters --- tests/test_cpymadtools/test_lhc.py | 4 ++-- tests/test_plotting/test_aperture.py | 2 +- tests/test_plotting/test_envelope.py | 2 +- tests/test_plotting/test_helpers.py | 2 +- tests/test_plotting/test_phasespace.py | 4 ++-- tests/test_plotting/test_plotting_utils.py | 4 ++-- tests/test_plotting/test_sbs_phase.py | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/test_cpymadtools/test_lhc.py b/tests/test_cpymadtools/test_lhc.py index 8cf6c811..2dc8947e 100644 --- a/tests/test_cpymadtools/test_lhc.py +++ b/tests/test_cpymadtools/test_lhc.py @@ -487,7 +487,7 @@ def test_rigidity_knob_fails_on_invalid_ir(_non_matched_lhc_madx, caplog): def test_rigidity_knob_fails_on_invalid_side(caplog, _non_matched_lhc_madx): madx = _non_matched_lhc_madx - with pytest.raises(ValueError, match="Invalid value for parameter 'side'."): + with pytest.raises(ValueError, match=r"Invalid value for parameter 'side'."): apply_lhc_rigidity_waist_shift_knob(madx, 1, 1, "invalid") for record in caplog.records: @@ -841,7 +841,7 @@ def test_lhc_run3_setup_context_manager_raises_on_wrong_b4_conditions(): @pytest.mark.skipif(not (TESTS_DIR.parent / "acc-models-lhc").is_dir(), reason="acc-models-lhc not found") def test_lhc_run3_setup_context_manager_raises_on_wrong_run_value(): with pytest.raises( # noqa: SIM117 - NotImplementedError, match="This setup is only possible for Run 2 and Run 3 configurations." + NotImplementedError, match=r"This setup is only possible for Run 2 and Run 3 configurations." ): # using b4 with beam1 setup crashes with LHCSetup(run=1, opticsfile="R2022a_A30cmC30cmA10mL200cm.madx") as madx: # noqa: F841 pass diff --git a/tests/test_plotting/test_aperture.py b/tests/test_plotting/test_aperture.py index 2af579f0..80ecd082 100644 --- a/tests/test_plotting/test_aperture.py +++ b/tests/test_plotting/test_aperture.py @@ -87,5 +87,5 @@ def test_plot_physical_apertures_ir5_collision_vertical(_collision_aperture_tole def test_plot_physical_apertures_raises_on_wrong_plane(): madx = Madx(stdout=False) - with pytest.raises(ValueError, match="Invalid 'plane' argument."): + with pytest.raises(ValueError, match=r"Invalid 'plane' argument."): plot_physical_apertures(madx, plane="invalid") diff --git a/tests/test_plotting/test_envelope.py b/tests/test_plotting/test_envelope.py index 5cbafc92..f75f1908 100644 --- a/tests/test_plotting/test_envelope.py +++ b/tests/test_plotting/test_envelope.py @@ -18,7 +18,7 @@ def test_plot_enveloppe_raises_on_wrong_plane(): madx = Madx(stdout=False) - with pytest.raises(ValueError, match="Invalid 'plane' argument."): + with pytest.raises(ValueError, match=r"Invalid 'plane' argument."): plot_beam_envelope(madx, "lhcb1", plane="invalid") diff --git a/tests/test_plotting/test_helpers.py b/tests/test_plotting/test_helpers.py index 37f9dc8d..08966e3c 100644 --- a/tests/test_plotting/test_helpers.py +++ b/tests/test_plotting/test_helpers.py @@ -40,5 +40,5 @@ def test_confidence_ellipse_fails_on_mismatched_dimensions(): def test_default_sbs_coupling_label_raises_on_wrong_component(): - with pytest.raises(ValueError, match="Invalid component for coupling RDT."): + with pytest.raises(ValueError, match=r"Invalid component for coupling RDT."): _determine_default_sbs_coupling_ylabel(rdt="f1001", component="NONEXISTANT") diff --git a/tests/test_plotting/test_phasespace.py b/tests/test_plotting/test_phasespace.py index b4b1db20..b9d14636 100644 --- a/tests/test_plotting/test_phasespace.py +++ b/tests/test_plotting/test_phasespace.py @@ -87,7 +87,7 @@ def test_plot_courant_snyder_phase_space_wrong_plane_input(): match_cas3(madx) x_coords_stable, px_coords_stable = np.array([]), np.array([]) # no need for tracking - with pytest.raises(ValueError, match="Invalid 'plane' argument."): + with pytest.raises(ValueError, match=r"Invalid 'plane' argument."): plot_courant_snyder_phase_space(madx, x_coords_stable, px_coords_stable, plane="invalid_plane") @@ -97,7 +97,7 @@ def test_plot_courant_snyder_phase_space_colored_wrong_plane_input(): madx.input(BASE_LATTICE) match_cas3(madx) x_coords_stable, px_coords_stable = np.array([]), np.array([]) # no need for tracking - with pytest.raises(ValueError, match="Invalid 'plane' argument."): + with pytest.raises(ValueError, match=r"Invalid 'plane' argument."): plot_courant_snyder_phase_space_colored(madx, x_coords_stable, px_coords_stable, plane="invalid_plane") diff --git a/tests/test_plotting/test_plotting_utils.py b/tests/test_plotting/test_plotting_utils.py index f6924efa..302122e1 100644 --- a/tests/test_plotting/test_plotting_utils.py +++ b/tests/test_plotting/test_plotting_utils.py @@ -54,7 +54,7 @@ def test_coupling_ylabel(f1001, f1010, abs_, real, imag): @pytest.mark.parametrize("rdt", ["invalid", "F1111", "nope"]) def test_coupling_ylabel_raises_on_invalid_rdt(rdt): - with pytest.raises(ValueError, match="Invalid RDT for coupling plot."): + with pytest.raises(ValueError, match=r"Invalid RDT for coupling plot."): _determine_default_sbs_coupling_ylabel(rdt, "abs") @@ -69,7 +69,7 @@ def test_phase_ylabel(plane): @pytest.mark.parametrize("plane", ["a", "Fb1", "nope", "not a plane"]) def test_phase_ylabel_raises_on_invalid_plane(plane): - with pytest.raises(ValueError, match="Invalid plane for phase plot."): + with pytest.raises(ValueError, match=r"Invalid plane for phase plot."): _determine_default_sbs_phase_ylabel(plane) diff --git a/tests/test_plotting/test_sbs_phase.py b/tests/test_plotting/test_sbs_phase.py index c5ad8e1e..1a3c13e2 100644 --- a/tests/test_plotting/test_sbs_phase.py +++ b/tests/test_plotting/test_sbs_phase.py @@ -42,7 +42,7 @@ def test_plot_both_beams(sbs_phasex, sbs_phasey, sbs_model_b2): @pytest.mark.parametrize("wrongplane", ["not", "accepted", "incorrect", ""]) def test_plot_phase_segment_raises_on_wrong_plane(wrongplane, sbs_phasex, sbs_model_b2): - with pytest.raises(ValueError, match="Invalid 'plane' argument."): + with pytest.raises(ValueError, match=r"Invalid 'plane' argument."): plot_phase_segment(segment_df=sbs_phasex, model_df=sbs_model_b2, plane=wrongplane) From acdd73aaad8eb157e25cc65b8ddee8ea8b023e83 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:31:14 +0100 Subject: [PATCH 10/12] figure is a dummy variable --- tests/test_plotting/test_tunediagram.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_plotting/test_tunediagram.py b/tests/test_plotting/test_tunediagram.py index 806b7d4c..fe202d5e 100644 --- a/tests/test_plotting/test_tunediagram.py +++ b/tests/test_plotting/test_tunediagram.py @@ -38,7 +38,7 @@ def test_plot_tune_diagram_colored_by_resonance_order(): @pytest.mark.parametrize("max_order", [2, 3, 4, 5]) @pytest.mark.parametrize("differentiate", [False, True]) def test_plot_tune_diagram_arguments(figure_title, legend_title, max_order, differentiate): - figure, ax = plt.subplots(figsize=(10, 10)) + _figure, ax = plt.subplots(figsize=(10, 10)) plot_tune_diagram( title=figure_title, legend_title=legend_title, From 5aeb39206f9180f6621fc02604214c3431f127d6 Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:40:02 +0100 Subject: [PATCH 11/12] more idiomatic comparison --- tests/test_cpymadtools/test_lhc.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_cpymadtools/test_lhc.py b/tests/test_cpymadtools/test_lhc.py index 2dc8947e..1f16cba0 100644 --- a/tests/test_cpymadtools/test_lhc.py +++ b/tests/test_cpymadtools/test_lhc.py @@ -7,7 +7,7 @@ import pytest import tfs from cpymad.madx import Madx -from pandas.testing import assert_frame_equal +from pandas.testing import assert_frame_equal, assert_series_equal from pyhdtoolkit.cpymadtools.constants import ( DEFAULT_TWISS_COLUMNS, @@ -727,8 +727,8 @@ def test_get_bpms_coupling_rdts(_non_matched_lhc_madx, _reference_twiss_rdts): def test_k_modulation(_non_matched_lhc_madx, _reference_kmodulation): madx = _non_matched_lhc_madx results = do_kmodulation(madx) - assert all(var == 0 for var in results.ERRTUNEX) - assert all(var == 0 for var in results.ERRTUNEY) + assert np.all(results.ERRTUNEX.to_numpy() == 0) # ty:ignore[unresolved-attribute] + assert np.all(results.ERRTUNEY.to_numpy() == 0) # ty:ignore[unresolved-attribute] reference = tfs.read(_reference_kmodulation) assert_frame_equal(results.convert_dtypes(), reference.convert_dtypes()) # avoid dtype comparison error on 0 cols From e2173aca8f7ffbde7242f06aa8e996d610746ada Mon Sep 17 00:00:00 2001 From: Felix Soubelet Date: Mon, 5 Jan 2026 10:40:29 +0100 Subject: [PATCH 12/12] happy linter --- tests/test_cpymadtools/test_lhc.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_cpymadtools/test_lhc.py b/tests/test_cpymadtools/test_lhc.py index 1f16cba0..7aaf32e0 100644 --- a/tests/test_cpymadtools/test_lhc.py +++ b/tests/test_cpymadtools/test_lhc.py @@ -7,7 +7,7 @@ import pytest import tfs from cpymad.madx import Madx -from pandas.testing import assert_frame_equal, assert_series_equal +from pandas.testing import assert_frame_equal from pyhdtoolkit.cpymadtools.constants import ( DEFAULT_TWISS_COLUMNS, @@ -712,10 +712,10 @@ def test_get_bpms_coupling_rdts(_non_matched_lhc_madx, _reference_twiss_rdts): twiss_with_rdts = get_lhc_bpms_twiss_and_rdts(madx) # We separate the complex components to compare to the reference - twiss_with_rdts["F1001R"] = twiss_with_rdts.F1001.apply(np.real) - twiss_with_rdts["F1001I"] = twiss_with_rdts.F1001.apply(np.imag) - twiss_with_rdts["F1010R"] = twiss_with_rdts.F1010.apply(np.real) - twiss_with_rdts["F1010I"] = twiss_with_rdts.F1010.apply(np.imag) + twiss_with_rdts["F1001R"] = twiss_with_rdts.F1001.apply(np.real) # ty:ignore[unresolved-attribute] + twiss_with_rdts["F1001I"] = twiss_with_rdts.F1001.apply(np.imag) # ty:ignore[unresolved-attribute] + twiss_with_rdts["F1010R"] = twiss_with_rdts.F1010.apply(np.real) # ty:ignore[unresolved-attribute] + twiss_with_rdts["F1010I"] = twiss_with_rdts.F1010.apply(np.imag) # ty:ignore[unresolved-attribute] twiss_with_rdts = twiss_with_rdts.drop(columns=["F1001", "F1010"]).set_index("NAME") # Only care to compare the coupling RDTs columns twiss_with_rdts = twiss_with_rdts.loc[:, ["F1001R", "F1001I", "F1010R", "F1010I"]]