diff --git a/docs/changes/newsfragments/8644.improved b/docs/changes/newsfragments/8644.improved new file mode 100644 index 000000000000..361030988fe2 --- /dev/null +++ b/docs/changes/newsfragments/8644.improved @@ -0,0 +1,3 @@ +The type annotations of ``Station.load_all_instruments`` now accept calling it without +arguments or with only one of ``only_names`` and ``only_types``. Previously these valid +calls matched none of the overloads and were rejected by static type checkers. diff --git a/docs/changes/newsfragments/8644.improved_driver b/docs/changes/newsfragments/8644.improved_driver new file mode 100644 index 000000000000..34dad960ed04 --- /dev/null +++ b/docs/changes/newsfragments/8644.improved_driver @@ -0,0 +1,6 @@ +``AlazarTechATS.acquire`` is now annotated to accept any ``AcquisitionInterface`` as +``acquisition_controller``, not only an ``AcquisitionController``, matching what it supports +at runtime. ``AcquisitionController`` now passes its type parameter on to +``AcquisitionInterface``, so the return type of ``acquire`` is inferred from the +``post_acquire`` return type of the controller. Subclasses of ``AcquisitionController[T]`` +whose ``post_acquire`` does not return ``T`` will now be reported by static type checkers. diff --git a/docs/changes/newsfragments/8644.improved_driver.1 b/docs/changes/newsfragments/8644.improved_driver.1 new file mode 100644 index 000000000000..835b4cd0dfa6 --- /dev/null +++ b/docs/changes/newsfragments/8644.improved_driver.1 @@ -0,0 +1,3 @@ +Added missing type annotations to the optional arguments of the Keysight B1500 +``MessageBuilder`` methods ``ercmaio``, ``lst_query``, ``pch_query``, ``sprm``, ``tc`` +and ``wat``. diff --git a/docs/changes/newsfragments/8644.underthehood b/docs/changes/newsfragments/8644.underthehood new file mode 100644 index 000000000000..45edb21b0cfe --- /dev/null +++ b/docs/changes/newsfragments/8644.underthehood @@ -0,0 +1,3 @@ +The minimum supported version of ``typing_extensions`` is now 4.12.0. Older versions do not +apply the default of a ``TypeVar``, so subscripting a parameter with only its value type at +runtime, e.g. ``Parameter[int]``, failed with ``TypeError: Too few arguments`` on Python 3.12. diff --git a/pyproject.toml b/pyproject.toml index e9b1bbca5ad7..1053246c2440 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ dependencies = [ "pyvisa>=1.12.0, <1.17.0", "ruamel.yaml>=0.16.0,!=0.16.6", "tabulate>=0.9.0", - "typing_extensions>=4.6.0", + "typing_extensions>=4.12.0", "tqdm>=4.59.0", "uncertainties>=3.2.0", "versioningit>=2.2.1", @@ -163,7 +163,6 @@ strict_equality = true module = [ "tests.*", "qcodes.instrument_drivers.Harvard.*", - "qcodes.instrument_drivers.Keysight.keysightb1500.message_builder.*", ] disallow_untyped_defs = false disallow_incomplete_defs = false @@ -202,7 +201,6 @@ reportPrivateUsage = "none" reportUnknownMemberType = "none" reportUnknownParameterType = "none" reportMissingTypeArgument = "none" -reportMissingParameterType = "none" reportUnknownArgumentType = "none" reportUnusedFunction = "none" reportUnusedImport = "none" diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS.py b/src/qcodes/instrument_drivers/AlazarTech/ATS.py index f23d2cf03fc9..a1e64776c0b8 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS.py @@ -322,7 +322,7 @@ def acquire[OutputType]( # noqa: D417 (missing args documentation) get_processed_data: str | None = None, allocated_buffers: int | None = None, buffer_timeout: int | None = None, - acquisition_controller: AcquisitionController[OutputType] | None = None, + acquisition_controller: AcquisitionInterface[OutputType] | None = None, ) -> OutputType: """ Perform a single acquisition with the Alazar board, and set certain @@ -897,7 +897,7 @@ def buffer_done_callback(self, buffers_completed: int) -> None: """ -class AcquisitionController[OutputType](Instrument, AcquisitionInterface[Any]): +class AcquisitionController[OutputType](Instrument, AcquisitionInterface[OutputType]): """ Compatibility class. The methods of :class:`AcquisitionController` have been extracted. This class is the base class fro AcquisitionInterfaces diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/message_builder.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/message_builder.py index cb8bbabd26eb..1baf36c672dc 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/message_builder.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/message_builder.py @@ -1587,7 +1587,13 @@ def ercmagrd_query(self) -> "MessageBuilder": self._msg.append(cmd) return self - def ercmaio(self, cmhl=None, acgs=None, bias=None, corr=None) -> "MessageBuilder": + def ercmaio( + self, + cmhl: int | None = None, + acgs: int | None = None, + bias: int | None = None, + corr: int | None = None, + ) -> "MessageBuilder": cmd = "ERCMAIO" if cmhl is not None: @@ -2191,7 +2197,12 @@ def lssv( return self @final_command - def lst_query(self, pnum=None, index=None, size=None) -> "MessageBuilder": + def lst_query( + self, + pnum: int | None = None, + index: int | None = None, + size: int | None = None, + ) -> "MessageBuilder": cmd = "LST?" if pnum is not None: @@ -2593,7 +2604,7 @@ def pch( return self @final_command - def pch_query(self, master=None) -> "MessageBuilder": + def pch_query(self, master: constants.ChNr | int | None = None) -> "MessageBuilder": cmd = "PCH" if master is not None: @@ -3031,7 +3042,9 @@ def spper_query(self) -> "MessageBuilder": self._msg.append(cmd) return self - def sprm(self, mode: constants.SPRM.Mode | int, condition=None) -> "MessageBuilder": + def sprm( + self, mode: constants.SPRM.Mode | int, condition: float | None = None + ) -> "MessageBuilder": if condition is None: cmd = f"SPRM {mode}" else: @@ -3198,7 +3211,7 @@ def tc( self, chnum: constants.ChNr | int, mode: constants.RangingMode | int, - ranging_type=None, + ranging_type: int | None = None, ) -> "MessageBuilder": cmd = f"TC {chnum},{mode}" @@ -3558,7 +3571,10 @@ def wacv( return self def wat( - self, wait_time_type: constants.WAT.Type | int, coeff: float, offset=None + self, + wait_time_type: constants.WAT.Type | int, + coeff: float, + offset: float | None = None, ) -> "MessageBuilder": cmd = f"WAT {wait_time_type},{coeff}" diff --git a/src/qcodes/station.py b/src/qcodes/station.py index cfc7d18b8579..fd52e9b80da7 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -847,22 +847,30 @@ def update_monitor() -> None: @overload def load_all_instruments( self, - only_names: None, - only_types: Iterable[str], + only_names: None = None, + only_types: None = None, ) -> tuple[str, ...]: ... @overload def load_all_instruments( self, only_names: Iterable[str], - only_types: None, + only_types: None = None, + ) -> tuple[str, ...]: ... + + @overload + def load_all_instruments( + self, + only_names: None = None, + *, + only_types: Iterable[str], ) -> tuple[str, ...]: ... @overload def load_all_instruments( self, only_names: None, - only_types: None, + only_types: Iterable[str], ) -> tuple[str, ...]: ... @overload diff --git a/tests/common.py b/tests/common.py index 11d4df019b2e..0f3b7aff5652 100644 --- a/tests/common.py +++ b/tests/common.py @@ -139,7 +139,7 @@ def skip_if_no_fixtures(dbname: str | Path) -> None: class DummyComponent(MetadatableWithName): """Docstring for DummyComponent.""" - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__() self.name = name diff --git a/tests/dataset/conftest.py b/tests/dataset/conftest.py index f80143253413..f6a65fc26939 100644 --- a/tests/dataset/conftest.py +++ b/tests/dataset/conftest.py @@ -5,7 +5,7 @@ import tempfile from contextlib import contextmanager from enum import StrEnum -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any import numpy as np import pytest @@ -33,12 +33,18 @@ ) from qcodes.validators import Arrays, ComplexNumbers, Numbers +if TYPE_CHECKING: + from numpy.typing import NDArray + + from qcodes.instrument import InstrumentBase + if TYPE_CHECKING: from collections.abc import Generator, Iterator from pathlib import Path from qcodes.dataset.data_set_protocol import DataSetProtocol from qcodes.dataset.experiment_container import Experiment + from qcodes.dataset.sqlite.connection import AtomicConnection @pytest.fixture(scope="function", name="non_created_db") @@ -52,7 +58,9 @@ def _make_non_created_db(tmp_path: Path) -> None: @pytest.fixture(scope="function") -def empty_temp_db_connection(tmp_path): +def empty_temp_db_connection( + tmp_path: Path, +) -> Generator[AtomicConnection, None, None]: """ Yield connection to an empty temporary DB file. """ @@ -65,7 +73,9 @@ def empty_temp_db_connection(tmp_path): @pytest.fixture(scope="function") -def two_empty_temp_db_connections(tmp_path): +def two_empty_temp_db_connections( + tmp_path: Path, +) -> Generator[tuple[AtomicConnection, AtomicConnection], None, None]: """ Yield connections to two empty files. Meant for use with the test_database_extract_runs @@ -83,7 +93,9 @@ def two_empty_temp_db_connections(tmp_path): @contextmanager -def temporarily_copied_DB(filepath: str, **kwargs): +def temporarily_copied_DB( + filepath: str, **kwargs: Any +) -> Generator[AtomicConnection, None, None]: """ Make a temporary copy of a db-file and delete it after use. Meant to be used together with the old version database fixtures, lest we change the @@ -108,7 +120,7 @@ def temporarily_copied_DB(filepath: str, **kwargs): @pytest.fixture(name="scalar_dataset") -def _make_scalar_dataset(dataset): +def _make_scalar_dataset(dataset: DataSet) -> Generator[DataSet, None, None]: n_params = 3 n_rows = 10**3 params_indep = [ @@ -138,7 +150,9 @@ def _make_scalar_dataset(dataset): @pytest.fixture( name="scalar_datasets_parameterized", params=((3, 10**3), (5, 10**3), (10, 50)) ) -def _make_scalar_datasets_parameterized(dataset, request: FixtureRequest): +def _make_scalar_datasets_parameterized( + dataset: DataSet, request: FixtureRequest +) -> Generator[DataSet, None, None]: n_params = request.param[0] n_rows = request.param[1] params_indep = [ @@ -166,7 +180,7 @@ def _make_scalar_datasets_parameterized(dataset, request: FixtureRequest): @pytest.fixture -def scalar_dataset_with_nulls(dataset): +def scalar_dataset_with_nulls(dataset: DataSet) -> Generator[DataSet, None, None]: """ A very simple dataset. A scalar is varied, and two parameters are measured one by one @@ -186,7 +200,9 @@ def scalar_dataset_with_nulls(dataset): @pytest.fixture(scope="function", params=["array", "numeric"]) -def array_dataset(experiment, request: FixtureRequest): +def array_dataset( + experiment: Experiment, request: FixtureRequest +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() param = ArraySetPointParam() meas.register_parameter(param, paramtype=request.param) @@ -206,7 +222,9 @@ def array_dataset(experiment, request: FixtureRequest): @pytest.fixture(scope="function", params=["array", "numeric"]) -def array_dataset_with_nulls(experiment, request: FixtureRequest): +def array_dataset_with_nulls( + experiment: Experiment, request: FixtureRequest +) -> Generator[DataSetProtocol, None, None]: """ A dataset where two arrays are measured, one as a function of two other (setpoint) arrays, the other as a function of just one @@ -235,7 +253,9 @@ def array_dataset_with_nulls(experiment, request: FixtureRequest): @pytest.fixture(scope="function", params=["array", "numeric"]) -def multi_dataset(experiment, request: FixtureRequest): +def multi_dataset( + experiment: Experiment, request: FixtureRequest +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() param = Multi2DSetPointParam() @@ -264,7 +284,9 @@ class MeasurementOptions(StrEnum): scope="function", params=[MeasurementOptions.SHAPE_KNOWN, MeasurementOptions.SHAPE_UNKNOWN], ) -def different_setpoint_dataset(experiment, request: FixtureRequest): +def different_setpoint_dataset( + experiment: Experiment, request: FixtureRequest +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() param = Multi2DSetPointParam2Sizes() @@ -328,7 +350,9 @@ def two_params_partial_2d_dataset( @pytest.fixture(scope="function") -def array_in_scalar_dataset(experiment): +def array_in_scalar_dataset( + experiment: Experiment, +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() scalar_param = Parameter("scalarparam", set_cmd=None) param = ArraySetPointParam() @@ -349,7 +373,9 @@ def array_in_scalar_dataset(experiment): @pytest.fixture(scope="function") -def varlen_array_in_scalar_dataset(experiment): +def varlen_array_in_scalar_dataset( + experiment: Experiment, +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() scalar_param = Parameter("scalarparam", set_cmd=None) param = ArraySetPointParam() @@ -371,7 +397,9 @@ def varlen_array_in_scalar_dataset(experiment): @pytest.fixture(scope="function") -def array_in_scalar_dataset_unrolled(experiment): +def array_in_scalar_dataset_unrolled( + experiment: Experiment, +) -> Generator[DataSetProtocol, None, None]: """ This fixture yields a dataset where an array-valued parameter is registered as a 'numeric' type and has an additional single-valued setpoint. We @@ -398,7 +426,9 @@ def array_in_scalar_dataset_unrolled(experiment): @pytest.fixture(scope="function", params=["array", "numeric"]) -def array_in_str_dataset(experiment, request: FixtureRequest): +def array_in_str_dataset( + experiment: Experiment, request: FixtureRequest +) -> Generator[DataSetProtocol, None, None]: meas = Measurement() scalar_param = Parameter("textparam", set_cmd=None) param = ArraySetPointParam() @@ -431,7 +461,7 @@ def some_paramspecbases() -> tuple[ @pytest.fixture -def some_paramspecs(): +def some_paramspecs() -> dict[int, dict[str, ParamSpec]]: """ Some different paramspecs for testing. The idea is that we just add a new group of paramspecs as the need arises @@ -481,7 +511,7 @@ def some_paramspecs(): @pytest.fixture -def some_interdeps(): +def some_interdeps() -> list[InterDependencies_]: """ Some different InterDependencies_ objects for testing """ @@ -510,21 +540,21 @@ def some_interdeps(): @pytest.fixture(name="DAC") # scope is "function" per default -def _make_dac(): +def _make_dac() -> Generator[DummyInstrument, None, None]: dac = DummyInstrument("dummy_dac", gates=["ch1", "ch2"]) yield dac dac.close() @pytest.fixture(name="DAC3D") # scope is "function" per default -def _make_dac_3d(): +def _make_dac_3d() -> Generator[DummyInstrument, None, None]: dac = DummyInstrument("dummy_dac", gates=["ch1", "ch2", "ch3"]) yield dac dac.close() @pytest.fixture(name="DAC_with_metadata") # scope is "function" per default -def _make_dac_with_metadata(): +def _make_dac_with_metadata() -> Generator[DummyInstrument, None, None]: dac = DummyInstrument( "dummy_dac", gates=["ch1", "ch2"], metadata={"dac": "metadata"} ) @@ -533,28 +563,28 @@ def _make_dac_with_metadata(): @pytest.fixture(name="DMM") -def _make_dmm(): +def _make_dmm() -> Generator[DummyInstrument, None, None]: dmm = DummyInstrument("dummy_dmm", gates=["v1", "v2"]) yield dmm dmm.close() @pytest.fixture -def channel_array_instrument(): +def channel_array_instrument() -> Generator[DummyChannelInstrument, None, None]: channelarrayinstrument = DummyChannelInstrument("dummy_channel_inst") yield channelarrayinstrument channelarrayinstrument.close() @pytest.fixture -def complex_num_instrument(): +def complex_num_instrument() -> Generator[DummyInstrument, None, None]: class MyParam(Parameter): - def get_raw(self): + def get_raw(self) -> complex: assert self.instrument is not None return self.instrument.setpoint() + 1j * self.instrument.setpoint() class RealPartParam(Parameter): - def get_raw(self): + def get_raw(self) -> float: assert self.instrument is not None return self.instrument.complex_setpoint().real @@ -642,14 +672,19 @@ def get_raw(self): @pytest.fixture -def SpectrumAnalyzer(): +def SpectrumAnalyzer() -> Generator[DummyInstrument, None, None]: """ Yields a DummyInstrument that holds ArrayParameters returning different types """ class BaseSpectrum(ArrayParameter): - def __init__(self, name, instrument, **kwargs): + def __init__( + self, + name: str, + instrument: InstrumentBase, + **kwargs: Any, + ) -> None: super().__init__( name=name, shape=(1,), # this attribute should be removed @@ -665,7 +700,7 @@ def __init__(self, name, instrument, **kwargs): self.stop = 2e6 self._rng = np.random.default_rng() - def get_data(self): + def get_data(self) -> NDArray[np.float64]: # This is how it should be: the setpoints are generated at the # time we get. But that will of course not work with the old Loop self.setpoints = (tuple(np.linspace(self.start, self.stop, self.npts)),) @@ -673,11 +708,16 @@ def get_data(self): return self._rng.standard_normal(self.npts) class Spectrum(BaseSpectrum): - def get_raw(self): + def get_raw(self) -> NDArray[np.float64]: return super().get_data() class MultiDimSpectrum(ArrayParameter): - def __init__(self, name, instrument, **kwargs): + def __init__( + self, + name: str, + instrument: InstrumentBase, + **kwargs: Any, + ) -> None: self.start = 0 self.stop = 2e6 self.npts = (100, 50, 20) @@ -699,16 +739,16 @@ def __init__(self, name, instrument, **kwargs): ) self._rng = np.random.default_rng() - def get_raw(self): + def get_raw(self) -> NDArray[np.float64]: return self._rng.standard_normal(self.npts) class ListSpectrum(BaseSpectrum): - def get_raw(self): + def get_raw(self) -> list[np.float64]: output = super().get_data() return list(output) class TupleSpectrum(BaseSpectrum): - def get_raw(self): + def get_raw(self) -> tuple[np.float64, ...]: output = super().get_data() return tuple(output) @@ -723,7 +763,9 @@ def get_raw(self): @pytest.fixture -def meas_with_registered_param(experiment, DAC, DMM): +def meas_with_registered_param( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> Generator[Measurement, None, None]: meas = Measurement() meas.register_parameter(DAC.ch1) meas.register_parameter(DMM.v1, setpoints=[DAC.ch1]) @@ -731,7 +773,9 @@ def meas_with_registered_param(experiment, DAC, DMM): @pytest.fixture -def meas_with_registered_param_2d(experiment, DAC, DMM): +def meas_with_registered_param_2d( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> Generator[Measurement, None, None]: meas = Measurement() meas.register_parameter(DAC.ch1) meas.register_parameter(DAC.ch2) @@ -740,7 +784,9 @@ def meas_with_registered_param_2d(experiment, DAC, DMM): @pytest.fixture -def meas_with_registered_param_3d(experiment, DAC3D, DMM): +def meas_with_registered_param_3d( + experiment: Experiment, DAC3D: DummyInstrument, DMM: DummyInstrument +) -> Generator[Measurement, None, None]: meas = Measurement() meas.register_parameter(DAC3D.ch1) meas.register_parameter(DAC3D.ch2) @@ -750,7 +796,11 @@ def meas_with_registered_param_3d(experiment, DAC3D, DMM): @pytest.fixture(name="meas_with_registered_param_complex") -def _make_meas_with_registered_param_complex(experiment, DAC, complex_num_instrument): +def _make_meas_with_registered_param_complex( + experiment: Experiment, + DAC: DummyInstrument, + complex_num_instrument: DummyInstrument, +) -> Generator[Measurement, None, None]: meas = Measurement() meas.register_parameter(DAC.ch1) meas.register_parameter(complex_num_instrument.complex_num, setpoints=[DAC.ch1]) @@ -767,11 +817,15 @@ def _make_dummy_instrument() -> Iterator[DummyChannelInstrument]: class ArrayshapedParam(Parameter): - def __init__(self, *args, **kwargs): + def __init__( + self, + *args: str, + **kwargs: Any, + ) -> None: super().__init__(*args, **kwargs) self._rng = np.random.default_rng() - def get_raw(self): + def get_raw(self) -> NDArray[np.float64]: assert isinstance(self.vals, Arrays) assert self.vals.shape is not None shape = self.vals.shape diff --git a/tests/dataset/dond/conftest.py b/tests/dataset/dond/conftest.py index 947b5e3610dc..c4343a05c8bf 100644 --- a/tests/dataset/dond/conftest.py +++ b/tests/dataset/dond/conftest.py @@ -1,12 +1,21 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + import matplotlib.pyplot as plt import pytest from qcodes import config, validators from qcodes.parameters import Parameter +if TYPE_CHECKING: + from collections.abc import Generator + + from _pytest._py.path import LocalPath + @pytest.fixture(autouse=True) -def set_tmp_output_dir(tmpdir): +def set_tmp_output_dir(tmpdir: LocalPath) -> Generator[None, None, None]: old_config = config.user.mainfolder try: config.user.mainfolder = str(tmpdir) @@ -16,25 +25,25 @@ def set_tmp_output_dir(tmpdir): @pytest.fixture() -def plot_close(): +def plot_close() -> Generator[None, None, None]: yield plt.close("all") @pytest.fixture() -def _param(): +def _param() -> Parameter[int]: p = Parameter("simple_parameter", set_cmd=None, get_cmd=lambda: 1) return p @pytest.fixture() -def _param_2(): +def _param_2() -> Parameter[int]: p = Parameter("simple_parameter_2", set_cmd=None, get_cmd=lambda: 2) return p @pytest.fixture() -def _param_complex(): +def _param_complex() -> Parameter[complex]: p = Parameter( "simple_complex_parameter", set_cmd=None, @@ -45,7 +54,7 @@ def _param_complex(): @pytest.fixture() -def _param_complex_2(): +def _param_complex_2() -> Parameter[complex]: p = Parameter( "simple_complex_parameter_2", set_cmd=None, @@ -56,18 +65,18 @@ def _param_complex_2(): @pytest.fixture() -def _param_set(): +def _param_set() -> Parameter[float | None]: p = Parameter("simple_setter_parameter", set_cmd=None, get_cmd=None) return p @pytest.fixture() -def _param_set_2(): +def _param_set_2() -> Parameter[float | None]: p = Parameter("simple_setter_parameter_2", set_cmd=None, get_cmd=None) return p -def _param_func(_p): +def _param_func(_p: Parameter[int]) -> Parameter[int]: """ A private utility function. """ @@ -78,15 +87,15 @@ def _param_func(_p): @pytest.fixture() -def _param_callable(_param): +def _param_callable(_param: Parameter[int]) -> Parameter[int]: return _param_func(_param) -def test_param_callable(_param_callable) -> None: +def test_param_callable(_param_callable: Parameter[int]) -> None: _param_modified = _param_callable assert _param_modified.get() == 2 @pytest.fixture() -def _string_callable(): +def _string_callable() -> str: return "Call" diff --git a/tests/dataset/dond/test_do0d.py b/tests/dataset/dond/test_do0d.py index a7e61e12f9ea..35c5d5b48f33 100644 --- a/tests/dataset/dond/test_do0d.py +++ b/tests/dataset/dond/test_do0d.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import hypothesis.strategies as hst import matplotlib.axes import numpy as np @@ -10,18 +12,27 @@ from qcodes.dataset.data_set import DataSet from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, + DummyChannelInstrument, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) from tests.dataset.conftest import ArrayshapedParam +if TYPE_CHECKING: + from pathlib import Path + + from qcodes.dataset.experiment_container import Experiment + from qcodes.parameters import Parameter + @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("period", [None, 1]) @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [True, None, False]) -def test_do0d_with_real_parameter(period, plot, plot_config) -> None: +def test_do0d_with_real_parameter( + period: float | None, plot: bool | None, plot_config: bool | None +) -> None: arrayparam = ArraySetPointParam(name="arrayparam") if plot_config is not None: @@ -39,7 +50,9 @@ def test_do0d_with_real_parameter(period, plot, plot_config) -> None: @pytest.mark.parametrize( "period, plot", [(None, True), (None, False), (1, True), (1, False)] ) -def test_do0d_with_complex_parameter(_param_complex, period, plot) -> None: +def test_do0d_with_complex_parameter( + _param_complex: "Parameter[complex]", period: float | None, plot: bool +) -> None: do0d(_param_complex, write_period=period, do_plot=plot) @@ -47,7 +60,9 @@ def test_do0d_with_complex_parameter(_param_complex, period, plot) -> None: @pytest.mark.parametrize( "period, plot", [(None, True), (None, False), (1, True), (1, False)] ) -def test_do0d_with_a_callable(_param_callable, period, plot) -> None: +def test_do0d_with_a_callable( + _param_callable: "Parameter[int]", period: float | None, plot: bool +) -> None: do0d(_param_callable, write_period=period, do_plot=plot) @@ -55,7 +70,12 @@ def test_do0d_with_a_callable(_param_callable, period, plot) -> None: @pytest.mark.parametrize( "period, plot", [(None, True), (None, False), (1, True), (1, False)] ) -def test_do0d_with_2_parameters(_param, _param_complex, period, plot) -> None: +def test_do0d_with_2_parameters( + _param: "Parameter[int]", + _param_complex: "Parameter[complex]", + period: float | None, + plot: bool, +) -> None: do0d(_param, _param_complex, write_period=period, do_plot=plot) @@ -64,31 +84,36 @@ def test_do0d_with_2_parameters(_param, _param_complex, period, plot) -> None: "period, plot", [(None, True), (None, False), (1, True), (1, False)] ) def test_do0d_with_parameter_and_a_callable( - _param_complex, _param_callable, period, plot + _param_complex: "Parameter[complex]", + _param_callable: "Parameter[int]", + period: float | None, + plot: bool, ) -> None: do0d(_param_callable, _param_complex, write_period=period, do_plot=plot) @pytest.mark.usefixtures("plot_close", "experiment") -def test_do0d_output_type_real_parameter(_param) -> None: +def test_do0d_output_type_real_parameter(_param: "Parameter[int]") -> None: data = do0d(_param) assert isinstance(data[0], DataSet) is True @pytest.mark.usefixtures("plot_close", "experiment") -def test_do0d_output_type_complex_parameter(_param_complex) -> None: +def test_do0d_output_type_complex_parameter( + _param_complex: "Parameter[complex]", +) -> None: data_complex = do0d(_param_complex) assert isinstance(data_complex[0], DataSet) is True @pytest.mark.usefixtures("plot_close", "experiment") -def test_do0d_output_type_callable(_param_callable) -> None: +def test_do0d_output_type_callable(_param_callable: "Parameter[int]") -> None: data_func = do0d(_param_callable) assert isinstance(data_func[0], DataSet) is True @pytest.mark.usefixtures("plot_close", "experiment") -def test_do0d_output_data(_param) -> None: +def test_do0d_output_data(_param: "Parameter[int]") -> None: exp = do0d(_param) data = exp[0] assert data.description.interdeps.names == (_param.name,) @@ -97,7 +122,7 @@ def test_do0d_output_data(_param) -> None: @pytest.mark.usefixtures("experiment") -def test_do0d_export_to_netcdf(_param, tmp_path) -> None: +def test_do0d_export_to_netcdf(_param: "Parameter[int]", tmp_path: "Path") -> None: dataset = do0d(_param, do_plot=False)[0] dataset.export(export_type="netcdf", path=tmp_path) @@ -111,7 +136,7 @@ def test_do0d_export_to_netcdf(_param, tmp_path) -> None: @pytest.mark.usefixtures("experiment") -def test_do0d_array_export_to_netcdf(tmp_path) -> None: +def test_do0d_array_export_to_netcdf(tmp_path: "Path") -> None: param = ArrayshapedParam( name="paramwitharrayval", vals=validators.Arrays(shape=(10,)) ) @@ -140,7 +165,13 @@ def test_do0d_array_export_to_netcdf(tmp_path) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_do0d_verify_shape( - _param, _param_complex, multiparamtype, dummyinstrument, n_points_pws + _param: "Parameter[int]", + _param_complex: "Parameter[complex]", + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -182,7 +213,9 @@ def test_do0d_parameter_with_array_vals() -> None: assert results[0].description.shapes == expected_shapes -def test_do0d_explicit_experiment(_param, experiment) -> None: +def test_do0d_explicit_experiment( + _param: "Parameter[int]", experiment: "Experiment" +) -> None: experiment_2 = new_experiment("new-exp", "no-sample") data1 = do0d(_param, do_plot=False, exp=experiment) @@ -195,13 +228,15 @@ def test_do0d_explicit_experiment(_param, experiment) -> None: @pytest.mark.usefixtures("experiment") -def test_do0d_explicit_name(_param) -> None: +def test_do0d_explicit_name(_param: "Parameter[int]") -> None: data1 = do0d(_param, do_plot=False, measurement_name="my measurement") assert data1[0].name == "my measurement" @pytest.mark.usefixtures("experiment") -def test_do0d_parameter_with_setpoints_2d(dummyinstrument) -> None: +def test_do0d_parameter_with_setpoints_2d( + dummyinstrument: DummyChannelInstrument, +) -> None: dummyinstrument.A.dummy_start(0) dummyinstrument.A.dummy_stop(10) dummyinstrument.A.dummy_n_points(10) @@ -218,7 +253,11 @@ def test_do0d_parameter_with_setpoints_2d(dummyinstrument) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_0d_output_type(_param, _param_complex, _param_callable) -> None: +def test_dond_0d_output_type( + _param: "Parameter[int]", + _param_complex: "Parameter[complex]", + _param_callable: "Parameter[int]", +) -> None: data_1 = do0d(_param) assert isinstance(data_1[0], DataSet) is True diff --git a/tests/dataset/dond/test_do1d.py b/tests/dataset/dond/test_do1d.py index 2c19c4f43fc8..fc6072af1567 100644 --- a/tests/dataset/dond/test_do1d.py +++ b/tests/dataset/dond/test_do1d.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import logging +from typing import TYPE_CHECKING import hypothesis.strategies as hst import matplotlib.axes @@ -13,6 +16,7 @@ from qcodes.dataset.data_set import DataSet from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, + DummyChannelInstrument, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, @@ -20,10 +24,15 @@ from qcodes.parameters import Parameter from tests.dataset.conftest import ArrayshapedParam +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment + @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("delay", [0, 0.1, 1]) -def test_do1d_with_real_parameter(_param_set, _param, delay) -> None: +def test_do1d_with_real_parameter( + _param_set: Parameter[float | None], _param: Parameter[int], delay: float +) -> None: start = 0 stop = 1 num_points = 1 @@ -34,7 +43,12 @@ def test_do1d_with_real_parameter(_param_set, _param, delay) -> None: @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) -def test_do1d_plot(_param_set, _param, plot, plot_config) -> None: +def test_do1d_plot( + _param_set: Parameter[float | None], + _param: Parameter[int], + plot: bool | None, + plot_config: bool | None, +) -> None: if plot_config is not None: config.dataset.dond_plot = plot_config @@ -52,7 +66,11 @@ def test_do1d_plot(_param_set, _param, plot, plot_config) -> None: @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("delay", [0, 0.1, 1]) -def test_do1d_with_complex_parameter(_param_set, _param_complex, delay) -> None: +def test_do1d_with_complex_parameter( + _param_set: Parameter[float | None], + _param_complex: Parameter[complex], + delay: float, +) -> None: start = 0 stop = 1 num_points = 1 @@ -62,7 +80,12 @@ def test_do1d_with_complex_parameter(_param_set, _param_complex, delay) -> None: @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("delay", [0, 0.1, 1]) -def test_do1d_with_2_parameter(_param_set, _param, _param_complex, delay) -> None: +def test_do1d_with_2_parameter( + _param_set: Parameter[float | None], + _param: Parameter[int], + _param_complex: Parameter[complex], + delay: float, +) -> None: start = 0 stop = 1 num_points = 1 @@ -72,7 +95,9 @@ def test_do1d_with_2_parameter(_param_set, _param, _param_complex, delay) -> Non @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("delay", [0, 0.1, 1]) -def test_do1d_output_type_real_parameter(_param_set, _param, delay) -> None: +def test_do1d_output_type_real_parameter( + _param_set: Parameter[float | None], _param: Parameter[int], delay: float +) -> None: start = 0 stop = 1 num_points = 1 @@ -82,7 +107,9 @@ def test_do1d_output_type_real_parameter(_param_set, _param, delay) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_do1d_output_data(_param, _param_set) -> None: +def test_do1d_output_data( + _param: Parameter[int], _param_set: Parameter[float | None] +) -> None: start = 0 stop = 1 num_points = 5 @@ -113,13 +140,15 @@ def test_do1d_output_data(_param, _param_set) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_do1d_verify_shape( - _param, - _param_complex, - _param_set, - multiparamtype, - dummyinstrument, - num_points, - n_points_pws, + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + num_points: int, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -156,7 +185,7 @@ def test_do1d_verify_shape( @pytest.mark.usefixtures("experiment") -def test_do1d_parameter_with_array_vals(_param_set) -> None: +def test_do1d_parameter_with_array_vals(_param_set: Parameter[float | None]) -> None: param = ArrayshapedParam( name="paramwitharrayval", vals=validators.Arrays(shape=(10,)) ) @@ -179,7 +208,11 @@ def test_do1d_parameter_with_array_vals(_param_set) -> None: assert param_data.shape == expected_shapes[name] -def test_do1d_explicit_experiment(_param_set, _param, experiment) -> None: +def test_do1d_explicit_experiment( + _param_set: Parameter[float | None], + _param: Parameter[int], + experiment: Experiment, +) -> None: start = 0 stop = 1 num_points = 5 @@ -215,7 +248,9 @@ def test_do1d_explicit_experiment(_param_set, _param, experiment) -> None: @pytest.mark.usefixtures("experiment") -def test_do1d_explicit_name(_param_set, _param) -> None: +def test_do1d_explicit_name( + _param_set: Parameter[float | None], _param: Parameter[int] +) -> None: start = 0 stop = 1 num_points = 5 @@ -235,7 +270,11 @@ def test_do1d_explicit_name(_param_set, _param) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_do1d_additional_setpoints(_param, _param_complex, _param_set) -> None: +def test_do1d_additional_setpoints( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], +) -> None: additional_setpoints = [ Parameter(f"additional_setter_parameter_{i}", set_cmd=None, get_cmd=None) for i in range(2) @@ -271,7 +310,10 @@ def test_do1d_additional_setpoints(_param, _param_complex, _param_set) -> None: @given(num_points_p1=hst.integers(min_value=1, max_value=10)) @pytest.mark.usefixtures("experiment") def test_do1d_additional_setpoints_shape( - _param, _param_complex, _param_set, num_points_p1 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + num_points_p1: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") array_shape = arrayparam.shape @@ -307,13 +349,17 @@ def test_do1d_additional_setpoints_shape( @pytest.mark.usefixtures("plot_close", "experiment") -def test_do1d_break_condition(caplog: LogCaptureFixture, _param_set, _param) -> None: +def test_do1d_break_condition( + caplog: LogCaptureFixture, + _param_set: Parameter[float | None], + _param: Parameter[int], +) -> None: start = 0 stop = 1 num_points = 5 delay = 0 - def break_condition(): + def break_condition() -> bool: return True data = do1d( diff --git a/tests/dataset/dond/test_do2d.py b/tests/dataset/dond/test_do2d.py index 3f1d8578ef53..a3a708c602d2 100644 --- a/tests/dataset/dond/test_do2d.py +++ b/tests/dataset/dond/test_do2d.py @@ -2,6 +2,10 @@ These are the basic black box tests for the doNd functions. """ +from __future__ import annotations + +from typing import TYPE_CHECKING + import hypothesis.strategies as hst import matplotlib.axes import matplotlib.pyplot as plt @@ -14,18 +18,29 @@ from qcodes.dataset.data_set import DataSet from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, + DummyChannelInstrument, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, ) from qcodes.parameters import Parameter +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment + @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize( "sweep, columns", [(False, False), (False, True), (True, False), (True, True)] ) -def test_do2d(_param, _param_complex, _param_set, _param_set_2, sweep, columns) -> None: +def test_do2d( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + sweep: bool, + columns: bool, +) -> None: start_p1 = 0 stop_p1 = 1 num_points_p1 = 1 @@ -57,7 +72,13 @@ def test_do2d(_param, _param_complex, _param_set, _param_set_2, sweep, columns) @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) -def test_do2d_plot(_param_set, _param_set_2, _param, plot, plot_config) -> None: +def test_do2d_plot( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], + plot: bool | None, + plot_config: bool | None, +) -> None: if plot_config is not None: config.dataset.dond_plot = plot_config @@ -94,7 +115,12 @@ def test_do2d_plot(_param_set, _param_set_2, _param, plot, plot_config) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_do2d_output_type(_param, _param_complex, _param_set, _param_set_2) -> None: +def test_do2d_output_type( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], +) -> None: start_p1 = 0 stop_p1 = 0.5 num_points_p1 = 1 @@ -123,7 +149,12 @@ def test_do2d_output_type(_param, _param_complex, _param_set, _param_set_2) -> N @pytest.mark.usefixtures("plot_close", "experiment") -def test_do2d_output_data(_param, _param_complex, _param_set, _param_set_2) -> None: +def test_do2d_output_data( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], +) -> None: start_p1 = 0 stop_p1 = 0.5 num_points_p1 = 5 @@ -201,17 +232,19 @@ def test_do2d_output_data(_param, _param_complex, _param_set, _param_set_2) -> N suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_do2d_verify_shape( - _param, - _param_complex, - _param_set, - _param_set_2, - multiparamtype, - dummyinstrument, - sweep, - columns, - num_points_p1, - num_points_p2, - n_points_pws, + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + sweep: bool, + columns: bool, + num_points_p1: int, + num_points_p2: int, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -280,7 +313,10 @@ def test_do2d_verify_shape( @pytest.mark.usefixtures("plot_close", "experiment") def test_do2d_additional_setpoints( - _param, _param_complex, _param_set, _param_set_2 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], ) -> None: additional_setpoints = [ Parameter(f"additional_setter_parameter_{i}", set_cmd=None, get_cmd=None) @@ -326,7 +362,12 @@ def test_do2d_additional_setpoints( @settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) @pytest.mark.usefixtures("experiment") def test_do2d_additional_setpoints_shape( - _param, _param_complex, _param_set, _param_set_2, num_points_p1, num_points_p2 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + num_points_p1: int, + num_points_p2: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") array_shape = arrayparam.shape @@ -372,7 +413,12 @@ def test_do2d_additional_setpoints_shape( assert results[0].description.shapes == expected_shapes -def test_do2d_explicit_experiment(_param_set, _param_set_2, _param, experiment) -> None: +def test_do2d_explicit_experiment( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], + experiment: Experiment, +) -> None: start_p1 = 0 stop_p1 = 0.5 num_points_p1 = 5 @@ -436,7 +482,11 @@ def test_do2d_explicit_experiment(_param_set, _param_set_2, _param, experiment) @pytest.mark.usefixtures("experiment") -def test_do2d_explicit_name(_param_set, _param_set_2, _param) -> None: +def test_do2d_explicit_name( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], +) -> None: start_p1 = 0 stop_p1 = 0.5 num_points_p1 = 5 diff --git a/tests/dataset/dond/test_dond.py b/tests/dataset/dond/test_dond.py index d79beef6a792..dc12841c423d 100644 --- a/tests/dataset/dond/test_dond.py +++ b/tests/dataset/dond/test_dond.py @@ -2,10 +2,12 @@ These are the basic black box tests for the doNd functions. """ +from __future__ import annotations + import logging import re from functools import partial -from typing import assert_type +from typing import TYPE_CHECKING, Any, assert_type import hypothesis.strategies as hst import matplotlib.axes @@ -31,6 +33,7 @@ from qcodes.dataset.dond.do_nd import _Sweeper from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, + DummyChannelInstrument, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, @@ -44,20 +47,25 @@ from qcodes.validators import Arrays, Ints from tests.dataset.conftest import ArrayshapedParam +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + from qcodes.dataset.experiment_container import Experiment + class TrackingParameter(Parameter): """Parameter that keeps track of number of get and set operations""" - def __init__(self, *args, **kwargs): + def __init__(self, *args: str, **kwargs: Any) -> None: self.set_count = 0 self.get_count = 0 super().__init__(*args, **kwargs) - def set_raw(self, value): + def set_raw(self, value: object) -> None: self.set_count += 1 self.cache._set_from_raw_value(value) - def get_raw(self): + def get_raw(self) -> object: self.get_count += 1 return self.cache.raw_value @@ -71,16 +79,16 @@ class GetReturnsCountParameter(Parameter): Allows you to set a value but returns the get count rather than the value""" - def __init__(self, *args, **kwargs): + def __init__(self, *args: str, **kwargs: Any) -> None: self.set_count = 0 self.get_count = 0 super().__init__(*args, **kwargs) - def set_raw(self, value): + def set_raw(self, value: object) -> None: self.set_count += 1 self.cache._set_from_raw_value(value) - def get_raw(self): + def get_raw(self) -> int: self.get_count += 1 return self.get_count @@ -89,7 +97,7 @@ def reset_count(self) -> None: self.set_count = 0 -def test_linear_sweep_get_setpoints(_param) -> None: +def test_linear_sweep_get_setpoints(_param: Parameter[int]) -> None: start = 0 stop = 1 num_points = 5 @@ -104,7 +112,12 @@ def test_linear_sweep_get_setpoints(_param) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("cache_config", [True, False]) @pytest.mark.parametrize("cache_setting", [True, False, None]) -def test_cache_config(_param, _param_2, cache_config, cache_setting) -> None: +def test_cache_config( + _param: Parameter[int], + _param_2: Parameter[int], + cache_config: bool, + cache_setting: bool | None, +) -> None: qc.config.dataset.in_memory_cache = cache_config start = 0 stop = 1 @@ -121,7 +134,9 @@ def test_cache_config(_param, _param_2, cache_config, cache_setting) -> None: assert ds.cache.live is None -def test_linear_sweep_properties(_param, _param_complex) -> None: +def test_linear_sweep_properties( + _param: Parameter[int], _param_complex: Parameter[complex] +) -> None: start = 0 stop = 1 num_points = 5 @@ -137,7 +152,9 @@ def test_linear_sweep_properties(_param, _param_complex) -> None: assert sweep_2.delay == 0 -def test_linear_sweep_parameter_class(_param, _param_complex) -> None: +def test_linear_sweep_parameter_class( + _param: Parameter[int], _param_complex: Parameter[complex] +) -> None: start = 0 stop = 1 num_points = 5 @@ -153,7 +170,7 @@ def test_linear_sweep_parameter_class(_param, _param_complex) -> None: assert isinstance(sweep_3.param, ParameterBase) -def test_log_sweep_get_setpoints(_param) -> None: +def test_log_sweep_get_setpoints(_param: Parameter[int]) -> None: start = 0 stop = 1 num_points = 5 @@ -165,7 +182,9 @@ def test_log_sweep_get_setpoints(_param) -> None: ) -def test_log_sweep_properties(_param, _param_complex) -> None: +def test_log_sweep_properties( + _param: Parameter[int], _param_complex: Parameter[complex] +) -> None: start = 0 stop = 1 num_points = 5 @@ -181,7 +200,9 @@ def test_log_sweep_properties(_param, _param_complex) -> None: assert sweep_2.delay == 0 -def test_log_sweep_parameter_class(_param, _param_complex) -> None: +def test_log_sweep_parameter_class( + _param: Parameter[int], _param_complex: Parameter[complex] +) -> None: start = 0 stop = 1 num_points = 5 @@ -197,7 +218,7 @@ def test_log_sweep_parameter_class(_param, _param_complex) -> None: assert isinstance(sweep_3.param, ParameterBase) -def test_array_sweep_get_setpoints(_param) -> None: +def test_array_sweep_get_setpoints(_param: Parameter[int]) -> None: array = np.linspace(0, 1, 5) delay = 1 sweep = ArraySweep(_param, array, delay) @@ -210,7 +231,7 @@ def test_array_sweep_get_setpoints(_param) -> None: np.testing.assert_array_equal(sweep2.get_setpoints(), np.array(array2)) -def test_array_sweep_properties(_param) -> None: +def test_array_sweep_properties(_param: Parameter[int]) -> None: array = np.linspace(0, 1, 5) delay = 1 sweep = ArraySweep(_param, array, delay) @@ -224,7 +245,9 @@ def test_array_sweep_properties(_param) -> None: assert sweep_2.delay == 0 -def test_array_sweep_parameter_class(_param, _param_complex) -> None: +def test_array_sweep_parameter_class( + _param: Parameter[int], _param_complex: Parameter[complex] +) -> None: array = np.linspace(0, 1, 5) sweep = ArraySweep(_param, array) @@ -238,7 +261,9 @@ def test_array_sweep_parameter_class(_param, _param_complex) -> None: assert isinstance(sweep_3.param, ParameterBase) -def test_dond_explicit_exp_meas_sample(_param, experiment) -> None: +def test_dond_explicit_exp_meas_sample( + _param: Parameter[int], experiment: Experiment +) -> None: experiment_2 = new_experiment("new-exp", "no-sample") data1 = dond(_param, do_plot=False, exp=experiment) @@ -263,7 +288,7 @@ def test_dond_explicit_exp_meas_sample(_param, experiment) -> None: def test_dond_multi_datasets_explicit_exp_meas_sample( - _param, _param_complex, experiment + _param: Parameter[int], _param_complex: Parameter[complex], experiment: Experiment ) -> None: experiment_2 = new_experiment("new-exp", "no-sample") @@ -295,7 +320,7 @@ def test_dond_multi_datasets_explicit_exp_meas_sample( def test_dond_multi_datasets_explicit_meas_names( - _param, _param_complex, experiment + _param: Parameter[int], _param_complex: Parameter[complex], experiment: Experiment ) -> None: data1 = dond( [_param], @@ -310,7 +335,9 @@ def test_dond_multi_datasets_explicit_meas_names( assert datasets1[1].name == "bar" -def test_dond_multi_datasets_meas_names_len_mismatch(_param, experiment) -> None: +def test_dond_multi_datasets_meas_names_len_mismatch( + _param: Parameter[int], experiment: Experiment +) -> None: with pytest.raises( ValueError, match=re.escape("Got 2 measurement names but should create 1 dataset(s)."), @@ -335,7 +362,13 @@ def test_dond_multi_datasets_meas_names_len_mismatch(_param, experiment) -> None suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_dond_0d_verify_shape( - _param, _param_complex, multiparamtype, dummyinstrument, n_points_pws + _param: Parameter[int], + _param_complex: Parameter[complex], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -395,7 +428,7 @@ def complex_get_cmd() -> np.ndarray: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_0d_output_data(_param) -> None: +def test_dond_0d_output_data(_param: Parameter[int]) -> None: exp = dond(_param) data = exp[0] assert isinstance(data, DataSetProtocol) @@ -420,7 +453,9 @@ def test_dond_0d_parameter_with_array_vals() -> None: @pytest.mark.parametrize("period", [None, 1]) @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) -def test_dond_0d_with_real_parameter(period, plot, plot_config) -> None: +def test_dond_0d_with_real_parameter( + period: float | None, plot: bool | None, plot_config: bool | None +) -> None: arrayparam = ArraySetPointParam(name="arrayparam") if plot_config is not None: @@ -435,7 +470,9 @@ def test_dond_0d_with_real_parameter(period, plot, plot_config) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_0d_parameter_with_setpoints_2d(dummyinstrument) -> None: +def test_dond_0d_parameter_with_setpoints_2d( + dummyinstrument: DummyChannelInstrument, +) -> None: dummyinstrument.A.dummy_start(0) dummyinstrument.A.dummy_stop(10) dummyinstrument.A.dummy_n_points(10) @@ -452,7 +489,7 @@ def test_dond_0d_parameter_with_setpoints_2d(dummyinstrument) -> None: @pytest.mark.usefixtures("experiment") -def test_dond_1d_parameter_with_array_vals(_param_set) -> None: +def test_dond_1d_parameter_with_array_vals(_param_set: Parameter[float | None]) -> None: param = ArrayshapedParam( name="paramwitharrayval", vals=validators.Arrays(shape=(10,)) ) @@ -490,13 +527,15 @@ def test_dond_1d_parameter_with_array_vals(_param_set) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_dond_1d_verify_shape( - _param, - _param_complex, - _param_set, - multiparamtype, - dummyinstrument, - num_points, - n_points_pws, + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + num_points: int, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -533,7 +572,11 @@ def test_dond_1d_verify_shape( @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_1d_additional_setpoints(_param, _param_complex, _param_set) -> None: +def test_dond_1d_additional_setpoints( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], +) -> None: additional_setpoints = [ Parameter(f"additional_setter_parameter_{i}", set_cmd=None, get_cmd=None) for i in range(2) @@ -560,7 +603,9 @@ def test_dond_1d_additional_setpoints(_param, _param_complex, _param_set) -> Non @settings(suppress_health_check=(HealthCheck.function_scoped_fixture,)) @given(num_points_p1=hst.integers(min_value=1, max_value=5)) @pytest.mark.usefixtures("experiment") -def test_dond_1d_additional_setpoints_shape(_param, _param_set, num_points_p1) -> None: +def test_dond_1d_additional_setpoints_shape( + _param: Parameter[int], _param_set: Parameter[float | None], num_points_p1: int +) -> None: arrayparam = ArraySetPointParam(name="arrayparam") array_shape = arrayparam.shape additional_setpoints = [ @@ -595,7 +640,12 @@ def test_dond_1d_additional_setpoints_shape(_param, _param_set, num_points_p1) - @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) -def test_dond_1d_plot(_param_set, _param, plot, plot_config) -> None: +def test_dond_1d_plot( + _param_set: Parameter[float | None], + _param: Parameter[int], + plot: bool | None, + plot_config: bool | None, +) -> None: if plot_config is not None: config.dataset.dond_plot = plot_config @@ -610,7 +660,11 @@ def test_dond_1d_plot(_param_set, _param, plot, plot_config) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_1d_output_data(_param, _param_complex, _param_set) -> None: +def test_dond_1d_output_data( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], +) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 5, 0) exp_1 = dond(sweep_1, _param, _param_complex) @@ -641,7 +695,11 @@ def test_dond_1d_output_data(_param, _param_complex, _param_set) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_1d_output_type(_param, _param_complex, _param_set) -> None: +def test_dond_1d_output_type( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], +) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 2, 0) data_1 = dond(sweep_1, _param, _param_complex) @@ -664,15 +722,17 @@ def test_dond_1d_output_type(_param, _param_complex, _param_set) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_dond_2d_verify_shape( - _param, - _param_complex, - _param_set, - _param_set_2, - multiparamtype, - dummyinstrument, - num_points_p1, - num_points_p2, - n_points_pws, + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + dummyinstrument: DummyChannelInstrument, + num_points_p1: int, + num_points_p2: int, + n_points_pws: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") multiparam = multiparamtype(name="multiparam") @@ -733,7 +793,10 @@ def test_dond_2d_verify_shape( @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_2d_additional_setpoints( - _param, _param_complex, _param_set, _param_set_2 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], ) -> None: additional_setpoints = [ Parameter(f"additional_setter_parameter_{i}", set_cmd=None, get_cmd=None) @@ -776,7 +839,12 @@ def test_dond_2d_additional_setpoints( @settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) @pytest.mark.usefixtures("experiment") def test_dond_2d_additional_setpoints_shape( - _param, _param_complex, _param_set, _param_set_2, num_points_p1, num_points_p2 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + num_points_p1: int, + num_points_p2: int, ) -> None: arrayparam = ArraySetPointParam(name="arrayparam") array_shape = arrayparam.shape @@ -821,7 +889,13 @@ def test_dond_2d_additional_setpoints_shape( @pytest.mark.usefixtures("plot_close", "experiment") @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) -def test_dond_2d_plot(_param_set, _param_set_2, _param, plot, plot_config) -> None: +def test_dond_2d_plot( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], + plot: bool | None, + plot_config: bool | None, +) -> None: if plot_config is not None: config.dataset.dond_plot = plot_config @@ -838,7 +912,12 @@ def test_dond_2d_plot(_param_set, _param_set_2, _param, plot, plot_config) -> No @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_2d_output_type(_param, _param_complex, _param_set, _param_set_2) -> None: +def test_dond_2d_output_type( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], +) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 2, 0) sweep_2 = LinSweep(_param_set_2, 0.5, 1, 2, 0) @@ -847,7 +926,12 @@ def test_dond_2d_output_type(_param, _param_complex, _param_set, _param_set_2) - @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_2d_output_data(_param, _param_complex, _param_set, _param_set_2) -> None: +def test_dond_2d_output_data( + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], +) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 5, 0) sweep_2 = LinSweep(_param_set_2, 0.5, 1, 5, 0) exp_2 = dond(sweep_1, sweep_2, _param, _param_complex) @@ -891,7 +975,10 @@ def test_dond_2d_output_data(_param, _param_complex, _param_set, _param_set_2) - @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_2d_multi_datasets_output_type( - _param, _param_complex, _param_set, _param_set_2 + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], ) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 2, 0) sweep_2 = LinSweep(_param_set_2, 0.5, 1, 2, 0) @@ -905,7 +992,11 @@ def test_dond_2d_multi_datasets_output_type( @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_2d_multi_datasets_multi_exp( - _param, _param_complex, _param_set, _param_set_2, request: FixtureRequest + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + request: FixtureRequest, ) -> None: exp1 = new_experiment("test-experiment-1", sample_name="test-sample-1") exp2 = new_experiment("test-experiment-2", sample_name="test-sample-2") @@ -928,7 +1019,11 @@ def test_dond_2d_multi_datasets_multi_exp( @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_2d_multi_datasets_multi_exp_inconsistent_raises( - _param, _param_complex, _param_set, _param_set_2, request: FixtureRequest + _param: Parameter[int], + _param_complex: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + request: FixtureRequest, ) -> None: exp1 = new_experiment("test-experiment-1", sample_name="test-sample-1") exp2 = new_experiment("test-experiment-2", sample_name="test-sample-2") @@ -951,7 +1046,12 @@ def test_dond_2d_multi_datasets_multi_exp_inconsistent_raises( @pytest.mark.parametrize("plot", [None, True, False]) @pytest.mark.parametrize("plot_config", [None, True, False]) def test_dond_2d_multiple_datasets_plot( - _param_set, _param_set_2, _param, _param_2, plot, plot_config + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], + _param_2: Parameter[int], + plot: bool | None, + plot_config: bool | None, ) -> None: if plot_config is not None: config.dataset.dond_plot = plot_config @@ -979,21 +1079,21 @@ def test_dond_2d_multiple_datasets_plot( @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_2d_multi_datasets_with_callable_output_data( - _param, - _param_2, - _param_complex, - _param_complex_2, - _param_set, - _param_set_2, - _string_callable, + _param: Parameter[int], + _param_2: Parameter[int], + _param_complex: Parameter[complex], + _param_complex_2: Parameter[complex], + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _string_callable: str, ) -> None: sweep_1 = LinSweep(_param_set, 0, 0.5, 5, 0) sweep_2 = LinSweep(_param_set_2, 0.5, 1, 5, 0) exp_1 = dond( sweep_1, sweep_2, - [_string_callable, _param, _param_complex], - [_string_callable, _param_2, _param_complex_2], + [_string_callable, _param, _param_complex], # pyright: ignore[reportArgumentType] + [_string_callable, _param_2, _param_complex_2], # pyright: ignore[reportArgumentType] ) datasets = exp_1[0] assert isinstance(datasets, tuple) @@ -1077,7 +1177,12 @@ def test_dond_2d_multi_datasets_with_callable_output_data( @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_together_sweep(_param_set, _param_set_2, _param, _param_2) -> None: +def test_dond_together_sweep( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], + _param_2: Parameter[int], +) -> None: sweep_1 = LinSweep(_param_set, 0, 1, 10, 0) sweep_2 = LinSweep(_param_set_2, 1, 2, 10, 0) @@ -1105,7 +1210,11 @@ def test_dond_together_sweep(_param_set, _param_set_2, _param, _param_2) -> None @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_together_sweep_sweeper(_param_set, _param_set_2, _param) -> None: +def test_dond_together_sweep_sweeper( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], +) -> None: sweep_len = 10 delay_1 = 0.1 @@ -1400,7 +1509,7 @@ def test_dond_together_sweep_sweeper_combined_lists() -> None: n_points_1=hst.integers(min_value=1, max_value=500), n_points_2=hst.integers(min_value=1, max_value=500), ) -def test_together_sweep_validation(n_points_1, n_points_2) -> None: +def test_together_sweep_validation(n_points_1: int, n_points_2: int) -> None: a = ManualParameter("a", initial_value=0) b = ManualParameter("b", initial_value=0) sweepA = LinSweep(a, 0, 3, n_points_1) @@ -1531,7 +1640,9 @@ def test_dond_together_sweep_sweeper_wrong_mp_in_dataset_dependencies() -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_together_sweep_parameter_with_setpoints(dummyinstrument) -> None: +def test_dond_together_sweep_parameter_with_setpoints( + dummyinstrument: DummyChannelInstrument, +) -> None: outer_shape = 10 inner_shape = 15 @@ -1584,7 +1695,7 @@ def test_dond_together_sweep_parameter_with_setpoints(dummyinstrument) -> None: @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_together_sweep_parameter_with_setpoints_explicit_mapping( - dummyinstrument, + dummyinstrument: DummyChannelInstrument, ) -> None: outer_shape = 10 inner_shape = 15 @@ -1640,7 +1751,7 @@ def test_dond_together_sweep_parameter_with_setpoints_explicit_mapping( @pytest.mark.usefixtures("plot_close", "experiment") def test_dond_together_sweep_parameter_with_setpoints_explicit_mapping_and_callable( - dummyinstrument, + dummyinstrument: DummyChannelInstrument, ) -> None: outer_shape = 10 inner_shape = 15 @@ -1696,7 +1807,11 @@ def test_dond_together_sweep_parameter_with_setpoints_explicit_mapping_and_calla @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_sweeper_combinations(_param_set, _param_set_2, _param) -> None: +def test_dond_sweeper_combinations( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], +) -> None: outer_shape = 10 inner_shape = 15 @@ -1763,7 +1878,7 @@ def test_error_measured_grouped_and_not_grouped() -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_post_action(mocker) -> None: +def test_post_action(mocker: MockerFixture) -> None: param_1 = ManualParameter("param_1", initial_value=0.0) param_2 = ManualParameter("param_2", initial_value=0.0) @@ -1797,7 +1912,11 @@ def test_default_log_info(caplog: LogCaptureFixture) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_get_after_set(_param_set, _param_set_2, _param) -> None: +def test_dond_get_after_set( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], +) -> None: n_points = 10 a = TrackingParameter("a", initial_value=0) @@ -1830,7 +1949,11 @@ def test_dond_get_after_set(_param_set, _param_set_2, _param) -> None: @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_get_after_set_stores_get_value(_param_set, _param_set_2, _param) -> None: +def test_dond_get_after_set_stores_get_value( + _param_set: Parameter[float | None], + _param_set_2: Parameter[float | None], + _param: Parameter[int], +) -> None: n_points = 11 a = GetReturnsCountParameter("a", initial_value=0) @@ -1858,7 +1981,9 @@ def test_dond_get_after_set_stores_get_value(_param_set, _param_set_2, _param) - @pytest.mark.usefixtures("plot_close", "experiment") -def test_dond_return_type(_param_set, _param) -> None: +def test_dond_return_type( + _param_set: Parameter[float | None], _param: Parameter[int] +) -> None: n_points = 11 # test that with squeeze=False we get MultiAxesTupleListWithDataSet as the return type diff --git a/tests/dataset/dond/test_dond_keyboard_interrupts.py b/tests/dataset/dond/test_dond_keyboard_interrupts.py index 146a19a31dfe..91345a134c2f 100644 --- a/tests/dataset/dond/test_dond_keyboard_interrupts.py +++ b/tests/dataset/dond/test_dond_keyboard_interrupts.py @@ -1,9 +1,14 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.dataset.dond.do_nd_utils import BreakConditionInterrupt, catch_interrupts +if TYPE_CHECKING: + from collections.abc import Iterator + -def test_catch_interrupts(): +def test_catch_interrupts() -> None: # Test normal execution (no interrupt) with catch_interrupts() as get_interrupt: assert get_interrupt() is None @@ -41,7 +46,7 @@ def test_catch_interrupts(): assert isinstance(get_interrupt(), BreakConditionInterrupt) -def test_catch_interrupts_in_loops(): +def test_catch_interrupts_in_loops() -> None: # Test interruption in a simple loop loop_count = 0 with pytest.raises(KeyboardInterrupt): # noqa: PT012 @@ -68,8 +73,8 @@ def test_catch_interrupts_in_loops(): assert inner_count == 5 -def test_catch_interrupts_simulated_sweeps(): - def simulated_sweep(interrupt_at=None): +def test_catch_interrupts_simulated_sweeps() -> None: + def simulated_sweep(interrupt_at: int | None = None) -> "Iterator[int]": for i in range(5): with catch_interrupts(): if i == interrupt_at: diff --git a/tests/dataset/helper_functions.py b/tests/dataset/helper_functions.py index a4c2ad837493..9c4f20b0caf7 100644 --- a/tests/dataset/helper_functions.py +++ b/tests/dataset/helper_functions.py @@ -8,6 +8,9 @@ import pandas as pd from numpy.testing import assert_array_equal +if TYPE_CHECKING: + from numpy.typing import NDArray + if TYPE_CHECKING: from collections.abc import Collection, Hashable, Mapping, Sequence @@ -70,8 +73,8 @@ def verify_data_dict_for_single_param( datadict: dict[str, np.ndarray], names: Sequence[str], shapes: Sequence[tuple[int, ...]], - values, -): + values: Sequence[NDArray[np.generic]], +) -> None: # check that there are no unexpected elements in the dict key_names = list(datadict.keys()) assert set(key_names) == set(names) @@ -89,8 +92,8 @@ def verify_dataframe_for_single_param( dataframe: pd.DataFrame, names: Sequence[str], shapes: Sequence[tuple[int, ...]], - values, -): + values: Sequence[NDArray[np.generic]], +) -> None: # check that the dataframe has the same elements as index and columns pandas_index_names = list(dataframe.index.names) pandas_column_names = list(dataframe) diff --git a/tests/dataset/measurement/test_measurement_context_manager.py b/tests/dataset/measurement/test_measurement_context_manager.py index bac839bb6287..d42fdaaa2cba 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 TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, Literal import hypothesis.strategies as hst import numpy as np @@ -41,10 +41,18 @@ from tests.common import retry_until_does_not_throw if TYPE_CHECKING: - from qcodes.instrument_drivers.mock_instruments import DummyInstrument + from pytest import TempPathFactory + from pytest_mock import MockerFixture + + from qcodes.instrument_drivers.mock_instruments import ( + DummyChannelInstrument, + DummyInstrument, + ) -def test_log_messages(caplog: LogCaptureFixture, meas_with_registered_param) -> None: +def test_log_messages( + caplog: LogCaptureFixture, meas_with_registered_param: Measurement +) -> None: caplog.set_level(logging.INFO) with meas_with_registered_param.run(): @@ -56,7 +64,7 @@ def test_log_messages(caplog: LogCaptureFixture, meas_with_registered_param) -> def test_log_includes_extra_info( - caplog: LogCaptureFixture, meas_with_registered_param + caplog: LogCaptureFixture, meas_with_registered_param: Measurement ) -> None: caplog.set_level(logging.INFO) meas_with_registered_param._extra_log_info = "some extra info" @@ -67,7 +75,9 @@ def test_log_includes_extra_info( @pytest.mark.usefixtures("experiment") -def test_register_parameter_arg_types(DAC, DMM): +def test_register_parameter_arg_types( + DAC: DummyInstrument, DMM: DummyInstrument +) -> None: """Test basis and setpoints argument types.""" meas = Measurement() meas.register_parameter(DAC.ch1) @@ -91,7 +101,7 @@ def test_register_parameter_arg_types(DAC, DMM): meas.register_parameter(DMM.v1, setpoints=(DAC.ch1, 3)) # type: ignore[arg-type] -def test_register_parameter_numbers(DAC, DMM) -> None: +def test_register_parameter_numbers(DAC: DummyInstrument, DMM: DummyInstrument) -> None: """ Test the registration of scalar QCoDeS parameters """ @@ -157,7 +167,7 @@ def test_register_parameter_numbers(DAC, DMM) -> None: meas.register_parameter(DMM.v1, setpoints=(DAC.ch2,)) -def test_register_custom_parameter(DAC) -> None: +def test_register_custom_parameter(DAC: DummyInstrument) -> None: """ Test the registration of custom parameters """ @@ -246,7 +256,7 @@ def test_register_delegate_parameters_with_late_source() -> None: assert meas.parameters["x"].type == "numeric" -def test_register_delegate_parameters_with_late_source_chain(): +def test_register_delegate_parameters_with_late_source_chain() -> None: x_param = Parameter("x", set_cmd=None, get_cmd=None) complex_param = Parameter( @@ -268,7 +278,7 @@ def test_register_delegate_parameters_with_late_source_chain(): assert meas.parameters["x"].type == "numeric" -def test_unregister_parameter(DAC, DMM) -> None: +def test_unregister_parameter(DAC: DummyInstrument, DMM: DummyInstrument) -> None: """ Test the unregistering of parameters. """ @@ -310,7 +320,7 @@ def test_unregister_parameter(DAC, DMM) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -def test_mixing_array_and_numeric(DAC, bg_writing) -> None: +def test_mixing_array_and_numeric(DAC: DummyInstrument, bg_writing: bool) -> None: """ Test that mixing array and numeric types is okay """ @@ -326,7 +336,9 @@ def test_mixing_array_and_numeric(DAC, bg_writing) -> None: ) -def test_measurement_name_default(experiment, DAC, DMM) -> None: +def test_measurement_name_default( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> None: fmt = experiment.format_string exp_id = experiment.exp_id @@ -347,7 +359,9 @@ def test_measurement_name_default(experiment, DAC, DMM) -> None: assert ds.name == default_name -def test_measurement_name_changed_via_attribute(experiment, DAC, DMM) -> None: +def test_measurement_name_changed_via_attribute( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> None: fmt = experiment.format_string exp_id = experiment.exp_id @@ -368,7 +382,9 @@ def test_measurement_name_changed_via_attribute(experiment, DAC, DMM) -> None: assert ds.name == name -def test_measurement_name_set_as_argument(experiment, DAC, DMM) -> None: +def test_measurement_name_set_as_argument( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> None: fmt = experiment.format_string exp_id = experiment.exp_id @@ -391,7 +407,7 @@ def test_measurement_name_set_as_argument(experiment, DAC, DMM) -> None: @settings(deadline=None) @given(wp=hst.one_of(hst.integers(), hst.floats(allow_nan=False), hst.text())) @pytest.mark.usefixtures("empty_temp_db") -def test_setting_write_period(wp) -> None: +def test_setting_write_period(wp: float | str) -> None: new_experiment("firstexp", sample_name="no sample") meas = Measurement() meas.register_custom_parameter(name="dummy") @@ -413,7 +429,7 @@ def test_setting_write_period(wp) -> None: @settings(deadline=None) @given(wp=hst.one_of(hst.integers(), hst.floats(allow_nan=False), hst.text())) @pytest.mark.usefixtures("experiment") -def test_setting_write_period_from_config(wp) -> None: +def test_setting_write_period_from_config(wp: float | str) -> None: qc.config.dataset.write_period = wp if isinstance(wp, str) or wp < 1e-3: @@ -429,7 +445,7 @@ def test_setting_write_period_from_config(wp) -> None: @pytest.mark.parametrize("write_in_background", [True, False]) @pytest.mark.usefixtures("experiment") -def test_setting_write_in_background_from_config(write_in_background) -> None: +def test_setting_write_in_background_from_config(write_in_background: bool) -> None: qc.config.dataset.write_in_background = write_in_background meas = Measurement() @@ -441,7 +457,7 @@ def test_setting_write_in_background_from_config(write_in_background) -> None: @pytest.mark.usefixtures("experiment") -def test_method_chaining(DAC) -> None: +def test_method_chaining(DAC: DummyInstrument) -> None: ( Measurement() .register_parameter(DAC.ch1) @@ -455,11 +471,11 @@ def test_method_chaining(DAC) -> None: @pytest.mark.usefixtures("experiment") @settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) @given(words=hst.lists(elements=hst.text(), min_size=4, max_size=10)) -def test_enter_and_exit_actions(DAC, words) -> None: +def test_enter_and_exit_actions(DAC: DummyInstrument, words: list[str]) -> None: # we use a list to check that the functions executed # in the correct order - def action(lst, word): + def action(lst: list[str], word: str) -> None: lst.append(word) meas = Measurement() @@ -501,7 +517,11 @@ def test_subscriptions( automatically after the write_period passes after a add_result call. """ - def collect_all_results(results, length, state): + def collect_all_results( + results: list[tuple[float, ...]], + length: int, + state: dict[int, list[tuple[float, ...]]], + ) -> None: """ Updates the *state* to contain all the *results* acquired during the experiment run @@ -513,7 +533,9 @@ def collect_all_results(results, length, state): # the same length. state[length] = results - def collect_values_larger_than_7(results, length, state): + def collect_values_larger_than_7( + results: list[tuple[float, ...]], length: int, state: list[float] + ) -> None: """ Appends to the *state* only the values from *results* that are larger than 7 @@ -606,7 +628,7 @@ def assert_states_updated_from_callbacks( def test_subscribers_called_at_exiting_context_if_queue_is_not_empty( - experiment, DAC + experiment: Experiment, DAC: DummyInstrument ) -> None: """ Upon quitting the "run()" context, verify that in case the queue is @@ -615,7 +637,9 @@ def test_subscribers_called_at_exiting_context_if_queue_is_not_empty( to a number that is larger than the number of value written to the dataset. """ - def collect_x_vals(results, length, state): + def collect_x_vals( + results: list[tuple[float]], length: int, state: list[float] + ) -> None: """ Collects first elements of results tuples in *state* """ @@ -652,16 +676,22 @@ def collect_x_vals(results, length, state): @pytest.mark.serial @pytest.mark.flaky(reruns=5) -def test_subscribers_called_for_all_data_points(experiment, DAC, DMM) -> None: +def test_subscribers_called_for_all_data_points( + experiment: Experiment, DAC: DummyInstrument, DMM: DummyInstrument +) -> None: N = random.randint(2000, 3000) - def sub_get_x_vals(results, length, state): + def sub_get_x_vals( + results: list[tuple[float, float]], length: int, state: list[float] + ) -> None: """ A list of all x values """ state += [res[0] for res in results] - def sub_get_y_vals(results, length, state): + def sub_get_y_vals( + results: list[tuple[float, float]], length: int, state: list[float] + ) -> None: """ A list of all y values """ @@ -702,7 +732,13 @@ def sub_get_y_vals(results, length, state): get_values=hst.lists(elements=hst.floats(), min_size=20, max_size=20), ) def test_datasaver_scalars( - experiment, DAC, DMM, set_values, get_values, breakpoint, write_period + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + set_values: list[float], + get_values: list[float], + breakpoint: int, + write_period: float, ) -> None: no_of_runs = len(experiment) @@ -811,7 +847,7 @@ class SomeMeasurementException(Exception): @settings(max_examples=10, deadline=None) @given(N=hst.integers(min_value=2, max_value=500)) @pytest.mark.usefixtures("empty_temp_db") -def test_datasaver_arrays_lists_tuples(bg_writing, N) -> None: +def test_datasaver_arrays_lists_tuples(bg_writing: bool, N: int) -> None: new_experiment("firstexp", sample_name="no sample") meas = Measurement() @@ -894,7 +930,7 @@ def test_datasaver_arrays_lists_tuples(bg_writing, N) -> None: @settings(max_examples=10, deadline=None) @given(N=hst.integers(min_value=2, max_value=500)) @pytest.mark.usefixtures("empty_temp_db") -def test_datasaver_numeric_and_array_paramtype(bg_writing, N) -> None: +def test_datasaver_numeric_and_array_paramtype(bg_writing: bool, N: int) -> None: """ Test saving one parameter with 'numeric' paramtype and one parameter with 'array' paramtype @@ -930,7 +966,7 @@ def test_datasaver_numeric_and_array_paramtype(bg_writing, N) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("empty_temp_db") -def test_datasaver_numeric_after_array_paramtype(bg_writing) -> None: +def test_datasaver_numeric_after_array_paramtype(bg_writing: bool) -> None: """ Test that passing values for 'array' parameter in `add_result` before passing values for 'numeric' parameter works. @@ -967,7 +1003,7 @@ def test_datasaver_numeric_after_array_paramtype(bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_datasaver_foul_input(bg_writing) -> None: +def test_datasaver_foul_input(bg_writing: bool) -> None: meas = Measurement() meas.register_custom_parameter( @@ -987,7 +1023,9 @@ def test_datasaver_foul_input(bg_writing) -> None: @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) -def test_datasaver_unsized_arrays(N, storage_type, bg_writing) -> None: +def test_datasaver_unsized_arrays( + N: int, storage_type: Literal["numeric", "array"], bg_writing: bool +) -> None: new_experiment("firstexp", sample_name="no sample") meas = Measurement() @@ -1048,7 +1086,14 @@ def test_datasaver_unsized_arrays(N, storage_type, bg_writing) -> None: @pytest.mark.parametrize("param_type", ["np_array", "tuple", "list"]) @pytest.mark.parametrize("storage_type", ["numeric", "array"]) def test_datasaver_arrayparams( - SpectrumAnalyzer, DAC, N, M, param_type, storage_type, seed, bg_writing + SpectrumAnalyzer: DummyInstrument, + DAC: DummyInstrument, + N: int, + M: int, + param_type: Literal["np_array", "tuple", "list"], + storage_type: Literal["numeric", "array"], + seed: int, + bg_writing: bool, ) -> None: """ Test that data is stored correctly for array parameters that @@ -1130,7 +1175,11 @@ def test_datasaver_arrayparams( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_array_parameters_channel( - channel_array_instrument, DAC, N, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + N: int, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: meas = Measurement() @@ -1197,7 +1246,11 @@ def test_datasaver_array_parameters_channel( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints( - channel_array_instrument, DAC, n, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + n: int, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: chan = channel_array_instrument.A param = chan.dummy_parameter_with_setpoints @@ -1274,7 +1327,11 @@ def test_datasaver_parameter_with_setpoints( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_explicitly_expanded( - channel_array_instrument, DAC, n, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + n: int, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: chan = channel_array_instrument.A param = chan.dummy_parameter_with_setpoints @@ -1343,7 +1400,7 @@ def test_datasaver_parameter_with_setpoints_explicitly_expanded( @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_that_are_different_raises( - channel_array_instrument, DAC + channel_array_instrument: DummyChannelInstrument, DAC: DummyInstrument ) -> None: chan = channel_array_instrument.A param = chan.dummy_parameter_with_setpoints_2d @@ -1383,7 +1440,10 @@ def test_datasaver_parameter_with_setpoints_that_are_different_raises( @given(n=hst.integers(min_value=5, max_value=500)) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_complex( - channel_array_instrument, DAC, n, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + n: int, + bg_writing: bool, ) -> None: chan = channel_array_instrument.A param = chan.dummy_parameter_with_setpoints_complex @@ -1441,7 +1501,10 @@ def test_datasaver_parameter_with_setpoints_complex( @given(n=hst.integers(min_value=5, max_value=500)) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_complex_explicitly_expanded( - channel_array_instrument, DAC, n, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + n: int, + bg_writing: bool, ) -> None: chan = channel_array_instrument.A param = chan.dummy_parameter_with_setpoints_complex @@ -1494,7 +1557,10 @@ def test_datasaver_parameter_with_setpoints_complex_explicitly_expanded( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_missing_reg_raises( - channel_array_instrument, DAC, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: """ Test that if for whatever reason new setpoints are added after @@ -1537,7 +1603,10 @@ def test_datasaver_parameter_with_setpoints_missing_reg_raises( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_reg_but_missing_validator( - channel_array_instrument, DAC, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: """ Test that if for whatever reason the setpoints are removed between @@ -1594,7 +1663,10 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing_validator( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_parameter_with_setpoints_reg_but_missing( - channel_array_instrument, DAC, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: """ Test that if for whatever reason the setpoints of a QCoDeS parameter are @@ -1636,7 +1708,11 @@ def test_datasaver_parameter_with_setpoints_reg_but_missing( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.parametrize("bg_writing", [True, False]) def test_datasaver_array_parameters_array( - channel_array_instrument, DAC, N, storage_type, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + N: int, + storage_type: Literal["numeric", "array"], + bg_writing: bool, ) -> None: """ Test that storing array parameters inside a loop works as expected @@ -1722,7 +1798,10 @@ def test_datasaver_array_parameters_array( @given(N=hst.integers(min_value=5, max_value=500)) @pytest.mark.usefixtures("experiment") def test_datasaver_complex_array_parameters_array( - channel_array_instrument, DAC, N, bg_writing + channel_array_instrument: DummyChannelInstrument, + DAC: DummyInstrument, + N: int, + bg_writing: bool, ) -> None: """ Test that storing a complex array parameters inside a loop with the sqlite @@ -1783,7 +1862,7 @@ def test_datasaver_complex_array_parameters_array( @pytest.mark.parametrize("bg_writing", [True, False]) -def test_datasaver_multidim_array(experiment, bg_writing) -> None: +def test_datasaver_multidim_array(experiment: Experiment, bg_writing: bool) -> None: """ Test that inserting multidim parameters as arrays works as expected """ @@ -1834,7 +1913,12 @@ def test_datasaver_multidim_array(experiment, bg_writing) -> None: @pytest.mark.parametrize("export", [True, False]) @pytest.mark.parametrize("export_type", [DataExportType.CSV, DataExportType.NETCDF]) def test_datasaver_export( - experiment, bg_writing, tmp_path_factory, export, export_type, mocker + experiment: Experiment, + bg_writing: bool, + tmp_path_factory: TempPathFactory, + export: bool, + export_type: DataExportType, + mocker: MockerFixture, ) -> None: """ Test export data to csv after measurement ends @@ -1894,7 +1978,7 @@ def test_datasaver_export( @pytest.mark.parametrize("bg_writing", [True, False]) -def test_datasaver_multidim_numeric(experiment, bg_writing) -> None: +def test_datasaver_multidim_numeric(experiment: Experiment, bg_writing: bool) -> None: """ Test that inserting multidim parameters as numeric works as expected """ @@ -1935,7 +2019,7 @@ def test_datasaver_multidim_numeric(experiment, bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_multidimarrayparameter_as_array( - SpectrumAnalyzer, bg_writing + SpectrumAnalyzer: DummyInstrument, bg_writing: bool ) -> None: """ Test that inserting multidim Arrrayparameters as array works as expected @@ -1982,7 +2066,7 @@ def test_datasaver_multidimarrayparameter_as_array( @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_multidimarrayparameter_as_numeric( - SpectrumAnalyzer, bg_writing + SpectrumAnalyzer: DummyInstrument, bg_writing: bool ) -> None: """ Test that storing a multidim Array parameter as numeric unravels the @@ -2029,7 +2113,7 @@ def test_datasaver_multidimarrayparameter_as_numeric( @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_multi_parameters_scalar( - channel_array_instrument, bg_writing + channel_array_instrument: DummyChannelInstrument, bg_writing: bool ) -> None: """ Test that we can register multiparameters that are scalar. @@ -2056,7 +2140,9 @@ def test_datasaver_multi_parameters_scalar( @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_datasaver_multi_parameters_array(channel_array_instrument, bg_writing) -> None: +def test_datasaver_multi_parameters_array( + channel_array_instrument: DummyChannelInstrument, bg_writing: bool +) -> None: """ Test that we can register multiparameters that are array like. """ @@ -2099,7 +2185,7 @@ def test_datasaver_multi_parameters_array(channel_array_instrument, bg_writing) @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_2d_multi_parameters_array( - channel_array_instrument, bg_writing + channel_array_instrument: DummyChannelInstrument, bg_writing: bool ) -> None: """ Test that we can register multiparameters that are array like and 2D. @@ -2166,7 +2252,9 @@ def test_datasaver_2d_multi_parameters_array( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @settings(deadline=None, max_examples=10) @given(Ns=hst.lists(hst.integers(2, 10), min_size=2, max_size=5)) -def test_datasaver_arrays_of_different_length(storage_type, Ns, bg_writing) -> None: +def test_datasaver_arrays_of_different_length( + storage_type: Literal["numeric", "array"], Ns: list[int], bg_writing: bool +) -> None: """ Test that we can save arrays of different length in a single call to datasaver.add_result @@ -2210,7 +2298,9 @@ def test_datasaver_arrays_of_different_length(storage_type, Ns, bg_writing) -> N @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_complex_num(complex_num_instrument, bg_writing) -> None: +def test_save_complex_num( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: """ Test that we can save various parameters mixed with complex parameters """ @@ -2297,7 +2387,9 @@ def test_save_complex_num(complex_num_instrument, bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_and_reload_complex_standalone(complex_num_instrument, bg_writing) -> None: +def test_save_and_reload_complex_standalone( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: param = complex_num_instrument.complex_num complex_num_instrument.setpoint(1) Parameter("test", set_cmd=None, get_cmd=lambda: 1 + 1j, vals=vals.ComplexNumbers()) @@ -2315,7 +2407,9 @@ def test_save_and_reload_complex_standalone(complex_num_instrument, bg_writing) @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_complex_num_setpoints(complex_num_instrument, bg_writing) -> None: +def test_save_complex_num_setpoints( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: """ Test that we can save a parameter with complex setpoints """ @@ -2343,7 +2437,9 @@ def test_save_complex_num_setpoints(complex_num_instrument, bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_complex_num_setpoints_array(complex_num_instrument, bg_writing) -> None: +def test_save_complex_num_setpoints_array( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: """ Test that we can save an array parameter with complex setpoints """ @@ -2382,7 +2478,9 @@ def test_save_complex_num_setpoints_array(complex_num_instrument, bg_writing) -> @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_complex_as_num_raises(complex_num_instrument, bg_writing) -> None: +def test_save_complex_as_num_raises( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: setparam = complex_num_instrument.setpoint param = complex_num_instrument.complex_num meas = Measurement() @@ -2403,7 +2501,9 @@ def test_save_complex_as_num_raises(complex_num_instrument, bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_save_numeric_as_complex_raises(complex_num_instrument, bg_writing) -> None: +def test_save_numeric_as_complex_raises( + complex_num_instrument: DummyInstrument, bg_writing: bool +) -> None: setparam = complex_num_instrument.setpoint param = complex_num_instrument.complex_num meas = Measurement() @@ -2421,7 +2521,7 @@ def test_save_numeric_as_complex_raises(complex_num_instrument, bg_writing) -> N datasaver.add_result((setparam, setparam()), (param, setparam())) -def test_parameter_inference(channel_array_instrument) -> None: +def test_parameter_inference(channel_array_instrument: DummyChannelInstrument) -> None: chan = channel_array_instrument.channels[0] # default values assert Measurement._infer_paramtype(chan.temperature, None) == "numeric" @@ -2457,7 +2557,7 @@ def test_parameter_inference(channel_array_instrument) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") -def test_adding_parents(bg_writing, DAC) -> None: +def test_adding_parents(bg_writing: bool, DAC: DummyInstrument) -> None: """ Test that we can register a DataSet as the parent of another DataSet as created by the Measurement diff --git a/tests/dataset/measurement/test_register_name.py b/tests/dataset/measurement/test_register_name.py index ba01b97b935b..9d88ce4da11f 100644 --- a/tests/dataset/measurement/test_register_name.py +++ b/tests/dataset/measurement/test_register_name.py @@ -10,7 +10,7 @@ @pytest.mark.usefixtures("experiment") -def test_register_name_with_manual_parameters(): +def test_register_name_with_manual_parameters() -> None: indep_param = ManualParameter( "indep_param", initial_value=1, register_name="renamed_indep_param" ) @@ -26,7 +26,7 @@ def test_register_name_with_manual_parameters(): @pytest.mark.usefixtures("experiment") -def test_register_name_with_pws(): +def test_register_name_with_pws() -> None: setpoints_param = Parameter( name="setpoints_param", get_cmd=partial(np.linspace, 0, 1, 101), @@ -51,7 +51,7 @@ def test_register_name_with_pws(): assert paramspecs[1].name in ("renamed_setpoints", "renamed_meas_param") -def test_register_name_utils(): +def test_register_name_utils() -> None: indep_param = ManualParameter( "indep_param", initial_value=1, register_name="renamed_indep_param" ) diff --git a/tests/dataset/measurement/test_self_registering_parameters.py b/tests/dataset/measurement/test_self_registering_parameters.py index 055b85232552..2f764a1a7981 100644 --- a/tests/dataset/measurement/test_self_registering_parameters.py +++ b/tests/dataset/measurement/test_self_registering_parameters.py @@ -37,7 +37,9 @@ def dependent_parameters() -> ( yield dep1, indep1, indep2 -def test_registering_control_param_registers_components(control_parameters) -> None: +def test_registering_control_param_registers_components( + control_parameters: tuple[ManualParameter, ManualParameter, ManualParameter], +) -> None: control1, comp1, comp2 = control_parameters meas = Measurement() meas.register_parameter(control1) @@ -46,7 +48,9 @@ def test_registering_control_param_registers_components(control_parameters) -> N assert comp2 in meas._registered_parameters -def test_registering_component_param_registers_control(control_parameters) -> None: +def test_registering_component_param_registers_control( + control_parameters: tuple[ManualParameter, ManualParameter, ManualParameter], +) -> None: control1, comp1, comp2 = control_parameters meas = Measurement() meas.register_parameter(comp1) @@ -55,7 +59,9 @@ def test_registering_component_param_registers_control(control_parameters) -> No assert comp2 in meas._registered_parameters -def test_registering_dependent_param_registers_indeps(dependent_parameters) -> None: +def test_registering_dependent_param_registers_indeps( + dependent_parameters: tuple[ManualParameter, ManualParameter, ManualParameter], +) -> None: dep1, indep1, indep2 = dependent_parameters meas = Measurement() meas.register_parameter(dep1) @@ -65,7 +71,9 @@ def test_registering_dependent_param_registers_indeps(dependent_parameters) -> N # Note, registering indep1 is not expected to also register dep1 automatically -def test_registering_chain_of_control_parameters(control_parameters) -> None: +def test_registering_chain_of_control_parameters( + control_parameters: tuple[ManualParameter, ManualParameter, ManualParameter], +) -> None: control1, comp1, comp2 = control_parameters comp11 = ManualParameter("comp11") comp12 = ManualParameter("comp12") @@ -89,7 +97,9 @@ def test_registering_chain_of_control_parameters(control_parameters) -> None: assert comp22 in meas._registered_parameters -def test_registering_dependent_param_with_setpoints(dependent_parameters) -> None: +def test_registering_dependent_param_with_setpoints( + dependent_parameters: tuple[ManualParameter, ManualParameter, ManualParameter], +) -> None: dep1, indep1, indep2 = dependent_parameters setpoints1 = ManualParameter("setpoints1") setpoints2 = ManualParameter("setpoints2") diff --git a/tests/dataset/measurement/test_self_unpacking.py b/tests/dataset/measurement/test_self_unpacking.py index 3a39a12fc274..0f1e21fc71d8 100644 --- a/tests/dataset/measurement/test_self_unpacking.py +++ b/tests/dataset/measurement/test_self_unpacking.py @@ -21,6 +21,7 @@ from collections.abc import Generator from qcodes.dataset.data_set_protocol import ValuesType + from qcodes.dataset.experiment_container import Experiment from qcodes.parameters.parameter_base import ParameterBase @@ -62,7 +63,12 @@ def controlling_parameters() -> ( yield control1, comp1, comp2 -def test_add_result_self_unpack(controlling_parameters, experiment): +def test_add_result_self_unpack( + controlling_parameters: tuple[ + ControllingParameter, ManualParameter, ManualParameter + ], + experiment: "Experiment", +) -> None: control1, comp1, comp2 = controlling_parameters meas1 = ManualParameter("meas1") @@ -93,7 +99,12 @@ def test_add_result_self_unpack(controlling_parameters, experiment): assert meas1_data["comp2"] == pytest.approx(np.linspace(10, 9, 11)) -def test_add_result_self_unpack_with_PWS(controlling_parameters, experiment): +def test_add_result_self_unpack_with_PWS( + controlling_parameters: tuple[ + ControllingParameter, ManualParameter, ManualParameter + ], + experiment: "Experiment", +) -> None: control1, comp1, comp2 = controlling_parameters pws_setpoints = Parameter( "pws_setpoints", diff --git a/tests/dataset/measurement/test_shapes.py b/tests/dataset/measurement/test_shapes.py index b9504dd47ccd..bc1dc0790749 100644 --- a/tests/dataset/measurement/test_shapes.py +++ b/tests/dataset/measurement/test_shapes.py @@ -10,6 +10,9 @@ if TYPE_CHECKING: from pytest import LogCaptureFixture + from qcodes.dataset.experiment_container import Experiment + from qcodes.instrument_drivers.mock_instruments import DummyInstrument + @given(n_points=hst.integers(min_value=1, max_value=50)) @example(n_points=5) @@ -19,7 +22,11 @@ suppress_health_check=(HealthCheck.function_scoped_fixture,), ) def test_datasaver_1d( - experiment, DAC, DMM, caplog: "LogCaptureFixture", n_points + experiment: "Experiment", + DAC: "DummyInstrument", + DMM: "DummyInstrument", + caplog: "LogCaptureFixture", + n_points: int, ) -> None: meas = Measurement() meas.register_parameter(DAC.ch1) @@ -80,7 +87,12 @@ def test_datasaver_1d( ) @example(n_points_1=5, n_points_2=10) def test_datasaver_2d( - experiment, DAC, DMM, caplog: "LogCaptureFixture", n_points_1, n_points_2 + experiment: "Experiment", + DAC: "DummyInstrument", + DMM: "DummyInstrument", + caplog: "LogCaptureFixture", + n_points_1: int, + n_points_2: int, ) -> None: meas = Measurement() meas.register_parameter(DAC.ch1) diff --git a/tests/dataset/test__get_data_from_ds.py b/tests/dataset/test__get_data_from_ds.py index 9111bad1c125..022100f21523 100644 --- a/tests/dataset/test__get_data_from_ds.py +++ b/tests/dataset/test__get_data_from_ds.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import hypothesis.strategies as hst import numpy as np import pytest @@ -13,8 +15,18 @@ from qcodes.dataset.measurements import Measurement from qcodes.parameters import ManualParameter, ParamSpecBase +if TYPE_CHECKING: + from pathlib import Path + + from qcodes.dataset.data_set import DataSet + from qcodes.dataset.experiment_container import Experiment + from qcodes.instrument_drivers.mock_instruments import ( + DummyChannelInstrument, + DummyInstrument, + ) -def test_get_data_by_id_order(dataset) -> None: + +def test_get_data_by_id_order(dataset: "DataSet") -> None: """ Test that the added values of setpoints end up associated with the correct setpoint parameter, irrespective of the ordering of those setpoint @@ -52,7 +64,7 @@ def test_get_data_by_id_order(dataset) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_multidimarrayparameter_as_array( - SpectrumAnalyzer, bg_writing + SpectrumAnalyzer: "DummyInstrument", bg_writing: "bool" ) -> None: array_param = SpectrumAnalyzer.multidimspectrum meas = Measurement() @@ -101,7 +113,7 @@ def test_datasaver_multidimarrayparameter_as_array( @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.usefixtures("experiment") def test_datasaver_multidimarrayparameter_as_numeric( - SpectrumAnalyzer, bg_writing + SpectrumAnalyzer: "DummyInstrument", bg_writing: "bool" ) -> None: """ Test that storing a multidim Array parameter as numeric unravels the @@ -165,7 +177,11 @@ def test_datasaver_multidimarrayparameter_as_numeric( @pytest.mark.parametrize("storage_type", ["numeric", "array"]) @pytest.mark.usefixtures("experiment") def test_datasaver_array_parameters_channel( - channel_array_instrument, DAC, N, storage_type, bg_writing + channel_array_instrument: "DummyChannelInstrument", + DAC: "DummyInstrument", + N: "int", + storage_type: "str", + bg_writing: "bool", ) -> None: array_param = channel_array_instrument.A.dummy_array_parameter meas = Measurement() @@ -198,7 +214,10 @@ def test_datasaver_array_parameters_channel( @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) def test_datasaver_array_parameters_array( - channel_array_instrument, DAC, N, bg_writing + channel_array_instrument: "DummyChannelInstrument", + DAC: "DummyInstrument", + N: "int", + bg_writing: "bool", ) -> None: """ Test that storing array parameters inside a loop works as expected @@ -243,7 +262,7 @@ def test_datasaver_array_parameters_array( @pytest.mark.parametrize("bg_writing", [True, False]) -def test_datasaver_multidim_array(experiment, bg_writing) -> None: +def test_datasaver_multidim_array(experiment: "Experiment", bg_writing: "bool") -> None: """ Test that inserting multidim parameters as arrays works as expected """ @@ -290,7 +309,9 @@ def test_datasaver_multidim_array(experiment, bg_writing) -> None: @pytest.mark.parametrize("bg_writing", [True, False]) -def test_datasaver_multidim_numeric(experiment, bg_writing) -> None: +def test_datasaver_multidim_numeric( + experiment: "Experiment", bg_writing: "bool" +) -> None: """ Test that inserting multidim parameters as numeric works as expected """ @@ -330,7 +351,7 @@ def test_datasaver_multidim_numeric(experiment, bg_writing) -> None: def test_get_data_from_ds_non_unique_setpoint_after_netcdf_reload( - experiment, tmp_path + experiment: "Experiment", tmp_path: "Path" ) -> None: """ Test that _get_data_from_ds works on a dataset reloaded from netcdf when diff --git a/tests/dataset/test_concurrent_datasets.py b/tests/dataset/test_concurrent_datasets.py index c205efff3d02..56a511c7f403 100644 --- a/tests/dataset/test_concurrent_datasets.py +++ b/tests/dataset/test_concurrent_datasets.py @@ -2,13 +2,20 @@ Test that multiple datasets can coexist as expected """ +from typing import TYPE_CHECKING + import pytest from qcodes.dataset import new_experiment from qcodes.dataset.data_set import DataSet +if TYPE_CHECKING: + from qcodes.dataset.sqlite.connection import AtomicConnection + -def test_foreground_after_background_raises(empty_temp_db_connection) -> None: +def test_foreground_after_background_raises( + empty_temp_db_connection: "AtomicConnection", +) -> None: new_experiment("test", "test1", conn=empty_temp_db_connection) ds1 = DataSet(conn=empty_temp_db_connection) ds1.mark_started(start_bg_writer=True) @@ -21,7 +28,9 @@ def test_foreground_after_background_raises(empty_temp_db_connection) -> None: ds1.mark_completed() -def test_background_after_foreground_raises(empty_temp_db_connection) -> None: +def test_background_after_foreground_raises( + empty_temp_db_connection: "AtomicConnection", +) -> None: new_experiment("test", "test1", conn=empty_temp_db_connection) ds1 = DataSet(conn=empty_temp_db_connection) ds1.mark_started(start_bg_writer=False) @@ -31,7 +40,7 @@ def test_background_after_foreground_raises(empty_temp_db_connection) -> None: ds2.mark_started(start_bg_writer=True) -def test_background_twice(empty_temp_db_connection) -> None: +def test_background_twice(empty_temp_db_connection: "AtomicConnection") -> None: new_experiment("test", "test1", conn=empty_temp_db_connection) ds1 = DataSet(conn=empty_temp_db_connection) ds1.mark_started(start_bg_writer=True) @@ -44,7 +53,7 @@ def test_background_twice(empty_temp_db_connection) -> None: ds2.mark_completed() -def test_foreground_twice(empty_temp_db_connection) -> None: +def test_foreground_twice(empty_temp_db_connection: "AtomicConnection") -> None: new_experiment("test", "test1", conn=empty_temp_db_connection) ds1 = DataSet(conn=empty_temp_db_connection) ds1.mark_started(start_bg_writer=False) @@ -53,7 +62,9 @@ def test_foreground_twice(empty_temp_db_connection) -> None: ds2.mark_started(start_bg_writer=False) -def test_foreground_after_background_non_concurrent(empty_temp_db_connection) -> None: +def test_foreground_after_background_non_concurrent( + empty_temp_db_connection: "AtomicConnection", +) -> None: new_experiment("test", "test1", conn=empty_temp_db_connection) ds1 = DataSet(conn=empty_temp_db_connection) ds1.mark_started(start_bg_writer=True) diff --git a/tests/dataset/test_converters.py b/tests/dataset/test_converters.py index 579fda908056..e970618d4824 100644 --- a/tests/dataset/test_converters.py +++ b/tests/dataset/test_converters.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + from qcodes.dataset.descriptions.rundescriber import RunDescriber from qcodes.dataset.descriptions.versioning.converters import ( new_to_old, @@ -18,8 +20,14 @@ from qcodes.dataset.descriptions.versioning.serialization import from_dict_to_current from qcodes.dataset.descriptions.versioning.v0 import InterDependencies +if TYPE_CHECKING: + from qcodes.dataset.descriptions.dependencies import InterDependencies_ + from qcodes.dataset.descriptions.param_spec import ParamSpec + -def test_convert_v0_to_newer(some_paramspecs) -> None: +def test_convert_v0_to_newer( + some_paramspecs: "dict[int, dict[str, ParamSpec]]", +) -> None: pgroup1 = some_paramspecs[1] interdeps = InterDependencies( @@ -33,7 +41,7 @@ def test_convert_v0_to_newer(some_paramspecs) -> None: _assert_dicts_are_related_as_expected(v0, v1, v2) -def test_convert_v1(some_interdeps) -> None: +def test_convert_v1(some_interdeps: "list[InterDependencies_]") -> None: interdeps_ = some_interdeps[0] v1 = RunDescriberV1Dict(interdependencies=interdeps_._to_dict(), version=1) @@ -42,7 +50,7 @@ def test_convert_v1(some_interdeps) -> None: _assert_dicts_are_related_as_expected(v0, v1, v2) -def test_convert_v2(some_interdeps) -> None: +def test_convert_v2(some_interdeps: "list[InterDependencies_]") -> None: interdeps_ = some_interdeps[0] interdeps = new_to_old(interdeps_) @@ -56,7 +64,9 @@ def test_convert_v2(some_interdeps) -> None: _assert_dicts_are_related_as_expected(v0, v1, v2) -def _assert_dicts_are_related_as_expected(v0, v1, v2): +def _assert_dicts_are_related_as_expected( + v0: "RunDescriberV0Dict", v1: "RunDescriberV1Dict", v2: "RunDescriberV2Dict" +) -> "None": assert ( v1["interdependencies"] == old_to_new(InterDependencies._from_dict(v0["interdependencies"]))._to_dict() @@ -74,7 +84,9 @@ def _assert_dicts_are_related_as_expected(v0, v1, v2): assert len(v2) == 3 -def test_construct_current_rundescriber_from_v0(some_paramspecs) -> None: +def test_construct_current_rundescriber_from_v0( + some_paramspecs: "dict[int, dict[str, ParamSpec]]", +) -> None: pgroup1 = some_paramspecs[1] interdeps = InterDependencies( @@ -111,7 +123,9 @@ def _assert_v3_dicts_equal_up_to_paramspec_order( } -def test_construct_current_rundescriber_from_v1(some_interdeps) -> None: +def test_construct_current_rundescriber_from_v1( + some_interdeps: "list[InterDependencies_]", +) -> None: interdeps_ = some_interdeps[0] interdeps = new_to_old(interdeps_) @@ -129,7 +143,9 @@ def test_construct_current_rundescriber_from_v1(some_interdeps) -> None: assert rds_upgraded._to_dict() == expected_v3_dict -def test_construct_current_rundescriber_from_v2(some_interdeps) -> None: +def test_construct_current_rundescriber_from_v2( + some_interdeps: "list[InterDependencies_]", +) -> None: interdeps_ = some_interdeps[0] interdeps = new_to_old(interdeps_) @@ -152,7 +168,9 @@ def test_construct_current_rundescriber_from_v2(some_interdeps) -> None: assert rds_upgraded._to_dict() == expected_v3_dict -def test_construct_current_rundescriber_from_v3(some_interdeps) -> None: +def test_construct_current_rundescriber_from_v3( + some_interdeps: "list[InterDependencies_]", +) -> None: interdeps_ = some_interdeps[0] interdeps = new_to_old(interdeps_) @@ -168,7 +186,9 @@ def test_construct_current_rundescriber_from_v3(some_interdeps) -> None: assert rds_upgraded._to_dict() == v3 -def test_construct_current_rundescriber_from_fake_v4(some_interdeps) -> None: +def test_construct_current_rundescriber_from_fake_v4( + some_interdeps: "list[InterDependencies_]", +) -> None: interdeps_ = some_interdeps[0] interdeps = new_to_old(interdeps_) diff --git a/tests/dataset/test_data_set_cache.py b/tests/dataset/test_data_set_cache.py index 4a49e0ab60c7..893f9a231875 100644 --- a/tests/dataset/test_data_set_cache.py +++ b/tests/dataset/test_data_set_cache.py @@ -2,6 +2,7 @@ from math import ceil from string import ascii_uppercase +from typing import TYPE_CHECKING, Literal import hypothesis.strategies as hst import numpy as np @@ -12,6 +13,15 @@ from qcodes.dataset.descriptions.detect_shapes import detect_shape_of_measurement from qcodes.dataset.measurements import Measurement +if TYPE_CHECKING: + from qcodes.dataset.data_set_protocol import ParameterData + from qcodes.dataset.experiment_container import Experiment + from qcodes.instrument_drivers.mock_instruments import ( + DummyChannelInstrument, + DummyInstrument, + ) + from qcodes.parameters import Parameter + @pytest.mark.parametrize("bg_writing", [True, False]) @pytest.mark.parametrize("set_shape", [True, False]) @@ -23,13 +33,13 @@ ) @given(n_points=hst.integers(min_value=1, max_value=11)) def test_cache_standalone( - experiment, - DMM, - n_points, - bg_writing, - channel_array_instrument, - set_shape, - in_memory_cache, + experiment: Experiment, + DMM: DummyInstrument, + n_points: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + set_shape: bool, + in_memory_cache: bool, ) -> None: meas1 = Measurement() meas1.register_parameter(DMM.v1) @@ -198,15 +208,15 @@ def test_cache_standalone( ) @given(n_points=hst.integers(min_value=1, max_value=11)) def test_cache_1d( - experiment, - DAC, - DMM, - n_points, - bg_writing, - channel_array_instrument, - setpoints_type, - set_shape, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + setpoints_type: Literal["text", "numeric"], + set_shape: bool, + in_memory_cache: bool, ) -> None: setpoints_param, setpoints_values = _prepare_setpoints_1d( DAC, channel_array_instrument, n_points, setpoints_type @@ -383,14 +393,14 @@ def test_cache_1d( ) @given(n_points=hst.integers(min_value=1, max_value=101)) def test_cache_1d_every_other_point( - experiment, - DAC, - DMM, - n_points, - bg_writing, - channel_array_instrument, - setpoints_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + setpoints_type: Literal["text", "numeric"], + in_memory_cache: bool, ) -> None: setpoints_param, setpoints_values = _prepare_setpoints_1d( DAC, channel_array_instrument, n_points, setpoints_type @@ -467,14 +477,14 @@ def test_cache_1d_every_other_point( n_points_inner=hst.integers(min_value=1, max_value=11), ) def test_cache_2d( - experiment, - DAC, - DMM, - n_points_outer, - n_points_inner, - bg_writing, - channel_array_instrument, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points_outer: int, + n_points_inner: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + in_memory_cache: bool, ) -> None: meas = Measurement() @@ -535,14 +545,14 @@ def test_cache_2d( n_points_inner=hst.integers(min_value=1, max_value=11), ) def test_cache_2d_num_with_multiple_storage_types( - experiment, - DAC, - DMM, - n_points_outer, - n_points_inner, - bg_writing, - storage_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points_outer: int, + n_points_inner: int, + bg_writing: bool, + storage_type: Literal["numeric", "array"] | None, + in_memory_cache: bool, ) -> None: meas = Measurement() @@ -592,13 +602,13 @@ def test_cache_2d_num_with_multiple_storage_types( ) @given(n_points=hst.integers(min_value=1, max_value=21)) def test_cache_1d_array_in_1d( - experiment, - DAC, - channel_array_instrument, - n_points, - bg_writing, - storage_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + channel_array_instrument: DummyChannelInstrument, + n_points: int, + bg_writing: bool, + storage_type: Literal["numeric", "array"] | None, + in_memory_cache: bool, ) -> None: param = channel_array_instrument.A.dummy_array_parameter meas = Measurement() @@ -640,13 +650,13 @@ def test_cache_1d_array_in_1d( ) @given(n_points=hst.integers(min_value=1, max_value=21)) def test_cache_multiparam_in_1d( - experiment, - DAC, - channel_array_instrument, - n_points, - bg_writing, - storage_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + channel_array_instrument: DummyChannelInstrument, + n_points: int, + bg_writing: bool, + storage_type: Literal["numeric", "array"] | None, + in_memory_cache: bool, ) -> None: param = channel_array_instrument.A.dummy_2d_multi_parameter meas = Measurement() @@ -689,14 +699,14 @@ def test_cache_multiparam_in_1d( ) @given(n_points=hst.integers(min_value=1, max_value=21)) def test_cache_complex_array_param_in_1d( - experiment, - DAC, - channel_array_instrument, - n_points, - bg_writing, - storage_type, - outer_param_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + channel_array_instrument: DummyChannelInstrument, + n_points: int, + bg_writing: bool, + storage_type: Literal["array"] | None, + outer_param_type: Literal["numeric", "text"], + in_memory_cache: bool, ) -> None: param = channel_array_instrument.A.dummy_complex_array_parameter meas = Measurement() @@ -745,14 +755,14 @@ def test_cache_complex_array_param_in_1d( ) @given(n_points=hst.integers(min_value=1, max_value=11)) def test_cache_1d_shape( - experiment, - DAC, - DMM, - n_points, - bg_writing, - channel_array_instrument, - setpoints_type, - in_memory_cache, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + setpoints_type: Literal["text", "numeric"], + in_memory_cache: bool, ) -> None: setpoints_param, setpoints_values = _prepare_setpoints_1d( DAC, channel_array_instrument, n_points, setpoints_type @@ -851,15 +861,15 @@ def test_cache_1d_shape( pws_n_points=hst.integers(min_value=1, max_value=11), ) def test_cache_2d_shape( - experiment, - DAC, - DMM, - n_points_outer, - n_points_inner, - pws_n_points, - bg_writing, - channel_array_instrument, - cache_size, + experiment: Experiment, + DAC: DummyInstrument, + DMM: DummyInstrument, + n_points_outer: int, + n_points_inner: int, + pws_n_points: int, + bg_writing: bool, + channel_array_instrument: DummyChannelInstrument, + cache_size: Literal["too_large", "correct", "too_small"], ) -> None: meas = Measurement() @@ -985,8 +995,11 @@ def test_cache_2d_shape( def _assert_completed_cache_is_as_expected( - cache_data_trees, param_data_trees, flatten=False, clip=False -): + cache_data_trees: ParameterData, + param_data_trees: ParameterData, + flatten: bool = False, + clip: bool = False, +) -> None: # there is a tiny round trip loss in accuracy # when serializing float types approx_kinds = ("f", "c") @@ -1027,12 +1040,12 @@ def _assert_completed_cache_is_as_expected( def _assert_partial_cache_is_as_expected( - cache_data_trees, - expected_shapes, - n_points_measured, - param_data_trees, - cache_correct=True, -): + cache_data_trees: ParameterData, + expected_shapes: dict[str, tuple[int, ...]], + n_points_measured: int, + param_data_trees: ParameterData, + cache_correct: bool = True, +) -> None: assert sorted(cache_data_trees.keys()) == sorted(expected_shapes.keys()) # there is a tiny round trip loss in accuracy # when serializing float types @@ -1068,7 +1081,7 @@ def _assert_parameter_data_is_identical( expected: dict[str, dict[str, np.ndarray]], actual: dict[str, dict[str, np.ndarray]], shaped_partial: bool = False, -): +) -> None: assert expected.keys() == actual.keys() # there is a tiny round trip loss in accuracy # when serializing float types @@ -1112,7 +1125,12 @@ def _array_param_used_in_tree(measurement: Measurement) -> bool: return found_array -def _prepare_setpoints_1d(DAC, channel_array_instrument, n_points, setpoints_type): +def _prepare_setpoints_1d( + DAC: DummyInstrument, + channel_array_instrument: DummyChannelInstrument, + n_points: int, + setpoints_type: Literal["numeric", "text"], +) -> tuple[Parameter[float] | Parameter[str], npt.NDArray[np.float64] | list[str]]: if setpoints_type == "numeric": setpoints_param = DAC.ch1 setpoints_values = np.linspace(-1, 1, n_points) diff --git a/tests/dataset/test_database_creation_and_upgrading.py b/tests/dataset/test_database_creation_and_upgrading.py index bd27c1df3474..e9b6c18ec96e 100644 --- a/tests/dataset/test_database_creation_and_upgrading.py +++ b/tests/dataset/test_database_creation_and_upgrading.py @@ -55,6 +55,9 @@ from tests.common import error_caused_by, skip_if_no_fixtures from tests.dataset.conftest import temporarily_copied_DB +if TYPE_CHECKING: + from qcodes.dataset.data_set_protocol import DataSetProtocol + if TYPE_CHECKING: from collections.abc import Generator @@ -749,7 +752,9 @@ def test_update_existing_guids(caplog: LogCaptureFixture) -> None: _assert_loc_station(ds5, old_loc, old_ws) -def _assert_loc_station(ds, expected_loc, expected_station): +def _assert_loc_station( + ds: "DataSetProtocol", expected_loc: "int", expected_station: "int" +) -> "None": guid_dict = parse_guid(ds.guid) assert guid_dict["location"] == expected_loc assert guid_dict["work_station"] == expected_station diff --git a/tests/dataset/test_database_extract_runs.py b/tests/dataset/test_database_extract_runs.py index a4fa880ad4ec..7ded903b41a3 100644 --- a/tests/dataset/test_database_extract_runs.py +++ b/tests/dataset/test_database_extract_runs.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import os import random import re @@ -30,7 +32,7 @@ ) from qcodes.dataset.linked_datasets.links import Link from qcodes.dataset.measurements import Measurement -from qcodes.dataset.sqlite.connection import path_to_dbfile +from qcodes.dataset.sqlite.connection import AtomicConnection, path_to_dbfile from qcodes.dataset.sqlite.database import get_db_version_and_newest_available_version from qcodes.dataset.sqlite.queries import get_experiments from qcodes.instrument_drivers.mock_instruments import DummyInstrument @@ -38,11 +40,13 @@ from tests.common import error_caused_by, skip_if_no_fixtures if TYPE_CHECKING: - from collections.abc import Callable + from collections.abc import Callable, Generator + + from qcodes.dataset.descriptions.dependencies import InterDependencies_ @contextmanager -def raise_if_file_changed(path_to_file: str): +def raise_if_file_changed(path_to_file: str) -> Generator[None, None, None]: """ Context manager that raises if a file is modified. On Windows, the OS modification time resolution is 100 ns @@ -57,7 +61,7 @@ def raise_if_file_changed(path_to_file: str): @pytest.fixture(scope="function", name="inst") -def _make_inst(): +def _make_inst() -> Generator[DummyInstrument, None, None]: """ Dummy instrument for testing, ensuring that it's instance gets closed and removed from the global register of instruments, which, if not done, @@ -68,7 +72,10 @@ def _make_inst(): inst.close() -def test_missing_runs_raises(two_empty_temp_db_connections, some_interdeps) -> None: +def test_missing_runs_raises( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], +) -> None: """ Test that an error is raised if we attempt to extract a run not present in the source DB @@ -107,7 +114,10 @@ def test_missing_runs_raises(two_empty_temp_db_connections, some_interdeps) -> N extract_runs_into_db(source_path, target_path, *run_ids) -def test_basic_extraction(two_empty_temp_db_connections, some_interdeps) -> None: +def test_basic_extraction( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], +) -> None: source_conn, target_conn = two_empty_temp_db_connections source_path = path_to_dbfile(source_conn) @@ -198,7 +208,10 @@ def test_basic_extraction(two_empty_temp_db_connections, some_interdeps) -> None extract_runs_into_db(source_path, target_path, source_dataset.run_id) -def test_real_dataset_1d(two_empty_temp_db_connections, inst) -> None: +def test_real_dataset_1d( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + inst: DummyInstrument, +) -> None: source_conn, target_conn = two_empty_temp_db_connections source_path = path_to_dbfile(source_conn) @@ -226,7 +239,10 @@ def test_real_dataset_1d(two_empty_temp_db_connections, inst) -> None: assert_array_equal(source_data_vals, target_data_vals) -def test_real_dataset_1d_pathlib_path(two_empty_temp_db_connections, inst) -> None: +def test_real_dataset_1d_pathlib_path( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + inst: DummyInstrument, +) -> None: source_conn, target_conn = two_empty_temp_db_connections source_path = Path(path_to_dbfile(source_conn)) @@ -254,7 +270,10 @@ def test_real_dataset_1d_pathlib_path(two_empty_temp_db_connections, inst) -> No assert_array_equal(source_data_vals, target_data_vals) -def test_real_dataset_2d(two_empty_temp_db_connections, inst) -> None: +def test_real_dataset_2d( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + inst: DummyInstrument, +) -> None: source_conn, target_conn = two_empty_temp_db_connections source_path = path_to_dbfile(source_conn) @@ -285,7 +304,8 @@ def test_real_dataset_2d(two_empty_temp_db_connections, inst) -> None: def test_correct_experiment_routing( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: """ Test that existing experiments are correctly identified AND that multiple @@ -382,7 +402,8 @@ def test_correct_experiment_routing( def test_runs_from_different_experiments_raises( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: """ Test that inserting runs from multiple experiments raises @@ -437,7 +458,9 @@ def test_runs_from_different_experiments_raises( extract_runs_into_db(source_path, target_path, *run_ids) -def test_extracting_dataless_run(two_empty_temp_db_connections) -> None: +def test_extracting_dataless_run( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], +) -> None: """ Although contrived, it could happen that a run with no data is extracted """ @@ -460,7 +483,8 @@ def test_extracting_dataless_run(two_empty_temp_db_connections) -> None: def test_result_table_naming_and_run_id( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: """ Check that a correct result table name is given and that a correct run_id @@ -505,7 +529,10 @@ def test_result_table_naming_and_run_id( assert target_ds.the_same_dataset_as(source_ds_2_2) -def test_load_by_X_functions(two_empty_temp_db_connections, some_interdeps) -> None: +def test_load_by_X_functions( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], +) -> None: """ Test some different loading functions """ @@ -557,7 +584,9 @@ def test_load_by_X_functions(two_empty_temp_db_connections, some_interdeps) -> N def test_combine_runs( - two_empty_temp_db_connections, empty_temp_db_connection, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + empty_temp_db_connection: AtomicConnection, + some_interdeps: list[InterDependencies_], ) -> None: """ Test that datasets that are exported in random order from 2 datasets @@ -645,7 +674,8 @@ def test_combine_runs( def test_copy_datasets_and_add_new( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: """ Test that new runs get the correct captured_run_id and captured_counter @@ -727,7 +757,8 @@ def test_copy_datasets_and_add_new( def test_old_versions_not_touched( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: source_conn, target_conn = two_empty_temp_db_connections @@ -782,7 +813,8 @@ def test_old_versions_not_touched( def test_experiments_with_NULL_sample_name( - two_empty_temp_db_connections, some_interdeps + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], ) -> None: """ In older API versions (corresponding to DB version 3), @@ -833,7 +865,8 @@ def test_experiments_with_NULL_sample_name( def test_integration_station_and_measurement( - two_empty_temp_db_connections, inst + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + inst: DummyInstrument, ) -> None: """ An integration test where the runs in the source DB file are produced @@ -869,7 +902,10 @@ def test_integration_station_and_measurement( assert datasaver.dataset.the_same_dataset_as(target_ds) -def test_atomicity(two_empty_temp_db_connections, some_interdeps) -> None: +def test_atomicity( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], +) -> None: """ Test the atomicity of the transaction by extracting and inserting two runs where the second one is not completed. The not completed error must @@ -903,7 +939,11 @@ def test_atomicity(two_empty_temp_db_connections, some_interdeps) -> None: extract_runs_into_db(source_path, target_path, 1, 2) -def test_column_mismatch(two_empty_temp_db_connections, some_interdeps, inst) -> None: +def test_column_mismatch( + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], + inst: DummyInstrument, +) -> None: """ Test insertion of runs with no metadata and no snapshot into a DB already containing a run that has both diff --git a/tests/dataset/test_datasaver.py b/tests/dataset/test_datasaver.py index 1a4f965adec7..a552b1b7c23b 100644 --- a/tests/dataset/test_datasaver.py +++ b/tests/dataset/test_datasaver.py @@ -18,7 +18,13 @@ CALLBACK_SNAPSHOT = None -def callback(result_list, data_set_len, state, run_id, snapshot): +def callback( + result_list: "list[tuple[object, ...]]", + data_set_len: "int", + state: "object", + run_id: "int", + snapshot: "str | None", +) -> "None": """ default_callback example function implemented in the Web UI. """ @@ -28,7 +34,7 @@ def callback(result_list, data_set_len, state, run_id, snapshot): CALLBACK_SNAPSHOT = snapshot -def reset_callback_globals(): +def reset_callback_globals() -> "None": global CALLBACK_COUNT, CALLBACK_RUN_ID, CALLBACK_SNAPSHOT CALLBACK_COUNT = 0 CALLBACK_RUN_ID = None @@ -37,7 +43,7 @@ def reset_callback_globals(): @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -def test_default_callback(bg_writing) -> None: +def test_default_callback(bg_writing: "bool") -> None: """ The Web UI needs to know the results of an experiment with the metadata. So a default_callback class variable is set by the Web UI with a callback @@ -75,7 +81,7 @@ def test_default_callback(bg_writing) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -def test_numpy_types(bg_writing) -> None: +def test_numpy_types(bg_writing: "bool") -> None: """ Test that we can save numpy types in the data set """ @@ -135,7 +141,10 @@ def test_numpy_types(bg_writing) -> None: ], ) @pytest.mark.parametrize("bg_writing", [True, False]) -def test_saving_numeric_values_as_text(numeric_type, bg_writing) -> None: +def test_saving_numeric_values_as_text( + numeric_type: "Callable[[int], int | float | np.integer | np.floating]", + bg_writing: "bool", +) -> None: """ Test the saving numeric values into 'text' parameter raises an exception """ diff --git a/tests/dataset/test_dataset_basic.py b/tests/dataset/test_dataset_basic.py index 1b35782d8ca0..1af0d9af4b2b 100644 --- a/tests/dataset/test_dataset_basic.py +++ b/tests/dataset/test_dataset_basic.py @@ -41,12 +41,13 @@ from pytest_mock import MockerFixture from qcodes.dataset.experiment_container import Experiment + from qcodes.dataset.sqlite.connection import AtomicConnection from qcodes.dataset.sqlite.query_helpers import VALUE n_experiments = 0 -def make_shadow_dataset(dataset: DataSet): +def make_shadow_dataset(dataset: DataSet) -> DataSet: """ Creates a new DataSet object that points to the same run_id in the same database file as the given dataset object. Note that for a pristine run, @@ -125,7 +126,7 @@ def test_dataset_length() -> None: assert len(ds) == 1 -def test_dataset_location(empty_temp_db_connection) -> None: +def test_dataset_location(empty_temp_db_connection: "AtomicConnection") -> None: """ Test that an dataset and experiment points to the correct db file when a connection is supplied. @@ -207,7 +208,7 @@ def test_dataset_states() -> None: @pytest.mark.parametrize("start_bg_writer", (True, False)) @pytest.mark.usefixtures("experiment") -def test_mark_completed_twice(start_bg_writer) -> None: +def test_mark_completed_twice(start_bg_writer: bool) -> None: """ Ensure that its not an error to call mark_completed on an already completed dataset @@ -247,7 +248,7 @@ def test_integer_timestamps_in_database_are_supported() -> None: assert isinstance(ds.completed_timestamp(), str) -def test_dataset_read_only_properties(dataset) -> None: +def test_dataset_read_only_properties(dataset: DataSet) -> None: read_only_props = [ "run_id", "path_to_db", @@ -276,15 +277,19 @@ def test_dataset_read_only_properties(dataset) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("non_existing_run_id", (1, 0, -1, "number#42")) -def test_create_dataset_from_non_existing_run_id(non_existing_run_id) -> None: +def test_create_dataset_from_non_existing_run_id( + non_existing_run_id: int | str, +) -> None: with pytest.raises( ValueError, match=f"Run with run_id {non_existing_run_id} does not exist in the database", ): - _ = DataSet(run_id=non_existing_run_id) + _ = DataSet(run_id=non_existing_run_id) # pyright: ignore[reportArgumentType] -def test_create_dataset_pass_both_connection_and_path_to_db(experiment) -> None: +def test_create_dataset_pass_both_connection_and_path_to_db( + experiment: "Experiment", +) -> None: some_valid_connection = experiment.conn with pytest.raises( ValueError, @@ -295,7 +300,7 @@ def test_create_dataset_pass_both_connection_and_path_to_db(experiment) -> None: _ = DataSet(path_to_db="some valid path", conn=some_valid_connection) -def test_load_by_id(dataset) -> None: +def test_load_by_id(dataset: DataSet) -> None: ds = load_by_id(dataset.run_id) assert dataset.run_id == ds.run_id assert dataset.path_to_db == ds.path_to_db @@ -303,7 +308,7 @@ def test_load_by_id(dataset) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("non_existing_run_id", (1, 0, -1)) -def test_load_by_id_for_nonexisting_run_id(non_existing_run_id) -> None: +def test_load_by_id_for_nonexisting_run_id(non_existing_run_id: int) -> None: with pytest.raises( ValueError, match=f"Run with run_id {non_existing_run_id} does not exist in the database", @@ -329,7 +334,9 @@ def test_load_by_id_for_none() -> None: ), ) @pytest.mark.usefixtures("empty_temp_db") -def test_add_experiments(experiment_name, sample_name, dataset_name) -> None: +def test_add_experiments( + experiment_name: str, sample_name: str, dataset_name: str +) -> None: qc.config.GUID_components.GUID_type = "random_sample" global n_experiments @@ -398,7 +405,7 @@ def test_dependent_parameters() -> None: assert ds.dependent_parameters == (pss[3], pss[0]) -def test_set_interdependencies(dataset) -> None: +def test_set_interdependencies(dataset: DataSet) -> None: exps = experiments() assert len(exps) == 1 exp = exps[0] @@ -561,17 +568,21 @@ def test_load_by_counter() -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("nonexisting_counter", (-1, 0, 1, None)) -def test_load_by_counter_for_nonexisting_counter(nonexisting_counter) -> None: +def test_load_by_counter_for_nonexisting_counter( + nonexisting_counter: int | None, +) -> None: exp_id = 1 with pytest.raises(RuntimeError, match="Expected one row"): - _ = load_by_counter(exp_id, nonexisting_counter) + _ = load_by_counter(exp_id, nonexisting_counter) # pyright: ignore[reportArgumentType] @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("nonexisting_exp_id", (-1, 0, 1, None)) -def test_load_by_counter_for_nonexisting_experiment(nonexisting_exp_id) -> None: +def test_load_by_counter_for_nonexisting_experiment( + nonexisting_exp_id: int | None, +) -> None: with pytest.raises(RuntimeError, match="Expected one row"): - _ = load_by_counter(nonexisting_exp_id, 1) + _ = load_by_counter(nonexisting_exp_id, 1) # pyright: ignore[reportArgumentType] @pytest.mark.usefixtures("empty_temp_db") @@ -580,13 +591,13 @@ def test_dataset_with_no_experiment_raises() -> None: new_data_set("test-dataset") -def test_guid(dataset) -> None: +def test_guid(dataset: DataSet) -> None: guid = dataset.guid assert len(guid) == 36 parse_guid(guid) -def test_numpy_ints(dataset) -> None: +def test_numpy_ints(dataset: DataSet) -> None: """ Test that we can insert numpy integers in the data set """ @@ -603,7 +614,7 @@ def test_numpy_ints(dataset) -> None: ) -def test_numpy_floats(dataset) -> None: +def test_numpy_floats(dataset: DataSet) -> None: """ Test that we can insert numpy floats in the data set """ @@ -619,7 +630,7 @@ def test_numpy_floats(dataset) -> None: assert np.allclose(data, expected_result, atol=1e-8) -def test_numpy_complex(dataset) -> None: +def test_numpy_complex(dataset: DataSet) -> None: """ Test that we can insert numpy complex in the data set """ @@ -629,13 +640,15 @@ def test_numpy_complex(dataset) -> None: dataset.mark_started() results = [{"x": tp(2.0 + 3.0j)} for tp in numpy_complex] - dataset.add_results(results) + # TODO: VALUE in qcodes.dataset.sqlite.query_helpers does not include + # numpy scalar types although add_results supports them + dataset.add_results(results) # pyright: ignore[reportArgumentType] expected_result = np.array([tp(2.0 + 3.0j) for tp in numpy_complex]) result = dataset.get_parameter_data() np.testing.assert_array_equal(result["x"]["x"], expected_result) -def test_numpy_nan(dataset) -> None: +def test_numpy_nan(dataset: DataSet) -> None: parameter_m = ParamSpecBase("m", "numeric") idps = InterDependencies_(standalones=(parameter_m,)) dataset.set_interdependencies(idps) @@ -647,7 +660,7 @@ def test_numpy_nan(dataset) -> None: assert np.isnan(retrieved[1]) -def test_numpy_inf(dataset) -> None: +def test_numpy_inf(dataset: DataSet) -> None: """ Test that we can insert and retrieve numpy inf in the data set """ @@ -671,7 +684,7 @@ def test_backward_compat__adapt_array_v0_33() -> None: assert arr == _convert_array(out.read()) -def test_missing_keys(dataset) -> None: +def test_missing_keys(dataset: DataSet) -> None: """ Test that we can now have partial results with keys missing. This is for example handy when having an interleaved 1D and 2D sweep. @@ -686,10 +699,10 @@ def test_missing_keys(dataset) -> None: dataset.set_interdependencies(idps) dataset.mark_started() - def fa(xv): + def fa(xv: int) -> int: return xv + 1 - def fb(xv, yv): + def fb(xv: int, yv: int) -> int: return xv + 2 - yv * 3 results = [] @@ -717,7 +730,9 @@ def fb(xv, yv): ) -def test_get_description(experiment, some_interdeps) -> None: +def test_get_description( + experiment: "Experiment", some_interdeps: list[InterDependencies_] +) -> None: ds = DataSet() assert ds.run_id == 1 @@ -743,7 +758,7 @@ def test_get_description(experiment, some_interdeps) -> None: assert loaded_ds.description == expected_desc -def test_metadata(experiment, request: FixtureRequest) -> None: +def test_metadata(experiment: "Experiment", request: FixtureRequest) -> None: metadata1 = {"number": 1, "string": "Once upon a time..."} metadata2 = {"more": "meta"} @@ -803,7 +818,9 @@ def test_metadata(experiment, request: FixtureRequest) -> None: assert ds1.metadata["np_scalar"] == 3 -def test_the_same_dataset_as(some_interdeps, experiment) -> None: +def test_the_same_dataset_as( + some_interdeps: list[InterDependencies_], experiment: "Experiment" +) -> None: ds = DataSet() ds.set_interdependencies(some_interdeps[1]) ds.mark_started() @@ -841,7 +858,7 @@ def test_parent_dataset_links_invalid_input() -> None: @pytest.mark.usefixtures("experiment") -def test_parent_dataset_links(some_interdeps) -> None: +def test_parent_dataset_links(some_interdeps: list[InterDependencies_]) -> None: """ Test that we can set links and retrieve them when loading the dataset """ @@ -883,7 +900,7 @@ class TestGetData: xdata = np.array(xvals) @pytest.fixture(autouse=True) - def ds_with_vals(self, dataset): + def ds_with_vals(self, dataset: DataSet) -> DataSet: """ This fixture creates a DataSet with values that is to be used by all the tests in this class @@ -927,9 +944,13 @@ def ds_with_vals(self, dataset): ], ) def test_get_data_with_start_and_end_args( - self, ds_with_vals, start, end, expected + self, + ds_with_vals: DataSet, + start: int | None, + end: int | None, + expected: npt.NDArray[np.int64] | list[np.int64], ) -> None: - data = ds_with_vals.get_parameter_data(self.x, start=start, end=end)["x"] + data = ds_with_vals.get_parameter_data(self.x.name, start=start, end=end)["x"] data = data["x"] np.testing.assert_array_equal(data, expected) @@ -939,7 +960,9 @@ def test_get_data_with_start_and_end_args( start=hst.one_of(hst.integers(1, 10**3), hst.none()), end=hst.one_of(hst.integers(1, 10**3), hst.none()), ) -def test_get_parameter_data(scalar_dataset, start, end) -> None: +def test_get_parameter_data( + scalar_dataset: DataSet, start: int | None, end: int | None +) -> None: input_names = ["param_3"] expected_names = {} @@ -966,7 +989,9 @@ def test_get_parameter_data(scalar_dataset, start, end) -> None: ) -def test_get_scalar_parameter_data_no_nulls(scalar_dataset_with_nulls) -> None: +def test_get_scalar_parameter_data_no_nulls( + scalar_dataset_with_nulls: DataSet, +) -> None: expected_names = {} expected_names["first_value"] = ["first_value", "setpoint"] expected_names["second_value"] = ["second_value", "setpoint"] @@ -986,7 +1011,9 @@ def test_get_scalar_parameter_data_no_nulls(scalar_dataset_with_nulls) -> None: ) -def test_get_array_parameter_data_no_nulls(array_dataset_with_nulls) -> None: +def test_get_array_parameter_data_no_nulls( + array_dataset_with_nulls: DataSet, +) -> None: types = [p.type for p in array_dataset_with_nulls.paramspecs.values()] expected_names = {} @@ -1018,7 +1045,7 @@ def test_get_array_parameter_data_no_nulls(array_dataset_with_nulls) -> None: ) -def test_get_array_parameter_data(array_dataset) -> None: +def test_get_array_parameter_data(array_dataset: DataSet) -> None: paramspecs = array_dataset.paramspecs types = [param.type for param in paramspecs.values()] par_name = "array_setpoint_param" @@ -1047,7 +1074,7 @@ def test_get_array_parameter_data(array_dataset) -> None: ) -def test_get_multi_parameter_data(multi_dataset) -> None: +def test_get_multi_parameter_data(multi_dataset: DataSet) -> None: paramspecs = multi_dataset.paramspecs types = [param.type for param in paramspecs.values()] @@ -1106,7 +1133,9 @@ def test_get_multi_parameter_data(multi_dataset) -> None: start=hst.one_of(hst.integers(1, 9), hst.none()), end=hst.one_of(hst.integers(1, 9), hst.none()), ) -def test_get_array_in_scalar_param_data(array_in_scalar_dataset, start, end) -> None: +def test_get_array_in_scalar_param_data( + array_in_scalar_dataset: DataSet, start: int | None, end: int | None +) -> None: par_name = "array_setpoint_param" setpoint_name = "array_setpoint_param_this_setpoint" @@ -1148,7 +1177,9 @@ def test_get_array_in_scalar_param_data(array_in_scalar_dataset, start, end) -> ) -def test_get_varlen_array_in_scalar_param_data(varlen_array_in_scalar_dataset) -> None: +def test_get_varlen_array_in_scalar_param_data( + varlen_array_in_scalar_dataset: DataSet, +) -> None: par_name = "array_setpoint_param" setpoint_name = "array_setpoint_param_this_setpoint" @@ -1196,7 +1227,7 @@ def test_get_varlen_array_in_scalar_param_data(varlen_array_in_scalar_dataset) - end=hst.one_of(hst.integers(1, 45), hst.none()), ) def test_get_array_in_scalar_param_unrolled( - array_in_scalar_dataset_unrolled, start, end + array_in_scalar_dataset_unrolled: DataSet, start: int | None, end: int | None ) -> None: par_name = "array_setpoint_param" setpoint_name = "array_setpoint_param_this_setpoint" @@ -1238,7 +1269,7 @@ def test_get_array_in_scalar_param_unrolled( ) -def test_get_array_in_str_param_data(array_in_str_dataset) -> None: +def test_get_array_in_str_param_data(array_in_str_dataset: DataSet) -> None: paramspecs = array_in_str_dataset.paramspecs types = [param.type for param in paramspecs.values()] @@ -1331,7 +1362,7 @@ def parameter_test_helper( expected_values: dict[str, list[np.ndarray]], start: int | None = None, end: int | None = None, -): +) -> None: """ A helper function to compare the data we actually read out of a given dataset with the expected data. @@ -1405,18 +1436,24 @@ def parameter_test_helper( def limit_data_to_start_end( - start, end, input_names, expected_names, expected_shapes, expected_values -): + start: int | None, + end: int | None, + input_names: list[str], + expected_names: dict[str, list[str]], + expected_shapes: dict[str, list[tuple[int, ...]]], + expected_values: dict[str, list[np.ndarray]], +) -> tuple[int | None, int | None]: if not (start is None and end is None): if start is None: start = 1 elif end is None: # all the shapes are the same so pick the first one end = expected_shapes[input_names[0]][0][0] + assert start is not None and end is not None if end < start: for name in input_names: - expected_shapes[name] = () - expected_values[name] = {} + expected_shapes[name] = [] + expected_values[name] = [] else: for name in input_names: new_shapes = [] diff --git a/tests/dataset/test_dataset_export.py b/tests/dataset/test_dataset_export.py index 7183f6fa6a08..027be867622e 100644 --- a/tests/dataset/test_dataset_export.py +++ b/tests/dataset/test_dataset_export.py @@ -66,7 +66,7 @@ def _make_mock_empty_dataset(experiment: Experiment) -> DataSet: @pytest.fixture(name="mock_dataset") -def _make_mock_dataset(experiment) -> DataSet: +def _make_mock_dataset(experiment: Experiment) -> DataSet: dataset = new_data_set("dataset") xparam = ParamSpecBase("x", "numeric") yparam = ParamSpecBase("y", "numeric") diff --git a/tests/dataset/test_dataset_in_mem_import.py b/tests/dataset/test_dataset_in_mem_import.py index 024bc9889502..ceb664b72c60 100644 --- a/tests/dataset/test_dataset_in_mem_import.py +++ b/tests/dataset/test_dataset_in_mem_import.py @@ -1,4 +1,7 @@ +from __future__ import annotations + import json +from typing import TYPE_CHECKING import numpy as np @@ -6,11 +9,20 @@ from qcodes.dataset.data_set import DataSet from qcodes.dataset.data_set_in_memory import DataSetInMem from qcodes.dataset.experiment_container import Experiment -from qcodes.dataset.sqlite.connection import path_to_dbfile +from qcodes.dataset.sqlite.connection import AtomicConnection, path_to_dbfile + +if TYPE_CHECKING: + from collections.abc import Sequence + from pathlib import Path + + from qcodes.dataset.data_set_protocol import DataSetProtocol + from qcodes.dataset.descriptions.dependencies import InterDependencies_ def test_basic_roundtrip( - two_empty_temp_db_connections, some_interdeps, tmp_path + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], + tmp_path: Path, ) -> None: """ Test that we can export from one db and import into another in @@ -33,13 +45,11 @@ def test_basic_roundtrip( path_to_db=source_path, ) source_datasets.append(source_dataset) - source_dataset._set_interdependencies(some_interdeps[1]) - - source_dataset._perform_start_actions() + source_dataset.prepare(interdeps=some_interdeps[1], snapshot={}) for val in range(10): source_dataset._enqueue_results( - {name: np.array([val]) for name in some_interdeps[1].names} + {param: np.array([val]) for param in some_interdeps[1].paramspecs} ) source_dataset.mark_completed() source_dataset.export(export_type="netcdf", path=str(tmp_path)) @@ -68,7 +78,9 @@ def test_basic_roundtrip( def test_roundtrip_to_db_with_existing_meas( - two_empty_temp_db_connections, some_interdeps, tmp_path + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], + tmp_path: Path, ) -> None: """ Test that we can export from one db and import into another in @@ -100,13 +112,11 @@ def test_roundtrip_to_db_with_existing_meas( path_to_db=source_path, ) source_datasets.append(source_dataset) - source_dataset._set_interdependencies(some_interdeps[1]) - - source_dataset._perform_start_actions() + source_dataset.prepare(interdeps=some_interdeps[1], snapshot={}) for val in range(10): source_dataset._enqueue_results( - {name: np.array([val]) for name in some_interdeps[1].names} + {param: np.array([val]) for param in some_interdeps[1].paramspecs} ) source_dataset.mark_completed() source_dataset.export(export_type="netcdf", path=str(tmp_path)) @@ -123,7 +133,7 @@ def test_roundtrip_to_db_with_existing_meas( for val in range(10): extra_dataset._enqueue_results( - {name: np.array([val]) for name in some_interdeps[1].names} + {param: np.array([val]) for param in some_interdeps[1].paramspecs} ) extra_dataset.mark_completed() @@ -152,7 +162,9 @@ def test_roundtrip_to_db_with_existing_meas( def test_roundtrip_to_db_with_existing_meas_in_same_exp( - two_empty_temp_db_connections, some_interdeps, tmp_path + two_empty_temp_db_connections: tuple[AtomicConnection, AtomicConnection], + some_interdeps: list[InterDependencies_], + tmp_path: Path, ) -> None: """ Test that we can export from one db and import into another in @@ -181,13 +193,11 @@ def test_roundtrip_to_db_with_existing_meas_in_same_exp( path_to_db=source_path, ) source_datasets.append(source_dataset) - source_dataset._set_interdependencies(some_interdeps[1]) - - source_dataset._perform_start_actions() + source_dataset.prepare(interdeps=some_interdeps[1], snapshot={}) for val in range(10): source_dataset._enqueue_results( - {name: np.array([val]) for name in some_interdeps[1].names} + {param: np.array([val]) for param in some_interdeps[1].paramspecs} ) source_dataset.mark_completed() source_dataset.export(export_type="netcdf", path=str(tmp_path)) @@ -204,7 +214,7 @@ def test_roundtrip_to_db_with_existing_meas_in_same_exp( for val in range(10): extra_dataset._enqueue_results( - {name: np.array([val]) for name in some_interdeps[1].names} + {param: np.array([val]) for param in some_interdeps[1].paramspecs} ) extra_dataset.mark_completed() @@ -232,8 +242,24 @@ def test_roundtrip_to_db_with_existing_meas_in_same_exp( ) -def _assert_before_writing_metadata(source_datasets, loaded_datasets) -> None: +def _assert_same_data(expected: DataSetProtocol, actual: DataSetProtocol) -> None: + expected_data = expected.get_parameter_data() + actual_data = actual.get_parameter_data() + assert expected_data.keys() == actual_data.keys() + for tree_name, expected_tree in expected_data.items(): + actual_tree = actual_data[tree_name] + assert expected_tree.keys() == actual_tree.keys() + for param_name, expected_values in expected_tree.items(): + np.testing.assert_array_equal(actual_tree[param_name], expected_values) + + +def _assert_before_writing_metadata( + source_datasets: Sequence[DataSetInMem], loaded_datasets: Sequence[DataSetInMem] +) -> None: for ds, lds in zip(source_datasets, loaded_datasets): + assert ds.number_of_results > 0 + _assert_same_data(ds, lds) + # these should always be equal assert ds.guid == lds.guid @@ -265,14 +291,17 @@ def _assert_before_writing_metadata(source_datasets, loaded_datasets) -> None: def _assert_after_writing_metadata( - source_datasets, - loaded_datasets, - reloaded_ds, - offset_total_ds, - offset_ds_in_exp, - offset_exps, + source_datasets: Sequence[DataSetInMem], + loaded_datasets: Sequence[DataSetInMem], + reloaded_ds: Sequence[DataSetProtocol], + offset_total_ds: int, + offset_ds_in_exp: int, + offset_exps: int, ) -> None: for ds, lds, rlds in zip(source_datasets, loaded_datasets, reloaded_ds): + _assert_same_data(ds, lds) + _assert_same_data(ds, rlds) + # these should always be equal assert ds.guid == lds.guid assert ds.guid == rlds.guid diff --git a/tests/dataset/test_dataset_in_memory.py b/tests/dataset/test_dataset_in_memory.py index df00b01c0cb3..69362b92c1c4 100644 --- a/tests/dataset/test_dataset_in_memory.py +++ b/tests/dataset/test_dataset_in_memory.py @@ -21,12 +21,20 @@ from qcodes.parameters import ManualParameter, Parameter, ParamSpecBase from qcodes.station import Station +if TYPE_CHECKING: + from qcodes.dataset.data_set_protocol import DataSetProtocol +if TYPE_CHECKING: + from qcodes.instrument_drivers.mock_instruments import DummyInstrument + if TYPE_CHECKING: from qcodes.dataset.experiment_container import Experiment def test_dataset_in_memory_reload_from_db( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -62,7 +70,12 @@ def test_dataset_in_memory_reload_from_db( shape2=hst.integers(min_value=1, max_value=100), ) def test_dataset_in_memory_reload_from_db_2d( - meas_with_registered_param_2d, DMM, DAC, tmp_path, shape1, shape2 + meas_with_registered_param_2d: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", + shape1: "int", + shape2: "int", ) -> None: meas_with_registered_param_2d.set_shapes( { @@ -120,7 +133,13 @@ def test_dataset_in_memory_reload_from_db_2d( shape3=hst.integers(min_value=1, max_value=10), ) def test_dataset_in_memory_reload_from_db_3d( - meas_with_registered_param_3d, DMM, DAC3D, tmp_path, shape1, shape2, shape3 + meas_with_registered_param_3d: "Measurement", + DMM: "DummyInstrument", + DAC3D: "DummyInstrument", + tmp_path: "Path", + shape1: "int", + shape2: "int", + shape3: "int", ) -> None: meas_with_registered_param_3d.set_shapes( { @@ -175,7 +194,10 @@ 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 + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with ( # noqa: PT012 pytest.raises( @@ -195,7 +217,10 @@ def test_dataset_in_memory_without_cache_raises( def test_dataset_in_memory_reload_from_db_complex( - meas_with_registered_param_complex, DAC, complex_num_instrument, tmp_path + meas_with_registered_param_complex: "Measurement", + DAC: "DummyInstrument", + complex_num_instrument: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param_complex.run( dataset_class=DataSetType.DataSetInMem @@ -219,7 +244,10 @@ def test_dataset_in_memory_reload_from_db_complex( def test_dataset_in_memory_reload_from_netcdf_complex( - meas_with_registered_param_complex, DAC, complex_num_instrument, tmp_path + meas_with_registered_param_complex: "Measurement", + DAC: "DummyInstrument", + complex_num_instrument: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param_complex.run( dataset_class=DataSetType.DataSetInMem @@ -245,7 +273,10 @@ def test_dataset_in_memory_reload_from_netcdf_complex( def test_dataset_in_memory_no_export_warns( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -272,7 +303,10 @@ def test_dataset_in_memory_no_export_warns( def test_dataset_in_memory_missing_file_warns( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -295,7 +329,10 @@ def test_dataset_in_memory_missing_file_warns( def test_dataset_in_reload_from_netcdf( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -321,7 +358,10 @@ def test_dataset_in_reload_from_netcdf( def test_dataset_load_from_netcdf_and_db( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -339,7 +379,7 @@ def test_dataset_load_from_netcdf_and_db( get_v = DMM.v1() datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) - path_to_db = datasaver.dataset._path_to_db + path_to_db = datasaver.dataset.path_to_db ds = datasaver.dataset ds.add_metadata("mymetadatatag", 42) @@ -359,7 +399,10 @@ def test_dataset_load_from_netcdf_and_db( def test_dataset_in_memory_does_not_create_runs_table( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -370,7 +413,8 @@ def test_dataset_in_memory_does_not_create_runs_table( datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) ds = datasaver.dataset - dbfile = datasaver.dataset._path_to_db + dbfile = datasaver.dataset.path_to_db + assert dbfile is not None conn = AtomicConnection(dbfile) @@ -381,7 +425,7 @@ def test_dataset_in_memory_does_not_create_runs_table( assert all(ds.name not in table_name for table_name in tablenames) -def test_load_from_netcdf_and_write_metadata_to_db(empty_temp_db) -> None: +def test_load_from_netcdf_and_write_metadata_to_db(empty_temp_db: "None") -> None: netcdf_file_path = ( Path(__file__).parent / "fixtures" / "db_files" / "netcdf" / "qcodes_2.nc" ) @@ -414,7 +458,7 @@ def test_load_from_netcdf_and_write_metadata_to_db(empty_temp_db) -> None: compare_datasets(ds, loaded_ds) -def test_load_from_netcdf_no_db_file(non_created_db) -> None: +def test_load_from_netcdf_no_db_file(non_created_db: "None") -> None: netcdf_file_path = ( Path(__file__).parent / "fixtures" / "db_files" / "netcdf" / "qcodes_2.nc" ) @@ -429,7 +473,12 @@ def test_load_from_netcdf_no_db_file(non_created_db) -> None: compare_datasets(ds, loaded_ds) -def test_load_from_db(meas_with_registered_param, DMM, DAC, tmp_path) -> None: +def test_load_from_db( + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", +) -> None: Station(DAC, DMM) with meas_with_registered_param.run( dataset_class=DataSetType.DataSetInMem @@ -459,7 +508,12 @@ def test_load_from_db(meas_with_registered_param, DMM, DAC, tmp_path) -> None: compare_datasets(ds, loaded_ds) -def test_load_from_file(meas_with_registered_param, DMM, DAC, tmp_path) -> None: +def test_load_from_file( + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", +) -> None: qcodes.config["dataset"]["export_prefix"] = "my_export_prefix" qcodes.config["dataset"]["export_type"] = "netcdf" @@ -472,7 +526,7 @@ def test_load_from_file(meas_with_registered_param, DMM, DAC, tmp_path) -> None: get_v = DMM.v1() datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) - ds: DataSetInMem = datasaver.dataset + ds: DataSetProtocol = datasaver.dataset ds.add_metadata("foo", "bar") ds.export(path=tmp_path) ds.add_metadata("metadata_added_after_export", "42") @@ -494,7 +548,12 @@ def test_load_from_file(meas_with_registered_param, DMM, DAC, tmp_path) -> None: compare_datasets(ds, loaded_ds) -def test_load_from_file_by_id(meas_with_registered_param, DMM, DAC, tmp_path) -> None: +def test_load_from_file_by_id( + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", +) -> None: qcodes.config["dataset"]["export_prefix"] = "my_export_prefix" qcodes.config["dataset"]["export_type"] = "netcdf" qcodes.config["dataset"]["load_from_exported_file"] = True @@ -507,7 +566,7 @@ def test_load_from_file_by_id(meas_with_registered_param, DMM, DAC, tmp_path) -> get_v = DMM.v1() datasaver.add_result((DAC.ch1, set_v), (DMM.v1, get_v)) - ds: DataSetInMem = datasaver.dataset + ds: DataSetProtocol = datasaver.dataset assert not isinstance(ds, DataSetInMem) ds.export(path=tmp_path) @@ -522,7 +581,9 @@ def test_load_from_file_by_id(meas_with_registered_param, DMM, DAC, tmp_path) -> assert not isinstance(loaded_ds_from_db, DataSetInMem) -def test_load_from_netcdf_non_completed_dataset(experiment, tmp_path) -> None: +def test_load_from_netcdf_non_completed_dataset( + experiment: "Experiment", tmp_path: "Path" +) -> None: """Test that non-completed datasets can be loaded from netcdf files.""" # Create a non-completed dataset by NOT using the measurement context manager # which automatically completes the dataset on exit @@ -565,7 +626,7 @@ def test_load_from_netcdf_non_completed_dataset(experiment, tmp_path) -> None: assert loaded_ds.run_timestamp_raw == ds.run_timestamp_raw -def test_load_from_netcdf_legacy_version(non_created_db) -> None: +def test_load_from_netcdf_legacy_version(non_created_db: "None") -> None: # Qcodes 0.26 exported netcdf files did not contain # the parent dataset links and used a different engine to write data # check that it still loads correctly @@ -584,7 +645,7 @@ def test_load_from_netcdf_legacy_version(non_created_db) -> None: compare_datasets(ds, loaded_ds) -def compare_datasets(ds, loaded_ds): +def compare_datasets(ds: "DataSetProtocol", loaded_ds: "DataSetProtocol") -> "None": assert ds.the_same_dataset_as(loaded_ds) assert len(ds) == len(loaded_ds) assert len(ds) != 0 @@ -606,7 +667,10 @@ def compare_datasets(ds, loaded_ds): def test_load_from_db_dataset_moved( - meas_with_registered_param, DMM, DAC, tmp_path + meas_with_registered_param: "Measurement", + DMM: "DummyInstrument", + DAC: "DummyInstrument", + tmp_path: "Path", ) -> None: Station(DAC, DMM) with meas_with_registered_param.run( diff --git a/tests/dataset/test_dataset_in_memory_bacis.py b/tests/dataset/test_dataset_in_memory_bacis.py index 1531642d476a..d8ab0305cc89 100644 --- a/tests/dataset/test_dataset_in_memory_bacis.py +++ b/tests/dataset/test_dataset_in_memory_bacis.py @@ -1,5 +1,6 @@ import re from pathlib import Path +from typing import TYPE_CHECKING import pytest @@ -9,8 +10,11 @@ from qcodes.dataset.descriptions.dependencies import InterDependencies_ from qcodes.parameters import ParamSpecBase +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment -def test_create_dataset_in_memory_explicit_db(empty_temp_db) -> None: + +def test_create_dataset_in_memory_explicit_db(empty_temp_db: "None") -> None: default_db_location = qc.config["core"]["db_location"] extra_db_location = str(Path(default_db_location).parent / "extra.db") @@ -25,7 +29,7 @@ def test_create_dataset_in_memory_explicit_db(empty_temp_db) -> None: assert default_db_location != extra_db_location -def test_empty_ds_parameters(experiment) -> None: +def test_empty_ds_parameters(experiment: "Experiment") -> None: ds = DataSetInMem._create_new_run(name="foo") assert ds._parameters is None @@ -38,7 +42,7 @@ def test_empty_ds_parameters(experiment) -> None: assert ds._parameters is None -def test_write_metadata_to_explicit_db(empty_temp_db) -> None: +def test_write_metadata_to_explicit_db(empty_temp_db: "None") -> None: default_db_location = qc.config["core"]["db_location"] extra_db_location = str(Path(default_db_location).parent / "extra.db") load_or_create_experiment(experiment_name="myexp", sample_name="mysample") @@ -55,13 +59,13 @@ def test_write_metadata_to_explicit_db(empty_temp_db) -> None: ds.the_same_dataset_as(loaded_ds) -def test_no_interdeps_raises_in_prepare(experiment) -> None: +def test_no_interdeps_raises_in_prepare(experiment: "Experiment") -> None: ds = DataSetInMem._create_new_run(name="foo") with pytest.raises(RuntimeError, match="No parameters supplied"): ds.prepare(interdeps=InterDependencies_(), snapshot={}) -def test_prepare_twice_raises(experiment) -> None: +def test_prepare_twice_raises(experiment: "Experiment") -> None: ds = DataSetInMem._create_new_run(name="foo") pss: list[ParamSpecBase] = [] @@ -77,7 +81,7 @@ def test_prepare_twice_raises(experiment) -> None: ds.prepare(interdeps=idps, snapshot={}) -def test_timestamps(experiment) -> None: +def test_timestamps(experiment: "Experiment") -> None: ds = DataSetInMem._create_new_run(name="foo") assert ds.run_timestamp() is None @@ -111,7 +115,7 @@ def test_timestamps(experiment) -> None: ds.mark_completed() -def test_mark_pristine_completed_raises(experiment) -> None: +def test_mark_pristine_completed_raises(experiment: "Experiment") -> None: ds = DataSetInMem._create_new_run(name="foo") with pytest.raises( @@ -120,7 +124,7 @@ def test_mark_pristine_completed_raises(experiment) -> None: ds.mark_completed() -def test_load_from_non_existing_guid(experiment) -> None: +def test_load_from_non_existing_guid(experiment: "Experiment") -> None: guid = "This is not a guid" with pytest.raises( RuntimeError, match="Could not find the requested run with GUID" diff --git a/tests/dataset/test_dataset_loading.py b/tests/dataset/test_dataset_loading.py index ebdb732f2553..784fe2667e49 100644 --- a/tests/dataset/test_dataset_loading.py +++ b/tests/dataset/test_dataset_loading.py @@ -3,6 +3,7 @@ import datetime import time from math import floor +from typing import TYPE_CHECKING import numpy as np import pytest @@ -26,6 +27,11 @@ raw_time_to_str_time, ) +if TYPE_CHECKING: + from collections.abc import Callable +if TYPE_CHECKING: + from qcodes.dataset.descriptions.dependencies import InterDependencies_ + @pytest.mark.usefixtures("experiment") def test_load_by_id() -> None: @@ -250,7 +256,7 @@ def test_completed_timestamp_with_default_format() -> None: @pytest.mark.usefixtures("experiment") -def test_load_by_guid(some_interdeps) -> None: +def test_load_by_guid(some_interdeps: list[InterDependencies_]) -> None: ds = DataSet() ds.set_interdependencies(some_interdeps[1]) ds.mark_started() @@ -261,8 +267,10 @@ def test_load_by_guid(some_interdeps) -> None: assert loaded_ds.the_same_dataset_as(ds) -def test_load_by_run_spec(empty_temp_db, some_interdeps) -> None: - def create_ds_with_exp_id(exp_id): +def test_load_by_run_spec( + empty_temp_db: None, some_interdeps: list[InterDependencies_] +) -> None: + def create_ds_with_exp_id(exp_id: int) -> DataSet: ds = DataSet(exp_id=exp_id) ds.set_interdependencies(some_interdeps[1]) ds.mark_started() @@ -357,7 +365,7 @@ def create_ds_with_exp_id(exp_id): def test_callback(scalar_datasets_parameterized: DataSet) -> None: called_progress: list[float] = [] - def callback_closure(called_progress: list[float]): + def callback_closure(called_progress: list[float]) -> Callable[[float], None]: def callback(progress: float) -> None: called_progress.append(progress) diff --git a/tests/dataset/test_dependencies.py b/tests/dataset/test_dependencies.py index d43699c8c9d3..8aee0c94575f 100644 --- a/tests/dataset/test_dependencies.py +++ b/tests/dataset/test_dependencies.py @@ -27,7 +27,9 @@ def test_wrong_input_raises() -> None: InterDependencies(pspecs) # type: ignore[arg-type] -def test_init(some_paramspecbases) -> None: +def test_init( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: """ Assert that the init functions correctly sets up the object. Assert via the public-facing methods. @@ -56,7 +58,9 @@ def test_init(some_paramspecbases) -> None: assert idps.top_level_parameters == (ps1, ps4) -def test_init_validation_raises(some_paramspecbases) -> None: +def test_init_validation_raises( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: (ps1, ps2, ps3, ps4) = some_paramspecbases # First test validation of trees invalid in their own right @@ -106,8 +110,10 @@ def test_init_validation_raises(some_paramspecbases) -> None: ) -def test_to_dict(some_paramspecbases) -> None: - def tester(idps) -> None: +def test_to_dict( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: + def tester(idps: "InterDependencies_") -> None: ser = idps._to_dict() json.dumps(ser) idps_deser = InterDependencies_._from_dict(ser) @@ -127,14 +133,16 @@ def tester(idps) -> None: tester(idps) -def test_old_to_new_and_back(some_paramspecs) -> None: +def test_old_to_new_and_back( + some_paramspecs: "dict[int, dict[str, ParamSpec]]", +) -> None: idps_old = InterDependencies(*some_paramspecs[1].values()) idps_new = old_to_new(idps_old) assert new_to_old(idps_new) == idps_old -def test_old_to_new(some_paramspecs) -> None: +def test_old_to_new(some_paramspecs: "dict[int, dict[str, ParamSpec]]") -> None: ps1 = some_paramspecs[1]["ps1"] ps2 = some_paramspecs[1]["ps2"] ps3 = some_paramspecs[1]["ps3"] @@ -183,7 +191,9 @@ def test_old_to_new(some_paramspecs) -> None: assert idps_new._id_to_paramspec == {ps.name: ps for ps in paramspecs3} -def test_new_to_old(some_paramspecbases) -> None: +def test_new_to_old( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: (ps1, ps2, ps3, ps4) = some_paramspecbases idps_new = InterDependencies_(dependencies={ps1: (ps2, ps3)}, standalones=(ps4,)) @@ -235,7 +245,9 @@ def test_new_to_old(some_paramspecbases) -> None: assert new_to_old(idps_new) == idps_old_expected -def test_validate_subset(some_paramspecbases) -> None: +def test_validate_subset( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: ps1, ps2, ps3, ps4 = some_paramspecbases idps = InterDependencies_( @@ -274,7 +286,9 @@ def test_validate_subset(some_paramspecbases) -> None: idps.validate_subset((ps2, ps42, ps4)) -def test_extend(some_paramspecbases) -> None: +def test_extend( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: ps1, ps2, ps3, _ = some_paramspecbases idps = InterDependencies_(standalones=(ps1, ps2)) @@ -317,7 +331,9 @@ def test_extend(some_paramspecbases) -> None: idps_ext = idps.extend(inferences={ps2: (ps1,)}) -def test_remove(some_paramspecbases) -> None: +def test_remove( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: ps1, ps2, ps3, ps4 = some_paramspecbases idps = InterDependencies_(dependencies={ps1: (ps2, ps3)}, inferences={ps2: (ps4,)}) @@ -347,7 +363,7 @@ def test_remove(some_paramspecbases) -> None: assert idps_rem == idps_expected -def test_equality_old(some_paramspecs) -> None: +def test_equality_old(some_paramspecs: "dict[int, dict[str, ParamSpec]]") -> None: # TODO: make this more fancy with itertools ps1 = some_paramspecs[1]["ps1"] @@ -441,7 +457,9 @@ def test_collect_related__complex( assert idps2.find_all_parameters_in_tree(ps1) == {ps1, ps2, ps3} -def test_all_parameters_in_tree_by_group_raises_on_non_top_level(some_paramspecbases): +def test_all_parameters_in_tree_by_group_raises_on_non_top_level( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> "None": (ps1, ps2, ps3, ps4) = some_paramspecbases idps = InterDependencies_(dependencies={ps1: (ps2,)}, inferences={ps2: (ps3,)}) @@ -478,7 +496,9 @@ def test_dependency_on_middle_parameter( assert idps.find_all_parameters_in_tree(ps1) == {ps1, ps2, ps3, ps4} -def test_frozen_interdependencies(some_paramspecbases) -> None: +def test_frozen_interdependencies( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: ps1, ps2, ps3, ps4 = some_paramspecbases idps = InterDependencies_(dependencies={ps1: (ps2, ps3)}, inferences={ps2: (ps4,)}) @@ -525,7 +545,9 @@ def test_frozen_interdependencies(some_paramspecbases) -> None: assert frozen._top_level_parameters_cache is not None -def test_frozen_from_dict(some_paramspecbases) -> None: +def test_frozen_from_dict( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: ps1, ps2, ps3, _ = some_paramspecbases idps = InterDependencies_(dependencies={ps1: (ps2, ps3)}) ser = idps._to_dict() diff --git a/tests/dataset/test_descriptions.py b/tests/dataset/test_descriptions.py index 248c52ebfc9c..44747961758d 100644 --- a/tests/dataset/test_descriptions.py +++ b/tests/dataset/test_descriptions.py @@ -1,4 +1,5 @@ import json +from typing import TYPE_CHECKING import pytest from ruamel.yaml import YAML @@ -8,6 +9,9 @@ from qcodes.dataset.descriptions.versioning import serialization as serial from qcodes.dataset.descriptions.versioning.converters import new_to_old +if TYPE_CHECKING: + from qcodes.parameters import ParamSpecBase + def test_wrong_input_type_raises() -> None: for interdeps in ("interdeps", ["p1", "p2"], 0): @@ -15,7 +19,9 @@ def test_wrong_input_type_raises() -> None: RunDescriber(interdeps=interdeps) # type: ignore[arg-type] -def test_equality(some_paramspecbases) -> None: +def test_equality( + some_paramspecbases: "tuple[ParamSpecBase, ParamSpecBase, ParamSpecBase, ParamSpecBase]", +) -> None: (psb1, psb2, psb3, _) = some_paramspecbases idp1 = InterDependencies_(dependencies={psb1: (psb2, psb3)}) @@ -31,7 +37,7 @@ def test_equality(some_paramspecbases) -> None: assert desc_3 != desc_2 -def test_keys_of_result_of_to_dict(some_interdeps) -> None: +def test_keys_of_result_of_to_dict(some_interdeps: "list[InterDependencies_]") -> None: for idps in some_interdeps: desc = RunDescriber(interdeps=idps) @@ -44,7 +50,7 @@ def test_keys_of_result_of_to_dict(some_interdeps) -> None: ] -def test_to_and_from_dict_roundtrip(some_interdeps) -> None: +def test_to_and_from_dict_roundtrip(some_interdeps: "list[InterDependencies_]") -> None: for idps in some_interdeps: desc = RunDescriber(interdeps=idps) @@ -56,7 +62,7 @@ def test_to_and_from_dict_roundtrip(some_interdeps) -> None: assert desc == new_desc -def test_yaml_creation_and_loading(some_interdeps) -> None: +def test_yaml_creation_and_loading(some_interdeps: "list[InterDependencies_]") -> None: yaml = YAML() for idps in some_interdeps: @@ -77,7 +83,9 @@ def test_yaml_creation_and_loading(some_interdeps) -> None: assert new_desc == desc -def test_jsonization_as_v0_for_storage(some_interdeps) -> None: +def test_jsonization_as_v0_for_storage( + some_interdeps: "list[InterDependencies_]", +) -> None: """ Test that a RunDescriber can be json-dumped as version 0 """ @@ -90,7 +98,9 @@ def test_jsonization_as_v0_for_storage(some_interdeps) -> None: assert serial.to_json_as_version(new_desc, 0) == old_json -def test_default_jsonization_for_storage(some_interdeps) -> None: +def test_default_jsonization_for_storage( + some_interdeps: "list[InterDependencies_]", +) -> None: """ Test that a RunDescriber is json-dumped as version 2 """ @@ -110,7 +120,9 @@ def test_default_jsonization_for_storage(some_interdeps) -> None: assert serial.to_json_for_storage(new_desc) == expected_json -def test_dictization_as_v0_for_storage(some_interdeps) -> None: +def test_dictization_as_v0_for_storage( + some_interdeps: "list[InterDependencies_]", +) -> None: """ Test that a RunDescriber always gets converted to dict that represents an old style RunDescriber, even when given new style interdeps @@ -125,7 +137,9 @@ def test_dictization_as_v0_for_storage(some_interdeps) -> None: assert serial.to_dict_as_version(new_desc, 0) == old_desc -def test_default_dictization_for_storage(some_interdeps) -> None: +def test_default_dictization_for_storage( + some_interdeps: "list[InterDependencies_]", +) -> None: """ Test that a RunDescriber always gets converted to dict that represents an old style RunDescriber, even when given new style interdeps @@ -145,7 +159,9 @@ def test_default_dictization_for_storage(some_interdeps) -> None: assert serial.to_dict_for_storage(new_desc) == old_desc -def test_dictization_of_current_version(some_interdeps) -> None: +def test_dictization_of_current_version( + some_interdeps: "list[InterDependencies_]", +) -> None: """ Test conversion to dictionary of a RunDescriber """ diff --git a/tests/dataset/test_detect_shape.py b/tests/dataset/test_detect_shape.py index 1fa2b097451b..7a2f64025c42 100644 --- a/tests/dataset/test_detect_shape.py +++ b/tests/dataset/test_detect_shape.py @@ -1,3 +1,7 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + import hypothesis.strategies as hst import numpy as np import pytest @@ -6,6 +10,7 @@ from qcodes.dataset.descriptions.detect_shapes import detect_shape_of_measurement from qcodes.instrument_drivers.mock_instruments import ( ArraySetPointParam, + DummyChannelInstrument, Multi2DSetPointParam, Multi2DSetPointParam2Sizes, MultiSetPointParam, @@ -15,9 +20,12 @@ from .conftest import ArrayshapedParam +if TYPE_CHECKING: + from collections.abc import Callable, Sized + @given(loop_shape=hst.lists(hst.integers(min_value=1), min_size=1, max_size=10)) -def test_get_shape_for_parameter_from_len(loop_shape) -> None: +def test_get_shape_for_parameter_from_len(loop_shape: list[int]) -> None: a = Parameter(name="a", initial_cache_value=10) shape = detect_shape_of_measurement((a,), loop_shape) assert shape == {"a": tuple(loop_shape)} @@ -29,7 +37,9 @@ def test_get_shape_for_parameter_from_len(loop_shape) -> None: ) ) @pytest.mark.parametrize("range_func", [range, np.arange]) -def test_get_shape_for_parameter_from_sequence(loop_shape, range_func) -> None: +def test_get_shape_for_parameter_from_sequence( + loop_shape: list[int], range_func: Callable[[int], Sized] +) -> None: a = Parameter(name="a", initial_cache_value=10) loop_sequence = tuple(range_func(x) for x in loop_shape) shape = detect_shape_of_measurement((a,), loop_sequence) @@ -37,7 +47,7 @@ def test_get_shape_for_parameter_from_sequence(loop_shape, range_func) -> None: @given(loop_shape=hst.lists(hst.integers(min_value=1), min_size=1, max_size=10)) -def test_get_shape_for_array_parameter_from_len(loop_shape) -> None: +def test_get_shape_for_array_parameter_from_len(loop_shape: list[int]) -> None: a = ArraySetPointParam(name="a") shape = detect_shape_of_measurement((a,), loop_shape) expected_shape = tuple(loop_shape) + tuple(a.shape) @@ -50,7 +60,9 @@ def test_get_shape_for_array_parameter_from_len(loop_shape) -> None: ) ) @pytest.mark.parametrize("range_func", [range, np.arange]) -def test_get_shape_for_array_parameter_from_shape(loop_shape, range_func) -> None: +def test_get_shape_for_array_parameter_from_shape( + loop_shape: list[int], range_func: Callable[[int], Sized] +) -> None: a = ArraySetPointParam(name="a") loop_sequence = tuple(range_func(x) for x in loop_shape) shape = detect_shape_of_measurement((a,), loop_sequence) @@ -63,7 +75,12 @@ def test_get_shape_for_array_parameter_from_shape(loop_shape, range_func) -> Non "multiparamtype", [MultiSetPointParam, Multi2DSetPointParam, Multi2DSetPointParam2Sizes], ) -def test_get_shape_for_multiparam_from_len(loop_shape, multiparamtype) -> None: +def test_get_shape_for_multiparam_from_len( + loop_shape: list[int], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], +) -> None: param = multiparamtype(name="meas_param") shapes = detect_shape_of_measurement((param,), loop_shape) expected_shapes = {} @@ -83,7 +100,11 @@ def test_get_shape_for_multiparam_from_len(loop_shape, multiparamtype) -> None: ) @pytest.mark.parametrize("range_func", [range, np.arange]) def test_get_shape_for_multiparam_from_shape( - loop_shape, multiparamtype, range_func + loop_shape: list[int], + multiparamtype: type[ + MultiSetPointParam | Multi2DSetPointParam | Multi2DSetPointParam2Sizes + ], + range_func: Callable[[int], Sized], ) -> None: param = multiparamtype(name="meas_param") loop_sequence = tuple(range_func(x) for x in loop_shape) @@ -99,7 +120,9 @@ def test_get_shape_for_multiparam_from_shape( loop_shape=hst.lists(hst.integers(min_value=1), min_size=1, max_size=10), n_points=hst.integers(min_value=1, max_value=1000), ) -def test_get_shape_for_pws_from_len(dummyinstrument, loop_shape, n_points) -> None: +def test_get_shape_for_pws_from_len( + dummyinstrument: DummyChannelInstrument, loop_shape: list[int], n_points: int +) -> None: param = dummyinstrument.A.dummy_parameter_with_setpoints dummyinstrument.A.dummy_n_points(n_points) shapes = detect_shape_of_measurement((param,), loop_shape) @@ -119,7 +142,10 @@ def test_get_shape_for_pws_from_len(dummyinstrument, loop_shape, n_points) -> No n_points=hst.integers(min_value=1, max_value=1000), ) def test_get_shape_for_pws_from_shape( - dummyinstrument, loop_shape, range_func, n_points + dummyinstrument: DummyChannelInstrument, + loop_shape: list[int], + range_func: Callable[[int], Sized], + n_points: int, ) -> None: param = dummyinstrument.A.dummy_parameter_with_setpoints dummyinstrument.A.dummy_n_points(n_points) @@ -140,7 +166,10 @@ def test_get_shape_for_pws_from_shape( n_points=hst.integers(min_value=1, max_value=1000), ) def test_get_shape_for_pws_with_register_name_from_shape( - dummyinstrument, loop_shape, range_func, n_points + dummyinstrument: DummyChannelInstrument, + loop_shape: list[int], + range_func: Callable[[int], Sized], + n_points: int, ) -> None: param = dummyinstrument.A.dummy_parameter_with_setpoints param._register_name = f"register_{param.full_name}" # register_name can ordinarily only be set at init @@ -158,7 +187,9 @@ def test_get_shape_for_pws_with_register_name_from_shape( hst.integers(min_value=1, max_value=1000), min_size=1, max_size=10 ) ) -def test_get_shape_for_param_with_array_validator_from_shape(loop_shape) -> None: +def test_get_shape_for_param_with_array_validator_from_shape( + loop_shape: list[int], +) -> None: param = ArrayshapedParam(name="paramwitharrayval", vals=Arrays(shape=(10,))) shapes = detect_shape_of_measurement((param,), loop_shape) @@ -174,7 +205,10 @@ def test_get_shape_for_param_with_array_validator_from_shape(loop_shape) -> None n_points_2=hst.integers(min_value=1, max_value=1000), ) def test_get_shape_for_multiple_parameters( - dummyinstrument, loop_shape, n_points_1, n_points_2 + dummyinstrument: DummyChannelInstrument, + loop_shape: list[int], + n_points_1: int, + n_points_2: int, ) -> None: param1 = dummyinstrument.A.dummy_parameter_with_setpoints dummyinstrument.A.dummy_n_points(n_points_1) diff --git a/tests/dataset/test_experiment_container.py b/tests/dataset/test_experiment_container.py index 23e819e210f1..720f47757a26 100644 --- a/tests/dataset/test_experiment_container.py +++ b/tests/dataset/test_experiment_container.py @@ -1,5 +1,6 @@ import logging import re +from typing import TYPE_CHECKING import pytest from pytest import LogCaptureFixture @@ -20,8 +21,11 @@ from qcodes.dataset.measurements import Measurement from qcodes.dataset.sqlite.database import conn_from_dbpath_or_conn, get_DB_location +if TYPE_CHECKING: + from qcodes.dataset.data_set import DataSet -def assert_experiments_equal(exp, exp_2): + +def assert_experiments_equal(exp: "Experiment", exp_2: "Experiment") -> "None": for attr in ["name", "sample_name", "path_to_db", "last_counter"]: assert getattr(exp, attr) == getattr(exp_2, attr) assert len(exp_2) == len(exp) @@ -45,7 +49,7 @@ def test_run_loaded_experiment() -> None: pass -def test_last_data_set_from_experiment(dataset) -> None: +def test_last_data_set_from_experiment(dataset: "DataSet") -> None: experiment = load_experiment(dataset.exp_id) ds = experiment.last_data_set() @@ -59,7 +63,9 @@ def test_last_data_set_from_experiment(dataset) -> None: assert experiment.path_to_db == ds.path_to_db -def test_last_data_set_from_experiment_with_no_datasets(experiment) -> None: +def test_last_data_set_from_experiment_with_no_datasets( + experiment: "Experiment", +) -> None: with pytest.raises(ValueError, match="There are no runs in this experiment"): _ = experiment.last_data_set() @@ -141,7 +147,7 @@ def test_has_attributes_after_init() -> None: getattr(exp, attr) -def test_experiment_read_only_properties(experiment) -> None: +def test_experiment_read_only_properties(experiment: "Experiment") -> None: read_only_props = [ "name", "exp_id", @@ -161,26 +167,26 @@ def test_experiment_read_only_properties(experiment) -> None: @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("non_existing_id", (1, 0, -1, "number#42")) -def test_create_experiment_from_non_existing_id(non_existing_id) -> None: +def test_create_experiment_from_non_existing_id(non_existing_id: int | str) -> None: with pytest.raises(ValueError, match="No such experiment in the database"): - _ = Experiment(exp_id=non_existing_id) + _ = Experiment(exp_id=non_existing_id) # pyright: ignore[reportArgumentType] @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("non_existing_id", (1, 0, -1)) -def test_load_experiment_from_non_existing_id(non_existing_id) -> None: +def test_load_experiment_from_non_existing_id(non_existing_id: "int") -> None: with pytest.raises(ValueError, match="No such experiment in the database"): _ = load_experiment(non_existing_id) @pytest.mark.usefixtures("empty_temp_db") @pytest.mark.parametrize("bad_id", (None, "number#42")) -def test_load_experiment_from_bad_id(bad_id) -> None: +def test_load_experiment_from_bad_id(bad_id: str | None) -> None: with pytest.raises(ValueError, match="Experiment ID must be an integer"): - _ = load_experiment(bad_id) + _ = load_experiment(bad_id) # pyright: ignore[reportArgumentType] -def test_format_string(empty_temp_db) -> None: +def test_format_string(empty_temp_db: "None") -> None: # default format string exp1 = Experiment(exp_id=None) assert "{}-{}-{}" == exp1.format_string @@ -201,7 +207,7 @@ def test_format_string(empty_temp_db) -> None: _ = Experiment(exp_id=None, format_string=fmt_str) -def test_load_experiment_by_name_defaults(empty_temp_db) -> None: +def test_load_experiment_by_name_defaults(empty_temp_db: "None") -> None: exp1 = Experiment(exp_id=None) exp2 = load_experiment_by_name("experiment_1") @@ -211,7 +217,7 @@ def test_load_experiment_by_name_defaults(empty_temp_db) -> None: assert_experiments_equal(exp1, exp3) -def test_load_experiment_by_name(empty_temp_db) -> None: +def test_load_experiment_by_name(empty_temp_db: "None") -> None: exp1 = Experiment(exp_id=None, name="myname") exp2 = load_experiment_by_name("myname") @@ -229,7 +235,7 @@ def test_load_experiment_by_name(empty_temp_db) -> None: assert_experiments_equal(exp4, exp6) -def test_load_experiment_by_name_bad_name(empty_temp_db) -> None: +def test_load_experiment_by_name_bad_name(empty_temp_db: "None") -> None: Experiment(exp_id=None, name="myname") with pytest.raises(ValueError, match="Experiment not found"): @@ -242,7 +248,7 @@ def test_load_experiment_by_name_bad_name(empty_temp_db) -> None: _ = load_experiment_by_name("myname__", "some_sample__") -def test_load_experiment_by_name_bad_sample_name(empty_temp_db) -> None: +def test_load_experiment_by_name_bad_sample_name(empty_temp_db: "None") -> None: Experiment(exp_id=None, sample_name="mysample") with pytest.raises(ValueError, match="Experiment not found"): @@ -255,7 +261,7 @@ def test_load_experiment_by_name_bad_sample_name(empty_temp_db) -> None: _ = load_experiment_by_name("experiment_1__", "mysample__") -def test_load_experiment_by_name_duplicate_name(empty_temp_db) -> None: +def test_load_experiment_by_name_duplicate_name(empty_temp_db: "None") -> None: exp1 = Experiment(exp_id=None, name="exp") exp2 = Experiment(exp_id=None, name="exp") @@ -292,7 +298,7 @@ def test_load_experiment_by_name_duplicate_name(empty_temp_db) -> None: assert_experiments_equal(exp3, exp3_loaded) -def test_load_experiment_by_name_duplicate_sample_name(empty_temp_db) -> None: +def test_load_experiment_by_name_duplicate_sample_name(empty_temp_db: "None") -> None: exp1 = Experiment(exp_id=None, name="exp1", sample_name="sss") exp2 = Experiment(exp_id=None, name="exp2", sample_name="sss") @@ -309,7 +315,9 @@ def test_load_experiment_by_name_duplicate_sample_name(empty_temp_db) -> None: assert_experiments_equal(exp2, exp2_loaded_with_sample) -def test_load_experiment_by_name_duplicate_name_and_sample_name(empty_temp_db) -> None: +def test_load_experiment_by_name_duplicate_name_and_sample_name( + empty_temp_db: "None", +) -> None: exp1 = Experiment(exp_id=None, name="exp", sample_name="sss") exp2 = Experiment(exp_id=None, name="exp", sample_name="sss") @@ -335,7 +343,7 @@ def test_load_experiment_by_name_duplicate_name_and_sample_name(empty_temp_db) - def test_new_experiment_duplicate_name_and_sample_name( - empty_temp_db, caplog: LogCaptureFixture + empty_temp_db: "None", caplog: LogCaptureFixture ) -> None: """ Test new_experiment to raise warning if it wants to create experiment @@ -368,7 +376,7 @@ def test_new_experiment_duplicate_name_and_sample_name( caplog.clear() -def test_load_last_experiment(empty_temp_db) -> None: +def test_load_last_experiment(empty_temp_db: "None") -> None: # test in case of no experiments with pytest.raises( ValueError, match="There are no experiments in the database file" @@ -388,7 +396,7 @@ def test_load_last_experiment(empty_temp_db) -> None: assert last_exp.path_to_db == exp2.path_to_db -def test_active_experiment(empty_temp_db) -> None: +def test_active_experiment(empty_temp_db: "None") -> None: conn = conn_from_dbpath_or_conn(conn=None, path_to_db=empty_temp_db) with pytest.raises(ValueError): get_default_experiment_id(conn) diff --git a/tests/dataset/test_export_info.py b/tests/dataset/test_export_info.py index ce2915de91fe..8c8eac8d34d1 100644 --- a/tests/dataset/test_export_info.py +++ b/tests/dataset/test_export_info.py @@ -38,7 +38,7 @@ def test_invalid_key_raises() -> None: _ = ExportInfo({"nd": nd_path}) -def test_export_info_json_roundtrip(basic_export_info) -> None: +def test_export_info_json_roundtrip(basic_export_info: "ExportInfo") -> None: exported_str = basic_export_info.to_str() loaded_export_info = ExportInfo.from_str(exported_str) assert loaded_export_info == basic_export_info diff --git a/tests/dataset/test_fix_functions.py b/tests/dataset/test_fix_functions.py index bececdbe3e0d..860e843456c8 100644 --- a/tests/dataset/test_fix_functions.py +++ b/tests/dataset/test_fix_functions.py @@ -69,7 +69,7 @@ def test_fix_wrong_run_descriptions() -> None: skip_if_no_fixtures(dbname_old) - def make_ps(n): + def make_ps(n: "int") -> "ParamSpec": ps = ParamSpec( f"p{n}", label=f"Parameter {n}", unit=f"unit {n}", paramtype="numeric" ) diff --git a/tests/dataset/test_guids.py b/tests/dataset/test_guids.py index 7dcc5edf79d2..6ecc8c8a35d8 100644 --- a/tests/dataset/test_guids.py +++ b/tests/dataset/test_guids.py @@ -1,6 +1,7 @@ import random import re import time +from typing import TYPE_CHECKING from uuid import uuid4 import hypothesis.strategies as hst @@ -18,9 +19,14 @@ validate_guid_format, ) +if TYPE_CHECKING: + from qcodes.configuration import Config +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(name="seed_random") -def _make_seed_random(): +def _make_seed_random() -> "Generator[None, None, None]": state = random.getstate() random.seed(a=0) try: @@ -35,7 +41,7 @@ def _make_seed_random(): stat=hst.integers(0, 0xFFFF), smpl=hst.integers(0, 0xFF_FFF_FFF), ) -def test_generate_legacy_guid(loc, stat, smpl) -> None: +def test_generate_legacy_guid(loc: "int", stat: "int", smpl: "int") -> None: """ Generate a guid in the legacy format (with an assigned sample name) and verify that it is parsed @@ -75,7 +81,7 @@ def test_generate_legacy_guid(loc, stat, smpl) -> None: stat=hst.integers(0, 0xFFFF), smpl=hst.integers(0, 0xFF_FFF_FFF), ) -def test_generate_guid(loc, stat, smpl) -> None: +def test_generate_guid(loc: "int", stat: "int", smpl: "int") -> None: """ Generate a guid and verify that it is parsed or raises if a sample name is given @@ -116,7 +122,7 @@ def test_generate_guid(loc, stat, smpl) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) @given(loc=hst.integers(-10, 350)) -def test_set_guid_location_code(loc, monkeypatch) -> None: +def test_set_guid_location_code(loc: "int", monkeypatch: "pytest.MonkeyPatch") -> None: monkeypatch.setattr("builtins.input", lambda x: str(loc)) orig_cfg = qc.config original_loc = orig_cfg["GUID_components"]["location"] @@ -136,7 +142,9 @@ def test_set_guid_location_code(loc, monkeypatch) -> None: suppress_health_check=(HealthCheck.function_scoped_fixture,), ) @given(ws=hst.integers(-10, 17000000)) -def test_set_guid_workstation_code(ws, monkeypatch) -> None: +def test_set_guid_workstation_code( + ws: "int", monkeypatch: "pytest.MonkeyPatch" +) -> None: monkeypatch.setattr("builtins.input", lambda x: str(ws)) orig_cfg = qc.config @@ -158,8 +166,8 @@ def test_set_guid_workstation_code(ws, monkeypatch) -> None: stats=hst.lists(hst.integers(0, 0xFFFF), min_size=2, max_size=2, unique=True), smpls=hst.lists(hst.integers(0, 0xFF_FFF_FFF), min_size=2, max_size=2, unique=True), ) -def test_filter_guid(locs, stats, smpls) -> None: - def make_test_guid(cfg, loc: int, smpl: int, stat: int): +def test_filter_guid(locs: "list[int]", stats: "list[int]", smpls: "list[int]") -> None: + def make_test_guid(cfg: "Config", loc: int, smpl: int, stat: int) -> "str": cfg["GUID_components"]["location"] = loc cfg["GUID_components"]["work_station"] = stat cfg["GUID_components"]["sample"] = smpl diff --git a/tests/dataset/test_links.py b/tests/dataset/test_links.py index e0b3571299f5..9cb3433830de 100644 --- a/tests/dataset/test_links.py +++ b/tests/dataset/test_links.py @@ -72,7 +72,7 @@ def test_link_construction_passes() -> None: @settings(max_examples=20) @given(not_guid=hst.text()) -def test_link_construction_raises(not_guid) -> None: +def test_link_construction_raises(not_guid: "str") -> None: head_guid = generate_guid() tail_guid = generate_guid() edge_type = "fit" @@ -146,7 +146,7 @@ def test_link_to_string_and_back() -> None: @settings(max_examples=5, deadline=1200) @given(N=hst.integers(min_value=0, max_value=25)) -def test_links_to_str_and_back(N) -> None: +def test_links_to_str_and_back(N: "int") -> None: links = generate_some_links(N) new_links = str_to_links(links_to_str(links)) diff --git a/tests/dataset/test_measurement_extensions.py b/tests/dataset/test_measurement_extensions.py index 37136b786cf3..ab84afca6cd5 100644 --- a/tests/dataset/test_measurement_extensions.py +++ b/tests/dataset/test_measurement_extensions.py @@ -24,31 +24,48 @@ from qcodes.parameters import Parameter, ParameterWithSetpoints from qcodes.validators import Arrays +if TYPE_CHECKING: + from numpy.typing import NDArray + + from qcodes.dataset.experiment_container import Experiment +if TYPE_CHECKING: + from pytest_mock import MockerFixture + + from qcodes.dataset.data_set_protocol import DataSetProtocol + if TYPE_CHECKING: from collections.abc import Sequence def assert_dataset_as_expected( - dataset, dims_dict: dict[str, int], data_vars: "Sequence[str]" -): + dataset: "DataSetProtocol", dims_dict: dict[str, int], data_vars: "Sequence[str]" +) -> "None": xr_ds = dataset.to_xarray_dataset() assert xr_ds.sizes == dims_dict assert set(xr_ds.data_vars) == set(data_vars) @pytest.fixture(name="default_params") -def default_params_(): - set1 = Parameter("set1", get_cmd=None, set_cmd=None, initial_value=0) - set2 = Parameter("set2", get_cmd=None, set_cmd=None, initial_value=0) - set3 = Parameter("set3", get_cmd=None, set_cmd=None, initial_value=0) +def default_params_() -> ( + "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]" +): + set1: Parameter[float] = Parameter( + "set1", get_cmd=None, set_cmd=None, initial_value=0 + ) + set2: Parameter[float] = Parameter( + "set2", get_cmd=None, set_cmd=None, initial_value=0 + ) + set3: Parameter[float] = Parameter( + "set3", get_cmd=None, set_cmd=None, initial_value=0 + ) - def get_set1(): + def get_set1() -> "float": return set1() - def get_sum23(): + def get_sum23() -> "float": return set2() + set3() - def get_diff23(): + def get_diff23() -> "float": return set2() - set3() meas1 = Parameter("meas1", get_cmd=get_set1, set_cmd=False) @@ -59,12 +76,14 @@ def get_diff23(): @pytest.fixture(name="pws_params") -def pws_params_(default_params): +def pws_params_( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", +) -> "tuple[ParameterWithSetpoints[NDArray[np.float64]], Parameter[float]]": sweep_start = 0 sweep_stop = 10 sweep_points = 11 - def get_pws_results(): + def get_pws_results() -> "NDArray[np.float64]": setpoints_arr = np.linspace(sweep_start, sweep_stop, sweep_points) return setpoints_arr**2 * set1() @@ -85,14 +104,19 @@ def get_pws_results(): @pytest.fixture(name="default_database_and_experiment") -def default_database_and_experiment_(tmp_path): +def default_database_and_experiment_( + tmp_path: "Path", +) -> "Experiment": db_path = Path(tmp_path) / "context_tests.db" initialise_or_create_database_at(db_path) experiment = load_or_create_experiment("context_tests") return experiment -def test_context(default_params, default_database_and_experiment): +def test_context( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": _ = default_database_and_experiment set1, set2, set3, meas1, meas2, meas3 = default_params metadata_dict = { # Nesting dictionaries does NOT work here @@ -153,7 +177,10 @@ def test_context(default_params, default_database_and_experiment): assert datasets[1].metadata == {} -def test_dond_into(default_params, default_database_and_experiment): +def test_dond_into( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": experiment = default_database_and_experiment set1, _, _, meas1, _, _ = default_params @@ -178,7 +205,10 @@ def test_dond_into(default_params, default_database_and_experiment): ) -def test_dond_into_and_context(default_params, default_database_and_experiment): +def test_dond_into_and_context( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": _ = default_database_and_experiment set1, set2, set3, meas1, meas2, meas3 = default_params @@ -211,7 +241,10 @@ def test_dond_into_and_context(default_params, default_database_and_experiment): ) -def test_linsweeper(default_params, default_database_and_experiment): +def test_linsweeper( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": _ = default_database_and_experiment set1, set2, _, meas1, meas2, _ = default_params @@ -235,7 +268,9 @@ def test_linsweeper(default_params, default_database_and_experiment): ) -def test_nested_linsweeper(default_params): +def test_nested_linsweeper( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", +) -> "None": set1, set2, _, _, _, _ = default_params linsweeper1 = LinSweeper(set1, 0, 1, 11, 0.001) linsweeper2 = LinSweeper(set2, -1, 0, 6, 0.001) @@ -259,7 +294,10 @@ def test_nested_linsweeper(default_params): ) -def test_context_with_pws(pws_params, default_database_and_experiment): +def test_context_with_pws( + pws_params: "tuple[ParameterWithSetpoints[NDArray[np.float64]], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": _ = default_database_and_experiment pws1, set1 = pws_params dataset_definition = [DataSetDefinition("dataset_1", [set1], [pws1])] @@ -270,6 +308,8 @@ def test_context_with_pws(pws_params, default_database_and_experiment): datasets = [datasaver.dataset for datasaver in datasavers] assert len(datasets) == 1 + assert isinstance(pws1.setpoints[0].vals, Arrays) + assert pws1.setpoints[0].vals.shape is not None assert_dataset_as_expected( datasets[0], dims_dict={ @@ -281,8 +321,10 @@ def test_context_with_pws(pws_params, default_database_and_experiment): def test_dond_into_with_callables( - default_params, default_database_and_experiment, mocker -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", + mocker: "MockerFixture", +) -> "None": experiment = default_database_and_experiment set1, _, _, meas1, _, _ = default_params @@ -312,8 +354,9 @@ def test_dond_into_with_callables( def test_dond_into_fails_with_together_sweeps( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": experiment = default_database_and_experiment set1, set2, _, meas1, _, _ = default_params @@ -333,7 +376,10 @@ def test_dond_into_fails_with_together_sweeps( ) -def test_dond_into_fails_with_groups(default_params, default_database_and_experiment): +def test_dond_into_fails_with_groups( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": experiment = default_database_and_experiment set1, _, _, meas1, meas2, _ = default_params @@ -354,8 +400,9 @@ def test_dond_into_fails_with_groups(default_params, default_database_and_experi def test_context_with_multiple_experiments( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": experiment = default_database_and_experiment experiment2 = load_or_create_experiment("other_experiment") set1, set2, set3, meas1, meas2, meas3 = default_params @@ -399,7 +446,10 @@ def test_context_with_multiple_experiments( assert datasets[1].exp_name == experiment2.name -def test_context_with_no_experiment(default_params, default_database_and_experiment): +def test_context_with_no_experiment( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": _ = default_database_and_experiment experiment2 = load_or_create_experiment("other_experiment") set1, set2, set3, meas1, meas2, meas3 = default_params @@ -441,8 +491,9 @@ def test_context_with_no_experiment(default_params, default_database_and_experim def test_context_with_override_experiment( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": experiment = default_database_and_experiment experiment2 = load_or_create_experiment("other_experiment") set1, set2, set3, meas1, meas2, meas3 = default_params @@ -488,8 +539,9 @@ def test_context_with_override_experiment( def test_shapes_in_dataset_definition_with_scalar_params( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test that shapes specified in DataSetDefinition are stored on the dataset.""" _ = default_database_and_experiment set1, set2, _, meas1, meas2, _ = default_params @@ -516,8 +568,9 @@ def test_shapes_in_dataset_definition_with_scalar_params( def test_shapes_in_dataset_definition_with_pws( - pws_params, default_database_and_experiment -): + pws_params: "tuple[ParameterWithSetpoints[NDArray[np.float64]], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test that shapes for ParameterWithSetpoints are stored on the dataset.""" _ = default_database_and_experiment pws1, set1 = pws_params @@ -541,7 +594,10 @@ def test_shapes_in_dataset_definition_with_pws( assert datasets[0].description.shapes == expected_shapes -def test_shapes_none_by_default(default_params, default_database_and_experiment): +def test_shapes_none_by_default( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test that shapes is None when not specified in DataSetDefinition.""" _ = default_database_and_experiment set1, _, _, meas1, _, _ = default_params @@ -562,8 +618,9 @@ def test_shapes_none_by_default(default_params, default_database_and_experiment) def test_setup_measurement_instances_sets_shapes( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test that setup_measurement_instances correctly sets shapes on Measurement.""" _ = default_database_and_experiment set1, _, _, meas1, _, _ = default_params @@ -583,8 +640,9 @@ def test_setup_measurement_instances_sets_shapes( def test_setup_measurement_instances_no_shapes( - default_params, default_database_and_experiment -): + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test that setup_measurement_instances leaves shapes as None when not specified.""" _ = default_database_and_experiment set1, _, _, meas1, _, _ = default_params @@ -601,7 +659,10 @@ def test_setup_measurement_instances_no_shapes( assert measurements[0]._shapes is None -def test_shapes_with_multiple_datasets(default_params, default_database_and_experiment): +def test_shapes_with_multiple_datasets( + default_params: "tuple[Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float], Parameter[float]]", + default_database_and_experiment: "Experiment", +) -> "None": """Test shapes are correctly applied to multiple datasets independently.""" _ = default_database_and_experiment set1, set2, set3, meas1, _, meas3 = default_params diff --git a/tests/dataset/test_metadata.py b/tests/dataset/test_metadata.py index 2fc61cfe5a65..a7b8ae244d35 100644 --- a/tests/dataset/test_metadata.py +++ b/tests/dataset/test_metadata.py @@ -1,15 +1,21 @@ -def test_get_metadata_from_dataset(dataset) -> None: +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from qcodes.dataset.data_set import DataSet + + +def test_get_metadata_from_dataset(dataset: "DataSet") -> None: dataset.add_metadata("something", 123) something = dataset.get_metadata("something") assert 123 == something -def test_get_nonexisting_metadata(dataset) -> None: +def test_get_nonexisting_metadata(dataset: "DataSet") -> None: data = dataset.get_metadata("something") assert data is None -def test_get_metadata_lower_upper_case(dataset) -> None: +def test_get_metadata_lower_upper_case(dataset: "DataSet") -> None: dataset.add_metadata("something", 123) something_lower = dataset.metadata.get("something", "didnt find lowercase") diff --git a/tests/dataset/test_nested_measurements.py b/tests/dataset/test_nested_measurements.py index dc832f7cf191..95e9d5ff86a1 100644 --- a/tests/dataset/test_nested_measurements.py +++ b/tests/dataset/test_nested_measurements.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import hypothesis.strategies as hst import numpy as np import pytest @@ -10,12 +12,20 @@ from qcodes.parameters import ParamSpecBase from tests.common import retry_until_does_not_throw +if TYPE_CHECKING: + from collections.abc import Callable +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment + from qcodes.instrument_drivers.mock_instruments import DummyInstrument + VALUE = str | float | list | np.ndarray | bool @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -def test_nested_measurement_basic(DAC, DMM, bg_writing) -> None: +def test_nested_measurement_basic( + DAC: "DummyInstrument", DMM: "DummyInstrument", bg_writing: "bool" +) -> None: meas1 = Measurement() meas1.register_parameter(DAC.ch1) meas1.register_parameter(DMM.v1, setpoints=(DAC.ch1,)) @@ -51,7 +61,7 @@ def test_nested_measurement_basic(DAC, DMM, bg_writing) -> None: @pytest.mark.usefixtures("experiment") @pytest.mark.parametrize("bg_writing", [True, False]) -def test_nested_measurement(bg_writing) -> None: +def test_nested_measurement(bg_writing: "bool") -> None: meas1 = Measurement() meas1.register_custom_parameter("foo1") meas1.register_custom_parameter("bar1", setpoints=("foo1",)) @@ -93,7 +103,7 @@ def test_nested_measurement(bg_writing) -> None: inner_len2=hst.integers(min_value=1, max_value=200), ) def test_nested_measurement_array( - bg_writing, outer_len, inner_len1, inner_len2 + bg_writing: "bool", outer_len: "int", inner_len1: "int", inner_len2: "int" ) -> None: meas1 = Measurement() meas1.register_custom_parameter("foo1", paramtype="numeric") @@ -164,13 +174,16 @@ def test_nested_measurement_array( @pytest.fixture(scope="function") -def basic_subscriber(): +def basic_subscriber() -> "Callable[[list[tuple[VALUE]], int, dict | None], None]": """ A basic subscriber that just puts results and length into state """ - def subscriber(results: list[tuple[VALUE]], length: int, state: dict) -> None: + def subscriber( + results: list[tuple[VALUE]], length: int, state: dict | None + ) -> None: + assert state is not None state[length] = results return subscriber @@ -178,7 +191,10 @@ def subscriber(results: list[tuple[VALUE]], length: int, state: dict) -> None: @pytest.mark.flaky(reruns=5) @pytest.mark.serial -def test_subscription_on_dual_datasets(experiment, basic_subscriber) -> None: +def test_subscription_on_dual_datasets( + experiment: "Experiment", + basic_subscriber: "Callable[[list[tuple[VALUE]], int, dict | None], None]", +) -> None: xparam = ParamSpecBase(name="x", paramtype="numeric", label="x parameter", unit="V") yparam1 = ParamSpecBase( name="y1", paramtype="numeric", label="y parameter", unit="Hz" @@ -223,7 +239,7 @@ def test_subscription_on_dual_datasets(experiment, basic_subscriber) -> None: @retry_until_does_not_throw( exception_class_to_expect=AssertionError, delay=0.5, tries=10 ) - def assert_expected_state(): + def assert_expected_state() -> "None": assert dataset1.subscribers[sub_id_1].state == expected_state_1 assert dataset2.subscribers[sub_id_2].state == expected_state_2 diff --git a/tests/dataset/test_parameter_with_setpoints_has_control.py b/tests/dataset/test_parameter_with_setpoints_has_control.py index d2aae82e39f5..430a0b68fa91 100644 --- a/tests/dataset/test_parameter_with_setpoints_has_control.py +++ b/tests/dataset/test_parameter_with_setpoints_has_control.py @@ -13,7 +13,9 @@ if TYPE_CHECKING: import pytest + from qcodes.dataset.data_set_protocol import ValuesType from qcodes.dataset.experiment_container import Experiment + from qcodes.parameters import ParameterBase def _make_controlled_setpoints( @@ -24,7 +26,9 @@ def _make_controlled_setpoints( """Create a ParameterWithSetpoints that infers ``controlled`` via unpack_self.""" class _ControlledSetpoints(ParameterWithSetpoints): - def unpack_self(self, value): # type: ignore[override] + def unpack_self( + self, value: "ValuesType" + ) -> "list[tuple[ParameterBase, ValuesType]]": res = super().unpack_self(value) res.append((controlled, controlled())) return res @@ -34,7 +38,7 @@ def unpack_self(self, value): # type: ignore[override] return p -def test_parameter_with_setpoints_has_control(experiment: "Experiment"): +def test_parameter_with_setpoints_has_control(experiment: "Experiment") -> "None": mp_data = np.arange(10) p1_data = np.linspace(-1, 1, 10) @@ -90,7 +94,7 @@ def test_parameter_with_setpoints_has_control(experiment: "Experiment"): npt.assert_array_almost_equal(raw_data["p2"]["p1"].ravel(), p1_data) -def test_parameter_with_setpoints_has_control_2d(experiment: "Experiment"): +def test_parameter_with_setpoints_has_control_2d(experiment: "Experiment") -> "None": """Test that an inferred parameter with the same size as its parent but different from the full dimension product is correctly included.""" diff --git a/tests/dataset/test_paramspec.py b/tests/dataset/test_paramspec.py index ed344a012032..7ad5d1a286e7 100644 --- a/tests/dataset/test_paramspec.py +++ b/tests/dataset/test_paramspec.py @@ -1,5 +1,6 @@ from keyword import iskeyword from numbers import Number +from typing import TYPE_CHECKING, TypedDict import hypothesis.strategies as hst import pytest @@ -9,8 +10,13 @@ from qcodes.dataset.descriptions.param_spec import ParamSpec from qcodes.parameters import ParamSpecBase +if TYPE_CHECKING: + from hypothesis.strategies import SearchStrategy -def valid_identifier(**kwargs): + from qcodes.dataset.descriptions.param_spec import ParamSpecDict + + +def valid_identifier(**kwargs: "int") -> "SearchStrategy[str]": """Return a strategy which generates a valid Python Identifier""" if "min_size" not in kwargs: kwargs["min_size"] = 4 @@ -20,6 +26,15 @@ def valid_identifier(**kwargs): ).filter(lambda x: x[0].isalpha() and x.isidentifier() and not (iskeyword(x))) +class _ParamSpecKwargs(TypedDict): + name: str + paramtype: str + label: str | None + unit: str | None + depends_on: list[ParamSpec | str] + inferred_from: list[ParamSpec | str] + + # This strategy generates a dict of kwargs needed to instantiate a valid # ParamSpec object valid_paramspec_kwargs = hst.fixed_dictionaries( @@ -39,7 +54,7 @@ def valid_identifier(**kwargs): @pytest.fixture -def version_0_dicts(): +def version_0_dicts() -> "list[ParamSpecDict]": sers = [] sers.append( { @@ -65,7 +80,7 @@ def version_0_dicts(): @pytest.fixture -def version_0_objects(): +def version_0_objects() -> "list[ParamSpec]": """ The ParamSpecs that the dictionaries above represent """ @@ -103,7 +118,14 @@ def version_0_objects(): elements=hst.sampled_from(["numeric", "array", "text"]), min_size=6, max_size=6 ), ) -def test_creation(name, sp1, sp2, inff1, inff2, paramtype) -> None: +def test_creation( + name: "str", + sp1: "str", + sp2: "str", + inff1: "str", + inff2: "str", + paramtype: "list[str]", +) -> None: invalid_types = ("np.array", "ndarray", "lala", "", Number, ndarray, 0, None) for inv_type in invalid_types: with pytest.raises(ValueError): @@ -149,7 +171,7 @@ def test_creation(name, sp1, sp2, inff1, inff2, paramtype) -> None: @given(name=hst.text(min_size=1)) -def test_repr(name) -> None: +def test_repr(name: "str") -> None: okay_types = ["array", "numeric", "text"] for okt in okay_types: @@ -172,7 +194,7 @@ def test_repr(name) -> None: name2=hst.text(min_size=4, max_size=100, alphabet=alphabet), name3=hst.text(min_size=4, max_size=100, alphabet=alphabet), ) -def test_depends_on(name1, name2, name3) -> None: +def test_depends_on(name1: "str", name2: "str", name3: "str") -> None: ps2 = ParamSpec(name2, "numeric") ps3 = ParamSpec(name3, "numeric") @@ -194,7 +216,7 @@ def test_depends_on(name1, name2, name3) -> None: name2=hst.text(min_size=4, max_size=100, alphabet=alphabet), name3=hst.text(min_size=4, max_size=100, alphabet=alphabet), ) -def test_inferred_from(name1, name2, name3) -> None: +def test_inferred_from(name1: "str", name2: "str", name3: "str") -> None: ps2 = ParamSpec(name2, "numeric") ps3 = ParamSpec(name3, "numeric") @@ -216,7 +238,7 @@ def test_inferred_from(name1, name2, name3) -> None: name1=hst.text(min_size=4, max_size=100, alphabet=alphabet), name2=hst.text(min_size=4, max_size=100, alphabet=alphabet), ) -def test_copy(name1, name2) -> None: +def test_copy(name1: "str", name2: "str") -> None: ps_indep = ParamSpec(name1, "numeric") ps = ParamSpec(name2, "numeric", depends_on=[ps_indep, "other_param"]) ps_copy = ps.copy() @@ -265,14 +287,16 @@ def test_convert_to_dict() -> None: assert ser["inferred_from"] == p1._inferred_from -def test_from_dict(version_0_dicts, version_0_objects) -> None: +def test_from_dict( + version_0_dicts: "list[ParamSpecDict]", version_0_objects: "list[ParamSpec]" +) -> None: for sdict, ps in zip(version_0_dicts, version_0_objects): deps = ParamSpec._from_dict(sdict) assert ps == deps @given(paramspecs=hst.lists(valid_paramspec_kwargs, min_size=2, max_size=2)) -def test_hash(paramspecs) -> None: +def test_hash(paramspecs: "list[_ParamSpecKwargs]") -> None: p1 = ParamSpec(**paramspecs[0]) p2 = ParamSpec(**paramspecs[1]) @@ -300,7 +324,11 @@ def test_hash(paramspecs) -> None: add_to_2_dep=hst.booleans(), ) def test_hash_with_deferred_and_inferred_as_paramspecs( - paramspecs, add_to_1_inf, add_to_1_dep, add_to_2_inf, add_to_2_dep + paramspecs: "list[_ParamSpecKwargs]", + add_to_1_inf: "bool", + add_to_1_dep: "bool", + add_to_2_inf: "bool", + add_to_2_dep: "bool", ) -> None: """ Test that hashing works if 'inferred_from' and/or 'depends_on' contain @@ -339,7 +367,7 @@ def test_hash_with_deferred_and_inferred_as_paramspecs( @given(paramspecs=hst.lists(valid_paramspec_kwargs, min_size=1, max_size=1)) -def test_base_version(paramspecs) -> None: +def test_base_version(paramspecs: "list[_ParamSpecKwargs]") -> None: kwargs = paramspecs[0] ps = ParamSpec(**kwargs) diff --git a/tests/dataset/test_plotting.py b/tests/dataset/test_plotting.py index 5ceb47476a71..d052bbe54f33 100644 --- a/tests/dataset/test_plotting.py +++ b/tests/dataset/test_plotting.py @@ -23,6 +23,12 @@ from qcodes.parameters import Parameter from qcodes.plotting.axis_labels import _ENGINEERING_PREFIXES, _UNITS_FOR_RESCALING +if TYPE_CHECKING: + from hypothesis.strategies import DataObject + from numpy.typing import NDArray +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment + if TYPE_CHECKING: from qcodes.dataset.data_export import DSPlotData @@ -61,7 +67,11 @@ class TerminateLoopException(Exception): ) @settings(suppress_health_check=[HealthCheck.too_slow]) def test_rescaled_ticks_and_units( - scale, unit, param_name, param_label, data_strategy + scale: "int", + unit: "str", + param_name: "str", + param_label: "str", + data_strategy: "DataObject | NDArray[np.float64]", ) -> None: if isinstance(data_strategy, np.ndarray): # No need to generate data, because it is being passed @@ -126,7 +136,9 @@ def test_rescaled_ticks_and_units( assert "2.12346" == ticks_formatter(2.123456789 / (10 ** (-scale))) -def test_plot_by_id_line_and_heatmap(experiment, request: FixtureRequest) -> None: +def test_plot_by_id_line_and_heatmap( + experiment: "Experiment", request: FixtureRequest +) -> None: """ Test that line plots and heatmaps can be plotted together """ @@ -160,7 +172,10 @@ def test_plot_by_id_line_and_heatmap(experiment, request: FixtureRequest) -> Non @pytest.mark.parametrize("nan_setpoints", [True, False]) @pytest.mark.parametrize("shifted", [True, False]) def test_plot_dataset_2d_shaped( - experiment, request: FixtureRequest, nan_setpoints, shifted + experiment: "Experiment", + request: FixtureRequest, + nan_setpoints: "bool", + shifted: "bool", ) -> None: """ Test plotting of preshaped data on a grid that may or may not be shifted @@ -378,7 +393,9 @@ def test__complex_to_real_preparser_complex_setpoint() -> None: @pytest.mark.parametrize("params", [None, "y", "y2", ["y", "y2"]]) -def test_plot_dataset_parameters(experiment, request: FixtureRequest, params) -> None: +def test_plot_dataset_parameters( + experiment: "Experiment", request: FixtureRequest, params: "str | list[str] | None" +) -> None: """ Test plotting of specified parameters with plot_dataset function. diff --git a/tests/dataset/test_raw_data_storage.py b/tests/dataset/test_raw_data_storage.py index 04e6eee2f354..f4e9aa165d38 100644 --- a/tests/dataset/test_raw_data_storage.py +++ b/tests/dataset/test_raw_data_storage.py @@ -418,7 +418,9 @@ def test_subscribe_before_start_defers_and_fires(self) -> None: received: list[int] = [] - def callback(results, length, state): + def callback( + results: list[tuple[object, ...]], length: int, state: object + ) -> None: received.append(length) # Subscribe while still pristine - no results table exists yet. diff --git a/tests/dataset/test_snapshot.py b/tests/dataset/test_snapshot.py index b723033574e0..d58a4077bb8a 100644 --- a/tests/dataset/test_snapshot.py +++ b/tests/dataset/test_snapshot.py @@ -1,4 +1,5 @@ import json +from typing import TYPE_CHECKING import numpy import pytest @@ -8,16 +9,21 @@ from qcodes.parameters import ManualParameter, Parameter from qcodes.station import Station +if TYPE_CHECKING: + from collections.abc import Generator +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment + @pytest.fixture # scope is "function" per default -def dac(): +def dac() -> "Generator[DummyInstrument, None, None]": dac = DummyInstrument("dummy_dac", gates=["ch1", "ch2"]) yield dac dac.close() @pytest.fixture -def dmm(): +def dmm() -> "Generator[DummyInstrument, None, None]": dmm = DummyInstrument("dummy_dmm", gates=["v1", "v2"]) yield dmm dmm.close() @@ -25,7 +31,10 @@ def dmm(): @pytest.mark.parametrize("pass_station", (True, False)) def test_station_snapshot_during_measurement( - experiment, dac, dmm, pass_station + experiment: "Experiment", + dac: "DummyInstrument", + dmm: "DummyInstrument", + pass_station: "bool", ) -> None: station = Station() station.add_component(dac) @@ -77,7 +86,9 @@ def test_station_snapshot_during_measurement( assert expected_snapshot == data_saver.dataset.snapshot -def test_snapshot_creation_for_types_not_supported_by_builtin_json(experiment) -> None: +def test_snapshot_creation_for_types_not_supported_by_builtin_json( + experiment: "Experiment", +) -> None: """ Test that `Measurement`/`Runner`/`DataSaver` infrastructure successfully dumps station snapshots in JSON format in cases when the @@ -119,7 +130,7 @@ def test_snapshot_creation_for_types_not_supported_by_builtin_json(experiment) - def test_station_snapshot_in_measurement_refreshes_only_invalid_caches( - experiment, + experiment: "Experiment", ) -> None: """ The station snapshot taken by a ``Measurement`` uses ``update="Only_invalid"`` diff --git a/tests/dataset/test_sqlite_base.py b/tests/dataset/test_sqlite_base.py index a48978d00ae6..19af1c240bdb 100644 --- a/tests/dataset/test_sqlite_base.py +++ b/tests/dataset/test_sqlite_base.py @@ -7,6 +7,7 @@ import time import unicodedata from contextlib import contextmanager +from typing import TYPE_CHECKING from unittest.mock import patch import hypothesis.strategies as hst @@ -34,11 +35,20 @@ from .helper_functions import verify_data_dict +if TYPE_CHECKING: + from collections.abc import Generator + + from qcodes.dataset.sqlite.connection import AtomicConnection +if TYPE_CHECKING: + from pathlib import Path + + from qcodes.dataset.experiment_container import Experiment + _unicode_categories = ("Lu", "Ll", "Lt", "Lm", "Lo", "Nd", "Pc", "Pd", "Zs") @contextmanager -def shadow_conn(path_to_db: str): +def shadow_conn(path_to_db: str) -> "Generator[AtomicConnection, None, None]": """ Simple context manager to create a connection for testing and close it on exit @@ -49,7 +59,7 @@ def shadow_conn(path_to_db: str): @pytest.fixture(name="simple_run_describer") -def _make_simple_run_describer(): +def _make_simple_run_describer() -> "Generator[RunDescriber, None, None]": x = ParamSpecBase("x", "numeric") t = ParamSpecBase("t", "numeric") y = ParamSpecBase("y", "numeric") @@ -61,7 +71,7 @@ def _make_simple_run_describer(): yield rundescriber -def test_path_to_dbfile(tmp_path) -> None: +def test_path_to_dbfile(tmp_path: "Path") -> None: tempdb = str(tmp_path / "database.db") conn = mut_db.connect(tempdb) try: @@ -71,14 +81,14 @@ def test_path_to_dbfile(tmp_path) -> None: conn.close() -def test_one_raises_on_no_results(experiment) -> None: +def test_one_raises_on_no_results(experiment: "Experiment") -> None: conn = experiment.conn with pytest.raises(RuntimeError, match="Expected one row"): mut_help.one(conn.cursor(), column="Something_you_dont_have") -def test_one_raises_on_more_than_one_result(experiment) -> None: +def test_one_raises_on_more_than_one_result(experiment: "Experiment") -> None: conn = experiment.conn # create another experiment with so that the query below returns @@ -95,7 +105,7 @@ def test_one_raises_on_more_than_one_result(experiment) -> None: mut_help.one(cur, column="exp_id") -def test_one_raises_on_wrong_column_name(experiment) -> None: +def test_one_raises_on_wrong_column_name(experiment: "Experiment") -> None: conn = experiment.conn query = """ @@ -108,7 +118,7 @@ def test_one_raises_on_wrong_column_name(experiment) -> None: mut_help.one(cur, column="eXP_id") -def test_one_raises_on_wrong_column_index(experiment) -> None: +def test_one_raises_on_wrong_column_index(experiment: "Experiment") -> None: conn = experiment.conn query = """ @@ -121,7 +131,7 @@ def test_one_raises_on_wrong_column_index(experiment) -> None: mut_help.one(cur, column=1) -def test_one_works_if_given_column_index(experiment) -> None: +def test_one_works_if_given_column_index(experiment: "Experiment") -> None: # This test relies on the fact that there's only one experiment in the # given database conn = experiment.conn @@ -137,7 +147,7 @@ def test_one_works_if_given_column_index(experiment) -> None: assert exp_id == experiment.exp_id -def test_one_works_if_given_column_name(experiment) -> None: +def test_one_works_if_given_column_name(experiment: "Experiment") -> None: # This test relies on the fact that there's only one experiment in the # given database conn = experiment.conn @@ -153,7 +163,7 @@ def test_one_works_if_given_column_name(experiment) -> None: assert exp_id == experiment.exp_id -def test_atomic_transaction_raises(experiment) -> None: +def test_atomic_transaction_raises(experiment: "Experiment") -> None: conn = experiment.conn bad_sql = '""' @@ -162,7 +172,7 @@ def test_atomic_transaction_raises(experiment) -> None: mut_conn.atomic_transaction(conn, bad_sql) -def test_atomic_raises(experiment) -> None: +def test_atomic_raises(experiment: "Experiment") -> None: conn = experiment.conn bad_sql = '""' @@ -172,7 +182,7 @@ def test_atomic_raises(experiment) -> None: assert error_caused_by(excinfo, "syntax error") -def test_insert_many_values_raises(experiment) -> None: +def test_insert_many_values_raises(experiment: "Experiment") -> None: conn = experiment.conn with pytest.raises(ValueError): @@ -181,7 +191,7 @@ def test_insert_many_values_raises(experiment) -> None: ) -def test_get_non_existing_metadata_returns_none(experiment) -> None: +def test_get_non_existing_metadata_returns_none(experiment: "Experiment") -> None: assert ( mut_queries.get_data_by_tag_and_table_name( experiment.conn, "something", "results" @@ -191,7 +201,7 @@ def test_get_non_existing_metadata_returns_none(experiment) -> None: @given(table_name=hst.text(max_size=50)) -def test__validate_table_raises(table_name) -> None: +def test__validate_table_raises(table_name: "str") -> None: should_raise = False for char in table_name: if unicodedata.category(char) not in _unicode_categories: @@ -204,7 +214,9 @@ def test__validate_table_raises(table_name) -> None: assert mut_queries._validate_table_name(table_name) -def test_get_dependents_simple(experiment, simple_run_describer) -> None: +def test_get_dependents_simple( + experiment: "Experiment", simple_run_describer: "RunDescriber" +) -> None: (_, run_id, _) = mut_queries.create_run( experiment.conn, experiment.exp_id, @@ -220,7 +232,7 @@ def test_get_dependents_simple(experiment, simple_run_describer) -> None: assert deps == [layout_id] -def test_get_layout_id_with_invalid_parameter_type(dataset) -> None: +def test_get_layout_id_with_invalid_parameter_type(dataset: "DataSet") -> None: with pytest.raises(ValueError, match="Wrong parameter type, must be ParamSpec"): mut_queries._get_layout_id( dataset.conn, @@ -229,7 +241,7 @@ def test_get_layout_id_with_invalid_parameter_type(dataset) -> None: ) -def test_get_dependents(experiment) -> None: +def test_get_dependents(experiment: "Experiment") -> None: # more parameters, more complicated dependencies x = ParamSpecBase("x", "numeric") t = ParamSpecBase("t", "numeric") @@ -265,36 +277,36 @@ def test_get_dependents(experiment) -> None: assert deps == expected_deps -def test_column_in_table(dataset) -> None: +def test_column_in_table(dataset: "DataSet") -> None: assert mut_help.is_column_in_table(dataset.conn, "runs", "run_id") assert not mut_help.is_column_in_table(dataset.conn, "runs", "non-existing-column") -def test_run_exist(dataset) -> None: +def test_run_exist(dataset: "DataSet") -> None: assert mut_queries.run_exists(dataset.conn, dataset.run_id) assert not mut_queries.run_exists(dataset.conn, dataset.run_id + 1) -def test_get_last_run(dataset) -> None: +def test_get_last_run(dataset: "DataSet") -> None: assert dataset.run_id == mut_queries.get_last_run(dataset.conn, dataset.exp_id) assert dataset.run_id == mut_queries.get_last_run(dataset.conn) -def test_get_last_run_no_runs(experiment) -> None: +def test_get_last_run_no_runs(experiment: "Experiment") -> None: assert None is mut_queries.get_last_run(experiment.conn, experiment.exp_id) assert None is mut_queries.get_last_run(experiment.conn) -def test_get_last_experiment(experiment) -> None: +def test_get_last_experiment(experiment: "Experiment") -> None: assert experiment.exp_id == mut_queries.get_last_experiment(experiment.conn) -def test_get_last_experiment_no_experiments(empty_temp_db) -> None: +def test_get_last_experiment_no_experiments(empty_temp_db: "None") -> None: conn = mut_db.connect(get_DB_location()) assert None is mut_queries.get_last_experiment(conn) -def test_update_runs_description(dataset) -> None: +def test_update_runs_description(dataset: "DataSet") -> None: invalid_descs = ["{}", "description"] for idesc in invalid_descs: @@ -305,7 +317,7 @@ def test_update_runs_description(dataset) -> None: mut_queries.update_run_description(dataset.conn, dataset.run_id, desc) -def test_runs_table_columns(empty_temp_db) -> None: +def test_runs_table_columns(empty_temp_db: "None") -> None: """ Ensure that the column names of a pristine runs table are what we expect """ @@ -320,7 +332,7 @@ def test_runs_table_columns(empty_temp_db) -> None: assert colnames == [] -def test_get_parameter_data(scalar_dataset) -> None: +def test_get_parameter_data(scalar_dataset: "DataSet") -> None: ds = scalar_dataset input_names = ["param_3"] @@ -380,7 +392,7 @@ def test_get_parameter_data_independent_parameters( ) -def test_is_run_id_in_db(empty_temp_db) -> None: +def test_is_run_id_in_db(empty_temp_db: "None") -> None: conn = mut_db.connect(get_DB_location()) mut_queries.new_experiment(conn, "test_exp", "no_sample") @@ -400,13 +412,15 @@ def test_is_run_id_in_db(empty_temp_db) -> None: assert expected_dict == acquired_dict -def test_atomic_creation(experiment, simple_run_describer) -> None: +def test_atomic_creation( + experiment: "Experiment", simple_run_describer: "RunDescriber" +) -> None: """ " Test that dataset creation is atomic. Test for https://github.com/QCoDeS/Qcodes/issues/1444 """ - def just_throw(*args): + def just_throw(*args: "object") -> "None": raise RuntimeError("This breaks adding metadata") # first we patch add_data_to_dynamic_columns to throw an exception @@ -456,7 +470,7 @@ def just_throw(*args): assert len(runs) == 1 -def test_set_run_timestamp(dataset) -> None: +def test_set_run_timestamp(dataset: "DataSet") -> None: assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None @@ -476,7 +490,7 @@ def test_set_run_timestamp(dataset) -> None: assert error_caused_by(ei, ("Can not set run_timestamp; it has already been set")) -def test_set_run_timestamp_explicit(dataset) -> None: +def test_set_run_timestamp_explicit(dataset: "DataSet") -> None: assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None @@ -495,7 +509,7 @@ def test_set_run_timestamp_explicit(dataset) -> None: assert error_caused_by(ei, "Can not set run_timestamp; it has already been set") -def test_mark_run_complete(dataset) -> None: +def test_mark_run_complete(dataset: "DataSet") -> None: assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None @@ -510,7 +524,7 @@ def test_mark_run_complete(dataset) -> None: assert dataset.completed_timestamp_raw > time_now -def test_mark_run_complete_twice(dataset, caplog: LogCaptureFixture) -> None: +def test_mark_run_complete_twice(dataset: "DataSet", caplog: LogCaptureFixture) -> None: assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None @@ -548,7 +562,7 @@ def test_mark_run_complete_twice(dataset, caplog: LogCaptureFixture) -> None: assert dataset.completed_timestamp_raw > completed_time -def test_mark_run_complete_explicit_time(dataset) -> None: +def test_mark_run_complete_explicit_time(dataset: "DataSet") -> None: assert dataset.run_timestamp_raw is None assert dataset.completed_timestamp_raw is None @@ -562,7 +576,7 @@ def test_mark_run_complete_explicit_time(dataset) -> None: mut_queries.mark_run_complete(dataset.conn, dataset.run_id) -def test_connect_read_only_mode(tmp_path): +def test_connect_read_only_mode(tmp_path: "Path") -> "None": """ Test that connecting with read_only=True allows reading but not writing. """ diff --git a/tests/dataset/test_sqlite_connection.py b/tests/dataset/test_sqlite_connection.py index 8cfc935d99e7..e55d29f645d2 100644 --- a/tests/dataset/test_sqlite_connection.py +++ b/tests/dataset/test_sqlite_connection.py @@ -29,14 +29,14 @@ from pathlib import Path -def sqlite_conn_in_transaction(conn: sqlite3.Connection): +def sqlite_conn_in_transaction(conn: sqlite3.Connection) -> "bool": assert isinstance(conn, sqlite3.Connection) assert True is conn.in_transaction assert None is conn.isolation_level return True -def conn_plus_in_transaction(conn: AtomicConnection): +def conn_plus_in_transaction(conn: AtomicConnection) -> "bool": assert isinstance(conn, AtomicConnection) assert True is conn.atomic_in_progress assert None is conn.isolation_level @@ -44,14 +44,16 @@ def conn_plus_in_transaction(conn: AtomicConnection): return True -def sqlite_conn_is_idle(conn: sqlite3.Connection, isolation=None): +def sqlite_conn_is_idle( + conn: sqlite3.Connection, isolation: "str | None" = None +) -> "bool": assert isinstance(conn, sqlite3.Connection) assert False is conn.in_transaction assert isolation == conn.isolation_level return True -def conn_plus_is_idle(conn: AtomicConnection, isolation=None): +def conn_plus_is_idle(conn: AtomicConnection, isolation: "str | None" = None) -> "bool": assert isinstance(conn, AtomicConnection) assert False is conn.atomic_in_progress assert isolation == conn.isolation_level @@ -124,7 +126,7 @@ def test_atomic_with_exception() -> None: assert 25 == sqlite_conn.execute("PRAGMA user_version").fetchall()[0][0] -def test_atomic_with_keyboardinterrupt(tmp_path) -> None: +def test_atomic_with_keyboardinterrupt(tmp_path: "Path") -> None: dbfile = str(tmp_path / "temp.db") conn = AtomicConnection(dbfile) isolation_level = conn.isolation_level @@ -149,7 +151,7 @@ def test_atomic_with_keyboardinterrupt(tmp_path) -> None: assert [(2,)] == reader.execute("SELECT x FROM t").fetchall() -def test_nested_atomic_with_keyboardinterrupt(tmp_path) -> None: +def test_nested_atomic_with_keyboardinterrupt(tmp_path: "Path") -> None: dbfile = str(tmp_path / "temp.db") conn = AtomicConnection(dbfile) isolation_level = conn.isolation_level @@ -185,7 +187,7 @@ def test_atomic_on_outmost_connection_that_is_in_transaction() -> None: @pytest.mark.parametrize("in_transaction", (True, False)) -def test_atomic_on_connection_plus_that_is_in_progress(in_transaction) -> None: +def test_atomic_on_connection_plus_that_is_in_progress(in_transaction: "bool") -> None: sqlite_conn = AtomicConnection(":memory:") # explicitly set to True for testing purposes @@ -248,7 +250,7 @@ def test_two_nested_atomics() -> None: def test_that_use_of_atomic_commits_only_at_outermost_context( - tmp_path, + tmp_path: "Path", ) -> None: """ This test tests the behavior of `AtomicConnection` that is created from @@ -332,7 +334,7 @@ def test_that_use_of_atomic_commits_only_at_outermost_context( assert 3 == len(control_conn.execute(get_all_runs).fetchall()) -def test_atomic_transaction(tmp_path) -> None: +def test_atomic_transaction(tmp_path: "Path") -> None: """Test that atomic_transaction works for AtomicConnection""" dbfile = str(tmp_path / "temp.db") @@ -347,7 +349,7 @@ def test_atomic_transaction(tmp_path) -> None: assert sql_create_table in ctrl_conn.execute(sql_table_exists).fetchall()[0] -def test_atomic_transaction_on_sqlite3_connection_raises(tmp_path) -> None: +def test_atomic_transaction_on_sqlite3_connection_raises(tmp_path: "Path") -> None: """Test that atomic_transaction does not work for sqlite3.Connection""" dbfile = str(tmp_path / "temp.db") diff --git a/tests/dataset/test_string_data.py b/tests/dataset/test_string_data.py index 928ffbd70698..3dba7e800d25 100644 --- a/tests/dataset/test_string_data.py +++ b/tests/dataset/test_string_data.py @@ -1,4 +1,5 @@ import re +from typing import TYPE_CHECKING import hypothesis.extra.numpy as hypnumpy import hypothesis.strategies as hst @@ -12,8 +13,13 @@ from qcodes.parameters import ManualParameter, Parameter, ParamSpecBase from qcodes.validators import Strings +if TYPE_CHECKING: + from numpy.typing import NDArray +if TYPE_CHECKING: + from qcodes.dataset.experiment_container import Experiment -def test_string_via_dataset(experiment) -> None: + +def test_string_via_dataset(experiment: "Experiment") -> None: """ Test that we can save text into database via DataSet API """ @@ -31,7 +37,7 @@ def test_string_via_dataset(experiment) -> None: assert test_set.get_parameter_data()["p"]["p"] == [["some text"]] -def test_string_via_datasaver(experiment) -> None: +def test_string_via_datasaver(experiment: "Experiment") -> None: """ Test that we can save text into database via DataSaver API """ @@ -56,7 +62,7 @@ def test_string_via_datasaver(experiment) -> None: assert test_set.get_parameter_data()["p"]["p"] == np.array(["some text"]) -def test_string(experiment) -> None: +def test_string(experiment: "Experiment") -> None: """ Test that we can save text into database via Measurement API """ @@ -80,7 +86,7 @@ def test_string(experiment) -> None: assert test_set.get_parameter_data()["p"]["p"] == np.array(["some text"]) -def test_string_with_wrong_paramtype(experiment) -> None: +def test_string_with_wrong_paramtype(experiment: "Experiment") -> None: """ Test that an exception occurs when saving string data if when registering a string parameter the paramtype was not set to 'text' @@ -165,7 +171,7 @@ def test_string_saved_and_loaded_as_numeric_via_dataset() -> None: test_set.conn.close() -def test_list_of_strings(experiment) -> None: +def test_list_of_strings(experiment: "Experiment") -> None: """ Test saving list of strings via DataSaver """ @@ -211,7 +217,10 @@ def test_list_of_strings(experiment) -> None: shape=hypnumpy.array_shapes(), ) ) -def test_string_and_date_data_in_array(experiment, p_values) -> None: +def test_string_and_date_data_in_array( + experiment: "Experiment", + p_values: "NDArray[np.str_ | np.bytes_ | np.timedelta64 | np.datetime64]", +) -> None: p = Parameter( "p", label="String parameter", diff --git a/tests/dataset/test_subscribing.py b/tests/dataset/test_subscribing.py index 07750119070d..2a4c9dcd4e0e 100644 --- a/tests/dataset/test_subscribing.py +++ b/tests/dataset/test_subscribing.py @@ -1,7 +1,7 @@ # Test some subscription scenarios import logging from numbers import Number -from typing import Any +from typing import TYPE_CHECKING, Any import pytest from numpy import ndarray @@ -12,6 +12,14 @@ from qcodes.parameters import ParamSpecBase from tests.common import retry_until_does_not_throw +if TYPE_CHECKING: + from collections.abc import Callable +if TYPE_CHECKING: + from collections.abc import Generator + from pathlib import Path + + from qcodes.dataset.data_set import DataSet + log = logging.getLogger(__name__) VALUE = str | Number | list[Any] | ndarray | bool @@ -28,7 +36,7 @@ class MockSubscriber: dataset! """ - def __init__(self, ds, lg): + def __init__(self, ds: "DataSet", lg: "bool") -> None: self.lg = lg self.ds = ds @@ -39,8 +47,13 @@ def __call__( state[length] = results -def config_subscriber_factory(ds, log): - def config_subscriber(results, length, state): +def config_subscriber_factory( + ds: "DataSet", log: "logging.Logger" +) -> "Callable[[list[tuple[VALUE]], int, dict | None], None]": + def config_subscriber( + results: "list[tuple[VALUE]]", length: "int", state: "dict | None" + ) -> "None": + assert state is not None state[length] = results log.debug(f"got log {log} and dataset {ds.completed}.") @@ -48,20 +61,23 @@ def config_subscriber(results, length, state): @pytest.fixture(scope="function") -def basic_subscriber(): +def basic_subscriber() -> "Callable[[list[tuple[VALUE]], int, dict | None], None]": """ A basic subscriber that just puts results and length into state """ - def subscriber(results: list[tuple[VALUE]], length: int, state: dict) -> None: + def subscriber( + results: list[tuple[VALUE]], length: int, state: dict | None + ) -> None: + assert state is not None state[length] = results return subscriber @pytest.fixture(name="working_subscriber_config") -def _make_working_subscriber_config(tmp_path): +def _make_working_subscriber_config(tmp_path: "Path") -> "Generator[None, None, None]": # This string represents the config file in the home directory: config = """ { @@ -90,7 +106,7 @@ def _make_working_subscriber_config(tmp_path): @pytest.fixture(name="broken_subscriber_config") -def _make_broken_subscriber_config(tmp_path): +def _make_broken_subscriber_config(tmp_path: "Path") -> "Generator[None, None, None]": # This string represents the config file in the home directory: config = """ { @@ -120,7 +136,10 @@ def _make_broken_subscriber_config(tmp_path): @pytest.mark.flaky(reruns=5) @pytest.mark.serial -def test_basic_subscription(dataset, basic_subscriber) -> None: +def test_basic_subscription( + dataset: "DataSet", + basic_subscriber: "Callable[[list[tuple[VALUE]], int, dict | None], None]", +) -> None: xparam = ParamSpecBase(name="x", paramtype="numeric", label="x parameter", unit="V") yparam = ParamSpecBase( name="y", paramtype="numeric", label="y parameter", unit="Hz" @@ -144,7 +163,7 @@ def test_basic_subscription(dataset, basic_subscriber) -> None: @retry_until_does_not_throw( exception_class_to_expect=AssertionError, delay=0.5, tries=10 ) - def assert_expected_state(): + def assert_expected_state() -> "None": assert dataset.subscribers[sub_id].state == expected_state assert_expected_state() @@ -161,7 +180,10 @@ def assert_expected_state(): @pytest.mark.usefixtures("working_subscriber_config") -def test_subscription_from_config(dataset, basic_subscriber) -> None: +def test_subscription_from_config( + dataset: "DataSet", + basic_subscriber: "Callable[[list[tuple[VALUE]], int, dict | None], None]", +) -> None: """ This test is similar to `test_basic_subscription`, with the only difference that another subscriber from a config file is added. @@ -191,7 +213,7 @@ def test_subscription_from_config(dataset, basic_subscriber) -> None: expected_state[x + 1] = [(x, y)] @retry_until_does_not_throw(exception_class_to_expect=AssertionError, tries=10) - def assert_expected_state(): + def assert_expected_state() -> "None": assert dataset.subscribers[sub_id].state == expected_state assert dataset.subscribers[sub_id_c].state == expected_state @@ -199,7 +221,7 @@ def assert_expected_state(): @pytest.mark.usefixtures("broken_subscriber_config") -def test_subscription_from_config_wrong_name(dataset) -> None: +def test_subscription_from_config_wrong_name(dataset: "DataSet") -> None: """ This test checks that an exception is thrown if a wrong name for a subscriber is passed diff --git a/tests/dataset_generators.py b/tests/dataset_generators.py index b54624cfa277..7f1e196514ff 100644 --- a/tests/dataset_generators.py +++ b/tests/dataset_generators.py @@ -1,12 +1,21 @@ +from typing import TYPE_CHECKING + import numpy as np from qcodes.dataset.descriptions.dependencies import InterDependencies_ from qcodes.parameters import ParamSpecBase +if TYPE_CHECKING: + from qcodes.dataset.data_set import DataSet + def dataset_with_outliers_generator( - ds, data_offset=5, low_outlier=-3, high_outlier=1, background_noise=True -): + ds: "DataSet", + data_offset: float = 5, + low_outlier: float = -3, + high_outlier: float = 1, + background_noise: bool = True, +) -> "DataSet": x = ParamSpecBase("x", "numeric", label="Flux", unit="e^2/hbar") t = ParamSpecBase("t", "numeric", label="Time", unit="s") z = ParamSpecBase("z", "numeric", label="Majorana number", unit="Anyon") diff --git a/tests/delegate/conftest.py b/tests/delegate/conftest.py index 38868839ae0a..a0d6d6de25b6 100644 --- a/tests/delegate/conftest.py +++ b/tests/delegate/conftest.py @@ -1,32 +1,36 @@ import os import pathlib +from typing import TYPE_CHECKING import pytest from qcodes.instrument_drivers.mock_instruments import MockDAC, MockField, MockLockin from qcodes.station import Station +if TYPE_CHECKING: + from qcodes.instrument.delegate import InstrumentGroup + PARENT_DIR = pathlib.Path(__file__).parent.absolute() @pytest.fixture(scope="function") -def dac(): +def dac() -> MockDAC: return MockDAC("dac", num_channels=3) @pytest.fixture(scope="function") -def field_x(): +def field_x() -> MockField: return MockField("field_x") @pytest.fixture(scope="function") -def lockin(): +def lockin() -> MockLockin: _lockin = MockLockin(name="lockin") return _lockin @pytest.fixture(scope="function") -def station(dac, lockin, field_x): +def station(dac: MockDAC, lockin: MockLockin, field_x: MockField) -> Station: _station = Station() _station.add_component(dac) _station.add_component(lockin) @@ -35,12 +39,12 @@ def station(dac, lockin, field_x): @pytest.fixture() -def chip_config(): +def chip_config() -> str: return os.path.join(PARENT_DIR, "data/chip.yml") @pytest.fixture() -def chip(station, chip_config): +def chip(station: Station, chip_config: str) -> "InstrumentGroup": if hasattr(station, "MockChip_123"): return station.MockChip_123 @@ -50,5 +54,5 @@ def chip(station, chip_config): @pytest.fixture() -def chip_config_typo(): +def chip_config_typo() -> str: return os.path.join(PARENT_DIR, "data/chip_typo.yml") diff --git a/tests/delegate/test_delegate_instrument.py b/tests/delegate/test_delegate_instrument.py index a712f01fad68..b221757afa15 100644 --- a/tests/delegate/test_delegate_instrument.py +++ b/tests/delegate/test_delegate_instrument.py @@ -1,3 +1,4 @@ +from typing import TYPE_CHECKING from unittest.mock import patch import pytest @@ -7,14 +8,20 @@ from qcodes.instrument.delegate import DelegateInstrument from qcodes.instrument_drivers.mock_instruments import MockField +if TYPE_CHECKING: + from qcodes.instrument_drivers.mock_instruments import MockDAC + from qcodes.station import Station -def test_mock_dac(dac) -> None: + +def test_mock_dac(dac: "MockDAC") -> None: assert dac.ch01.voltage() == 0.0 dac.ch01.voltage(1.0) assert dac.ch01.voltage() == 1.0 -def test_mock_field_delegate(station, field_x, chip_config) -> None: +def test_mock_field_delegate( + station: "Station", field_x: MockField, chip_config: str +) -> None: with patch.object( MockField, "set_field", wraps=field_x.set_field ) as mock_set_field: @@ -38,7 +45,7 @@ def test_mock_field_delegate(station, field_x, chip_config) -> None: assert_almost_equal(field.ramp_X_field(), 0.0) -def test_delegate_channel_instrument(station, chip_config) -> None: +def test_delegate_channel_instrument(station: "Station", chip_config: str) -> None: station.load_config_file(chip_config) switch = station.load_switch(station=station) @@ -56,7 +63,9 @@ def test_delegate_channel_instrument(station, chip_config) -> None: assert state.gnd == "off" -def test_invalid_parameter_paths_raise(station, request: pytest.FixtureRequest) -> None: +def test_invalid_parameter_paths_raise( + station: "Station", request: pytest.FixtureRequest +) -> None: """A parameter must map to either a single path or a sequence of paths.""" name = "delegate_with_invalid_paths" diff --git a/tests/delegate/test_device.py b/tests/delegate/test_device.py index 60e005fda835..c94faa2c6109 100644 --- a/tests/delegate/test_device.py +++ b/tests/delegate/test_device.py @@ -1,4 +1,5 @@ import os +from typing import TYPE_CHECKING import numpy as np import pytest @@ -6,8 +7,15 @@ from qcodes.dataset import Measurement from qcodes.instrument_drivers.mock_instruments import DummyChannel, MockCustomChannel +if TYPE_CHECKING: + from qcodes.instrument.delegate import InstrumentGroup + from qcodes.instrument_drivers.mock_instruments import MockDAC, MockLockin + from qcodes.station import Station -def test_device(station, chip_config, dac, lockin) -> None: + +def test_device( + station: "Station", chip_config: str, dac: "MockDAC", lockin: "MockLockin" +) -> None: assert os.path.exists(chip_config) station.load_config_file(chip_config) chip = station.load_MockChip_123(station=station) @@ -23,7 +31,7 @@ def test_device(station, chip_config, dac, lockin) -> None: @pytest.mark.usefixtures("experiment") -def test_device_meas(station, chip) -> None: +def test_device_meas(station: "Station", chip: "InstrumentGroup") -> None: meas = Measurement(station=station) device = chip.device1 meas.register_parameter(device.gate) @@ -39,7 +47,7 @@ def test_device_meas(station, chip) -> None: assert len(datasaver.dataset.to_pandas_dataframe_dict()["device1_drain"]) == 10 -def test_device_with_channels(chip, station) -> None: +def test_device_with_channels(chip: "InstrumentGroup", station: "Station") -> None: device = chip.channel_device assert device.gate_1 == station.dac.ch01 @@ -59,7 +67,9 @@ def test_device_with_channels(chip, station) -> None: assert device.readout() == 30 -def test_device_with_custom_channels(chip, station) -> None: +def test_device_with_custom_channels( + chip: "InstrumentGroup", station: "Station" +) -> None: device = chip.channel_device_custom assert device.gate_1._dac_channel == station.dac.ch01 @@ -71,7 +81,7 @@ def test_device_with_custom_channels(chip, station) -> None: assert isinstance(device.fast_gate, DummyChannel) -def test_chip_definition(chip_config_typo, station) -> None: +def test_chip_definition(chip_config_typo: str, station: "Station") -> None: station.load_config_file(chip_config_typo) with pytest.raises(KeyError): _ = station.load_MockChip_123(station=station) diff --git a/tests/drivers/AlazarTech/test_alazar_api.py b/tests/drivers/AlazarTech/test_alazar_api.py index 7b778abbb557..431816024d6a 100644 --- a/tests/drivers/AlazarTech/test_alazar_api.py +++ b/tests/drivers/AlazarTech/test_alazar_api.py @@ -7,6 +7,7 @@ import gc import logging import os +from typing import TYPE_CHECKING from weakref import WeakValueDictionary import pytest @@ -18,11 +19,15 @@ API_SUCCESS, ERROR_CODES, Capability, + ReturnCode, ) from qcodes.instrument_drivers.AlazarTech.dll_wrapper import DllWrapperMeta +if TYPE_CHECKING: + from collections.abc import Generator -def _skip_if_alazar_dll_and_boards_not_installed(): + +def _skip_if_alazar_dll_and_boards_not_installed() -> pytest.MarkDecorator: if not os.path.exists(f"{AlazarTechATS.dll_path}.dll"): return pytest.mark.skip( "Alazar API DLL was not found in 'AlazarTechATS.dll_path'." @@ -43,22 +48,22 @@ def _skip_if_alazar_dll_and_boards_not_installed(): @pytest.fixture -def alazar(): +def alazar() -> "Generator[AlazarTechATS, None, None]": alazar = AlazarTechATS("alazar", system_id=SYSTEM_ID, board_id=BOARD_ID) yield alazar alazar.close() @pytest.fixture -def alazar_api(): +def alazar_api() -> "Generator[AlazarATSAPI, None, None]": yield AlazarATSAPI(AlazarTechATS.dll_path) def test_alazar_api_singleton_behavior(caplog: LogCaptureFixture) -> None: - def using_msg(dll_path): + def using_msg(dll_path: str) -> str: return f"Using existing instance for DLL path {dll_path}." - def creating_msg(dll_path): + def creating_msg(dll_path: str) -> str: return f"Creating new instance for DLL path {dll_path}." assert DllWrapperMeta._instances == WeakValueDictionary() @@ -119,7 +124,7 @@ def test_find_boards() -> None: assert boards[0]["board_id"] == BOARD_ID -def test_get_board_info(alazar_api) -> None: +def test_get_board_info(alazar_api: AlazarATSAPI) -> None: info = AlazarTechATS.get_board_info( api=alazar_api, system_id=SYSTEM_ID, board_id=BOARD_ID ) @@ -134,7 +139,7 @@ def test_get_board_info(alazar_api) -> None: assert info["board_id"] == BOARD_ID -def test_idn(alazar) -> None: +def test_idn(alazar: AlazarTechATS) -> None: idn = alazar.get_idn() assert { "firmware", @@ -153,10 +158,12 @@ def test_idn(alazar) -> None: "max_samples", } == set(idn.keys()) assert idn["vendor"] == "AlazarTech" - assert idn["model"][:3] == "ATS" + model = idn["model"] + assert isinstance(model, str) + assert model[:3] == "ATS" -def test_return_codes_are_correct(alazar_api) -> None: +def test_return_codes_are_correct(alazar_api: AlazarATSAPI) -> None: """ Test correctness of the coded return codes (success, failure, unknowns), and consistency with what `AlazarErrorToText` function returns. @@ -167,44 +174,44 @@ def test_return_codes_are_correct(alazar_api) -> None: assert alazar_api.error_to_text(API_SUCCESS) == "ApiSuccess" - lower_unknown = API_SUCCESS - 1 + lower_unknown = ReturnCode(API_SUCCESS - 1) assert alazar_api.error_to_text(lower_unknown) == "Unknown" - upper_unknown = max(list(ERROR_CODES.keys())) + 1 + upper_unknown = ReturnCode(max(list(ERROR_CODES.keys())) + 1) assert alazar_api.error_to_text(upper_unknown) == "Unknown" -def test_get_channel_info_convenient(alazar) -> None: +def test_get_channel_info_convenient(alazar: AlazarTechATS) -> None: bps, max_s = alazar.api.get_channel_info_(alazar._handle) assert isinstance(bps, int) assert isinstance(max_s, int) -def test_get_cpld_version_convenient(alazar) -> None: +def test_get_cpld_version_convenient(alazar: AlazarTechATS) -> None: cpld_ver = alazar.api.get_cpld_version_(alazar._handle) assert isinstance(cpld_ver, str) assert len(cpld_ver.split(".")) == 2 -def test_get_driver_version_convenient(alazar_api) -> None: +def test_get_driver_version_convenient(alazar_api: AlazarATSAPI) -> None: driver_ver = alazar_api.get_driver_version_() assert isinstance(driver_ver, str) assert len(driver_ver.split(".")) == 3 -def test_get_sdk_version_convenient(alazar_api) -> None: +def test_get_sdk_version_convenient(alazar_api: AlazarATSAPI) -> None: sdk_ver = alazar_api.get_sdk_version_() assert isinstance(sdk_ver, str) assert len(sdk_ver.split(".")) == 3 -def test_query_capability_convenient(alazar) -> None: +def test_query_capability_convenient(alazar: AlazarTechATS) -> None: cap = Capability.GET_SERIAL_NUMBER cap_value = alazar.api.query_capability_(alazar._handle, cap) assert isinstance(cap_value, int) -def test_writing_and_reading_registers(alazar) -> None: +def test_writing_and_reading_registers(alazar: AlazarTechATS) -> None: """ The approach is to read the register that includes information about trigger holdoff parameter, and write the same value back to the board. diff --git a/tests/drivers/AlazarTech/test_alazar_buffer.py b/tests/drivers/AlazarTech/test_alazar_buffer.py index 5a88d112892d..b557f861ec51 100644 --- a/tests/drivers/AlazarTech/test_alazar_buffer.py +++ b/tests/drivers/AlazarTech/test_alazar_buffer.py @@ -1,9 +1,13 @@ import ctypes +from typing import TYPE_CHECKING import pytest from qcodes.instrument_drivers.AlazarTech.ATS import Buffer +if TYPE_CHECKING: + from qcodes.instrument_drivers.AlazarTech.ATS import CtypesTypes + def test_buffer_is_allocated_when_initiated() -> None: b = Buffer(ctypes.c_uint8, 25) @@ -14,5 +18,5 @@ def test_buffer_is_allocated_when_initiated() -> None: "ctype", (ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint32, ctypes.c_int32, ctypes.c_float), ) -def test_supported_ctypes_for_sample(ctype) -> None: +def test_supported_ctypes_for_sample(ctype: "CtypesTypes") -> None: Buffer(ctype, 8) diff --git a/tests/drivers/AlazarTech/test_dll_wrapper.py b/tests/drivers/AlazarTech/test_dll_wrapper.py index d371b8854008..12db274653e6 100644 --- a/tests/drivers/AlazarTech/test_dll_wrapper.py +++ b/tests/drivers/AlazarTech/test_dll_wrapper.py @@ -16,10 +16,10 @@ def test_wrapped_dll_singleton_behavior(caplog: LogCaptureFixture) -> None: - def using_msg(dll_path): + def using_msg(dll_path: str) -> str: return f"Using existing instance for DLL path {dll_path}." - def creating_msg(dll_path): + def creating_msg(dll_path: str) -> str: return f"Creating new instance for DLL path {dll_path}." dll_path_1 = "ntdll.dll" diff --git a/tests/drivers/keysight_b1500/test_commandlist.py b/tests/drivers/keysight_b1500/test_commandlist.py index 5076a1dd7c28..0663abd4dcca 100644 --- a/tests/drivers/keysight_b1500/test_commandlist.py +++ b/tests/drivers/keysight_b1500/test_commandlist.py @@ -1,10 +1,15 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.Keysight.keysightb1500.message_builder import CommandList +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture -def uut(): +def uut() -> "Generator[CommandList, None, None]": yield CommandList() @@ -15,7 +20,7 @@ def test_append(uut: CommandList) -> None: assert ["a", "b"] == uut -def test_set_final(uut) -> None: +def test_set_final(uut: CommandList) -> None: uut.append("a") uut.set_final() @@ -24,7 +29,7 @@ def test_set_final(uut) -> None: uut.append("b") -def test_clear(uut) -> None: +def test_clear(uut: CommandList) -> None: uut.append("a") uut.set_final() @@ -34,7 +39,7 @@ def test_clear(uut) -> None: assert ["b"] == uut -def test_string_representation(uut) -> None: +def test_string_representation(uut: CommandList) -> None: uut.append("a") uut.append("b") diff --git a/tests/drivers/keysight_b1500/test_messagebuilder.py b/tests/drivers/keysight_b1500/test_messagebuilder.py index bc394357d07d..5e8182f1dfdb 100644 --- a/tests/drivers/keysight_b1500/test_messagebuilder.py +++ b/tests/drivers/keysight_b1500/test_messagebuilder.py @@ -1,4 +1,5 @@ import re +from typing import TYPE_CHECKING, NoReturn import pytest @@ -8,9 +9,12 @@ as_csv, ) +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture -def mb(): +def mb() -> "Generator[MessageBuilder, None, None]": yield MessageBuilder() @@ -22,21 +26,23 @@ def test_as_csv() -> None: assert "1,2" == as_csv([c.ChNr.SLOT_01_CH1, c.ChNr.SLOT_02_CH1]) -def _skip(): +def _skip() -> NoReturn: pytest.skip("not implemented yet") -def test_cmd(mb) -> None: +def test_cmd(mb: MessageBuilder) -> None: cmd = mb.aad(1, 0).ach(1, 5).ab() assert "AAD 1,0;ACH 1,5;AB" == cmd.message -def test_raise_error_on_appending_command_after_final_command(mb) -> None: +def test_raise_error_on_appending_command_after_final_command( + mb: MessageBuilder, +) -> None: with pytest.raises(ValueError): mb.aad(1, 0).ab().ach(1, 5) -def test_exception_on_too_long_message(mb) -> None: +def test_exception_on_too_long_message(mb: MessageBuilder) -> None: length = 0 while length < 250: mb.os() @@ -52,7 +58,7 @@ def test_exception_on_too_long_message(mb) -> None: _ = mb.message -def test_clear_message_queue(mb) -> None: +def test_clear_message_queue(mb: MessageBuilder) -> None: mb.aad(1, 0) assert mb.message == "AAD 1,0" @@ -61,7 +67,7 @@ def test_clear_message_queue(mb) -> None: assert mb.message == "" -def test_aad(mb) -> None: +def test_aad(mb: MessageBuilder) -> None: assert "AAD 1,0" == mb.aad(c.ChNr.SLOT_01_CH1, c.AAD.Type.HIGH_SPEED).message mb.clear_message_queue() @@ -72,11 +78,11 @@ def test_aad(mb) -> None: ) -def test_ab(mb) -> None: +def test_ab(mb: MessageBuilder) -> None: assert "AB" == mb.ab().message -def test_ach(mb) -> None: +def test_ach(mb: MessageBuilder) -> None: assert "ACH 1,5" == mb.ach(c.ChNr.SLOT_01_CH1, c.ChNr.SLOT_05_CH1).message mb.clear_message_queue() @@ -88,7 +94,7 @@ def test_ach(mb) -> None: assert "ACH" == mb.ach().message -def test_act(mb) -> None: +def test_act(mb: MessageBuilder) -> None: assert "ACT 0,1" == mb.act(c.ACT.Mode.AUTO, 1).message mb.clear_message_queue() @@ -96,15 +102,15 @@ def test_act(mb) -> None: assert "ACT 2" == mb.act(c.ACT.Mode.PLC).message -def test_acv(mb) -> None: +def test_acv(mb: MessageBuilder) -> None: assert "ACV 7,0.01" == mb.acv(c.ChNr.SLOT_07_CH1, 0.01).message -def test_adj(mb) -> None: +def test_adj(mb: MessageBuilder) -> None: assert "ADJ 9,1" == mb.adj(c.ChNr.SLOT_09_CH1, c.ADJ.Mode.MANUAL).message -def test_adj_query(mb) -> None: +def test_adj_query(mb: MessageBuilder) -> None: assert "ADJ? 1" == mb.adj_query(c.ChNr.SLOT_01_CH1).message mb.clear_message_queue() @@ -114,7 +120,7 @@ def test_adj_query(mb) -> None: ) -def test_ait(mb) -> None: +def test_ait(mb: MessageBuilder) -> None: assert ( "AIT 2,3,0.001" == mb.ait( @@ -128,7 +134,7 @@ def test_ait(mb) -> None: ) -def test_aitm(mb) -> None: +def test_aitm(mb: MessageBuilder) -> None: assert "AITM 0" == mb.aitm(c.APIVersion.B1500).message @@ -136,25 +142,25 @@ def test_aitm_query(mb: MessageBuilder) -> None: assert "AITM?" == mb.aitm_query().message -def test_als(mb) -> None: +def test_als(mb: MessageBuilder) -> None: with pytest.raises(NotImplementedError): mb.als(c.ChNr.SLOT_01_CH1, 1, b"a") -def test_als_query(mb) -> None: +def test_als_query(mb: MessageBuilder) -> None: assert "ALS? 1" == mb.als_query(c.ChNr.SLOT_01_CH1).message -def test_alw(mb) -> None: +def test_alw(mb: MessageBuilder) -> None: with pytest.raises(NotImplementedError): mb.alw(c.ChNr.SLOT_01_CH1, 1, b"a") -def test_alw_query(mb) -> None: +def test_alw_query(mb: MessageBuilder) -> None: assert "ALW? 1" == mb.alw_query(c.ChNr.SLOT_01_CH1).message -def test_av(mb) -> None: +def test_av(mb: MessageBuilder) -> None: assert "AV 10" == mb.av(10).message mb.clear_message_queue() assert "AV -50" == mb.av(-50).message @@ -162,13 +168,13 @@ def test_av(mb) -> None: assert "AV 100,1" == mb.av(100, c.AV.Mode.MANUAL).message -def test_az(mb) -> None: +def test_az(mb: MessageBuilder) -> None: assert "AZ 0" == mb.az(False).message mb.clear_message_queue() assert "AZ 1" == mb.az(True).message -def test_bc(mb) -> None: +def test_bc(mb: MessageBuilder) -> None: assert "BC" == mb.bc().message @@ -180,7 +186,7 @@ def test_bdt(mb: MessageBuilder) -> None: assert "BDT 0.1,0.001" == mb.bdt(hold=0.1, delay=1e-3).message -def test_bdv(mb) -> None: +def test_bdv(mb: MessageBuilder) -> None: assert ( "BDV 1,0,0,100,0.01" == mb.bdv( @@ -193,7 +199,7 @@ def test_bdv(mb) -> None: ) -def test_bgi(mb) -> None: +def test_bgi(mb: MessageBuilder) -> None: assert ( "BGI 1,0,1e-08,14,1e-06" == mb.bgi( @@ -206,96 +212,96 @@ def test_bgi(mb) -> None: ) -def test_bgv(mb) -> None: +def test_bgv(mb: MessageBuilder) -> None: assert "BGV 1,0,0.1,12,5" == mb.bgv(1, 0, 0.1, 12, 5).message -def test_bsi(mb) -> None: +def test_bsi(mb: MessageBuilder) -> None: assert "BSI 1,0,1e-12,1e-06,10" == mb.bsi(1, 0, 1e-12, 1e-6, 10).message -def test_bsm(mb) -> None: +def test_bsm(mb: MessageBuilder) -> None: assert "BSM 1,2,3" == mb.bsm(1, 2, 3).message -def test_bssi(mb) -> None: +def test_bssi(mb: MessageBuilder) -> None: assert "BSSI 1,0,1e-06,10" == mb.bssi(1, 0, 1e-6, 10).message -def test_bssv(mb) -> None: +def test_bssv(mb: MessageBuilder) -> None: assert "BSSV 1,0,5,1e-06" == mb.bssv(1, 0, 5, 1e-6).message -def test_bst(mb) -> None: +def test_bst(mb: MessageBuilder) -> None: assert "BST 5,0.1" == mb.bst(5, 0.1).message -def test_bsv(mb) -> None: +def test_bsv(mb: MessageBuilder) -> None: assert "BSV 1,0,0,20,1e-06" == mb.bsv(1, 0, 0, 20, 1e-6).message -def test_bsvm(mb) -> None: +def test_bsvm(mb: MessageBuilder) -> None: assert "BSVM 1" == mb.bsvm(1).message -def test_ca(mb) -> None: +def test_ca(mb: MessageBuilder) -> None: assert "CA" == mb.ca().message -def test_cal_query(mb) -> None: +def test_cal_query(mb: MessageBuilder) -> None: assert "*CAL?" == mb.cal_query().message -def test_cl(mb) -> None: +def test_cl(mb: MessageBuilder) -> None: assert "CL" == mb.cl().message mb.clear_message_queue() assert "CL 1,2,3,5" == mb.cl([1, 2, 3, 5]).message -def test_clcorr(mb) -> None: +def test_clcorr(mb: MessageBuilder) -> None: assert "CLCORR 9,1" == mb.clcorr(9, 1).message -def test_cm(mb) -> None: +def test_cm(mb: MessageBuilder) -> None: assert "CM 0" == mb.cm(False).message -def test_cmm(mb) -> None: +def test_cmm(mb: MessageBuilder) -> None: assert "CMM 1,2" == mb.cmm(1, 2).message -def test_cn(mb) -> None: +def test_cn(mb: MessageBuilder) -> None: assert "CN" == mb.cn().message mb.clear_message_queue() assert "CN 1,2,3,5" == mb.cn([1, 2, 3, 5]).message -def test_cnx(mb) -> None: +def test_cnx(mb: MessageBuilder) -> None: assert "CNX" == mb.cnx().message mb.clear_message_queue() assert "CNX 1,2,3,5" == mb.cnx([1, 2, 3, 5]).message -def test_corr_query(mb) -> None: +def test_corr_query(mb: MessageBuilder) -> None: assert "CORR? 9,3" == mb.corr_query(9, 3).message -def test_corrdt(mb) -> None: +def test_corrdt(mb: MessageBuilder) -> None: assert ( "CORRDT 9,3000000,0,0,0,0,0,0" == mb.corrdt(9, 3000000, 0, 0, 0, 0, 0, 0).message ) -def test_corrdt_query(mb) -> None: +def test_corrdt_query(mb: MessageBuilder) -> None: assert "CORRDT? 9,1" == mb.corrdt_query(9, 1).message -def test_corrl(mb) -> None: +def test_corrl(mb: MessageBuilder) -> None: assert "CORRL 9,3000000" == mb.corrl(9, 3000000).message -def test_corrl_query(mb) -> None: +def test_corrl_query(mb: MessageBuilder) -> None: assert "CORRL? 9" == mb.corrl_query(9).message mb.clear_message_queue() assert "CORRL? 9,2" == mb.corrl_query(9, 2).message @@ -308,382 +314,382 @@ def test_corrser_query(mb: MessageBuilder) -> None: ) -def test_corrst(mb) -> None: - assert "CORRST 3,1,1" == mb.corrst(3, 1, 1).message +def test_corrst(mb: MessageBuilder) -> None: + assert "CORRST 3,1,1" == mb.corrst(3, 1, True).message -def test_corrst_query(mb) -> None: +def test_corrst_query(mb: MessageBuilder) -> None: assert "CORRST? 1,2" == mb.corrst_query(1, 2).message -def test_dcorr(mb) -> None: +def test_dcorr(mb: MessageBuilder) -> None: assert "DCORR 3,1,100,0.1,0.2" == mb.dcorr(3, 1, 100, 0.1, 0.2).message -def test_dcorr_query(mb) -> None: +def test_dcorr_query(mb: MessageBuilder) -> None: assert "DCORR? 3,1" == mb.dcorr_query(3, 1).message -def test_dcv(mb) -> None: +def test_dcv(mb: MessageBuilder) -> None: assert "DCV 3,2.5" == mb.dcv(3, 2.5).message -def test_di(mb) -> None: +def test_di(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_diag_query(mb) -> None: +def test_diag_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_do(mb) -> None: +def test_do(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_dsmplarm(mb) -> None: +def test_dsmplarm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_dsmplflush(mb) -> None: +def test_dsmplflush(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_dsmplsetup(mb) -> None: +def test_dsmplsetup(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_dv(mb) -> None: +def test_dv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_dz(mb) -> None: +def test_dz(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_emg_query(mb) -> None: +def test_emg_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_end(mb) -> None: +def test_end(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erc(mb) -> None: +def test_erc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmaa(mb) -> None: +def test_ercmaa(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmaa_query(mb) -> None: +def test_ercmaa_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmagrd(mb) -> None: +def test_ercmagrd(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmagrd_query(mb) -> None: +def test_ercmagrd_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmaio(mb) -> None: +def test_ercmaio(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmaio_query(mb) -> None: +def test_ercmaio_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ercmapfgd(mb) -> None: +def test_ercmapfgd(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpa(mb) -> None: +def test_erhpa(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpa_query(mb) -> None: +def test_erhpa_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpe(mb) -> None: +def test_erhpe(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpe_query(mb) -> None: +def test_erhpe_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpl(mb) -> None: +def test_erhpl(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpl_query(mb) -> None: +def test_erhpl_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpp(mb) -> None: +def test_erhpp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpp_query(mb) -> None: +def test_erhpp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpqg(mb) -> None: +def test_erhpqg(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpqg_query(mb) -> None: +def test_erhpqg_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpr(mb) -> None: +def test_erhpr(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhpr_query(mb) -> None: +def test_erhpr_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhps(mb) -> None: +def test_erhps(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhps_query(mb) -> None: +def test_erhps_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvca(mb) -> None: +def test_erhvca(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvca_query(mb) -> None: +def test_erhvca_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvctst_query(mb) -> None: +def test_erhvctst_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvp(mb) -> None: +def test_erhvp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvp_query(mb) -> None: +def test_erhvp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvpv(mb) -> None: +def test_erhvpv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvs(mb) -> None: +def test_erhvs(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erhvs_query(mb) -> None: +def test_erhvs_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erm(mb) -> None: +def test_erm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ermod(mb) -> None: +def test_ermod(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ermod_query(mb) -> None: +def test_ermod_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfda(mb) -> None: +def test_erpfda(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfda_query(mb) -> None: +def test_erpfda_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfdp(mb) -> None: +def test_erpfdp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfdp_query(mb) -> None: +def test_erpfdp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfds(mb) -> None: +def test_erpfds(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfds_query(mb) -> None: +def test_erpfds_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfga(mb) -> None: +def test_erpfga(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfga_query(mb) -> None: +def test_erpfga_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfgp(mb) -> None: +def test_erpfgp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfgp_query(mb) -> None: +def test_erpfgp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfgr(mb) -> None: +def test_erpfgr(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfgr_query(mb) -> None: +def test_erpfgr_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfqg(mb) -> None: +def test_erpfqg(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfqg_query(mb) -> None: +def test_erpfqg_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpftemp_query(mb) -> None: +def test_erpftemp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfuhca(mb) -> None: +def test_erpfuhca(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfuhca_query(mb) -> None: +def test_erpfuhca_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfuhccal_query(mb) -> None: +def test_erpfuhccal_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfuhcmax_query(mb) -> None: +def test_erpfuhcmax_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erpfuhctst(mb) -> None: +def test_erpfuhctst(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_err_query(mb) -> None: +def test_err_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_errx_query(mb) -> None: +def test_errx_query(mb: MessageBuilder) -> None: assert "ERRX?" == mb.errx_query().message mb.clear_message_queue() assert "ERRX? 0" == mb.errx_query(mode=c.ERRX.Mode.CODE_AND_MESSAGE).message -def test_ers_query(mb) -> None: +def test_ers_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erssp(mb) -> None: +def test_erssp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_erssp_query(mb) -> None: +def test_erssp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_eruhva(mb) -> None: +def test_eruhva(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_eruhva_query(mb) -> None: +def test_eruhva_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_fc(mb) -> None: +def test_fc(mb: MessageBuilder) -> None: assert "FC 3,1000" == mb.fc(3, 1000).message -def test_fl(mb) -> None: +def test_fl(mb: MessageBuilder) -> None: assert "FL 1" == mb.fl(True).message mb.clear_message_queue() assert "FL 0,1,3,5" == mb.fl(False, [1, 3, 5]).message @@ -697,7 +703,7 @@ def test_fl(mb) -> None: _ = mb.fl(False, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]).message -def test_fmt(mb) -> None: +def test_fmt(mb: MessageBuilder) -> None: assert "FMT 1" == mb.fmt(c.FMT.Format.ASCII_12_DIGITS_WITH_HEADER_CRLF_EOI).message mb.clear_message_queue() assert ( @@ -709,160 +715,160 @@ def test_fmt(mb) -> None: ) -def test_hvsmuop(mb) -> None: +def test_hvsmuop(mb: MessageBuilder) -> None: _skip() -def test_hvsmuop_query(mb) -> None: +def test_hvsmuop_query(mb: MessageBuilder) -> None: assert "HVSMUOP?" == mb.hvsmuop_query().message -def test_idn_query(mb) -> None: +def test_idn_query(mb: MessageBuilder) -> None: assert "IN" == mb.in_().message mb.clear_message_queue() assert "IN 1,2,3,5,6" == mb.in_([1, 2, 3, 5, 6]).message -def test_imp(mb) -> None: +def test_imp(mb: MessageBuilder) -> None: assert "IMP 10" == mb.imp(c.IMP.MeasurementMode.Z_THETA_RAD).message -def test_in_(mb) -> None: +def test_in_(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_intlkvth(mb) -> None: +def test_intlkvth(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_intlkvth_query(mb) -> None: +def test_intlkvth_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lgi(mb) -> None: +def test_lgi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lgv(mb) -> None: +def test_lgv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lim(mb) -> None: +def test_lim(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lim_query(mb) -> None: +def test_lim_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lmn(mb) -> None: +def test_lmn(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lop_query(mb) -> None: +def test_lop_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lrn_query(mb) -> None: +def test_lrn_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lsi(mb) -> None: +def test_lsi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lsm(mb) -> None: +def test_lsm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lssi(mb) -> None: +def test_lssi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lssv(mb) -> None: +def test_lssv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lst_query(mb) -> None: +def test_lst_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lstm(mb) -> None: +def test_lstm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lsv(mb) -> None: +def test_lsv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_lsvm(mb) -> None: +def test_lsvm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcc(mb) -> None: +def test_mcc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcpnt(mb) -> None: +def test_mcpnt(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcpnx(mb) -> None: +def test_mcpnx(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcpt(mb) -> None: +def test_mcpt(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcpws(mb) -> None: +def test_mcpws(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mcpwnx(mb) -> None: +def test_mcpwnx(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mdcv(mb) -> None: +def test_mdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mi(mb) -> None: +def test_mi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ml(mb) -> None: +def test_ml(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mm(mb) -> None: +def test_mm(mb: MessageBuilder) -> None: assert "MM 1,1" == mb.mm(mode=c.MM.Mode.SPOT, channels=[c.ChNr.SLOT_01_CH1]).message mb.clear_message_queue() assert ( @@ -874,183 +880,183 @@ def test_mm(mb) -> None: ) -def test_msc(mb) -> None: +def test_msc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_msp(mb) -> None: +def test_msp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mt(mb) -> None: +def test_mt(mb: MessageBuilder) -> None: assert "MT 0.0,0.42,32" == mb.mt(0.0, 0.42, 32).message mb.clear_message_queue() assert "MT 0.0,0.42,32,0.12" == mb.mt(0.0, 0.42, 32, 0.12).message -def test_mtdcv(mb) -> None: +def test_mtdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_mv(mb) -> None: +def test_mv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_nub_query(mb) -> None: +def test_nub_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_odsw(mb) -> None: +def test_odsw(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_odsw_query(mb) -> None: +def test_odsw_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_opc_query(mb) -> None: +def test_opc_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_os(mb) -> None: +def test_os(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_osx(mb) -> None: +def test_osx(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pa(mb) -> None: +def test_pa(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pad(mb) -> None: +def test_pad(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pax(mb) -> None: +def test_pax(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pch(mb) -> None: +def test_pch(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pch_query(mb) -> None: +def test_pch_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pdcv(mb) -> None: +def test_pdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pi(mb) -> None: +def test_pi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pt(mb) -> None: +def test_pt(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ptdcv(mb) -> None: +def test_ptdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pv(mb) -> None: +def test_pv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pwdcv(mb) -> None: +def test_pwdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pwi(mb) -> None: +def test_pwi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_pwv(mb) -> None: +def test_pwv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsc(mb) -> None: +def test_qsc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsl(mb) -> None: +def test_qsl(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsm(mb) -> None: +def test_qsm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qso(mb) -> None: +def test_qso(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsr(mb) -> None: +def test_qsr(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qst(mb) -> None: +def test_qst(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsv(mb) -> None: +def test_qsv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_qsz(mb) -> None: +def test_qsz(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_rc(mb) -> None: +def test_rc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_rcv(mb) -> None: +def test_rcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ri(mb) -> None: +def test_ri(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_rm(mb) -> None: +def test_rm(mb: MessageBuilder) -> None: assert "RM 1,2" == mb.rm(1, c.RM.Mode.AUTO_UP).message mb.clear_message_queue() assert "RM 2,3,60" == mb.rm(2, c.RM.Mode.AUTO_UP_DOWN, 60).message @@ -1059,450 +1065,452 @@ def test_rm(mb) -> None: mb.rm(c.ChNr.SLOT_01_CH1, c.RM.Mode.DEFAULT, 22) -def test_rst(mb) -> None: +def test_rst(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ru(mb) -> None: +def test_ru(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_rv(mb) -> None: +def test_rv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_rz(mb) -> None: +def test_rz(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sal(mb) -> None: +def test_sal(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sap(mb) -> None: +def test_sap(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sar(mb) -> None: +def test_sar(mb: MessageBuilder) -> None: assert "SAR 1,0" == mb.sar(1, enable_picoamp_autoranging=True).message -def test_scr(mb) -> None: +def test_scr(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ser(mb) -> None: +def test_ser(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ser_query(mb) -> None: +def test_ser_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sim(mb) -> None: +def test_sim(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sim_query(mb) -> None: +def test_sim_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sopc(mb) -> None: +def test_sopc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sopc_query(mb) -> None: +def test_sopc_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sovc(mb) -> None: +def test_sovc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sovc_query(mb) -> None: +def test_sovc_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spm(mb) -> None: +def test_spm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spm_query(mb) -> None: +def test_spm_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spp(mb) -> None: +def test_spp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spper(mb) -> None: +def test_spper(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spper_query(mb) -> None: +def test_spper_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sprm(mb) -> None: +def test_sprm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sprm_query(mb) -> None: +def test_sprm_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spst_query(mb) -> None: +def test_spst_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spt(mb) -> None: +def test_spt(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spt_query(mb) -> None: +def test_spt_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spupd(mb) -> None: +def test_spupd(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spv(mb) -> None: +def test_spv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_spv_query(mb) -> None: +def test_spv_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sre(mb) -> None: +def test_sre(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_sre_query(mb) -> None: +def test_sre_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_srp(mb) -> None: +def test_srp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ssl(mb) -> None: +def test_ssl(mb: MessageBuilder) -> None: assert "SSL 9,0" == mb.ssl(9, enable_indicator_led=False).message -def test_ssp(mb) -> None: +def test_ssp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ssr(mb) -> None: +def test_ssr(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_st(mb) -> None: +def test_st(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_stb_query(mb) -> None: +def test_stb_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_stgp(mb) -> None: +def test_stgp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_stgp_query(mb) -> None: +def test_stgp_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tacv(mb) -> None: +def test_tacv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tc(mb) -> None: +def test_tc(mb: MessageBuilder) -> None: assert "TC 3,0" == mb.tc(3, 0).message -def test_tdcv(mb) -> None: +def test_tdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tdi(mb) -> None: +def test_tdi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tdv(mb) -> None: +def test_tdv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgmo(mb) -> None: +def test_tgmo(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgp(mb) -> None: +def test_tgp(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgpc(mb) -> None: +def test_tgpc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgsi(mb) -> None: +def test_tgsi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgso(mb) -> None: +def test_tgso(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tgxo(mb) -> None: +def test_tgxo(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ti(mb) -> None: +def test_ti(mb: MessageBuilder) -> None: assert "TI 1" == mb.ti(chnum=1).message mb.clear_message_queue() assert "TI 1,-14" == mb.ti(chnum=1, i_range=c.IMeasRange.FIX_1uA).message -def test_tiv(mb) -> None: +def test_tiv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tm(mb) -> None: +def test_tm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tmacv(mb) -> None: +def test_tmacv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tmdcv(mb) -> None: +def test_tmdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tsc(mb) -> None: +def test_tsc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tsq(mb) -> None: +def test_tsq(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tsr(mb) -> None: +def test_tsr(mb: MessageBuilder) -> None: assert "TSR" == mb.tsr().message mb.clear_message_queue() assert "TSR 1" == mb.tsr(c.ChNr.SLOT_01_CH1).message -def test_tst(mb) -> None: +def test_tst(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ttc(mb) -> None: +def test_ttc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tti(mb) -> None: +def test_tti(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ttiv(mb) -> None: +def test_ttiv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ttv(mb) -> None: +def test_ttv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_tv(mb) -> None: +def test_tv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_unt_query(mb) -> None: +def test_unt_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_var(mb) -> None: +def test_var(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_var_query(mb) -> None: +def test_var_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wacv(mb) -> None: +def test_wacv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wat(mb) -> None: +def test_wat(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wdcv(mb) -> None: +def test_wdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wfc(mb) -> None: +def test_wfc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wi(mb) -> None: +def test_wi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wm(mb) -> None: +def test_wm(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wmacv(mb) -> None: +def test_wmacv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wmdcv(mb) -> None: +def test_wmdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wmfc(mb) -> None: +def test_wmfc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wncc(mb) -> None: +def test_wncc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wnu_query(mb) -> None: +def test_wnu_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wnx(mb) -> None: +def test_wnx(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_ws(mb) -> None: +def test_ws(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wsi(mb) -> None: +def test_wsi(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wsv(mb) -> None: +def test_wsv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wt(mb) -> None: +def test_wt(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wtacv(mb) -> None: +def test_wtacv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wtdcv(mb) -> None: +def test_wtdcv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wtfc(mb) -> None: +def test_wtfc(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wv(mb) -> None: +def test_wv(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_wz_query(mb) -> None: +def test_wz_query(mb: MessageBuilder) -> None: # assert '' == mb.().message _skip() -def test_xe(mb) -> None: +def test_xe(mb: MessageBuilder) -> None: assert "XE" == mb.xe().message -def test_nplc_setting_for_high_speed_vs_high_resolution_mode(mb) -> None: +def test_nplc_setting_for_high_speed_vs_high_resolution_mode( + mb: MessageBuilder, +) -> None: msg = ( mb.ait(adc_type=c.AIT.Type.HIGH_SPEED, mode=c.AIT.Mode.NPLC, coeff=3) .ait(adc_type=c.AIT.Type.HIGH_RESOLUTION, mode=c.AIT.Mode.NPLC, coeff=8) @@ -1511,7 +1519,7 @@ def test_nplc_setting_for_high_speed_vs_high_resolution_mode(mb) -> None: assert msg == "AIT 0,2,3;AIT 1,2,8" -def test_set_resolution_mode_for_each_smu(mb) -> None: +def test_set_resolution_mode_for_each_smu(mb: MessageBuilder) -> None: msg = ( mb.aad(chnum=1, adc_type=c.AAD.Type.HIGH_SPEED) .aad(chnum=2, adc_type=c.AAD.Type.HIGH_RESOLUTION) diff --git a/tests/drivers/test_agilent_e8257d.py b/tests/drivers/test_agilent_e8257d.py index d8d0ea9375ea..0e1bc6e24421 100644 --- a/tests/drivers/test_agilent_e8257d.py +++ b/tests/drivers/test_agilent_e8257d.py @@ -12,7 +12,7 @@ class TestAgilentE8257D(DriverTestCase[AgilentE8257D]): driver = AgilentE8257D @classmethod - def setUpClass(cls): + def setUpClass(cls) -> None: super().setUpClass() cls.instrument.off() # Not a test but a safety measure diff --git a/tests/drivers/test_aimtti_pl601p.py b/tests/drivers/test_aimtti_pl601p.py index df4a0fa47686..6c5582aa6e44 100644 --- a/tests/drivers/test_aimtti_pl601p.py +++ b/tests/drivers/test_aimtti_pl601p.py @@ -1,10 +1,15 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.AimTTi import AimTTiPL601 +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function", name="driver") -def _make_driver(): +def _make_driver() -> "Generator[AimTTiPL601, None, None]": driver = AimTTiPL601( "AimTTi", address="GPIB::1::INSTR", pyvisa_sim_file="AimTTi_PL601P.yaml" ) @@ -13,7 +18,7 @@ def _make_driver(): driver.close() -def test_idn(driver) -> None: +def test_idn(driver: AimTTiPL601) -> None: assert { "firmware": "3.05-4.06", "model": "PL601-P", diff --git a/tests/drivers/test_coppermountain_m5065.py b/tests/drivers/test_coppermountain_m5065.py index a091001fc79b..b4e676960bee 100644 --- a/tests/drivers/test_coppermountain_m5065.py +++ b/tests/drivers/test_coppermountain_m5065.py @@ -1,18 +1,23 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.CopperMountain import CopperMountainM5065 +if TYPE_CHECKING: + from collections.abc import Generator + class DummyM5065: - def __init__(self, *args, **kwargs): + def __init__(self, *args: object, **kwargs: object) -> None: pass - def start(self): + def start(self) -> float: return 1e6 @pytest.fixture() -def vna(): +def vna() -> "Generator[CopperMountainM5065, None, None]": instance = CopperMountainM5065( name="M5065", address="TCPIP0::localhost::hislip0::INSTR", @@ -23,45 +28,45 @@ def vna(): instance.close() -def test_m5065_instantiation(vna): +def test_m5065_instantiation(vna: CopperMountainM5065) -> None: assert vna.name == "M5065" assert vna.address == "TCPIP0::localhost::hislip0::INSTR" -def test_idn_command(vna): +def test_idn_command(vna: CopperMountainM5065) -> None: idn = vna.get_idn() assert idn["vendor"] == "CMT" assert idn["model"] == "M5065" -def test_min_and_max_frequency_defaults(vna): +def test_min_and_max_frequency_defaults(vna: CopperMountainM5065) -> None: assert vna.min_freq == 300e3 assert vna.max_freq == 6.5e9 -def test_output_param(vna): +def test_output_param(vna: CopperMountainM5065) -> None: vna.output(True) assert vna.output() is True vna.output(False) assert vna.output() is False -def test_power_param(vna): +def test_power_param(vna: CopperMountainM5065) -> None: vna.power(-20) assert vna.power() == -20 -def test_if_bandwidth_param(vna): +def test_if_bandwidth_param(vna: CopperMountainM5065) -> None: vna.if_bandwidth(1000) assert vna.if_bandwidth() == 1000 -def test_averages_param(vna): +def test_averages_param(vna: CopperMountainM5065) -> None: vna.averages(2) assert vna.averages() == 2 -def test_frequency_params(vna): +def test_frequency_params(vna: CopperMountainM5065) -> None: vna.start(1e6) vna.stop(2e6) vna.center(1.5e6) @@ -72,21 +77,23 @@ def test_frequency_params(vna): assert vna.span() == 1e6 -def test_setting_start_raises_error_when_larger_than_stop(vna): +def test_setting_start_raises_error_when_larger_than_stop( + vna: CopperMountainM5065, +) -> None: vna.stop(1e6) with pytest.raises(ValueError, match="Stop frequency"): vna.start(1e7) -def test_number_of_points_param(vna): +def test_number_of_points_param(vna: CopperMountainM5065) -> None: vna.number_of_points(201) assert vna.number_of_points() == 201 -def test_trigger_source_param(vna): +def test_trigger_source_param(vna: CopperMountainM5065) -> None: vna.trigger_source("bus") assert vna.trigger_source() == "bus" -def test_update_lin_traces(vna): +def test_update_lin_traces(vna: CopperMountainM5065) -> None: vna.update_lin_traces() diff --git a/tests/drivers/test_coppermountain_m5180.py b/tests/drivers/test_coppermountain_m5180.py index 84a55af31074..562bf444f7cc 100644 --- a/tests/drivers/test_coppermountain_m5180.py +++ b/tests/drivers/test_coppermountain_m5180.py @@ -1,18 +1,23 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.CopperMountain import CopperMountainM5180 +if TYPE_CHECKING: + from collections.abc import Generator + class DummyM5065: - def __init__(self, *args, **kwargs): + def __init__(self, *args: object, **kwargs: object) -> None: pass - def start(self): + def start(self) -> float: return 1e6 @pytest.fixture() -def vna(): +def vna() -> "Generator[CopperMountainM5180, None, None]": instance = CopperMountainM5180( name="M5180", address="TCPIP0::localhost::hislip0::INSTR", @@ -23,17 +28,17 @@ def vna(): instance.close() -def test_m5180_instantiation(vna): +def test_m5180_instantiation(vna: CopperMountainM5180) -> None: assert vna.name == "M5180" assert vna.address == "TCPIP0::localhost::hislip0::INSTR" -def test_idn_command(vna): +def test_idn_command(vna: CopperMountainM5180) -> None: idn = vna.get_idn() assert idn["vendor"] == "CMT" assert idn["model"] == "M5180" -def test_min_and_max_frequency_defaults(vna): +def test_min_and_max_frequency_defaults(vna: CopperMountainM5180) -> None: assert vna.min_freq == 300e3 assert vna.max_freq == 18e9 diff --git a/tests/drivers/test_cryomagnetics_tm620.py b/tests/drivers/test_cryomagnetics_tm620.py index 5608e9b816a5..2c9bc7294cbb 100644 --- a/tests/drivers/test_cryomagnetics_tm620.py +++ b/tests/drivers/test_cryomagnetics_tm620.py @@ -24,29 +24,31 @@ def fixture_tm620() -> "Generator[CryomagneticsModelTM620, None, None]": instrument.close() -def test_initialization(tm620): +def test_initialization(tm620: CryomagneticsModelTM620) -> None: assert tm620.name == "test_cryo_tm620" assert tm620.address == "GPIB0::1::INSTR" assert hasattr(tm620, "shield") assert hasattr(tm620, "magnet") -def test_get_A_success(tm620): +def test_get_A_success(tm620: CryomagneticsModelTM620) -> None: with patch.object(tm620, "ask", return_value="55.12K"): assert tm620._get_A() == 55.12 -def test_get_B_success(tm620): +def test_get_B_success(tm620: CryomagneticsModelTM620) -> None: with patch.object(tm620, "ask", return_value="4.21K"): assert tm620._get_B() == 4.21 -def test_parse_output_valid(tm620): +def test_parse_output_valid(tm620: CryomagneticsModelTM620) -> None: assert tm620._parse_output("55.12K") == "55.12" assert tm620._parse_output("4.34C") == "4.34" -def test_parse_output_invalid(tm620, caplog): +def test_parse_output_invalid( + tm620: CryomagneticsModelTM620, caplog: pytest.LogCaptureFixture +) -> None: with ( caplog.at_level("ERROR"), pytest.raises(ValueError, match="No floating point number found"), @@ -55,12 +57,14 @@ def test_parse_output_invalid(tm620, caplog): assert "No floating point number found in output" in caplog.text -def test_convert_to_numerics_valid(tm620): +def test_convert_to_numerics_valid(tm620: CryomagneticsModelTM620) -> None: assert tm620._convert_to_numeric("55.12") == 55.12 assert tm620._convert_to_numeric("4.34") == 4.34 -def test_convert_to_numerics_invalid(tm620, caplog): +def test_convert_to_numerics_invalid( + tm620: CryomagneticsModelTM620, caplog: pytest.LogCaptureFixture +) -> None: 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/drivers/test_keithley_2450.py b/tests/drivers/test_keithley_2450.py index 4818f4fd0181..c108ef1dd7fe 100644 --- a/tests/drivers/test_keithley_2450.py +++ b/tests/drivers/test_keithley_2450.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING import numpy as np import pytest @@ -6,9 +7,12 @@ from qcodes.instrument_drivers.Keithley import Keithley2450 +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def k2450(): +def k2450() -> "Generator[Keithley2450, None, None]": """ Create a Keithley 2450 instrument """ @@ -34,7 +38,7 @@ def test_wrong_mode(caplog: LogCaptureFixture) -> None: instrument.close() -def test_change_source_function(k2450) -> None: +def test_change_source_function(k2450: Keithley2450) -> None: """ The parameters available on the source sub-module depend on the function. """ @@ -54,7 +58,7 @@ def test_change_source_function(k2450) -> None: ) -def test_source_change_error(k2450) -> None: +def test_source_change_error(k2450: Keithley2450) -> None: """ If the sense function is in resistance mode, test that an error is generated when we change the source function @@ -72,7 +76,7 @@ def test_source_change_error(k2450) -> None: k2450.source.function("current") -def test_sense_current_mode(k2450) -> None: +def test_sense_current_mode(k2450: Keithley2450) -> None: """ Test that when we are in a sense function, for example, 'current', that the sense property is returning to the correct submodule. We also test @@ -89,7 +93,7 @@ def test_sense_current_mode(k2450) -> None: assert not hasattr(k2450.sense, other_sense_function) -def test_setpoint_always_follows_source_function(k2450) -> None: +def test_setpoint_always_follows_source_function(k2450: Keithley2450) -> None: """ Changing the source and/or sense functions should not confuse the setpoints. These should always follow the source module @@ -108,7 +112,7 @@ def test_setpoint_always_follows_source_function(k2450) -> None: assert k2450.sense.sweep.setpoints == (k2450.source.sweep_axis,) -def test_reset_sweep_on_source_change(k2450) -> None: +def test_reset_sweep_on_source_change(k2450: Keithley2450) -> None: """ If we change the source function, we need to run the sweep setup again """ @@ -123,7 +127,7 @@ def test_reset_sweep_on_source_change(k2450) -> None: k2450.source.get_sweep_axis() -def test_sweep(k2450) -> None: +def test_sweep(k2450: Keithley2450) -> None: """ Verify that we can start sweeps """ diff --git a/tests/drivers/test_keithley_26xx.py b/tests/drivers/test_keithley_26xx.py index 9a22d1f16be9..0ddfd44b6d1c 100644 --- a/tests/drivers/test_keithley_26xx.py +++ b/tests/drivers/test_keithley_26xx.py @@ -13,11 +13,13 @@ ) if TYPE_CHECKING: + from collections.abc import Generator + from qcodes.instrument_drivers.Keithley import Keithley2600Channel @pytest.fixture(scope="function", name="driver") -def _make_driver(): +def _make_driver() -> "Generator[Keithley2614B, None, None]": driver = Keithley2614B( "Keithley_2600", address="GPIB::1::INSTR", pyvisa_sim_file="Keithley_2600.yaml" ) @@ -27,14 +29,16 @@ def _make_driver(): @pytest.fixture(scope="function", name="smus") -def _make_smus(driver): +def _make_smus( + driver: Keithley2614B, +) -> "Generator[tuple[Keithley2600Channel, ...], None, None]": smu_names = {"smua", "smub"} assert smu_names == set(driver.submodules.keys()) yield tuple(getattr(driver, smu_name) for smu_name in smu_names) -def test_idn(driver) -> None: +def test_idn(driver: Keithley2614B) -> None: assert { "firmware": "3.0.0", "model": "2601B", @@ -43,7 +47,7 @@ def test_idn(driver) -> None: } == driver.IDN() -def test_smu_channels_and_their_parameters(driver) -> None: +def test_smu_channels_and_their_parameters(driver: Keithley2614B) -> None: assert {"smua", "smub"} == set(driver.submodules.keys()) for smu_name in ("smua", "smub"): @@ -154,11 +158,11 @@ def test_smu_channels_and_their_parameters(driver) -> None: def test_snapshot_updates_every_parameter( - driver, caplog: pytest.LogCaptureFixture + driver: Keithley2614B, caplog: pytest.LogCaptureFixture ) -> None: # a query missing from the sim file waits for the VISA timeout and is only logged with caplog.at_level(logging.WARNING): - driver.snapshot(update=True) + driver.snapshot(update="All") assert not [ record.getMessage() @@ -167,7 +171,9 @@ def test_snapshot_updates_every_parameter( ] -def test_setting_source_voltage_range_disables_autorange(smus) -> None: +def test_setting_source_voltage_range_disables_autorange( + smus: "tuple[Keithley2600Channel, ...]", +) -> None: for smu in smus: smu.source_autorange_v_enabled(True) assert smu.source_autorange_v_enabled() is True @@ -176,7 +182,9 @@ def test_setting_source_voltage_range_disables_autorange(smus) -> None: assert smu.source_autorange_v_enabled() is False -def test_setting_measure_voltage_range_disables_autorange(smus) -> None: +def test_setting_measure_voltage_range_disables_autorange( + smus: "tuple[Keithley2600Channel, ...]", +) -> None: for smu in smus: smu.measure_autorange_v_enabled(True) assert smu.measure_autorange_v_enabled() is True @@ -185,7 +193,9 @@ def test_setting_measure_voltage_range_disables_autorange(smus) -> None: assert smu.measure_autorange_v_enabled() is False -def test_setting_source_current_range_disables_autorange(smus) -> None: +def test_setting_source_current_range_disables_autorange( + smus: "tuple[Keithley2600Channel, ...]", +) -> None: for smu in smus: smu.source_autorange_i_enabled(True) assert smu.source_autorange_i_enabled() is True @@ -194,7 +204,9 @@ def test_setting_source_current_range_disables_autorange(smus) -> None: assert smu.source_autorange_i_enabled() is False -def test_setting_measure_current_range_disables_autorange(smus) -> None: +def test_setting_measure_current_range_disables_autorange( + smus: "tuple[Keithley2600Channel, ...]", +) -> None: for smu in smus: smu.measure_autorange_i_enabled(True) assert smu.measure_autorange_i_enabled() is True @@ -203,7 +215,7 @@ def test_setting_measure_current_range_disables_autorange(smus) -> None: assert smu.measure_autorange_i_enabled() is False -def test_fast_sweep_parameters(smus) -> None: +def test_fast_sweep_parameters(smus: "tuple[Keithley2600Channel, ...]") -> None: for smu in smus: smu = cast("Keithley2600Channel", smu) @@ -235,7 +247,7 @@ def test_fast_sweep_parameters(smus) -> None: np.testing.assert_array_almost_equal(setpoints, expected_setpoints) -def test_fastsweep(driver) -> None: +def test_fastsweep(driver: Keithley2614B) -> None: smu = driver.smua # Configure the fastsweep using LinSweep @@ -252,7 +264,7 @@ def test_fastsweep(driver) -> None: np.testing.assert_array_equal(result, fake_data) -def test_fastsweep_2d_parameters(driver) -> None: +def test_fastsweep_2d_parameters(driver: Keithley2614B) -> None: """Test 2D fastsweep configuration with inner and outer sweeps.""" smua = driver.smua smub = driver.smub @@ -286,7 +298,7 @@ def test_fastsweep_2d_parameters(driver) -> None: assert smua.fastsweep.setpoints[1] is smua.fastsweep_inner_setpoints -def test_fastsweep_2d_execution(driver) -> None: +def test_fastsweep_2d_execution(driver: Keithley2614B) -> None: """Test 2D fastsweep returns correctly shaped data.""" smua = driver.smua smub = driver.smub @@ -311,7 +323,7 @@ def test_fastsweep_2d_execution(driver) -> None: np.testing.assert_array_equal(result.flatten(), fake_data) -def test_fastsweep_channel_detection(driver) -> None: +def test_fastsweep_channel_detection(driver: Keithley2614B) -> None: """Test that channels are correctly detected from LinSweep parameters.""" smua = driver.smua smub = driver.smub @@ -336,7 +348,7 @@ def test_fastsweep_channel_detection(driver) -> None: assert result.shape == (5, 10) -def test_fastsweep_reconfigure_creates_fresh_setpoints(driver) -> None: +def test_fastsweep_reconfigure_creates_fresh_setpoints(driver: Keithley2614B) -> None: """Test that calling setup_fastsweep twice creates fresh setpoint parameters. Regression test: previously, setpoint parameters were reused and their diff --git a/tests/drivers/test_keithley_3706a.py b/tests/drivers/test_keithley_3706a.py index 12364532b561..8032a6b5359a 100644 --- a/tests/drivers/test_keithley_3706a.py +++ b/tests/drivers/test_keithley_3706a.py @@ -1,12 +1,16 @@ import itertools +from typing import TYPE_CHECKING import pytest from qcodes.instrument_drivers.Keithley.Keithley_3706A import Keithley3706A +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function", name="driver") -def _make_driver(): +def _make_driver() -> "Generator[Keithley3706A, None, None]": driver = Keithley3706A( "Keithley_3706A", address="GPIB::11::INSTR", @@ -17,7 +21,7 @@ def _make_driver(): @pytest.fixture() -def channels_in_slot_one(): +def channels_in_slot_one() -> list[str]: channels = [] for i in range(1, 7): for j in range(int(f"1{i}01"), int(f"1{i}17")): @@ -26,7 +30,7 @@ def channels_in_slot_one(): @pytest.fixture() -def channels_in_slot_two(): +def channels_in_slot_two() -> list[str]: channels = [] for i in range(1, 7): for j in range(int(f"2{i}01"), int(f"2{i}17")): @@ -35,7 +39,7 @@ def channels_in_slot_two(): @pytest.fixture() -def channels_in_slot_three(): +def channels_in_slot_three() -> list[str]: channels = [] for i in range(1, 7): for j in range(int(f"3{i}01"), int(f"3{i}17")): @@ -44,7 +48,7 @@ def channels_in_slot_three(): @pytest.fixture() -def matrix_channels(): +def matrix_channels() -> list[str]: slots = ["1", "2", "3"] rows = [["1", "2", "3", "4", "5", "6"]] * 3 columns = [ @@ -74,7 +78,7 @@ def matrix_channels(): return m_channels -def test_idn(driver) -> None: +def test_idn(driver: Keithley3706A) -> None: assert { "firmware": "01.56a", "model": "3706A-SNFP", @@ -83,7 +87,7 @@ def test_idn(driver) -> None: } == driver.get_idn() -def test_switch_card_idn(driver) -> None: +def test_switch_card_idn(driver: Keithley3706A) -> None: assert { "slot_no": "1", "model": "3730", @@ -93,15 +97,15 @@ def test_switch_card_idn(driver) -> None: } == driver.get_switch_cards()[0] -def test_installed_card_id(driver) -> None: +def test_installed_card_id(driver: Keithley3706A) -> None: assert ["1", "2", "3"] == driver._get_slot_ids() -def test_slot_names(driver) -> None: +def test_slot_names(driver: Keithley3706A) -> None: assert ["slot1", "slot2", "slot3"] == driver._get_slot_names() -def test_get_interlock_state(driver) -> None: +def test_get_interlock_state(driver: Keithley3706A) -> None: dict_list = ( { "slot_no": "1", @@ -118,22 +122,22 @@ def test_get_interlock_state(driver) -> None: assert dict_list == driver.get_interlock_state() -def test_get_number_of_rows(driver) -> None: +def test_get_number_of_rows(driver: Keithley3706A) -> None: assert [6, 6, 6] == driver._get_number_of_rows() -def test_get_number_of_columns(driver) -> None: +def test_get_number_of_columns(driver: Keithley3706A) -> None: assert [16, 16, 16] == driver._get_number_of_columns() @pytest.mark.parametrize("val", [0, 1, 2]) -def test_get_rows(driver, val) -> None: +def test_get_rows(driver: Keithley3706A, val: int) -> None: rows_in_a_slot = ["1", "2", "3", "4", "5", "6"] assert rows_in_a_slot == driver._get_rows()[val] @pytest.mark.parametrize("val", [0, 1, 2]) -def test_get_columns(driver, val) -> None: +def test_get_columns(driver: Keithley3706A, val: int) -> None: columns_in_a_slot = [ "01", "02", @@ -156,31 +160,37 @@ def test_get_columns(driver, val) -> None: @pytest.mark.parametrize("val", [1, 2, 3]) -def test_number_of_channels_by_slot(driver, val) -> None: +def test_number_of_channels_by_slot(driver: Keithley3706A, val: int) -> None: assert 96 == len(driver.get_channels_by_slot(val)) -def test_total_number_of_channels(driver) -> None: +def test_total_number_of_channels(driver: Keithley3706A) -> None: assert 3 * 96 == len(driver.get_channels()) -def test_channels_in_slot_one(driver, channels_in_slot_one) -> None: +def test_channels_in_slot_one( + driver: Keithley3706A, channels_in_slot_one: list[str] +) -> None: assert channels_in_slot_one == driver.get_channels_by_slot(1) -def test_channels_in_slot_two(driver, channels_in_slot_two) -> None: +def test_channels_in_slot_two( + driver: Keithley3706A, channels_in_slot_two: list[str] +) -> None: assert channels_in_slot_two == driver.get_channels_by_slot(2) -def test_channels_in_slot_three(driver, channels_in_slot_three) -> None: +def test_channels_in_slot_three( + driver: Keithley3706A, channels_in_slot_three: list[str] +) -> None: assert channels_in_slot_three == driver.get_channels_by_slot(3) -def test_matrix_channels(driver, matrix_channels) -> None: +def test_matrix_channels(driver: Keithley3706A, matrix_channels: list[str]) -> None: assert matrix_channels == driver.get_channels() -def test_analog_backplane_specifiers(driver) -> None: +def test_analog_backplane_specifiers(driver: Keithley3706A) -> None: specifiers = [ "1911", "1912", @@ -205,12 +215,12 @@ def test_analog_backplane_specifiers(driver) -> None: @pytest.mark.parametrize("val", ["slot1", "allslots", "3111", "3912", "2103:2116"]) -def test_validator_truth(driver, val) -> None: +def test_validator_truth(driver: Keithley3706A, val: str) -> None: assert driver._validator(val) is True @pytest.mark.parametrize( "val", ["slot12", "alslots", "5111", "912", "123213", "QCoDeS"] ) -def test_validator_falsehood(driver, val) -> None: +def test_validator_falsehood(driver: Keithley3706A, val: str) -> None: assert driver._validator(val) is False diff --git a/tests/drivers/test_keithley_7510.py b/tests/drivers/test_keithley_7510.py index 2d23aaffcba5..0f2082b6dfc9 100644 --- a/tests/drivers/test_keithley_7510.py +++ b/tests/drivers/test_keithley_7510.py @@ -1,12 +1,17 @@ +from typing import TYPE_CHECKING + import hypothesis.strategies as st import pytest from hypothesis import HealthCheck, given, settings from qcodes.instrument_drivers.Keithley import Keithley7510 +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def dmm_7510_driver(): +def dmm_7510_driver() -> "Generator[Keithley7510, None, None]": inst = Keithley7510( "Keithley_7510_sim", address="GPIB::1::INSTR", @@ -19,7 +24,7 @@ def dmm_7510_driver(): inst.close() -def test_get_idn(dmm_7510_driver) -> None: +def test_get_idn(dmm_7510_driver: Keithley7510) -> None: assert dmm_7510_driver.IDN() == { "vendor": "KEITHLEY INSTRUMENTS", "model": "DMM7510", @@ -28,7 +33,7 @@ def test_get_idn(dmm_7510_driver) -> None: } -def test_change_sense_function(dmm_7510_driver) -> None: +def test_change_sense_function(dmm_7510_driver: Keithley7510) -> None: """ Measurement should be the same as the sense function, e.g., only voltage measurement is allowed when the sense function is "voltage". @@ -42,7 +47,9 @@ def test_change_sense_function(dmm_7510_driver) -> None: @settings(deadline=None, suppress_health_check=(HealthCheck.function_scoped_fixture,)) @given(st.sampled_from((0.1, 1, 10, 100, 1000)), st.floats(0.01, 10)) -def test_set_range_and_nplc(dmm_7510_driver, upper_limit, nplc) -> None: +def test_set_range_and_nplc( + dmm_7510_driver: Keithley7510, upper_limit: float, nplc: float +) -> None: """ Test the ability of setting range and nplc value for sense function. "Voltage" is used as an example. diff --git a/tests/drivers/test_keithley_s46.py b/tests/drivers/test_keithley_s46.py index 5f5e94c0032e..fc950bcb639f 100644 --- a/tests/drivers/test_keithley_s46.py +++ b/tests/drivers/test_keithley_s46.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING import pytest from pytest import FixtureRequest, LogCaptureFixture @@ -8,6 +9,9 @@ KeithleyS46LockAcquisitionError, ) +if TYPE_CHECKING: + from collections.abc import Generator + def test_aliases_dict() -> None: """ @@ -28,7 +32,7 @@ def calc_channel_nr(alias: str) -> int: @pytest.fixture(scope="function") -def s46_six(): +def s46_six() -> "Generator[KeithleyS46, None, None]": """ A six channel-per-relay instrument """ @@ -43,7 +47,7 @@ def s46_six(): @pytest.fixture(scope="function") -def s46_four(): +def s46_four() -> "Generator[KeithleyS46, None, None]": """ A four channel-per-relay instrument """ diff --git a/tests/drivers/test_keysight_34465a.py b/tests/drivers/test_keysight_34465a.py index e7beb972ea28..bcd5f175a6e6 100644 --- a/tests/drivers/test_keysight_34465a.py +++ b/tests/drivers/test_keysight_34465a.py @@ -1,4 +1,4 @@ -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Protocol import numpy as np import pytest @@ -11,6 +11,10 @@ from collections.abc import Generator +class _AskCallable(Protocol): + def __call__(self, cmd: str) -> str: ... + + @pytest.fixture(scope="function") def driver() -> "Generator[Keysight34465A, None, None]": keysight_sim = Keysight34465A( @@ -27,7 +31,7 @@ def driver() -> "Generator[Keysight34465A, None, None]": @pytest.fixture(scope="function") def driver_with_read_and_fetch_mocked( - val_volt, + val_volt: str, ) -> "Generator[Keysight34465A, None, None]": keysight_sim = Keysight34465A( "keysight_34465A_sim", @@ -35,7 +39,9 @@ def driver_with_read_and_fetch_mocked( pyvisa_sim_file="Keysight_34465A.yaml", ) - def get_ask_with_read_mock(original_ask, read_value): + def get_ask_with_read_mock( + original_ask: _AskCallable, read_value: str + ) -> _AskCallable: def ask_with_read_mock(cmd: str) -> str: if cmd in ("READ?", "FETCH?"): return read_value @@ -69,7 +75,7 @@ def test_reset(driver: Keysight34465A) -> None: driver.reset() -def test_NPLC(driver) -> None: +def test_NPLC(driver: Keysight34465A) -> None: assert driver.NPLC.get() == 10.0 driver.NPLC.set(0.2) assert driver.NPLC.get() == 0.2 @@ -78,7 +84,7 @@ def test_NPLC(driver) -> None: @pytest.mark.parametrize("val_volt", ["100.0"]) def test_get_voltage( - driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: float + driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: str ) -> None: voltage = driver_with_read_and_fetch_mocked.volt.get() assert voltage == 100.0 @@ -86,7 +92,7 @@ def test_get_voltage( @pytest.mark.parametrize("val_volt", ["9.9e37"]) def test_get_voltage_plus_inf( - driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: float + driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: str ) -> None: voltage = driver_with_read_and_fetch_mocked.volt.get() assert voltage == np.inf @@ -94,7 +100,7 @@ def test_get_voltage_plus_inf( @pytest.mark.parametrize("val_volt", ["-9.9e37"]) def test_get_voltage_minus_inf( - driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: float + driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: str ) -> None: voltage = driver_with_read_and_fetch_mocked.volt.get() assert voltage == -np.inf @@ -102,7 +108,7 @@ def test_get_voltage_minus_inf( @pytest.mark.parametrize("val_volt", ["10, 9.9e37, -9.9e37"]) def test_get_timetrace( - driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: float + driver_with_read_and_fetch_mocked: Keysight34465A, val_volt: str ) -> None: driver_with_read_and_fetch_mocked.timetrace_npts(3) assert driver_with_read_and_fetch_mocked.timetrace_npts() == 3 diff --git a/tests/drivers/test_keysight_34934a.py b/tests/drivers/test_keysight_34934a.py index 2dd5de3b9848..c7208c69f949 100644 --- a/tests/drivers/test_keysight_34934a.py +++ b/tests/drivers/test_keysight_34934a.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import hypothesis.strategies as st import pytest from hypothesis import given @@ -5,9 +7,12 @@ from qcodes.instrument_drivers.Keysight.keysight_34934a import Keysight34934A from qcodes.instrument_drivers.Keysight.keysight_34980a import Keysight34980A +if TYPE_CHECKING: + from collections.abc import Callable, Generator + @pytest.fixture(scope="function") -def switch_driver(): +def switch_driver() -> "Generator[Keysight34980A, None, None]": inst = Keysight34980A( "keysight_34980A_sim", address="GPIB::1::INSTR", @@ -20,19 +25,23 @@ def switch_driver(): inst.close() -def test_protection_mode(switch_driver) -> None: +def test_protection_mode(switch_driver: Keysight34980A) -> None: """ To check the protection mode (34934A module only) """ - assert switch_driver.module[1].protection_mode() == "AUTO100" + module = switch_driver.module[1] + assert isinstance(module, Keysight34934A) + assert module.protection_mode() == "AUTO100" -def test_connection(switch_driver) -> None: +def test_connection(switch_driver: Keysight34980A) -> None: """ To check if a channel is closed or open """ - assert not switch_driver.module[1].is_closed(2, 3) - assert switch_driver.module[1].is_open(2, 3) + module = switch_driver.module[1] + assert isinstance(module, Keysight34934A) + assert not module.is_closed(2, 3) + assert module.is_open(2, 3) # The following is to test the numbering function for the module 34934A @@ -44,95 +53,95 @@ def test_connection(switch_driver) -> None: @given( st.sampled_from(("M1H", "M1L", "M2H", "M2L")), st.integers(1, 4), st.integers(1, 32) ) -def test_4x32(config, row, column) -> None: +def test_4x32(config: str, row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(4, 32, config) g = numbering_function_4x32(config) assert f(row, column) == g(row, column) @given(st.sampled_from(("MH", "ML")), st.integers(1, 4), st.integers(1, 64)) -def test_4x64(config, row, column) -> None: +def test_4x64(config: str, row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(4, 64, config) g = numbering_function_4x64(config) assert f(row, column) == g(row, column) @given(st.integers(1, 4), st.integers(1, 128)) -def test_4x128(row, column) -> None: +def test_4x128(row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(4, 128) g = numbering_function_4x128() assert f(row, column) == g(row, column) @given(st.sampled_from(("MH", "ML")), st.integers(1, 8), st.integers(1, 32)) -def test_8x32(config, row, column) -> None: +def test_8x32(config: str, row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(8, 32, config) g = numbering_function_8x32(config) assert f(row, column) == g(row, column) @given(st.integers(1, 8), st.integers(1, 64)) -def test_8x64(row, column) -> None: +def test_8x64(row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(8, 64) g = numbering_function_8x64() assert f(row, column) == g(row, column) @given(st.integers(1, 16), st.integers(1, 32)) -def test_16x32(row, column) -> None: +def test_16x32(row: int, column: int) -> None: f = Keysight34934A.get_numbering_function(16, 32) g = numbering_function_16x32() assert f(row, column) == g(row, column) -def numbering_function_4x32(wiring_config): +def numbering_function_4x32(wiring_config: str) -> "Callable[[int, int], str]": offsets = {"M1H": 0, "M2H": 32, "M1L": 64, "M2L": 96} - def numbering_function(row, col): + def numbering_function(row: int, col: int) -> str: n = 100 * (2 * row - 1) + col + offsets[wiring_config] return str(int(n)) return numbering_function -def numbering_function_4x64(wiring_config): +def numbering_function_4x64(wiring_config: str) -> "Callable[[int, int], str]": offsets = {"MH": 0, "ML": 64} - def numbering_function(row, col): + def numbering_function(row: int, col: int) -> str: n = 100 * (2 * row - 1) + col + offsets[wiring_config] return str(int(n)) return numbering_function -def numbering_function_4x128(): - def numbering_function(row, col): +def numbering_function_4x128() -> "Callable[[int, int], str]": + def numbering_function(row: int, col: int) -> str: n = 100 * (2 * row - 1) + col return str(int(n)) return numbering_function -def numbering_function_8x32(wiring_config): +def numbering_function_8x32(wiring_config: str) -> "Callable[[int, int], str]": offsets = {"MH": 0, "ML": 32} - def numbering_function(row, col): + def numbering_function(row: int, col: int) -> str: n = 100 * row + col + offsets[wiring_config] return str(int(n)) return numbering_function -def numbering_function_8x64(): - def numbering_function(row, col): +def numbering_function_8x64() -> "Callable[[int, int], str]": + def numbering_function(row: int, col: int) -> str: n = 100 * row + col return str(int(n)) return numbering_function -def numbering_function_16x32(): - def numbering_function(row, col): +def numbering_function_16x32() -> "Callable[[int, int], str]": + def numbering_function(row: int, col: int) -> str: n = 50 * (row + 1) + col return str(int(n)) diff --git a/tests/drivers/test_keysight_34980a.py b/tests/drivers/test_keysight_34980a.py index 06dbd2ea4807..01a194e4a9d0 100644 --- a/tests/drivers/test_keysight_34980a.py +++ b/tests/drivers/test_keysight_34980a.py @@ -1,13 +1,17 @@ import logging +from typing import TYPE_CHECKING import pytest from pytest import FixtureRequest, LogCaptureFixture from qcodes.instrument_drivers.Keysight.keysight_34980a import Keysight34980A +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def switch_driver(): +def switch_driver() -> "Generator[Keysight34980A, None, None]": inst = Keysight34980A( "keysight_34980A_sim", address="GPIB::1::INSTR", diff --git a/tests/drivers/test_keysight_b220x.py b/tests/drivers/test_keysight_b220x.py index 8df739cfcff3..38cbe414c508 100644 --- a/tests/drivers/test_keysight_b220x.py +++ b/tests/drivers/test_keysight_b220x.py @@ -33,17 +33,17 @@ def uut() -> "Generator[KeysightB220X, None, None]": instance.close() -def test_idn_command(uut) -> None: +def test_idn_command(uut: KeysightB220X) -> None: assert "AGILENT" in uut.IDN()["vendor"] assert 0 == uut.get_status() -def test_connect(uut) -> None: +def test_connect(uut: KeysightB220X) -> None: uut.connect(2, 48) assert 0 == uut.get_status() -def test_connect_throws_at_invalid_channel_number(uut) -> None: +def test_connect_throws_at_invalid_channel_number(uut: KeysightB220X) -> None: with pytest.raises(ValueError): uut.connect(2, 49) with pytest.raises(ValueError): @@ -54,7 +54,7 @@ def test_connect_throws_at_invalid_channel_number(uut) -> None: uut.connect(15, 10) -def test_connect_emits_warning_on_statusbyte_not_null(uut) -> None: +def test_connect_emits_warning_on_statusbyte_not_null(uut: KeysightB220X) -> None: # some tricks are used to trigger an instrument error both in the # simulation as well as in the real instrument: # 1. with gnd mode enabled, it is illegal to connect to input channel 12, @@ -74,7 +74,7 @@ def test_connect_emits_warning_on_statusbyte_not_null(uut) -> None: uut.gnd_mode(False) -def test_disconnect_throws_at_invalid_channel_number(uut) -> None: +def test_disconnect_throws_at_invalid_channel_number(uut: KeysightB220X) -> None: with pytest.raises(ValueError): uut.disconnect(2, 49) with pytest.raises(ValueError): @@ -85,35 +85,35 @@ def test_disconnect_throws_at_invalid_channel_number(uut) -> None: uut.disconnect(15, 10) -def test_connections(uut) -> None: +def test_connections(uut: KeysightB220X) -> None: uut.connect(2, 48) uut.connect(10, 12) assert {(2, 48), (10, 12)} == uut.connections() -def test_to_channel_list(uut) -> None: +def test_to_channel_list(uut: KeysightB220X) -> None: assert "(@00345,01109)" == uut.to_channel_list([(3, 45), (11, 9)]) -def test_connect_paths(uut) -> None: +def test_connect_paths(uut: KeysightB220X) -> None: uut.disconnect_all() uut.connect_paths([(3, 45), (11, 9)]) assert 0 == uut.get_status() -def test_disconnect_paths(uut) -> None: +def test_disconnect_paths(uut: KeysightB220X) -> None: uut.connect_paths([(3, 45), (11, 9)]) uut.disconnect_paths([(3, 45), (11, 9)]) assert 0 == uut.get_status() -def test_disconnect_all(uut) -> None: +def test_disconnect_all(uut: KeysightB220X) -> None: uut.connect(2, 48) uut.disconnect_all() assert 0 == uut.get_status() -def test_disconnect(uut) -> None: +def test_disconnect(uut: KeysightB220X) -> None: uut.connect(2, 48) assert 0 == uut.get_status() uut.disconnect(2, 48) @@ -123,21 +123,23 @@ def test_disconnect(uut) -> None: @pytest.mark.filterwarnings("ignore:When going") -def test_connection_rule(uut) -> None: +def test_connection_rule(uut: KeysightB220X) -> None: uut.connection_rule("single") assert 0 == uut.get_status() assert "single" == uut.connection_rule() assert 0 == uut.get_status() -def test_connection_rule_emits_warning_when_going_from_free_to_single(uut) -> None: +def test_connection_rule_emits_warning_when_going_from_free_to_single( + uut: KeysightB220X, +) -> None: uut.connection_rule("free") # uut should already be in free mode after reset with pytest.warns(UserWarning): uut.connection_rule("single") -def test_connection_sequence(uut) -> None: +def test_connection_sequence(uut: KeysightB220X) -> None: assert "bbm" == uut.connection_sequence() assert 0 == uut.get_status() uut.connection_sequence("mbb") @@ -145,74 +147,74 @@ def test_connection_sequence(uut) -> None: assert "mbb" == uut.connection_sequence() -def test_bias_disable_all_outputs(uut) -> None: +def test_bias_disable_all_outputs(uut: KeysightB220X) -> None: uut.bias_disable_all_outputs() assert 0 == uut.get_status() -def test_bias_disable_ouput(uut) -> None: +def test_bias_disable_ouput(uut: KeysightB220X) -> None: uut.bias_disable_output(1) assert 0 == uut.get_status() -def test_bias_enable_all_outputs(uut) -> None: +def test_bias_enable_all_outputs(uut: KeysightB220X) -> None: uut.bias_enable_all_outputs() assert 0 == uut.get_status() -def test_bias_enable_output(uut) -> None: +def test_bias_enable_output(uut: KeysightB220X) -> None: uut.bias_enable_output(1) assert 0 == uut.get_status() -def test_bias_input_port(uut) -> None: +def test_bias_input_port(uut: KeysightB220X) -> None: assert 10 == uut.bias_input_port() uut.bias_input_port(9) assert 9 == uut.bias_input_port() assert 0 == uut.get_status() -def test_bias_mode(uut) -> None: +def test_bias_mode(uut: KeysightB220X) -> None: uut.bias_mode(True) assert uut.bias_mode() assert 0 == uut.get_status() -def test_gnd_disable_all_outputs(uut) -> None: +def test_gnd_disable_all_outputs(uut: KeysightB220X) -> None: uut.gnd_disable_all_outputs() assert 0 == uut.get_status() -def test_gnd_disable_output(uut) -> None: +def test_gnd_disable_output(uut: KeysightB220X) -> None: uut.gnd_disable_output(1) assert 0 == uut.get_status() -def test_gnd_enable_all_outputs(uut) -> None: +def test_gnd_enable_all_outputs(uut: KeysightB220X) -> None: uut.gnd_enable_all_outputs() assert 0 == uut.get_status() -def test_gnd_enable_output(uut) -> None: +def test_gnd_enable_output(uut: KeysightB220X) -> None: uut.gnd_enable_output(1) assert 0 == uut.get_status() -def test_gnd_input_port(uut) -> None: +def test_gnd_input_port(uut: KeysightB220X) -> None: assert 12 == uut.gnd_input_port() uut.gnd_input_port(5) assert 5 == uut.gnd_input_port() assert 0 == uut.get_status() -def test_gnd_mode(uut) -> None: +def test_gnd_mode(uut: KeysightB220X) -> None: assert not uut.gnd_mode() uut.gnd_mode(True) assert uut.gnd_mode() assert 0 == uut.get_status() -def test_unused_inputs(uut) -> None: +def test_unused_inputs(uut: KeysightB220X) -> None: uut.unused_inputs() assert 0 == uut.get_status() @@ -225,14 +227,14 @@ def test_unused_inputs(uut) -> None: assert [5, 6, 7, 8] == uut.unused_inputs() -def test_couple_mode(uut) -> None: +def test_couple_mode(uut: KeysightB220X) -> None: assert not uut.couple_mode() uut.couple_mode(True) assert uut.couple_mode() assert 0 == uut.get_status() -def test_couple_ports(uut) -> None: +def test_couple_ports(uut: KeysightB220X) -> None: assert not uut.couple_ports() assert 0 == uut.get_status() @@ -250,12 +252,12 @@ def test_couple_ports(uut) -> None: uut.couple_ports([2, 3]) -def test_couple_port_autodetect(uut) -> None: +def test_couple_port_autodetect(uut: KeysightB220X) -> None: uut.couple_port_autodetect() assert 0 == uut.get_status() -def test_get_error(uut) -> None: +def test_get_error(uut: KeysightB220X) -> None: uut.get_error() assert 0 == uut.get_status() diff --git a/tests/drivers/test_keysight_e4980a.py b/tests/drivers/test_keysight_e4980a.py index 5b0ae9d3db10..7375171a977e 100644 --- a/tests/drivers/test_keysight_e4980a.py +++ b/tests/drivers/test_keysight_e4980a.py @@ -1,12 +1,16 @@ import re +from typing import TYPE_CHECKING import pytest import qcodes.instrument_drivers.Keysight.keysight_e4980a as E4980A +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(name="driver") -def _make_driver(): +def _make_driver() -> "Generator[E4980A.KeysightE4980A, None, None]": instr = E4980A.KeysightE4980A( "E4980A", address="GPIB::1::INSTR", pyvisa_sim_file="Keysight_E4980A.yaml" ) @@ -14,7 +18,7 @@ def _make_driver(): instr.close() -def test_idn(driver) -> None: +def test_idn(driver: E4980A.KeysightE4980A) -> None: assert { "firmware": "A.02.10", "model": "E4980A", @@ -23,7 +27,9 @@ def test_idn(driver) -> None: } == driver.IDN() -def test_raise_error_for_volt_level_query_when_signal_set_as_current(driver) -> None: +def test_raise_error_for_volt_level_query_when_signal_set_as_current( + driver: E4980A.KeysightE4980A, +) -> None: driver.current_level(0.01) msg = re.escape( "Cannot get voltage level as signal is set with current level parameter." @@ -32,12 +38,12 @@ def test_raise_error_for_volt_level_query_when_signal_set_as_current(driver) -> driver.voltage_level() -def test_voltage_level_set_method(driver) -> None: +def test_voltage_level_set_method(driver: E4980A.KeysightE4980A) -> None: driver.voltage_level(3) assert driver.voltage_level() == 3 -def test_signal_mode_parameter(driver) -> None: +def test_signal_mode_parameter(driver: E4980A.KeysightE4980A) -> None: driver.voltage_level(2) assert driver.signal_mode() == "Voltage" @@ -45,7 +51,9 @@ def test_signal_mode_parameter(driver) -> None: assert driver.signal_mode() == "Current" -def test_raise_error_for_curr_level_query_when_signal_set_as_voltage(driver) -> None: +def test_raise_error_for_curr_level_query_when_signal_set_as_voltage( + driver: E4980A.KeysightE4980A, +) -> None: driver.voltage_level(1) msg = re.escape( "Cannot get current level as signal is set with voltage level parameter." @@ -54,6 +62,6 @@ def test_raise_error_for_curr_level_query_when_signal_set_as_voltage(driver) -> driver.current_level() -def test_current_level_set_method(driver) -> None: +def test_current_level_set_method(driver: E4980A.KeysightE4980A) -> None: driver.current_level(0.003) assert driver.current_level() == 0.003 diff --git a/tests/drivers/test_keysight_n6705b.py b/tests/drivers/test_keysight_n6705b.py index f0e437fc60a8..9ebc17f28340 100644 --- a/tests/drivers/test_keysight_n6705b.py +++ b/tests/drivers/test_keysight_n6705b.py @@ -1,10 +1,15 @@ +from typing import TYPE_CHECKING + import pytest import qcodes.instrument_drivers.Keysight.Keysight_N6705B as N6705B_module +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function", name="driver") -def _make_driver(): +def _make_driver() -> "Generator[N6705B_module.KeysightN6705B, None, None]": driver = N6705B_module.KeysightN6705B( "N6705B", address="GPIB::1::INSTR", pyvisa_sim_file="Keysight_N6705B.yaml" ) @@ -12,7 +17,7 @@ def _make_driver(): driver.close() -def test_idn(driver) -> None: +def test_idn(driver: N6705B_module.KeysightN6705B) -> None: assert { "firmware": "D.01.08", "model": "N6705B", @@ -21,7 +26,7 @@ def test_idn(driver) -> None: } == driver.IDN() -def test_channels(driver) -> None: +def test_channels(driver: N6705B_module.KeysightN6705B) -> None: # Ensure each channel got instantiated assert len(driver.channels) == 4 for i, ch in enumerate(driver.channels): diff --git a/tests/drivers/test_keysight_n9030b.py b/tests/drivers/test_keysight_n9030b.py index 87a926d64cca..466d645017f0 100644 --- a/tests/drivers/test_keysight_n9030b.py +++ b/tests/drivers/test_keysight_n9030b.py @@ -1,3 +1,5 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.Keysight.Keysight_N9030B import ( @@ -6,9 +8,12 @@ KeysightN9030BSpectrumAnalyzerMode, ) +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(name="driver") -def _make_driver(): +def _make_driver() -> "Generator[KeysightN9030B, None, None]": driver = KeysightN9030B( "n9030B_sim", address="GPIB::1::INSTR", pyvisa_sim_file="Keysight_N9030B.yaml" ) @@ -17,16 +22,20 @@ def _make_driver(): @pytest.fixture(name="sa") -def _activate_swept_sa_measurement(driver): +def _activate_swept_sa_measurement( + driver: KeysightN9030B, +) -> "Generator[KeysightN9030BSpectrumAnalyzerMode, None, None]": yield driver.sa @pytest.fixture(name="pn") -def _activate_log_plot_measurement(driver): +def _activate_log_plot_measurement( + driver: KeysightN9030B, +) -> "Generator[KeysightN9030BPhaseNoiseMode, None, None]": yield driver.pn -def test_idn(driver) -> None: +def test_idn(driver: KeysightN9030B) -> None: assert { "firmware": "0.1", "model": "N9030B", @@ -35,7 +44,7 @@ def test_idn(driver) -> None: } == driver.IDN() -def test_swept_sa_setup(sa) -> None: +def test_swept_sa_setup(sa: KeysightN9030BSpectrumAnalyzerMode) -> None: assert isinstance(sa, KeysightN9030BSpectrumAnalyzerMode) sa.setup_swept_sa_sweep(123, 11e3, 501) @@ -47,7 +56,7 @@ def test_swept_sa_setup(sa) -> None: assert sa.npts() == 501 -def test_log_plot_setup(pn) -> None: +def test_log_plot_setup(pn: KeysightN9030BPhaseNoiseMode) -> None: assert isinstance(pn, KeysightN9030BPhaseNoiseMode) pn.setup_log_plot_sweep(1000, 1e7, 10001) diff --git a/tests/drivers/test_lakeshore_325.py b/tests/drivers/test_lakeshore_325.py index 1eec724ff916..f683421a52f6 100644 --- a/tests/drivers/test_lakeshore_325.py +++ b/tests/drivers/test_lakeshore_325.py @@ -17,14 +17,17 @@ sorted # type: ignore[arg-type] ) ) -def test_decode_sensor_status(list_of_codes) -> None: +def test_decode_sensor_status(list_of_codes: list[LakeshoreModel325Status]) -> None: """ The sensor status is one of the status codes, or a sum thereof. Multiple status are possible as they are not necessarily mutually exclusive. The static method 'decode_sensor_status' in the Model_325_Sensor class can decode the status into status code(s). """ - codes = [code.name.replace("_", " ") for code in list_of_codes[::-1]] + codes = [] + for code in list_of_codes[::-1]: + assert code.name is not None + codes.append(code.name.replace("_", " ")) codes_message = ", ".join(codes) sum_of_codes = int(sum(list_of_codes)) status_messages = LakeshoreModel325Sensor.decode_sensor_status(sum_of_codes) diff --git a/tests/drivers/test_lakeshore_335.py b/tests/drivers/test_lakeshore_335.py index ab3c866780a8..039f0a442ac0 100644 --- a/tests/drivers/test_lakeshore_335.py +++ b/tests/drivers/test_lakeshore_335.py @@ -1,5 +1,6 @@ import logging import time +from typing import Any from qcodes.instrument import InstrumentBase from qcodes.instrument_drivers.Lakeshore import LakeshoreModel335 @@ -17,7 +18,7 @@ class LakeshoreModel335Mock(MockVisaInstrument, LakeshoreModel335): - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) # initial values @@ -67,11 +68,11 @@ def __init__(self, *args, **kwargs) -> None: self.simulate_heating = False self.start_heating_time = time.perf_counter() - def start_heating(self): + def start_heating(self) -> None: self.start_heating_time = time.perf_counter() self.simulate_heating = True - def get_t_when_heating(self): + def get_t_when_heating(self) -> float: """ Simply define a fixed setpoint of 4 k for now """ @@ -81,7 +82,7 @@ def get_t_when_heating(self): return max(4, 7 - delta) @query("KRDG?") - def temperature(self, output): + def temperature(self, output: str) -> float | str: chan = self.channel_mock[output] if self.simulate_heating: return self.get_t_when_heating() @@ -89,7 +90,7 @@ def temperature(self, output): @instrument_fixture(scope="function", name="lakeshore_335") -def _make_lakeshore_335(): +def _make_lakeshore_335() -> LakeshoreModel335Mock: return LakeshoreModel335Mock( "lakeshore_335_fixture", "GPIB::2::INSTR", @@ -98,7 +99,7 @@ def _make_lakeshore_335(): ) -def test_pid_set(lakeshore_335) -> None: +def test_pid_set(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 P, I, D = 1, 2, 3 # noqa: E741 # Only current source outputs/heaters have PID parameters, @@ -111,7 +112,7 @@ def test_pid_set(lakeshore_335) -> None: assert (h.P(), h.I(), h.D()) == (P, I, D) -def test_output_mode(lakeshore_335) -> None: +def test_output_mode(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 mode = "off" input_channel = "A" @@ -126,7 +127,7 @@ def test_output_mode(lakeshore_335) -> None: assert h.powerup_enable() == powerup_enable -def test_range(lakeshore_335) -> None: +def test_range(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 output_range = "medium" outputs = [getattr(ls, f"output_{n}") for n in range(1, 3)] @@ -135,7 +136,7 @@ def test_range(lakeshore_335) -> None: assert h.output_range() == output_range -def test_tlimit(lakeshore_335) -> None: +def test_tlimit(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 tlimit = 5.1 for ch in ls.channels: @@ -143,7 +144,7 @@ def test_tlimit(lakeshore_335) -> None: assert ch.t_limit() == tlimit -def test_setpoint(lakeshore_335) -> None: +def test_setpoint(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 setpoint = 5.1 outputs = [getattr(ls, f"output_{n}") for n in range(1, 3)] @@ -152,7 +153,7 @@ def test_setpoint(lakeshore_335) -> None: assert h.setpoint() == setpoint -def test_select_range_limits(lakeshore_335) -> None: +def test_select_range_limits(lakeshore_335: LakeshoreModel335Mock) -> None: h = lakeshore_335.output_1 ranges = [1, 2, 3] h.range_limits(ranges) @@ -166,14 +167,16 @@ def test_select_range_limits(lakeshore_335) -> None: assert h.output_range() == h.INVERSE_RANGES[len(ranges)] -def test_set_and_wait_unit_setpoint_reached(lakeshore_335) -> None: +def test_set_and_wait_unit_setpoint_reached( + lakeshore_335: LakeshoreModel335Mock, +) -> None: ls = lakeshore_335 ls.output_1.setpoint(4) ls.start_heating() ls.output_1.wait_until_set_point_reached() -def test_blocking_t(lakeshore_335) -> None: +def test_blocking_t(lakeshore_335: LakeshoreModel335Mock) -> None: ls = lakeshore_335 h = ls.output_1 ranges = [1.2, 2.4, 3.1] diff --git a/tests/drivers/test_lakeshore_336.py b/tests/drivers/test_lakeshore_336.py index 62486b1b47b0..5f1dc0a79976 100644 --- a/tests/drivers/test_lakeshore_336.py +++ b/tests/drivers/test_lakeshore_336.py @@ -1,5 +1,6 @@ import logging import time +from typing import Any import pytest @@ -19,7 +20,7 @@ class LakeshoreModel336Mock(MockVisaInstrument, LakeshoreModel336): - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) # initial values @@ -89,11 +90,11 @@ def __init__(self, *args, **kwargs) -> None: self.simulate_heating = False self.start_heating_time = time.perf_counter() - def start_heating(self): + def start_heating(self) -> None: self.start_heating_time = time.perf_counter() self.simulate_heating = True - def get_t_when_heating(self): + def get_t_when_heating(self) -> float: """ Simply define a fixed setpoint of 4 k for now """ @@ -103,7 +104,7 @@ def get_t_when_heating(self): return max(4, 7 - delta) @query("KRDG?") - def temperature(self, output): + def temperature(self, output: str) -> float | str: chan = self.channel_mock[output] if self.simulate_heating: return self.get_t_when_heating() @@ -111,7 +112,7 @@ def temperature(self, output): @instrument_fixture(scope="function", name="lakeshore_336") -def _make_lakeshore_336(): +def _make_lakeshore_336() -> LakeshoreModel336Mock: return LakeshoreModel336Mock( "lakeshore_336_fixture", "GPIB::2::INSTR", @@ -120,7 +121,7 @@ def _make_lakeshore_336(): ) -def test_pid_set(lakeshore_336) -> None: +def test_pid_set(lakeshore_336: LakeshoreModel336Mock) -> None: ls = lakeshore_336 P, I, D = 1, 2, 3 # noqa: E741 # Only current source outputs/heaters have PID parameters, @@ -136,7 +137,9 @@ def test_pid_set(lakeshore_336) -> None: @pytest.mark.parametrize("output_num", [1, 2, 3, 4]) @pytest.mark.parametrize("mode", ["off", "closed_loop", "zone", "open_loop"]) @pytest.mark.parametrize("input_channel", ["A", "B", "C", "D"]) -def test_output_mode(lakeshore_336, output_num, mode, input_channel) -> None: +def test_output_mode( + lakeshore_336: LakeshoreModel336Mock, output_num: int, mode: str, input_channel: str +) -> None: ls = lakeshore_336 mode = "off" h = getattr(ls, f"output_{output_num}") @@ -148,7 +151,7 @@ def test_output_mode(lakeshore_336, output_num, mode, input_channel) -> None: assert h.powerup_enable() -def test_range(lakeshore_336) -> None: +def test_range(lakeshore_336: LakeshoreModel336Mock) -> None: ls = lakeshore_336 output_range = "medium" outputs = [getattr(ls, f"output_{n}") for n in range(1, 5)] @@ -157,7 +160,7 @@ def test_range(lakeshore_336) -> None: assert h.output_range() == output_range -def test_tlimit(lakeshore_336) -> None: +def test_tlimit(lakeshore_336: LakeshoreModel336Mock) -> None: ls = lakeshore_336 tlimit = 5.1 for ch in ls.channels: @@ -165,7 +168,7 @@ def test_tlimit(lakeshore_336) -> None: assert ch.t_limit() == tlimit -def test_setpoint(lakeshore_336) -> None: +def test_setpoint(lakeshore_336: LakeshoreModel336Mock) -> None: ls = lakeshore_336 setpoint = 5.1 outputs = [getattr(ls, f"output_{n}") for n in range(1, 5)] @@ -174,7 +177,7 @@ def test_setpoint(lakeshore_336) -> None: assert h.setpoint() == setpoint -def test_curve_parameters(lakeshore_336) -> None: +def test_curve_parameters(lakeshore_336: LakeshoreModel336Mock) -> None: # The curve numbers are assigned in the simulation pyvisa sim # YAML file for each sensor/channel, and properties of the # curves also include curve number in them to help testing @@ -187,7 +190,7 @@ def test_curve_parameters(lakeshore_336) -> None: assert ch.curve_coefficient() == "negative" -def test_select_range_limits(lakeshore_336) -> None: +def test_select_range_limits(lakeshore_336: LakeshoreModel336Mock) -> None: h = lakeshore_336.output_1 ranges = [1, 2, 3] h.range_limits(ranges) @@ -201,14 +204,16 @@ def test_select_range_limits(lakeshore_336) -> None: assert h.output_range() == h.INVERSE_RANGES[len(ranges)] -def test_set_and_wait_unit_setpoint_reached(lakeshore_336) -> None: +def test_set_and_wait_unit_setpoint_reached( + lakeshore_336: LakeshoreModel336Mock, +) -> None: ls = lakeshore_336 ls.output_1.setpoint(4) ls.start_heating() ls.output_1.wait_until_set_point_reached() -def test_blocking_t(lakeshore_336) -> None: +def test_blocking_t(lakeshore_336: LakeshoreModel336Mock) -> None: ls = lakeshore_336 h = ls.output_1 ranges = [1.2, 2.4, 3.1] diff --git a/tests/drivers/test_lakeshore_372.py b/tests/drivers/test_lakeshore_372.py index 76ff8497f225..dca80adbec8c 100644 --- a/tests/drivers/test_lakeshore_372.py +++ b/tests/drivers/test_lakeshore_372.py @@ -8,7 +8,7 @@ import pytest -from qcodes.instrument import InstrumentBase +from qcodes.instrument import Instrument, InstrumentBase from qcodes.instrument_drivers.Lakeshore import LakeshoreModel372 from qcodes.instrument_drivers.Lakeshore.lakeshore_base import ( LakeshoreBaseSensorChannel, @@ -17,7 +17,7 @@ from qcodes.utils import QCoDeSDeprecationWarning if TYPE_CHECKING: - from collections.abc import Callable + from collections.abc import Callable, Generator log = logging.getLogger(__name__) @@ -30,7 +30,7 @@ class MockVisaInstrument: instrument. """ - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.visa_log = get_instrument_logger(self, VISA_LOGGER) # type: ignore[arg-type] @@ -62,7 +62,7 @@ def __init__(self, *args, **kwargs) -> None: with suppress(AttributeError): self.cmds[f.command_name] = f - def write_raw(self, cmd) -> None: + def write_raw(self, cmd: str) -> None: cmd_parts = cmd.split(" ") cmd_str = cmd_parts[0].upper() if cmd_str in self.cmds: @@ -72,7 +72,7 @@ def write_raw(self, cmd) -> None: else: super().write_raw(cmd) # type: ignore[misc] - def ask_raw(self, cmd) -> Any: + def ask_raw(self, cmd: str) -> Any: query_parts = cmd.split(" ") query_str = query_parts[0].upper() if query_str in self.queries: @@ -104,14 +104,14 @@ def wrapper(func: Callable[P, T]) -> Callable[P, T]: class DictClass: - def __init__(self, **kwargs): + def __init__(self, **kwargs: Any) -> None: # https://stackoverflow.com/questions/16237659/python-how-to-implement-getattr super().__setattr__("_attrs", kwargs) for kwarg, value in kwargs.items(): self._attrs[kwarg] = value - def __getattr__(self, attr): + def __getattr__(self, attr: str) -> Any: try: return self._attrs[attr] except KeyError as e: @@ -122,7 +122,7 @@ def __setattr__(self, name: str, value: Any) -> None: class LakeshoreModel372Mock(MockVisaInstrument, LakeshoreModel372): - def __init__(self, *args, **kwargs) -> None: + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) # initial values @@ -190,11 +190,11 @@ def __init__(self, *args, **kwargs) -> None: self.simulate_heating = False self.start_heating_time = time.perf_counter() - def start_heating(self): + def start_heating(self) -> None: self.start_heating_time = time.perf_counter() self.simulate_heating = True - def get_t_when_heating(self): + def get_t_when_heating(self) -> float: """ Simply define a fixed setpoint of 4 k for now """ @@ -204,7 +204,7 @@ def get_t_when_heating(self): return max(4, 7 - delta) @query("KRDG?") - def temperature(self, output): + def temperature(self, output: str) -> float | str: chan = self.channel_mock[output] if self.simulate_heating: return self.get_t_when_heating() @@ -213,11 +213,11 @@ def temperature(self, output): def instrument_fixture( scope: Literal["session", "package", "module", "class", "function"] = "function", - name=None, -): - def wrapper(func): + name: str | None = None, +) -> Callable[[Callable[[], Instrument]], Callable[..., object]]: + def wrapper(func: Callable[[], Instrument]) -> Callable[..., object]: @pytest.fixture(scope=scope, name=name) - def wrapped_fixture(): + def wrapped_fixture() -> Generator[Instrument, None, None]: inst = func() try: yield inst @@ -230,7 +230,7 @@ def wrapped_fixture(): @instrument_fixture(scope="function") -def lakeshore_372(): +def lakeshore_372() -> LakeshoreModel372Mock: return LakeshoreModel372Mock( "lakeshore_372_fixture", "GPIB::3::INSTR", @@ -239,7 +239,7 @@ def lakeshore_372(): ) -def test_pid_set(lakeshore_372) -> None: +def test_pid_set(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 P, I, D = 1, 2, 3 # noqa: E741 for h in (ls.warmup_heater, ls.analog_heater, ls.sample_heater): @@ -249,7 +249,7 @@ def test_pid_set(lakeshore_372) -> None: assert (h.P(), h.I(), h.D()) == (P, I, D) -def test_output_mode(lakeshore_372) -> None: +def test_output_mode(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 mode = "off" input_channel = 1 @@ -272,7 +272,7 @@ def test_output_mode(lakeshore_372) -> None: assert h.delay() == delay -def test_range(lakeshore_372) -> None: +def test_range(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 output_range = "10mA" for h in (ls.warmup_heater, ls.analog_heater, ls.sample_heater): @@ -280,7 +280,7 @@ def test_range(lakeshore_372) -> None: assert h.output_range() == output_range -def test_tlimit(lakeshore_372) -> None: +def test_tlimit(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 tlimit = 5.1 for ch in ls.channels: @@ -288,7 +288,7 @@ def test_tlimit(lakeshore_372) -> None: assert ch.t_limit() == tlimit -def test_setpoint(lakeshore_372) -> None: +def test_setpoint(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 setpoint = 5.1 for h in (ls.warmup_heater, ls.analog_heater, ls.sample_heater): @@ -296,7 +296,7 @@ def test_setpoint(lakeshore_372) -> None: assert h.setpoint() == setpoint -def test_select_range_limits(lakeshore_372) -> None: +def test_select_range_limits(lakeshore_372: LakeshoreModel372Mock) -> None: h = lakeshore_372.sample_heater ranges = list(range(1, 9)) h.range_limits(ranges) @@ -309,14 +309,16 @@ def test_select_range_limits(lakeshore_372) -> None: assert h.output_range() == h.INVERSE_RANGES[len(ranges)] -def test_set_and_wait_unit_setpoint_reached(lakeshore_372) -> None: +def test_set_and_wait_unit_setpoint_reached( + lakeshore_372: LakeshoreModel372Mock, +) -> None: ls = lakeshore_372 ls.sample_heater.setpoint(4) ls.start_heating() ls.sample_heater.wait_until_set_point_reached() -def test_blocking_t(lakeshore_372) -> None: +def test_blocking_t(lakeshore_372: LakeshoreModel372Mock) -> None: ls = lakeshore_372 h = lakeshore_372.sample_heater ranges = list(range(1, 9)) diff --git a/tests/drivers/test_lakeshore_file_parser.py b/tests/drivers/test_lakeshore_file_parser.py index da94c8706f7f..4bcf94111ed9 100644 --- a/tests/drivers/test_lakeshore_file_parser.py +++ b/tests/drivers/test_lakeshore_file_parser.py @@ -1,4 +1,5 @@ import io +from typing import TYPE_CHECKING import pytest @@ -7,6 +8,9 @@ _read_curve_file, ) +if TYPE_CHECKING: + from collections.abc import Generator + curve_file_content = """ \ Sensor Model: CX-1050-SD-HT-1.4L Serial Number: X116121 @@ -27,11 +31,11 @@ @pytest.fixture(scope="function") -def curve_file(): +def curve_file() -> "Generator[io.StringIO, None, None]": yield io.StringIO(curve_file_content) -def test_file_parser(curve_file) -> None: +def test_file_parser(curve_file: io.StringIO) -> None: file_data = _read_curve_file(curve_file) assert list(file_data.keys()) == ["metadata", "data"] @@ -52,7 +56,7 @@ def test_file_parser(curve_file) -> None: } -def test_sanitise_data(curve_file) -> None: +def test_sanitise_data(curve_file: io.StringIO) -> None: file_data = _read_curve_file(curve_file) data_dict = _get_sanitize_data(file_data) diff --git a/tests/drivers/test_mercuryips.py b/tests/drivers/test_mercuryips.py index d6e19e6df29d..e63ecec31c30 100644 --- a/tests/drivers/test_mercuryips.py +++ b/tests/drivers/test_mercuryips.py @@ -1,4 +1,5 @@ import logging +from typing import TYPE_CHECKING import hypothesis.strategies as hst import numpy as np @@ -9,9 +10,12 @@ from qcodes.instrument_drivers.oxford.MercuryiPS_VISA import OxfordMercuryiPS from qcodes.math_utils.field_vector import FieldVector +if TYPE_CHECKING: + from collections.abc import Generator, Iterable + @pytest.fixture(scope="function") -def driver(): +def driver() -> "Generator[OxfordMercuryiPS, None, None]": mips = OxfordMercuryiPS( "mips", address="GPIB::1::INSTR", pyvisa_sim_file="MercuryiPS.yaml" ) @@ -20,12 +24,12 @@ def driver(): @pytest.fixture(scope="function") -def driver_spher_lim(): - def spherical_limits(x, y, z): +def driver_spher_lim() -> "Generator[OxfordMercuryiPS, None, None]": + def spherical_limits(x: float, y: float, z: float) -> bool: """ Checks that the field is inside a sphere of radius 2 """ - return np.sqrt(x**2 + y**2 + z**2) <= 2 + return bool(np.sqrt(x**2 + y**2 + z**2) <= 2) mips_sl = OxfordMercuryiPS( "mips_sl", @@ -39,12 +43,12 @@ def spherical_limits(x, y, z): @pytest.fixture(scope="function") -def driver_cyl_lim(): - def cylindrical_limits(x, y, z): +def driver_cyl_lim() -> "Generator[OxfordMercuryiPS, None, None]": + def cylindrical_limits(x: float, y: float, z: float) -> bool: """ Checks that the field is inside a particular cylinder """ - rho_check = np.sqrt(x**2 + y**2) <= 2 + rho_check = bool(np.sqrt(x**2 + y**2) <= 2) z_check = z < 3 and z > -1 return rho_check and z_check @@ -60,11 +64,11 @@ def cylindrical_limits(x, y, z): mips_cl.close() -def test_idn(driver) -> None: +def test_idn(driver: OxfordMercuryiPS) -> None: assert driver.IDN()["model"] == "SIMULATED MERCURY iPS" -def test_simple_setting(driver) -> None: +def test_simple_setting(driver: OxfordMercuryiPS) -> None: """ Some very simple setting of parameters. Mainly just to sanity-check the pyvisa-sim setup. @@ -74,13 +78,13 @@ def test_simple_setting(driver) -> None: assert driver.GRPX.field_target() == 0.1 -def test_vector_setting(driver) -> None: +def test_vector_setting(driver: OxfordMercuryiPS) -> None: assert driver.field_target().distance(FieldVector(0, 0, 0)) <= 1e-8 driver.field_target(FieldVector(r=0.1, theta=0, phi=0)) assert driver.field_target().distance(FieldVector(r=0.1, theta=0, phi=0)) <= 1e-8 -def test_vector_ramp_rate(driver) -> None: +def test_vector_ramp_rate(driver: OxfordMercuryiPS) -> None: driver.field_ramp_rate(FieldVector(0.1, 0.1, 0.1)) assert driver.field_ramp_rate().distance(FieldVector(0.1, 0.1, 0.1)) <= 1e-8 @@ -102,7 +106,13 @@ def test_wrong_field_limit_raises() -> None: y=hst.floats(min_value=-3, max_value=3), z=hst.floats(min_value=-3, max_value=3), ) -def test_field_limits(x, y, z, driver_spher_lim, driver_cyl_lim) -> None: +def test_field_limits( + x: float, + y: float, + z: float, + driver_spher_lim: OxfordMercuryiPS, + driver_cyl_lim: OxfordMercuryiPS, +) -> None: """ Try with a few different field_limits functions and see if we get no-go exceptions when we expect them @@ -129,7 +139,7 @@ def test_field_limits(x, y, z, driver_spher_lim, driver_cyl_lim) -> None: mip.z_target(z) -def get_ramp_order(caplog_records): +def get_ramp_order(caplog_records: "Iterable[logging.LogRecord]") -> list[str]: """ Helper function used in test_ramp_safely """ @@ -148,7 +158,9 @@ def get_ramp_order(caplog_records): y=hst.floats(min_value=-3, max_value=3), z=hst.floats(min_value=-3, max_value=3), ) -def test_ramp_safely(driver, x, y, z, caplog: LogCaptureFixture) -> None: +def test_ramp_safely( + driver: OxfordMercuryiPS, x: float, y: float, z: float, caplog: LogCaptureFixture +) -> None: """ Test that we get the first-down-then-up order right """ diff --git a/tests/drivers/test_rigol_ds1074z.py b/tests/drivers/test_rigol_ds1074z.py index 1064ce5c43e4..9790508488e1 100644 --- a/tests/drivers/test_rigol_ds1074z.py +++ b/tests/drivers/test_rigol_ds1074z.py @@ -1,10 +1,15 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.rigol import RigolDS1074Z +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def driver(): +def driver() -> "Generator[RigolDS1074Z, None, None]": rigol = RigolDS1074Z( "rigol", address="GPIB::1::INSTR", @@ -16,7 +21,7 @@ def driver(): rigol.close() -def test_initialize(driver) -> None: +def test_initialize(driver: RigolDS1074Z) -> None: """ Test that simple initialisation works """ @@ -24,32 +29,32 @@ def test_initialize(driver) -> None: assert idn_dict["vendor"] == "QCoDeS" -def test_gets_correct_waveform_xorigin(driver) -> None: +def test_gets_correct_waveform_xorigin(driver: RigolDS1074Z) -> None: assert driver.waveform_xorigin() == 0 -def test_gets_correct_waveform_xincrem(driver) -> None: +def test_gets_correct_waveform_xincrem(driver: RigolDS1074Z) -> None: assert driver.waveform_xincrem() == 0.1 -def test_sets_correct_waveform_npoints(driver) -> None: +def test_sets_correct_waveform_npoints(driver: RigolDS1074Z) -> None: driver.waveform_npoints(1000) assert driver.waveform_npoints() == 1000 -def test_gets_correct_waveform_yorigin(driver) -> None: +def test_gets_correct_waveform_yorigin(driver: RigolDS1074Z) -> None: assert driver.waveform_yorigin() == 0 -def test_gets_correct_waveform_yincrem(driver) -> None: +def test_gets_correct_waveform_yincrem(driver: RigolDS1074Z) -> None: assert driver.waveform_yincrem() == 0.1 -def test_gets_correct_waveform_yref(driver) -> None: +def test_gets_correct_waveform_yref(driver: RigolDS1074Z) -> None: assert driver.waveform_yref() == 0 -def test_sets_correct_trigger_mode(driver) -> None: +def test_sets_correct_trigger_mode(driver: RigolDS1074Z) -> None: driver.trigger_mode("edge") assert driver.trigger_mode() == "edge" driver.trigger_mode("pattern") @@ -60,7 +65,7 @@ def test_sets_correct_trigger_mode(driver) -> None: assert driver.trigger_mode() == "video" -def test_get_data_source(driver) -> None: +def test_get_data_source(driver: RigolDS1074Z) -> None: driver.data_source("ch1") assert driver.data_source() == "ch1" driver.data_source("ch2") diff --git a/tests/drivers/test_rs_sgs100a.py b/tests/drivers/test_rs_sgs100a.py index 76382ec1c232..9361c7098595 100644 --- a/tests/drivers/test_rs_sgs100a.py +++ b/tests/drivers/test_rs_sgs100a.py @@ -6,11 +6,11 @@ from qcodes.instrument_drivers.rohde_schwarz.SGS100A import RohdeSchwarzSGS100A if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Generator, Sequence @pytest.fixture(scope="function", name="sg") -def _make_sg(): +def _make_sg() -> "Generator[RohdeSchwarzSGS100A, None, None]": """ Create a RohdeSchwarz SGS100A instrument """ @@ -21,7 +21,9 @@ def _make_sg(): driver.close() -def verify_property(sg, param_name, vals: "Sequence[Any]"): +def verify_property( + sg: RohdeSchwarzSGS100A, param_name: str, vals: "Sequence[Any]" +) -> None: param = getattr(sg, param_name) for val in vals: param(val) @@ -32,74 +34,74 @@ def verify_property(sg, param_name, vals: "Sequence[Any]"): assert new_val == val -def test_frequency(sg) -> None: +def test_frequency(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "frequency", [1e6, 2e6, 3e9, 20e9]) -def test_phase(sg) -> None: +def test_phase(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "phase", [0, 45, 90, 180, 270, 359, 360]) -def test_power(sg) -> None: +def test_power(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "power", [-120, -50, 0, 10, 25]) -def test_status(sg) -> None: +def test_status(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "status", [True, False]) -def test_IQ_state(sg) -> None: +def test_IQ_state(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "IQ_state", [True, False]) -def test_pulsemod_state(sg) -> None: +def test_pulsemod_state(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "pulsemod_state", [True, False]) -def test_pulsemod_source(sg) -> None: +def test_pulsemod_source(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "pulsemod_source", ["INT", "EXT"]) -def test_ref_osc_source(sg) -> None: +def test_ref_osc_source(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "ref_osc_source", ["INT", "EXT"]) -def test_LO_source(sg) -> None: +def test_LO_source(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "LO_source", ["INT", "EXT"]) -def test_ref_LO_out(sg) -> None: +def test_ref_LO_out(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "ref_LO_out", ["REF", "LO", "OFF"]) -def test_ref_osc_output_freq(sg) -> None: +def test_ref_osc_output_freq(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "ref_osc_output_freq", ["10MHz", "100MHz", "1000MHz"]) -def test_ref_osc_external_freq(sg) -> None: +def test_ref_osc_external_freq(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "ref_osc_external_freq", ["10MHz", "100MHz", "1000MHz"]) -def test_IQ_impairments(sg) -> None: +def test_IQ_impairments(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "IQ_impairments", [True, False]) -def test_I_offset(sg) -> None: +def test_I_offset(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "I_offset", [-10, 0, 10]) -def test_Q_offset(sg) -> None: +def test_Q_offset(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "Q_offset", [-10, 0, 10]) -def test_IQ_gain_imbalance(sg) -> None: +def test_IQ_gain_imbalance(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "IQ_gain_imbalance", [-1, 0, 1]) -def test_IQ_angle(sg) -> None: +def test_IQ_angle(sg: RohdeSchwarzSGS100A) -> None: verify_property(sg, "IQ_angle", [-8, -4, 0, 4, 8]) -def test_operation_mode(sg) -> None: +def test_operation_mode(sg: RohdeSchwarzSGS100A) -> None: print(f"operation mode is set to {sg.operation_mode()}") verify_property(sg, "operation_mode", ["NORMal", "BBBYpass"]) diff --git a/tests/drivers/test_rto_1000.py b/tests/drivers/test_rto_1000.py index faa23b922017..4987a6dc4ee4 100644 --- a/tests/drivers/test_rto_1000.py +++ b/tests/drivers/test_rto_1000.py @@ -1,10 +1,15 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.instrument_drivers.rohde_schwarz.RTO1000 import RTO1000 +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def driver(): +def driver() -> "Generator[RTO1000, None, None]": rto_sim = RTO1000( "rto_sim", address="GPIB::1::INSTR", @@ -16,13 +21,13 @@ def driver(): rto_sim.close() -def test_init(driver) -> None: +def test_init(driver: RTO1000) -> None: idn_dict = driver.IDN() assert idn_dict["vendor"] == "QCoDeS" -def test_trigger_source_level(driver) -> None: +def test_trigger_source_level(driver: RTO1000) -> None: assert driver.trigger_source() == "CH1" assert driver.trigger_level() == 0 driver.trigger_level(1.0) diff --git a/tests/drivers/test_stahl.py b/tests/drivers/test_stahl.py index 3f43143adcdd..e06a61ddd779 100644 --- a/tests/drivers/test_stahl.py +++ b/tests/drivers/test_stahl.py @@ -1,15 +1,19 @@ import logging +from typing import TYPE_CHECKING import pytest from pytest import LogCaptureFixture from qcodes.instrument_drivers.stahl import Stahl +if TYPE_CHECKING: + from collections.abc import Generator + LOG_NAME = "qcodes.instrument.instrument_base" @pytest.fixture(scope="function") -def stahl_instrument(): +def stahl_instrument() -> "Generator[Stahl, None, None]": inst = Stahl("Stahl", "ASRL3", pyvisa_sim_file="stahl.yaml") try: @@ -34,7 +38,7 @@ def test_parse_idn_string() -> None: Stahl.parse_idn_string("HS123 005 16 bla b") -def test_get_idn(stahl_instrument) -> None: +def test_get_idn(stahl_instrument: Stahl) -> None: """ Instrument attributes are set correctly after getting the IDN """ @@ -50,7 +54,7 @@ def test_get_idn(stahl_instrument) -> None: assert stahl_instrument.output_type == "bipolar" -def test_get_set_voltage(stahl_instrument, caplog: LogCaptureFixture) -> None: +def test_get_set_voltage(stahl_instrument: Stahl, caplog: LogCaptureFixture) -> None: """ Test that we can correctly get/set voltages """ @@ -66,7 +70,7 @@ def test_get_set_voltage(stahl_instrument, caplog: LogCaptureFixture) -> None: def test_get_set_voltage_assert_warning( - stahl_instrument, caplog: LogCaptureFixture + stahl_instrument: Stahl, caplog: LogCaptureFixture ) -> None: """ On channel 2 we have deliberately introduced an error in the @@ -80,7 +84,7 @@ def test_get_set_voltage_assert_warning( ) -def test_get_current(stahl_instrument) -> None: +def test_get_current(stahl_instrument: Stahl) -> None: """ Test that we can read currents and that the unit is in Ampere """ @@ -88,7 +92,7 @@ def test_get_current(stahl_instrument) -> None: assert stahl_instrument.channel[0].current.unit == "A" -def test_get_temperature(stahl_instrument) -> None: +def test_get_temperature(stahl_instrument: Stahl) -> None: """ Due to limitations in pyvisa-sim, we cannot test this. Line 191 of pyvisa-sim/component.py should read diff --git a/tests/drivers/test_tektronix_awg5208.py b/tests/drivers/test_tektronix_awg5208.py index e6b16a101ff0..4a8b68d5bced 100644 --- a/tests/drivers/test_tektronix_awg5208.py +++ b/tests/drivers/test_tektronix_awg5208.py @@ -1,12 +1,16 @@ import os +from typing import TYPE_CHECKING import pytest from qcodes.instrument_drivers.tektronix.AWG5208 import TektronixAWG5208 +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(scope="function") -def awg(): +def awg() -> "Generator[TektronixAWG5208, None, None]": awg_sim = TektronixAWG5208( "awg_sim", address="GPIB0::1::INSTR", pyvisa_sim_file="Tektronix_AWG5208.yaml" ) @@ -15,13 +19,13 @@ def awg(): awg_sim.close() -def test_init_awg(awg) -> None: +def test_init_awg(awg: TektronixAWG5208) -> None: idn_dict = awg.IDN() assert idn_dict["vendor"] == "QCoDeS" -def test_channel_resolution_docstring(awg) -> None: +def test_channel_resolution_docstring(awg: TektronixAWG5208) -> None: expected_docstring = ( "12 bit resolution allows for four " "markers, 13 bit resolution " diff --git a/tests/drivers/test_tektronix_awg70000a.py b/tests/drivers/test_tektronix_awg70000a.py index 99c955aefaf4..6248fa50eba5 100644 --- a/tests/drivers/test_tektronix_awg70000a.py +++ b/tests/drivers/test_tektronix_awg70000a.py @@ -3,6 +3,7 @@ import logging import zipfile from io import BytesIO, StringIO +from typing import TYPE_CHECKING, Any import hypothesis.strategies as hst import numpy as np @@ -18,6 +19,11 @@ TektronixAWG70002A, ) +if TYPE_CHECKING: + from collections.abc import Callable, Generator + + import numpy.typing as npt + def strip_outer_tags(sml: str) -> str: """ @@ -36,7 +42,7 @@ def strip_outer_tags(sml: str) -> str: @pytest.fixture(scope="function") -def awg2(): +def awg2() -> Generator[TektronixAWG70002A, None, None]: awg2_sim = TektronixAWG70002A( "awg2_sim", address="GPIB0::2::INSTR", @@ -48,13 +54,13 @@ def awg2(): @pytest.fixture(scope="function") -def random_wfm_m1_m2_package(): +def random_wfm_m1_m2_package() -> Callable[[], npt.NDArray[np.number]]: """ Make a random 2400 points np.array([wfm, m1, m2]). The waveform has values in [-0.1, 0.1) """ - def make(): + def make() -> npt.NDArray[np.number]: rng = np.random.default_rng() length = rng.integers(2400, 2500) wfm = 0.2 * (rng.random(length) - 0.5) @@ -66,7 +72,7 @@ def make(): @pytest.fixture(scope="module", name="forged_sequence") -def _make_forged_sequence(): +def _make_forged_sequence() -> dict[int, dict[str, Any]]: """ Return an example forged sequence containing a subsequence @@ -76,7 +82,7 @@ def _make_forged_sequence(): num_chans = 3 types = ["element"] * (N - 1) + ["subsequence"] - def random_element(num_chans): + def random_element(num_chans: int) -> dict[int, dict[str, npt.NDArray[Any]]]: """ Return an element with random values @@ -109,7 +115,7 @@ def random_element(num_chans): return seq -def test_init_awg2(awg2) -> None: +def test_init_awg2(awg2: TektronixAWG70002A) -> None: idn_dict = awg2.IDN() assert idn_dict["vendor"] == "QCoDeS" @@ -117,7 +123,7 @@ def test_init_awg2(awg2) -> None: @settings(deadline=2500, max_examples=7) @given(N=hst.integers(1, 100)) -def test_SML_successful_generation_vary_length(N) -> None: +def test_SML_successful_generation_vary_length(N: int) -> None: tw = [0] * N nreps = [1] * N ejs = [0] * N @@ -136,18 +142,18 @@ def test_SML_successful_generation_vary_length(N) -> None: @given(num_samples=hst.integers(min_value=2400), markers_included=hst.booleans()) -def test_WFMXHeader_succesful(num_samples, markers_included) -> None: +def test_WFMXHeader_succesful(num_samples: int, markers_included: bool) -> None: xmlstr = TektronixAWG70000Base._makeWFMXFileHeader(num_samples, markers_included) etree.parse(StringIO(xmlstr)) @given(num_samples=hst.integers(max_value=2399), markers_included=hst.booleans()) -def test_WFMXHeader_failing(num_samples, markers_included) -> None: +def test_WFMXHeader_failing(num_samples: int, markers_included: bool) -> None: with pytest.raises(ValueError): TektronixAWG70000Base._makeWFMXFileHeader(num_samples, markers_included) -def test_seqxfilefromfs_failing(forged_sequence) -> None: +def test_seqxfilefromfs_failing(forged_sequence: dict[int, dict[str, Any]]) -> None: # typing convenience make_seqx = TektronixAWG70000Base.make_SEQX_from_forged_sequence @@ -188,7 +194,9 @@ def test_seqxfilefromfs_failing(forged_sequence) -> None: ) -def test_seqxfilefromfs_warns(forged_sequence, caplog: LogCaptureFixture) -> None: +def test_seqxfilefromfs_warns( + forged_sequence: dict[int, dict[str, Any]], caplog: LogCaptureFixture +) -> None: """ Test that a warning is logged when waveform is clipped """ @@ -203,7 +211,7 @@ def test_seqxfilefromfs_warns(forged_sequence, caplog: LogCaptureFixture) -> Non assert "Waveform exceeds specified channel range" in message -def test_seqxfile_from_fs(forged_sequence) -> None: +def test_seqxfile_from_fs(forged_sequence: dict[int, dict[str, Any]]) -> None: # typing convenience make_seqx = TektronixAWG70000Base.make_SEQX_from_forged_sequence @@ -238,7 +246,10 @@ def test_seqxfile_from_fs(forged_sequence) -> None: # TODO: Add some failing tests for inproper input -def test_makeSEQXFile(awg2, random_wfm_m1_m2_package) -> None: +def test_makeSEQXFile( + awg2: TektronixAWG70002A, + random_wfm_m1_m2_package: Callable[[], npt.NDArray[np.number]], +) -> None: """ Test that this function works (for some input) """ diff --git a/tests/extensions/parameters/test_parameter_mixin.py b/tests/extensions/parameters/test_parameter_mixin.py index adfcc22b2149..424397260b67 100644 --- a/tests/extensions/parameters/test_parameter_mixin.py +++ b/tests/extensions/parameters/test_parameter_mixin.py @@ -73,7 +73,7 @@ class IncorrectNamedMixin(ParameterMixin): ] -def test_typeerror_if_multiple_parameterbase_leaves(): +def test_typeerror_if_multiple_parameterbase_leaves() -> None: class FakeParam1(ParameterBase): pass @@ -187,7 +187,7 @@ class LeafComplexBParameterMixin(ComplexParameterMixin, LeafParameterMixin): ] -def test_sets_common_compatible_bases(): +def test_sets_common_compatible_bases() -> None: class BaseA(ParameterBase): pass @@ -206,7 +206,7 @@ class ComboParameterMixin(MixinAParameterMixin, MixinBParameterMixin): assert ComboParameterMixin._COMPATIBLE_BASES == [BaseB] -def test_multiple_mixins_no_compatible(): +def test_multiple_mixins_no_compatible() -> None: class DummyBase(ParameterBase): pass @@ -224,7 +224,7 @@ class ComboParameterMixin(EmptyAParameterMixin, EmptyBParameterMixin): _PARAMETER_MIXIN_CLASSES_COMPATIBLE: Final[bool] = True -def test_raises_if_incompatible(): +def test_raises_if_incompatible() -> None: class BadBase(ParameterBase): pass @@ -310,7 +310,7 @@ class ComplexParameterD( pass -def test_typeerror_multiple_parameter_mixin_with_parameterbase(): +def test_typeerror_multiple_parameter_mixin_with_parameterbase() -> None: class MyBase(ParameterBase): pass @@ -396,7 +396,7 @@ class ComplexParameterF(ComplexParameterMixin, CompatibleParameter): assert ParameterMixin not in all_mixins -def test_leaf_class_detection(): +def test_leaf_class_detection() -> None: class MyBase(ParameterBase): pass diff --git a/tests/extensions/parameters/test_parameter_mixin_group_registry.py b/tests/extensions/parameters/test_parameter_mixin_group_registry.py index e0d81204cf39..d69a83a13214 100644 --- a/tests/extensions/parameters/test_parameter_mixin_group_registry.py +++ b/tests/extensions/parameters/test_parameter_mixin_group_registry.py @@ -7,14 +7,14 @@ class GroupRegistryTestParameterMixin(GroupRegistryParameterMixin): pass -def test_register_and_trigger_group_callbacks(): - calls = [] +def test_register_and_trigger_group_callbacks() -> None: + calls: list[str] = [] GroupRegistryTestParameterMixin._group_registry.clear() - def cb1(): + def cb1() -> None: calls.append("cb1") - def cb2(): + def cb2() -> None: calls.append("cb2") GroupRegistryTestParameterMixin.register_group_callback("alpha", cb1) @@ -24,7 +24,7 @@ def cb2(): assert calls == ["cb1", "cb2"] -def test_trigger_group_warns_if_none(): +def test_trigger_group_warns_if_none() -> None: GroupRegistryTestParameterMixin._group_registry.clear() with pytest.warns(UserWarning, match="No callbacks registered for group 'missing'"): GroupRegistryTestParameterMixin.trigger_group("missing") @@ -35,17 +35,17 @@ def test_warning_no_callbacks_for_group() -> None: GroupRegistryParameterMixin.trigger_group("empty_group") -def test_multiple_callbacks_in_group(): +def test_multiple_callbacks_in_group() -> None: """ Test that multiple callbacks registered to a group are all called in order. """ - call_order = [] + call_order: list[str] = [] GroupRegistryTestParameterMixin._group_registry.clear() - def callback_one(): + def callback_one() -> None: call_order.append("callback_one") - def callback_two(): + def callback_two() -> None: call_order.append("callback_two") GroupRegistryTestParameterMixin.register_group_callback( @@ -59,17 +59,17 @@ def callback_two(): assert call_order == ["callback_one", "callback_two"] -def test_callback_execution_order(): +def test_callback_execution_order() -> None: """ Test that callbacks are executed in the order they were registered. """ - execution_sequence = [] + execution_sequence: list[str] = [] GroupRegistryTestParameterMixin._group_registry.clear() - def first_callback(): + def first_callback() -> None: execution_sequence.append("first") - def second_callback(): + def second_callback() -> None: execution_sequence.append("second") GroupRegistryTestParameterMixin.register_group_callback( diff --git a/tests/extensions/parameters/test_parameter_mixin_interdependent.py b/tests/extensions/parameters/test_parameter_mixin_interdependent.py index 4a0087984523..407a44f795d6 100644 --- a/tests/extensions/parameters/test_parameter_mixin_interdependent.py +++ b/tests/extensions/parameters/test_parameter_mixin_interdependent.py @@ -1,5 +1,5 @@ import re -from typing import Any, cast +from typing import TYPE_CHECKING, Any, cast import pytest @@ -8,13 +8,19 @@ from qcodes.parameters import Parameter from qcodes.utils import QCoDeSDeprecationWarning +if TYPE_CHECKING: + from collections.abc import Callable, Generator + class MockInstrument(Instrument): """ A mock instrument that can host parameters. """ - def __init__(self, name: str, **kwargs): + some_param: "InterdependentParameter" + managed_param: "InterdependentParameter" + + def __init__(self, name: str, **kwargs: Any) -> None: super().__init__(name, **kwargs) @@ -23,7 +29,7 @@ class InterdependentParameter(InterdependentParameterMixin, Parameter): @pytest.fixture -def store(): +def store() -> dict[str, Any]: """ Provides a dictionary to store parameter values. """ @@ -31,7 +37,7 @@ def store(): @pytest.fixture -def callback_flag(): +def callback_flag() -> dict[str, bool]: """ Provides a mutable flag to track callback invocation. """ @@ -39,7 +45,7 @@ def callback_flag(): @pytest.fixture -def callback(callback_flag): +def callback(callback_flag: dict[str, bool]) -> "Callable[[], None]": """ Provides a callback that sets callback_flag["called"] to True. """ @@ -51,7 +57,7 @@ def _callback(**kwargs: Any) -> None: @pytest.fixture -def callback_data(): +def callback_data() -> list[tuple[tuple[Any, ...], dict[str, Any]]]: """ Provides a list to store callback invocation data. """ @@ -59,19 +65,21 @@ def callback_data(): @pytest.fixture -def data_callback(callback_data): +def data_callback( + callback_data: list[tuple[tuple[Any, ...], dict[str, Any]]], +) -> "Callable[[], None]": """ Provides a callback that records (args, kwargs) into callback_data. """ - def _callback(*args, **kwargs): + def _callback(*args: Any, **kwargs: Any) -> None: callback_data.append((args, kwargs)) return _callback @pytest.fixture -def mock_instr(): +def mock_instr() -> "Generator[MockInstrument, None, None]": """ Provides a mock instrument for interdependent parameter tests. """ @@ -81,7 +89,10 @@ def mock_instr(): def test_dependency_update_invoked_on_change( - store, callback_flag, callback, mock_instr + store: dict[str, Any], + callback_flag: dict[str, bool], + callback: "Callable[[], None]", + mock_instr: MockInstrument, ) -> None: mock_instr.some_param = cast( "InterdependentParameter", @@ -114,7 +125,10 @@ def test_dependency_update_invoked_on_change( def test_adding_dependent_parameter_later( - store, callback_flag, callback, mock_instr + store: dict[str, Any], + callback_flag: dict[str, bool], + callback: "Callable[[], None]", + mock_instr: MockInstrument, ) -> None: mock_instr.some_param = cast( "InterdependentParameter", @@ -148,7 +162,7 @@ def test_adding_dependent_parameter_later( def test_error_on_non_interdependent_dependency( - store, mock_instr: MockInstrument + store: dict[str, Any], mock_instr: MockInstrument ) -> None: mock_instr.add_parameter( @@ -180,8 +194,10 @@ def test_error_on_non_interdependent_dependency( # Parameter managed_param depends on a non-interdependent param -def test_parsers_and_dependency_propagation(store, mock_instr) -> None: - def dependency_update(): +def test_parsers_and_dependency_propagation( + store: dict[str, Any], mock_instr: MockInstrument +) -> None: + def dependency_update() -> None: mock_instr.managed_param.set(999) mock_instr.some_param = cast( @@ -218,7 +234,9 @@ def dependency_update(): assert mock_instr.managed_param.get() == 999, "Dependency not updated." -def test_typeerror_if_dependency_update_method_invalid(mock_instr): +def test_typeerror_if_dependency_update_method_invalid( + mock_instr: MockInstrument, +) -> None: param = mock_instr.add_parameter( name="some_param", parameter_class=InterdependentParameter, @@ -229,10 +247,10 @@ def test_typeerror_if_dependency_update_method_invalid(mock_instr): with pytest.raises( TypeError, match=re.escape("dependency_update_method must be callable or None.") ): - param.dependency_update_method = 123 + param.dependency_update_method = 123 # pyright: ignore[reportAttributeAccessIssue] -def test_typeerror_if_dependent_on_invalid(mock_instr): +def test_typeerror_if_dependent_on_invalid(mock_instr: MockInstrument) -> None: param = mock_instr.add_parameter( name="some_param", parameter_class=InterdependentParameter, @@ -243,10 +261,10 @@ def test_typeerror_if_dependent_on_invalid(mock_instr): with pytest.raises( TypeError, match=re.escape("dependent_on must be a list of strings.") ): - param.dependent_on = "not_a_list" + param.dependent_on = "not_a_list" # pyright: ignore[reportAttributeAccessIssue] # Assign a list with non-string with pytest.raises( TypeError, match=re.escape("dependent_on must be a list of strings.") ): - param.dependent_on = [123, None] + param.dependent_on = [123, None] # pyright: ignore[reportAttributeAccessIssue] 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 dd5bed990144..27d161307aca 100644 --- a/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py +++ b/tests/extensions/parameters/test_parameter_mixin_on_cache_change.py @@ -1,4 +1,4 @@ -from typing import Any, cast +from typing import TYPE_CHECKING, Any, cast import pytest @@ -6,13 +6,22 @@ from qcodes.instrument import Instrument from qcodes.parameters import Parameter +if TYPE_CHECKING: + from collections.abc import Generator + + from qcodes.extensions.parameters.parameter_mixin_on_cache_change import ( + OnCacheChangeCallback, + ) + class MockInstrument(Instrument): """ A mock instrument to host parameters. """ - def __init__(self, name: str): + test_parameter: "OnCacheChangeParameter" + + def __init__(self, name: str) -> None: super().__init__(name) @@ -23,7 +32,7 @@ class OnCacheChangeParameter(OnCacheChangeParameterMixin, Parameter): @pytest.fixture -def store(): +def store() -> dict[str, Any]: """ Provides a dictionary to store parameter values. """ @@ -31,7 +40,7 @@ def store(): @pytest.fixture -def callback_flag(): +def callback_flag() -> dict[str, bool]: """ Provides a mutable flag to track callback invocation. """ @@ -39,7 +48,7 @@ def callback_flag(): @pytest.fixture -def callback(callback_flag): +def callback(callback_flag: dict[str, bool]) -> "OnCacheChangeCallback": """ Provides a callback that sets callback_flag["called"] to True. """ @@ -51,7 +60,7 @@ def _callback(**kwargs: Any) -> None: @pytest.fixture -def callback_data(): +def callback_data() -> list[Any]: """ Provides a list to store callback invocation data. """ @@ -59,19 +68,19 @@ def callback_data(): @pytest.fixture -def data_callback(callback_data): +def data_callback(callback_data: list[Any]) -> "OnCacheChangeCallback": """ Provides a callback that records (args, kwargs) into callback_data. """ - def _callback(**kwargs): + def _callback(**kwargs: Any) -> None: callback_data.append(kwargs) return _callback @pytest.fixture -def mock_instr(): +def mock_instr() -> "Generator[MockInstrument, None, None]": """ Provides a mock instrument to host parameters. """ @@ -81,18 +90,24 @@ def mock_instr(): @pytest.mark.parametrize("invalid_callback", ["not_a_callable", 123, [], {}]) -def test_error_on_non_callable_callback(mock_instr, invalid_callback) -> None: +def test_error_on_non_callable_callback( + mock_instr: MockInstrument, + invalid_callback: str | int | list[Any] | dict[Any, Any], +) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", parameter_class=OnCacheChangeParameter, docstring="A parameter for testing non-callable callbacks.", ) with pytest.raises(TypeError): - test_parameter.on_cache_change = invalid_callback + test_parameter.on_cache_change = invalid_callback # pyright: ignore[reportAttributeAccessIssue] def test_no_callback_invocation_on_init_or_get( - store, callback_flag, callback, mock_instr + store: dict[str, Any], + callback_flag: dict[str, bool], + callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, ) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", @@ -107,7 +122,12 @@ def test_no_callback_invocation_on_init_or_get( assert not callback_flag["called"], "Callback invoked unexpectedly." -def test_callback_invoked_on_set(store, callback_flag, callback, mock_instr) -> None: +def test_callback_invoked_on_set( + store: dict[str, Any], + callback_flag: dict[str, bool], + callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, +) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", parameter_class=OnCacheChangeParameter, @@ -121,7 +141,10 @@ def test_callback_invoked_on_set(store, callback_flag, callback, mock_instr) -> def test_changing_callback_after_init( - store, callback_flag, callback, mock_instr + store: dict[str, Any], + callback_flag: dict[str, bool], + callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, ) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", @@ -138,7 +161,11 @@ def test_changing_callback_after_init( assert callback_flag["called"] -def test_callback_on_get_value_change(callback_flag, callback, mock_instr) -> None: +def test_callback_on_get_value_change( + callback_flag: dict[str, bool], + callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, +) -> None: get_reply = None test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( @@ -157,7 +184,10 @@ def test_callback_on_get_value_change(callback_flag, callback, mock_instr) -> No def test_callback_on_direct_cache_update( - store, callback_data, data_callback, mock_instr + store: dict[str, Any], + callback_data: list[dict[str, Any]], + data_callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, ) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", @@ -174,7 +204,10 @@ def test_callback_on_direct_cache_update( def test_no_callback_if_value_unchanged( - store, callback_data, data_callback, mock_instr + store: dict[str, Any], + callback_data: list[dict[str, Any]], + data_callback: "OnCacheChangeCallback", + mock_instr: MockInstrument, ) -> None: test_parameter: OnCacheChangeParameter = mock_instr.add_parameter( name="test_parameter", @@ -193,8 +226,12 @@ def test_no_callback_if_value_unchanged( assert not callback_data -def test_callback_value_parsers(store, callback_data, mock_instr) -> None: - def cb(**kwargs): +def test_callback_value_parsers( + store: dict[str, Any], + callback_data: list[tuple[Any, Any, Any, Any]], + mock_instr: MockInstrument, +) -> None: + def cb(**kwargs: Any) -> None: callback_data.append( ( kwargs.get("value_old"), 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 23a487552150..3f8eca9eb8d5 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 @@ -1,4 +1,4 @@ -from typing import Any +from typing import TYPE_CHECKING, Any import pytest @@ -7,17 +7,20 @@ from qcodes.parameters import Parameter from qcodes.utils import QCoDeSDeprecationWarning +if TYPE_CHECKING: + from collections.abc import Generator + class MockResetInstrument(Instrument): """ A mock instrument that records calls to perform_reset. """ - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name) self.reset_call_args: list[tuple[tuple[Any, ...], dict[str, Any]]] = [] - def perform_reset(self, *args: Any, **kwargs: Any): + def perform_reset(self, *args: Any, **kwargs: Any) -> None: self.reset_call_args.append((args, kwargs)) SetCacheValueOnResetParameterMixin.trigger_group("reset_group_general") @@ -29,7 +32,7 @@ class ResetTestParameter(SetCacheValueOnResetParameterMixin, Parameter): @pytest.fixture -def store(): +def store() -> dict[str, Any]: """ Provides a dictionary to store parameter values. """ @@ -37,7 +40,7 @@ def store(): @pytest.fixture -def reset_instr(): +def reset_instr() -> "Generator[MockResetInstrument, None, None]": """ Provides a mock instrument with reset capability. """ @@ -47,11 +50,13 @@ def reset_instr(): @pytest.fixture(autouse=True) -def clear_reset_registry(): +def clear_reset_registry() -> None: SetCacheValueOnResetParameterMixin._group_registry.clear() -def test_cache_resets_to_value(store, reset_instr) -> None: +def test_cache_resets_to_value( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: test_param: ResetTestParameter = reset_instr.add_parameter( name="test_param", parameter_class=ResetTestParameter, @@ -67,7 +72,9 @@ def test_cache_resets_to_value(store, reset_instr) -> None: assert test_param.get() == 42 -def test_warning_if_cache_value_unset(store, reset_instr) -> None: +def test_warning_if_cache_value_unset( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: with pytest.warns( UserWarning, match="cache_value_after_reset for parameter 'test_param' is not set", @@ -81,7 +88,9 @@ def test_warning_if_cache_value_unset(store, reset_instr) -> None: ) -def test_cache_resets_to_none(store, reset_instr) -> None: +def test_cache_resets_to_none( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: test_param: ResetTestParameter = reset_instr.add_parameter( name="test_param_none", parameter_class=ResetTestParameter, @@ -97,7 +106,9 @@ def test_cache_resets_to_none(store, reset_instr) -> None: assert test_param.get() is None -def test_set_parser_with_default_get_parser(store, reset_instr) -> None: +def test_set_parser_with_default_get_parser( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: test_param: ResetTestParameter = reset_instr.add_parameter( name="test_param", parameter_class=ResetTestParameter, @@ -116,7 +127,9 @@ def test_set_parser_with_default_get_parser(store, reset_instr) -> None: assert test_param.get_raw() == 30 -def test_direct_cache_update_and_reset(store, reset_instr) -> None: +def test_direct_cache_update_and_reset( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: test_param: ResetTestParameter = reset_instr.add_parameter( name="test_param", parameter_class=ResetTestParameter, @@ -165,7 +178,9 @@ def test_error_if_get_parser_supplied(reset_instr: MockResetInstrument) -> None: ) -def test_parameter_in_multiple_reset_groups(store, reset_instr) -> None: +def test_parameter_in_multiple_reset_groups( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: test_param: ResetTestParameter = reset_instr.add_parameter( name="test_param", parameter_class=ResetTestParameter, @@ -184,7 +199,7 @@ def test_parameter_in_multiple_reset_groups(store, reset_instr) -> None: assert test_param.get() == 100 -def test_get_raw_with_val_mapping(reset_instr) -> None: +def test_get_raw_with_val_mapping(reset_instr: MockResetInstrument) -> None: class MyParam(SetCacheValueOnResetParameterMixin, Parameter): pass @@ -205,7 +220,9 @@ class MyParam(SetCacheValueOnResetParameterMixin, Parameter): assert p.get_raw() == "1" -def test_warning_if_group_names_is_none(store, reset_instr): +def test_warning_if_group_names_is_none( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: with pytest.warns(UserWarning, match="No group_name"): reset_instr.add_parameter( name="test_param", @@ -216,7 +233,9 @@ def test_warning_if_group_names_is_none(store, reset_instr): ) -def test_warning_if_group_names_missing(store, reset_instr): +def test_warning_if_group_names_missing( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: with pytest.warns(UserWarning, match="No group_name"): reset_instr.add_parameter( name="test_param", @@ -226,7 +245,9 @@ def test_warning_if_group_names_missing(store, reset_instr): ) -def test_typeerror_if_group_names_invalid(store, reset_instr): +def test_typeerror_if_group_names_invalid( + store: dict[str, Any], reset_instr: MockResetInstrument +) -> None: with ( pytest.warns(QCoDeSDeprecationWarning), pytest.raises(TypeError, match="group_names must be a list of strings or None"), diff --git a/tests/extensions/test_infer.py b/tests/extensions/test_infer.py index afcd12e4cba9..c16a609ac5a2 100644 --- a/tests/extensions/test_infer.py +++ b/tests/extensions/test_infer.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Any +from typing import TYPE_CHECKING, Any import numpy as np import pytest @@ -21,9 +21,12 @@ from qcodes.instrument import Instrument, InstrumentBase, InstrumentModule from qcodes.parameters import DelegateParameter, ManualParameter, Parameter +if TYPE_CHECKING: + from collections.abc import Generator + class DummyModule(InstrumentModule): - def __init__(self, name: str, parent: Instrument): + def __init__(self, name: str, parent: Instrument) -> None: super().__init__(name=name, parent=parent) self.good_chan_parameter = ManualParameter( "good_chan_parameter", instrument=self @@ -32,7 +35,7 @@ def __init__(self, name: str, parent: Instrument): class DummyInstrument(Instrument): - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name=name) self.good_inst_parameter = ManualParameter( "good_inst_parameter", instrument=self @@ -42,12 +45,12 @@ def __init__(self, name: str): class DummyInstrument2(DummyInstrument): - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name=name) class DummyDelegateInstrument(InstrumentBase): - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name=name) self.inst_delegate = DelegateParameter( name="inst_delegate", source=None, instrument=self, bind_to_instrument=True @@ -59,7 +62,7 @@ def __init__(self, name: str): class DummyDelegateModule(InstrumentModule): - def __init__(self, name: str, parent: InstrumentBase): + def __init__(self, name: str, parent: InstrumentBase) -> None: super().__init__(name=name, parent=parent) self.chan_delegate = DelegateParameter( name="chan_delegate", source=None, instrument=self, bind_to_instrument=True @@ -69,13 +72,13 @@ def __init__(self, name: str, parent: InstrumentBase): class UserLinkingParameter(Parameter): def __init__( self, name: str, linked_parameter: Parameter | None = None, **kwargs: Any - ): + ) -> None: super().__init__(name=name, **kwargs) self.linked_parameter: Parameter | None = linked_parameter @pytest.fixture(name="instrument_fixture") -def make_instrument_fixture(): +def make_instrument_fixture() -> Generator[DummyInstrument, None, None]: inst = DummyInstrument("dummy_instrument") InferAttrs.clear() try: @@ -85,7 +88,7 @@ def make_instrument_fixture(): @pytest.fixture(name="instrument_fixture2") -def make_instrument_fixture2(): +def make_instrument_fixture2() -> Generator[DummyInstrument2, None, None]: inst = DummyInstrument2("dummy_instrument2") InferAttrs.clear() try: @@ -95,7 +98,9 @@ def make_instrument_fixture2(): @pytest.fixture(name="good_inst_delegates") -def make_good_delegate_parameters(instrument_fixture): +def make_good_delegate_parameters( + instrument_fixture: DummyInstrument, +) -> tuple[DelegateParameter, DelegateParameter, UserLinkingParameter]: inst = instrument_fixture good_inst_del_1 = DelegateParameter( "good_inst_del_1", source=inst.good_inst_parameter @@ -108,7 +113,9 @@ def make_good_delegate_parameters(instrument_fixture): @pytest.fixture(name="multi_inst_chain") -def make_multi_instrument_chain(instrument_fixture, instrument_fixture2): +def make_multi_instrument_chain( + instrument_fixture: DummyInstrument, instrument_fixture2: DummyInstrument2 +) -> tuple[DelegateParameter, DelegateParameter, UserLinkingParameter]: inst = instrument_fixture inst2 = instrument_fixture2 good_inst_del_1 = DelegateParameter( @@ -125,7 +132,12 @@ def make_multi_instrument_chain(instrument_fixture, instrument_fixture2): return good_inst_del_1, good_inst_del_2, good_inst_del_3 -def test_get_root_parameter_valid(instrument_fixture, good_inst_delegates): +def test_get_root_parameter_valid( + instrument_fixture: DummyInstrument, + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: inst = instrument_fixture good_inst_del_1, good_inst_del_2, good_inst_del_3 = good_inst_delegates @@ -144,7 +156,11 @@ def test_get_root_parameter_valid(instrument_fixture, good_inst_delegates): assert get_root_parameter(good_inst_del_3) is inst.good_inst_parameter -def test_get_root_parameter_no_source(good_inst_delegates): +def test_get_root_parameter_no_source( + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: good_inst_del_1, good_inst_del_2, _ = good_inst_delegates good_inst_del_1.source = None @@ -154,13 +170,21 @@ def test_get_root_parameter_no_source(good_inst_delegates): assert "is not attached to a source" in str(exc_info.value) -def test_get_root_parameter_no_user_attr(good_inst_delegates): +def test_get_root_parameter_no_user_attr( + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: _, _, good_inst_del_3 = good_inst_delegates InferAttrs.clear() assert get_root_parameter(good_inst_del_3, "external_parameter") is good_inst_del_3 -def test_get_root_parameter_none_user_attr(good_inst_delegates): +def test_get_root_parameter_none_user_attr( + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: _, _, good_inst_del_3 = good_inst_delegates good_inst_del_3.linked_parameter = None with pytest.raises(InferError) as exc_info: @@ -168,14 +192,19 @@ def test_get_root_parameter_none_user_attr(good_inst_delegates): assert "is not attached to a source on attribute" in str(exc_info.value) -def test_infer_instrument_valid(instrument_fixture, good_inst_delegates): +def test_infer_instrument_valid( + instrument_fixture: DummyInstrument, + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: inst = instrument_fixture _, _, good_inst_del_3 = good_inst_delegates InferAttrs.add("linked_parameter") assert infer_instrument(good_inst_del_3) is inst -def test_infer_instrument_no_instrument(instrument_fixture): +def test_infer_instrument_no_instrument(instrument_fixture: DummyInstrument) -> None: inst = instrument_fixture no_inst_delegate = DelegateParameter( "no_inst_delegate", source=inst.bad_inst_parameter @@ -185,7 +214,7 @@ def test_infer_instrument_no_instrument(instrument_fixture): assert "has no instrument" in str(exc_info.value) -def test_infer_instrument_root_instrument_base(): +def test_infer_instrument_root_instrument_base() -> None: delegate_inst = DummyDelegateInstrument("dummy_delegate_instrument") with pytest.raises(InferError) as exc_info: @@ -193,7 +222,7 @@ def test_infer_instrument_root_instrument_base(): assert "Could not determine source instrument for parameter" in str(exc_info.value) -def test_infer_channel_valid(instrument_fixture): +def test_infer_channel_valid(instrument_fixture: DummyInstrument) -> None: inst = instrument_fixture chan_delegate = DelegateParameter( "chan_delegate", source=inst.module.good_chan_parameter @@ -201,7 +230,7 @@ def test_infer_channel_valid(instrument_fixture): assert infer_channel(chan_delegate) is inst.module -def test_infer_channel_no_channel(instrument_fixture): +def test_infer_channel_no_channel(instrument_fixture: DummyInstrument) -> None: inst = instrument_fixture no_chan_delegate = DelegateParameter( "no_chan_delegate", source=inst.module.bad_chan_parameter @@ -218,7 +247,12 @@ def test_infer_channel_no_channel(instrument_fixture): assert "Could not determine a root instrument channel" in str(exc_info.value) -def test_get_parameter_chain(instrument_fixture, good_inst_delegates): +def test_get_parameter_chain( + instrument_fixture: DummyInstrument, + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: inst = instrument_fixture good_inst_del_1, good_inst_del_2, good_inst_del_3 = good_inst_delegates parameter_chain = get_parameter_chain(good_inst_del_3, "linked_parameter") @@ -259,7 +293,12 @@ def test_get_parameter_chain(instrument_fixture, good_inst_delegates): ) -def test_parameters_on_delegate_instruments(instrument_fixture, good_inst_delegates): +def test_parameters_on_delegate_instruments( + instrument_fixture: DummyInstrument, + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: inst = instrument_fixture _, good_inst_del_2, _ = good_inst_delegates @@ -272,7 +311,7 @@ def test_parameters_on_delegate_instruments(instrument_fixture, good_inst_delega assert infer_instrument(delegate_inst.inst_delegate) is inst -def test_merge_user_and_class_attrs(): +def test_merge_user_and_class_attrs() -> None: InferAttrs.add("attr1") attr_set = _merge_user_and_class_attrs("attr2") assert {"attr1", "attr2"} == attr_set @@ -281,7 +320,7 @@ def test_merge_user_and_class_attrs(): assert {"attr1", "attr2", "attr3"} == attr_set_list -def test_infer_attrs(): +def test_infer_attrs() -> None: InferAttrs.clear() assert InferAttrs.known_attrs() == () @@ -296,7 +335,11 @@ def test_infer_attrs(): assert set(InferAttrs.known_attrs()) == {"attr1", "attr2", "attr3"} -def test_get_parameter_chain_with_loops(good_inst_delegates): +def test_get_parameter_chain_with_loops( + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: good_inst_del_1, good_inst_del_2, good_inst_del_3 = good_inst_delegates good_inst_del_1.source = good_inst_del_3 parameter_chain = get_parameter_chain(good_inst_del_3, "linked_parameter") @@ -311,7 +354,11 @@ def test_get_parameter_chain_with_loops(good_inst_delegates): ) -def test_get_root_parameter_with_loops(good_inst_delegates): +def test_get_root_parameter_with_loops( + good_inst_delegates: tuple[ + DelegateParameter, DelegateParameter, UserLinkingParameter + ], +) -> None: good_inst_del_1, good_inst_del_2, good_inst_del_3 = good_inst_delegates good_inst_del_1.source = good_inst_del_3 with pytest.raises(InferError) as exc_info: @@ -319,7 +366,7 @@ def test_get_root_parameter_with_loops(good_inst_delegates): assert "generated a loop of linking parameters" in str(exc_info.value) -def test_chain_links_of_type(): +def test_chain_links_of_type() -> None: root_param = ManualParameter("root", initial_value=0) user_link = UserLinkingParameter("user_link", linked_parameter=root_param) delegate_link = DelegateParameter("delegate_link", source=user_link) @@ -330,7 +377,7 @@ def test_chain_links_of_type(): assert set(user_links) == {user_link, user_link_2} -def test_sole_chain_link_of_type(): +def test_sole_chain_link_of_type() -> None: root_param = ManualParameter("root", initial_value=0) user_link = UserLinkingParameter("user_link", linked_parameter=root_param) delegate_link = DelegateParameter("delegate_link", source=user_link) @@ -352,8 +399,10 @@ def test_sole_chain_link_of_type(): def test_get_instrument_from_chain( - instrument_fixture, instrument_fixture2, multi_inst_chain -): + instrument_fixture: DummyInstrument, + instrument_fixture2: DummyInstrument2, + multi_inst_chain: tuple[DelegateParameter, DelegateParameter, UserLinkingParameter], +) -> None: inst = instrument_fixture inst2 = instrument_fixture2 _good_inst_del_1, _good_inst_del_2, good_inst_del_3 = multi_inst_chain @@ -365,7 +414,10 @@ def test_get_instrument_from_chain( assert set(instruments) == {inst, inst2} -def test_get_sole_instrument_from_chain(instrument_fixture2, multi_inst_chain): +def test_get_sole_instrument_from_chain( + instrument_fixture2: DummyInstrument2, + multi_inst_chain: tuple[DelegateParameter, DelegateParameter, UserLinkingParameter], +) -> None: inst2 = instrument_fixture2 _good_inst_del_1, _good_inst_del_2, good_inst_del_3 = multi_inst_chain diff --git a/tests/extensions/test_refactoring.py b/tests/extensions/test_refactoring.py index 1a26d479dcd9..6321d6da9793 100644 --- a/tests/extensions/test_refactoring.py +++ b/tests/extensions/test_refactoring.py @@ -148,7 +148,7 @@ def test_transform_add_parameter_multiline_docstring() -> None: assert output_lines[-2] == '"""This is the first line This is the second line"""' -def test_transform_add_parameter_dedent(): +def test_transform_add_parameter_dedent() -> None: code = dedent( """ self.add_parameter( diff --git a/tests/helpers/test_json_encoder.py b/tests/helpers/test_json_encoder.py index 01a525e454ff..01fc4f5c64a8 100644 --- a/tests/helpers/test_json_encoder.py +++ b/tests/helpers/test_json_encoder.py @@ -89,7 +89,7 @@ def test_non_serializable() -> None: e = NumpyJSONEncoder() class Dummy: - def __str__(self): + def __str__(self) -> str: return "i am a dummy with \\ slashes /" assert e.encode(Dummy()) == '"i am a dummy with \\\\ slashes /"' @@ -103,13 +103,13 @@ def test_object_with_serialization_method() -> None: e = NumpyJSONEncoder() class Dummy: - def __init__(self): + def __init__(self) -> None: self.confession = "a_dict_addict" - def __str__(self): + def __str__(self) -> str: return "me as a string" - def _JSONEncoder(self): + def _JSONEncoder(self) -> dict[str, str]: return {"i_am_actually": self.confession} assert e.encode(Dummy()) == '{"i_am_actually": "a_dict_addict"}' @@ -166,7 +166,7 @@ def test_numpy_encoder_examplemetadata() -> None: @given(bytes_to_encode=hst.binary(max_size=100)) -def test_bytes(bytes_to_encode) -> None: +def test_bytes(bytes_to_encode: bytes) -> None: e = NumpyJSONEncoder() v = e.encode(bytes_to_encode) @@ -177,7 +177,7 @@ def test_bytes(bytes_to_encode) -> None: @given(bytes_to_encode=hst.binary(max_size=100)) -def test_bytes_array(bytes_to_encode) -> None: +def test_bytes_array(bytes_to_encode: bytes) -> None: e = NumpyJSONEncoder() value = bytearray(bytes_to_encode) v = e.encode(value) diff --git a/tests/helpers/test_strip_attrs.py b/tests/helpers/test_strip_attrs.py index 5dc8e39ddbd5..e032ed292f14 100644 --- a/tests/helpers/test_strip_attrs.py +++ b/tests/helpers/test_strip_attrs.py @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, NoReturn import pytest @@ -11,12 +11,12 @@ class A: class BadKeysDict(dict[Any, Any]): - def keys(self): + def keys(self) -> NoReturn: raise RuntimeError("you can't have the keys!") class NoDelDict(dict[Any, Any]): - def __delitem__(self, item): + def __delitem__(self, item: Any) -> NoReturn: raise KeyError("get your hands off me!") diff --git a/tests/mockers/test_simulated_ats_api.py b/tests/mockers/test_simulated_ats_api.py index 93d0b1a9a9c1..98ba3ef03dc3 100644 --- a/tests/mockers/test_simulated_ats_api.py +++ b/tests/mockers/test_simulated_ats_api.py @@ -1,19 +1,24 @@ import logging +from typing import TYPE_CHECKING import numpy as np +import numpy.typing as npt import pytest from qcodes.instrument.mockers.simulated_ats_api import SimulatedATS9360API from qcodes.instrument_drivers.AlazarTech.ATS import AcquisitionInterface from qcodes.instrument_drivers.AlazarTech.ATS9360 import AlazarTechATS9360 as ATS9360 +if TYPE_CHECKING: + from collections.abc import Generator -def ones_generator(data): + +def ones_generator(data: npt.NDArray) -> None: data[:] = np.ones(data.shape) @pytest.fixture(scope="function") -def simulated_alazar(): +def simulated_alazar() -> "Generator[ATS9360, None, None]": driver = ATS9360( "Alazar", api=SimulatedATS9360API(dll_path="simulated", buffer_generator=ones_generator), @@ -28,22 +33,28 @@ def simulated_alazar(): @pytest.fixture(scope="function") -def alazar_ctrl(): - class TestAcquisitionController(AcquisitionInterface): - def __init__(self): - self.buffers = [] +def alazar_ctrl() -> "Generator[AcquisitionInterface[list[npt.NDArray]], None, None]": + class TestAcquisitionController(AcquisitionInterface[list[npt.NDArray]]): + def __init__(self) -> None: + self.buffers: list[npt.NDArray] = [] - def handle_buffer(self, buffer, buffer_number=None): + def handle_buffer( + self, buffer: npt.NDArray, buffer_number: int | None = None + ) -> None: self.buffers.append(np.copy(buffer)) - def post_acquire(self): + def post_acquire(self) -> list[npt.NDArray]: return self.buffers yield TestAcquisitionController() @pytest.mark.win32 -def test_simulated_alazar(simulated_alazar, alazar_ctrl, caplog) -> None: +def test_simulated_alazar( + simulated_alazar: ATS9360, + alazar_ctrl: AcquisitionInterface[list[npt.NDArray]], + caplog: pytest.LogCaptureFixture, +) -> None: alazar = simulated_alazar buffers_per_acquisition = 10 with caplog.at_level(logging.DEBUG): diff --git a/tests/parameter/conftest.py b/tests/parameter/conftest.py index 8ddb9f1395a0..49128488b22b 100644 --- a/tests/parameter/conftest.py +++ b/tests/parameter/conftest.py @@ -61,7 +61,7 @@ def _make_dummy_instrument() -> Generator[DummyChannelInstrument, None, None]: class GettableParam(Parameter): """Parameter that keeps track of number of get operations""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._get_count = 0 @@ -74,7 +74,7 @@ class BetterGettableParam(Parameter): """Parameter that keeps track of number of get operations, But can actually store values""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._get_count = 0 @@ -86,7 +86,7 @@ def get_raw(self) -> Any: class SettableParam(Parameter): """Parameter that keeps track of number of set operations""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: self._set_count = 0 super().__init__(*args, **kwargs) @@ -97,7 +97,7 @@ def set_raw(self, value: Any) -> None: class OverwriteGetParam(Parameter): """Parameter that overwrites get.""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._value = 42 self.set_count = 0 @@ -111,7 +111,7 @@ def get(self) -> int: class OverwriteSetParam(Parameter): """Parameter that overwrites set.""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self._value = 42 self.set_count = 0 @@ -125,7 +125,7 @@ def set(self, value: Any) -> None: class GetSetRawParameter(Parameter): """Parameter that implements get and set raw""" - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) def get_raw(self) -> ParamRawDataType: @@ -142,7 +142,7 @@ class BookkeepingValidator[T](vals.Validator[T]): def __init__( self, min_value: float = -float("inf"), max_value: float = float("inf") - ): + ) -> None: self.values_validated: list[T] = [] def validate(self, value: T, context: str = "") -> None: @@ -152,7 +152,7 @@ def validate(self, value: T, context: str = "") -> None: class MemoryParameter(Parameter): - def __init__(self, get_cmd: Callable[[], Any] | None = None, **kwargs: Any): + def __init__(self, get_cmd: Callable[[], Any] | None = None, **kwargs: Any) -> None: self.set_values: list[Any] = [] self.get_values: list[Any] = [] super().__init__( @@ -177,7 +177,7 @@ def get_func() -> ParamDataType: class VirtualParameter(Parameter): - def __init__(self, name: str, param: Parameter, **kwargs: Any): + def __init__(self, name: str, param: Parameter, **kwargs: Any) -> None: self._param = param super().__init__(name=name, **kwargs) diff --git a/tests/parameter/test_array_parameter.py b/tests/parameter/test_array_parameter.py index 8d9ff7cc75e5..710e94344fca 100644 --- a/tests/parameter/test_array_parameter.py +++ b/tests/parameter/test_array_parameter.py @@ -8,7 +8,7 @@ class SimpleArrayParam(ArrayParameter): - def __init__(self, return_val: ParamRawDataType, *args: Any, **kwargs: Any): + def __init__(self, return_val: ParamRawDataType, *args: Any, **kwargs: Any) -> None: self._return_val = return_val self._get_count = 0 super().__init__(*args, **kwargs) diff --git a/tests/parameter/test_delegate_parameter.py b/tests/parameter/test_delegate_parameter.py index 55278f3f9aae..0fe8245d87aa 100644 --- a/tests/parameter/test_delegate_parameter.py +++ b/tests/parameter/test_delegate_parameter.py @@ -41,7 +41,7 @@ def _make_simple_param(numeric_val: int) -> Generator[Parameter, None, None]: class ObservableParam(Parameter): - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: self.instr_val = None super().__init__(*args, **kwargs) @@ -792,7 +792,7 @@ def test_value_validation_with_offset_and_scale() -> None: delegate_param.set(1) -def test_delegate_of_delegate_updates_settable_gettable(): +def test_delegate_of_delegate_updates_settable_gettable() -> None: gettable_settable_source_param = Parameter( "source", set_cmd=None, get_cmd=None, vals=vals.Numbers(-5, 5) ) diff --git a/tests/parameter/test_get_latest.py b/tests/parameter/test_get_latest.py index 856f7443933f..5d9fb36c89f2 100644 --- a/tests/parameter/test_get_latest.py +++ b/tests/parameter/test_get_latest.py @@ -167,7 +167,7 @@ def test_no_get_max_val_age() -> None: # could be added in a subclass. Here we create a subclass that does add a # get command and also does not implement the check for max_val_age class LocalParameter(ParameterBase): - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.set_raw = lambda x: x # type: ignore[method-assign] self.set = self._wrap_set(self.set_raw) diff --git a/tests/parameter/test_get_set_wrapping.py b/tests/parameter/test_get_set_wrapping.py index 3bbe3416d5bd..83220d3a7d6a 100644 --- a/tests/parameter/test_get_set_wrapping.py +++ b/tests/parameter/test_get_set_wrapping.py @@ -70,7 +70,9 @@ def test_gettable_settable_attributes_with_get_set_raw( listed as gettable/settable and reverse.""" class GetSetParam(baseclass): # type: ignore[valid-type,misc] - def __init__(self, *args: Any, initial_value: Any = None, **kwargs: Any): + def __init__( + self, *args: Any, initial_value: Any = None, **kwargs: Any + ) -> None: self._value = initial_value super().__init__(*args, **kwargs) diff --git a/tests/parameter/test_group_parameter.py b/tests/parameter/test_group_parameter.py index 9464b031e1cc..d6152dbc7fb5 100644 --- a/tests/parameter/test_group_parameter.py +++ b/tests/parameter/test_group_parameter.py @@ -8,11 +8,11 @@ from qcodes.parameters import Group, GroupParameter if TYPE_CHECKING: - from collections.abc import Callable + from collections.abc import Callable, Generator @pytest.fixture(autouse=True) -def close_all_instruments(): +def close_all_instruments() -> "Generator[None, None, None]": """Makes sure that after startup and teardown all instruments are closed""" Instrument.close_all() yield diff --git a/tests/parameter/test_issequence.py b/tests/parameter/test_issequence.py index 3e4bab334bc1..769ca8bdd13e 100644 --- a/tests/parameter/test_issequence.py +++ b/tests/parameter/test_issequence.py @@ -1,9 +1,14 @@ +from typing import TYPE_CHECKING, Any, NoReturn + import pytest from qcodes.parameters.sequence_helpers import is_sequence +if TYPE_CHECKING: + from collections.abc import Iterator, Sequence + -def a_func(): +def a_func() -> NoReturn: raise RuntimeError("this function shouldn't get called") @@ -40,12 +45,12 @@ class AClass: @pytest.mark.parametrize("val", yes_sequence) -def test_yes(val) -> None: +def test_yes(val: "Sequence[Any] | Iterator[Any]") -> None: assert is_sequence(val) @pytest.mark.parametrize("val", no_sequence) -def test_no(val) -> None: +def test_no(val: object) -> None: assert not is_sequence(val) diff --git a/tests/parameter/test_issequenceof.py b/tests/parameter/test_issequenceof.py index 7c710473dfe3..2a16ac36e455 100644 --- a/tests/parameter/test_issequenceof.py +++ b/tests/parameter/test_issequenceof.py @@ -1,9 +1,12 @@ -from typing import Any +from typing import TYPE_CHECKING, Any import pytest from qcodes.parameters.sequence_helpers import is_sequence_of +if TYPE_CHECKING: + from collections.abc import Sequence + simple_good: list[tuple[Any, ...]] = [ # empty lists pass without even checking that we provided a # valid type spec @@ -20,7 +23,7 @@ @pytest.mark.parametrize("args", simple_good) -def test_simple_good(args) -> None: +def test_simple_good(args: tuple[Any, ...]) -> None: assert is_sequence_of(*args) @@ -28,7 +31,7 @@ def test_simple_good(args) -> None: @pytest.mark.parametrize("args", simple_bad) -def test_simple_bad(args) -> None: +def test_simple_bad(args: tuple[Any, ...]) -> None: assert not is_sequence_of(*args) # second arg, if provided, must be a type or tuple of types # failing this doesn't return False, it raises an error @@ -51,7 +54,9 @@ def test_examples_raises() -> None: @pytest.mark.parametrize("args", good_depth) -def test_depth_good(args) -> None: +def test_depth_good( + args: "tuple[Sequence[Any], type | tuple[type, ...] | None, int]", +) -> None: assert is_sequence_of(*args) @@ -59,7 +64,7 @@ def test_depth_good(args) -> None: @pytest.mark.parametrize("args", bad_depth) -def test_depth_bad(args) -> None: +def test_depth_bad(args: "tuple[Sequence[Any], type, int]") -> None: assert not is_sequence_of(*args) @@ -77,7 +82,9 @@ def test_depth_bad(args) -> None: @pytest.mark.parametrize("args", good_shapes) -def test_shape_good(args) -> None: +def test_shape_good( + args: "tuple[Sequence[Any], type | tuple[type, ...] | None, tuple[int, ...]]", +) -> None: obj, types, shape = args assert is_sequence_of(obj, types, shape=shape) @@ -93,7 +100,9 @@ def test_shape_good(args) -> None: @pytest.mark.parametrize("args", bad_shapes) -def test_shape_bad(args) -> None: +def test_shape_bad( + args: "tuple[Sequence[Any], type | tuple[type, ...], tuple[int, ...]]", +) -> None: obj, types, shape = args assert not is_sequence_of(obj, types, shape=shape) diff --git a/tests/parameter/test_multi_channel_instrument_parameter.py b/tests/parameter/test_multi_channel_instrument_parameter.py index c3b7d12c1456..19f051668e6b 100644 --- a/tests/parameter/test_multi_channel_instrument_parameter.py +++ b/tests/parameter/test_multi_channel_instrument_parameter.py @@ -19,7 +19,7 @@ def dummy_channel_instrument() -> "Generator[DummyChannelInstrument, None, None] def test_set_multi_channel_instrument_parameter( dummy_channel_instrument: DummyChannelInstrument, -): +) -> None: """Tests :class:`MultiChannelInstrumentParameter` set method.""" for name, param in dummy_channel_instrument.channels[0].parameters.items(): if not param.settable: diff --git a/tests/parameter/test_multi_parameter.py b/tests/parameter/test_multi_parameter.py index 5e60778a9657..453e319872f5 100644 --- a/tests/parameter/test_multi_parameter.py +++ b/tests/parameter/test_multi_parameter.py @@ -8,7 +8,7 @@ class SimpleMultiParam(MultiParameter): - def __init__(self, return_val: Any, *args: Any, **kwargs: Any): + def __init__(self, return_val: Any, *args: Any, **kwargs: Any) -> None: self._return_val = return_val self._get_count = 0 super().__init__(*args, **kwargs) diff --git a/tests/parameter/test_parameter_cache.py b/tests/parameter/test_parameter_cache.py index ca1220f063ad..68d5954be052 100644 --- a/tests/parameter/test_parameter_cache.py +++ b/tests/parameter/test_parameter_cache.py @@ -256,7 +256,7 @@ def test_no_get_max_val_age_runtime_error( value = 1 class LocalParameter(ParameterBase): - def __init__(self, *args: Any, **kwargs: Any): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.set_raw = lambda x: x # type: ignore[method-assign] self.set = self._wrap_set(self.set_raw) diff --git a/tests/parameter/test_parameter_context_manager.py b/tests/parameter/test_parameter_context_manager.py index 9f30bcc58389..f4cc7fa6f1b1 100644 --- a/tests/parameter/test_parameter_context_manager.py +++ b/tests/parameter/test_parameter_context_manager.py @@ -11,7 +11,7 @@ class DummyTrackingInstrument(DummyInstrument): - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name) self.add_parameter("a", set_cmd=None, get_cmd=None) diff --git a/tests/parameter/test_parameter_on_set_callback.py b/tests/parameter/test_parameter_on_set_callback.py index d1a9cdee8b3e..89bc5a7f4aab 100644 --- a/tests/parameter/test_parameter_on_set_callback.py +++ b/tests/parameter/test_parameter_on_set_callback.py @@ -269,12 +269,12 @@ def timing_callback(param: ParameterBase, value: Any) -> None: def test_set_callback_for_instance( basic_callback: "Callable[[ParameterBase, Any], None]", captured_params: list[tuple[ParameterBase, Any]], -): +) -> None: param_a = Parameter("test_param_a", set_cmd=None, get_cmd=None) param_b = Parameter("test_param_b", set_cmd=None, get_cmd=None) captured_instance_params = [] - def callback(param: ParameterBase, val): + def callback(param: ParameterBase, val: Any) -> None: if ParameterBase.global_on_set_callback: ParameterBase.global_on_set_callback(param, val) captured_instance_params.append(val) diff --git a/tests/parameter/test_parameter_override.py b/tests/parameter/test_parameter_override.py index a66914bf80dd..3017b87c9136 100644 --- a/tests/parameter/test_parameter_override.py +++ b/tests/parameter/test_parameter_override.py @@ -6,11 +6,14 @@ from qcodes.instrument import Instrument if TYPE_CHECKING: - from qcodes.parameters import Parameter + from typing import Unpack + + from qcodes.instrument import InstrumentBaseKWArgs + from qcodes.parameters import Parameter, ParameterBase class DummyOverrideInstr(Instrument): - def __init__(self, name, **kwargs): + def __init__(self, name: str, **kwargs: "Unpack[InstrumentBaseKWArgs]") -> None: """ This instrument errors because it tries to override an attribute with a parameter. Removing the parameter using `self.parameters.pop("voltage")` is not safe but @@ -25,19 +28,19 @@ def __init__(self, name, **kwargs): class DummyParameterIsAttrInstr(Instrument): - def __init__(self, name, **kwargs): + def __init__(self, name: str, **kwargs: "Unpack[InstrumentBaseKWArgs]") -> None: """ This instrument errors because it tries to override an attribute with a parameter. """ super().__init__(name, **kwargs) self.voltage = self.add_parameter("voltage", set_cmd=None, get_cmd=None) - def voltage(self): + def voltage(self) -> int: return 0 class DummyParameterIsPropertyInstr(Instrument): - def __init__(self, name, **kwargs): + def __init__(self, name: str, **kwargs: "Unpack[InstrumentBaseKWArgs]") -> None: """ We allow overriding a property since this pattern has been seen in the wild to define an interface for the instrument. @@ -46,7 +49,7 @@ def __init__(self, name, **kwargs): self.add_parameter("voltage", set_cmd=None, get_cmd=None) @property - def voltage(self): + def voltage(self) -> "ParameterBase": return self.parameters["voltage"] @@ -56,7 +59,7 @@ class DummyClassAttrInstr(Instrument): voltage: "Parameter | None" = None frequency: "Parameter | None" = None - def __init__(self, name, **kwargs): + def __init__(self, name: str, **kwargs: "Unpack[InstrumentBaseKWArgs]") -> None: """ We allow overriding a property since this pattern has been seen in the wild to define an interface for the instrument. @@ -68,7 +71,7 @@ def __init__(self, name, **kwargs): class DummyInstr(Instrument): - def __init__(self, name, **kwargs): + def __init__(self, name: str, **kwargs: "Unpack[InstrumentBaseKWArgs]") -> None: """ We allow overriding a property since this pattern has been seen in the wild to define an interface for the instrument. @@ -79,7 +82,7 @@ def __init__(self, name, **kwargs): self.some_attr = 1 -def test_overriding_parameter_attribute_with_parameter_raises(): +def test_overriding_parameter_attribute_with_parameter_raises() -> None: with pytest.raises( KeyError, match="Duplicate parameter name voltage on instrument", @@ -87,19 +90,21 @@ def test_overriding_parameter_attribute_with_parameter_raises(): DummyOverrideInstr("my_instr") -def test_overriding_attribute_with_parameter_raises(): +def test_overriding_attribute_with_parameter_raises() -> None: with pytest.warns( match="Parameter voltage overrides an attribute of the same name on instrument", ): DummyParameterIsAttrInstr("my_instr") -def test_overriding_property_with_parameter_works(request): +def test_overriding_property_with_parameter_works( + request: pytest.FixtureRequest, +) -> None: request.addfinalizer(DummyParameterIsPropertyInstr.close_all) DummyParameterIsPropertyInstr("my_instr") -def test_removing_parameter_works(request): +def test_removing_parameter_works(request: pytest.FixtureRequest) -> None: request.addfinalizer(DummyInstr.close_all) a = DummyInstr("my_instr") @@ -113,7 +118,9 @@ def test_removing_parameter_works(request): assert a.some_attr == 1 -def test_removed_parameter_from_prop_instrument_works(request): +def test_removed_parameter_from_prop_instrument_works( + request: pytest.FixtureRequest, +) -> None: request.addfinalizer(DummyParameterIsPropertyInstr.close_all) a = DummyParameterIsPropertyInstr("my_instr") a.remove_parameter("voltage") @@ -121,7 +128,9 @@ def test_removed_parameter_from_prop_instrument_works(request): a.voltage.set(1) -def test_remove_parameter_from_class_attr_works(request, caplog): +def test_remove_parameter_from_class_attr_works( + request: pytest.FixtureRequest, caplog: pytest.LogCaptureFixture +) -> None: request.addfinalizer(DummyClassAttrInstr.close_all) a = DummyClassAttrInstr("my_instr") diff --git a/tests/parameter/test_parameter_ramp.py b/tests/parameter/test_parameter_ramp.py index a1d49af003e3..549f263c5009 100644 --- a/tests/parameter/test_parameter_ramp.py +++ b/tests/parameter/test_parameter_ramp.py @@ -40,7 +40,7 @@ def test_step_ramp(caplog: LogCaptureFixture) -> None: @given(scale=hst.integers(1, 100), value=hst.floats(min_value=1e-9, max_value=10)) -def test_ramp_scaled(scale, value) -> None: +def test_ramp_scaled(scale: int, value: float) -> None: start_point = 0.0 p = MemoryParameter(name="p", scale=scale, initial_value=start_point) assert p() == start_point @@ -75,7 +75,7 @@ def test_ramp_scaled(scale, value) -> None: @given(value=hst.floats(min_value=1e-9, max_value=10)) -def test_ramp_parser(value) -> None: +def test_ramp_parser(value: float) -> None: start_point = 0.0 p = MemoryParameter( name="p", @@ -118,7 +118,7 @@ def test_ramp_parser(value) -> None: @given(scale=hst.integers(1, 100), value=hst.floats(min_value=1e-9, max_value=10)) @settings(deadline=None) -def test_ramp_parsed_scaled(scale, value) -> None: +def test_ramp_parsed_scaled(scale: int, value: float) -> None: start_point = 0.0 p = MemoryParameter( name="p", @@ -158,11 +158,11 @@ def test_ramp_parsed_scaled(scale, value) -> None: def test_stepping_from_invalid_starting_point() -> None: the_value = -10 - def set_function(value): + def set_function(value: float) -> None: nonlocal the_value the_value = value - def get_function(): + def get_function() -> float: return the_value a = Parameter( diff --git a/tests/parameter/test_parameter_registration.py b/tests/parameter/test_parameter_registration.py index 235bae32f1fb..00f6920c2676 100644 --- a/tests/parameter/test_parameter_registration.py +++ b/tests/parameter/test_parameter_registration.py @@ -20,7 +20,7 @@ class BrokenParameter(Parameter): def __init__( self, name: str, instrument: "InstrumentBase", *args: Any, **kwargs: Any - ): + ) -> None: super().__init__(name, *args, **kwargs) self._instrument = instrument @@ -30,7 +30,7 @@ class BrokenParameter2(Parameter): def __init__( self, name: str, instrument: "InstrumentBase", set_cmd: Any, get_cmd: Any - ): + ) -> None: super().__init__(name=name, instrument=instrument) diff --git a/tests/parameter/test_parameter_scale_offset.py b/tests/parameter/test_parameter_scale_offset.py index 7ba9533c668e..0070e088f954 100644 --- a/tests/parameter/test_parameter_scale_offset.py +++ b/tests/parameter/test_parameter_scale_offset.py @@ -50,7 +50,13 @@ def test_scale_raw_value() -> None: # the following test stra @hst.composite -def iterable_or_number(draw, values, size, values_scalar, is_values): +def iterable_or_number( + draw: hst.DrawFn, + values: hst.SearchStrategy[float], + size: hst.SearchStrategy[int], + values_scalar: hst.SearchStrategy[bool], + is_values: bool, +) -> float | list[float]: if draw(values_scalar): # if parameter values are scalar, # return scalar for values and scale/offset @@ -74,7 +80,11 @@ def iterable_or_number(draw, values, size, values_scalar, is_values): offsets=iterable_or_number(TestFloats, SharedSize, ValuesScalar, False), scales=iterable_or_number(TestFloats, SharedSize, ValuesScalar, False), ) -def test_scale_and_offset_raw_value_iterable(values, offsets, scales) -> None: +def test_scale_and_offset_raw_value_iterable( + values: float | list[float], + offsets: float | list[float], + scales: float | list[float], +) -> None: p = Parameter(name="test_scale_and_offset_raw_value", set_cmd=None) # test that scale and offset does not change the default behaviour @@ -95,6 +105,9 @@ def test_scale_and_offset_raw_value_iterable(values, offsets, scales) -> None: # test set, only for scalar values if not isinstance(values, Iterable): + # scalar values imply scalar scale/offset (shared ``values_scalar`` draw) + assert not isinstance(scales, Iterable) + assert not isinstance(offsets, Iterable) p(values) # No set/get cmd performed np.testing.assert_allclose( @@ -138,7 +151,9 @@ def test_scale_and_offset_raw_value_iterable(values, offsets, scales) -> None: scales=iterable_or_number(TestFloats, SharedSize, ValuesScalar, False), ) def test_scale_and_offset_raw_value_iterable_for_set_cache( - values, offsets, scales + values: float | list[float], + offsets: float | list[float], + scales: float | list[float], ) -> None: p = Parameter(name="test_scale_and_offset_raw_value", set_cmd=None) @@ -199,7 +214,7 @@ def test_scale_and_offset_raw_value_iterable_for_set_cache( def test_numpy_array_valued_parameter_preserves_type_if_scale_and_offset_are_set() -> ( None ): - def rands(): + def rands() -> np.ndarray: return np.random.default_rng().standard_normal(5) param = Parameter(name="test_param", set_cmd=None, get_cmd=rands) diff --git a/tests/parameter/test_parameter_with_setpoints.py b/tests/parameter/test_parameter_with_setpoints.py index 497fe08a6275..c16fe018d43c 100644 --- a/tests/parameter/test_parameter_with_setpoints.py +++ b/tests/parameter/test_parameter_with_setpoints.py @@ -1,14 +1,23 @@ +from typing import TYPE_CHECKING + import numpy as np import pytest import qcodes.validators as vals from qcodes.parameters import Parameter, ParameterWithSetpoints, expand_setpoints_helper +if TYPE_CHECKING: + from collections.abc import Generator + _rng = np.random.default_rng() +type SetpointsParameters = tuple[ + Parameter, Parameter, Parameter, Parameter, Parameter, Parameter +] + @pytest.fixture() -def parameters(): +def parameters() -> "Generator[SetpointsParameters, None, None]": n_points_1 = Parameter("n_points_1", set_cmd=None, vals=vals.Ints()) n_points_2 = Parameter("n_points_2", set_cmd=None, vals=vals.Ints()) n_points_3 = Parameter("n_points_3", set_cmd=None, vals=vals.Ints()) @@ -370,7 +379,7 @@ def test_validation_one_sp_dim_missing() -> None: param_sp_without_shape.validate(param_sp_without_shape.get()) -def test_expand_setpoints_1c(parameters) -> None: +def test_expand_setpoints_1c(parameters: SetpointsParameters) -> None: """ Test that the setpoints expander helper function works correctly """ @@ -392,7 +401,7 @@ def test_expand_setpoints_1c(parameters) -> None: assert len(data[0][1]) == len(data[1][1]) -def test_expand_setpoints_2d(parameters) -> None: +def test_expand_setpoints_2d(parameters: SetpointsParameters) -> None: n_points_1, n_points_2, _n_points_3, setpoints_1, setpoints_2, _setpoints_3 = ( parameters ) @@ -420,7 +429,7 @@ def test_expand_setpoints_2d(parameters) -> None: np.testing.assert_array_equal(sp2[i, :], np.arange(sp1.shape[1])) -def test_expand_setpoints_3d(parameters) -> None: +def test_expand_setpoints_3d(parameters: SetpointsParameters) -> None: n_points_1, n_points_2, n_points_3, setpoints_1, setpoints_2, setpoints_3 = ( parameters ) diff --git a/tests/parameter/test_permissive_range.py b/tests/parameter/test_permissive_range.py index c0a5928a956f..c4e511b3666d 100644 --- a/tests/parameter/test_permissive_range.py +++ b/tests/parameter/test_permissive_range.py @@ -23,13 +23,13 @@ @pytest.mark.parametrize("args", bad_args) -def test_bad_calls(args) -> None: +def test_bad_calls(args: list[float | str | None]) -> None: with pytest.raises(TypeError): - permissive_range(*args) + permissive_range(*args) # pyright: ignore[reportArgumentType] @pytest.mark.parametrize("args,result", good_args) -def test_good_calls(args, result) -> None: +def test_good_calls(args: tuple[float, float, float], result: list[float]) -> None: # TODO(giulioungaretti) # not sure what we are testing here. # in python 1.0 and 1 are actually the same diff --git a/tests/parameter/test_scaled_parameter.py b/tests/parameter/test_scaled_parameter.py index 9c9a0092eb21..fb2357ce4063 100644 --- a/tests/parameter/test_scaled_parameter.py +++ b/tests/parameter/test_scaled_parameter.py @@ -116,7 +116,7 @@ def test_wrapped_parameter(instrument: DummyInstrument) -> None: assert instrument.scaler.wrapped_parameter == instrument.target_parameter -def test_divider(instrument) -> None: +def test_divider(instrument: DummyInstrument) -> None: test_division = 10 test_value = 5 diff --git a/tests/parameter/test_validators.py b/tests/parameter/test_validators.py index 4d98bbfb7866..338a9247755d 100644 --- a/tests/parameter/test_validators.py +++ b/tests/parameter/test_validators.py @@ -6,7 +6,7 @@ from qcodes.validators import Ints, Numbers -def test_add_ints_validator_to_parameter(): +def test_add_ints_validator_to_parameter() -> None: p = Parameter("test_param", set_cmd=None, get_cmd=None) ints_val = Ints(min_value=0, max_value=10) p.add_validator(ints_val) @@ -15,7 +15,7 @@ def test_add_ints_validator_to_parameter(): assert p.vals is ints_val -def test_remove_ints_validator_from_parameter(): +def test_remove_ints_validator_from_parameter() -> None: p = Parameter("test_param", set_cmd=None, get_cmd=None) p.add_validator(Ints(min_value=0, max_value=10)) p.remove_validator() @@ -148,7 +148,7 @@ def test_validator_snapshot() -> None: assert "" == snapshot["vals"] -def test_replace_vals(): +def test_replace_vals() -> None: p = Parameter("test_param", set_cmd=None, get_cmd=None) val1 = Ints(min_value=0, max_value=10) p.add_validator(val1) diff --git a/tests/sphinx_extension/test_parse_parameter_attr.py b/tests/sphinx_extension/test_parse_parameter_attr.py index a19d457eb544..c0331a715195 100644 --- a/tests/sphinx_extension/test_parse_parameter_attr.py +++ b/tests/sphinx_extension/test_parse_parameter_attr.py @@ -1,3 +1,5 @@ +from typing import Any + import pytest from sphinx.util.inspect import safe_getattr from typing_extensions import deprecated @@ -15,7 +17,7 @@ class DummyTestClass(InstrumentBase): A class attribute """ - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.other_attr = "InstanceAttribute" @@ -41,7 +43,7 @@ class DummyDecoratedInitTestClass(InstrumentBase): """ @deprecated("Deprecate to test that decorated init is handled correctly") - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.other_attr = "InstanceAttribute" @@ -57,7 +59,7 @@ class DummyDecoratedClassTestClass(InstrumentBase): A class attribute """ - def __init__(self, *args, **kwargs): + def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) self.other_attr = "InstanceAttribute" diff --git a/tests/test_abstract_instrument.py b/tests/test_abstract_instrument.py index 63a6bd729b3d..5b32772d1a7a 100644 --- a/tests/test_abstract_instrument.py +++ b/tests/test_abstract_instrument.py @@ -1,10 +1,13 @@ -from typing import Any +from typing import TYPE_CHECKING, Any import pytest from pytest import FixtureRequest from qcodes.instrument import ChannelList, Instrument, InstrumentBase, InstrumentChannel +if TYPE_CHECKING: + from collections.abc import Generator + class ExampleBaseVoltageSource(Instrument): """ @@ -13,7 +16,7 @@ class ExampleBaseVoltageSource(Instrument): allows us to enforce an interface. """ - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name) self.add_parameter( @@ -28,7 +31,7 @@ class VoltageSource(ExampleBaseVoltageSource): Make a specific implementation of the interface """ - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name) self.add_parameter("voltage", unit="V", get_cmd=None, set_cmd=None) @@ -45,7 +48,7 @@ class VoltageSourceBadUnit(ExampleBaseVoltageSource): The units must match between sub and base classes """ - def __init__(self, name: str): + def __init__(self, name: str) -> None: super().__init__(name) self.add_parameter( @@ -63,7 +66,7 @@ class VoltageSourceInitException(Instrument): is raised """ - def __init__(self, name: str, do_raise=True): + def __init__(self, name: str, do_raise: bool = True) -> None: super().__init__(name) if do_raise: @@ -75,7 +78,7 @@ class VoltageChannelBase(InstrumentChannel): Create a channel with an abstract parameter """ - def __init__(self, parent: InstrumentBase, name: str, **kwargs: Any): + def __init__(self, parent: InstrumentBase, name: str, **kwargs: Any) -> None: super().__init__(parent, name, **kwargs) self.add_parameter("voltage", unit="V", abstract=True) @@ -86,7 +89,7 @@ class VoltageChannel(VoltageChannelBase): Create an implementation of the abstract channel """ - def __init__(self, parent: InstrumentBase, name: str, **kwargs: Any): + def __init__(self, parent: InstrumentBase, name: str, **kwargs: Any) -> None: super().__init__(parent, name, **kwargs) self.add_parameter("voltage", unit="V", get_cmd=None, set_cmd=None) @@ -101,7 +104,7 @@ class VoltageAbstractChannelSource(Instrument): def __init__( self, name: str, - ): + ) -> None: super().__init__(name) channel = VoltageChannelBase(self, "voltage") self.add_submodule("voltage", channel) @@ -117,7 +120,7 @@ class VoltageChannelSource(Instrument): def __init__( self, name: str, - ): + ) -> None: super().__init__(name) channel = VoltageChannel(self, "voltage") self.add_submodule("voltage", channel) @@ -132,7 +135,7 @@ class VoltageAbstractChannelListSource(Instrument): def __init__( self, name: str, - ): + ) -> None: super().__init__(name) channel = VoltageChannelBase(self, "voltage") channellist = ChannelList(self, "cl", VoltageChannelBase, chan_list=[channel]) @@ -149,7 +152,7 @@ class VoltageChannelListSource(Instrument): def __init__( self, name: str, - ): + ) -> None: super().__init__(name) channel = VoltageChannel(self, "voltage") channellist = ChannelList(self, "cl", VoltageChannel, chan_list=[channel]) @@ -157,13 +160,13 @@ def __init__( @pytest.fixture(name="driver", scope="module") -def _driver(): +def _driver() -> "Generator[VoltageSource, None, None]": drvr = VoltageSource("abstract_instrument_driver") yield drvr drvr.close() -def test_sanity(driver) -> None: +def test_sanity(driver: VoltageSource) -> None: """ If all abstract parameters are implemented, we should be able to instantiate the instrument diff --git a/tests/test_autoloadable_channels.py b/tests/test_autoloadable_channels.py index 1a79cd142da2..e2633a99a570 100644 --- a/tests/test_autoloadable_channels.py +++ b/tests/test_autoloadable_channels.py @@ -103,7 +103,7 @@ class SimpleTestChannel(AutoLoadableInstrumentChannel): @classmethod def _discover_from_instrument( - cls, parent: InstrumentBase, **kwargs + cls, parent: InstrumentBase, **kwargs: Any ) -> list[dict[Any, Any]]: """ New channels need `name` and `channel` keyword arguments. @@ -131,7 +131,7 @@ def _discover_from_instrument( @classmethod def _get_new_instance_kwargs( - cls, parent: InstrumentBase | None = None, **kwargs + cls, parent: InstrumentBase | None = None, **kwargs: Any ) -> dict[Any, Any]: """ Find the smallest channel number not yet occupied. An optional keyword diff --git a/tests/test_channels.py b/tests/test_channels.py index 910c9bec5492..0537146357a9 100644 --- a/tests/test_channels.py +++ b/tests/test_channels.py @@ -1,7 +1,7 @@ import logging import re from collections.abc import Generator, Sequence -from typing import TYPE_CHECKING, assert_type +from typing import TYPE_CHECKING, Any, assert_type import hypothesis.strategies as hst import numpy as np @@ -114,7 +114,7 @@ def test_channels_get(dci: DummyChannelInstrument) -> None: @settings(suppress_health_check=(HealthCheck.function_scoped_fixture,)) @given(value=hst.floats(0, 300), channel=hst.integers(0, 3)) def test_channel_access_is_identical( - dci: DummyChannelInstrument, value, channel + dci: DummyChannelInstrument, value: float, channel: int ) -> None: channel_to_label = {0: "A", 1: "B", 2: "C", 3: "D"} label = channel_to_label[channel] @@ -836,7 +836,7 @@ def test_multi_function_on_empty_channel_tuple_raises( channels.multi_function("temperature") -def _verify_multiparam_data(data) -> None: +def _verify_multiparam_data(data: Any) -> None: assert "multi_setpoint_param_this_setpoint_set" in data.arrays assert_array_equal( data.arrays["multi_setpoint_param_this_setpoint_set"].ndarray, @@ -856,7 +856,7 @@ def _verify_multiparam_data(data) -> None: ) -def _verify_array_data(data, channels=("A",)) -> None: +def _verify_array_data(data: Any, channels: Sequence[str] = ("A",)) -> None: assert "array_setpoint_param_this_setpoint_set" in data.arrays assert_array_equal( data.arrays["array_setpoint_param_this_setpoint_set"].ndarray, diff --git a/tests/test_command.py b/tests/test_command.py index 8db963dcb9ab..7b9dbc34bfa4 100644 --- a/tests/test_command.py +++ b/tests/test_command.py @@ -46,16 +46,16 @@ def no_cmd_function() -> NoReturn: def test_cmd_str() -> None: - def f_now(x): + def f_now(x: str) -> str: return x + " now" - def upper(s): + def upper(s: str) -> str: return s.upper() - def reversestr(s): + def reversestr(s: str) -> str: return s[::-1] - def swap(a, b): + def swap(a: str, b: str) -> tuple[str, str]: return b, a # basic exec_str diff --git a/tests/test_config.py b/tests/test_config.py index e85c10b7e57a..f1cf2315411a 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -2,6 +2,7 @@ import json import os from functools import partial +from typing import TYPE_CHECKING, Any from unittest.mock import PropertyMock, mock_open import jsonschema.exceptions @@ -10,6 +11,12 @@ import qcodes from qcodes.configuration import Config +if TYPE_CHECKING: + from collections.abc import Generator, Mapping + from pathlib import Path + + from pytest_mock import MockerFixture, MockType + VALID_JSON = "{}" ENV_KEY = "/dev/random" BAD_JSON = "{}" @@ -107,12 +114,12 @@ } -def side_effect(map, name): +def side_effect(map: "Mapping[str, dict[str, Any]]", name: str) -> dict[str, Any]: return map[name] @pytest.fixture(scope="function") -def path_to_config_file_on_disk(tmp_path): +def path_to_config_file_on_disk(tmp_path: "Path") -> "Generator[str, None, None]": contents = { "core": { "loglevel": "WARNING", @@ -137,13 +144,13 @@ def path_to_config_file_on_disk(tmp_path): @pytest.fixture(name="config") -def _make_config(): +def _make_config() -> "Generator[Config, None, None]": conf = Config() yield conf @pytest.fixture(name="load_config") -def _make_mock_config(mocker): +def _make_mock_config(mocker: "MockerFixture") -> "Generator[MockType, None, None]": schema = mocker.patch.object(Config, "current_schema", new_callable=PropertyMock) env = mocker.patch.object(Config, "env_file_name", new_callable=PropertyMock) load_config = mocker.patch.object(Config, "load_config") @@ -155,42 +162,46 @@ def _make_mock_config(mocker): yield load_config -def test_missing_config_file(config) -> None: +def test_missing_config_file(config: Config) -> None: with pytest.raises(FileNotFoundError): config.load_config("./missing.json") -def test_default_config_files(config, load_config) -> None: +def test_default_config_files(config: Config, load_config: "MockType") -> None: load_config.side_effect = partial(side_effect, GOOD_CONFIG_MAP) # don't try to load custom schemas - config.schema_cwd_file_name = None - config.schema_home_file_name = None - config.schema_env_file_name = None + config.schema_cwd_file_name = None # pyright: ignore[reportAttributeAccessIssue] + config.schema_home_file_name = None # pyright: ignore[reportAttributeAccessIssue] + config.schema_env_file_name = None # pyright: ignore[reportAttributeAccessIssue] config.defaults, _ = config.load_default() - config = config.update_config() - assert config == CONFIG + updated_config = config.update_config() + assert updated_config == CONFIG -def test_bad_config_files(config, load_config) -> None: +def test_bad_config_files(config: Config, load_config: "MockType") -> None: load_config.side_effect = partial(side_effect, BAD_CONFIG_MAP) # don't try to load custom schemas - config.schema_cwd_file_name = None - config.schema_home_file_name = None - config.schema_env_file_name = None + config.schema_cwd_file_name = None # pyright: ignore[reportAttributeAccessIssue] + config.schema_home_file_name = None # pyright: ignore[reportAttributeAccessIssue] + config.schema_env_file_name = None # pyright: ignore[reportAttributeAccessIssue] config.defaults, _ = config.load_default() with pytest.raises(jsonschema.exceptions.ValidationError): config.update_config() -def test_user_schema(config, load_config, mocker) -> None: +def test_user_schema( + config: Config, load_config: "MockType", mocker: "MockerFixture" +) -> None: mocker.patch("builtins.open", mock_open(read_data=USER_SCHEMA)) load_config.side_effect = partial(side_effect, GOOD_CONFIG_MAP) config.defaults, _ = config.load_default() - config = config.update_config() - assert config == CONFIG + updated_config = config.update_config() + assert updated_config == CONFIG -def test_bad_user_schema(config, load_config, mocker) -> None: +def test_bad_user_schema( + config: Config, load_config: "MockType", mocker: "MockerFixture" +) -> None: mocker.patch("builtins.open", mock_open(read_data=USER_SCHEMA)) load_config.side_effect = partial(side_effect, BAD_CONFIG_MAP) config.defaults, _ = config.load_default() @@ -198,7 +209,7 @@ def test_bad_user_schema(config, load_config, mocker) -> None: config.update_config() -def test_update_user_config(config, mocker) -> None: +def test_update_user_config(config: Config, mocker: "MockerFixture") -> None: myconfig = mocker.patch.object(Config, "current_config", new_callable=PropertyMock) # deep copy because we mutate state myconfig.return_value = copy.deepcopy(CONFIG) @@ -207,7 +218,9 @@ def test_update_user_config(config, mocker) -> None: assert config.current_config == UPDATED_CONFIG -def test_update_and_validate_user_config(config, mocker) -> None: +def test_update_and_validate_user_config( + config: Config, mocker: "MockerFixture" +) -> None: myconfig = mocker.patch.object(Config, "current_config", new_callable=PropertyMock) schema = mocker.patch.object(Config, "current_schema", new_callable=PropertyMock) schema.return_value = copy.deepcopy(SCHEMA) @@ -218,7 +231,7 @@ def test_update_and_validate_user_config(config, mocker) -> None: assert config.current_schema == UPDATED_SCHEMA -def test_update_from_path(path_to_config_file_on_disk) -> None: +def test_update_from_path(path_to_config_file_on_disk: str) -> None: cfg = qcodes.config # check that the default is still the default diff --git a/tests/test_field_vector.py b/tests/test_field_vector.py index fe3711ce32f2..16cb6f2b3765 100644 --- a/tests/test_field_vector.py +++ b/tests/test_field_vector.py @@ -38,13 +38,13 @@ @given(random_coordinates["spherical"]) @settings(max_examples=10) -def test_spherical_properties(spherical0) -> None: +def test_spherical_properties(spherical_coords: tuple[float, float, float]) -> None: """ If the cartesian to spherical transform has been correctly implemented then we expect certain symmetrical properties """ # Generate a random coordinate in spherical representation - spherical0 = dict(zip(["r", "theta", "phi"], spherical0)) + spherical0 = dict(zip(["r", "theta", "phi"], spherical_coords)) cartisian0 = FieldVector(**spherical0).get_components("x", "y", "z") # Mirror the theta angle in the xy-plane. @@ -80,13 +80,15 @@ def test_spherical_properties(spherical0) -> None: @given(random_coordinates["cylindrical"]) @settings(max_examples=10) -def test_cylindrical_properties(cylindrical0) -> None: +def test_cylindrical_properties( + cylindrical_coords: tuple[float, float, float], +) -> None: """ If the cartesian to cylindrical transform has been correctly implemented then we expect certain symmetrical properties """ # Generate a random coordinate in cylindrical representation - cylindrical0 = dict(zip(["rho", "phi", "z"], cylindrical0)) + cylindrical0 = dict(zip(["rho", "phi", "z"], cylindrical_coords)) cartisian0 = FieldVector(**cylindrical0).get_components("x", "y", "z") # If we flip the sign of the rho coordinate, we will flip the xy coordinate @@ -99,9 +101,12 @@ def test_cylindrical_properties(cylindrical0) -> None: @given(random_coordinates["cylindrical"], random_coordinates["spherical"]) @settings(max_examples=10) -def test_triangle_inequality(cylindrical0, spherical0) -> None: - cylindrical0 = FieldVector(**dict(zip(["rho", "phi", "z"], cylindrical0))) - spherical0 = FieldVector(**dict(zip(["r", "phi", "theta"], spherical0))) +def test_triangle_inequality( + cylindrical_coords: tuple[float, float, float], + spherical_coords: tuple[float, float, float], +) -> None: + cylindrical0 = FieldVector(**dict(zip(["rho", "phi", "z"], cylindrical_coords))) + spherical0 = FieldVector(**dict(zip(["r", "phi", "theta"], spherical_coords))) assert (cylindrical0 + spherical0).norm() <= ( cylindrical0.norm() + spherical0.norm() @@ -113,7 +118,7 @@ def test_triangle_inequality(cylindrical0, spherical0) -> None: @given(random_coordinates["cartesian"]) @settings(max_examples=10) -def test_homogeneous_roundtrip(cartesian0) -> None: +def test_homogeneous_roundtrip(cartesian0: tuple[float, float, float]) -> None: vec = FieldVector(**dict(zip("xyz", cartesian0))) h_vec = 13 * vec.as_homogeneous() @@ -125,7 +130,7 @@ def test_homogeneous_roundtrip(cartesian0) -> None: @given(random_coordinates["spherical"]) @settings(max_examples=10) -def test_json_dump(spherical0) -> None: +def test_json_dump(spherical0: tuple[float, float, float]) -> None: vec = FieldVector(**dict(zip(["r", "phi", "theta"], spherical0))) dump = json.dumps(vec, cls=NumpyJSONEncoder) diff --git a/tests/test_instrument.py b/tests/test_instrument.py index b2ba6dec987b..a3a96126714a 100644 --- a/tests/test_instrument.py +++ b/tests/test_instrument.py @@ -34,7 +34,9 @@ from qcodes.parameters import Function, Parameter if TYPE_CHECKING: - from collections.abc import Iterator + from collections.abc import Iterator, Sequence + + from qcodes.metadatable.metadatable_base import Snapshot, SnapshotUpdate @pytest.fixture(name="testdummy", scope="function") @@ -75,7 +77,7 @@ def _empty_instrument_with_empty_submodule() -> Iterator[Instrument]: @pytest.fixture(name="close_before_and_after", scope="function") -def _close_before_and_after(): +def _close_before_and_after() -> Iterator[None]: Instrument.close_all() try: yield @@ -266,7 +268,7 @@ def test_repr(testdummy: DummyInstrument) -> None: assert repr(testdummy) == "" -def test_add_remove_f_p(testdummy) -> None: +def test_add_remove_f_p(testdummy: DummyInstrument) -> None: with pytest.raises(KeyError, match="Duplicate parameter name dac1"): testdummy.add_parameter("dac1", get_cmd="foo") @@ -294,7 +296,7 @@ def test_add_remove_f_p(testdummy) -> None: assert isinstance(dac1, Parameter) -def test_instances(testdummy, parabola) -> None: +def test_instances(testdummy: DummyInstrument, parabola: MockParabola) -> None: instruments = [testdummy, parabola] for instrument in instruments: for other_instrument in instruments: @@ -312,13 +314,13 @@ def test_instances(testdummy, parabola) -> None: assert instrument is Instrument.find_instrument(instrument.name) -def test_is_valid(testdummy) -> None: +def test_is_valid(testdummy: DummyInstrument) -> None: assert Instrument.is_valid(testdummy) testdummy.close() assert not Instrument.is_valid(testdummy) -def test_snapshot_value(testdummy) -> None: +def test_snapshot_value(testdummy: DummyInstrument) -> None: testdummy.add_parameter( "has_snapshot_value", parameter_class=Parameter, @@ -346,7 +348,7 @@ def test_snapshot_value(testdummy) -> None: assert "value" not in snapshot["parameters"]["no_snapshot_value"] -def test_meta_instrument(parabola) -> None: +def test_meta_instrument(parabola: MockParabola) -> None: mock_instrument = MockMetaParabola("mock_parabola", parabola) # Check that the mock instrument can return values @@ -382,7 +384,7 @@ def test_empty_instrument(empty_instrument_with_empty_submodule: Instrument) -> empty_instrument_with_empty_submodule.print_readable_snapshot() -def test_find(testdummy) -> None: +def test_find(testdummy: DummyInstrument) -> None: """Test finding an existing instrument""" instr_2 = find_or_create_instrument( @@ -567,7 +569,7 @@ def test_instrumentbase_metadata() -> None: @pytest.mark.parametrize("cls", [(InstrumentBase), (Instrument)]) -def test_instrument_label(cls, request: FixtureRequest) -> None: +def test_instrument_label(cls: type[InstrumentBase], request: FixtureRequest) -> None: """Instrument uses nicely formatted label if available.""" instrument = cls(name="name") if isinstance(cls, type(Instrument)): @@ -585,7 +587,7 @@ def test_instrument_label(cls, request: FixtureRequest) -> None: assert instrument.label == label -def test_instrument_without_ref_is_gced(): +def test_instrument_without_ref_is_gced() -> None: # When there are no active references to an instrument and it is # gced there should be no live references to the instrument @@ -627,14 +629,18 @@ def __init__(self, sample_value: int) -> None: super().__init__() self.sample_value = sample_value - def snapshot_base(self, update=True, params_to_skip_update=None): + def snapshot_base( + self, + update: bool | SnapshotUpdate | None = True, + params_to_skip_update: Sequence[str] | None = None, + ) -> Snapshot: return {"sample_key": self.sample_value} class TestInstrument(InstrumentBase): __test__ = False - def __init__(self, name, label) -> None: + def __init__(self, name: str, label: str) -> None: super().__init__(name, label=label) self._meta_attrs.extend(["test_attribute"]) self._test_attribute = TestSnapshotType(12) diff --git a/tests/test_interactive_widget.py b/tests/test_interactive_widget.py index 283665bcf5a7..85a7eeb9e6ff 100644 --- a/tests/test_interactive_widget.py +++ b/tests/test_interactive_widget.py @@ -1,4 +1,6 @@ import time +from pathlib import Path +from typing import TYPE_CHECKING, Literal from unittest.mock import patch # importing ipykernel has the side effect @@ -17,12 +19,20 @@ from qcodes import interactive_widget +if TYPE_CHECKING: + from collections.abc import Callable, Generator + from unittest.mock import MagicMock + + from ipywidgets import Box # type: ignore[import-untyped] + + from qcodes.dataset.data_set import DataSet + # set matplotlib backend before importing pyplot matplotlib.use("Agg") @pytest.fixture(name="tab", scope="function") -def _create_tab(): +def _create_tab() -> "Generator[Tab, None, None]": yield interactive_widget.create_tab() @@ -53,7 +63,7 @@ def test_full_widget_on_one_dataset() -> None: def test_button_to_text( - standalone_parameters_dataset, + standalone_parameters_dataset: "DataSet", ) -> None: box = interactive_widget.button_to_text("title", "body") (button,) = box.children @@ -66,7 +76,7 @@ def test_button_to_text( assert len(box.children) == 1 -def test_snapshot_button(tab, standalone_parameters_dataset) -> None: +def test_snapshot_button(tab: Tab, standalone_parameters_dataset: "DataSet") -> None: ds = standalone_parameters_dataset snapshot_button = interactive_widget._get_snapshot_button(ds, tab) snapshot_button.click() @@ -75,19 +85,36 @@ def test_snapshot_button(tab, standalone_parameters_dataset) -> None: assert "snapshot" in tab.get_title(1) -def test_export_button(tab, standalone_parameters_dataset) -> None: +def test_export_button( + tab: Tab, + standalone_parameters_dataset: "DataSet", + tmp_path: Path, + monkeypatch: pytest.MonkeyPatch, +) -> None: + # the export button writes to the current working directory + monkeypatch.chdir(tmp_path) ds = standalone_parameters_dataset export_button = interactive_widget._get_export_button(ds, tab) export_button.click() - time.sleep(0.5) # after click + + export_path = Path(ds.export_info.export_paths["csv"]) + assert export_path.parent == tmp_path / "export" + assert export_path.is_file() @patch("matplotlib.pyplot.show") -def test_plot_button(tab, standalone_parameters_dataset) -> None: +def test_plot_button( + mock_show: "MagicMock", tab: Tab, standalone_parameters_dataset: "DataSet" +) -> None: ds = standalone_parameters_dataset plot_button = interactive_widget._get_plot_button(ds, tab) plot_button.click() - time.sleep(0.5) # after click + + assert len(tab.children) == 2 + assert tab.get_title(1) == f"RID #{ds.captured_run_id} plot" + # plt.show is only reached if plot_dataset did not raise; errors inside the + # widget callback are caught and printed rather than propagated + mock_show.assert_called_once() @pytest.mark.parametrize( @@ -100,8 +127,8 @@ def test_plot_button(tab, standalone_parameters_dataset) -> None: ], ) def test_get_experiment_button( - get_button_function, - standalone_parameters_dataset, + get_button_function: "Callable[[DataSet], Box]", + standalone_parameters_dataset: "DataSet", ) -> None: ds = standalone_parameters_dataset box = get_button_function(ds) @@ -111,14 +138,14 @@ def test_get_experiment_button( assert len(box.children) == 2 -def test_get_parameters(standalone_parameters_dataset) -> None: +def test_get_parameters(standalone_parameters_dataset: "DataSet") -> None: parameters = interactive_widget._get_parameters(standalone_parameters_dataset) assert bool(parameters["dependent"]) # not empty assert bool(parameters["independent"]) # not empty def test_editable_metadata( - standalone_parameters_dataset, + standalone_parameters_dataset: "DataSet", ) -> None: ds = standalone_parameters_dataset box = interactive_widget.editable_metadata(ds) @@ -139,7 +166,7 @@ def test_editable_metadata( assert box.children[0].description == test_test -def test_experiments_widget(standalone_parameters_dataset) -> None: +def test_experiments_widget(standalone_parameters_dataset: "DataSet") -> None: dss = [standalone_parameters_dataset] widget = interactive_widget.experiments_widget(data_sets=dss) assert len(widget.children) == 3 @@ -151,7 +178,10 @@ def test_experiments_widget(standalone_parameters_dataset) -> None: @pytest.mark.parametrize("sort_by", [None, "run_id", "timestamp"]) -def test_experiments_widget_sorting(standalone_parameters_dataset, sort_by) -> None: +def test_experiments_widget_sorting( + standalone_parameters_dataset: "DataSet", + sort_by: Literal["timestamp", "run_id"] | None, +) -> None: dss = [standalone_parameters_dataset] widget = interactive_widget.experiments_widget(data_sets=dss, sort_by=sort_by) assert len(widget.children) == 3 diff --git a/tests/test_logger.py b/tests/test_logger.py index c70e0bf1e728..dfa00e32dbca 100644 --- a/tests/test_logger.py +++ b/tests/test_logger.py @@ -333,7 +333,9 @@ def test_instrument_connect_message(caplog: LogCaptureFixture) -> None: assert any(rec.msg == expected_con_mssg for rec in setup_records) -def test_instrument_logger_extra_info(awg5208, caplog: LogCaptureFixture) -> None: +def test_instrument_logger_extra_info( + awg5208: TektronixAWG5208, caplog: LogCaptureFixture +) -> None: """ Test that the connect_message method logs as expected diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 87da1e55699e..b608d7bd2b05 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -8,11 +8,17 @@ from qcodes.utils import diff_param_values if TYPE_CHECKING: - from qcodes.metadatable.metadatable_base import Snapshot + from collections.abc import Sequence + + from qcodes.metadatable.metadatable_base import Snapshot, SnapshotUpdate class HasSnapshotBase(Metadatable): - def snapshot_base(self, update=False, params_to_skip_update=None): + def snapshot_base( + self, + update: bool | SnapshotUpdate | None = False, + params_to_skip_update: Sequence[str] | None = None, + ) -> Snapshot: return {"cheese": "gruyere"} diff --git a/tests/test_monitor.py b/tests/test_monitor.py index b0772e63b678..523456e1be3f 100644 --- a/tests/test_monitor.py +++ b/tests/test_monitor.py @@ -6,7 +6,7 @@ import json import random -from typing import cast +from typing import TYPE_CHECKING, cast import pytest import websockets @@ -19,11 +19,18 @@ from qcodes.monitor import monitor from qcodes.parameters import Parameter +if TYPE_CHECKING: + from collections.abc import Generator + monitor.WEBSOCKET_PORT = random.randint(50000, 60000) @pytest.fixture(name="inst_and_monitor") -def _make_inst_and_monitor(): +def _make_inst_and_monitor() -> Generator[ + tuple[DummyInstrument, monitor.Monitor, tuple[Parameter, ...], Parameter], + None, + None, +]: instr = DummyInstrument("MonitorDummy") param = Parameter("DummyParam", unit="V", get_cmd=None, set_cmd=None) param(1) @@ -39,7 +46,7 @@ def _make_inst_and_monitor(): @pytest.fixture(name="channel_instr") -def _make_channel_instr(): +def _make_channel_instr() -> Generator[DummyChannelInstrument, None, None]: instr = DummyChannelInstrument("MonitorDummy") try: yield instr @@ -48,7 +55,9 @@ def _make_channel_instr(): @pytest.fixture(name="channel_instr_monitor", params=[True, False]) -def _make_channel_instr_monitor(channel_instr, request: FixtureRequest): +def _make_channel_instr_monitor( + channel_instr: DummyChannelInstrument, request: FixtureRequest +) -> Generator[tuple[monitor.Monitor, bool], None, None]: m = monitor.Monitor( channel_instr.A.dummy_start, channel_instr.B.dummy_start, @@ -117,7 +126,11 @@ async def test_connection() -> None: @pytest.mark.asyncio -async def test_instrument_update(inst_and_monitor) -> None: +async def test_instrument_update( + inst_and_monitor: tuple[ + DummyInstrument, monitor.Monitor, tuple[Parameter, ...], Parameter + ], +) -> None: """ Test instrument updates """ @@ -164,7 +177,9 @@ async def test_instrument_update(inst_and_monitor) -> None: @pytest.mark.asyncio -async def test_monitor_root_instr(channel_instr_monitor) -> None: +async def test_monitor_root_instr( + channel_instr_monitor: tuple[monitor.Monitor, bool], +) -> None: _, use_root_instrument = channel_instr_monitor async with websockets.connect( f"ws://localhost:{monitor.WEBSOCKET_PORT}" diff --git a/tests/test_plot_utils.py b/tests/test_plot_utils.py index 5e07095be83f..ea867e765036 100644 --- a/tests/test_plot_utils.py +++ b/tests/test_plot_utils.py @@ -2,6 +2,8 @@ Tests for `qcodes.utils.plotting`. """ +from typing import TYPE_CHECKING + import matplotlib from pytest import fixture @@ -10,6 +12,9 @@ from .dataset_generators import dataset_with_outliers_generator +if TYPE_CHECKING: + from qcodes.dataset.data_set import DataSet + # set matplotlib backend before importing pyplot matplotlib.use("Agg") @@ -17,27 +22,27 @@ @fixture(scope="function") -def dataset_with_data_outside_iqr_high_outlier(dataset): +def dataset_with_data_outside_iqr_high_outlier(dataset: "DataSet") -> "DataSet": return dataset_with_outliers_generator( dataset, data_offset=2, low_outlier=-2, high_outlier=3 ) @fixture(scope="function") -def dataset_with_data_outside_iqr_low_outlier(dataset): +def dataset_with_data_outside_iqr_low_outlier(dataset: "DataSet") -> "DataSet": return dataset_with_outliers_generator( dataset, data_offset=2, low_outlier=-2, high_outlier=3 ) @fixture(scope="function") -def dataset_with_outliers(dataset): +def dataset_with_outliers(dataset: "DataSet") -> "DataSet": return dataset_with_outliers_generator( dataset, low_outlier=-3, high_outlier=3, background_noise=False ) -def test_extend(dataset_with_outliers) -> None: +def test_extend(dataset_with_outliers: "DataSet") -> None: # this one should clipp the upper values run_id = dataset_with_outliers.run_id _, cb = plot_by_id(run_id, auto_color_scale=False) @@ -52,7 +57,7 @@ def test_extend(dataset_with_outliers) -> None: plt.close() -def test_defaults(dataset_with_outliers) -> None: +def test_defaults(dataset_with_outliers: "DataSet") -> None: run_id = dataset_with_outliers.run_id _, cb = plot_by_id(run_id) diff --git a/tests/test_snapshot.py b/tests/test_snapshot.py index 1b8c70319192..68ceef1428cb 100644 --- a/tests/test_snapshot.py +++ b/tests/test_snapshot.py @@ -19,7 +19,7 @@ ], ) def test_snapshot_skip_params_update( - request: FixtureRequest, params, params_to_skip + request: FixtureRequest, params: list[str], params_to_skip: list[str] ) -> None: """ Test that params_to_skip_update works as expected, in particular that only @@ -63,7 +63,7 @@ def test_snapshot_skip_params_update( ], ) def test_snapshot_exclude_params( - request: FixtureRequest, params, params_to_exclude + request: FixtureRequest, params: list[str], params_to_exclude: list[str] ) -> None: """ Test that params_to_exclude works as expected, in particular that only diff --git a/tests/test_station.py b/tests/test_station.py index 4607199ebd1b..0c633b325f08 100644 --- a/tests/test_station.py +++ b/tests/test_station.py @@ -6,6 +6,7 @@ from contextlib import contextmanager from io import StringIO from pathlib import Path +from typing import TYPE_CHECKING import pytest from ruamel.yaml import YAML @@ -25,9 +26,12 @@ from .common import DummyComponent +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(autouse=True) -def set_default_station_to_none_automatically(): +def set_default_station_to_none_automatically() -> "Generator[None, None, None]": """Makes sure that after startup and teardown there is no default station""" Station.default = None yield @@ -35,7 +39,7 @@ def set_default_station_to_none_automatically(): @pytest.fixture(autouse=True) -def close_all_instruments(): +def close_all_instruments() -> "Generator[None, None, None]": """Makes sure that after startup and teardown all instruments are closed""" Instrument.close_all() yield @@ -43,7 +47,7 @@ def close_all_instruments(): @pytest.fixture(autouse=True) -def treat_validation_warning_as_error(): +def treat_validation_warning_as_error() -> "Generator[None, None, None]": warnings.simplefilter("error", ValidationWarning) yield warnings.simplefilter("default", ValidationWarning) @@ -252,7 +256,7 @@ def test_update_config_schema() -> None: @contextmanager -def config_file_context(file_content): +def config_file_context(file_content: str) -> "Generator[str, None, None]": with tempfile.TemporaryDirectory() as tmpdirname: filename = Path(tmpdirname, "station_config.yaml") with filename.open("w") as f: @@ -261,7 +265,9 @@ def config_file_context(file_content): @contextmanager -def config_files_context(file_content1, file_content2): +def config_files_context( + file_content1: str, file_content2: str +) -> "Generator[list[str], None, None]": with tempfile.TemporaryDirectory() as tmpdirname: filename1 = Path(tmpdirname, "station_config1.yaml") with filename1.open("w") as f: @@ -273,7 +279,7 @@ def config_files_context(file_content1, file_content2): @pytest.fixture(name="example_station_config") -def _make_example_station_config(): +def _make_example_station_config() -> "Generator[str, None, None]": """ Returns path to temp yaml file with station config. """ @@ -301,7 +307,7 @@ def _make_example_station_config(): yield filename -def test_dynamic_reload_of_file(example_station_config) -> None: +def test_dynamic_reload_of_file(example_station_config: str) -> None: st = Station(config_file=example_station_config) mock_dac = st.load_instrument("mock_dac") assert "ch1" in mock_dac.parameters @@ -325,12 +331,12 @@ def station_config_has_been_loaded(st: Station) -> bool: @pytest.fixture(name="example_station") -def _make_example_station(example_station_config): +def _make_example_station(example_station_config: str) -> Station: return Station(config_file=example_station_config) # instrument loading related tests -def test_station_config_path_resolution(example_station_config) -> None: +def test_station_config_path_resolution(example_station_config: str) -> None: config = qcodes.config["station"] # There is no default yaml file present that defines a station @@ -386,11 +392,13 @@ def test_station_config_path_resolution(example_station_config) -> None: assert station_config_has_been_loaded(Station(config_file=str(path))) -def test_station_configuration_is_a_component_of_station(example_station) -> None: +def test_station_configuration_is_a_component_of_station( + example_station: Station, +) -> None: assert station_config_has_been_loaded(example_station) -def test_station_config_can_be_loaded_from_snapshot(example_station) -> None: +def test_station_config_can_be_loaded_from_snapshot(example_station: Station) -> None: assert station_config_has_been_loaded(example_station) # ensure that we can correctly dump config which is a subclass of UserDict configdump = json.dumps(example_station.config, cls=NumpyJSONEncoder) @@ -410,7 +418,7 @@ def test_station_config_can_be_loaded_from_snapshot(example_station) -> None: @pytest.fixture -def simple_mock_station(): +def simple_mock_station() -> "Generator[Station, None, None]": yield station_from_config_str( """ instruments: @@ -420,7 +428,7 @@ def simple_mock_station(): ) -def test_simple_mock_config(simple_mock_station) -> None: +def test_simple_mock_config(simple_mock_station: Station) -> None: st = simple_mock_station assert station_config_has_been_loaded(st) assert hasattr(st, "load_mock") @@ -429,10 +437,11 @@ def test_simple_mock_config(simple_mock_station) -> None: mock_snapshot["type"] == "qcodes.instrument_drivers.mock_instruments.DummyInstrument" ) + assert st.config is not None assert "mock" in st.config["instruments"] -def test_simple_mock_load_mock(simple_mock_station) -> None: +def test_simple_mock_load_mock(simple_mock_station: Station) -> None: st = simple_mock_station mock = st.load_mock() assert isinstance(mock, DummyInstrument) @@ -440,7 +449,7 @@ def test_simple_mock_load_mock(simple_mock_station) -> None: assert st.components["mock"] is mock -def test_simple_mock_load_instrument(simple_mock_station) -> None: +def test_simple_mock_load_instrument(simple_mock_station: Station) -> None: st = simple_mock_station mock = st.load_instrument("mock") assert isinstance(mock, DummyInstrument) @@ -551,7 +560,7 @@ def test_init_parameters() -> None: st.load_instrument("lakeshore") -def test_name_init_kwarg(simple_mock_station) -> None: +def test_name_init_kwarg(simple_mock_station: Station) -> None: # special case of `name` as kwarg st = simple_mock_station mock = st.load_instrument("mock", name="test") @@ -577,7 +586,7 @@ def test_name_specified_in_init_in_yaml_is_used() -> None: class InstrumentWithNameAsNotFirstArgument(Instrument): - def __init__(self, first_arg, name): + def __init__(self, first_arg: int, name: str) -> None: super().__init__(name) self._first_arg = first_arg @@ -998,14 +1007,14 @@ def test_nested_config_scalar_submodule_value_runtime_error() -> None: st.load_instrument("mock") -def test_monitor_not_loaded_by_default(example_station_config) -> None: +def test_monitor_not_loaded_by_default(example_station_config: str) -> None: st = Station(config_file=example_station_config) st.load_instrument("mock_dac") assert Monitor.running is None def test_monitor_loaded_if_specified( - example_station_config, request: pytest.FixtureRequest + example_station_config: str, request: pytest.FixtureRequest ) -> None: st = Station(config_file=example_station_config, use_monitor=True) st.load_instrument("mock_dac") @@ -1016,7 +1025,7 @@ def test_monitor_loaded_if_specified( def test_monitor_loaded_by_default_if_in_config( - example_station_config, request: pytest.FixtureRequest + example_station_config: str, request: pytest.FixtureRequest ) -> None: qcodes.config["station"]["use_monitor"] = True st = Station(config_file=example_station_config) @@ -1027,7 +1036,7 @@ def test_monitor_loaded_by_default_if_in_config( assert Monitor.running._parameters[0].name == "ch1" -def test_monitor_not_loaded_if_specified(example_station_config) -> None: +def test_monitor_not_loaded_if_specified(example_station_config: str) -> None: st = Station(config_file=example_station_config, use_monitor=False) st.load_instrument("mock_dac") assert Monitor.running is None @@ -1070,7 +1079,7 @@ def test_config_validation_comprehensive_config() -> None: def test_load_all_instruments_raises_on_both_only_names_and_only_types_passed( - example_station, + example_station: Station, ) -> None: with pytest.raises( ValueError, @@ -1081,7 +1090,7 @@ def test_load_all_instruments_raises_on_both_only_names_and_only_types_passed( example_station.load_all_instruments(only_names=(), only_types=()) -def test_load_all_instruments_no_args(example_station) -> None: +def test_load_all_instruments_no_args(example_station: Station) -> None: all_instruments_in_config = {"lakeshore", "mock_dac", "mock_dac2"} loaded_instruments = example_station.load_all_instruments() @@ -1093,7 +1102,7 @@ def test_load_all_instruments_no_args(example_station) -> None: assert Instrument.exist(instrument) -def test_load_all_instruments_only_types(example_station) -> None: +def test_load_all_instruments_only_types(example_station: Station) -> None: all_dummy_instruments = {"mock_dac", "mock_dac2"} loaded_instruments = example_station.load_all_instruments( @@ -1106,6 +1115,7 @@ def test_load_all_instruments_only_types(example_station) -> None: assert instrument in example_station.components assert Instrument.exist(instrument) + assert example_station.config is not None other_instruments = ( set(example_station.config["instruments"].keys()) - all_dummy_instruments ) @@ -1115,7 +1125,7 @@ def test_load_all_instruments_only_types(example_station) -> None: assert not Instrument.exist(instrument) -def test_load_all_instruments_only_names(example_station) -> None: +def test_load_all_instruments_only_names(example_station: Station) -> None: instruments_to_load = {"lakeshore", "mock_dac"} loaded_instruments = example_station.load_all_instruments( @@ -1128,6 +1138,7 @@ def test_load_all_instruments_only_names(example_station) -> None: assert instrument in example_station.components assert Instrument.exist(instrument) + assert example_station.config is not None other_instruments = ( set(example_station.config["instruments"].keys()) - instruments_to_load ) @@ -1140,7 +1151,7 @@ def test_load_all_instruments_only_names(example_station) -> None: def test_load_all_instruments_without_config_raises() -> None: station = Station() with pytest.raises(ValueError, match="Station has no config"): - station.load_all_instruments() # type: ignore[call-overload] + station.load_all_instruments() def test_station_config_created_with_multiple_config_files() -> None: diff --git a/tests/test_sweep_values.py b/tests/test_sweep_values.py index a7b4a517852a..d01002af4499 100644 --- a/tests/test_sweep_values.py +++ b/tests/test_sweep_values.py @@ -1,29 +1,34 @@ +from typing import TYPE_CHECKING + import pytest from qcodes.parameters import Parameter from qcodes.parameters.sweep_values import SweepValues from qcodes.validators import Numbers +if TYPE_CHECKING: + from collections.abc import Generator + @pytest.fixture(name="c0") -def _make_c0(): +def _make_c0() -> "Generator[Parameter, None, None]": c0 = Parameter("c0", vals=Numbers(-10, 10), get_cmd=None, set_cmd=None) yield c0 @pytest.fixture(name="c1") -def _make_c1(): +def _make_c1() -> "Generator[Parameter, None, None]": c1 = Parameter("c1", get_cmd=None, set_cmd=None) yield c1 @pytest.fixture(name="c2") -def _make_c2(): +def _make_c2() -> "Generator[Parameter, None, None]": c2 = Parameter("c2", get_cmd=lambda: 42) yield c2 -def test_errors(c0, c1, c2) -> None: +def test_errors(c0: Parameter, c1: Parameter, c2: Parameter) -> None: # only complete 3-part slices are valid with pytest.raises(TypeError): c0[1:2] # For Int params this could be defined as step=1 @@ -56,20 +61,21 @@ def test_errors(c0, c1, c2) -> None: # improper use of extend with pytest.raises(TypeError): - c0[0.1].extend(5) + c0[0.1].extend(5) # pyright: ignore[reportArgumentType] # SweepValue object has no getter, even if the parameter does with pytest.raises(AttributeError): - _ = c0[0.1].get + _ = c0[0.1].get # pyright: ignore[reportAttributeAccessIssue] -def test_valid(c0) -> None: +def test_valid(c0: Parameter) -> None: c0_sv = c0[1] # setter gets mapped assert c0_sv.set == c0.set # normal sequence operations access values assert list(c0_sv) == [1] - assert c0_sv[0] == 1 + # TODO: SweepFixedValues.__getitem__ only accepts slice but int keys work + assert c0_sv[0] == 1 # pyright: ignore[reportArgumentType] assert 1 in c0_sv assert 2 not in c0_sv @@ -98,7 +104,8 @@ def test_valid(c0) -> None: # in-place and copying reverse c0_sv.reverse() - c0_sv5 = reversed(c0_sv) + # TODO: SweepFixedValues.__reversed__ returns Self, which is not an Iterator + c0_sv5 = reversed(c0_sv) # pyright: ignore[reportCallIssue, reportArgumentType] assert list(c0_sv) == [1.7, 1.6, 1.5, 1] assert list(c0_sv5) == [1, 1.5, 1.6, 1.7] @@ -117,7 +124,7 @@ def test_base() -> None: iter(SweepValues(p)) -def test_snapshot(c0) -> None: +def test_snapshot(c0: Parameter) -> None: assert c0[0].snapshot() == {"parameter": c0.snapshot(), "values": [{"item": 0}]} assert c0[0:5:0.3].snapshot()["values"] == [ # type: ignore[misc] @@ -143,7 +150,7 @@ def test_snapshot(c0) -> None: ] -def test_repr(c0) -> None: +def test_repr(c0: Parameter) -> None: sv = c0[0] assert repr(sv) == ( f"" diff --git a/tests/test_threading.py b/tests/test_threading.py index 95175a549a14..506d1ee7f756 100644 --- a/tests/test_threading.py +++ b/tests/test_threading.py @@ -5,7 +5,7 @@ import threading import time from collections import defaultdict -from typing import Any +from typing import TYPE_CHECKING, Any import pytest @@ -14,6 +14,9 @@ from qcodes.parameters import Parameter, ParamRawDataType from qcodes.utils.threading_utils import RespondingThread, thread_map +if TYPE_CHECKING: + from collections.abc import Generator + class ParameterWithThreadKnowledge(Parameter): def __init__(self, *args: Any, **kwargs: Any) -> None: @@ -25,7 +28,7 @@ def get_raw(self) -> ParamRawDataType: @pytest.fixture(name="dummy_1", scope="function") -def _dummy_dac1(): +def _dummy_dac1() -> "Generator[DummyInstrument, None, None]": instrument = DummyInstrument(name="dummy_1", gates=["ch1"]) instrument.add_parameter( @@ -43,7 +46,7 @@ def _dummy_dac1(): @pytest.fixture(name="dummy_2", scope="function") -def _dummy_dac2(): +def _dummy_dac2() -> "Generator[DummyInstrument, None, None]": instrument = DummyInstrument(name="dummy_2", gates=["ch1"]) instrument.add_parameter( @@ -60,7 +63,9 @@ def _dummy_dac2(): instrument.close() -def test_call_params_threaded(dummy_1, dummy_2) -> None: +def test_call_params_threaded( + dummy_1: DummyInstrument, dummy_2: DummyInstrument +) -> None: params_output = call_params_threaded( (dummy_1.voltage_1, dummy_1.voltage_2, dummy_2.voltage_1, dummy_2.voltage_2) ) @@ -79,7 +84,9 @@ def test_call_params_threaded(dummy_1, dummy_2) -> None: } == expected_params_per_thread -def test_thread_pool_params_caller(dummy_1, dummy_2) -> None: +def test_thread_pool_params_caller( + dummy_1: DummyInstrument, dummy_2: DummyInstrument +) -> None: params = ( dummy_1.voltage_1, dummy_1.voltage_2, diff --git a/tests/test_visa.py b/tests/test_visa.py index c3f42b56f8fe..0466891ce6b2 100644 --- a/tests/test_visa.py +++ b/tests/test_visa.py @@ -17,13 +17,21 @@ if TYPE_CHECKING: from collections.abc import Generator + from typing import Unpack from pytest_mock import MockerFixture + from qcodes.instrument import VisaInstrumentKWArgs + class MockVisa(VisaInstrument): - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) + def __init__( + self, + name: str, + address: str | None = None, + **kwargs: "Unpack[VisaInstrumentKWArgs]", + ) -> None: + super().__init__(name, address, **kwargs) self.state = self.add_parameter( "state", get_cmd="STAT?", @@ -58,15 +66,15 @@ class MockVisaHandle(pyvisa.resources.MessageBasedResource): resource_name: str = "MOCK::INSTR" # pyright: ignore[reportIncompatibleVariableOverride] - def __init__(self): + def __init__(self) -> None: self.state = 0 self.closed = False self._session = None # required for session property - def clear(self): + def clear(self) -> None: self.state = 0 - def close(self): + def close(self) -> None: # make it an error to ask or write after close self.closed = True @@ -89,7 +97,7 @@ def write( return len(message) - def ask(self, cmd): + def ask(self, cmd: str) -> float: if self.closed: raise RuntimeError("Trying to ask a closed instrument") if self.state > 10: @@ -107,7 +115,7 @@ def set_visa_attribute( setattr(self, str(name), state) return pyvisa.constants.StatusCode.success - def __del__(self): + def __del__(self) -> None: pass @@ -199,7 +207,7 @@ def test_ask_write_local(mock_visa: MockVisa) -> None: def test_visa_backend(mocker: "MockerFixture", request: FixtureRequest) -> None: rm_mock = mocker.patch("qcodes.instrument.visa.pyvisa.ResourceManager") - address_opened = [None] + address_opened: list[str | None] = [None] class MockBackendVisaInstrument(VisaInstrument): _visa_handle = MockVisaHandle() @@ -209,7 +217,7 @@ def visabackend(self) -> str: return "sim" class MockRM: - def open_resource(self, address): + def open_resource(self, address: str) -> MockVisaHandle: address_opened[0] = address return MockVisaHandle() diff --git a/tests/utils/test_isfunction.py b/tests/utils/test_isfunction.py index 81bc0268ab81..4088c7986195 100644 --- a/tests/utils/test_isfunction.py +++ b/tests/utils/test_isfunction.py @@ -51,14 +51,14 @@ def f0(one_arg: int) -> int: def test_function_varargs() -> None: - def f(*args) -> None: + def f(*args: object) -> None: return None assert is_function(f, 0) assert is_function(f, 1) assert is_function(f, 100) - def g(a, b=1, *args) -> None: + def g(a: object, b: object = 1, *args: object) -> None: return None assert not is_function(g, 0) diff --git a/tests/utils/test_partial_with_docstring.py b/tests/utils/test_partial_with_docstring.py index c7159d91b566..4e39ec3087e0 100644 --- a/tests/utils/test_partial_with_docstring.py +++ b/tests/utils/test_partial_with_docstring.py @@ -2,7 +2,7 @@ def test_partial_with_docstring() -> None: - def f(): + def f() -> None: pass docstring = "some docstring" @@ -18,7 +18,7 @@ def test_partial_with_docstring_pass_args() -> None: functools.partial """ - def f(a: int, b: int): + def f(a: int, b: int) -> int: return a + b docstring = "some docstring" @@ -29,7 +29,7 @@ def f(a: int, b: int): def test_partial_with_docstring_returns_value() -> None: - def f(a: int, b: int): + def f(a: int, b: int) -> int: return a + b docstring = "some docstring" diff --git a/tests/validators/test_literal.py b/tests/validators/test_literal.py index c549e8003afd..cb625d1d1228 100644 --- a/tests/validators/test_literal.py +++ b/tests/validators/test_literal.py @@ -41,7 +41,7 @@ def test_valid_values() -> None: assert a123_val.valid_values == (1, 2, 3) -def test_missing_generic_arg_raises_at_runtime(): +def test_missing_generic_arg_raises_at_runtime() -> None: wrong_validator = LiteralValidator() with pytest.raises(