From 457c7e66c11bed508ea21092c139f94c701510ce Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 07:43:52 +0200 Subject: [PATCH 01/43] Implement B009 --- pyproject.toml | 1 + src/qcodes/instrument_drivers/stanford_research/SR86x.py | 2 +- src/qcodes/utils/json_utils.py | 4 ++-- tests/drivers/test_lakeshore_372.py | 4 ++-- tests/test_station.py | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c83022134df6..a26a807ad70a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,6 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", "PYI059", # these are preview rules that are not yet stable but explicitly enabled. + "B009" ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/instrument_drivers/stanford_research/SR86x.py b/src/qcodes/instrument_drivers/stanford_research/SR86x.py index a7bdc84d3aad..26274d0671b2 100644 --- a/src/qcodes/instrument_drivers/stanford_research/SR86x.py +++ b/src/qcodes/instrument_drivers/stanford_research/SR86x.py @@ -1291,7 +1291,7 @@ def get_data_channels_parameters( method_name = "get_latest" return tuple( - getattr(getattr(self.data_channels[i], "assigned_parameter"), method_name)() + getattr(self.data_channels[i].assigned_parameter, method_name)() for i in range(self._N_DATA_CHANNELS) ) diff --git a/src/qcodes/utils/json_utils.py b/src/qcodes/utils/json_utils.py index 64afb2e80818..7cd07fe89030 100644 --- a/src/qcodes/utils/json_utils.py +++ b/src/qcodes/utils/json_utils.py @@ -61,7 +61,7 @@ def default(self, o: Any) -> Any: } elif hasattr(o, "_JSONEncoder"): # Use object's custom JSON encoder - jsosencode = getattr(o, "_JSONEncoder") + jsosencode = o._JSONEncoder return jsosencode() else: try: @@ -82,7 +82,7 @@ def default(self, o: Any) -> Any: ): return { "__class__": type(o).__name__, - "__args__": getattr(o, "__getnewargs__")(), + "__args__": o.__getnewargs__(), } else: # we cannot convert the object to JSON, just take a string diff --git a/tests/drivers/test_lakeshore_372.py b/tests/drivers/test_lakeshore_372.py index e88dbbb95979..9d2b11a07161 100644 --- a/tests/drivers/test_lakeshore_372.py +++ b/tests/drivers/test_lakeshore_372.py @@ -62,9 +62,9 @@ def __init__(self, *args, **kwargs) -> None: f = getattr(self, func_name) # only add for methods that have such an attribute with suppress(AttributeError): - self.queries[getattr(f, "query_name")] = f + self.queries[f.query_name] = f with suppress(AttributeError): - self.cmds[getattr(f, "command_name")] = f + self.cmds[f.command_name] = f def write_raw(self, cmd) -> None: cmd_parts = cmd.split(" ") diff --git a/tests/test_station.py b/tests/test_station.py index 89eedca4992f..01ec4388559c 100644 --- a/tests/test_station.py +++ b/tests/test_station.py @@ -619,7 +619,7 @@ def test_setup_alias_parameters() -> None: """ ) mock = st.load_instrument("mock") - p = getattr(mock, "gate_a") + p = mock.gate_a assert isinstance(p, Parameter) assert p.unit == "mV" assert p.label == "main gate" @@ -665,7 +665,7 @@ def test_setup_delegate_parameters() -> None: """ ) mock = st.load_instrument("mock") - p = getattr(mock, "gate_a") + p = mock.gate_a assert isinstance(p, DelegateParameter) assert p.unit == "mV" assert p.label == "main gate" From eb6dcde64e4766964baf53bcda9d0d857c55fa2b Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 07:57:56 +0200 Subject: [PATCH 02/43] Enable SIM117 --- ..._manager_for_performing_measurements.ipynb | 10 +- docs/examples/logging/logfile_parsing.ipynb | 5 +- docs/examples/logging/logging_example.ipynb | 22 +-- pyproject.toml | 2 +- src/qcodes/dataset/data_set_in_memory.py | 12 +- .../private/Keysight_344xxA_submodules.py | 5 +- .../dond/test_dond_keyboard_interrupts.py | 16 +-- .../test_measurement_context_manager.py | 51 ++++--- tests/dataset/test_data_set_cache.py | 126 +++++++++--------- .../test_database_creation_and_upgrading.py | 10 +- tests/dataset/test_database_extract_runs.py | 51 ++++--- tests/dataset/test_dataset_in_memory.py | 24 ++-- tests/dataset/test_fix_functions.py | 16 ++- tests/dataset/test_measurement_extensions.py | 44 +++--- tests/dataset/test_sqlite_base.py | 33 ++--- tests/dataset/test_sqlite_connection.py | 24 ++-- tests/drivers/test_cryomagnetics_4g.py | 22 +-- tests/drivers/test_cryomagnetics_TM620.py | 13 +- .../test_parameter_mixin_interdependent.py | 38 +++--- ...arameter_mixin_set_cache_value_on_reset.py | 80 +++++------ .../test_parameter_context_manager.py | 5 +- tests/test_instrument.py | 10 +- tests/test_logger.py | 36 ++--- 23 files changed, 343 insertions(+), 312 deletions(-) diff --git a/docs/examples/DataSet/Using_doNd_functions_in_comparison_to_Measurement_context_manager_for_performing_measurements.ipynb b/docs/examples/DataSet/Using_doNd_functions_in_comparison_to_Measurement_context_manager_for_performing_measurements.ipynb index 03c683f72e6d..fd2977868fcd 100644 --- a/docs/examples/DataSet/Using_doNd_functions_in_comparison_to_Measurement_context_manager_for_performing_measurements.ipynb +++ b/docs/examples/DataSet/Using_doNd_functions_in_comparison_to_Measurement_context_manager_for_performing_measurements.ipynb @@ -1736,9 +1736,8 @@ } ], "source": [ - "with qcodes.logger.console_level(\"DEBUG\"):\n", - " with qcodes.logger.filter_instrument(dac):\n", - " dond(set_only_sweep, dmm.v1, dmm.v2)" + "with qcodes.logger.console_level(\"DEBUG\"), qcodes.logger.filter_instrument(dac):\n", + " dond(set_only_sweep, dmm.v1, dmm.v2)" ] }, { @@ -1796,9 +1795,8 @@ } ], "source": [ - "with qcodes.logger.console_level(\"DEBUG\"):\n", - " with qcodes.logger.filter_instrument(dac):\n", - " dond(set_and_get_sweep, dmm.v1, dmm.v2)" + "with qcodes.logger.console_level(\"DEBUG\"), qcodes.logger.filter_instrument(dac):\n", + " dond(set_and_get_sweep, dmm.v1, dmm.v2)" ] }, { diff --git a/docs/examples/logging/logfile_parsing.ipynb b/docs/examples/logging/logfile_parsing.ipynb index 052d217ef29b..60c6d817ea87 100644 --- a/docs/examples/logging/logfile_parsing.ipynb +++ b/docs/examples/logging/logfile_parsing.ipynb @@ -53,9 +53,8 @@ "source": [ "# put the 30MB into a zip file\n", "filepath = os.path.join(os.getcwd(), \"static\", \"pythonlog.zip\")\n", - "with ZipFile(filepath) as z:\n", - " with z.open(\"pythonlog.log\", \"r\") as f:\n", - " my_log = [line.decode() for line in f]" + "with ZipFile(filepath) as z, z.open(\"pythonlog.log\", \"r\") as f:\n", + " my_log = [line.decode() for line in f]" ] }, { diff --git a/docs/examples/logging/logging_example.ipynb b/docs/examples/logging/logging_example.ipynb index aa68a1972c33..a639546cb3b7 100644 --- a/docs/examples/logging/logging_example.ipynb +++ b/docs/examples/logging/logging_example.ipynb @@ -292,9 +292,8 @@ ], "source": [ "driver.cartesian((0, 0, 0))\n", - "with logger.console_level(\"DEBUG\"):\n", - " with logger.filter_instrument(mag_x):\n", - " driver.cartesian((0, 0, 1))" + "with logger.console_level(\"DEBUG\"), logger.filter_instrument(mag_x):\n", + " driver.cartesian((0, 0, 1))" ] }, { @@ -330,9 +329,8 @@ ], "source": [ "driver.cartesian((0, 0, 0))\n", - "with logger.console_level(\"DEBUG\"):\n", - " with logger.filter_instrument((mag_x, mag_y)):\n", - " driver.cartesian((0, 0, 1))" + "with logger.console_level(\"DEBUG\"), logger.filter_instrument((mag_x, mag_y)):\n", + " driver.cartesian((0, 0, 1))" ] }, { @@ -1197,7 +1195,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -1321,10 +1319,12 @@ "source": [ "with logger.console_level(logging.WARN):\n", " driver.cartesian((0, 0, 0))\n", - " with capture_dataframe(level=\"DEBUG\") as (handler, get_dataframe):\n", - " with logger.filter_instrument(mag_x, handler=handler):\n", - " driver.cartesian((0, 0, 1))\n", - " df = get_dataframe()\n", + " with (\n", + " capture_dataframe(level=\"DEBUG\") as (handler, get_dataframe),\n", + " logger.filter_instrument(mag_x, handler=handler),\n", + " ):\n", + " driver.cartesian((0, 0, 1))\n", + " df = get_dataframe()\n", "df" ] }, diff --git a/pyproject.toml b/pyproject.toml index a26a807ad70a..c38b49dcdc88 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", "PYI059", # these are preview rules that are not yet stable but explicitly enabled. - "B009" + "B009", "SIM117" ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/dataset/data_set_in_memory.py b/src/qcodes/dataset/data_set_in_memory.py index 9eb12971a350..241b789ba3bb 100644 --- a/src/qcodes/dataset/data_set_in_memory.py +++ b/src/qcodes/dataset/data_set_in_memory.py @@ -614,11 +614,13 @@ def add_metadata(self, tag: str, metadata: Any) -> None: def _add_to_dyn_column_if_in_db(self, tag: str, data: Any) -> None: if self._dataset_is_in_runs_table(): - with contextlib.closing( - conn_from_dbpath_or_conn(conn=None, path_to_db=self._path_to_db) - ) as conn: - with atomic(conn) as aconn: - add_data_to_dynamic_columns(aconn, self.run_id, {tag: data}) + with ( + contextlib.closing( + conn_from_dbpath_or_conn(conn=None, path_to_db=self._path_to_db) + ) as conn, + atomic(conn) as aconn, + ): + add_data_to_dynamic_columns(aconn, self.run_id, {tag: data}) @property def metadata(self) -> dict[str, Any]: diff --git a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py index e35c0930b652..8d399d4b3c56 100644 --- a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py +++ b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py @@ -1172,9 +1172,8 @@ def _get_parameter(self, sense_function: str = "DC Voltage") -> float: The float value of the parameter. """ - with self.sense_function.set_to(sense_function): - with self.sample.count.set_to(1): - response = self.ask("READ?") + with self.sense_function.set_to(sense_function), self.sample.count.set_to(1): + response = self.ask("READ?") if float(response) >= 9.9e37: return np.inf diff --git a/tests/dataset/dond/test_dond_keyboard_interrupts.py b/tests/dataset/dond/test_dond_keyboard_interrupts.py index b236633d275b..390df2e1da41 100644 --- a/tests/dataset/dond/test_dond_keyboard_interrupts.py +++ b/tests/dataset/dond/test_dond_keyboard_interrupts.py @@ -9,9 +9,8 @@ def test_catch_interrupts(): assert get_interrupt() is None # Test KeyboardInterrupt - with pytest.raises(KeyboardInterrupt): - with catch_interrupts() as get_interrupt: - raise KeyboardInterrupt() + with pytest.raises(KeyboardInterrupt), catch_interrupts() as get_interrupt: + raise KeyboardInterrupt() # Test BreakConditionInterrupt with catch_interrupts() as get_interrupt: @@ -20,12 +19,11 @@ def test_catch_interrupts(): # Test that cleanup code runs for KeyboardInterrupt cleanup_ran = False - with pytest.raises(KeyboardInterrupt): - with catch_interrupts(): - try: - raise KeyboardInterrupt() - finally: - cleanup_ran = True + with pytest.raises(KeyboardInterrupt), catch_interrupts(): + try: + raise KeyboardInterrupt() + finally: + cleanup_ran = True assert cleanup_ran # Test that cleanup code runs for BreakConditionInterrupt diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 59c7378ad6aa..b316d86c5ca2 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -7,7 +7,7 @@ import traceback from functools import reduce from time import sleep -from typing import Any +from typing import TYPE_CHECKING, Any import hypothesis.strategies as hst import numpy as np @@ -25,7 +25,7 @@ FrozenInterDependencies_, InterDependencies_, ) -from qcodes.dataset.experiment_container import new_experiment +from qcodes.dataset.experiment_container import Experiment, new_experiment from qcodes.dataset.export_config import DataExportType from qcodes.dataset.measurements import Measurement from qcodes.dataset.sqlite.connection import atomic_transaction @@ -40,6 +40,9 @@ from qcodes.validators import Arrays, ComplexNumbers from tests.common import retry_until_does_not_throw +if TYPE_CHECKING: + from qcodes.instrument_drivers.mock_instruments import DummyInstrument + def test_log_messages(caplog: LogCaptureFixture, meas_with_registered_param) -> None: caplog.set_level(logging.INFO) @@ -747,7 +750,9 @@ def test_datasaver_scalars( # More assertions of setpoints, labels and units in the DB! -def test_datasaver_inst_metadata(experiment, DAC_with_metadata, DMM) -> None: +def test_datasaver_inst_metadata( + experiment: Experiment, DAC_with_metadata: DummyInstrument, DMM: DummyInstrument +) -> None: """ Check that additional instrument metadata is captured into the dataset snapshot """ @@ -770,7 +775,7 @@ def test_datasaver_inst_metadata(experiment, DAC_with_metadata, DMM) -> None: def test_exception_happened_during_measurement_is_stored_in_dataset_metadata( - experiment, + experiment: Experiment, ) -> None: meas = Measurement() meas.register_custom_parameter(name="nodata") @@ -780,11 +785,13 @@ class SomeMeasurementException(Exception): dataset = None # `pytest.raises`` is used here instead of custom try-except for convenience - with pytest.raises(SomeMeasurementException, match="foo") as e: - with meas.run() as datasaver: - dataset = datasaver.dataset + with ( + pytest.raises(SomeMeasurementException, match="foo") as e, + meas.run() as datasaver, + ): + dataset = datasaver.dataset - raise SomeMeasurementException("foo") + raise SomeMeasurementException("foo") assert dataset is not None metadata = dataset.metadata assert "measurement_exception" in metadata @@ -1355,10 +1362,12 @@ def test_datasaver_parameter_with_setpoints_that_are_different_raises( assert dep_ps in meas._interdeps.dependencies[param_ps] - with meas.run() as datasaver: + with ( + meas.run() as datasaver, + pytest.raises(ValueError, match="Multiple distinct values found for"), + ): # This fails because a 2D PWS expects 2D setpoints parameter values (ie a grid) - with pytest.raises(ValueError, match="Multiple distinct values found for"): - datasaver.add_result((param, param.get()), (sp_param_1, sp_param_1.get())) + datasaver.add_result((param, param.get()), (sp_param_1, sp_param_1.get())) @pytest.mark.parametrize("bg_writing", [True, False]) @@ -1542,8 +1551,9 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing_validator( param.setpoints = () - with meas.run(write_in_background=bg_writing) as datasaver: - with pytest.raises( + with ( + meas.run(write_in_background=bg_writing) as datasaver, + pytest.raises( ValueError, match=r"Shape of output is not" r" consistent with setpoints." @@ -1554,11 +1564,13 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing_validator( r"shape \(\)', 'getting dummy_" r"channel_inst_ChanA_dummy_" r"parameter_with_setpoints", - ): - datasaver.add_result(*expand_setpoints_helper(param)) + ), + ): + datasaver.add_result(*expand_setpoints_helper(param)) - with meas.run(write_in_background=bg_writing) as datasaver: - with pytest.raises( + with ( + meas.run(write_in_background=bg_writing) as datasaver, + pytest.raises( ValueError, match=r"Shape of output is not" r" consistent with setpoints." @@ -1569,8 +1581,9 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing_validator( r"shape \(\)', 'getting dummy_" r"channel_inst_ChanA_dummy_" r"parameter_with_setpoints", - ): - datasaver.add_result((param, param.get())) + ), + ): + datasaver.add_result((param, param.get())) @pytest.mark.parametrize("bg_writing", [True, False]) diff --git a/tests/dataset/test_data_set_cache.py b/tests/dataset/test_data_set_cache.py index 486fd1b8415b..06b606193c50 100644 --- a/tests/dataset/test_data_set_cache.py +++ b/tests/dataset/test_data_set_cache.py @@ -134,41 +134,43 @@ def test_cache_standalone( for param in meas_parameters2: meas2.register_parameter(param) - with meas1.run( - write_in_background=bg_writing, in_memory_cache=in_memory_cache - ) as datasaver1: - with meas2.run( + with ( + meas1.run( write_in_background=bg_writing, in_memory_cache=in_memory_cache - ) as datasaver2: - dataset1 = datasaver1.dataset - dataset2 = datasaver2.dataset - _assert_parameter_data_is_identical( - dataset1.get_parameter_data(), dataset1.cache.data() - ) - _assert_parameter_data_is_identical( - dataset2.get_parameter_data(), dataset2.cache.data() - ) - for _ in range(n_points): - meas_vals1 = [(param, param.get()) for param in meas_parameters1] + ) as datasaver1, + meas2.run( + write_in_background=bg_writing, in_memory_cache=in_memory_cache + ) as datasaver2, + ): + dataset1 = datasaver1.dataset + dataset2 = datasaver2.dataset + _assert_parameter_data_is_identical( + dataset1.get_parameter_data(), dataset1.cache.data() + ) + _assert_parameter_data_is_identical( + dataset2.get_parameter_data(), dataset2.cache.data() + ) + for _ in range(n_points): + meas_vals1 = [(param, param.get()) for param in meas_parameters1] - datasaver1.add_result(*meas_vals1) - datasaver1.flush_data_to_database(block=True) + datasaver1.add_result(*meas_vals1) + datasaver1.flush_data_to_database(block=True) - meas_vals2 = [(param, param.get()) for param in meas_parameters2] + meas_vals2 = [(param, param.get()) for param in meas_parameters2] - datasaver2.add_result(*meas_vals2) - datasaver2.flush_data_to_database(block=True) + datasaver2.add_result(*meas_vals2) + datasaver2.flush_data_to_database(block=True) - _assert_parameter_data_is_identical( - dataset1.get_parameter_data(), - dataset1.cache.data(), - shaped_partial=set_shape, - ) - _assert_parameter_data_is_identical( - dataset2.get_parameter_data(), - dataset2.cache.data(), - shaped_partial=set_shape, - ) + _assert_parameter_data_is_identical( + dataset1.get_parameter_data(), + dataset1.cache.data(), + shaped_partial=set_shape, + ) + _assert_parameter_data_is_identical( + dataset2.get_parameter_data(), + dataset2.cache.data(), + shaped_partial=set_shape, + ) _assert_parameter_data_is_identical( dataset1.get_parameter_data(), dataset1.cache.data() ) @@ -316,43 +318,45 @@ def test_cache_1d( for param in meas_parameters2: meas2.register_parameter(param, setpoints=(setpoints_param,)) - with meas1.run( - write_in_background=bg_writing, in_memory_cache=in_memory_cache - ) as datasaver1: - with meas2.run( + with ( + meas1.run( write_in_background=bg_writing, in_memory_cache=in_memory_cache - ) as datasaver2: - dataset1 = datasaver1.dataset - dataset2 = datasaver2.dataset - _assert_parameter_data_is_identical( - dataset1.get_parameter_data(), dataset1.cache.data() - ) - _assert_parameter_data_is_identical( - dataset2.get_parameter_data(), dataset2.cache.data() - ) - for v in setpoints_values: - setpoints_param.set(v) + ) as datasaver1, + meas2.run( + write_in_background=bg_writing, in_memory_cache=in_memory_cache + ) as datasaver2, + ): + dataset1 = datasaver1.dataset + dataset2 = datasaver2.dataset + _assert_parameter_data_is_identical( + dataset1.get_parameter_data(), dataset1.cache.data() + ) + _assert_parameter_data_is_identical( + dataset2.get_parameter_data(), dataset2.cache.data() + ) + for v in setpoints_values: + setpoints_param.set(v) - meas_vals1 = [(param, param.get()) for param in meas_parameters1] + meas_vals1 = [(param, param.get()) for param in meas_parameters1] - datasaver1.add_result((setpoints_param, v), *meas_vals1) - datasaver1.flush_data_to_database(block=True) + datasaver1.add_result((setpoints_param, v), *meas_vals1) + datasaver1.flush_data_to_database(block=True) - meas_vals2 = [(param, param.get()) for param in meas_parameters2] + meas_vals2 = [(param, param.get()) for param in meas_parameters2] - datasaver2.add_result((setpoints_param, v), *meas_vals2) - datasaver2.flush_data_to_database(block=True) + datasaver2.add_result((setpoints_param, v), *meas_vals2) + datasaver2.flush_data_to_database(block=True) - _assert_parameter_data_is_identical( - dataset1.get_parameter_data(), - dataset1.cache.data(), - shaped_partial=set_shape, - ) - _assert_parameter_data_is_identical( - dataset2.get_parameter_data(), - dataset2.cache.data(), - shaped_partial=set_shape, - ) + _assert_parameter_data_is_identical( + dataset1.get_parameter_data(), + dataset1.cache.data(), + shaped_partial=set_shape, + ) + _assert_parameter_data_is_identical( + dataset2.get_parameter_data(), + dataset2.cache.data(), + shaped_partial=set_shape, + ) _assert_parameter_data_is_identical( dataset1.get_parameter_data(), dataset1.cache.data() ) diff --git a/tests/dataset/test_database_creation_and_upgrading.py b/tests/dataset/test_database_creation_and_upgrading.py index e8266b281413..b63f69ebf2df 100644 --- a/tests/dataset/test_database_creation_and_upgrading.py +++ b/tests/dataset/test_database_creation_and_upgrading.py @@ -246,10 +246,12 @@ def test_initialised_database_at_restores_db_location_on_error(tmp_path: Path) - db_location = str(tmp_path / "context_err.db") original_location = qc.config["core"]["db_location"] - with pytest.raises(RuntimeError, match="intentional"): - with initialised_database_at(db_location): - assert qc.config["core"]["db_location"] == db_location - raise RuntimeError("intentional") + with ( + pytest.raises(RuntimeError, match="intentional"), + initialised_database_at(db_location), + ): + assert qc.config["core"]["db_location"] == db_location + raise RuntimeError("intentional") assert qc.config["core"]["db_location"] == original_location diff --git a/tests/dataset/test_database_extract_runs.py b/tests/dataset/test_database_extract_runs.py index 7b0d727e8d49..f30a126facc2 100644 --- a/tests/dataset/test_database_extract_runs.py +++ b/tests/dataset/test_database_extract_runs.py @@ -752,18 +752,17 @@ def test_old_versions_not_touched( # First test that we cannot use an old version as source - with raise_if_file_changed(fixturepath): - with pytest.warns(UserWarning) as warning: - extract_runs_into_db(fixturepath, target_path, 1) - expected_mssg = ( - "Source DB version is 2, but this " - f"function needs it to be in version {new_v}. " - "Run this function again with " - "upgrade_source_db=True to auto-upgrade " - "the source DB file." - ) - assert isinstance(warning[0].message, Warning) - assert warning[0].message.args[0] == expected_mssg + with raise_if_file_changed(fixturepath), pytest.warns(UserWarning) as warning: + extract_runs_into_db(fixturepath, target_path, 1) + expected_mssg = ( + "Source DB version is 2, but this " + f"function needs it to be in version {new_v}. " + "Run this function again with " + "upgrade_source_db=True to auto-upgrade " + "the source DB file." + ) + assert isinstance(warning[0].message, Warning) + assert warning[0].message.args[0] == expected_mssg # Then test that we cannot use an old version as target @@ -777,18 +776,17 @@ def test_old_versions_not_touched( source_ds.add_results([{name: 0.0 for name in some_interdeps[1].names}]) source_ds.mark_completed() - with raise_if_file_changed(fixturepath): - with pytest.warns(UserWarning) as warning: - extract_runs_into_db(source_path, fixturepath, 1) - expected_mssg = ( - "Target DB version is 2, but this " - f"function needs it to be in version {new_v}. " - "Run this function again with " - "upgrade_target_db=True to auto-upgrade " - "the target DB file." - ) - assert isinstance(warning[0].message, Warning) - assert warning[0].message.args[0] == expected_mssg + with raise_if_file_changed(fixturepath), pytest.warns(UserWarning) as warning: + extract_runs_into_db(source_path, fixturepath, 1) + expected_mssg = ( + "Target DB version is 2, but this " + f"function needs it to be in version {new_v}. " + "Run this function again with " + "upgrade_target_db=True to auto-upgrade " + "the target DB file." + ) + assert isinstance(warning[0].message, Warning) + assert warning[0].message.args[0] == expected_mssg def test_experiments_with_NULL_sample_name( @@ -909,11 +907,10 @@ def test_atomicity(two_empty_temp_db_connections, some_interdeps) -> None: source_ds_1.mark_completed() # now check that the target file is untouched - with raise_if_file_changed(target_path): + with raise_if_file_changed(target_path), pytest.raises(RuntimeError): # although the not completed error is a ValueError, we get the # RuntimeError from SQLite - with pytest.raises(RuntimeError): - extract_runs_into_db(source_path, target_path, 1, 2) + extract_runs_into_db(source_path, target_path, 1, 2) def test_column_mismatch(two_empty_temp_db_connections, some_interdeps, inst) -> None: diff --git a/tests/dataset/test_dataset_in_memory.py b/tests/dataset/test_dataset_in_memory.py index 46825eca5704..f5e24c8c31d6 100644 --- a/tests/dataset/test_dataset_in_memory.py +++ b/tests/dataset/test_dataset_in_memory.py @@ -178,19 +178,21 @@ def test_dataset_in_memory_reload_from_db_3d( def test_dataset_in_memory_without_cache_raises( meas_with_registered_param, DMM, DAC, tmp_path ) -> None: - with pytest.raises( - RuntimeError, - match=re.escape( - "Cannot disable the in memory cache for a dataset that is only in memory." + with ( + pytest.raises( + RuntimeError, + match=re.escape( + "Cannot disable the in memory cache for a dataset that is only in memory." + ), ), - ): - with meas_with_registered_param.run( + meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem, in_memory_cache=False - ) as datasaver: - for set_v in np.linspace(0, 25, 10): - DAC.ch1.set(set_v) - get_v = DMM.v1() - datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) + ) as datasaver, + ): + for set_v in np.linspace(0, 25, 10): + DAC.ch1.set(set_v) + get_v = DMM.v1() + datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) def test_dataset_in_memory_reload_from_db_complex( diff --git a/tests/dataset/test_fix_functions.py b/tests/dataset/test_fix_functions.py index 80155811b298..bececdbe3e0d 100644 --- a/tests/dataset/test_fix_functions.py +++ b/tests/dataset/test_fix_functions.py @@ -55,9 +55,11 @@ def test_version_4a_bugfix_raises() -> None: skip_if_no_fixtures(dbname_old) - with temporarily_copied_DB(dbname_old, debug=False, version=3) as conn: - with pytest.raises(RuntimeError): - fix_version_4a_run_description_bug(conn) + with ( + temporarily_copied_DB(dbname_old, debug=False, version=3) as conn, + pytest.raises(RuntimeError), + ): + fix_version_4a_run_description_bug(conn) def test_fix_wrong_run_descriptions() -> None: @@ -107,6 +109,8 @@ def test_fix_wrong_run_descriptions_raises() -> None: skip_if_no_fixtures(dbname_old) - with temporarily_copied_DB(dbname_old, debug=False, version=4) as conn: - with pytest.raises(RuntimeError): - fix_wrong_run_descriptions(conn, [1]) + with ( + temporarily_copied_DB(dbname_old, debug=False, version=4) as conn, + pytest.raises(RuntimeError), + ): + fix_wrong_run_descriptions(conn, [1]) diff --git a/tests/dataset/test_measurement_extensions.py b/tests/dataset/test_measurement_extensions.py index 6531131ae48f..56fb450cc392 100644 --- a/tests/dataset/test_measurement_extensions.py +++ b/tests/dataset/test_measurement_extensions.py @@ -325,17 +325,19 @@ def test_dond_into_fails_with_together_sweeps( core_test_measurement = Measurement(name="core_test_1", exp=experiment) core_test_measurement.register_parameter(set1) core_test_measurement.register_parameter(meas1, setpoints=[set1]) - with pytest.raises(ValueError, match="dond_into does not support TogetherSweeps"): - with core_test_measurement.run() as datasaver: - sweep1 = LinSweep(set1, 0, 5, 11, 0.001) - sweep2 = LinSweep(set2, 10, 20, 11, 0.001) + with ( + pytest.raises(ValueError, match="dond_into does not support TogetherSweeps"), + core_test_measurement.run() as datasaver, + ): + sweep1 = LinSweep(set1, 0, 5, 11, 0.001) + sweep2 = LinSweep(set2, 10, 20, 11, 0.001) - dond_into( - datasaver, - TogetherSweep(sweep1, sweep2), # pyright: ignore [reportArgumentType] - meas1, - ) - _ = datasaver.dataset + dond_into( + datasaver, + TogetherSweep(sweep1, sweep2), # pyright: ignore [reportArgumentType] + meas1, + ) + _ = datasaver.dataset def test_dond_into_fails_with_groups(default_params, default_database_and_experiment): @@ -345,18 +347,18 @@ def test_dond_into_fails_with_groups(default_params, default_database_and_experi core_test_measurement = Measurement(name="core_test_1", exp=experiment) core_test_measurement.register_parameter(set1) core_test_measurement.register_parameter(meas1, setpoints=[set1]) - with pytest.raises( - ValueError, match="dond_into does not support multiple datasets" + with ( + pytest.raises(ValueError, match="dond_into does not support multiple datasets"), + core_test_measurement.run() as datasaver, ): - with core_test_measurement.run() as datasaver: - sweep1 = LinSweep(set1, 0, 5, 11, 0.001) - dond_into( - datasaver, - sweep1, - [meas1], # pyright: ignore [reportArgumentType] - [meas2], # pyright: ignore [reportArgumentType] - ) - _ = datasaver.dataset + sweep1 = LinSweep(set1, 0, 5, 11, 0.001) + dond_into( + datasaver, + sweep1, + [meas1], # pyright: ignore [reportArgumentType] + [meas2], # pyright: ignore [reportArgumentType] + ) + _ = datasaver.dataset def test_context_with_multiple_experiments( diff --git a/tests/dataset/test_sqlite_base.py b/tests/dataset/test_sqlite_base.py index d55ec2f00f9c..d01b40f41861 100644 --- a/tests/dataset/test_sqlite_base.py +++ b/tests/dataset/test_sqlite_base.py @@ -167,9 +167,8 @@ def test_atomic_raises(experiment) -> None: bad_sql = '""' - with pytest.raises(RuntimeError) as excinfo: - with mut_conn.atomic(conn): - mut_conn.transaction(conn, bad_sql) + with pytest.raises(RuntimeError) as excinfo, mut_conn.atomic(conn): + mut_conn.transaction(conn, bad_sql) assert error_caused_by(excinfo, "syntax error") @@ -404,20 +403,22 @@ def just_throw(*args): # first we patch add_data_to_dynamic_columns to throw an exception # if create_data is not atomic this would create a partial # run in the db. Causing the next create_run to fail - with patch( - "qcodes.dataset.sqlite.queries.add_data_to_dynamic_columns", new=just_throw - ): - with pytest.raises( + with ( + patch( + "qcodes.dataset.sqlite.queries.add_data_to_dynamic_columns", new=just_throw + ), + pytest.raises( RuntimeError, match="Rolling back due to unhandled exception" - ) as e: - mut_queries.create_run( - experiment.conn, - experiment.exp_id, - name="testrun", - guid=generate_guid(), - description=simple_run_describer, - metadata={"a": 1}, - ) + ) as e, + ): + mut_queries.create_run( + experiment.conn, + experiment.exp_id, + name="testrun", + guid=generate_guid(), + description=simple_run_describer, + metadata={"a": 1}, + ) assert error_caused_by(e, "This breaks adding metadata") # since we are starting from an empty database and the above transaction # should be rolled back there should be no runs in the run table diff --git a/tests/dataset/test_sqlite_connection.py b/tests/dataset/test_sqlite_connection.py index 2b37da071500..62eb6e33b4b4 100644 --- a/tests/dataset/test_sqlite_connection.py +++ b/tests/dataset/test_sqlite_connection.py @@ -58,9 +58,8 @@ def test_atomic_raises_for_non_atomic_conn() -> None: "atomic context manager only accepts AtomicConnection " "database connection objects." ) - with pytest.raises(ValueError, match=match_str): - with atomic(sqlite_conn): # type: ignore[arg-type] - pass + with pytest.raises(ValueError, match=match_str), atomic(sqlite_conn): # type: ignore[arg-type] + pass def test_atomic() -> None: @@ -93,12 +92,14 @@ def test_atomic_with_exception() -> None: assert 25 == sqlite_conn.execute("PRAGMA user_version").fetchall()[0][0] - with pytest.raises( - RuntimeError, match="Rolling back due to unhandled exception" - ) as e: - with atomic(sqlite_conn) as atomic_conn: - atomic_conn.execute("PRAGMA user_version(42)") - raise Exception("intended exception") + with ( + pytest.raises( + RuntimeError, match="Rolling back due to unhandled exception" + ) as e, + atomic(sqlite_conn) as atomic_conn, + ): + atomic_conn.execute("PRAGMA user_version(42)") + raise Exception("intended exception") assert error_caused_by(e, "intended exception") assert 25 == sqlite_conn.execute("PRAGMA user_version").fetchall()[0][0] @@ -115,9 +116,8 @@ def test_atomic_on_outmost_connection_that_is_in_transaction() -> None: "Please commit those before starting an atomic " "transaction." ) - with pytest.raises(RuntimeError, match=match_str): - with atomic(conn): - pass + with pytest.raises(RuntimeError, match=match_str), atomic(conn): + pass @pytest.mark.parametrize("in_transaction", (True, False)) diff --git a/tests/drivers/test_cryomagnetics_4g.py b/tests/drivers/test_cryomagnetics_4g.py index ac9943cf6d48..23d0906669fa 100644 --- a/tests/drivers/test_cryomagnetics_4g.py +++ b/tests/drivers/test_cryomagnetics_4g.py @@ -95,16 +95,16 @@ def test_set_field_successful( ) -> None: with ( patch.object(cryo_instrument, "write") as mock_write, + caplog.at_level(logging.WARNING), ): - with caplog.at_level(logging.WARNING): - cryo_instrument.set_field(0.1, block=False) - calls = [ - call - for call in mock_write.call_args_list - if "LLIM" in call[0][0] or "SWEEP" in call[0][0] - ] - assert any("SWEEP UP" in str(call) for call in calls) - assert "Magnetic field is ramping but not currently blocked!" in caplog.text + cryo_instrument.set_field(0.1, block=False) + calls = [ + call + for call in mock_write.call_args_list + if "LLIM" in call[0][0] or "SWEEP" in call[0][0] + ] + assert any("SWEEP UP" in str(call) for call in calls) + assert "Magnetic field is ramping but not currently blocked!" in caplog.text def test_set_field_blocking(cryo_instrument: CryomagneticsModel4G) -> None: @@ -153,9 +153,9 @@ def mock_time() -> float: "qcodes.instrument_drivers.cryomagnetics._cryomagnetics4g._time", side_effect=mock_time, ), + pytest.raises(Cryomagnetics4GException, match=r"Timeout|stabilized"), ): - with pytest.raises(Cryomagnetics4GException, match=r"Timeout|stabilized"): - cryo_instrument.wait_while_ramping(1.0, threshold=1e-4) + cryo_instrument.wait_while_ramping(1.0, threshold=1e-4) def test_wait_while_ramping_success(cryo_instrument: CryomagneticsModel4G) -> None: diff --git a/tests/drivers/test_cryomagnetics_TM620.py b/tests/drivers/test_cryomagnetics_TM620.py index 294f69ba4568..5608e9b816a5 100644 --- a/tests/drivers/test_cryomagnetics_TM620.py +++ b/tests/drivers/test_cryomagnetics_TM620.py @@ -47,9 +47,11 @@ def test_parse_output_valid(tm620): def test_parse_output_invalid(tm620, caplog): - with caplog.at_level("ERROR"): - with pytest.raises(ValueError, match="No floating point number found"): - tm620._parse_output("Invalid output") + with ( + caplog.at_level("ERROR"), + pytest.raises(ValueError, match="No floating point number found"), + ): + tm620._parse_output("Invalid output") assert "No floating point number found in output" in caplog.text @@ -59,7 +61,6 @@ def test_convert_to_numerics_valid(tm620): def test_convert_to_numerics_invalid(tm620, caplog): - with caplog.at_level("ERROR"): - with pytest.raises(ValueError, match="Unable to convert"): - tm620._convert_to_numeric("not_a_number") + with caplog.at_level("ERROR"), pytest.raises(ValueError, match="Unable to convert"): + tm620._convert_to_numeric("not_a_number") assert "Error converting 'not_a_number' to float" in caplog.text diff --git a/tests/extensions/parameters/test_parameter_mixin_interdependent.py b/tests/extensions/parameters/test_parameter_mixin_interdependent.py index 889ecf520665..88b8a8aa97bd 100644 --- a/tests/extensions/parameters/test_parameter_mixin_interdependent.py +++ b/tests/extensions/parameters/test_parameter_mixin_interdependent.py @@ -159,25 +159,27 @@ def test_error_on_non_interdependent_dependency(store, mock_instr) -> None: ) """A non-interdependent parameter.""" - with pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"): - with pytest.raises( + with ( + pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"), + pytest.raises( KeyError, match="Duplicate parameter name managed_param on instrument" - ): - with pytest.raises( - TypeError, match="must be an instance of InterdependentParameterMixin" - ): - mock_instr.managed_param = cast( - "InterdependentParameter", - mock_instr.add_parameter( - name="managed_param", - parameter_class=InterdependentParameter, - dependent_on=["not_interdependent_param"], - set_cmd=lambda x: store.update({"managed": x}), - get_cmd=lambda: store.get("managed"), - docstring="Parameter managed_param depends on a non-interdependent param.", - ), - ) - """Parameter managed_param depends on a non-interdependent param.""" + ), + pytest.raises( + TypeError, match="must be an instance of InterdependentParameterMixin" + ), + ): + mock_instr.managed_param = cast( + "InterdependentParameter", + mock_instr.add_parameter( + name="managed_param", + parameter_class=InterdependentParameter, + dependent_on=["not_interdependent_param"], + set_cmd=lambda x: store.update({"managed": x}), + get_cmd=lambda: store.get("managed"), + docstring="Parameter managed_param depends on a non-interdependent param.", + ), + ) + """Parameter managed_param depends on a non-interdependent param.""" def test_parsers_and_dependency_propagation(store, mock_instr) -> None: diff --git a/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py b/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py index 7bc80a0177d7..2977785e3375 100644 --- a/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py +++ b/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py @@ -135,34 +135,36 @@ def test_direct_cache_update_and_reset(store, reset_instr) -> None: assert test_param.get() == 50 -def test_error_if_get_cmd_supplied(reset_instr) -> None: - with pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"): - # with pytest.raises(KeyError, match="Duplicate parameter name managed_param on instrument"): - with pytest.raises(TypeError, match="without 'get_cmd'"): - reset_instr.add_parameter( - name="test_param_error", - parameter_class=ResetTestParameter, - group_names=["reset_group_general"], - cache_value_after_reset=42, - set_cmd=lambda x: None, - get_cmd=lambda: 100, - docstring="A parameter incorrectly supplying get_cmd.", - ) - - -def test_error_if_get_parser_supplied(reset_instr) -> None: - with pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"): - # with pytest.raises(KeyError, match="Duplicate parameter name managed_param on instrument"): - with pytest.raises(TypeError, match="Supplying 'get_parser' is not allowed"): - reset_instr.add_parameter( - name="test_param_get_parser_error", - parameter_class=ResetTestParameter, - group_names=["reset_group_general"], - cache_value_after_reset=42, - set_cmd=lambda x: None, - get_parser=lambda x: x + 1, - docstring="A parameter incorrectly supplying get_parser.", - ) +def test_error_if_get_cmd_supplied(reset_instr: MockResetInstrument) -> None: + with ( + pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"), + pytest.raises(TypeError, match="without 'get_cmd'"), + ): + reset_instr.add_parameter( + name="test_param_error", + parameter_class=ResetTestParameter, + group_names=["reset_group_general"], + cache_value_after_reset=42, + set_cmd=lambda x: None, + get_cmd=lambda: 100, + docstring="A parameter incorrectly supplying get_cmd.", + ) + + +def test_error_if_get_parser_supplied(reset_instr: MockResetInstrument) -> None: + with ( + pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"), + pytest.raises(TypeError, match="Supplying 'get_parser' is not allowed"), + ): + reset_instr.add_parameter( + name="test_param_get_parser_error", + parameter_class=ResetTestParameter, + group_names=["reset_group_general"], + cache_value_after_reset=42, + set_cmd=lambda x: None, + get_parser=lambda x: x + 1, + docstring="A parameter incorrectly supplying get_parser.", + ) def test_parameter_in_multiple_reset_groups(store, reset_instr) -> None: @@ -227,14 +229,14 @@ def test_warning_if_group_names_missing(store, reset_instr): def test_typeerror_if_group_names_invalid(store, reset_instr): - with pytest.warns(QCoDeSDeprecationWarning): - with pytest.raises( - TypeError, match="group_names must be a list of strings or None" - ): - reset_instr.add_parameter( - name="test_param", - parameter_class=ResetTestParameter, - cache_value_after_reset=42, - group_names=123, - set_cmd=lambda x: store.update({"reset_param": x}), - ) + with ( + pytest.warns(QCoDeSDeprecationWarning), + pytest.raises(TypeError, match="group_names must be a list of strings or None"), + ): + reset_instr.add_parameter( + name="test_param", + parameter_class=ResetTestParameter, + cache_value_after_reset=42, + group_names=123, + set_cmd=lambda x: store.update({"reset_param": x}), + ) diff --git a/tests/parameter/test_parameter_context_manager.py b/tests/parameter/test_parameter_context_manager.py index 09171ad115ec..a735844e52d5 100644 --- a/tests/parameter/test_parameter_context_manager.py +++ b/tests/parameter/test_parameter_context_manager.py @@ -279,7 +279,6 @@ def test_reset_at_exit_with_allow_changes_false( ) -> None: p = instrument.a p.set(2) - with p.restore_at_exit(allow_changes=False): - with pytest.raises(TypeError): - p.set(5) + with p.restore_at_exit(allow_changes=False), pytest.raises(TypeError): + p.set(5) assert p() == 2 diff --git a/tests/test_instrument.py b/tests/test_instrument.py index cbd4ce126319..111f502b755a 100644 --- a/tests/test_instrument.py +++ b/tests/test_instrument.py @@ -123,11 +123,13 @@ def test_instrument_fail() -> None: @pytest.mark.usefixtures("close_before_and_after") def test_instrument_on_invalid_identifier() -> None: # Check if warning and error raised when invalid identifer name given - with pytest.warns( - UserWarning, match="Changed !-name to !_name for instrument identifier" + with ( + pytest.warns( + UserWarning, match="Changed !-name to !_name for instrument identifier" + ), + pytest.raises(ValueError, match="!_name invalid instrument identifier"), ): - with pytest.raises(ValueError, match="!_name invalid instrument identifier"): - DummyInstrument(name="!-name") + DummyInstrument(name="!-name") assert Instrument.instances() == [] assert DummyInstrument.instances() == [] diff --git a/tests/test_logger.py b/tests/test_logger.py index a148a9657caa..624fcddc6afb 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -149,9 +149,8 @@ def test_start_logger_twice() -> None: def test_set_level_without_starting_raises() -> None: - with pytest.raises(RuntimeError): - with logger.console_level("DEBUG"): - pass + with pytest.raises(RuntimeError), logger.console_level("DEBUG"): + pass assert len(logging.getLogger().handlers) == NUM_PYTEST_LOGGERS @@ -161,10 +160,12 @@ def test_handler_level() -> None: logging.debug(TEST_LOG_MESSAGE) assert logs.value == "" - with logger.LogCapture(level=logging.INFO) as logs: - with logger.handler_level(level=logging.DEBUG, handler=logs.string_handler): - print(logs.string_handler) - logging.debug(TEST_LOG_MESSAGE) + with ( + logger.LogCapture(level=logging.INFO) as logs, + logger.handler_level(level=logging.DEBUG, handler=logs.string_handler), + ): + print(logs.string_handler) + logging.debug(TEST_LOG_MESSAGE) assert logs.value.strip() == TEST_LOG_MESSAGE @@ -177,9 +178,11 @@ def test_filter_instrument( # filter one instrument driver.cartesian((0, 0, 0)) - with logger.LogCapture(level=logging.DEBUG) as logs: - with logger.filter_instrument(mag_x, handler=logs.string_handler): - driver.cartesian((0, 0, 1)) + with ( + logger.LogCapture(level=logging.DEBUG) as logs, + logger.filter_instrument(mag_x, handler=logs.string_handler), + ): + driver.cartesian((0, 0, 1)) for line in logs.value.splitlines(): assert "[x(AMIModel430)]" in line assert "[y(AMIModel430)]" not in line @@ -187,9 +190,11 @@ def test_filter_instrument( # filter multiple instruments driver.cartesian((0, 0, 0)) - with logger.LogCapture(level=logging.DEBUG) as logs: - with logger.filter_instrument((mag_x, mag_y), handler=logs.string_handler): - driver.cartesian((0, 0, 1)) + with ( + logger.LogCapture(level=logging.DEBUG) as logs, + logger.filter_instrument((mag_x, mag_y), handler=logs.string_handler), + ): + driver.cartesian((0, 0, 1)) any_x = False any_y = False @@ -214,9 +219,8 @@ def test_filter_without_started_logger_raises( # filter one instrument driver.cartesian((0, 0, 0)) - with pytest.raises(RuntimeError): - with logger.filter_instrument(mag_x): - pass + with pytest.raises(RuntimeError), logger.filter_instrument(mag_x): + pass def test_capture_dataframe() -> None: From b86755e109833bcb636eec48e83f27d7e4dcd5fc Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 08:01:24 +0200 Subject: [PATCH 03/43] Enable SIM905 --- pyproject.toml | 2 +- tests/conftest.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c38b49dcdc88..8cdfe1d077f8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", "PYI059", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117" + "B009", "SIM117", "SIM905" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/tests/conftest.py b/tests/conftest.py index eae647bbd852..2018a865df69 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -38,7 +38,7 @@ def pytest_configure(config: pytest.Config) -> None: def pytest_runtest_setup(item: pytest.Item) -> None: - ALL = set("darwin linux win32".split()) + ALL = set(["darwin", "linux", "win32"]) supported_platforms = ALL.intersection(mark.name for mark in item.iter_markers()) if supported_platforms and sys.platform not in supported_platforms: pytest.skip(f"cannot run on platform {sys.platform}") From c284be8b20b4f9be253ddff2534afb53757c0e99 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 08:01:47 +0200 Subject: [PATCH 04/43] This rule is now stable --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 8cdfe1d077f8..35f330678287 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -250,7 +250,7 @@ select = [ "PLR", "PLC", "PLW", "W", "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", - "RUF027", "PYI059", # these are preview rules that are not yet stable but explicitly enabled. + "RUF027", # these are preview rules that are not yet stable but explicitly enabled. "B009", "SIM117", "SIM905" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages From 2ecca1233375c870c1d903ecaf937c746dfe0d11 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 08:14:28 +0200 Subject: [PATCH 05/43] Enable SIM102 --- pyproject.toml | 2 +- src/qcodes/dataset/data_set_cache.py | 8 +++-- src/qcodes/dataset/dond/do_2d.py | 5 ++- src/qcodes/dataset/dond/do_nd.py | 5 ++- src/qcodes/dataset/export_config.py | 5 ++- src/qcodes/dataset/guids.py | 15 ++++----- src/qcodes/dataset/plotting.py | 21 +++++++----- src/qcodes/dataset/sqlite/queries.py | 7 ++-- .../parameter_mixin_group_registry.py | 9 +++-- src/qcodes/instrument/channel.py | 9 +++-- src/qcodes/instrument/instrument_base.py | 5 ++- .../instrument_drivers/AlazarTech/ATS.py | 13 ++++---- .../Keysight/keysightb1500/KeysightB1517A.py | 33 +++++++++++-------- .../Keysight/keysightb1500/KeysightB1520A.py | 15 ++++----- .../DynaCoolPPMS/private/server.py | 7 ++-- .../american_magnetics/AMI430_visa.py | 5 ++- .../oxford/MercuryiPS_VISA.py | 5 ++- src/qcodes/parameters/group_parameter.py | 5 ++- src/qcodes/utils/delaykeyboardinterrupt.py | 9 +++-- src/qcodes/utils/function_helpers.py | 5 ++- src/qcodes/validators/validators.py | 30 ++++++++++------- 21 files changed, 110 insertions(+), 108 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 35f330678287..cb1fb52db49f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/dataset/data_set_cache.py b/src/qcodes/dataset/data_set_cache.py index d3d361d2ce0d..686dcc9da6ae 100644 --- a/src/qcodes/dataset/data_set_cache.py +++ b/src/qcodes/dataset/data_set_cache.py @@ -442,11 +442,13 @@ def _insert_into_data_dict( data[j] = np.atleast_1d(new_values[i]) return data, None else: - if existing_values.dtype.kind in ("U", "S"): + if ( + existing_values.dtype.kind in ("U", "S") + and new_values.dtype.itemsize > existing_values.dtype.itemsize + ): # string type arrays may be too small for the new data # read so rescale if needed. - if new_values.dtype.itemsize > existing_values.dtype.itemsize: - existing_values = existing_values.astype(new_values.dtype) + existing_values = existing_values.astype(new_values.dtype) n_values = new_values.size new_write_status = write_status + n_values if new_write_status > existing_values.size: diff --git a/src/qcodes/dataset/dond/do_2d.py b/src/qcodes/dataset/dond/do_2d.py index 0a39dc906c0b..98dfaad001a2 100644 --- a/src/qcodes/dataset/dond/do_2d.py +++ b/src/qcodes/dataset/dond/do_2d.py @@ -214,9 +214,8 @@ def do2d( *additional_setpoints_data, ) - if callable(break_condition): - if break_condition(): - raise BreakConditionInterrupt("Break condition was met.") + if callable(break_condition) and break_condition(): + raise BreakConditionInterrupt("Break condition was met.") for action in after_inner_actions: action() diff --git a/src/qcodes/dataset/dond/do_nd.py b/src/qcodes/dataset/dond/do_nd.py index c3b6a304f178..8a1887883598 100644 --- a/src/qcodes/dataset/dond/do_nd.py +++ b/src/qcodes/dataset/dond/do_nd.py @@ -835,9 +835,8 @@ def dond( *additional_setpoints_data, ) - if callable(break_condition): - if break_condition(): - raise BreakConditionInterrupt("Break condition was met.") + if callable(break_condition) and break_condition(): + raise BreakConditionInterrupt("Break condition was met.") finally: for datasaver in datasavers: ds, plot_axis, plot_color = _handle_plotting( diff --git a/src/qcodes/dataset/export_config.py b/src/qcodes/dataset/export_config.py index 1a0a41def998..36dba5f38e31 100644 --- a/src/qcodes/dataset/export_config.py +++ b/src/qcodes/dataset/export_config.py @@ -80,9 +80,8 @@ def get_data_export_type( if isinstance(export_type, DataExportType): return export_type - elif export_type: - if hasattr(DataExportType, export_type.upper()): - return getattr(DataExportType, export_type.upper()) + elif export_type and hasattr(DataExportType, export_type.upper()): + return getattr(DataExportType, export_type.upper()) return None diff --git a/src/qcodes/dataset/guids.py b/src/qcodes/dataset/guids.py index 78bae87a0bed..7abbaf24e772 100644 --- a/src/qcodes/dataset/guids.py +++ b/src/qcodes/dataset/guids.py @@ -219,15 +219,12 @@ def filter_guids_by_parts( for guid in guids: guid_dict = parse_guid(guid) match = True - if sample_id is not None: - if guid_dict["sample"] != sample_id: - match = False - if location is not None: - if guid_dict["location"] != location: - match = False - if work_station is not None: - if guid_dict["work_station"] != work_station: - match = False + if sample_id is not None and guid_dict["sample"] != sample_id: + match = False + if location is not None and guid_dict["location"] != location: + match = False + if work_station is not None and guid_dict["work_station"] != work_station: + match = False if match: matched_guids.append(guid) diff --git a/src/qcodes/dataset/plotting.py b/src/qcodes/dataset/plotting.py index bc381a6aece7..9b1965812da7 100644 --- a/src/qcodes/dataset/plotting.py +++ b/src/qcodes/dataset/plotting.py @@ -272,9 +272,9 @@ def plot_dataset( if len(data) == 2: # 1D PLOTTING if data[1]["name"] not in parameters: indices_to_remove.append(i) - elif len(data) == 3: # 2D PLOTTING - if data[2]["name"] not in parameters: - indices_to_remove.append(i) + elif len(data) == 3 and data[2]["name"] not in parameters: + # 2D PLOTTING + indices_to_remove.append(i) alldata = [d for (i, d) in enumerate(alldata) if i not in indices_to_remove] for data, ax, colorbar in zip(alldata, axeslist, colorbars): @@ -904,12 +904,15 @@ def _rescale_ticks_and_units( ax.set_ylabel(new_y_label) # for z aka colorbar axis - if cax is not None and len(data) > 2: - if not _is_string_valued_array(data[2]["data"]): - z_ticks_formatter, new_z_label = _make_rescaled_ticks_and_units(data[2]) - cax.set_label(new_z_label) - cax.formatter = z_ticks_formatter - cax.update_ticks() + if ( + cax is not None + and len(data) > 2 + and not _is_string_valued_array(data[2]["data"]) + ): + z_ticks_formatter, new_z_label = _make_rescaled_ticks_and_units(data[2]) + cax.set_label(new_z_label) + cax.formatter = z_ticks_formatter + cax.update_ticks() def _is_string_valued_array(values: npt.NDArray) -> bool: diff --git a/src/qcodes/dataset/sqlite/queries.py b/src/qcodes/dataset/sqlite/queries.py index 4825f99f8bcd..82ff255d53aa 100644 --- a/src/qcodes/dataset/sqlite/queries.py +++ b/src/qcodes/dataset/sqlite/queries.py @@ -840,10 +840,9 @@ def mark_run_complete( is a noop. """ - if override is False: - if completed(conn=conn, run_id=run_id): - log.warning("Trying to mark a run completed that was already completed.") - return + if override is False and completed(conn=conn, run_id=run_id): + log.warning("Trying to mark a run completed that was already completed.") + return query = """ UPDATE diff --git a/src/qcodes/extensions/parameters/parameter_mixin_group_registry.py b/src/qcodes/extensions/parameters/parameter_mixin_group_registry.py index 05747ea2ba9a..472a75102a53 100644 --- a/src/qcodes/extensions/parameters/parameter_mixin_group_registry.py +++ b/src/qcodes/extensions/parameters/parameter_mixin_group_registry.py @@ -88,11 +88,10 @@ def group_names(self) -> list[str] | None: @group_names.setter def group_names(self, value: list[str] | None) -> None: - if value is not None: - if not isinstance(value, list) or not all( - isinstance(v, str) for v in value - ): - raise TypeError("group_names must be a list of strings or None.") + if value is not None and ( + not isinstance(value, list) or not all(isinstance(v, str) for v in value) + ): + raise TypeError("group_names must be a list of strings or None.") self._group_names = value @classmethod diff --git a/src/qcodes/instrument/channel.py b/src/qcodes/instrument/channel.py index 1e807320e4da..c8936dc2c1f9 100644 --- a/src/qcodes/instrument/channel.py +++ b/src/qcodes/instrument/channel.py @@ -440,11 +440,10 @@ def multi_parameter( AttributeError: If no parameter with the given name exists. """ - if len(self) > 0: - # Check if this is a valid parameter - if name in self._channels[0].parameters: - param = self._construct_multiparam(name) - return param + # Check if this is a valid parameter + if len(self) > 0 and name in self._channels[0].parameters: + param = self._construct_multiparam(name) + return param raise AttributeError( f"'{self.__class__.__name__}' object has no parameter '{name}'" ) diff --git a/src/qcodes/instrument/instrument_base.py b/src/qcodes/instrument/instrument_base.py index c3030c102200..f5e16e6cd903 100644 --- a/src/qcodes/instrument/instrument_base.py +++ b/src/qcodes/instrument/instrument_base.py @@ -385,9 +385,8 @@ def _get_component_by_name( component = component.get_component(remaining_name) remaining_name_parts = [] - if component is not None: - if len(remaining_name_parts) == 0: - return component + if component is not None and len(remaining_name_parts) == 0: + return component if len(remaining_name_parts) == 0: raise KeyError( diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS.py b/src/qcodes/instrument_drivers/AlazarTech/ATS.py index 90c4932d3220..572d51c69318 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -567,13 +567,12 @@ def acquire[OutputType]( # noqa: D417 (missing args documentation) # check if all parameters are up to date # Getting IDN is very slow so skip that for _, p in self.parameters.items(): - if isinstance(p, TraceParameter): - if p.synced_to_card is False: - raise RuntimeError( - f"TraceParameter {p} not synced to " - f"Alazar card detected. Aborting. Data " - f"may be corrupt" - ) + if isinstance(p, TraceParameter) and p.synced_to_card is False: + raise RuntimeError( + f"TraceParameter {p} not synced to " + f"Alazar card detected. Aborting. Data " + f"may be corrupt" + ) # Compute the total transfer time, and display performance information. end_time = time.perf_counter() diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py index 94e67aab13a8..deb456821a39 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1517A.py @@ -1179,20 +1179,25 @@ def source_config( range """ - if min_compliance_range is not None: - if isinstance(min_compliance_range, type(output_range)): - raise TypeError( - "When forcing voltage, min_compliance_range must be an " - "current output range (and vice versa)." - ) - - if isinstance(output_range, VOutputRange): - if output_range not in self._valid_v_output_ranges: - raise RuntimeError("Invalid Source Voltage Output Range") - - if isinstance(output_range, IOutputRange): - if output_range not in self._valid_i_output_ranges: - raise RuntimeError("Invalid Source Current Output Range") + if min_compliance_range is not None and isinstance( + min_compliance_range, type(output_range) + ): + raise TypeError( + "When forcing voltage, min_compliance_range must be an " + "current output range (and vice versa)." + ) + + if ( + isinstance(output_range, VOutputRange) + and output_range not in self._valid_v_output_ranges + ): + raise RuntimeError("Invalid Source Voltage Output Range") + + if ( + isinstance(output_range, IOutputRange) + and output_range not in self._valid_i_output_ranges + ): + raise RuntimeError("Invalid Source Current Output Range") self._source_config = { "output_range": output_range, diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py index 138234c9e8f9..324fa6a5ddc6 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py @@ -808,14 +808,13 @@ def sign(s: float) -> float: end_value = self.cv_sweep.sweep_end() step_value = self.cv_sweep.sweep_steps() mode = self.cv_sweep.sweep_mode() - if mode in (2, 4): - if not sign(start_value) == sign(end_value): - if sign(start_value) == 0: - start_value = sign(start_value) * 0.005 # resolution - elif sign(end_value) == 0: - end_value = sign(end_value) * 0.005 # resolution - else: - raise AssertionError("Polarity of start and end is not same.") + if mode in (2, 4) and not sign(start_value) == sign(end_value): + if sign(start_value) == 0: + start_value = sign(start_value) * 0.005 # resolution + elif sign(end_value) == 0: + end_value = sign(end_value) * 0.005 # resolution + else: + raise AssertionError("Polarity of start and end is not same.") def linear_sweep(start: float, end: float, steps: int) -> tuple[float, ...]: sweep_val = np.linspace(start, end, steps).flatten().tolist() diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/server.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/server.py index 921d5b0878ac..0494c21f161b 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/server.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/server.py @@ -45,10 +45,9 @@ def run_server() -> None: read_sockets = select.select(list(socket_dict.keys()), [], [], 1)[0] # Keyboard - if kbhit(): - if ord(getch()) == 27: - print("Server exiting") - break + if kbhit() and ord(getch()) == 27: + print("Server exiting") + break for sock in read_sockets: # New connection diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index 651b76822197..8aaafe8f195d 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -474,9 +474,8 @@ def set_field( self.write(f"CONF:FIELD:TARG {value}") # If we have a persistent switch, make sure it is resistive - if self.switch_heater.enabled(): - if not self.switch_heater.state(): - raise AMI430Exception("Switch heater is not on") + if self.switch_heater.enabled() and not self.switch_heater.state(): + raise AMI430Exception("Switch heater is not on") self.ramp() # Check if we want to block diff --git a/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py b/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py index cba85ab87e78..97469981039c 100644 --- a/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py +++ b/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py @@ -678,9 +678,8 @@ def ramp(self, mode: str = "safe") -> None: raise RuntimeError( f"Expected an OxfordMercuryWorkerPS but got {type(worker)}" ) - if worker.field_target() != cur: - if worker.field_ramp_rate() == 0: - raise ValueError(f"Can not ramp {worker}; ramp rate set to zero!") + if worker.field_target() != cur and worker.field_ramp_rate() == 0: + raise ValueError(f"Can not ramp {worker}; ramp rate set to zero!") # then the actual ramp { diff --git a/src/qcodes/parameters/group_parameter.py b/src/qcodes/parameters/group_parameter.py index 0759b3225f82..1092d3f4e8f4 100644 --- a/src/qcodes/parameters/group_parameter.py +++ b/src/qcodes/parameters/group_parameter.py @@ -178,9 +178,8 @@ def __init__( for p in parameters: p._group = self - if single_instrument: - if len({p.root_instrument for p in parameters}) > 1: - raise ValueError("All parameters should belong to the same instrument") + if single_instrument and len({p.root_instrument for p in parameters}) > 1: + raise ValueError("All parameters should belong to the same instrument") self._instrument = parameters[0].root_instrument diff --git a/src/qcodes/utils/delaykeyboardinterrupt.py b/src/qcodes/utils/delaykeyboardinterrupt.py index 173fdb290748..05652ccc9994 100644 --- a/src/qcodes/utils/delaykeyboardinterrupt.py +++ b/src/qcodes/utils/delaykeyboardinterrupt.py @@ -92,6 +92,9 @@ def __exit__( ) -> None: if self.old_handler is not None: signal.signal(signal.SIGINT, self.old_handler) - if self.signal_received is not None: - if self.old_handler is not None and not isinstance(self.old_handler, int): - self.old_handler(*self.signal_received) + if ( + self.signal_received is not None + and self.old_handler is not None + and not isinstance(self.old_handler, int) + ): + self.old_handler(*self.signal_received) diff --git a/src/qcodes/utils/function_helpers.py b/src/qcodes/utils/function_helpers.py index 4d79cf0a1ed8..d141860af82a 100644 --- a/src/qcodes/utils/function_helpers.py +++ b/src/qcodes/utils/function_helpers.py @@ -21,9 +21,8 @@ def is_function(f: object, arg_count: int, coroutine: bool | None = False) -> bo if not callable(f): return False - if coroutine is not None: - if bool(coroutine) is not iscoroutinefunction(f): - return False + if coroutine is not None and bool(coroutine) is not iscoroutinefunction(f): + return False if isinstance(f, type): # for type casting functions, eg int, str, float diff --git a/src/qcodes/validators/validators.py b/src/qcodes/validators/validators.py index ce1410cf532f..5bec8df80710 100644 --- a/src/qcodes/validators/validators.py +++ b/src/qcodes/validators/validators.py @@ -1017,20 +1017,26 @@ def validate(self, value: npt.NDArray, context: str = "") -> None: ) # Only check if max is not inf as it can be expensive for large arrays - if self._max_value != (float("inf")) and self._max_value is not None: - if not (np.max(value) <= self._max_value): - raise ValueError( - f"{value!r} is invalid: all values must be between " - f"{self._min_value} and {self._max_value} inclusive; {context}" - ) + if ( + self._max_value != (float("inf")) + and self._max_value is not None + and not (np.max(value) <= self._max_value) + ): + raise ValueError( + f"{value!r} is invalid: all values must be between " + f"{self._min_value} and {self._max_value} inclusive; {context}" + ) # Only check if min is not -inf as it can be expensive for large arrays - if self._min_value != (-float("inf")) and self._min_value is not None: - if not (self._min_value <= np.min(value)): - raise ValueError( - f"{value!r} is invalid: all values must be between " - f"{self._min_value} and {self._max_value} inclusive; {context}" - ) + if ( + self._min_value != (-float("inf")) + and self._min_value is not None + and not (self._min_value <= np.min(value)) + ): + raise ValueError( + f"{value!r} is invalid: all values must be between " + f"{self._min_value} and {self._max_value} inclusive; {context}" + ) is_numeric = True From fcc38c2a6a6ea6dda641ccf61612bdccb94b2702 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 08:21:11 +0200 Subject: [PATCH 06/43] Enable B018 --- docs/examples/Parameters/Parameters.ipynb | 3 +-- ...xample with Keysight E4980A LCR meter.ipynb | 4 ++-- ...ith Keysight B1500 Parameter Analyzer.ipynb | 16 ++++++++-------- pyproject.toml | 2 +- tests/helpers/test_delegate_attribues.py | 18 +++++++++--------- tests/parameter/test_delegate_parameter.py | 2 +- tests/test_import.py | 4 ++-- tests/test_sweep_values.py | 2 +- 8 files changed, 25 insertions(+), 26 deletions(-) diff --git a/docs/examples/Parameters/Parameters.ipynb b/docs/examples/Parameters/Parameters.ipynb index c51075851ed1..f5d488a6c9f2 100644 --- a/docs/examples/Parameters/Parameters.ipynb +++ b/docs/examples/Parameters/Parameters.ipynb @@ -412,7 +412,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -429,7 +429,6 @@ } ], "source": [ - "dac.ch1\n", "print(f\"Default validators: {dac.ch1.validators}\")\n", "\n", "# if we try to set a value outside the range of the default validator we get an error.\n", diff --git a/docs/examples/driver_examples/QCoDeS Example with Keysight E4980A LCR meter.ipynb b/docs/examples/driver_examples/QCoDeS Example with Keysight E4980A LCR meter.ipynb index 245fab025dc8..ba711fc1270e 100644 --- a/docs/examples/driver_examples/QCoDeS Example with Keysight E4980A LCR meter.ipynb +++ b/docs/examples/driver_examples/QCoDeS Example with Keysight E4980A LCR meter.ipynb @@ -441,7 +441,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -454,7 +454,7 @@ ], "source": [ "try:\n", - " measurement.capacitance\n", + " _ = measurement.capacitance\n", "except AttributeError as err:\n", " print(err)" ] diff --git a/docs/examples/driver_examples/Qcodes example with Keysight B1500 Parameter Analyzer.ipynb b/docs/examples/driver_examples/Qcodes example with Keysight B1500 Parameter Analyzer.ipynb index b1abb9705ec0..fffbf3d12229 100644 --- a/docs/examples/driver_examples/Qcodes example with Keysight B1500 Parameter Analyzer.ipynb +++ b/docs/examples/driver_examples/Qcodes example with Keysight B1500 Parameter Analyzer.ipynb @@ -79,7 +79,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -87,7 +87,6 @@ "from matplotlib import pyplot as plt\n", "from pyvisa.errors import VisaIOError\n", "\n", - "import qcodes as qc\n", "from qcodes.dataset import (\n", " Measurement,\n", " initialise_database,\n", @@ -95,16 +94,17 @@ " plot_dataset,\n", ")\n", "from qcodes.instrument_drivers.Keysight import KeysightB1500\n", - "from qcodes.instrument_drivers.Keysight.keysightb1500 import MessageBuilder, constants" + "from qcodes.instrument_drivers.Keysight.keysightb1500 import MessageBuilder, constants\n", + "from qcodes.station import Station" ] }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ - "station = qc.Station() # Create a station to hold all the instruments" + "station = Station() # Create a station to hold all the instruments" ] }, { @@ -215,9 +215,9 @@ "metadata": {}, "outputs": [], "source": [ - "b1500.smu1 # first SMU in the system\n", - "b1500.cmu1 # first CMU in the system\n", - "b1500.smu2 # second SMU in the system" + "_smu1 = b1500.smu1 # first SMU in the system\n", + "_cmu1 = b1500.cmu1 # first CMU in the system\n", + "_smu2 = b1500.smu2 # second SMU in the system" ] }, { diff --git a/pyproject.toml b/pyproject.toml index cb1fb52db49f..c3457a3770d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/tests/helpers/test_delegate_attribues.py b/tests/helpers/test_delegate_attribues.py index dad135a66521..69d54084cf10 100644 --- a/tests/helpers/test_delegate_attribues.py +++ b/tests/helpers/test_delegate_attribues.py @@ -14,7 +14,7 @@ class ToDict(DelegateAttributes): td = ToDict() # td.d doesn't exist yet with pytest.raises(AttributeError): - td.d + _ = td.d # but you can still get other attributes assert td.apples == "green" @@ -39,7 +39,7 @@ class ToDict(DelegateAttributes): # missing items still raise AttributeError, not KeyError with pytest.raises(AttributeError): - td.kiwis + _ = td.kiwis # all appropriate items are in dir() exactly once for attr in ["apples", "oranges", "bananas"]: @@ -56,7 +56,7 @@ class ToDicts(DelegateAttributes): # you can still access the second one when the first doesn't exist with pytest.raises(AttributeError): - td.d + _ = td.d assert td.e == e assert td.cats == 12 @@ -86,7 +86,7 @@ class ToObject(DelegateAttributes): # recipient not connected yet but you can look at other attributes with pytest.raises(AttributeError): - to_obj.recipient + _ = to_obj.recipient assert to_obj.gray == "#888" to_obj.recipient = recipient # type: ignore[attr-defined] @@ -138,7 +138,7 @@ class ToObjects(DelegateAttributes): # missing attributes still raise correctly with pytest.raises(AttributeError): - to_objs.f + _ = to_objs.f # all appropriate items are in dir() exactly once for attr in "abcde": @@ -176,7 +176,7 @@ class ToBoth(DelegateAttributes): # missing attributes still raise correctly with pytest.raises(AttributeError): - tb.ninja + _ = tb.ninja # all appropriate items are in dir() exactly once for attr in ["rock", "paper", "scissors", "year", "water"]: @@ -199,7 +199,7 @@ def prop(self) -> int: obj = WithFaultyProperty() with pytest.raises(AttributeError, match="missing"): - obj.prop + _ = obj.prop def test_faulty_property_preserves_inner_traceback() -> None: @@ -215,7 +215,7 @@ def prop(self) -> int: obj = WithFaultyProperty() with pytest.raises(AttributeError, match="specific underlying failure") as excinfo: - obj.prop + _ = obj.prop assert any(entry.name == "prop" for entry in excinfo.traceback) @@ -238,7 +238,7 @@ class Plain(DelegateAttributes): # ``__name__`` is not defined on ``Plain`` instances, so accessing it # should raise ``AttributeError``, never ``TypeError``. with pytest.raises(AttributeError): - obj.__name__ # type: ignore[attr-defined] + _ = obj.__name__ # type: ignore[attr-defined] # ``inspect.iscoroutinefunction`` internally does # ``getattr(obj, '__name__', None)`` — this must not raise. diff --git a/tests/parameter/test_delegate_parameter.py b/tests/parameter/test_delegate_parameter.py index 90d15aef3b60..26a6ad1b1e30 100644 --- a/tests/parameter/test_delegate_parameter.py +++ b/tests/parameter/test_delegate_parameter.py @@ -455,7 +455,7 @@ def _assert_delegate_cache_none_source(delegate_param: DelegateParameter) -> Non with pytest.raises(TypeError): delegate_param.cache.get() with pytest.raises(TypeError): - delegate_param.cache.raw_value + _ = delegate_param.cache.raw_value assert delegate_param.cache.max_val_age is None assert delegate_param.cache.timestamp is None diff --git a/tests/test_import.py b/tests/test_import.py index d3e553ff278c..73d312b0720f 100644 --- a/tests/test_import.py +++ b/tests/test_import.py @@ -85,7 +85,7 @@ def test_top_level_submodule_access_not_deprecated() -> None: def test_top_level_unknown_attribute_raises() -> None: with pytest.raises(AttributeError, match="definitely_not_a_qcodes_attribute"): - qcodes.definitely_not_a_qcodes_attribute # type: ignore[attr-defined] + _ = qcodes.definitely_not_a_qcodes_attribute # type: ignore[attr-defined] def test_instrument_parameter_reexport_deprecated() -> None: @@ -127,4 +127,4 @@ def test_instrument_parameter_reexport_deprecated_all(name: str) -> None: def test_instrument_unknown_attribute_raises() -> None: with pytest.raises(AttributeError, match="definitely_not_a_qcodes_attribute"): - qcodes.instrument.definitely_not_a_qcodes_attribute # type: ignore[attr-defined] + _ = qcodes.instrument.definitely_not_a_qcodes_attribute # type: ignore[attr-defined] diff --git a/tests/test_sweep_values.py b/tests/test_sweep_values.py index 0f6d888bc34f..a7b4a517852a 100644 --- a/tests/test_sweep_values.py +++ b/tests/test_sweep_values.py @@ -60,7 +60,7 @@ def test_errors(c0, c1, c2) -> None: # SweepValue object has no getter, even if the parameter does with pytest.raises(AttributeError): - c0[0.1].get + _ = c0[0.1].get def test_valid(c0) -> None: From f3a7b9c5a211f6edd1eae0c6ca8fd1f20e97f750 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 09:06:29 +0200 Subject: [PATCH 07/43] Enable PT031 --- .../DataSet/Accessing-data-in-DataSet.ipynb | 2 +- .../Parameter_defined_InterDependencies.ipynb | 2 +- pyproject.toml | 2 +- src/qcodes/calibrations/keithley.py | 2 +- .../descriptions/versioning/converters.py | 2 +- src/qcodes/dataset/dond/do_nd.py | 2 +- src/qcodes/dataset/exporters/export_info.py | 2 +- src/qcodes/dataset/plotting.py | 4 +- src/qcodes/dataset/sqlite/queries.py | 2 +- src/qcodes/dataset/sqlite/settings.py | 2 +- .../instrument/delegate/instrument_group.py | 2 +- src/qcodes/instrument/instrument_base.py | 2 +- .../instrument_drivers/AimTTi/_AimTTi_PL_P.py | 2 +- src/qcodes/instrument_drivers/HP/HP_8753D.py | 4 +- .../Keithley/Keithley_2000.py | 2 +- .../Keithley/Keithley_6500.py | 2 +- .../instrument_drivers/Keysight/N51x1.py | 2 +- .../Keysight/keysight_34980a.py | 2 +- .../Lakeshore/Lakeshore_model_325.py | 2 +- .../oxford/MercuryiPS_VISA.py | 2 +- .../instrument_drivers/rohde_schwarz/ZNB.py | 4 +- .../instrument_drivers/tektronix/AWG70000A.py | 22 +++++----- src/qcodes/plotting/axis_labels.py | 2 +- src/qcodes/station.py | 10 ++--- src/qcodes/utils/attribute_helpers.py | 2 +- .../test_self_registering_parameters.py | 2 +- .../measurement/test_self_unpacking.py | 6 +-- tests/dataset/test_data_set_cache.py | 2 +- tests/dataset/test_database_extract_runs.py | 36 ++++++++--------- tests/dataset/test_dataset_export.py | 6 +-- tests/dataset/test_dataset_in_memory.py | 16 ++++---- tests/dataset/test_nested_measurements.py | 28 ++++++------- tests/drivers/test_keithley_s46.py | 2 +- tests/drivers/test_keysight_b220x.py | 12 ++++-- tests/drivers/test_lakeshore_335.py | 2 +- tests/drivers/test_lakeshore_336.py | 2 +- tests/drivers/test_tektronix_AWG70000A.py | 2 +- .../test_parameter_mixin_interdependent.py | 40 +++++++++---------- tests/parameter/test_delegate_parameter.py | 2 +- .../parameter/test_parameter_registration.py | 6 +-- tests/parameter/test_validators.py | 2 +- tests/test_channels.py | 16 ++++---- tests/test_instrument.py | 4 +- tests/test_station.py | 4 +- 44 files changed, 138 insertions(+), 136 deletions(-) diff --git a/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb b/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb index fa931e406b62..c9b1e9005ebd 100644 --- a/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb +++ b/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb @@ -502,7 +502,7 @@ } ], "source": [ - "for d in interdeps.dependencies.keys():\n", + "for d in interdeps.dependencies:\n", " print(f\"Parameter {d.name!r} ({d.label}, {d.unit}) depends on:\")\n", " for i in interdeps.dependencies[d]:\n", " print(f\"- {i.name!r} ({i.label}, {i.unit})\")" diff --git a/docs/examples/Parameters/Parameter_defined_InterDependencies.ipynb b/docs/examples/Parameters/Parameter_defined_InterDependencies.ipynb index bcb464e6ecd1..3cd2ca6c7bc8 100644 --- a/docs/examples/Parameters/Parameter_defined_InterDependencies.ipynb +++ b/docs/examples/Parameters/Parameter_defined_InterDependencies.ipynb @@ -74,7 +74,7 @@ " super().__init__(name=name, get_cmd=False)\n", " # dict of Parameter to (slope, offset) of components\n", " self._components_dict: dict[Parameter, tuple[float, float]] = components\n", - " for param in self._components_dict.keys():\n", + " for param in self._components_dict:\n", " self._has_control_of.add(param)\n", " param.is_controlled_by.add(self)\n", "\n", diff --git a/pyproject.toml b/pyproject.toml index c3457a3770d9..2137d03079f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/calibrations/keithley.py b/src/qcodes/calibrations/keithley.py index e165b3b4b470..5c621633c531 100644 --- a/src/qcodes/calibrations/keithley.py +++ b/src/qcodes/calibrations/keithley.py @@ -104,7 +104,7 @@ def calibrate_keithley_smu_v_single( time_delay: float = 3.0, ) -> None: assert channel in {smu_channel.channel for smu_channel in smu.channels} - assert v_range in src_FS_map.keys() + assert v_range in src_FS_map src_FS = src_FS_map[v_range] sense_modes = ["SENSE_LOCAL"] diff --git a/src/qcodes/dataset/descriptions/versioning/converters.py b/src/qcodes/dataset/descriptions/versioning/converters.py index 897b8a8b6fb1..a17fac6da32c 100644 --- a/src/qcodes/dataset/descriptions/versioning/converters.py +++ b/src/qcodes/dataset/descriptions/versioning/converters.py @@ -94,7 +94,7 @@ def new_to_old(idps: InterDependencies_) -> InterDependencies: } ) - for ps_base in idps._paramspec_to_id.keys(): + for ps_base in idps._paramspec_to_id: paramspecs.update( { ps_base.name: ParamSpec( diff --git a/src/qcodes/dataset/dond/do_nd.py b/src/qcodes/dataset/dond/do_nd.py index 8a1887883598..893f666c37b9 100644 --- a/src/qcodes/dataset/dond/do_nd.py +++ b/src/qcodes/dataset/dond/do_nd.py @@ -208,7 +208,7 @@ def __getitem__(self, index: int) -> tuple[ParameterSetEvent, ...]: if index == 0: previous_setpoints: dict[str, SweepVarType | None] = {} - for key in setpoints.keys(): + for key in setpoints: previous_setpoints[key] = None else: previous_setpoints = self._make_single_point_setpoints_dict(index - 1) diff --git a/src/qcodes/dataset/exporters/export_info.py b/src/qcodes/dataset/exporters/export_info.py index d1ef1f52f2c1..47e1860239b8 100644 --- a/src/qcodes/dataset/exporters/export_info.py +++ b/src/qcodes/dataset/exporters/export_info.py @@ -16,7 +16,7 @@ class ExportInfo: def __post_init__(self) -> None: """Verify that keys used in export_paths are as expected.""" allowed_keys = tuple(a.value for a in DataExportType) - for key in self.export_paths.keys(): + for key in self.export_paths: if key not in allowed_keys: warnings.warn( f"The supported export types are: {allowed_keys}. Got {key} " diff --git a/src/qcodes/dataset/plotting.py b/src/qcodes/dataset/plotting.py index 9b1965812da7..37c367d18e79 100644 --- a/src/qcodes/dataset/plotting.py +++ b/src/qcodes/dataset/plotting.py @@ -630,7 +630,7 @@ def plot_2d_scatterplot( """ import matplotlib - if "rasterized" in kwargs.keys(): + if "rasterized" in kwargs: rasterized = kwargs.pop("rasterized") else: rasterized = len(z) > qc.config.plotting.rasterize_threshold @@ -739,7 +739,7 @@ def plot_on_a_plain_grid( x_to_plot, y_to_plot, z_to_plot = reshape_2D_data(x, y, z) num_points = x_to_plot.size * y_to_plot.size - if "rasterized" in kwargs.keys(): + if "rasterized" in kwargs: rasterized = kwargs.pop("rasterized") else: rasterized = num_points > qc.config.plotting.rasterize_threshold diff --git a/src/qcodes/dataset/sqlite/queries.py b/src/qcodes/dataset/sqlite/queries.py index 82ff255d53aa..ccfb2afffa4a 100644 --- a/src/qcodes/dataset/sqlite/queries.py +++ b/src/qcodes/dataset/sqlite/queries.py @@ -1902,7 +1902,7 @@ def insert_data_in_dynamic_columns( """ validate_dynamic_column_data(data) - for key in data.keys(): + for key in data: insert_column(conn, table_name, key) update_columns(conn, row_id, table_name, data) diff --git a/src/qcodes/dataset/sqlite/settings.py b/src/qcodes/dataset/sqlite/settings.py index 31604aab7744..69611f49f025 100644 --- a/src/qcodes/dataset/sqlite/settings.py +++ b/src/qcodes/dataset/sqlite/settings.py @@ -66,7 +66,7 @@ def _read_settings() -> tuple[dict[str, str | int], dict[str, bool | int | str]] param = lst[0] val = None - if param in DEFAULT_LIMITS.keys(): + if param in DEFAULT_LIMITS: # we are only expecting # None val for a setting assert val is not None diff --git a/src/qcodes/instrument/delegate/instrument_group.py b/src/qcodes/instrument/delegate/instrument_group.py index cd091b60b5c8..5e8e507baf17 100644 --- a/src/qcodes/instrument/delegate/instrument_group.py +++ b/src/qcodes/instrument/delegate/instrument_group.py @@ -49,7 +49,7 @@ def __init__( instr_class = getattr(module, instr_class_name) for submodule_name, inputs in submodules.items(): - if not any(x in inputs.keys() for x in ["parameters", "channels"]): + if not any(x in inputs for x in ["parameters", "channels"]): raise KeyError( f"Missing keyworded input arguments for {submodule_name}" ) diff --git a/src/qcodes/instrument/instrument_base.py b/src/qcodes/instrument/instrument_base.py index f5e16e6cd903..aa80283df133 100644 --- a/src/qcodes/instrument/instrument_base.py +++ b/src/qcodes/instrument/instrument_base.py @@ -168,7 +168,7 @@ def add_parameter( if parameter_class is None: parameter_class = cast("type[TParameter]", Parameter) - if "bind_to_instrument" not in kwargs.keys(): + if "bind_to_instrument" not in kwargs: kwargs["bind_to_instrument"] = True bind_to_instrument = kwargs["bind_to_instrument"] diff --git a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py index 748053bdb155..67db739b4e40 100644 --- a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py @@ -268,7 +268,7 @@ def __init__( _model = self.get_idn()["model"] - if (_model not in self._numOutputChannels.keys()) or (_model is None): + if (_model not in self._numOutputChannels) or (_model is None): raise NotKnownModel("Unknown model, connection cannot be established.") self.numOfChannels = self._numOutputChannels[_model] diff --git a/src/qcodes/instrument_drivers/HP/HP_8753D.py b/src/qcodes/instrument_drivers/HP/HP_8753D.py index 72dc1f929f3c..ae6756427ab7 100644 --- a/src/qcodes/instrument_drivers/HP/HP_8753D.py +++ b/src/qcodes/instrument_drivers/HP/HP_8753D.py @@ -336,7 +336,7 @@ def _display_format_setter(self, fmt: str) -> None: "SWR": "SWR", } - if fmt not in val_mapping.keys(): + if fmt not in val_mapping: raise ValueError(f"Cannot set display_format to {fmt}.") self._traceready = False @@ -363,7 +363,7 @@ def _display_format_getter(self) -> str: cmd = "" # keep asking until we find the currently used format - for cmd in val_mapping.keys(): + for cmd in val_mapping: resp = self.ask(f"{cmd}?") if resp in ["1", "1\n"]: break diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py index eeb3f884d3f6..6e8213b25a6e 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py @@ -28,7 +28,7 @@ def _parse_output_string(s: str) -> str: "rep": "repeat", } - if s in conversions.keys(): + if s in conversions: s = conversions[s] return s diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py index 2c60b2e99223..e70cc54d151d 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_6500.py @@ -28,7 +28,7 @@ def _parse_output_string(string_value: str) -> str: s = s[1:-1] conversions = {"mov": "moving", "rep": "repeat"} - if s in conversions.keys(): + if s in conversions: s = conversions[s] return s diff --git a/src/qcodes/instrument_drivers/Keysight/N51x1.py b/src/qcodes/instrument_drivers/Keysight/N51x1.py index 40889c3902db..e84c20a4e1d4 100644 --- a/src/qcodes/instrument_drivers/Keysight/N51x1.py +++ b/src/qcodes/instrument_drivers/Keysight/N51x1.py @@ -39,7 +39,7 @@ def __init__( } frequency_option = None - for f_option in freq_dict.keys(): + for f_option in freq_dict: if f_option in self._options: frequency_option = f_option if frequency_option is None: diff --git a/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py b/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py index b278c20088a6..65562394afad 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py +++ b/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py @@ -124,7 +124,7 @@ def scan_slots(self) -> None: Scan the occupied slots and make an object for each switch matrix module installed """ - for slot in self.system_slots_info.keys(): + for slot in self.system_slots_info: model_string = self.system_slots_info[slot]["model"] for model, model_class in KEYSIGHT_MODELS.items(): if model in model_string: diff --git a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py index 4cbaf3847a93..b328a2e24988 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py @@ -185,7 +185,7 @@ def validate_datadict(cls, data_dict: dict[Any, Any]) -> str: f"At least {cls.temperature_key} needed in the data dictionary" ) - sensor_units = [i for i in data_dict.keys() if i != cls.temperature_key] + sensor_units = [i for i in data_dict if i != cls.temperature_key] if len(sensor_units) != 1: raise ValueError( diff --git a/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py b/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py index 97469981039c..afd59796c5b6 100644 --- a/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py +++ b/src/qcodes/instrument_drivers/oxford/MercuryiPS_VISA.py @@ -56,7 +56,7 @@ def _signal_parser(our_scaling: float, response: str) -> float: scale_and_unit = response[len(digits) :] if scale_and_unit == "": their_scaling: float = 1 - elif scale_and_unit[0] in scale_to_factor.keys(): + elif scale_and_unit[0] in scale_to_factor: their_scaling = scale_to_factor[scale_and_unit[0]] else: their_scaling = 1 diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py index 02497f5e767d..04965fe511aa 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py @@ -480,7 +480,7 @@ def __init__( "ZNLE14": 0, "ZNLE18": 0, } - if model not in self._model_min_source_power.keys(): + if model not in self._model_min_source_power: raise RuntimeError(f"Unsupported ZNB model: {model}") self._min_source_power: float self._min_source_power = self._model_min_source_power[model] @@ -1101,7 +1101,7 @@ def __init__( "ZNLE14": (1e6, 14e9), "ZNLE18": (1e6, 18e9), } - if model not in m_frequency.keys(): + if model not in m_frequency: raise RuntimeError(f"Unsupported ZNB model {model}") self._min_freq: float self._max_freq: float diff --git a/src/qcodes/instrument_drivers/tektronix/AWG70000A.py b/src/qcodes/instrument_drivers/tektronix/AWG70000A.py index 7384b163fa36..42f6483e0aac 100644 --- a/src/qcodes/instrument_drivers/tektronix/AWG70000A.py +++ b/src/qcodes/instrument_drivers/tektronix/AWG70000A.py @@ -1097,9 +1097,9 @@ def make_SEQX_from_forged_sequence( raise InvalidForgedSequenceError(e) chan_list: list[str | int] = [] - for pos1 in seq.keys(): - for pos2 in seq[pos1]["content"].keys(): - for ch in seq[pos1]["content"][pos2]["data"].keys(): + for pos1 in seq: + for pos2 in seq[pos1]["content"]: + for ch in seq[pos1]["content"][pos2]["data"]: if ch not in chan_list: chan_list.append(ch) @@ -1130,14 +1130,14 @@ def make_SEQX_from_forged_sequence( wfmx_files: list[bytes] = [] wfmx_filenames: list[str] = [] - for pos1 in seq.keys(): - for pos2 in seq[pos1]["content"].keys(): + for pos1 in seq: + for pos2 in seq[pos1]["content"]: for ch, data in seq[pos1]["content"][pos2]["data"].items(): wfm = data["wfm"] markerdata = [] for mkey in ["m1", "m2", "m3", "m4"]: - if mkey in data.keys(): + if mkey in data: markerdata.append(data.get(mkey)) wfm_data = np.stack((wfm, *markerdata)) @@ -1157,7 +1157,7 @@ def make_SEQX_from_forged_sequence( subseqsml_files: list[str] = [] subseqsml_filenames: list[str] = [] - for pos1 in seq.keys(): + for pos1 in seq: if seq[pos1]["type"] == "subsequence": ss_wfm_names: list[list[str]] = [] @@ -1166,7 +1166,7 @@ def make_SEQX_from_forged_sequence( # and we must also provide default values if nothing # is specified seqings: list[dict[str, int]] = [] - for pos2 in seq[pos1]["content"].keys(): + for pos2 in seq[pos1]["content"]: pos_seqs = seq[pos1]["content"][pos2]["sequencing"] pos_seqs["twait"] = pos_seqs.get("twait", 0) pos_seqs["nrep"] = pos_seqs.get("nrep", 1) @@ -1179,7 +1179,7 @@ def make_SEQX_from_forged_sequence( [n for n in wfmx_filenames if f"wfm_{pos1}_{pos2}" in n] ) - seqing = {k: [d[k] for d in seqings] for k in seqings[0].keys()} + seqing = {k: [d[k] for d in seqings] for k in seqings[0]} subseqname = f"subsequence_{pos1}" @@ -1206,7 +1206,7 @@ def make_SEQX_from_forged_sequence( asset_names: list[list[str]] = [] seqings = [] subseq_positions: list[int] = [] - for pos1 in seq.keys(): + for pos1 in seq: pos_seqs = seq[pos1]["sequencing"] pos_seqs["twait"] = pos_seqs.get("twait", 0) @@ -1222,7 +1222,7 @@ def make_SEQX_from_forged_sequence( ) else: asset_names.append([wn for wn in wfmx_filenames if f"wfm_{pos1}" in wn]) - seqing = {k: [d[k] for d in seqings] for k in seqings[0].keys()} + seqing = {k: [d[k] for d in seqings] for k in seqings[0]} log.debug(f"Assets for SML file: {asset_names}") diff --git a/src/qcodes/plotting/axis_labels.py b/src/qcodes/plotting/axis_labels.py index 2b8636552341..21f04ba9f585 100644 --- a/src/qcodes/plotting/axis_labels.py +++ b/src/qcodes/plotting/axis_labels.py @@ -60,7 +60,7 @@ ) _THRESHOLDS: dict[float, int] = OrderedDict( - {10 ** (scale + 3): scale for scale in _ENGINEERING_PREFIXES.keys()} + {10 ** (scale + 3): scale for scale in _ENGINEERING_PREFIXES} ) diff --git a/src/qcodes/station.py b/src/qcodes/station.py index 1b604775f46d..30ea43a39b66 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -267,7 +267,7 @@ def add_component( if name is None: name = getattr(component, "name", f"component{len(self.components)}") namestr = str(name) - if namestr in self.components.keys(): + if namestr in self.components: raise RuntimeError( f'Cannot add component "{namestr}", because a ' "component of that name is already registered to the station" @@ -476,7 +476,7 @@ def update_load_instrument_methods() -> None: delattr(self, self._added_methods.pop()) # add shortcut methods - for instrument_name in self._instrument_config.keys(): + for instrument_name in self._instrument_config: method_name = f"load_{instrument_name}" if method_name.isidentifier(): setattr( @@ -562,7 +562,7 @@ def load_instrument( self.load_config_files(*self.config_file) # load from config - if identifier not in self._instrument_config.keys(): + if identifier not in self._instrument_config: raise RuntimeError( f"Instrument {identifier} not found in instrument config file" ) @@ -783,7 +783,7 @@ def load_all_instruments( instrument_names_to_load = set(only_names) elif only_types is not None and only_names is None: for inst_name, inst_dict in config["instruments"].items(): - if "driver" in inst_dict.keys(): + if "driver" in inst_dict: # fallback for old format where type was used # together with the driver key. inst_type = inst_dict["type"] @@ -905,7 +905,7 @@ def _merge_yamls(*yamls: str | Path) -> str: while len(deq) > 1: data2, data1 = deq[0], deq[1] for entry in data2[top_key]: - if entry not in data1[top_key].keys(): + if entry not in data1[top_key]: data1[top_key].update({entry: data2[top_key][entry]}) else: raise KeyError( diff --git a/src/qcodes/utils/attribute_helpers.py b/src/qcodes/utils/attribute_helpers.py index 33262bdade11..4c11e6168bd5 100644 --- a/src/qcodes/utils/attribute_helpers.py +++ b/src/qcodes/utils/attribute_helpers.py @@ -94,7 +94,7 @@ def __dir__(self) -> list[str]: for name in self.delegate_attr_dicts: d = getattr(self, name, None) if d is not None: - names += [k for k in d.keys() if k not in self.omit_delegate_attrs] + names += [k for k in d if k not in self.omit_delegate_attrs] for name in self.delegate_attr_objects: obj = getattr(self, name, None) diff --git a/tests/dataset/measurement/test_self_registering_parameters.py b/tests/dataset/measurement/test_self_registering_parameters.py index 38e01738cf93..055b85232552 100644 --- a/tests/dataset/measurement/test_self_registering_parameters.py +++ b/tests/dataset/measurement/test_self_registering_parameters.py @@ -103,7 +103,7 @@ def test_registering_dependent_param_with_setpoints(dependent_parameters) -> Non dependency_tree = meas._interdeps.dependencies assert len(dependency_tree) == 1 - assert dep1.param_spec in dependency_tree.keys() + assert dep1.param_spec in dependency_tree # Ensure that order in the dependency spec tree is preserved # Explicit Setpoints first, then internal depends_on parameters diff --git a/tests/dataset/measurement/test_self_unpacking.py b/tests/dataset/measurement/test_self_unpacking.py index 7e0245ab17b1..3a39a12fc274 100644 --- a/tests/dataset/measurement/test_self_unpacking.py +++ b/tests/dataset/measurement/test_self_unpacking.py @@ -31,7 +31,7 @@ def __init__( super().__init__(name=name, get_cmd=False) # dict of Parameter to (slope, offset) of components self._components_dict: dict[Parameter, tuple[float, float]] = components - for param in self._components_dict.keys(): + for param in self._components_dict: self._has_control_of.add(param) param.is_controlled_by.add(self) @@ -84,7 +84,7 @@ def test_add_result_self_unpack(controlling_parameters, experiment): meas1_data = dataset_data.get("meas1", None) assert meas1_data is not None assert all( - param_name in meas1_data.keys() + param_name in meas1_data for param_name in ("meas1", "comp1", "comp2", "control1") ) assert meas1_data["meas1"] == pytest.approx(np.linspace(1, 2, 11)) @@ -125,7 +125,7 @@ def test_add_result_self_unpack_with_PWS(controlling_parameters, experiment): pws_data = dataset_data.get("pws", None) assert (pws_data) is not None assert all( - param_name in pws_data.keys() + param_name in pws_data for param_name in ("pws", "comp1", "comp2", "control1", "pws_setpoints") ) expected_setpoints, expected_control = np.meshgrid( diff --git a/tests/dataset/test_data_set_cache.py b/tests/dataset/test_data_set_cache.py index 06b606193c50..4a49e0ab60c7 100644 --- a/tests/dataset/test_data_set_cache.py +++ b/tests/dataset/test_data_set_cache.py @@ -1078,7 +1078,7 @@ def _assert_parameter_data_is_identical( expected_inner = outer_val actual_inner = actual[outer_key] assert expected_inner.keys() == actual_inner.keys() - for inner_key in expected_inner.keys(): + for inner_key in expected_inner: expected_np_array = expected_inner[inner_key] actual_np_array = actual_inner[inner_key] if shaped_partial: diff --git a/tests/dataset/test_database_extract_runs.py b/tests/dataset/test_database_extract_runs.py index f30a126facc2..a8952d4bf8ae 100644 --- a/tests/dataset/test_database_extract_runs.py +++ b/tests/dataset/test_database_extract_runs.py @@ -754,15 +754,15 @@ def test_old_versions_not_touched( with raise_if_file_changed(fixturepath), pytest.warns(UserWarning) as warning: extract_runs_into_db(fixturepath, target_path, 1) - expected_mssg = ( - "Source DB version is 2, but this " - f"function needs it to be in version {new_v}. " - "Run this function again with " - "upgrade_source_db=True to auto-upgrade " - "the source DB file." - ) - assert isinstance(warning[0].message, Warning) - assert warning[0].message.args[0] == expected_mssg + expected_mssg = ( + "Source DB version is 2, but this " + f"function needs it to be in version {new_v}. " + "Run this function again with " + "upgrade_source_db=True to auto-upgrade " + "the source DB file." + ) + assert isinstance(warning[0].message, Warning) + assert warning[0].message.args[0] == expected_mssg # Then test that we cannot use an old version as target @@ -778,15 +778,15 @@ def test_old_versions_not_touched( with raise_if_file_changed(fixturepath), pytest.warns(UserWarning) as warning: extract_runs_into_db(source_path, fixturepath, 1) - expected_mssg = ( - "Target DB version is 2, but this " - f"function needs it to be in version {new_v}. " - "Run this function again with " - "upgrade_target_db=True to auto-upgrade " - "the target DB file." - ) - assert isinstance(warning[0].message, Warning) - assert warning[0].message.args[0] == expected_mssg + expected_mssg = ( + "Target DB version is 2, but this " + f"function needs it to be in version {new_v}. " + "Run this function again with " + "upgrade_target_db=True to auto-upgrade " + "the target DB file." + ) + assert isinstance(warning[0].message, Warning) + assert warning[0].message.args[0] == expected_mssg def test_experiments_with_NULL_sample_name( diff --git a/tests/dataset/test_dataset_export.py b/tests/dataset/test_dataset_export.py index 92423935e91e..dd656597181e 100644 --- a/tests/dataset/test_dataset_export.py +++ b/tests/dataset/test_dataset_export.py @@ -893,7 +893,7 @@ def test_export_to_xarray_non_unique_dependent_parameter( _assert_xarray_metadata_is_as_expected(ds, mock_dataset_nonunique) for array_name in ds.data_vars: - assert "snapshot" not in ds[array_name].attrs.keys() + assert "snapshot" not in ds[array_name].attrs def test_export_to_xarray_extra_metadata(mock_dataset: DataSet) -> None: @@ -904,7 +904,7 @@ def test_export_to_xarray_extra_metadata(mock_dataset: DataSet) -> None: _assert_xarray_metadata_is_as_expected(ds, mock_dataset) for array_name in ds.data_vars: - assert "snapshot" not in ds[array_name].attrs.keys() + assert "snapshot" not in ds[array_name].attrs def test_export_to_xarray_ds_dict_extra_metadata(mock_dataset: DataSet) -> None: @@ -941,7 +941,7 @@ def test_export_to_xarray_extra_metadata_can_be_stored( # dataset # export info is only set after the export so its not part of # the exported metadata so skip it here. - for key in mock_dataset.metadata.keys(): + for key in mock_dataset.metadata: if key != "export_info": assert mock_dataset.metadata[key] == loaded_data.attrs[key] # check that the added metadata roundtrip correctly diff --git a/tests/dataset/test_dataset_in_memory.py b/tests/dataset/test_dataset_in_memory.py index f5e24c8c31d6..21567edbf12f 100644 --- a/tests/dataset/test_dataset_in_memory.py +++ b/tests/dataset/test_dataset_in_memory.py @@ -452,9 +452,9 @@ def test_load_from_db(meas_with_registered_param, DMM, DAC, tmp_path) -> None: assert loaded_ds.export_info == ds.export_info assert loaded_ds.metadata == ds.metadata - assert "foo" in loaded_ds.metadata.keys() - assert "export_info" in loaded_ds.metadata.keys() - assert "metadata_added_after_export" in loaded_ds.metadata.keys() + assert "foo" in loaded_ds.metadata + assert "export_info" in loaded_ds.metadata + assert "metadata_added_after_export" in loaded_ds.metadata assert loaded_ds.metadata["metadata_added_after_export"] == 69 compare_datasets(ds, loaded_ds) @@ -487,8 +487,8 @@ def test_load_from_file(meas_with_registered_param, DMM, DAC, tmp_path) -> None: assert loaded_ds.export_info == ds.export_info assert loaded_ds.metadata == ds.metadata - assert "export_info" in loaded_ds.metadata.keys() - assert "metadata_added_after_export" in loaded_ds.metadata.keys() + assert "export_info" in loaded_ds.metadata + assert "metadata_added_after_export" in loaded_ds.metadata assert loaded_ds.metadata["foo"] == "bar" assert loaded_ds.metadata["metadata_added_after_export"] == "42" @@ -642,9 +642,9 @@ def test_load_from_db_dataset_moved( assert loaded_ds.export_info == ds.export_info assert loaded_ds.metadata == ds.metadata - assert "foo" in loaded_ds.metadata.keys() - assert "export_info" in loaded_ds.metadata.keys() - assert "metadata_added_after_export" in loaded_ds.metadata.keys() + assert "foo" in loaded_ds.metadata + assert "export_info" in loaded_ds.metadata + assert "metadata_added_after_export" in loaded_ds.metadata assert loaded_ds.cache.data() == {} diff --git a/tests/dataset/test_nested_measurements.py b/tests/dataset/test_nested_measurements.py index 7824a60b9831..dc832f7cf191 100644 --- a/tests/dataset/test_nested_measurements.py +++ b/tests/dataset/test_nested_measurements.py @@ -36,15 +36,15 @@ def test_nested_measurement_basic(DAC, DMM, bg_writing) -> None: data1 = ds1.dataset.get_parameter_data()["dummy_dmm_v1"] assert len(data1.keys()) == 2 - assert "dummy_dmm_v1" in data1.keys() - assert "dummy_dac_ch1" in data1.keys() + assert "dummy_dmm_v1" in data1 + assert "dummy_dac_ch1" in data1 assert_allclose(data1["dummy_dmm_v1"], np.zeros(10)) assert_allclose(data1["dummy_dac_ch1"], np.arange(10)) data2 = ds2.dataset.get_parameter_data()["dummy_dmm_v2"] assert len(data2.keys()) == 2 - assert "dummy_dmm_v2" in data2.keys() - assert "dummy_dac_ch2" in data2.keys() + assert "dummy_dmm_v2" in data2 + assert "dummy_dac_ch2" in data2 assert_allclose(data2["dummy_dmm_v2"], np.zeros(10)) assert_allclose(data2["dummy_dac_ch2"], np.arange(10)) @@ -70,16 +70,16 @@ def test_nested_measurement(bg_writing) -> None: data1 = ds1.dataset.get_parameter_data()["bar1"] assert len(data1.keys()) == 2 - assert "foo1" in data1.keys() - assert "bar1" in data1.keys() + assert "foo1" in data1 + assert "bar1" in data1 assert_allclose(data1["foo1"], np.arange(10)) assert_allclose(data1["bar1"], np.arange(10) ** 2) data2 = ds2.dataset.get_parameter_data()["bar2"] assert len(data2.keys()) == 2 - assert "foo2" in data2.keys() - assert "bar2" in data2.keys() + assert "foo2" in data2 + assert "bar2" in data2 assert_allclose(data2["foo2"], np.arange(0, 20, 2)) assert_allclose(data2["bar2"], np.arange(0, 20, 2) ** 2) @@ -134,9 +134,9 @@ def test_nested_measurement_array( data1 = ds1.dataset.get_parameter_data()["bar1"] assert len(data1.keys()) == 3 - assert "foo1" in data1.keys() - assert "bar1spt" in data1.keys() - assert "bar1" in data1.keys() + assert "foo1" in data1 + assert "bar1spt" in data1 + assert "bar1" in data1 expected_foo1_data = np.repeat(np.arange(outer_len), inner_len1).reshape( outer_len, inner_len1 @@ -149,9 +149,9 @@ def test_nested_measurement_array( data2 = ds2.dataset.get_parameter_data()["bar2"] assert len(data2.keys()) == 3 - assert "foo2" in data2.keys() - assert "bar2spt" in data2.keys() - assert "bar2" in data2.keys() + assert "foo2" in data2 + assert "bar2spt" in data2 + assert "bar2" in data2 expected_foo2_data = np.repeat(np.arange(outer_len), inner_len2).reshape( outer_len, inner_len2 diff --git a/tests/drivers/test_keithley_s46.py b/tests/drivers/test_keithley_s46.py index 907e4cb1b788..76d0062bcefe 100644 --- a/tests/drivers/test_keithley_s46.py +++ b/tests/drivers/test_keithley_s46.py @@ -136,7 +136,7 @@ def test_channel_number_invariance(s46_four: KeithleyS46, s46_six: KeithleyS46) channel aliases should represent the same channel. See also page 2-5 of the manual (e.g. B1 is *always* channel 7) """ - for alias in KeithleyS46.channel_numbers.keys(): + for alias in KeithleyS46.channel_numbers: if hasattr(s46_four, alias) and hasattr(s46_six, alias): channel_four = getattr(s46_four, alias) channel_six = getattr(s46_six, alias) diff --git a/tests/drivers/test_keysight_b220x.py b/tests/drivers/test_keysight_b220x.py index 9b0aa16a9bca..8df739cfcff3 100644 --- a/tests/drivers/test_keysight_b220x.py +++ b/tests/drivers/test_keysight_b220x.py @@ -1,13 +1,17 @@ import itertools +from typing import TYPE_CHECKING import pytest from pyvisa.errors import VisaIOError from qcodes.instrument_drivers.Keysight.keysight_b220x import KeysightB220X +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture -def uut(): +def uut() -> "Generator[KeysightB220X, None, None]": try: resource_name = "insert_Keysight_B2200_VISA_resource_name_here" instance = KeysightB220X("switch_matrix", address=resource_name) @@ -65,9 +69,9 @@ def test_connect_emits_warning_on_statusbyte_not_null(uut) -> None: with pytest.warns(UserWarning): uut.connect(12, 33) - # The simulated instrument does not reset the settings to default - # values, so gnd mode is explicitly disabled here: - uut.gnd_mode(False) + # The simulated instrument does not reset the settings to default + # values, so gnd mode is explicitly disabled here: + uut.gnd_mode(False) def test_disconnect_throws_at_invalid_channel_number(uut) -> None: diff --git a/tests/drivers/test_lakeshore_335.py b/tests/drivers/test_lakeshore_335.py index d676bd15efb1..d02949013a5a 100644 --- a/tests/drivers/test_lakeshore_335.py +++ b/tests/drivers/test_lakeshore_335.py @@ -60,7 +60,7 @@ def __init__(self, *args, **kwargs) -> None: compensation_enabled=0, # False, units=1, ) # 'kelvin') - for i in self.channel_name_command.keys() + for i in self.channel_name_command } # simulate delayed heating diff --git a/tests/drivers/test_lakeshore_336.py b/tests/drivers/test_lakeshore_336.py index e7923c1010b7..3806c14e894f 100644 --- a/tests/drivers/test_lakeshore_336.py +++ b/tests/drivers/test_lakeshore_336.py @@ -82,7 +82,7 @@ def __init__(self, *args, **kwargs) -> None: compensation_enabled=0, # False, units=1, # 'kelvin' ) - for i in self.channel_name_command.keys() + for i in self.channel_name_command } # simulate delayed heating diff --git a/tests/drivers/test_tektronix_AWG70000A.py b/tests/drivers/test_tektronix_AWG70000A.py index 4c51c97071e0..aceb2f88afd1 100644 --- a/tests/drivers/test_tektronix_AWG70000A.py +++ b/tests/drivers/test_tektronix_AWG70000A.py @@ -84,7 +84,7 @@ def random_element(num_chans): """ data = {n: {} for n in range(1, 1 + num_chans)} rng = np.random.default_rng() - for key in data.keys(): + for key in data: data[key] = { "wfm": rng.standard_normal(2400), "m1": rng.integers(0, 2, 2400), diff --git a/tests/extensions/parameters/test_parameter_mixin_interdependent.py b/tests/extensions/parameters/test_parameter_mixin_interdependent.py index 88b8a8aa97bd..4a0087984523 100644 --- a/tests/extensions/parameters/test_parameter_mixin_interdependent.py +++ b/tests/extensions/parameters/test_parameter_mixin_interdependent.py @@ -147,17 +147,18 @@ def test_adding_dependent_parameter_later( assert callback_flag["called"], "dependency_update_method was not called." -def test_error_on_non_interdependent_dependency(store, mock_instr) -> None: - mock_instr.not_interdependent_param = cast( - "InterdependentParameter", - mock_instr.add_parameter( - name="not_interdependent_param", - set_cmd=lambda x: store.update({"not_interdep": x}), - get_cmd=lambda: store.get("not_interdep"), - docstring="A non-interdependent parameter.", - ), +def test_error_on_non_interdependent_dependency( + store, mock_instr: MockInstrument +) -> None: + + mock_instr.add_parameter( + name="not_interdependent_param", + set_cmd=lambda x: store.update({"not_interdep": x}), + get_cmd=lambda: store.get("not_interdep"), + docstring="A non-interdependent parameter.", ) - """A non-interdependent parameter.""" + + # A non-interdependent parameter. with ( pytest.warns(QCoDeSDeprecationWarning, match="does not correctly pass kwargs"), @@ -168,18 +169,15 @@ def test_error_on_non_interdependent_dependency(store, mock_instr) -> None: TypeError, match="must be an instance of InterdependentParameterMixin" ), ): - mock_instr.managed_param = cast( - "InterdependentParameter", - mock_instr.add_parameter( - name="managed_param", - parameter_class=InterdependentParameter, - dependent_on=["not_interdependent_param"], - set_cmd=lambda x: store.update({"managed": x}), - get_cmd=lambda: store.get("managed"), - docstring="Parameter managed_param depends on a non-interdependent param.", - ), + _ = mock_instr.add_parameter( + name="managed_param", + parameter_class=InterdependentParameter, + dependent_on=["not_interdependent_param"], + set_cmd=lambda x: store.update({"managed": x}), + get_cmd=lambda: store.get("managed"), + docstring="Parameter managed_param depends on a non-interdependent param.", ) - """Parameter managed_param depends on a non-interdependent param.""" + # Parameter managed_param depends on a non-interdependent param def test_parsers_and_dependency_propagation(store, mock_instr) -> None: diff --git a/tests/parameter/test_delegate_parameter.py b/tests/parameter/test_delegate_parameter.py index 26a6ad1b1e30..d682cdd6b517 100644 --- a/tests/parameter/test_delegate_parameter.py +++ b/tests/parameter/test_delegate_parameter.py @@ -442,7 +442,7 @@ def _assert_none_source_is_correct(delegate_param: DelegateParameter) -> None: delegate_param.set(1) snapshot = delegate_param.snapshot() assert snapshot["source_parameter"] is None - assert "value" not in snapshot.keys() + assert "value" not in snapshot snapshot.pop("ts") updated_snapshot = delegate_param.snapshot(update=True) updated_snapshot.pop("ts") diff --git a/tests/parameter/test_parameter_registration.py b/tests/parameter/test_parameter_registration.py index b70fa44cf63e..235bae32f1fb 100644 --- a/tests/parameter/test_parameter_registration.py +++ b/tests/parameter/test_parameter_registration.py @@ -68,7 +68,7 @@ def test_parameter_registration_with_non_instr_passing_parameter( ) # test that even if the parameter does not pass instrument to the baseclass # it will still be registered on the instr - assert "brokenparameter" in dummy_attr_instr.parameters.keys() + assert "brokenparameter" in dummy_attr_instr.parameters def test_parameter_registration_with_non_kwargs_passing_parameter( @@ -87,7 +87,7 @@ def test_parameter_registration_with_non_kwargs_passing_parameter( # test that even if the parameter does not pass kwargs # (bind_to_instrument specifically) # to the baseclass it will still be registered on the instr - assert "brokenparameter2" in dummy_attr_instr.parameters.keys() + assert "brokenparameter2" in dummy_attr_instr.parameters def test_parameter_registration_bind_to_instrument_false( @@ -100,4 +100,4 @@ def test_parameter_registration_bind_to_instrument_false( get_cmd=None, bind_to_instrument=False, ) - assert "non_binding_parameter" not in dummy_attr_instr.parameters.keys() + assert "non_binding_parameter" not in dummy_attr_instr.parameters diff --git a/tests/parameter/test_validators.py b/tests/parameter/test_validators.py index faee51975450..4d98bbfb7866 100644 --- a/tests/parameter/test_validators.py +++ b/tests/parameter/test_validators.py @@ -139,7 +139,7 @@ def test_validator_snapshot() -> None: snapshot = p.snapshot() assert "" not in snapshot["validators"] assert "" not in snapshot["validators"] - assert "vals" not in snapshot.keys() + assert "vals" not in snapshot p.vals = Ints(min_value=4, max_value=6) snapshot = p.snapshot() assert "" not in snapshot["validators"] diff --git a/tests/test_channels.py b/tests/test_channels.py index b15567a5ec8c..1f921b8b9968 100644 --- a/tests/test_channels.py +++ b/tests/test_channels.py @@ -379,7 +379,7 @@ def test_channel_tuple_snapshot_enabled(empty_instrument: Instrument) -> None: snapshot = empty_instrument.channels.snapshot() assert snapshot["snapshotable"] is True assert len(snapshot.keys()) == 3 - assert "channels" in snapshot.keys() + assert "channels" in snapshot def test_channel_tuple_dir(dci: DummyChannelInstrument) -> None: @@ -829,36 +829,36 @@ def test_multi_function_on_empty_channel_tuple_raises( def _verify_multiparam_data(data) -> None: - assert "multi_setpoint_param_this_setpoint_set" in data.arrays.keys() + assert "multi_setpoint_param_this_setpoint_set" in data.arrays assert_array_equal( data.arrays["multi_setpoint_param_this_setpoint_set"].ndarray, np.repeat(np.arange(5.0, 10).reshape(1, 5), 11, axis=0), ) - assert "dci_ChanA_multi_setpoint_param_this" in data.arrays.keys() + assert "dci_ChanA_multi_setpoint_param_this" in data.arrays assert_array_equal( data.arrays["dci_ChanA_multi_setpoint_param_this"].ndarray, np.zeros((11, 5)) ) - assert "dci_ChanA_multi_setpoint_param_this" in data.arrays.keys() + assert "dci_ChanA_multi_setpoint_param_this" in data.arrays assert_array_equal( data.arrays["dci_ChanA_multi_setpoint_param_that"].ndarray, np.ones((11, 5)) ) - assert "dci_ChanA_temperature_set" in data.arrays.keys() + assert "dci_ChanA_temperature_set" in data.arrays assert_array_equal( data.arrays["dci_ChanA_temperature_set"].ndarray, np.arange(0, 10.1, 1) ) def _verify_array_data(data, channels=("A",)) -> None: - assert "array_setpoint_param_this_setpoint_set" in data.arrays.keys() + assert "array_setpoint_param_this_setpoint_set" in data.arrays assert_array_equal( data.arrays["array_setpoint_param_this_setpoint_set"].ndarray, np.repeat(np.arange(5.0, 10).reshape(1, 5), 11, axis=0), ) for channel in channels: aname = f"dci_Chan{channel}_dummy_array_parameter" - assert aname in data.arrays.keys() + assert aname in data.arrays assert_array_equal(data.arrays[aname].ndarray, np.ones((11, 5)) + 1) - assert "dci_ChanA_temperature_set" in data.arrays.keys() + assert "dci_ChanA_temperature_set" in data.arrays assert_array_equal( data.arrays["dci_ChanA_temperature_set"].ndarray, np.arange(0, 10.1, 1) ) diff --git a/tests/test_instrument.py b/tests/test_instrument.py index 111f502b755a..989ab0fde72d 100644 --- a/tests/test_instrument.py +++ b/tests/test_instrument.py @@ -281,7 +281,7 @@ def test_add_remove_f_p(testdummy) -> None: match="Use attributes directly on the instrument object instead", ): fcn = testdummy["function"] - assert isinstance(fcn, Function) + assert isinstance(fcn, Function) # by design, one gets the parameter if a function exists # and has same name with pytest.warns( @@ -289,7 +289,7 @@ def test_add_remove_f_p(testdummy) -> None: match="Use attributes directly on the instrument object instead", ): dac1 = testdummy["dac1"] - assert isinstance(dac1, Parameter) + assert isinstance(dac1, Parameter) def test_instances(testdummy, parabola) -> None: diff --git a/tests/test_station.py b/tests/test_station.py index 01ec4388559c..c8d03a290cc6 100644 --- a/tests/test_station.py +++ b/tests/test_station.py @@ -528,12 +528,12 @@ def test_init_parameters() -> None: ) mock = st.load_instrument("mock") for ch in ["ch1", "ch2"]: - assert ch in mock.parameters.keys() + assert ch in mock.parameters assert len(mock.parameters) == 4 # there is also IDN and a fixed param # Overwrite parameter mock = st.load_instrument("mock", gates=["TestGate"]) - assert "TestGate" in mock.parameters.keys() + assert "TestGate" in mock.parameters assert len(mock.parameters) == 3 # there is also IDN and a fixed param # test address sims_path = get_qcodes_path("instrument", "sims") From 35f2560641995c02b1e9551d98fa3a81358398a3 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 09:08:16 +0200 Subject: [PATCH 08/43] Enable PT014 --- pyproject.toml | 2 +- tests/test_snapshot.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2137d03079f4..52ba5a4cbc89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 86a4daffa039..124e9c7dfab2 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -58,7 +58,6 @@ def test_snapshot_skip_params_update( (["v1", "v2", "v3", "v4"], ["v2"]), (["v1", "v2", "v3", "v4"], ["v3"]), (["v1", "v2", "v3", "v4"], ["v4"]), - (["v1", "v2", "v3", "v4"], ["v4"]), (["v1", "v2", "v3", "v4"], ["v1", "v2"]), (["v1", "v2", "v3", "v4"], []), ], From 68912a151c697e2632aefdc9cf4ccee555c30800 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 09:16:33 +0200 Subject: [PATCH 09/43] Implement C405 and C414 --- pyproject.toml | 2 +- src/qcodes/extensions/infer.py | 2 +- src/qcodes/math_utils/field_vector.py | 2 +- src/qcodes/station.py | 7 ++++--- src/qcodes/utils/attribute_helpers.py | 2 +- tests/conftest.py | 2 +- tests/dataset/measurement/test_load_legacy_data.py | 6 +++--- tests/dataset/test_dataset_basic.py | 2 +- tests/dataset/test_guid_helpers.py | 2 +- tests/dataset/test_plotting.py | 6 ++---- tests/drivers/AlazarTech/test_alazar_api.py | 4 ++-- tests/drivers/test_keithley_26xx.py | 4 ++-- tests/extensions/test_infer.py | 14 +++++++------- tests/parameter/test_on_off_mapping.py | 2 +- 14 files changed, 28 insertions(+), 29 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 52ba5a4cbc89..1c7356cd028a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/extensions/infer.py b/src/qcodes/extensions/infer.py index dc31e1a8ca58..3abc0d3ff0bd 100644 --- a/src/qcodes/extensions/infer.py +++ b/src/qcodes/extensions/infer.py @@ -217,7 +217,7 @@ def _merge_user_and_class_attrs( if alt_source_attrs is None: return InferAttrs.known_attrs() elif isinstance(alt_source_attrs, str): - return set.union(set((alt_source_attrs,)), set(InferAttrs.known_attrs())) + return set.union({alt_source_attrs}, set(InferAttrs.known_attrs())) else: return set.union(set(alt_source_attrs), set(InferAttrs.known_attrs())) diff --git a/src/qcodes/math_utils/field_vector.py b/src/qcodes/math_utils/field_vector.py index 284627d89297..6dab47bf2f82 100644 --- a/src/qcodes/math_utils/field_vector.py +++ b/src/qcodes/math_utils/field_vector.py @@ -204,7 +204,7 @@ def set_vector(self, **new_values: float) -> None: >>> f.set_vector(x=9, y=0, r=3) """ - names = sorted(list(new_values.keys())) + names = sorted(new_values.keys()) groups = [["x", "y", "z"], ["phi", "r", "theta"], ["phi", "rho", "z"]] if names not in groups: raise ValueError("Can only set vector with a complete value set") diff --git a/src/qcodes/station.py b/src/qcodes/station.py index 30ea43a39b66..b7ae92432d26 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -851,9 +851,10 @@ def update_schema_file( json.dump(data, f, indent=4) additional_instrument_modules = additional_instrument_modules or [] - instrument_modules: set[ModuleType] = set( - [qcodes.instrument_drivers, *additional_instrument_modules] - ) + instrument_modules: set[ModuleType] = { + qcodes.instrument_drivers, + *additional_instrument_modules, + } instrument_names = tuple( itertools.chain.from_iterable( diff --git a/src/qcodes/utils/attribute_helpers.py b/src/qcodes/utils/attribute_helpers.py index 4c11e6168bd5..04d181b0f224 100644 --- a/src/qcodes/utils/attribute_helpers.py +++ b/src/qcodes/utils/attribute_helpers.py @@ -115,7 +115,7 @@ def strip_attrs(obj: object, whitelist: "Sequence[str]" = ()) -> None: """ try: - lst = set(list(obj.__dict__.keys())) - set(whitelist) + lst = set(obj.__dict__.keys()) - set(whitelist) for key in lst: try: del obj.__dict__[key] diff --git a/tests/conftest.py b/tests/conftest.py index 2018a865df69..1d4741a1dbb8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -38,7 +38,7 @@ def pytest_configure(config: pytest.Config) -> None: def pytest_runtest_setup(item: pytest.Item) -> None: - ALL = set(["darwin", "linux", "win32"]) + ALL = {"darwin", "linux", "win32"} supported_platforms = ALL.intersection(mark.name for mark in item.iter_markers()) if supported_platforms and sys.platform not in supported_platforms: pytest.skip(f"cannot run on platform {sys.platform}") diff --git a/tests/dataset/measurement/test_load_legacy_data.py b/tests/dataset/measurement/test_load_legacy_data.py index 40bdb7abea84..05b83dd3108f 100644 --- a/tests/dataset/measurement/test_load_legacy_data.py +++ b/tests/dataset/measurement/test_load_legacy_data.py @@ -34,7 +34,7 @@ def test_load_legacy_files_2d() -> None: snapshot_str = data.get_metadata("snapshot") assert isinstance(snapshot_str, str) snapshot = json.loads(snapshot_str) - assert sorted(list(snapshot.keys())) == [ + assert sorted(snapshot.keys()) == [ "__class__", "arrays", "formatter", @@ -72,7 +72,7 @@ def test_load_legacy_files_1d() -> None: snapshot_str = data.get_metadata("snapshot") assert isinstance(snapshot_str, str) snapshot = json.loads(snapshot_str) - assert sorted(list(snapshot.keys())) == [ + assert sorted(snapshot.keys()) == [ "__class__", "arrays", "formatter", @@ -110,7 +110,7 @@ def test_load_legacy_files_1d_pathlib_path() -> None: snapshot_str = data.get_metadata("snapshot") assert isinstance(snapshot_str, str) snapshot = json.loads(snapshot_str) - assert sorted(list(snapshot.keys())) == [ + assert sorted(snapshot.keys()) == [ "__class__", "arrays", "formatter", diff --git a/tests/dataset/test_dataset_basic.py b/tests/dataset/test_dataset_basic.py index e0e45bb3b73d..d0ab9cf21ebb 100644 --- a/tests/dataset/test_dataset_basic.py +++ b/tests/dataset/test_dataset_basic.py @@ -420,7 +420,7 @@ def test_set_interdependencies(dataset) -> None: paramspecs = shadow_ds.paramspecs expected_keys = ["a_param", "b_param", "c_param"] - keys = sorted(list(paramspecs.keys())) + keys = sorted(paramspecs.keys()) assert keys == expected_keys for expected_param_name in expected_keys: ps = paramspecs[expected_param_name] diff --git a/tests/dataset/test_guid_helpers.py b/tests/dataset/test_guid_helpers.py index 4c4c00674750..9ddfbcf57b11 100644 --- a/tests/dataset/test_guid_helpers.py +++ b/tests/dataset/test_guid_helpers.py @@ -75,7 +75,7 @@ def test_guids_from_list_str() -> None: assert guids_from_list_str(str(tuple(guids))) == tuple(guids) extracted_guids = guids_from_list_str(str(set(guids))) assert extracted_guids is not None - assert sorted(extracted_guids) == sorted(tuple(guids)) + assert sorted(extracted_guids) == sorted(guids) def test_many_guids_from_list_str() -> None: diff --git a/tests/dataset/test_plotting.py b/tests/dataset/test_plotting.py index 94d9e0dcec45..98825aad3857 100644 --- a/tests/dataset/test_plotting.py +++ b/tests/dataset/test_plotting.py @@ -37,11 +37,9 @@ class TerminateLoopException(Exception): @given( param_name=text(min_size=1, max_size=10), param_label=text(min_size=0, max_size=15), - scale=sampled_from(sorted(list(_ENGINEERING_PREFIXES.keys()))), + scale=sampled_from(sorted(_ENGINEERING_PREFIXES.keys())), unit=sampled_from( - sorted( - list(_UNITS_FOR_RESCALING.union(["", "unit", "kg", "%", "permille", "nW"])) - ) + sorted(_UNITS_FOR_RESCALING.union(["", "unit", "kg", "%", "permille", "nW"])) ), data_strategy=data(), ) diff --git a/tests/drivers/AlazarTech/test_alazar_api.py b/tests/drivers/AlazarTech/test_alazar_api.py index cd4bbd70c794..7b778abbb557 100644 --- a/tests/drivers/AlazarTech/test_alazar_api.py +++ b/tests/drivers/AlazarTech/test_alazar_api.py @@ -129,7 +129,7 @@ def test_get_board_info(alazar_api) -> None: "board_kind", "max_samples", "bits_per_sample", - } == set(list(info.keys())) + } == set(info.keys()) assert info["system_id"] == SYSTEM_ID assert info["board_id"] == BOARD_ID @@ -151,7 +151,7 @@ def test_idn(alazar) -> None: "pcie_link_width", "bits_per_sample", "max_samples", - } == set(list(idn.keys())) + } == set(idn.keys()) assert idn["vendor"] == "AlazarTech" assert idn["model"][:3] == "ATS" diff --git a/tests/drivers/test_keithley_26xx.py b/tests/drivers/test_keithley_26xx.py index 75e0ded8322a..84fa1cd8bf34 100644 --- a/tests/drivers/test_keithley_26xx.py +++ b/tests/drivers/test_keithley_26xx.py @@ -28,7 +28,7 @@ def _make_driver(): @pytest.fixture(scope="function", name="smus") def _make_smus(driver): smu_names = {"smua", "smub"} - assert smu_names == set(list(driver.submodules.keys())) + assert smu_names == set(driver.submodules.keys()) yield tuple(getattr(driver, smu_name) for smu_name in smu_names) @@ -43,7 +43,7 @@ def test_idn(driver) -> None: def test_smu_channels_and_their_parameters(driver) -> None: - assert {"smua", "smub"} == set(list(driver.submodules.keys())) + assert {"smua", "smub"} == set(driver.submodules.keys()) for smu_name in ("smua", "smub"): smu = getattr(driver, smu_name) diff --git a/tests/extensions/test_infer.py b/tests/extensions/test_infer.py index 087dd169de02..afcd12e4cba9 100644 --- a/tests/extensions/test_infer.py +++ b/tests/extensions/test_infer.py @@ -275,10 +275,10 @@ def test_parameters_on_delegate_instruments(instrument_fixture, good_inst_delega def test_merge_user_and_class_attrs(): InferAttrs.add("attr1") attr_set = _merge_user_and_class_attrs("attr2") - assert set(("attr1", "attr2")) == attr_set + assert {"attr1", "attr2"} == attr_set attr_set_list = _merge_user_and_class_attrs(("attr2", "attr3")) - assert set(("attr1", "attr2", "attr3")) == attr_set_list + assert {"attr1", "attr2", "attr3"} == attr_set_list def test_infer_attrs(): @@ -286,14 +286,14 @@ def test_infer_attrs(): assert InferAttrs.known_attrs() == () InferAttrs.add("attr1") - assert set(InferAttrs.known_attrs()) == set(("attr1",)) + assert set(InferAttrs.known_attrs()) == {"attr1"} InferAttrs.add("attr2") InferAttrs.discard("attr1") - assert set(InferAttrs.known_attrs()) == set(("attr2",)) + assert set(InferAttrs.known_attrs()) == {"attr2"} InferAttrs.add(("attr1", "attr3")) - assert set(InferAttrs.known_attrs()) == set(("attr1", "attr2", "attr3")) + assert set(InferAttrs.known_attrs()) == {"attr1", "attr2", "attr3"} def test_get_parameter_chain_with_loops(good_inst_delegates): @@ -327,7 +327,7 @@ def test_chain_links_of_type(): InferAttrs.add("linked_parameter") user_links = get_chain_links_of_type(UserLinkingParameter, user_link_2) - assert set(user_links) == set([user_link, user_link_2]) + assert set(user_links) == {user_link, user_link_2} def test_sole_chain_link_of_type(): @@ -362,7 +362,7 @@ def test_get_instrument_from_chain( instruments = get_parent_instruments_from_chain_of_type( DummyInstrument, good_inst_del_3 ) - assert set(instruments) == set([inst, inst2]) + assert set(instruments) == {inst, inst2} def test_get_sole_instrument_from_chain(instrument_fixture2, multi_inst_chain): diff --git a/tests/parameter/test_on_off_mapping.py b/tests/parameter/test_on_off_mapping.py index 190ef33dde29..2bb4df4f8ede 100644 --- a/tests/parameter/test_on_off_mapping.py +++ b/tests/parameter/test_on_off_mapping.py @@ -7,7 +7,7 @@ def test_values_of_mapping_are_only_the_given_two() -> None: val_mapping = create_on_off_val_mapping(on_val="666", off_val="000") - values_set = set(list(val_mapping.values())) + values_set = set(val_mapping.values()) assert values_set == {"000", "666"} From 570297f315ab7fe90134f9af2d10775593a59025 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 09:19:07 +0200 Subject: [PATCH 10/43] Implement C419 --- pyproject.toml | 2 +- .../instrument_drivers/american_magnetics/AMI430_visa.py | 2 +- src/qcodes/utils/installation_info.py | 2 +- .../keysight_b1500/b1500_driver_tests/test_b1520a_cmu.py | 4 ++-- tests/drivers/test_Keysight_33XXX.py | 8 +++----- tests/drivers/test_ami430_visa.py | 4 ++-- tests/drivers/test_keithley_s46.py | 2 +- 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1c7356cd028a..d18224429872 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index 8aaafe8f195d..56653f8f8d59 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -1058,7 +1058,7 @@ def _verify_safe_setpoint( return bool(np.linalg.norm(setpoint_values) < self._field_limit) answer = any( - [limit_function(*setpoint_values) for limit_function in self._field_limit] + limit_function(*setpoint_values) for limit_function in self._field_limit ) return answer diff --git a/src/qcodes/utils/installation_info.py b/src/qcodes/utils/installation_info.py index 73837e1c52c2..2683f7b37b25 100644 --- a/src/qcodes/utils/installation_info.py +++ b/src/qcodes/utils/installation_info.py @@ -28,7 +28,7 @@ def is_qcodes_installed_editably() -> bool | None: stdout=subprocess.PIPE, ) e_pkgs = json.loads(pipproc.stdout.decode("utf-8")) - answer = any([d["name"] == "qcodes" for d in e_pkgs]) + answer = any(d["name"] == "qcodes" for d in e_pkgs) except Exception as e: # we actually do want a catch-all here log.warning(f"{type(e)}: {e!s}") answer = None diff --git a/tests/drivers/keysight_b1500/b1500_driver_tests/test_b1520a_cmu.py b/tests/drivers/keysight_b1500/b1500_driver_tests/test_b1520a_cmu.py index 4a5532f5d2c7..b7b54cef35d9 100644 --- a/tests/drivers/keysight_b1500/b1500_driver_tests/test_b1520a_cmu.py +++ b/tests/drivers/keysight_b1500/b1500_driver_tests/test_b1520a_cmu.py @@ -215,7 +215,7 @@ def test_cv_sweep_voltages(cmu: KeysightB1520A) -> None: cmu.cv_sweep.sweep_steps(steps) voltages = cmu.cv_sweep_voltages() - assert all([a == b for a, b in zip(np.linspace(start, end, steps), voltages)]) + assert all(a == b for a, b in zip(np.linspace(start, end, steps), voltages)) def test_sweep_modes(cmu: KeysightB1520A) -> None: @@ -234,7 +234,7 @@ def test_sweep_modes(cmu: KeysightB1520A) -> None: cmu.cv_sweep.sweep_mode(mode) voltages = cmu.cv_sweep_voltages() - assert all([a == b for a, b in zip((-1.0, 0.0, 1.0, 0.0, -1.0), voltages)]) + assert all(a == b for a, b in zip((-1.0, 0.0, 1.0, 0.0, -1.0), voltages)) def test_run_sweep(cmu: KeysightB1520A) -> None: diff --git a/tests/drivers/test_Keysight_33XXX.py b/tests/drivers/test_Keysight_33XXX.py index b48ef15cc01e..ddac1d07923f 100644 --- a/tests/drivers/test_Keysight_33XXX.py +++ b/tests/drivers/test_Keysight_33XXX.py @@ -126,11 +126,9 @@ def test_wrong_model_warns( assert len(warns) >= 4 assert ( sum( - [ - "The driver class name " in record.msg - and "does not match the detected model" in record.msg - for record in warns - ] + "The driver class name " in record.msg + and "does not match the detected model" in record.msg + for record in warns ) == 4 ) diff --git a/tests/drivers/test_ami430_visa.py b/tests/drivers/test_ami430_visa.py index ba98879e2471..3b6b4cd5e149 100644 --- a/tests/drivers/test_ami430_visa.py +++ b/tests/drivers/test_ami430_visa.py @@ -702,7 +702,7 @@ def test_field_limit_exception(current_driver: AMIModel4303D) -> None: set_points = zip(*(i.flatten() for i in np.meshgrid(x, y, z))) for set_point in set_points: - should_not_raise = any([is_safe(*set_point) for is_safe in field_limit]) + should_not_raise = any(is_safe(*set_point) for is_safe in field_limit) if should_not_raise: current_driver.cartesian(set_point) @@ -712,7 +712,7 @@ def test_field_limit_exception(current_driver: AMIModel4303D) -> None: assert "field would exceed limit" in excinfo.value.args[0] vals_and_setpoints = zip(current_driver.cartesian(), set_point) - belief = not (all([val == sp for val, sp in vals_and_setpoints])) + belief = not (all(val == sp for val, sp in vals_and_setpoints)) assert belief diff --git a/tests/drivers/test_keithley_s46.py b/tests/drivers/test_keithley_s46.py index 76d0062bcefe..5f5e94c0032e 100644 --- a/tests/drivers/test_keithley_s46.py +++ b/tests/drivers/test_keithley_s46.py @@ -23,7 +23,7 @@ def calc_channel_nr(alias: str) -> int: return offset_dict[alias[0]] + int(alias[1:]) assert all( - [nr == calc_channel_nr(al) for al, nr in KeithleyS46.channel_numbers.items()] + nr == calc_channel_nr(al) for al, nr in KeithleyS46.channel_numbers.items() ) From 8e22ca4e6321d99c9758a2771dd1862080accb3d Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 09:21:07 +0200 Subject: [PATCH 11/43] Implement SIM201 --- pyproject.toml | 2 +- src/qcodes/dataset/sqlite/db_upgrades/__init__.py | 2 +- src/qcodes/dataset/sqlite/queries.py | 2 +- src/qcodes/instrument/instrument_base.py | 2 +- .../Keysight/keysightb1500/KeysightB1520A.py | 2 +- tests/dataset/measurement/test_measurement_context_manager.py | 2 +- tests/drivers/test_tektronix_AWG70000A.py | 2 +- tests/parameter/test_delegate_parameter.py | 4 ++-- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d18224429872..d98baa71bb45 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/dataset/sqlite/db_upgrades/__init__.py b/src/qcodes/dataset/sqlite/db_upgrades/__init__.py index 8af71f7cf291..c8e9d9b866ce 100644 --- a/src/qcodes/dataset/sqlite/db_upgrades/__init__.py +++ b/src/qcodes/dataset/sqlite/db_upgrades/__init__.py @@ -143,7 +143,7 @@ def perform_db_upgrade(conn: AtomicConnection, version: int = -1) -> None: current_version = get_user_version(conn) - show_progress_bar = not (_get_no_of_runs(conn) == 0) + show_progress_bar = _get_no_of_runs(conn) != 0 if current_version < version: log.info("Commencing database upgrade") diff --git a/src/qcodes/dataset/sqlite/queries.py b/src/qcodes/dataset/sqlite/queries.py index ccfb2afffa4a..fbb132f9da1e 100644 --- a/src/qcodes/dataset/sqlite/queries.py +++ b/src/qcodes/dataset/sqlite/queries.py @@ -2299,7 +2299,7 @@ def raw_time_to_str_time( def _check_if_table_found(conn: AtomicConnection, table_name: str) -> bool: query = "SELECT name FROM sqlite_master WHERE type='table' AND name=?" cursor = conn.cursor() - return not many_many(cursor.execute(query, (table_name,)), "name") == [] + return many_many(cursor.execute(query, (table_name,)), "name") != [] def _get_result_table_name_by_guid(conn: AtomicConnection, guid: str) -> str: diff --git a/src/qcodes/instrument/instrument_base.py b/src/qcodes/instrument/instrument_base.py index aa80283df133..21f26445bd08 100644 --- a/src/qcodes/instrument/instrument_base.py +++ b/src/qcodes/instrument/instrument_base.py @@ -528,7 +528,7 @@ def print_readable_snapshot( if unit != "": # corresponds to no unit msg += f"({unit})" # Truncate the message if it is longer than max length - if len(msg) > max_chars and not max_chars == -1: + if len(msg) > max_chars and max_chars != -1: msg = msg[0 : max_chars - 3] + "..." print(msg) diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py index 324fa6a5ddc6..5e23049a8da7 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py @@ -808,7 +808,7 @@ def sign(s: float) -> float: end_value = self.cv_sweep.sweep_end() step_value = self.cv_sweep.sweep_steps() mode = self.cv_sweep.sweep_mode() - if mode in (2, 4) and not sign(start_value) == sign(end_value): + if mode in (2, 4) and sign(start_value) != sign(end_value): if sign(start_value) == 0: start_value = sign(start_value) * 0.005 # resolution elif sign(end_value) == 0: diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index b316d86c5ca2..948b30464638 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -725,7 +725,7 @@ def test_datasaver_scalars( # so we add a bit more wait time here if the expected number # of points have not been written for _ in range(10): - if not datasaver.points_written == breakpoint + 1: + if datasaver.points_written != breakpoint + 1: sleep(write_period * 1.1) assert datasaver.points_written == breakpoint + 1 diff --git a/tests/drivers/test_tektronix_AWG70000A.py b/tests/drivers/test_tektronix_AWG70000A.py index aceb2f88afd1..99c955aefaf4 100644 --- a/tests/drivers/test_tektronix_AWG70000A.py +++ b/tests/drivers/test_tektronix_AWG70000A.py @@ -25,7 +25,7 @@ def strip_outer_tags(sml: str) -> str: complies with the schema provided by tektronix """ # make function idempotent - if not sml[1:9] == "DataFile": + if sml[1:9] != "DataFile": print("Incorrect file format or outer tags already stripped") return sml diff --git a/tests/parameter/test_delegate_parameter.py b/tests/parameter/test_delegate_parameter.py index d682cdd6b517..fb23aadd8d74 100644 --- a/tests/parameter/test_delegate_parameter.py +++ b/tests/parameter/test_delegate_parameter.py @@ -123,7 +123,7 @@ def test_same_label_and_unit_on_init(simple_param: Parameter) -> None: def test_overwritten_unit_on_init(simple_param: Parameter) -> None: d = DelegateParameter("test_delegate_parameter", source=simple_param, unit="Ohm") assert d.label == simple_param.label - assert not d.unit == simple_param.unit + assert d.unit != simple_param.unit assert d.unit == "Ohm" @@ -132,7 +132,7 @@ def test_overwritten_label_on_init(simple_param: Parameter) -> None: "test_delegate_parameter", source=simple_param, label="Physical parameter" ) assert d.unit == simple_param.unit - assert not d.label == simple_param.label + assert d.label != simple_param.label assert d.label == "Physical parameter" From 01e2e4452ebaa9546cb98c0f13848ae0bbf6f7e9 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 10:40:51 +0200 Subject: [PATCH 12/43] Add PIE790 --- pyproject.toml | 2 +- src/qcodes/dataset/dond/sweeps.py | 5 ----- src/qcodes/extensions/_refactor.py | 1 - src/qcodes/instrument/channel.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL068_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL155_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL303QMD_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL303QMT_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL303_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_PL601_P.py | 2 -- .../instrument_drivers/AimTTi/Aim_TTi_QL355_TP.py | 2 -- src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py | 2 -- src/qcodes/instrument_drivers/AlazarTech/ATS.py | 3 --- .../AlazarTech/ATS_acquisition_controllers.py | 1 - .../instrument_drivers/Keithley/Keithley_2601B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2602A.py | 2 -- .../instrument_drivers/Keithley/Keithley_2602B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2604B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2611B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2612B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2614B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2634B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2635B.py | 2 -- .../instrument_drivers/Keithley/Keithley_2636B.py | 2 -- src/qcodes/instrument_drivers/QDev/QDac_channels.py | 2 -- src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py | 2 -- .../rohde_schwarz/Rohde_Schwarz_ZNB20.py | 2 -- .../rohde_schwarz/Rohde_Schwarz_ZNB8.py | 2 -- .../rohde_schwarz/_rohde_schwarz_znle.py | 10 ---------- src/qcodes/instrument_drivers/tektronix/DPO7200xx.py | 2 -- src/qcodes/instrument_drivers/tektronix/TPS2012.py | 2 -- src/qcodes/parameters/delegate_parameter.py | 1 - src/qcodes/station.py | 2 -- tests/drivers/test_stahl.py | 1 - tests/extensions/parameters/test_parameter_mixin.py | 6 ------ .../parameters/test_parameter_mixin_on_cache_change.py | 2 -- .../test_parameter_mixin_set_cache_value_on_reset.py | 2 -- 37 files changed, 1 insertion(+), 85 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index d98baa71bb45..14cd74352ff0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/dataset/dond/sweeps.py b/src/qcodes/dataset/dond/sweeps.py index 7f3062fe8100..e971ea82ed79 100644 --- a/src/qcodes/dataset/dond/sweeps.py +++ b/src/qcodes/dataset/dond/sweeps.py @@ -23,7 +23,6 @@ def get_setpoints(self) -> npt.NDArray[T]: """ Returns an array of setpoint values for this sweep. """ - pass @property @abstractmethod @@ -31,7 +30,6 @@ def param(self) -> ParameterBase: """ Returns the Qcodes sweep parameter. """ - pass @property @abstractmethod @@ -39,7 +37,6 @@ def delay(self) -> float: """ Delay between two consecutive sweep points. """ - pass @property @abstractmethod @@ -47,7 +44,6 @@ def num_points(self) -> int: """ Number of sweep points. """ - pass @property @abstractmethod @@ -55,7 +51,6 @@ def post_actions(self) -> ActionsT: """ Actions to be performed after setting param to its setpoint. """ - pass @property def get_after_set(self) -> bool: diff --git a/src/qcodes/extensions/_refactor.py b/src/qcodes/extensions/_refactor.py index e9fc20c177a1..9b40054130c6 100644 --- a/src/qcodes/extensions/_refactor.py +++ b/src/qcodes/extensions/_refactor.py @@ -91,7 +91,6 @@ def visit_Arg(self, node: cst.Arg) -> None: self.annotations.parameter_class = e_value case cst.Arg(): _LOG.info("Unexpected node %s", str(node)) - pass def leave_Call(self, original_node: cst.Call, updated_node: cst.Call) -> cst.Call: call_name = _get_call_name(updated_node) diff --git a/src/qcodes/instrument/channel.py b/src/qcodes/instrument/channel.py index c8936dc2c1f9..cbd09872e549 100644 --- a/src/qcodes/instrument/channel.py +++ b/src/qcodes/instrument/channel.py @@ -924,8 +924,6 @@ def validate(self, value: InstrumentChannel, context: str = "") -> None: class ChannelListValidator(ChannelTupleValidator): """Alias for backwards compatibility. Do not use""" - pass - class AutoLoadableInstrumentChannel(InstrumentChannel): """ diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL068_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL068_P.py index 6db141bbd099..b209e7059a7d 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL068_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL068_P.py @@ -5,5 +5,3 @@ class AimTTiPL068P(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL068-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL155_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL155_P.py index c557d5f188b6..7cdda788d7ec 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL155_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL155_P.py @@ -5,5 +5,3 @@ class AimTTiPL155P(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL155-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMD_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMD_P.py index 11120e9962a6..eeb9a8072757 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMD_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMD_P.py @@ -5,5 +5,3 @@ class AimTTiPL303QMDP(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL303QMD-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMT_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMT_P.py index bb85f41c2ae1..51dcc4336789 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMT_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303QMT_P.py @@ -5,5 +5,3 @@ class AimTTiPL303QMTP(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL303QMT-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303_P.py index 34f809f93c93..7836d2719e81 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL303_P.py @@ -5,5 +5,3 @@ class AimTTiPL303P(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL303-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL601_P.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL601_P.py index fcc75a78bcb3..1fa6af6737b0 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL601_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_PL601_P.py @@ -5,5 +5,3 @@ class AimTTiPL601(AimTTi): """ This is the QCoDeS driver for the Aim TTi PL601-P series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_QL355_TP.py b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_QL355_TP.py index e60573eec118..bc796aa5d5a9 100644 --- a/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_QL355_TP.py +++ b/src/qcodes/instrument_drivers/AimTTi/Aim_TTi_QL355_TP.py @@ -5,5 +5,3 @@ class AimTTiQL355TP(AimTTi): """ This is the QCoDeS driver for the Aim TTi QL355TP series power supply. """ - - pass diff --git a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py index 67db739b4e40..4f31f17e7d1d 100644 --- a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py @@ -20,8 +20,6 @@ class NotKnownModel(Exception): An Error thrown when connecting to an unknown Aim TTi model """ - pass - class AimTTiChannel(InstrumentChannel): """ diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS.py b/src/qcodes/instrument_drivers/AlazarTech/ATS.py index 572d51c69318..9c63688b54f5 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -850,13 +850,11 @@ def pre_start_capture(self) -> None: The Alazar instrument will call this method right before 'AlazarStartCapture' is called """ - pass def pre_acquire(self) -> None: """ This method is called immediately after 'AlazarStartCapture' is called """ - pass def handle_buffer( self, buffer: npt.NDArray, buffer_number: int | None = None @@ -897,7 +895,6 @@ def buffer_done_callback(self, buffers_completed: int) -> None: to local memory at the time of this callback. """ - pass class AcquisitionController[OutputType](Instrument, AcquisitionInterface[Any]): diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py b/src/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py index 5b64c61829be..a6e6d3ddd10e 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS_acquisition_controllers.py @@ -99,7 +99,6 @@ def pre_acquire(self) -> None: # this could be used to start an Arbitrary Waveform Generator, etc... # using this method ensures that the contents are executed AFTER the # Alazar card starts listening for a trigger pulse - pass def handle_buffer( self, buffer: npt.NDArray, buffer_number: int | None = None diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2601B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2601B.py index 0965e1cf20e7..968229890b8c 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2601B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2601B.py @@ -5,5 +5,3 @@ class Keithley2601B(Keithley2600): """ QCoDeS driver for the Keithley 2601B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2602A.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2602A.py index 84fc78beba27..7653d3116658 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2602A.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2602A.py @@ -5,5 +5,3 @@ class Keithley2602A(Keithley2600): """ QCoDeS driver for the Keithley 2602A Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2602B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2602B.py index 129a56249e6e..c4d33ae6ad7a 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2602B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2602B.py @@ -5,5 +5,3 @@ class Keithley2602B(Keithley2600): """ QCoDeS driver for the Keithley 2602B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2604B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2604B.py index 36d9bffaa794..374d0c5d1f16 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2604B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2604B.py @@ -5,5 +5,3 @@ class Keithley2604B(Keithley2600): """ QCoDeS driver for the Keithley 2604B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2611B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2611B.py index 684be904dce9..9b3beb0355fb 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2611B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2611B.py @@ -5,5 +5,3 @@ class Keithley2611B(Keithley2600): """ QCoDeS driver for the Keithley 2611B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2612B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2612B.py index ed99ec4ceb61..f80897ab7301 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2612B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2612B.py @@ -5,5 +5,3 @@ class Keithley2612B(Keithley2600): """ QCoDeS driver for the Keithley 2612B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2614B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2614B.py index 765fe96a8fef..255326370e3d 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2614B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2614B.py @@ -5,5 +5,3 @@ class Keithley2614B(Keithley2600): """ QCoDeS driver for the Keithley 2614B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2634B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2634B.py index 70282a793da6..17bd9123b059 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2634B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2634B.py @@ -5,5 +5,3 @@ class Keithley2634B(Keithley2600): """ QCoDeS driver for the Keithley 2634B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2635B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2635B.py index 04255c861cb9..18a6bd87ed69 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2635B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2635B.py @@ -5,5 +5,3 @@ class Keithley2635B(Keithley2600): """ QCoDeS driver for the Keithley 2635B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2636B.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2636B.py index 8e60665fc543..ca60a8576cee 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2636B.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2636B.py @@ -5,5 +5,3 @@ class Keithley2636B(Keithley2600): """ QCoDeS driver for the Keithley 2636B Source-Meter """ - - pass diff --git a/src/qcodes/instrument_drivers/QDev/QDac_channels.py b/src/qcodes/instrument_drivers/QDev/QDac_channels.py index 67b95e44ae6e..98d59f251180 100644 --- a/src/qcodes/instrument_drivers/QDev/QDac_channels.py +++ b/src/qcodes/instrument_drivers/QDev/QDac_channels.py @@ -819,5 +819,3 @@ class QDac(QDevQDac): """ Backwards compatibility alias for QDevQDac driver """ - - pass diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py b/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py index f0cbbe9251d7..af5981f72c9e 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/RTO1000.py @@ -1123,5 +1123,3 @@ class RTO1000(RohdeSchwarzRTO1000): """ Backwards compatibility alias for RohdeSchwarzRTO1000 """ - - pass diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB20.py b/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB20.py index f4f95849bd95..1013bbcad3fe 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB20.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB20.py @@ -6,5 +6,3 @@ class RohdeSchwarzZNB20(RohdeSchwarzZNBBase): QCoDeS driver for Rohde & Schwarz ZNB20 """ - - pass diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB8.py b/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB8.py index 7eee00ba4fd2..c29aa0f8ff74 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB8.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/Rohde_Schwarz_ZNB8.py @@ -8,5 +8,3 @@ class RohdeSchwarzZNB8(RohdeSchwarzZNBBase): QCoDeS driver for Rohde & Schwarz ZNB8 """ - - pass diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/_rohde_schwarz_znle.py b/src/qcodes/instrument_drivers/rohde_schwarz/_rohde_schwarz_znle.py index 6846d86a6bcf..0fc41cd21230 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/_rohde_schwarz_znle.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/_rohde_schwarz_znle.py @@ -7,8 +7,6 @@ class RohdeSchwarzZNLE3(RohdeSchwarzZNBBase): """ - pass - class RohdeSchwarzZNLE4(RohdeSchwarzZNBBase): """ @@ -16,8 +14,6 @@ class RohdeSchwarzZNLE4(RohdeSchwarzZNBBase): """ - pass - class RohdeSchwarzZNLE6(RohdeSchwarzZNBBase): """ @@ -25,8 +21,6 @@ class RohdeSchwarzZNLE6(RohdeSchwarzZNBBase): """ - pass - class RohdeSchwarzZNLE14(RohdeSchwarzZNBBase): """ @@ -34,13 +28,9 @@ class RohdeSchwarzZNLE14(RohdeSchwarzZNBBase): """ - pass - class RohdeSchwarzZNLE18(RohdeSchwarzZNBBase): """ QCoDeS driver for Rohde & Schwarz ZNLE18 """ - - pass diff --git a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py index 72a116bfe915..7bb6a1b60915 100644 --- a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py +++ b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py @@ -48,8 +48,6 @@ class TektronixDPOModeError(Exception): perform an action """ - pass - class TektronixDPO7000xx(VisaInstrument): """ diff --git a/src/qcodes/instrument_drivers/tektronix/TPS2012.py b/src/qcodes/instrument_drivers/tektronix/TPS2012.py index 9de61876de19..aa5556cef29e 100644 --- a/src/qcodes/instrument_drivers/tektronix/TPS2012.py +++ b/src/qcodes/instrument_drivers/tektronix/TPS2012.py @@ -473,5 +473,3 @@ class TPS2012(TektronixTPS2012): """ Deprecated alias for ``TektronixTPS2012`` """ - - pass diff --git a/src/qcodes/parameters/delegate_parameter.py b/src/qcodes/parameters/delegate_parameter.py index df8b2f6f2628..d0d1a563214c 100644 --- a/src/qcodes/parameters/delegate_parameter.py +++ b/src/qcodes/parameters/delegate_parameter.py @@ -176,7 +176,6 @@ def _update_with( delegate parameter mirrors the cache of the source parameter by design, this method is just a noop. """ - pass def __call__(self) -> _local_ParameterDataTypeVar: return self.get(get_if_invalid=True) diff --git a/src/qcodes/station.py b/src/qcodes/station.py index b7ae92432d26..576fa049923d 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -97,8 +97,6 @@ def get_config_use_monitor() -> str | None: class ValidationWarning(Warning): """Replacement for jsonschema.error.ValidationError as warning.""" - pass - class StationConfig(dict[Any, Any]): def snapshot(self, update: bool = True) -> StationConfig: diff --git a/tests/drivers/test_stahl.py b/tests/drivers/test_stahl.py index 6d31d7cc8525..3f43143adcdd 100644 --- a/tests/drivers/test_stahl.py +++ b/tests/drivers/test_stahl.py @@ -94,4 +94,3 @@ def test_get_temperature(stahl_instrument) -> None: Line 191 of pyvisa-sim/component.py should read "return response.encode('latin-1')" for this to work. """ - pass diff --git a/tests/extensions/parameters/test_parameter_mixin.py b/tests/extensions/parameters/test_parameter_mixin.py index 8de743fe2d1c..adfcc22b2149 100644 --- a/tests/extensions/parameters/test_parameter_mixin.py +++ b/tests/extensions/parameters/test_parameter_mixin.py @@ -13,20 +13,14 @@ class CompatibleParameter(Parameter): """Docstring for CompatibleParameter""" - pass - class AnotherCompatibleParameter(Parameter): """Docstring for AnotherCompatibleParameter""" - pass - class IncompatibleParameter(Parameter): """Docstring for IncompatibleParameter""" - pass - class CompatibleParameterMixin(ParameterMixin): """Docstring for CompatibleParameterMixin""" diff --git a/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py b/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py index 0ee917904631..dd5bed990144 100644 --- a/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py +++ b/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py @@ -21,8 +21,6 @@ class OnCacheChangeParameter(OnCacheChangeParameterMixin, Parameter): A parameter invoking callbacks on cache changes. """ - pass - @pytest.fixture def store(): diff --git a/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py b/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py index 2977785e3375..23a487552150 100644 --- a/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py +++ b/tests/extensions/parameters/test_parameter_mixin_set_cache_value_on_reset.py @@ -27,8 +27,6 @@ class ResetTestParameter(SetCacheValueOnResetParameterMixin, Parameter): A parameter resetting its cache value on instrument reset. """ - pass - @pytest.fixture def store(): From 3a0d72fd5077c8ad8742ecebd7886fa18d1592e1 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 10:51:59 +0200 Subject: [PATCH 13/43] Enable FLY002 --- docs/examples/basic_examples/Configuring_QCoDeS.ipynb | 4 +--- pyproject.toml | 5 +++-- src/qcodes/instrument/visa.py | 2 +- .../Keysight/keysightb1500/KeysightB1500_module.py | 2 +- src/qcodes/logger/logger.py | 2 +- tests/drivers/test_lakeshore_335.py | 2 +- tests/drivers/test_lakeshore_336.py | 2 +- tests/drivers/test_lakeshore_372.py | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/docs/examples/basic_examples/Configuring_QCoDeS.ipynb b/docs/examples/basic_examples/Configuring_QCoDeS.ipynb index 7b2c87135024..0a02fb04a7c8 100644 --- a/docs/examples/basic_examples/Configuring_QCoDeS.ipynb +++ b/docs/examples/basic_examples/Configuring_QCoDeS.ipynb @@ -250,9 +250,7 @@ ], "source": [ "print(\n", - " \"\\n\".join(\n", - " [qc.config.home_file_name, qc.config.env_file_name, qc.config.cwd_file_name]\n", - " )\n", + " f\"{qc.config.home_file_name}\\n{qc.config.env_file_name}\\n{qc.config.cwd_file_name}\"\n", ")" ] }, diff --git a/pyproject.toml b/pyproject.toml index 14cd74352ff0..75d1ea2afcdf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,14 +251,15 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now # PLxxxx are pylint lints that generate a fair amount of warnings # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed -ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917"] +ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", + "DTZ007", "DTZ005", "N999"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument/visa.py b/src/qcodes/instrument/visa.py index 4d91ce6b7e24..61547e7dc994 100644 --- a/src/qcodes/instrument/visa.py +++ b/src/qcodes/instrument/visa.py @@ -26,7 +26,7 @@ from qcodes.parameters.parameter import Parameter -VISA_LOGGER = ".".join((InstrumentBase.__module__, "com", "visa")) +VISA_LOGGER = f"{InstrumentBase.__module__}.com.visa" log = logging.getLogger(__name__) diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py index 8c768e8ba74e..7e3c423ab55d 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py @@ -196,7 +196,7 @@ def fixed_negative_float(response: str) -> float: decimal = decimal.replace("-", "") - output = ".".join([number, decimal]) + output = f"{number}.{decimal}" return float(output) diff --git a/src/qcodes/logger/logger.py b/src/qcodes/logger/logger.py index 8291d4b9dd7e..60ea78228114 100644 --- a/src/qcodes/logger/logger.py +++ b/src/qcodes/logger/logger.py @@ -164,7 +164,7 @@ def generate_log_file_name() -> str: pid = str(os.getpid()) dt_str = datetime.now().strftime("%y%m%d") - python_log_name = "-".join([dt_str, pid, PYTHON_LOG_NAME]) + python_log_name = f"{dt_str}-{pid}-{PYTHON_LOG_NAME}" return python_log_name diff --git a/tests/drivers/test_lakeshore_335.py b/tests/drivers/test_lakeshore_335.py index d02949013a5a..8982cf4620a1 100644 --- a/tests/drivers/test_lakeshore_335.py +++ b/tests/drivers/test_lakeshore_335.py @@ -13,7 +13,7 @@ log = logging.getLogger(__name__) -VISA_LOGGER = ".".join((InstrumentBase.__module__, "com", "visa")) +VISA_LOGGER = f"{InstrumentBase.__module__}.com.visa" class LakeshoreModel335Mock(MockVisaInstrument, LakeshoreModel335): diff --git a/tests/drivers/test_lakeshore_336.py b/tests/drivers/test_lakeshore_336.py index 3806c14e894f..a53e6d79fad7 100644 --- a/tests/drivers/test_lakeshore_336.py +++ b/tests/drivers/test_lakeshore_336.py @@ -15,7 +15,7 @@ log = logging.getLogger(__name__) -VISA_LOGGER = ".".join((InstrumentBase.__module__, "com", "visa")) +VISA_LOGGER = f"{InstrumentBase.__module__}.com.visa" class LakeshoreModel336Mock(MockVisaInstrument, LakeshoreModel336): diff --git a/tests/drivers/test_lakeshore_372.py b/tests/drivers/test_lakeshore_372.py index 9d2b11a07161..b6085bc3b5f9 100644 --- a/tests/drivers/test_lakeshore_372.py +++ b/tests/drivers/test_lakeshore_372.py @@ -22,7 +22,7 @@ log = logging.getLogger(__name__) -VISA_LOGGER = ".".join((InstrumentBase.__module__, "com", "visa")) +VISA_LOGGER = f"{InstrumentBase.__module__}.com.visa" P = ParamSpec("P") T = TypeVar("T") From 2b7004f5880f745418b5e70765f9a611c345abcb Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 10:55:12 +0200 Subject: [PATCH 14/43] Enable C408 --- benchmarking/benchmarks/dataset.py | 8 ++++---- pyproject.toml | 2 +- src/qcodes/dataset/dond/do2d_retrace.py | 2 +- src/qcodes/dataset/dond/do_2d.py | 2 +- src/qcodes/dataset/dond/do_nd.py | 8 ++++---- src/qcodes/dataset/exporters/export_to_csv.py | 2 +- src/qcodes/dataset/guid_helpers.py | 4 ++-- src/qcodes/dataset/measurement_extensions.py | 2 +- .../instrument_drivers/Galil/dmc_41x3.py | 2 +- .../instrument_drivers/Keysight/KtM960x.py | 2 +- .../instrument_drivers/Keysight/KtMAwg.py | 2 +- .../keysightb1500/KeysightB1500_module.py | 14 +++++++------ .../private/Keysight_344xxA_submodules.py | 4 ++-- .../Lakeshore/Lakeshore_model_325.py | 2 +- src/qcodes/interactive_widget.py | 20 +++++++++---------- src/qcodes/station.py | 2 +- tests/dataset/test_guid_helpers.py | 10 +++++----- tests/delegate/test_delegate_instrument.py | 4 ++-- tests/parameter/test_snapshot.py | 9 ++++++--- 19 files changed, 53 insertions(+), 48 deletions(-) diff --git a/benchmarking/benchmarks/dataset.py b/benchmarking/benchmarks/dataset.py index 8175e19cba43..e005640986e2 100644 --- a/benchmarking/benchmarks/dataset.py +++ b/benchmarking/benchmarks/dataset.py @@ -50,8 +50,8 @@ class Adding5Params: timer = time.perf_counter def __init__(self): - self.parameters = list() - self.values = list() + self.parameters = [] + self.values = [] self.experiment = None self.runner = None self.datasaver = None @@ -116,8 +116,8 @@ def teardown(self, bench_param): shutil.rmtree(self.tmpdir) self.tmpdir = None - self.parameters = list() - self.values = list() + self.parameters = [] + self.values = [] def time_test(self, bench_param): """Adding data for 5 parameters""" diff --git a/pyproject.toml b/pyproject.toml index 75d1ea2afcdf..aa146249f40d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002", "C408" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/dataset/dond/do2d_retrace.py b/src/qcodes/dataset/dond/do2d_retrace.py index 833359d7135d..7961f2a08091 100644 --- a/src/qcodes/dataset/dond/do2d_retrace.py +++ b/src/qcodes/dataset/dond/do2d_retrace.py @@ -46,7 +46,7 @@ def do2d_retrace( after_inner_actions: ActionsT = (), measurement_name: str = "", exp: Experiment | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), show_progress: bool | None = None, ) -> tuple[DataSetProtocol, DataSetProtocol]: """ diff --git a/src/qcodes/dataset/dond/do_2d.py b/src/qcodes/dataset/dond/do_2d.py index 98dfaad001a2..55fe5fb566fc 100644 --- a/src/qcodes/dataset/dond/do_2d.py +++ b/src/qcodes/dataset/dond/do_2d.py @@ -68,7 +68,7 @@ def do2d( flush_columns: bool = False, do_plot: bool | None = None, use_threads: bool | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), show_progress: bool | None = None, log_info: str | None = None, break_condition: BreakConditionT | None = None, diff --git a/src/qcodes/dataset/dond/do_nd.py b/src/qcodes/dataset/dond/do_nd.py index 893f666c37b9..18ee6ad0b95b 100644 --- a/src/qcodes/dataset/dond/do_nd.py +++ b/src/qcodes/dataset/dond/do_nd.py @@ -593,7 +593,7 @@ def dond( do_plot: bool | None = None, show_progress: bool | None = None, use_threads: bool | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), log_info: str | None = None, break_condition: BreakConditionT | None = None, dataset_dependencies: Mapping[str, Sequence[ParamMeasT]] | None = None, @@ -613,7 +613,7 @@ def dond( do_plot: bool | None = None, show_progress: bool | None = None, use_threads: bool | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), log_info: str | None = None, break_condition: BreakConditionT | None = None, dataset_dependencies: Mapping[str, Sequence[ParamMeasT]] | None = None, @@ -633,7 +633,7 @@ def dond( do_plot: bool | None = None, show_progress: bool | None = None, use_threads: bool | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), log_info: str | None = None, break_condition: BreakConditionT | None = None, dataset_dependencies: Mapping[str, Sequence[ParamMeasT]] | None = None, @@ -653,7 +653,7 @@ def dond( do_plot: bool | None = None, show_progress: bool | None = None, use_threads: bool | None = None, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), log_info: str | None = None, break_condition: BreakConditionT | None = None, dataset_dependencies: Mapping[str, Sequence[ParamMeasT]] | None = None, diff --git a/src/qcodes/dataset/exporters/export_to_csv.py b/src/qcodes/dataset/exporters/export_to_csv.py index e10068c49c35..6d07976dcf50 100644 --- a/src/qcodes/dataset/exporters/export_to_csv.py +++ b/src/qcodes/dataset/exporters/export_to_csv.py @@ -26,7 +26,7 @@ def dataframe_to_csv( ) -> None: import pandas as pd - dfs_to_save = list() + dfs_to_save = [] for parametername, df in dfdict.items(): if not single_file: dst = os.path.join(path, f"{parametername}.dat") diff --git a/src/qcodes/dataset/guid_helpers.py b/src/qcodes/dataset/guid_helpers.py index 7fb2e98b3b22..98ecc9582d97 100644 --- a/src/qcodes/dataset/guid_helpers.py +++ b/src/qcodes/dataset/guid_helpers.py @@ -89,7 +89,7 @@ def guids_from_list_str(s: str) -> tuple[str, ...] | None: """ if s == "": - return tuple() + return () try: validate_guid_format(s) @@ -111,7 +111,7 @@ def guids_from_list_str(s: str) -> tuple[str, ...] | None: if isinstance(parsed.value, str) and len(parsed.value) > 0: return (parsed.value,) else: - return tuple() + return () if not isinstance(parsed, (ast.List, ast.Tuple, ast.Set)): return None diff --git a/src/qcodes/dataset/measurement_extensions.py b/src/qcodes/dataset/measurement_extensions.py index 145bad912161..fae7f8cb1b06 100644 --- a/src/qcodes/dataset/measurement_extensions.py +++ b/src/qcodes/dataset/measurement_extensions.py @@ -161,7 +161,7 @@ def parse_dond_into_args( def dond_into( datasaver: DataSaver, *params: AbstractSweep | ParamMeasT, - additional_setpoints: Sequence[ParameterBase] = tuple(), + additional_setpoints: Sequence[ParameterBase] = (), ) -> None: """ A doNd-like utility function that writes gridded data to the supplied DataSaver diff --git a/src/qcodes/instrument_drivers/Galil/dmc_41x3.py b/src/qcodes/instrument_drivers/Galil/dmc_41x3.py index 1ac93effe35d..d211032ad5b2 100644 --- a/src/qcodes/instrument_drivers/Galil/dmc_41x3.py +++ b/src/qcodes/instrument_drivers/Galil/dmc_41x3.py @@ -551,7 +551,7 @@ def _get_absolute_position(self) -> dict[str, int]: """ Gets absolution position of the motors from the defined origin """ - result = dict() + result = {} data = self.ask("PA ?,?,?").split(" ") result["A"] = int(data[0][:-1]) result["B"] = int(data[1][:-1]) diff --git a/src/qcodes/instrument_drivers/Keysight/KtM960x.py b/src/qcodes/instrument_drivers/Keysight/KtM960x.py index 896a0904e834..462cc5e1ead4 100644 --- a/src/qcodes/instrument_drivers/Keysight/KtM960x.py +++ b/src/qcodes/instrument_drivers/Keysight/KtM960x.py @@ -228,7 +228,7 @@ def _measure(self) -> tuple[ParamRawDataType, ...]: def get_errors(self) -> dict[int, str]: error_code = ctypes.c_int(-1) error_message = ctypes.create_string_buffer(256) - error_dict = dict() + error_dict = {} while error_code.value != 0: status = self._dll.KtM960x_error_query( self._session, ctypes.byref(error_code), error_message diff --git a/src/qcodes/instrument_drivers/Keysight/KtMAwg.py b/src/qcodes/instrument_drivers/Keysight/KtMAwg.py index 4d6f17e86748..ea1b7f81ddc9 100644 --- a/src/qcodes/instrument_drivers/Keysight/KtMAwg.py +++ b/src/qcodes/instrument_drivers/Keysight/KtMAwg.py @@ -338,7 +338,7 @@ def _catch_error(self, status: int) -> None: def get_errors(self) -> dict[int, str]: error_code = ctypes.c_int(-1) error_message = ctypes.create_string_buffer(256) - error_dict = dict() + error_dict = {} while error_code.value != 0: status = self._dll.KtMAwg_error_query( self._session, ctypes.byref(error_code), error_message diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py index 7e3c423ab55d..a5db649b86df 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_module.py @@ -201,12 +201,14 @@ def fixed_negative_float(response: str) -> float: _dcorr_labels_units_map = { - constants.DCORR.Mode.Cp_G: dict( - primary=dict(label="Cp", unit="F"), secondary=dict(label="G", unit="S") - ), - constants.DCORR.Mode.Ls_Rs: dict( - primary=dict(label="Ls", unit="H"), secondary=dict(label="Rs", unit="Ω") - ), + constants.DCORR.Mode.Cp_G: { + "primary": {"label": "Cp", "unit": "F"}, + "secondary": {"label": "G", "unit": "S"}, + }, + constants.DCORR.Mode.Ls_Rs: { + "primary": {"label": "Ls", "unit": "H"}, + "secondary": {"label": "Rs", "unit": "Ω"}, + }, } diff --git a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py index 8d399d4b3c56..a0a97c4de59c 100644 --- a/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py +++ b/src/qcodes/instrument_drivers/Keysight/private/Keysight_344xxA_submodules.py @@ -1141,7 +1141,7 @@ def _licenses(self) -> "Sequence[str]": licenses_raw = self.ask("SYST:LIC:CAT?") licenses_list = [x.strip('"') for x in licenses_raw.split(",")] return licenses_list - return tuple() + return () def _options(self) -> tuple[str, ...]: """ @@ -1157,7 +1157,7 @@ def _options(self) -> tuple[str, ...]: options_raw = self.ask("*OPT?") options_list = [opt for opt in options_raw.split(",") if opt != "0"] return tuple(options_list) - return tuple() + return () def _get_parameter(self, sense_function: str = "DC Voltage") -> float: """ diff --git a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py index b328a2e24988..b66ef86940b8 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py @@ -45,7 +45,7 @@ def strip(strings: "Iterable[str]") -> tuple[str, ...]: # Meta data lines contain a colon metadata_lines = takewhile(lambda s: ":" in s, lines) # Data from the file is collected in the following dict - file_data: dict[str, dict[str, Any]] = dict() + file_data: dict[str, dict[str, Any]] = {} # Capture meta data parsed_lines = [strip(line.split(":")) for line in metadata_lines] file_data["metadata"] = {key: value for key, value in parsed_lines} diff --git a/src/qcodes/interactive_widget.py b/src/qcodes/interactive_widget.py index 523dfa18015b..b1d085be482c 100644 --- a/src/qcodes/interactive_widget.py +++ b/src/qcodes/interactive_widget.py @@ -80,7 +80,7 @@ def on_click(_: Button) -> None: "Back", "warning", on_click=_back_button(title, body, box), - button_kwargs=dict(icon="undo"), + button_kwargs={"icon": "undo"}, ) box.children = (text_input, back_button) @@ -250,7 +250,7 @@ def _on_click(_: Button) -> None: f"Close {which}", "danger", on_click=delete_tab(out, tab), - button_kwargs=dict(icon="eraser"), + button_kwargs={"icon": "eraser"}, ) display(close_button) @@ -300,15 +300,15 @@ def on_click(_: Button) -> None: "", "success", on_click=_save_button(box, ds), - button_kwargs=dict(icon="save"), - layout_kwargs=dict(width="50%"), + button_kwargs={"icon": "save"}, + layout_kwargs={"width": "50%"}, ) cancel_button = button( "", "danger", on_click=_save_button(box, ds, do_save=False), - button_kwargs=dict(icon="close"), - layout_kwargs=dict(width="50%"), + button_kwargs={"icon": "close"}, + layout_kwargs={"width": "50%"}, ) subbox = HBox( [save_button, cancel_button], @@ -333,7 +333,7 @@ def _changeable_button(text: str, box: Box) -> Button: text, "success", on_click=_button_to_input(text, box), - button_kwargs=dict(icon="edit") if text == "" else {}, + button_kwargs={"icon": "edit"} if text == "" else {}, ) text = ds.metadata.get(_META_DATA_KEY, "") @@ -429,7 +429,7 @@ def _get_snapshot_button(ds: DataSetProtocol, tab: Tab) -> Button: "warning", tooltip="Click to open this DataSet's snapshot in a tab above.", on_click=_do_in_tab(tab, ds, "snapshot"), - button_kwargs=dict(icon="camera"), + button_kwargs={"icon": "camera"}, ) @@ -439,7 +439,7 @@ def _get_plot_button(ds: DataSetProtocol, tab: Tab) -> Button: "warning", tooltip="Click to open this DataSet's plot in a tab above.", on_click=_do_in_tab(tab, ds, "plot"), - button_kwargs=dict(icon="line-chart"), + button_kwargs={"icon": "line-chart"}, ) @@ -454,7 +454,7 @@ def _get_export_button( "csv", path=Path.cwd() / "export", ), - button_kwargs=dict(icon="file-export"), + button_kwargs={"icon": "file-export"}, ) diff --git a/src/qcodes/station.py b/src/qcodes/station.py index 576fa049923d..1fdad358e078 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -436,7 +436,7 @@ def load_config_files(self, *filenames: str) -> None: if len(filenames) == 0: self.load_config_file() else: - paths = list() + paths = [] for filename in filenames: assert isinstance(filename, str) path = self._get_config_file_path(filename) diff --git a/tests/dataset/test_guid_helpers.py b/tests/dataset/test_guid_helpers.py index 9ddfbcf57b11..038631fc281e 100644 --- a/tests/dataset/test_guid_helpers.py +++ b/tests/dataset/test_guid_helpers.py @@ -63,11 +63,11 @@ def test_guids_from_list_str() -> None: "07fd7195-c51e-44d6-a085-fa8274cf00d6", "070d7195-c51e-44d6-a085-fa8274cf00d6", ] - assert guids_from_list_str("") == tuple() - assert guids_from_list_str("''") == tuple() - assert guids_from_list_str('""') == tuple() - assert guids_from_list_str(str(tuple())) == tuple() - assert guids_from_list_str(str(list())) == tuple() + assert guids_from_list_str("") == () + assert guids_from_list_str("''") == () + assert guids_from_list_str('""') == () + assert guids_from_list_str(str(())) == () + assert guids_from_list_str(str([])) == () assert guids_from_list_str(str({})) is None assert guids_from_list_str(str(guids)) == tuple(guids) assert guids_from_list_str(str([guids[0]])) == (guids[0],) diff --git a/tests/delegate/test_delegate_instrument.py b/tests/delegate/test_delegate_instrument.py index aa6954a85512..7fab7fa389c3 100644 --- a/tests/delegate/test_delegate_instrument.py +++ b/tests/delegate/test_delegate_instrument.py @@ -28,7 +28,7 @@ def test_mock_field_delegate(station, field_x, chip_config) -> None: assert_almost_equal(ramp.field, 0.001) assert ramp.ramp_rate == 0.02 - field.ramp_X(dict(field=0.0, ramp_rate=10.0)) + field.ramp_X({"field": 0.0, "ramp_rate": 10.0}) assert field.ramp_rate() == 10.0 assert_almost_equal(field.X(), 0.0) assert field.ramp_X_ramp_rate() == 10.0 @@ -45,7 +45,7 @@ def test_delegate_channel_instrument(station, chip_config) -> None: assert state.bus == "off" assert state.gnd == "off" - switch.state01(dict(dac_output="on", smc="off", bus="off", gnd="off")) + switch.state01({"dac_output": "on", "smc": "off", "bus": "off", "gnd": "off"}) state = switch.state01() assert state.dac_output == "on" assert state.smc == "off" diff --git a/tests/parameter/test_snapshot.py b/tests/parameter/test_snapshot.py index 8f48d9ea8f77..bd2dc32c3261 100644 --- a/tests/parameter/test_snapshot.py +++ b/tests/parameter/test_snapshot.py @@ -23,9 +23,12 @@ def create_parameter( get_cmd: Callable[..., Any] | bool | Literal["NOT_PASSED"] | None, offset: float | Literal["NOT_PASSED"] = NOT_PASSED, ) -> Parameter: - kwargs: dict[str, Any] = dict( - set_cmd=None, label="Parameter", unit="a.u.", docstring="some docs" - ) + kwargs: dict[str, Any] = { + "set_cmd": None, + "label": "Parameter", + "unit": "a.u.", + "docstring": "some docs", + } if offset != NOT_PASSED: kwargs.update(offset=offset) From 616eda3c07a7b97441a3d64ae6b6414deafc4c3d Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 10:57:53 +0200 Subject: [PATCH 15/43] Enable C400 --- pyproject.toml | 2 +- .../QuantumDesign/DynaCoolPPMS/DynaCool.py | 4 ++-- .../QuantumDesign/DynaCoolPPMS/private/commandhandler.py | 4 ++-- .../measurement/test_measurement_context_manager.py | 8 ++++---- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index aa146249f40d..9f283f057cd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -251,7 +251,7 @@ select = [ "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002", "C408" # rules that became default in 0.16.0. Enable until we can switch to extend select + "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002", "C408", "C400" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index ad0f97e4f641..d577b0a9b7f6 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -386,7 +386,7 @@ def _field_setter( The combined set function for the three field parameters, field_setpoint, field_rate, and field_approach """ - temporary_values = list(self.parameters[p].raw_value for p in self.field_params) + temporary_values = [self.parameters[p].raw_value for p in self.field_params] values = cast("list[int | float]", temporary_values) values[self.field_params.index(param)] = value @@ -420,7 +420,7 @@ def _temp_setter( The setter function for the temperature parameters. All three are set with the same call to the instrument API """ - temp_values = list(self.parameters[par].raw_value for par in self.temp_params) + temp_values = [self.parameters[par].raw_value for par in self.temp_params] values = cast("list[int | float]", temp_values) values[self.temp_params.index(param)] = value diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py index 0aeae6e5f493..d99b71d0764e 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py @@ -135,7 +135,7 @@ def err_func() -> int: is_query = True else: cmd = self._sets[cmd_head] - args = list(float(arg) for arg in cmd_str[5:].split(", ")) + args = [float(arg) for arg in cmd_str[5:].split(", ")] is_query = False return CmdArgs(cmd=cmd, args=args), is_query @@ -169,7 +169,7 @@ def __call__(self, cmd: str) -> str: if is_query: # read out the mutated values # (win32 reverses the order) - vals = list(arg.value for arg in cmd_and_args.args) + vals = [arg.value for arg in cmd_and_args.args] vals.reverse() # reset the value variables for good measures for arg in cmd_and_args.args: diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 948b30464638..1740f9534ce4 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -2182,13 +2182,13 @@ def test_datasaver_arrays_of_different_length(storage_type, Ns, bg_writing) -> N with meas.run(write_in_background=bg_writing) as datasaver: result_t = ("temperature", 70) - result_freqs = list( + result_freqs = [ (f"freqs{n}", np.linspace(0, 1, Ns[n])) for n in range(no_of_signals) - ) - result_sigs = list( + ] + result_sigs = [ (f"signal{n}", np.random.default_rng().standard_normal(Ns[n])) for n in range(no_of_signals) - ) + ] full_result: tuple[tuple[str, int | np.ndarray | str], ...] = tuple( result_freqs + result_sigs + [result_t] ) From d01a8c0ab729ad50562a6a16eebd46523f1d15f3 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 12:01:26 +0200 Subject: [PATCH 16/43] Disable a few more rules for now --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 9f283f057cd8..0ee34050f00c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -259,7 +259,7 @@ select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "N999"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter From a51e5d38afe068625f5a3d95bc1ff3ba66319a3d Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 12:49:58 +0200 Subject: [PATCH 17/43] Switch to extend-select and ignore remaining errors --- pyproject.toml | 5 ++--- tests/dataset/test_plotting.py | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0ee34050f00c..acb9e05283b4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -244,14 +244,13 @@ explicit-preview-rules = true # TID253 banned-module-level-imports # W pydocstyle # PLx pylint -select = [ +extend-select = [ "E", "F", "PT025", "UP", "RUF", "YTT", "INP", "I", "G", "ISC", "TID253", "NPY", "PLE", "PLR", "PLC", "PLW", "W", "D214", "D300", "D402", "D403", "D405", "D410", "D411", "D412", "D413", "D414", "D416", "D417", "D418", "D419", "TC", "PYI", "RUF027", # these are preview rules that are not yet stable but explicitly enabled. - "B009", "SIM117", "SIM905", "SIM102", "B018", "SIM118", "PT031", "PT014", "C405", "C414", "C419", "SIM201", "PIE790", "FLY002", "C408", "C400" # rules that became default in 0.16.0. Enable until we can switch to extend select ] # G004 We have a lot of use of f strings in log messages # so disable that lint for now @@ -259,7 +258,7 @@ select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210", "B016", "FURB105"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/tests/dataset/test_plotting.py b/tests/dataset/test_plotting.py index 98825aad3857..c3638109fd89 100644 --- a/tests/dataset/test_plotting.py +++ b/tests/dataset/test_plotting.py @@ -419,7 +419,7 @@ def test_plot_dataset_parameters(experiment, request: FixtureRequest, params) -> assert_allclose(np.array(plotted), data, rtol=1e-10) # check only 'requested' parameter has been plotted - elif params == "y" or "y2": + elif params in {"y", "y2"}: assert isinstance(params, str) assert len(axes) == 1 dsdata = dataset.get_parameter_data() From f126afc5c3511fa4de547b297655cbd4cd687890 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 12:58:12 +0200 Subject: [PATCH 18/43] Fix FURB105 --- docs/examples/DataSet/Accessing-data-in-DataSet.ipynb | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb b/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb index c9b1e9005ebd..e3909e71bdc0 100644 --- a/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb +++ b/docs/examples/DataSet/Accessing-data-in-DataSet.ipynb @@ -972,7 +972,7 @@ " print(f\"DataFrame for parameter {parameter_name}\")\n", " print(\"-----------------------------\")\n", " print(f\"{df.head()!r}\")\n", - " print(\"\")" + " print()" ] }, { diff --git a/pyproject.toml b/pyproject.toml index acb9e05283b4..1c52ee89ad39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210", "B016", "FURB105"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210", "B016"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter From ce6116122c0122d87f302f5fd8f8974d6e7c47e6 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:00:01 +0200 Subject: [PATCH 19/43] Implement B016 --- .../QCodes example with Keithley S46.ipynb | 12 ++++++------ pyproject.toml | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/examples/driver_examples/QCodes example with Keithley S46.ipynb b/docs/examples/driver_examples/QCodes example with Keithley S46.ipynb index 66b7f4eeae58..dc3f6dc2dd9e 100644 --- a/docs/examples/driver_examples/QCodes example with Keithley S46.ipynb +++ b/docs/examples/driver_examples/QCodes example with Keithley S46.ipynb @@ -177,7 +177,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -191,7 +191,7 @@ "source": [ "try:\n", " s46.A2(\"close\")\n", - " raise (\"We should not be here\")\n", + " raise RuntimeError(\"We should not be here\")\n", "except KeithleyS46LockAcquisitionError as e:\n", " print(e)" ] @@ -216,7 +216,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -230,7 +230,7 @@ "source": [ "try:\n", " s46.A1(\"close\")\n", - " raise (\"We should not be here\")\n", + " raise RuntimeError(\"We should not be here\")\n", "except KeithleyS46LockAcquisitionError as e:\n", " print(e)" ] @@ -246,7 +246,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -260,7 +260,7 @@ "source": [ "try:\n", " s46.B2(\"close\")\n", - " raise (\"We should not be here\")\n", + " raise RuntimeError(\"We should not be here\")\n", "except KeithleyS46LockAcquisitionError as e:\n", " print(e)" ] diff --git a/pyproject.toml b/pyproject.toml index 1c52ee89ad39..9d980c811b22 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210", "B016"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter From 3a260746447e58a4aee9480b5f10f45037551020 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:01:19 +0200 Subject: [PATCH 20/43] Implement SIM210 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/Keithley/Keithley_2000.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9d980c811b22..e6a25b2800ab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113", "SIM210"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py index 6e8213b25a6e..3ce69db89fad 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2000.py @@ -35,7 +35,7 @@ def _parse_output_string(s: str) -> str: def _parse_output_bool(value: str) -> bool: - return True if int(value) == 1 else False + return int(value) == 1 class Keithley2000(VisaInstrument): From f4ff43e54ba4345892ee1c2a4541ccfe8db3d992 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:03:56 +0200 Subject: [PATCH 21/43] Implement SIM113 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/tektronix/AWG5014.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e6a25b2800ab..7a1978138650 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166", "SIM113"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/tektronix/AWG5014.py b/src/qcodes/instrument_drivers/tektronix/AWG5014.py index e3825a79c682..3476ca926220 100644 --- a/src/qcodes/instrument_drivers/tektronix/AWG5014.py +++ b/src/qcodes/instrument_drivers/tektronix/AWG5014.py @@ -1354,12 +1354,10 @@ def _generate_awg_file( log.warning(f"AWG: {k} not recognized as valid AWG channel setting") # waveforms - ii = 21 - wf_record_str = BytesIO() wlist = list(packed_waveforms.keys()) wlist.sort() - for wf in wlist: + for ii, wf in enumerate(wlist, start=21): wfdat = packed_waveforms[wf] lenwfdat = len(wfdat) @@ -1372,13 +1370,12 @@ def _generate_awg_file( + self._pack_record(f"WAVEFORM_TIMESTAMP_{ii}", timetuple[:-1], "8H") + self._pack_record(f"WAVEFORM_DATA_{ii}", wfdat, f"{lenwfdat}H") ) - ii += 1 # sequence kk = 1 seq_record_str = BytesIO() - for segment in wfname_l.transpose(): + for kk, segment in enumerate(wfname_l.transpose(), start=1): seq_record_str.write( self._pack_record(f"SEQUENCE_WAIT_{kk}", trig_wait[kk - 1], "h") + self._pack_record(f"SEQUENCE_LOOP_{kk}", int(nrep[kk - 1]), "l") @@ -1397,7 +1394,6 @@ def _generate_awg_file( "{}s".format(len(wfname + "\x00")), ) ) - kk += 1 awg_file = ( head_str.getvalue() From 5bd93ac15084308d9e0801f4532931e6504f18c7 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:13:43 +0200 Subject: [PATCH 22/43] Implement FURB166 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/tektronix/AWGFileParser.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7a1978138650..19f8c4c5f973 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033", "FURB166"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/tektronix/AWGFileParser.py b/src/qcodes/instrument_drivers/tektronix/AWGFileParser.py index 567a7a29d6b8..9c7ed36b4c0e 100644 --- a/src/qcodes/instrument_drivers/tektronix/AWGFileParser.py +++ b/src/qcodes/instrument_drivers/tektronix/AWGFileParser.py @@ -335,7 +335,7 @@ def _unpacker( bitstring = bin(bitnum)[2:].zfill(16) m2[ii] = int(bitstring[0]) m1[ii] = int(bitstring[1]) - wf[ii] = (int(bitstring[2:], base=2) - 2**13) / 2**13 + wf[ii] = (int(bitstring[2:], base=2) - 2**13) / 2**13 # noqa: FURB166 The prefix is not the int base but markers so passing directly to int() is not correct # print(bitstring, int(bitstring[2:], base=2)) return wf, m1, m2 From 24320c3a8593b49caf27dd72ebf8371c9f92ceb2 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:16:01 +0200 Subject: [PATCH 23/43] Implement B033 --- pyproject.toml | 2 +- src/qcodes/plotting/axis_labels.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 19f8c4c5f973..1d567a836f68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804", "B033"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/plotting/axis_labels.py b/src/qcodes/plotting/axis_labels.py index 21f04ba9f585..6a1003edcacf 100644 --- a/src/qcodes/plotting/axis_labels.py +++ b/src/qcodes/plotting/axis_labels.py @@ -27,7 +27,6 @@ "ohm", "Ohm", "Ω", - "\N{GREEK CAPITAL LETTER OMEGA}", "S", "Wb", "T", From fe3fb5e4c8ab847a8529f7b001603637719780f6 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:17:15 +0200 Subject: [PATCH 24/43] Implement PIE804 --- pyproject.toml | 2 +- tests/dataset/test_plotting.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1d567a836f68..acb05bd58ab4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009", "PIE804"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/tests/dataset/test_plotting.py b/tests/dataset/test_plotting.py index c3638109fd89..5ceb47476a71 100644 --- a/tests/dataset/test_plotting.py +++ b/tests/dataset/test_plotting.py @@ -258,7 +258,9 @@ def test_appropriate_kwargs() -> None: assert kwargs == check - with _appropriate_kwargs("2D_point", False, **{}) as ap_kwargs: + my_args = {} + + with _appropriate_kwargs("2D_point", False, **my_args) as ap_kwargs: assert len(ap_kwargs) == 1 assert ap_kwargs["cmap"] == qc.config.plotting.default_color_map From bb1bc9ea3a304945f5ac04f98306f217c03b53d1 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:17:46 +0200 Subject: [PATCH 25/43] Implement LOG009 --- docs/examples/logging/logging_example.ipynb | 4 ++-- pyproject.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/logging/logging_example.ipynb b/docs/examples/logging/logging_example.ipynb index a639546cb3b7..819d5fb5a51e 100644 --- a/docs/examples/logging/logging_example.ipynb +++ b/docs/examples/logging/logging_example.ipynb @@ -358,7 +358,7 @@ "metadata": {}, "outputs": [], "source": [ - "with logger.console_level(logging.WARN):\n", + "with logger.console_level(logging.WARNING):\n", " driver.cartesian((0, 0, 0))\n", " with capture_dataframe(level=\"DEBUG\") as (handler, get_dataframe):\n", " driver.cartesian((0, 0, 1))\n", @@ -1317,7 +1317,7 @@ } ], "source": [ - "with logger.console_level(logging.WARN):\n", + "with logger.console_level(logging.WARNING):\n", " driver.cartesian((0, 0, 0))\n", " with (\n", " capture_dataframe(level=\"DEBUG\") as (handler, get_dataframe),\n", diff --git a/pyproject.toml b/pyproject.toml index acb05bd58ab4..ed59950ebb70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103", "LOG009"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter From 13a3fceaa67817666aa52980f2d93fd33abd6eb2 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:22:07 +0200 Subject: [PATCH 26/43] Implement SIM103 --- .../DataSet/Offline Plotting Tutorial.ipynb | 10 ++-------- pyproject.toml | 2 +- src/qcodes/dataset/descriptions/rundescriber.py | 4 +--- src/qcodes/dataset/descriptions/versioning/v0.py | 4 +--- src/qcodes/instrument/instrument.py | 15 +++++++-------- .../instrument_drivers/Keithley/Keithley_3706A.py | 4 +--- src/qcodes/parameters/cache.py | 9 ++------- 7 files changed, 15 insertions(+), 33 deletions(-) diff --git a/docs/examples/DataSet/Offline Plotting Tutorial.ipynb b/docs/examples/DataSet/Offline Plotting Tutorial.ipynb index dcb8a2237a28..dfddf0e41b06 100644 --- a/docs/examples/DataSet/Offline Plotting Tutorial.ipynb +++ b/docs/examples/DataSet/Offline Plotting Tutorial.ipynb @@ -669,17 +669,11 @@ "\n", "\n", "def no_x(xv):\n", - " if xv > 0 and xv < 3:\n", - " return True\n", - " else:\n", - " return False\n", + " return bool(xv > 0 and xv < 3)\n", "\n", "\n", "def no_t(tv):\n", - " if tv > 0 and tv < 450:\n", - " return True\n", - " else:\n", - " return False\n", + " return bool(tv > 0 and tv < 450)\n", "\n", "\n", "with meas.run() as datasaver:\n", diff --git a/pyproject.toml b/pyproject.toml index ed59950ebb70..e862d5ee7a59 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409", "SIM103"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/dataset/descriptions/rundescriber.py b/src/qcodes/dataset/descriptions/rundescriber.py index 33c1f2c5de36..697a47ea4419 100644 --- a/src/qcodes/dataset/descriptions/rundescriber.py +++ b/src/qcodes/dataset/descriptions/rundescriber.py @@ -108,9 +108,7 @@ def __eq__(self, other: object) -> bool: return False if self.interdeps != other.interdeps: return False - if self.shapes != other.shapes: - return False - return True + return self.shapes == other.shapes def __repr__(self) -> str: return f"RunDescriber({self.interdeps}, Shapes: {self._shapes})" diff --git a/src/qcodes/dataset/descriptions/versioning/v0.py b/src/qcodes/dataset/descriptions/versioning/v0.py index 4c73bda41af4..84cb1b5453f5 100644 --- a/src/qcodes/dataset/descriptions/versioning/v0.py +++ b/src/qcodes/dataset/descriptions/versioning/v0.py @@ -36,9 +36,7 @@ def __eq__(self, other: object) -> bool: return False ours = sorted(self.paramspecs, key=lambda ps: ps.name) theirs = sorted(other.paramspecs, key=lambda ps: ps.name) - if not ours == theirs: - return False - return True + return ours == theirs def _to_dict(self) -> InterDependenciesDict: """ diff --git a/src/qcodes/instrument/instrument.py b/src/qcodes/instrument/instrument.py index 2352e271c165..3a522581097e 100644 --- a/src/qcodes/instrument/instrument.py +++ b/src/qcodes/instrument/instrument.py @@ -379,16 +379,15 @@ def is_valid(instr_instance: Instrument) -> bool: instr_instance: Instance of an Instrument class or its subclass. """ - if ( + is_valid = ( isinstance(instr_instance, Instrument) and instr_instance in instr_instance.instances() - ): - # note that it is important to call `instances` on the instance - # object instead of `Instrument` class, because instances of - # Instrument subclasses are recorded inside their subclasses; see - # `instances` for more information - return True - return False + ) + # note that it is important to call `instances` on the instance + # object instead of `Instrument` class, because instances of + # Instrument subclasses are recorded inside their subclasses; see + # `instances` for more information + return is_valid # `write_raw` and `ask_raw` are the interface to hardware # # `write` and `ask` are standard wrappers to help with error reporting # diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py index 96c68ee3183d..897131f4c02b 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py @@ -222,9 +222,7 @@ def _warn_on_disengaged_interlocks(self, val: str) -> None: def _is_backplane_channel(self, channel_id: str) -> bool: if len(channel_id) != 4: raise Keithley3706AInvalidValue(f"{channel_id} is not a valid channel id") - if channel_id[1] == "9": - return True - return False + return channel_id[1] == "9" def exclusive_close(self, val: str) -> None: """ diff --git a/src/qcodes/parameters/cache.py b/src/qcodes/parameters/cache.py index c0fddffe3ba0..6a43badb127f 100644 --- a/src/qcodes/parameters/cache.py +++ b/src/qcodes/parameters/cache.py @@ -202,13 +202,8 @@ def _timestamp_expired(self) -> bool: oldest_accepted_timestamp = datetime.now() - timedelta( seconds=self._max_val_age ) - if self._timestamp < oldest_accepted_timestamp: - # Time of last get exceeds max_val_age seconds, need to - # perform new .get() - return True - else: - # parameter is still valid - return False + too_old = self._timestamp < oldest_accepted_timestamp + return too_old @overload def get(self, get_if_invalid: Literal[True]) -> ParameterDataTypeVar: ... From 696e9eb5a1db571651c20615b2ebad6b7c22a0f6 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 13:23:17 +0200 Subject: [PATCH 27/43] Implement C409 --- pyproject.toml | 2 +- .../Keysight/keysightb1500/KeysightB1500_base.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e862d5ee7a59..ad250950c7d6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010", "C409"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py index 55a38a3421f8..ed829ddbe4ae 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py @@ -516,9 +516,9 @@ class IVSweepMeasurement( def __init__(self, name: str, instrument: KeysightB1500, **kwargs: Any): super().__init__( name, - names=tuple(["param1", "param2"]), - units=tuple(["A", "A"]), - labels=tuple(["Param1 Current", "Param2 Current"]), + names=("param1", "param2"), + units=("A", "A"), + labels=("Param1 Current", "Param2 Current"), shapes=((1,),) * 2, setpoint_names=(("Voltage",),) * 2, setpoint_labels=(("Voltage",),) * 2, From 94de5198bca4ac88e67bb5c639c9baa52f010a9f Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 14:55:34 +0200 Subject: [PATCH 28/43] Implement B010 --- pyproject.toml | 2 +- src/qcodes/parameters/combined_parameter.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ad250950c7d6..1044145d9477 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102", "B010"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/parameters/combined_parameter.py b/src/qcodes/parameters/combined_parameter.py index 44f70b13912e..f6777d487447 100644 --- a/src/qcodes/parameters/combined_parameter.py +++ b/src/qcodes/parameters/combined_parameter.py @@ -110,7 +110,7 @@ def __init__( if aggregator: self.f = aggregator - setattr(self, "aggregate", self._aggregate) + self.aggregate = self._aggregate def set(self, index: int) -> list[Any]: """ From db3b56136f53d43afd6195e4247a3214bdb5dbb7 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 16:09:40 +0200 Subject: [PATCH 29/43] Implement PERF102 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/AlazarTech/ATS.py | 2 +- src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py | 2 +- src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py | 4 ++-- tests/dataset/test_dataset_export.py | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1044145d9477..1a72fbbd9e10 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008", "PERF102"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS.py b/src/qcodes/instrument_drivers/AlazarTech/ATS.py index 9c63688b54f5..dd37c8244686 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -566,7 +566,7 @@ def acquire[OutputType]( # noqa: D417 (missing args documentation) time_done_free_mem = time.perf_counter() # check if all parameters are up to date # Getting IDN is very slow so skip that - for _, p in self.parameters.items(): + for p in self.parameters.values(): if isinstance(p, TraceParameter) and p.synced_to_card is False: raise RuntimeError( f"TraceParameter {p} not synced to " diff --git a/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py b/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py index ec01042e8101..906312286088 100644 --- a/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py +++ b/src/qcodes/instrument_drivers/CopperMountain/_M5xxx.py @@ -595,7 +595,7 @@ def update_lin_traces(self) -> None: start = self.start() stop = self.stop() number_of_points = self.number_of_points() - for _, parameter in self.parameters.items(): + for parameter in self.parameters.values(): if isinstance(parameter, (FrequencySweepMagPhase)): try: parameter.set_sweep(start, stop, number_of_points) diff --git a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py index 04965fe511aa..d9c1033f49d3 100644 --- a/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py +++ b/src/qcodes/instrument_drivers/rohde_schwarz/ZNB.py @@ -882,7 +882,7 @@ def update_lin_traces(self) -> None: start = self.start() stop = self.stop() npts = self.npts() - for _, parameter in self.parameters.items(): + for parameter in self.parameters.values(): if isinstance( parameter, (FrequencySweep, FrequencySweepMagPhase, FrequencySweepDBPhase), @@ -898,7 +898,7 @@ def update_cw_traces(self) -> None: """ bandwidth = self.bandwidth() npts = self.npts() - for _, parameter in self.parameters.items(): + for parameter in self.parameters.values(): if isinstance(parameter, FixedFrequencyTraceIQ): try: parameter.set_cw_sweep(npts, bandwidth) diff --git a/tests/dataset/test_dataset_export.py b/tests/dataset/test_dataset_export.py index dd656597181e..bf1036e348f3 100644 --- a/tests/dataset/test_dataset_export.py +++ b/tests/dataset/test_dataset_export.py @@ -844,7 +844,7 @@ def test_partally_overlapping_setpoint_xarray_export_two_params_partial( expected_size = (5, 4) # Each variable should be 2D and have matching coords - for _, da in xrds.data_vars.items(): + for da in xrds.data_vars.values(): assert len(da.dims) == 2 for dim, size in zip(da.dims, expected_size): assert dim in xrds.coords From e18b761a4601385ac97539eadf3d272a826dc072 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 16:20:41 +0200 Subject: [PATCH 30/43] Implement SIM114 --- pyproject.toml | 2 +- src/qcodes/dataset/data_set_cache.py | 5 +---- src/qcodes/dataset/descriptions/detect_shapes.py | 9 ++++----- src/qcodes/dataset/dond/do_nd.py | 4 +--- src/qcodes/dataset/measurement_extensions.py | 4 +--- src/qcodes/dataset/measurements.py | 6 +++--- .../instrument_drivers/american_magnetics/AMI430_visa.py | 4 +--- .../measurement/test_measurement_context_manager.py | 5 +---- 8 files changed, 13 insertions(+), 26 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1a72fbbd9e10..47484be968b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "SIM114", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/dataset/data_set_cache.py b/src/qcodes/dataset/data_set_cache.py index 686dcc9da6ae..cab0db67ba58 100644 --- a/src/qcodes/dataset/data_set_cache.py +++ b/src/qcodes/dataset/data_set_cache.py @@ -376,10 +376,7 @@ def _merge_data_single_param( ) elif new_values is not None or shape is not None: (merged_data, new_write_status) = _create_new_data_dict(new_values, shape) - elif existing_values is not None: - merged_data = existing_values - new_write_status = single_tree_write_status - elif shape is None and new_values is None: + elif existing_values is not None or (shape is None and new_values is None): merged_data = existing_values new_write_status = single_tree_write_status else: diff --git a/src/qcodes/dataset/descriptions/detect_shapes.py b/src/qcodes/dataset/descriptions/detect_shapes.py index 76a6cdf22017..8897fc8868e5 100644 --- a/src/qcodes/dataset/descriptions/detect_shapes.py +++ b/src/qcodes/dataset/descriptions/detect_shapes.py @@ -90,11 +90,10 @@ def _get_shape_of_step(step: int | np.integer[Any] | Sized | npt.NDArray) -> int def _param_is_array_like(meas_param: ParameterBase) -> bool: - if isinstance(meas_param, (ArrayParameter, ParameterWithSetpoints)): - return True - elif isinstance(meas_param.vals, Arrays): - return True - return False + is_array_like = isinstance( + meas_param, (ArrayParameter, ParameterWithSetpoints) + ) or isinstance(meas_param.vals, Arrays) + return is_array_like def _get_shape_of_arrayparam(param: ParameterBase) -> tuple[int, ...]: diff --git a/src/qcodes/dataset/dond/do_nd.py b/src/qcodes/dataset/dond/do_nd.py index 18ee6ad0b95b..62930a81ff0c 100644 --- a/src/qcodes/dataset/dond/do_nd.py +++ b/src/qcodes/dataset/dond/do_nd.py @@ -882,9 +882,7 @@ def _parse_dond_arguments( sweep_instances: list[AbstractSweep | TogetherSweep] = [] params_meas: list[ParamMeasT | Sequence[ParamMeasT]] = [] for par in params: - if isinstance(par, AbstractSweep): - sweep_instances.append(par) - elif isinstance(par, TogetherSweep): + if isinstance(par, (AbstractSweep, TogetherSweep)): sweep_instances.append(par) else: params_meas.append(par) diff --git a/src/qcodes/dataset/measurement_extensions.py b/src/qcodes/dataset/measurement_extensions.py index fae7f8cb1b06..24c40b0ecd99 100644 --- a/src/qcodes/dataset/measurement_extensions.py +++ b/src/qcodes/dataset/measurement_extensions.py @@ -151,9 +151,7 @@ def parse_dond_into_args( raise ValueError("dond_into does not support TogetherSweeps") elif isinstance(par, Sequence): raise ValueError("dond_into does not support multiple datasets") - elif isinstance(par, ParameterBase) and par.gettable: - params_meas.append(par) - elif callable(par): + elif (isinstance(par, ParameterBase) and par.gettable) or callable(par): params_meas.append(par) return sweep_instances, params_meas diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 3437bbb8a7c6..ad5565b14ac4 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -1122,9 +1122,9 @@ def _infer_paramtype(parameter: ParameterBase, paramtype: str | None) -> str: return_paramtype: str if paramtype is not None: # override with argument return_paramtype = paramtype - elif isinstance(parameter.vals, vals.Arrays): - return_paramtype = "array" - elif isinstance(parameter, ArrayParameter): + elif isinstance(parameter.vals, vals.Arrays) or isinstance( + parameter, ArrayParameter + ): return_paramtype = "array" elif isinstance(parameter.vals, vals.Strings): return_paramtype = "text" diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index 56653f8f8d59..7f3c791a4104 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -427,9 +427,7 @@ def _can_start_ramping(self) -> bool: state = self.ramping_state() if state == "ramping": # If we don't have a persistent switch, or it's warm - if not self.switch_heater.enabled(): - return True - elif self.switch_heater.state(): + if not self.switch_heater.enabled() or self.switch_heater.state(): return True elif state in ["holding", "paused", "at zero current"]: return True diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 1740f9534ce4..865483cd21a3 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -416,10 +416,7 @@ def test_setting_write_period(wp) -> None: def test_setting_write_period_from_config(wp) -> None: qc.config.dataset.write_period = wp - if isinstance(wp, str): - with pytest.raises(ValueError): - Measurement() - elif wp < 1e-3: + if isinstance(wp, str) or wp < 1e-3: with pytest.raises(ValueError): Measurement() else: From 49dc02561b957162163252d4c7662d84b0aae05c Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 16:30:50 +0200 Subject: [PATCH 31/43] Implement B023 --- pyproject.toml | 2 +- .../test_measurement_context_manager.py | 15 +++++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 47484be968b5..703007ee2226 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "B023", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index 865483cd21a3..412cf89c33a8 100644 --- a/tests/dataset/measurement/test_measurement_context_manager.py +++ b/tests/dataset/measurement/test_measurement_context_manager.py @@ -489,7 +489,9 @@ def action(lst, word): meas.add_after_run(action, testlist) -def test_subscriptions(experiment, DAC, DMM) -> None: +def test_subscriptions( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> None: """ Test that subscribers are called at the moment the data is flushed to database @@ -579,13 +581,18 @@ def collect_values_larger_than_7(results, length, state): @retry_until_does_not_throw( exception_class_to_expect=AssertionError, delay=0.5, tries=20 ) - def assert_states_updated_from_callbacks() -> None: - assert values_larger_than_7 == values_larger_than_7__expected + def assert_states_updated_from_callbacks( + num: int, expected_values: list[int] + ) -> None: + assert values_larger_than_7 == expected_values assert list(all_results_dict.keys()) == [ result_index for result_index in range(1, num + 1 + 1) ] - assert_states_updated_from_callbacks() + assert_states_updated_from_callbacks( + num=num, + expected_values=values_larger_than_7__expected, + ) # Ensure that after exiting the "run()" context, # all subscribers get unsubscribed from the dataset From 041cba1caa7138a224db8b5f5b1fa129ae8a4d96 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 16:31:48 +0200 Subject: [PATCH 32/43] Add PIE808 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py | 2 +- .../Keysight/keysightb1500/KeysightB1500_base.py | 4 ++-- .../Keysight/keysightb1500/KeysightB1520A.py | 12 ++++++------ src/qcodes/instrument_drivers/tektronix/DPO7200xx.py | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 703007ee2226..9659c0f30029 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "PIE808", "LOG015", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "LOG015", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py index 4f31f17e7d1d..94659018f230 100644 --- a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py @@ -48,7 +48,7 @@ def __init__( self.channel = channel # The instrument can store up to ten configurations # internally. - self.set_up_store_slots = [i for i in range(0, 10)] + self.set_up_store_slots = [i for i in range(10)] self.volt: Parameter = self.add_parameter( "volt", diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py index ed829ddbe4ae..f5c1d6fc3005 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_base.py @@ -705,7 +705,7 @@ def get_raw(self) -> tuple[tuple[float, ...], ...]: for channel_index in range(n_channels): parsed_data_items = [ parsed_data[i][channel_index::n_all_data_channels] - for i in range(0, n_items_per_data_point) + for i in range(n_items_per_data_point) ] single_channel_data = _FMTResponse(*parsed_data_items) convert_dummy_val_to_nan(single_channel_data) @@ -721,7 +721,7 @@ def get_raw(self) -> tuple[tuple[float, ...], ...]: source_voltage_index = n_channels parsed_source_voltage_items = [ parsed_data[i][source_voltage_index::n_all_data_channels] - for i in range(0, n_items_per_data_point) + for i in range(n_items_per_data_point) ] self.source_voltage = _FMTResponse(*parsed_source_voltage_items) diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py index 5e23049a8da7..8c968ce67032 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1520A.py @@ -1206,16 +1206,16 @@ def get_raw(self) -> tuple[tuple[float, ...], tuple[float, ...]]: parsed_data = fmt_response_base_parser(raw_data) if len(set(parsed_data.type)) == 2: - self.param1 = _FMTResponse(*(parsed_data[i][::2] for i in range(0, 4))) - self.param2 = _FMTResponse(*(parsed_data[i][1::2] for i in range(0, 4))) + self.param1 = _FMTResponse(*(parsed_data[i][::2] for i in range(4))) + self.param2 = _FMTResponse(*(parsed_data[i][1::2] for i in range(4))) self.shapes = ((num_steps,),) * 2 self.setpoints = ((self.instrument.cv_sweep_voltages(),),) * 2 else: - self.param1 = _FMTResponse(*(parsed_data[i][::4] for i in range(0, 4))) - self.param2 = _FMTResponse(*(parsed_data[i][1::4] for i in range(0, 4))) - self.ac_voltage = _FMTResponse(*(parsed_data[i][2::4] for i in range(0, 4))) - self.dc_voltage = _FMTResponse(*(parsed_data[i][3::4] for i in range(0, 4))) + self.param1 = _FMTResponse(*(parsed_data[i][::4] for i in range(4))) + self.param2 = _FMTResponse(*(parsed_data[i][1::4] for i in range(4))) + self.ac_voltage = _FMTResponse(*(parsed_data[i][2::4] for i in range(4))) + self.dc_voltage = _FMTResponse(*(parsed_data[i][3::4] for i in range(4))) self.shapes = ((len(self.dc_voltage.value),),) * 2 self.setpoints = ((self.dc_voltage.value,),) * 2 diff --git a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py index 7bb6a1b60915..f4a3b0b0a266 100644 --- a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py +++ b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py @@ -911,7 +911,7 @@ def __init__( f"CH{i}" for i in range(1, TektronixDPO7000xx.number_of_channels) ] - trigger_sources.extend([f"D{i}" for i in range(0, 16)]) + trigger_sources.extend([f"D{i}" for i in range(16)]) if self._identifier == "A": trigger_sources.append("line") From 99c9efff49efba82ae72be71a68807ca15265d77 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Fri, 24 Jul 2026 16:37:45 +0200 Subject: [PATCH 33/43] Add LOG015 --- pyproject.toml | 2 +- src/qcodes/instrument_drivers/Keysight/keysight_34934a.py | 5 ++--- src/qcodes/instrument_drivers/Keysight/keysight_34980a.py | 3 +-- .../instrument_drivers/american_magnetics/AMI430_visa.py | 6 +++--- src/qcodes/instrument_drivers/oxford/triton.py | 3 +-- src/qcodes/parameters/parameter_base.py | 2 +- tests/test_logger.py | 6 ++++-- 7 files changed, 13 insertions(+), 14 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9659c0f30029..2359a1c1e4a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "LOG015", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/instrument_drivers/Keysight/keysight_34934a.py b/src/qcodes/instrument_drivers/Keysight/keysight_34934a.py index c1bd9a1c1233..b206bf733474 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysight_34934a.py +++ b/src/qcodes/instrument_drivers/Keysight/keysight_34934a.py @@ -1,4 +1,3 @@ -import logging import re from typing import TYPE_CHECKING @@ -64,7 +63,7 @@ def __init__( layout = self.ask(f"SYSTEM:MODule:TERMinal:TYPE? {self.slot}") self._is_locked = layout == "NONE" if self._is_locked: - logging.warning( + self.log.warning( f"For slot {slot}, no configuration module" f"connected, or safety interlock jumper removed. " "Making any connection is not allowed" @@ -79,7 +78,7 @@ def write(self, cmd: str) -> None: connections. There will be no effect when try to connect any channels. """ if self._is_locked: - logging.warning( + self.log.warning( "Warning: no configuration module connected, " "or safety interlock enabled. " "Making any connection is not allowed" diff --git a/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py b/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py index 65562394afad..576b98882519 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py +++ b/src/qcodes/instrument_drivers/Keysight/keysight_34980a.py @@ -1,4 +1,3 @@ -import logging import re import warnings from functools import wraps @@ -140,7 +139,7 @@ def scan_slots(self) -> None: ) self.module[slot] = sub_module_no_driver self.add_submodule(sub_module_name, sub_module_no_driver) - logging.warning( + self.log.warning( f"can not find driver for {model_string} in slot {slot}" ) diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index 7f3c791a4104..532a1c22a904 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -417,11 +417,11 @@ def _can_start_ramping(self) -> bool: Check the current state of the magnet to see if we can start ramping """ if self.is_quenched(): - logging.error(f"{__name__}: Could not ramp because of quench") + self.log.error(f"{__name__}: Could not ramp because of quench") return False if self.switch_heater.in_persistent_mode(): - logging.error(f"{__name__}: Could not ramp because persistent") + self.log.error(f"{__name__}: Could not ramp because persistent") return False state = self.ramping_state() @@ -432,7 +432,7 @@ def _can_start_ramping(self) -> bool: elif state in ["holding", "paused", "at zero current"]: return True - logging.error(f"{__name__}: Could not ramp, state: {state}") + self.log.error(f"{__name__}: Could not ramp, state: {state}") return False def set_field( diff --git a/src/qcodes/instrument_drivers/oxford/triton.py b/src/qcodes/instrument_drivers/oxford/triton.py index 643045e3d0d2..05d9fd11e2e0 100644 --- a/src/qcodes/instrument_drivers/oxford/triton.py +++ b/src/qcodes/instrument_drivers/oxford/triton.py @@ -1,5 +1,4 @@ import configparser -import logging import re from functools import partial from time import sleep @@ -274,7 +273,7 @@ def __init__( try: self._get_named_channels() except Exception: - logging.warning("Ignored an error in _get_named_channels\n", exc_info=True) + self.log.warning("Ignored an error in _get_named_channels\n", exc_info=True) self.connect_message() diff --git a/src/qcodes/parameters/parameter_base.py b/src/qcodes/parameters/parameter_base.py index dcbaa6b60bd0..0b6f6f6bbb33 100644 --- a/src/qcodes/parameters/parameter_base.py +++ b/src/qcodes/parameters/parameter_base.py @@ -1372,7 +1372,7 @@ def _set_paramtype(self, paramtype: str) -> None: if self.vals is None: self.vals = new_vals elif type(self.vals) is not type(new_vals): - logging.warning( + LOG.warning( f"Tried to set a new paramtype {paramtype}, but this parameter already has paramtype {self.paramtype} which does not match" ) self.param_spec.type = paramtype diff --git a/tests/test_logger.py b/tests/test_logger.py index 624fcddc6afb..7bda84246591 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -26,6 +26,8 @@ NUM_PYTEST_LOGGERS = 4 +_LOG = logging.getLogger(__name__) + @pytest.fixture(autouse=True) def cleanup_started_logger() -> "Generator[None, None, None]": @@ -157,7 +159,7 @@ def test_set_level_without_starting_raises() -> None: def test_handler_level() -> None: logger.start_logger() with logger.LogCapture(level=logging.INFO) as logs: - logging.debug(TEST_LOG_MESSAGE) + _LOG.debug(TEST_LOG_MESSAGE) assert logs.value == "" with ( @@ -165,7 +167,7 @@ def test_handler_level() -> None: logger.handler_level(level=logging.DEBUG, handler=logs.string_handler), ): print(logs.string_handler) - logging.debug(TEST_LOG_MESSAGE) + _LOG.debug(TEST_LOG_MESSAGE) assert logs.value.strip() == TEST_LOG_MESSAGE From 460f3fba219e47cca659f51e90edfe345aa9b388 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Sat, 25 Jul 2026 07:52:55 +0200 Subject: [PATCH 34/43] Implement B008 --- pyproject.toml | 2 +- src/qcodes/dataset/measurements.py | 4 +++- .../instrument_drivers/mock_instruments/__init__.py | 5 ++++- src/qcodes/logger/logger.py | 4 +++- src/qcodes/validators/validators.py | 10 ++++++---- 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 2359a1c1e4a2..e879e704d917 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110", "PERF402", "B008"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110", "PERF402"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index ad5565b14ac4..7985debc2e5f 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -539,7 +539,7 @@ def __init__( experiment: Experiment | None = None, station: Station | None = None, write_period: float | None = None, - interdeps: InterDependencies_ = InterDependencies_(), + interdeps: InterDependencies_ | None = None, name: str = "", subscribers: Sequence[SubscriberType] | None = None, parent_datasets: Sequence[Mapping[Any, Any]] = (), @@ -554,6 +554,8 @@ def __init__( if in_memory_cache is None: in_memory_cache = qc.config.dataset.in_memory_cache in_memory_cache = cast("bool", in_memory_cache) + if interdeps is None: + interdeps = InterDependencies_() self._dataset_class = dataset_class self.write_period = self._calculate_write_period( diff --git a/src/qcodes/instrument_drivers/mock_instruments/__init__.py b/src/qcodes/instrument_drivers/mock_instruments/__init__.py index edd248da108d..f7cb92451ce0 100644 --- a/src/qcodes/instrument_drivers/mock_instruments/__init__.py +++ b/src/qcodes/instrument_drivers/mock_instruments/__init__.py @@ -1078,11 +1078,14 @@ def snapshot_base( return snap +_default_numbers = Numbers(min_value=-1.0, max_value=1.0) + + class MockField(DummyBase): def __init__( self, name: str, - vals: Numbers = Numbers(min_value=-1.0, max_value=1.0), + vals: Numbers = _default_numbers, **kwargs: Unpack[InstrumentBaseKWArgs], ): """Mock instrument for emulating a magnetic field axis diff --git a/src/qcodes/logger/logger.py b/src/qcodes/logger/logger.py index 60ea78228114..1b77143bf45c 100644 --- a/src/qcodes/logger/logger.py +++ b/src/qcodes/logger/logger.py @@ -412,9 +412,11 @@ class LogCapture: def __init__( self, - logger: logging.Logger = logging.getLogger(), + logger: logging.Logger | None = None, level: LevelType | None = None, ) -> None: + if logger is None: + logger = logging.getLogger() self.logger = logger self.level = level or logging.NOTSET diff --git a/src/qcodes/validators/validators.py b/src/qcodes/validators/validators.py index 5bec8df80710..23bc311a4b8b 100644 --- a/src/qcodes/validators/validators.py +++ b/src/qcodes/validators/validators.py @@ -1064,6 +1064,9 @@ def max_value(self) -> float | None: return float(self._max_value) if self._max_value is not None else None +anything = Anything() # singleton instance of Anything + + class Lists[T](Validator[list[T]]): """ Validator for lists @@ -1073,13 +1076,12 @@ class Lists[T](Validator[list[T]]): """ - def __init__(self, elt_validator: Validator[T] = Anything()) -> None: + def __init__(self, elt_validator: Validator[T] = anything) -> None: self._elt_validator = elt_validator self._valid_values = ([vval for vval in elt_validator._valid_values],) def __repr__(self) -> str: - msg = "" + msg = f"" return msg def validate(self, value: list[T], context: str = "") -> None: @@ -1120,7 +1122,7 @@ class Sequence(Validator[typing.Sequence[Any]]): def __init__( self, - elt_validator: Validator[Any] = Anything(), + elt_validator: Validator[Any] = anything, length: int | None = None, require_sorted: bool = False, ) -> None: From 4a88cdbbe31e52c8063277dcb06c1051042038c6 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Sat, 25 Jul 2026 07:54:44 +0200 Subject: [PATCH 35/43] implement PERF402 --- pyproject.toml | 2 +- tests/dataset/dond/test_dond_keyboard_interrupts.py | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e879e704d917..0cf638646c1d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110", "PERF402"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/tests/dataset/dond/test_dond_keyboard_interrupts.py b/tests/dataset/dond/test_dond_keyboard_interrupts.py index 390df2e1da41..8480b77fd946 100644 --- a/tests/dataset/dond/test_dond_keyboard_interrupts.py +++ b/tests/dataset/dond/test_dond_keyboard_interrupts.py @@ -80,7 +80,9 @@ def simulated_sweep(interrupt_at=None): results = [] with pytest.raises(KeyboardInterrupt): for value in simulated_sweep(interrupt_at=3): - results.append(value) + results.append(value) # noqa: PERF402 + # simulate adding numbers one by one using copy + # so its ok here assert results == [0, 1, 2] # Test interruption in nested sweeps @@ -92,6 +94,8 @@ def simulated_sweep(interrupt_at=None): for inner_value in simulated_sweep( interrupt_at=2 if outer_value == 1 else None ): - inner_results.append(inner_value) + inner_results.append(inner_value) # noqa: PERF402 + # simulate adding numbers one by one using copy + # so its ok here assert outer_results == [0, 1] assert inner_results == [0, 1, 2, 3, 4, 0, 1] From ee35e209af75cb8fc712d0f8001455a2b4261d2f Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Sat, 25 Jul 2026 08:22:39 +0200 Subject: [PATCH 36/43] Implement TRY201 --- pyproject.toml | 2 +- src/qcodes/dataset/experiment_container.py | 2 +- src/qcodes/dataset/sqlite/queries.py | 4 ++-- src/qcodes/instrument/instrument.py | 6 +++--- src/qcodes/instrument/visa.py | 4 ++-- src/qcodes/instrument_drivers/Keithley/Keithley_s46.py | 4 ++-- .../instrument_drivers/american_magnetics/AMI430_visa.py | 8 ++++---- .../instrument_drivers/cryomagnetics/_cryomagnetics4g.py | 8 ++++---- src/qcodes/parameters/parameter_base.py | 4 ++-- src/qcodes/station.py | 2 +- 10 files changed, 22 insertions(+), 22 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 0cf638646c1d..9469aaea7397 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "TRY201", "S110"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "S110"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/src/qcodes/dataset/experiment_container.py b/src/qcodes/dataset/experiment_container.py index ad1f658e4a3c..d7b52e8c9997 100644 --- a/src/qcodes/dataset/experiment_container.py +++ b/src/qcodes/dataset/experiment_container.py @@ -400,7 +400,7 @@ def load_or_create_experiment( if "Experiment not found" in str(exception): experiment = new_experiment(experiment_name, sample_name, conn=conn) else: - raise exception + raise return experiment diff --git a/src/qcodes/dataset/sqlite/queries.py b/src/qcodes/dataset/sqlite/queries.py index fbb132f9da1e..07b6f5a77dd9 100644 --- a/src/qcodes/dataset/sqlite/queries.py +++ b/src/qcodes/dataset/sqlite/queries.py @@ -1829,7 +1829,7 @@ def get_data_by_tag_and_table_name( ): data = None else: - raise e + raise return data @@ -1953,7 +1953,7 @@ def add_data_to_dynamic_columns( if str(e).startswith("duplicate"): update_columns(conn, row_id, table_name, data) else: - raise e + raise def get_experiment_name_from_experiment_id(conn: AtomicConnection, exp_id: int) -> str: diff --git a/src/qcodes/instrument/instrument.py b/src/qcodes/instrument/instrument.py index 3a522581097e..0afa748d8c06 100644 --- a/src/qcodes/instrument/instrument.py +++ b/src/qcodes/instrument/instrument.py @@ -365,7 +365,7 @@ def exist(name: str, instrument_class: type[Instrument] | None = None) -> bool: if instrument_is_not_found: instrument_exists = False else: - raise exception + raise return instrument_exists @@ -416,7 +416,7 @@ def write(self, cmd: str) -> None: *e.args, f"writing {cmd!r} to {self!r}", ) - raise e + raise def write_raw(self, cmd: str) -> None: """ @@ -460,7 +460,7 @@ def ask(self, cmd: str) -> str: except Exception as e: e.args = (*e.args, f"asking {cmd!r} to {self!r}") - raise e + raise def ask_raw(self, cmd: str) -> str: """ diff --git a/src/qcodes/instrument/visa.py b/src/qcodes/instrument/visa.py index 61547e7dc994..bbf294b9e29b 100644 --- a/src/qcodes/instrument/visa.py +++ b/src/qcodes/instrument/visa.py @@ -267,10 +267,10 @@ def _connect_and_handle_error( ) -> pyvisa.resources.MessageBasedResource: try: visa_handle = self._open_resource(address, visalib) - except Exception as e: + except Exception: self.visa_log.exception(f"Could not connect at {address}") self.close() - raise e + raise return visa_handle def _open_resource( diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py index 07f501d07d3b..8238349c8720 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py @@ -181,11 +181,11 @@ def __init__( ) self._available_channels.append(alias) - except RuntimeError as err: + except RuntimeError: # If we error on undesirable state we want to make sure # we also close the visa connection self.close() - raise err + raise @staticmethod def _get_closed_channels_parser(reply: str) -> list[str]: diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index 532a1c22a904..f31b18762909 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -598,7 +598,7 @@ def _update_units( def write_raw(self, cmd: str) -> None: try: super().write_raw(cmd) - except VisaIOError as err: + except VisaIOError: # The ami communication has found to be unstable # so we retry the communication here msg = f"Got VisaIOError while writing {cmd} to instrument." @@ -610,12 +610,12 @@ def write_raw(self, cmd: str) -> None: self.device_clear() super().write_raw(cmd) else: - raise err + raise def ask_raw(self, cmd: str) -> str: try: result = super().ask_raw(cmd) - except VisaIOError as err: + except VisaIOError: # The ami communication has found to be unstable # so we retry the communication here msg = f"Got VisaIOError while asking the instrument: {cmd}" @@ -627,7 +627,7 @@ def ask_raw(self, cmd: str) -> str: self.device_clear() result = super().ask_raw(cmd) else: - raise err + raise return result diff --git a/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py b/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py index 39c7ef9f3433..e643217480bf 100644 --- a/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py +++ b/src/qcodes/instrument_drivers/cryomagnetics/_cryomagnetics4g.py @@ -445,7 +445,7 @@ def _initialize_max_current_limits(self) -> None: def write_raw(self, cmd: str) -> None: try: super().write_raw(cmd) - except VisaIOError as err: + except VisaIOError: # The ami communication has found to be unstable # so we retry the communication here msg = f"Got VisaIOError while writing {cmd} to instrument." @@ -457,12 +457,12 @@ def write_raw(self, cmd: str) -> None: self.device_clear() super().write_raw(cmd) else: - raise err + raise def ask_raw(self, cmd: str) -> str: try: result = super().ask_raw(cmd) - except VisaIOError as err: + except VisaIOError: # The communication has found to be unstable # so we retry the communication here msg = f"Got VisaIOError while asking the instrument: {cmd}" @@ -474,5 +474,5 @@ def ask_raw(self, cmd: str) -> str: self.device_clear() result = super().ask_raw(cmd) else: - raise err + raise return result diff --git a/src/qcodes/parameters/parameter_base.py b/src/qcodes/parameters/parameter_base.py index 0b6f6f6bbb33..d8752d7ddc0c 100644 --- a/src/qcodes/parameters/parameter_base.py +++ b/src/qcodes/parameters/parameter_base.py @@ -908,7 +908,7 @@ def get_wrapper(*args: Any, **kwargs: Any) -> ParameterDataTypeVar: except Exception as e: e.args = (*e.args, f"getting {self}") - raise e + raise return get_wrapper @@ -966,7 +966,7 @@ def set_wrapper(value: ParameterDataTypeVar, **kwargs: Any) -> None: except Exception as e: e.args = (*e.args, f"setting {self} to {value}") - raise e + raise return set_wrapper diff --git a/src/qcodes/station.py b/src/qcodes/station.py index 1fdad358e078..1b7b41f67e99 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -295,7 +295,7 @@ def remove_component(self, name: str) -> MetadatableWithName | None: if name in str(e): raise KeyError(f"Component {name} is not part of the station") else: - raise e + raise def get_component(self, full_name: str) -> MetadatableWithName: """ From c397e42f24b66544672be6cc38ee2ca7b4c6df62 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Sat, 25 Jul 2026 08:29:50 +0200 Subject: [PATCH 37/43] Implement B017 --- pyproject.toml | 2 +- tests/parameter/test_permissive_range.py | 2 +- tests/test_instrument.py | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9469aaea7397..95c0ac1af8d9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -258,7 +258,7 @@ extend-select = [ # it may be worth fixing some or these in the future # PYI036 disable until https://github.com/astral-sh/ruff/issues/9794 is fixed ignore = ["E501", "G004", "PLR2004", "PLR0913", "PLR0911", "PLR0912", "PLR0915", "PLW0602", "PLW0603", "PLW2901", "PYI036", "PLR0917", - "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "B017", "TRY004", "TRY002", "S110"] # new defaults of of 0.16.0 that we don't want to enable yet + "DTZ007", "DTZ005", "DTZ006", "N999", "BLE001", "TRY004", "TRY002", "S110"] # new defaults of of 0.16.0 that we don't want to enable yet # we want to explicitly use the micro symbol # not the greek letter diff --git a/tests/parameter/test_permissive_range.py b/tests/parameter/test_permissive_range.py index 76160485502a..2007d97d9c17 100644 --- a/tests/parameter/test_permissive_range.py +++ b/tests/parameter/test_permissive_range.py @@ -24,7 +24,7 @@ @pytest.mark.parametrize("args", bad_args) def test_bad_calls(args) -> None: - with pytest.raises(Exception): + with pytest.raises(TypeError, match="not supported between"): permissive_range(*args) diff --git a/tests/test_instrument.py b/tests/test_instrument.py index 989ab0fde72d..5b51d4679c4e 100644 --- a/tests/test_instrument.py +++ b/tests/test_instrument.py @@ -97,7 +97,9 @@ def test_validate_function(testdummy: DummyInstrument) -> None: testdummy.dac1.cache._value = 1000 # overrule the validator testdummy.dac1.cache._raw_value = 1000 # overrule the validator - with pytest.raises(Exception): + with pytest.raises( + ValueError, match=r"1000 is invalid: must be between -800 and 400 inclusive" + ): testdummy.validate_status() From d59f0b6d81243f2d93a7eea89d792ef3e18c6550 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 27 Jul 2026 07:46:42 +0200 Subject: [PATCH 38/43] Ignore new type checking errors --- src/qcodes/utils/json_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/qcodes/utils/json_utils.py b/src/qcodes/utils/json_utils.py index 7cd07fe89030..9b0175928501 100644 --- a/src/qcodes/utils/json_utils.py +++ b/src/qcodes/utils/json_utils.py @@ -61,7 +61,7 @@ def default(self, o: Any) -> Any: } elif hasattr(o, "_JSONEncoder"): # Use object's custom JSON encoder - jsosencode = o._JSONEncoder + jsosencode = o._JSONEncoder # pyright: ignore[reportAttributeAccessIssue] return jsosencode() else: try: @@ -82,7 +82,7 @@ def default(self, o: Any) -> Any: ): return { "__class__": type(o).__name__, - "__args__": o.__getnewargs__(), + "__args__": o.__getnewargs__(), # pyright: ignore[reportAttributeAccessIssue] } else: # we cannot convert the object to JSON, just take a string From 8b15979aa6b1d3ef620071c5d686b7e943fb09a8 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 27 Jul 2026 09:39:17 +0200 Subject: [PATCH 39/43] Remove shebang --- docs/conf.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index e8fdcb5dcb63..9b78ed91a829 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,3 @@ -#!/usr/bin/env python3 -# # QCoDeS documentation build configuration file, created by # sphinx-quickstart on Thu Jun 2 10:41:37 2016. # From 94961a42ca9b155789010a9512e8a56b2c3b9e2e Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 27 Jul 2026 09:43:37 +0200 Subject: [PATCH 40/43] remove not matching regex --- tests/parameter/test_permissive_range.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/parameter/test_permissive_range.py b/tests/parameter/test_permissive_range.py index 2007d97d9c17..c0a5928a956f 100644 --- a/tests/parameter/test_permissive_range.py +++ b/tests/parameter/test_permissive_range.py @@ -24,7 +24,7 @@ @pytest.mark.parametrize("args", bad_args) def test_bad_calls(args) -> None: - with pytest.raises(TypeError, match="not supported between"): + with pytest.raises(TypeError): permissive_range(*args) From 304a629e8b2dc8e2ba31ad8172a1b4dadafc3e89 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Mon, 27 Jul 2026 09:48:06 +0200 Subject: [PATCH 41/43] Remove another shebang --- src/qcodes/monitor/monitor.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/qcodes/monitor/monitor.py b/src/qcodes/monitor/monitor.py index e8bcf8f6a795..eb9caa7e8830 100644 --- a/src/qcodes/monitor/monitor.py +++ b/src/qcodes/monitor/monitor.py @@ -1,5 +1,3 @@ -#! /usr/bin/env python -# vim:fenc=utf-8 # # Copyright © 2017 unga # From dca87ba93c9b13f13f69409a44a4204f5e4ea447 Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 30 Jul 2026 14:30:03 +0200 Subject: [PATCH 42/43] Feedback from review --- src/qcodes/dataset/plotting.py | 11 ++++++----- .../instrument_drivers/Keithley/Keithley_3706A.py | 5 ++++- src/qcodes/instrument_drivers/tektronix/AWG5014.py | 1 - src/qcodes/validators/validators.py | 6 +++--- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/qcodes/dataset/plotting.py b/src/qcodes/dataset/plotting.py index 37c367d18e79..6145968e7822 100644 --- a/src/qcodes/dataset/plotting.py +++ b/src/qcodes/dataset/plotting.py @@ -269,11 +269,12 @@ def plot_dataset( indices_to_remove = [] for i, data in enumerate(alldata): - if len(data) == 2: # 1D PLOTTING - if data[1]["name"] not in parameters: - indices_to_remove.append(i) - elif len(data) == 3 and data[2]["name"] not in parameters: - # 2D PLOTTING + # the last element of the data list is the dependent parameter, + # so we check if it is in the list of parameters to plot + deselected_in_1D_plot = len(data) == 2 and data[1]["name"] not in parameters + deselected_in_2D_plot = len(data) == 3 and data[2]["name"] not in parameters + + if deselected_in_1D_plot or deselected_in_2D_plot: indices_to_remove.append(i) alldata = [d for (i, d) in enumerate(alldata) if i not in indices_to_remove] diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py index 897131f4c02b..842d4734960f 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_3706A.py @@ -222,7 +222,10 @@ def _warn_on_disengaged_interlocks(self, val: str) -> None: def _is_backplane_channel(self, channel_id: str) -> bool: if len(channel_id) != 4: raise Keithley3706AInvalidValue(f"{channel_id} is not a valid channel id") - return channel_id[1] == "9" + + is_backplane_channel = channel_id[1] == "9" + + return is_backplane_channel def exclusive_close(self, val: str) -> None: """ diff --git a/src/qcodes/instrument_drivers/tektronix/AWG5014.py b/src/qcodes/instrument_drivers/tektronix/AWG5014.py index 3476ca926220..c0084abea479 100644 --- a/src/qcodes/instrument_drivers/tektronix/AWG5014.py +++ b/src/qcodes/instrument_drivers/tektronix/AWG5014.py @@ -1372,7 +1372,6 @@ def _generate_awg_file( ) # sequence - kk = 1 seq_record_str = BytesIO() for kk, segment in enumerate(wfname_l.transpose(), start=1): diff --git a/src/qcodes/validators/validators.py b/src/qcodes/validators/validators.py index 23bc311a4b8b..bcda83550e19 100644 --- a/src/qcodes/validators/validators.py +++ b/src/qcodes/validators/validators.py @@ -1064,7 +1064,7 @@ def max_value(self) -> float | None: return float(self._max_value) if self._max_value is not None else None -anything = Anything() # singleton instance of Anything +_anything = Anything() # singleton instance of Anything class Lists[T](Validator[list[T]]): @@ -1076,7 +1076,7 @@ class Lists[T](Validator[list[T]]): """ - def __init__(self, elt_validator: Validator[T] = anything) -> None: + def __init__(self, elt_validator: Validator[T] = _anything) -> None: self._elt_validator = elt_validator self._valid_values = ([vval for vval in elt_validator._valid_values],) @@ -1122,7 +1122,7 @@ class Sequence(Validator[typing.Sequence[Any]]): def __init__( self, - elt_validator: Validator[Any] = anything, + elt_validator: Validator[Any] = _anything, length: int | None = None, require_sorted: bool = False, ) -> None: From 6bc281cbb3fd6477de9f4983ff3a7b089d207a8d Mon Sep 17 00:00:00 2001 From: "Jens H. Nielsen" Date: Thu, 30 Jul 2026 14:34:23 +0200 Subject: [PATCH 43/43] Lint new code --- src/qcodes/instrument/instrument.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/qcodes/instrument/instrument.py b/src/qcodes/instrument/instrument.py index 0afa748d8c06..1a43075ae465 100644 --- a/src/qcodes/instrument/instrument.py +++ b/src/qcodes/instrument/instrument.py @@ -207,9 +207,9 @@ def close_all( for inststr in list(cls._all_instruments): try: inst: Instrument = cls.find_instrument(inststr) - if only_subclasses and issubclass(type(inst), cls): - should_be_closed = True - elif not only_subclasses: + if ( + only_subclasses and issubclass(type(inst), cls) + ) or not only_subclasses: should_be_closed = True else: should_be_closed = False