diff --git a/pyproject.toml b/pyproject.toml index fe1b35963ed..2a2f3f4ec14 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -227,7 +227,7 @@ filterwarnings = [ # I isort # ISC flake8-implicit-str-concat # TID253 banned-module-level-imports -select = ["E", "F", "PT025", "UP", "RUF200", "I", "G", "ISC", "TID253"] +select = ["E", "F", "PT025", "UP", "RUF010", "RUF012", "RUF200", "I", "G", "ISC", "TID253"] # darker will fix this as code is # reformatted when it is changed. # We have a lot of use of f strings in log messages diff --git a/src/qcodes/configuration/config.py b/src/qcodes/configuration/config.py index a5d2f362b97..62b220c143b 100644 --- a/src/qcodes/configuration/config.py +++ b/src/qcodes/configuration/config.py @@ -48,7 +48,6 @@ class Config: """Filename of default config""" current_config_path = default_file_name """Path of the last loaded config file""" - _loaded_config_files = [default_file_name] # get abs path of schema file schema_default_file_name = str(files(_PARENT_MODULE) / schema_file_name) @@ -84,15 +83,16 @@ class Config: defaults_schema: DotDict """The default schema""" - _diff_config: dict[str, Any] = {} - _diff_schema: dict[str, Any] = {} - def __init__(self, path: str | None = None) -> None: """ Args: path: Optional path to directory containing a `qcodesrc.json` config file """ + self._loaded_config_files = [self.default_file_name] + self._diff_config: dict[str, Any] = {} + self._diff_schema: dict[str, Any] = {} + self.config_file_path = path self.defaults, self.defaults_schema = self.load_default() self.update_config() diff --git a/src/qcodes/dataset/descriptions/param_spec.py b/src/qcodes/dataset/descriptions/param_spec.py index 8567910be09..0e8cece5255 100644 --- a/src/qcodes/dataset/descriptions/param_spec.py +++ b/src/qcodes/dataset/descriptions/param_spec.py @@ -2,7 +2,7 @@ from collections.abc import Sequence from copy import deepcopy -from typing import Any +from typing import Any, ClassVar from typing_extensions import TypedDict @@ -20,8 +20,7 @@ class ParamSpecDict(ParamSpecBaseDict): class ParamSpecBase: - - allowed_types = ['array', 'numeric', 'text', 'complex'] + allowed_types: ClassVar[list[str]] = ["array", "numeric", "text", "complex"] def __init__( self, diff --git a/src/qcodes/dataset/measurements.py b/src/qcodes/dataset/measurements.py index 1e81be2d3c8..96f1043b04d 100644 --- a/src/qcodes/dataset/measurements.py +++ b/src/qcodes/dataset/measurements.py @@ -273,7 +273,7 @@ def _unpack_partial_result( else: err_msg = ( "Can not add result for parameter " - f"{str(param)} or {str_or_register_name(param)}," + f"{param!s} or {str_or_register_name(param)}," "no such parameter registered " "with this measurement." ) diff --git a/src/qcodes/instrument/channel.py b/src/qcodes/instrument/channel.py index b3f8da645e9..3a55b2d218f 100644 --- a/src/qcodes/instrument/channel.py +++ b/src/qcodes/instrument/channel.py @@ -791,7 +791,7 @@ def validate(self, value: InstrumentChannel, context: str = '') -> None: """ if value not in self._channel_list: raise ValueError( - f"{repr(value)} is not part of the expected channel list; {context}" + f"{value!r} is not part of the expected channel list; {context}" ) diff --git a/src/qcodes/instrument/instrument_base.py b/src/qcodes/instrument/instrument_base.py index 62d887f32a2..fe94dda7456 100644 --- a/src/qcodes/instrument/instrument_base.py +++ b/src/qcodes/instrument/instrument_base.py @@ -5,7 +5,7 @@ import logging import warnings from collections.abc import Callable, Mapping, Sequence -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, ClassVar import numpy as np @@ -578,7 +578,7 @@ def _is_abstract(self) -> bool: # instrument.get('someparam') === instrument['someparam'].get() # # etc... # # - delegate_attr_dicts = ["parameters", "functions", "submodules"] + delegate_attr_dicts: ClassVar[list[str]] = ["parameters", "functions", "submodules"] def __getitem__(self, key: str) -> Callable[..., Any] | Parameter: """Delegate instrument['name'] to parameter or function 'name'.""" diff --git a/src/qcodes/instrument/ip_to_visa.py b/src/qcodes/instrument/ip_to_visa.py index bf74c41c567..ab0b0d500e2 100644 --- a/src/qcodes/instrument/ip_to_visa.py +++ b/src/qcodes/instrument/ip_to_visa.py @@ -74,7 +74,7 @@ def __init__( traversable_handle = files("qcodes.instrument.sims") / pyvisa_sim_file with as_file(traversable_handle) as sim_visalib_path: - self.visalib = f"{str(sim_visalib_path)}@sim" + self.visalib = f"{sim_visalib_path!s}@sim" self.set_address(address=address) if device_clear: diff --git a/src/qcodes/instrument/mockers/ami430.py b/src/qcodes/instrument/mockers/ami430.py index 49e6072c171..b872f7bd10c 100644 --- a/src/qcodes/instrument/mockers/ami430.py +++ b/src/qcodes/instrument/mockers/ami430.py @@ -1,10 +1,11 @@ import re import time from datetime import datetime +from typing import ClassVar class MockAMI430: - states = { + states: ClassVar[dict[str, str]] = { "RAMPING to target field/current": "1", "HOLDING at the target field/current": "2", "PAUSED": "3", @@ -17,17 +18,11 @@ class MockAMI430: "Cooling persistent switch": "10" } - field_units = { - "tesla": "1", - "kilogauss": "0" - } + field_units: ClassVar[dict[str, str]] = {"tesla": "1", "kilogauss": "0"} - ramp_rate_units = { - "A/s": "0", - "A/min": "1" - } + ramp_rate_units: ClassVar[dict[str, str]] = {"A/s": "0", "A/min": "1"} - quench_state = {False: "0", True: "1"} + quench_state: ClassVar[dict[bool, str]] = {False: "0", True: "1"} def __init__(self, name): diff --git a/src/qcodes/instrument/mockers/simulated_ats_api.py b/src/qcodes/instrument/mockers/simulated_ats_api.py index 2dfe6b9769a..65dc9cc56d1 100644 --- a/src/qcodes/instrument/mockers/simulated_ats_api.py +++ b/src/qcodes/instrument/mockers/simulated_ats_api.py @@ -8,7 +8,7 @@ import ctypes -from typing import Any, Callable, Optional +from typing import Any, Callable, ClassVar, Optional import numpy as np @@ -23,7 +23,7 @@ class SimulatedATS9360API(AlazarATSAPI): - registers = { + registers: ClassVar[dict[int, int]] = { 8: 70254688, 58: int(np.uint32(1 << 26)) # Trigger hold off } diff --git a/src/qcodes/instrument/visa.py b/src/qcodes/instrument/visa.py index bea9f58f485..23bf2ad96bf 100644 --- a/src/qcodes/instrument/visa.py +++ b/src/qcodes/instrument/visa.py @@ -111,7 +111,7 @@ def __init__( "could not be found. Trying to load " f"file {pyvisa_sim_file} from module: {module}" ) - visalib = f"{str(sim_visalib_path)}@sim" + visalib = f"{sim_visalib_path!s}@sim" ( visa_handle, visabackend, diff --git a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py index 14d2419a378..89fcbd2ac55 100644 --- a/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py +++ b/src/qcodes/instrument_drivers/AimTTi/_AimTTi_PL_P.py @@ -1,4 +1,4 @@ -from typing import Any, Optional +from typing import Any, ClassVar, Optional from qcodes import validators as vals from qcodes.instrument import ChannelList, Instrument, InstrumentChannel, VisaInstrument @@ -214,7 +214,7 @@ class AimTTi(VisaInstrument): Tested with Aim TTi PL601-P equipped with a single output channel. """ - _numOutputChannels = { + _numOutputChannels: ClassVar[dict[str, int]] = { "PL068-P": 1, "PL155-P": 1, "PL303-P": 1, diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS9360.py b/src/qcodes/instrument_drivers/AlazarTech/ATS9360.py index 8078daf251d..e65b3c746c3 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS9360.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS9360.py @@ -318,10 +318,12 @@ def __init__(self, name: str, get_cmd=self._get_trigger_holdoff, set_cmd=self._set_trigger_holdoff) - model = self.get_idn()['model'] - if model != 'ATS9360': - raise Exception(f"The Alazar board kind is not 'ATS9360'," - f" found '{str(model)}' instead.") + model = self.get_idn()["model"] + if model != "ATS9360": + raise Exception( + f"The Alazar board kind is not 'ATS9360'," + f" found '{model!s}' instead." + ) def _get_trigger_holdoff(self) -> bool: fwversion = self.get_idn()['firmware'] diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS9373.py b/src/qcodes/instrument_drivers/AlazarTech/ATS9373.py index 7eab83750d2..3cd93ca1094 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS9373.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS9373.py @@ -334,10 +334,12 @@ def __init__(self, name: str, get_cmd=self._get_trigger_holdoff, set_cmd=self._set_trigger_holdoff) - model = self.get_idn()['model'] - if model != 'ATS9373': - raise Exception(f"The Alazar board kind is not 'ATS9373'," - f" found '{str(model)}' instead.") + model = self.get_idn()["model"] + if model != "ATS9373": + raise Exception( + f"The Alazar board kind is not 'ATS9373'," + f" found '{model!s}' instead." + ) def _get_trigger_holdoff(self) -> bool: fwversion = self.get_idn()["firmware"] diff --git a/src/qcodes/instrument_drivers/AlazarTech/ATS9870.py b/src/qcodes/instrument_drivers/AlazarTech/ATS9870.py index a8414fa7d87..1bc1d1dc2cb 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ATS9870.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ATS9870.py @@ -301,10 +301,12 @@ def __init__(self, name: str, initial_value=1000, vals=validators.Ints(min_value=0)) - model = self.get_idn()['model'] - if model != 'ATS9870': - raise Exception(f"The Alazar board kind is not 'ATS9870'," - f" found '{str(model)}' instead.") + model = self.get_idn()["model"] + if model != "ATS9870": + raise Exception( + f"The Alazar board kind is not 'ATS9870'," + f" found '{model!s}' instead." + ) class AlazarTech_ATS9870(AlazarTechATS9870): diff --git a/src/qcodes/instrument_drivers/AlazarTech/ats_api.py b/src/qcodes/instrument_drivers/AlazarTech/ats_api.py index 8c1e7ab131e..bf141a3d421 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/ats_api.py +++ b/src/qcodes/instrument_drivers/AlazarTech/ats_api.py @@ -7,7 +7,7 @@ import ctypes from ctypes import POINTER -from typing import Any, Union +from typing import Any, ClassVar, Union # `ParameterBase` is needed because users may pass instrument parameters # that originate from `Instrument.parameters` dictionary which is typed @@ -51,7 +51,7 @@ class AlazarATSAPI(WrappedDll): ## ACTUAL DLL API FUNCTIONS ## - signatures: dict[str, Signature] = {} + signatures: ClassVar[dict[str, Signature]] = {} def set_trigger_time_out(self, handle: int, diff --git a/src/qcodes/instrument_drivers/AlazarTech/dll_wrapper.py b/src/qcodes/instrument_drivers/AlazarTech/dll_wrapper.py index 78933940ea8..8d56135d4bf 100644 --- a/src/qcodes/instrument_drivers/AlazarTech/dll_wrapper.py +++ b/src/qcodes/instrument_drivers/AlazarTech/dll_wrapper.py @@ -14,7 +14,7 @@ from collections.abc import Callable, Sequence from functools import partial from threading import Lock -from typing import Any, NamedTuple, NewType, TypeVar +from typing import Any, ClassVar, NamedTuple, NewType, TypeVar from weakref import WeakValueDictionary from qcodes.parameters import ParameterBase @@ -144,7 +144,7 @@ class WrappedDll(metaclass=DllWrapperMeta): dll_path: Path to the DLL library to load and wrap """ - signatures: dict[str, Signature] = {} + signatures: ClassVar[dict[str, Signature]] = {} """ Signatures for loaded DLL functions; It is to be filled with :class:`Signature` instances for the DLL diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py index d43271807df..6b041762209 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_2450.py @@ -1,5 +1,5 @@ from types import TracebackType -from typing import Any, Optional, Union, cast +from typing import Any, ClassVar, Optional, Union, cast import numpy as np from typing_extensions import TypedDict @@ -46,9 +46,9 @@ class Keithley2450Buffer(InstrumentChannel): Treat the reading buffer as a submodule, similar to Sense and Source """ - default_buffer = {"defbuffer1", "defbuffer2"} + default_buffer: ClassVar[set[str]] = {"defbuffer1", "defbuffer2"} - buffer_elements = { + buffer_elements: ClassVar[dict[str, str]] = { "date": "DATE", "measurement_formatted": "FORMatted", "fractional_seconds": "FRACtional", @@ -202,6 +202,11 @@ def delete(self) -> None: self.write(f":TRACe:DELete '{self.buffer_name}'") +class _FunctionMode(TypedDict): + name: str + unit: str + range_vals: Numbers + class Keithley2450Sense(InstrumentChannel): """ The sense module of the Keithley 2450 SMU. @@ -217,7 +222,7 @@ class Keithley2450Sense(InstrumentChannel): which returns the proper submodule for any given function mode """ - function_modes = { + function_modes: ClassVar[dict[str, _FunctionMode]] = { "current": {"name": '"CURR:DC"', "unit": "A", "range_vals": Numbers(10e-9, 1)}, "resistance": { "name": '"RES"', @@ -372,7 +377,7 @@ class Keithley2450Source(InstrumentChannel): which returns the proper submodule for any given function mode """ - function_modes = { + function_modes: ClassVar[dict[str, _FunctionMode]] = { "current": {"name": "CURR", "unit": "A", "range_vals": Numbers(-1, 1)}, "voltage": {"name": "VOLT", "unit": "V", "range_vals": Numbers(-200, 200)}, } diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py index 55e35a6c479..19944fa2e43 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_7510.py @@ -1,6 +1,6 @@ from collections.abc import Sequence from types import TracebackType -from typing import Any, Optional, Union, cast +from typing import Any, ClassVar, Optional, TypedDict, Union, cast import numpy as np @@ -79,9 +79,9 @@ class Keithley7510Buffer(InstrumentChannel): Treat the reading buffer as a submodule, similar to Sense. """ - default_buffer = {"defbuffer1", "defbuffer2"} + default_buffer: ClassVar[set[str]] = {"defbuffer1", "defbuffer2"} - buffer_elements = { + buffer_elements: ClassVar[dict[str, str]] = { "date": "DATE", "measurement_formatted": "FORMatted", "fractional_seconds": "FRACtional", @@ -389,6 +389,12 @@ def delete(self) -> None: self.write(f":TRACe:DELete '{self.short_name}'") +class _FunctionMode(TypedDict): + name: str + unit: str + range_vals: Optional[Numbers] + + class Keithley7510Sense(InstrumentChannel): """ The sense module of the Keithley 7510 DMM, based on the sense module of @@ -411,7 +417,7 @@ class Keithley7510Sense(InstrumentChannel): which returns the proper submodule for any given function mode. """ - function_modes = { + function_modes: ClassVar[dict[str, _FunctionMode]] = { "voltage": { "name": '"VOLT:DC"', "unit": "V", @@ -589,7 +595,7 @@ class Keithley7510DigitizeSense(InstrumentChannel): The Digitize sense module of the Keithley 7510 DMM. """ - function_modes: dict[str, dict[str, Any]] = { + function_modes: ClassVar[dict[str, _FunctionMode]] = { "None": {"name": '"NONE"', "unit": "", "range_vals": None}, "voltage": { "name": '"VOLT"', diff --git a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py index e8445da0988..8fb4a072e08 100644 --- a/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py +++ b/src/qcodes/instrument_drivers/Keithley/Keithley_s46.py @@ -3,7 +3,7 @@ """ import re from itertools import product -from typing import Any, Optional +from typing import Any, ClassVar, Optional from qcodes.instrument import Instrument, VisaInstrument from qcodes.parameters import Parameter, ParamRawDataType @@ -128,13 +128,13 @@ class KeithleyS46(VisaInstrument): # Make a dictionary where keys are channel aliases (e.g. 'A1', 'B3', etc) # and values are corresponding channel numbers. - channel_numbers: dict[str, int] = { + channel_numbers: ClassVar[dict[str, int]] = { f"{a}{b}": count + 1 for count, (a, b) in enumerate(product(["A", "B", "C", "D"], range(1, 7))) } channel_numbers.update({f"R{i}": i + 24 for i in range(1, 9)}) # Make a reverse dict for efficient alias lookup given a channel number - aliases = {v: k for k, v in channel_numbers.items()} + aliases: ClassVar[dict[int, str]] = {v: k for k, v in channel_numbers.items()} def __init__(self, name: str, address: str, **kwargs: Any): diff --git a/src/qcodes/instrument_drivers/Keysight/Infiniium.py b/src/qcodes/instrument_drivers/Keysight/Infiniium.py index de588e11881..2a1afc5ae75 100644 --- a/src/qcodes/instrument_drivers/Keysight/Infiniium.py +++ b/src/qcodes/instrument_drivers/Keysight/Infiniium.py @@ -1,6 +1,6 @@ import re from collections.abc import Sequence -from typing import Any, Literal, Optional, Union +from typing import Any, ClassVar, Literal, Optional, Union import numpy as np from pyvisa import VisaIOError @@ -84,7 +84,14 @@ class DSOTraceParam(ParameterWithSetpoints): Trace parameter for the Infiniium series DSO """ - UNIT_MAP = {0: "UNKNOWN", 1: "V", 2: "s", 3: "''", 4: "A", 5: "dB"} + UNIT_MAP: ClassVar[dict[int, str]] = { + 0: "UNKNOWN", + 1: "V", + 2: "s", + 3: "''", + 4: "A", + 5: "dB", + } def __init__( self, diff --git a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py index e29164721c7..4c0bc4f5eb6 100644 --- a/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py +++ b/src/qcodes/instrument_drivers/Keysight/keysightb1500/KeysightB1500_sampling_measurement.py @@ -100,10 +100,11 @@ def compliance(self) -> list[int]: if total_count == normal_count: print('All measurements are normal') else: - indices = [i for i, x in enumerate(data.status) - if x == "C" or x == "T"] - warnings.warn(f'{str(exception_count)} measurements were ' - f'out of compliance at {str(indices)}') + indices = [i for i, x in enumerate(data.status) if x == "C" or x == "T"] + warnings.warn( + f"{exception_count!s} measurements were " + f"out of compliance at {indices!s}" + ) compliance_list = [constants.MeasurementError[key].value for key in data.status] diff --git a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py index dd6ff7ae007..74a41847d0a 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_325.py @@ -83,7 +83,7 @@ class LakeshoreModel325Curve(InstrumentChannel): An InstrumentChannel representing a curve on a Lakeshore Model 325 """ - valid_sensor_units = ["mV", "V", "Ohm", "log Ohm"] + valid_sensor_units = ("mV", "V", "Ohm", "log Ohm") temperature_key = "Temperature (K)" def __init__(self, parent: "LakeshoreModel325", index: int) -> None: diff --git a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_336.py b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_336.py index 847e6a6a7d4..f1f17ad7c68 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_336.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_336.py @@ -37,7 +37,7 @@ class LakeshoreModel336CurrentSource(BaseOutput): RANGES: ClassVar[dict[str, int]] = {"off": 0, "low": 1, "medium": 2, "high": 3} - _input_channel_parameter_kwargs = { + _input_channel_parameter_kwargs: ClassVar[dict[str, dict[str, int]]] = { "val_mapping": _channel_name_to_outmode_command_map } @@ -82,7 +82,7 @@ class LakeshoreModel336Channel(BaseSensorChannel): """ - SENSOR_STATUSES = { + SENSOR_STATUSES: ClassVar[dict[int, str]] = { 0: "OK", 1: "Invalid Reading", 16: "Temp Underrange", @@ -166,7 +166,7 @@ class LakeshoreModel336(LakeshoreBase): QCoDeS driver for Lakeshore Model 336 Temperature Controller. """ - channel_name_command: dict[str, str] = _channel_name_to_command_map + channel_name_command: ClassVar[dict[str, str]] = _channel_name_to_command_map CHANNEL_CLASS = LakeshoreModel336Channel diff --git a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_372.py b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_372.py index 625ffc4b527..3a5e273c33d 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_372.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Lakeshore_model_372.py @@ -98,7 +98,8 @@ class LakeshoreModel372Channel(BaseSensorChannel): An InstrumentChannel representing a single sensor on a Lakeshore Model 372. """ - SENSOR_STATUSES = { + + SENSOR_STATUSES: ClassVar[dict[int, str]] = { 0: "OK", 1: "CS OVL", 2: "VCM OVL", @@ -288,12 +289,12 @@ class LakeshoreModel372(LakeshoreBase): Computer Interface Operation section of the manual) is not implemented. """ - channel_name_command: dict[str, str] = { + channel_name_command: ClassVar[dict[str, str]] = { f"ch{i:02}": str(i) for i in range(1, 1 + _n_channels) } - input_channel_parameter_values_to_channel_name_on_instrument = { - i: f"ch{i:02}" for i in range(1, 1 + _n_channels) - } + input_channel_parameter_values_to_channel_name_on_instrument: ClassVar[ + dict[int, str] + ] = {i: f"ch{i:02}" for i in range(1, 1 + _n_channels)} CHANNEL_CLASS = LakeshoreModel372Channel diff --git a/src/qcodes/instrument_drivers/Lakeshore/Model_336.py b/src/qcodes/instrument_drivers/Lakeshore/Model_336.py index fc69fd1a5be..7b8f592f9fc 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Model_336.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Model_336.py @@ -24,7 +24,7 @@ class Model_336(LakeshoreBase): Lakeshore Model 336 Temperature Controller Driver """ - channel_name_command: dict[str, str] = _channel_name_to_command_map + channel_name_command: ClassVar[dict[str, str]] = _channel_name_to_command_map CHANNEL_CLASS = Model_336_Channel diff --git a/src/qcodes/instrument_drivers/Lakeshore/Model_372.py b/src/qcodes/instrument_drivers/Lakeshore/Model_372.py index 8213d1010fa..5586f94584c 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/Model_372.py +++ b/src/qcodes/instrument_drivers/Lakeshore/Model_372.py @@ -3,7 +3,7 @@ It will eventually be deprecated and removed """ -from typing import Any +from typing import Any, ClassVar import qcodes.validators as vals from qcodes.instrument_drivers.Lakeshore.lakeshore_base import ( @@ -28,12 +28,12 @@ class Model_372(LakeshoreBase): Computer Interface Operation section of the manual) is not implemented. """ - channel_name_command: dict[str, str] = { + channel_name_command: ClassVar[dict[str, str]] = { f"ch{i:02}": str(i) for i in range(1, 1 + _n_channels) } - input_channel_parameter_values_to_channel_name_on_instrument = { - i: f'ch{i:02}' for i in range(1, 1 + _n_channels) - } + input_channel_parameter_values_to_channel_name_on_instrument: ClassVar[ + dict[int, str] + ] = {i: f"ch{i:02}" for i in range(1, 1 + _n_channels)} CHANNEL_CLASS = Model_372_Channel diff --git a/src/qcodes/instrument_drivers/Lakeshore/_lakeshore_model_335.py b/src/qcodes/instrument_drivers/Lakeshore/_lakeshore_model_335.py index 71f8baa0140..fedcf7ccdbf 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/_lakeshore_model_335.py +++ b/src/qcodes/instrument_drivers/Lakeshore/_lakeshore_model_335.py @@ -29,7 +29,7 @@ class LakeshoreModel335Channel(BaseSensorChannel): """ - SENSOR_STATUSES = { + SENSOR_STATUSES: ClassVar[dict[int, str]] = { 0: "OK", 1: "Invalid Reading", 16: "Temp Underrange", @@ -125,7 +125,7 @@ class LakeshoreModel335CurrentSource(BaseOutput): RANGES: ClassVar[dict[str, int]] = {"off": 0, "low": 1, "medium": 2, "high": 3} - _input_channel_parameter_kwargs = { + _input_channel_parameter_kwargs: ClassVar[dict[str, dict[str, int]]] = { "val_mapping": _channel_name_to_outmode_command_map } @@ -144,7 +144,7 @@ class LakeshoreModel335(LakeshoreBase): Lakeshore Model 335 Temperature Controller Driver """ - channel_name_command: dict[str, str] = _channel_name_to_command_map + channel_name_command: ClassVar[dict[str, str]] = _channel_name_to_command_map CHANNEL_CLASS = LakeshoreModel335Channel diff --git a/src/qcodes/instrument_drivers/Lakeshore/lakeshore_base.py b/src/qcodes/instrument_drivers/Lakeshore/lakeshore_base.py index d5c50d3a529..2403cad27c6 100644 --- a/src/qcodes/instrument_drivers/Lakeshore/lakeshore_base.py +++ b/src/qcodes/instrument_drivers/Lakeshore/lakeshore_base.py @@ -480,9 +480,11 @@ class LakeshoreBase(VisaInstrument): # is used in instrument commands as values. For example, if channel called # "B" is referred to in instrument commands as '2', then this dictionary # will contain {'B': '2'} entry. - channel_name_command: dict[str, str] = {} + channel_name_command: ClassVar[dict[str, str]] = {} - input_channel_parameter_values_to_channel_name_on_instrument: dict[Any, str] + input_channel_parameter_values_to_channel_name_on_instrument: ClassVar[ + dict[Any, str] + ] def __init__( self, diff --git a/src/qcodes/instrument_drivers/QDevil/QDevil_QDAC.py b/src/qcodes/instrument_drivers/QDevil/QDevil_QDAC.py index 72424dbdc69..6b429239309 100644 --- a/src/qcodes/instrument_drivers/QDevil/QDevil_QDAC.py +++ b/src/qcodes/instrument_drivers/QDevil/QDevil_QDAC.py @@ -51,7 +51,7 @@ class Waveform: square = 2 triangle = 3 staircase = 4 - all_waveforms = [sine, square, triangle, staircase] + all_waveforms = (sine, square, triangle, staircase) class Generator: diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py index 3a298400689..1d4e9be075a 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/DynaCool.py @@ -1,7 +1,7 @@ import warnings from functools import partial from time import sleep -from typing import Any, Optional, Union, cast +from typing import Any, Callable, ClassVar, Literal, Optional, Union, cast import numpy as np from pyvisa import VisaIOError @@ -31,13 +31,14 @@ class DynaCool(VisaInstrument): # _do_blocking_ramp method _ramp_time_resolution = 0.1 - temp_params = ['temperature_setpoint', 'temperature_rate', - 'temperature_settling'] - field_params = ['field_target', 'field_rate', 'field_approach'] + temp_params = ("temperature_setpoint", "temperature_rate", "temperature_settling") + field_params = ("field_target", "field_rate", "field_approach") - _errors = {-2: lambda: warnings.warn('Unknown command'), - 1: lambda: None, - 0: lambda: None} + _errors: ClassVar[dict[int, Callable[[], None]]] = { + -2: lambda: warnings.warn("Unknown command"), + 1: lambda: None, + 0: lambda: None, + } def __init__(self, name: str, address: str, @@ -291,7 +292,9 @@ def _measured_field_getter(self) -> float: number_in_tesla = number_in_oersted*1e-4 return number_in_tesla - def _field_getter(self, param_name: str) -> Union[int, float]: + def _field_getter( + self, param_name: Literal["field_target", "field_rate", "field_approach"] + ) -> Union[int, float]: """ The combined get function for the three field parameters, field_setpoint, field_rate, and field_approach @@ -303,7 +306,11 @@ def _field_getter(self, param_name: str) -> Union[int, float]: return dict(zip(self.field_params, [sp, rate, approach]))[param_name] - def _field_setter(self, param: str, value: float) -> None: + def _field_setter( + self, + param: Literal["field_target", "field_rate", "field_approach"], + value: float, + ) -> None: """ The combined set function for the three field parameters, field_setpoint, field_rate, and field_approach @@ -315,7 +322,12 @@ def _field_setter(self, param: str, value: float) -> None: self.write(f'FELD {values[0]}, {values[1]}, {values[2]}, 0') - def _temp_getter(self, param_name: str) -> Union[int, float]: + def _temp_getter( + self, + param_name: Literal[ + "temperature_setpoint", "temperature_rate", "temperature_settling" + ], + ) -> Union[int, float]: """ This function queries the last temperature setpoint (w. rate and mode) from the instrument. @@ -327,7 +339,13 @@ def _temp_getter(self, param_name: str) -> Union[int, float]: return dict(zip(self.temp_params, [sp, rate, mode]))[param_name] - def _temp_setter(self, param: str, value: float) -> None: + def _temp_setter( + self, + param: Literal[ + "temperature_setpoint", "temperature_rate", "temperature_settling" + ], + value: float, + ) -> None: """ The setter function for the temperature parameters. All three are set with the same call to the instrument API diff --git a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py index 1f8b9c10456..60f5bd2bfcb 100644 --- a/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py +++ b/src/qcodes/instrument_drivers/QuantumDesign/DynaCoolPPMS/private/commandhandler.py @@ -1,7 +1,7 @@ import logging from collections import namedtuple from itertools import chain -from typing import Any +from typing import Any, ClassVar log = logging.getLogger(__name__) @@ -38,8 +38,10 @@ class CommandHandler: """ # Variable types - _variants = {'double': win32com.client.VARIANT(VT_BYREF | VT_R8, 0.0), - 'long': win32com.client.VARIANT(VT_BYREF | VT_I4, 0)} + _variants: ClassVar[dict[str, win32com.client.VARIANT]] = { + "double": win32com.client.VARIANT(VT_BYREF | VT_R8, 0.0), + "long": win32com.client.VARIANT(VT_BYREF | VT_I4, 0), + } def __init__(self, inst_type: str = 'dynacool') -> None: self.inst_type = inst_type diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430.py index bcb42dbce9c..66a9dcb2384 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430.py @@ -9,7 +9,7 @@ from collections.abc import Iterable, Sequence from contextlib import ExitStack from functools import partial -from typing import Any, Callable, TypeVar, cast +from typing import Any, Callable, ClassVar, TypeVar, cast import numpy as np @@ -134,8 +134,13 @@ class AMI430(IPInstrument): address: IP address of the power supply programmer current_ramp_limit: A current ramp limit, in units of A/s """ - _SHORT_UNITS = {'seconds': 's', 'minutes': 'min', - 'tesla': 'T', 'kilogauss': 'kG'} + + _SHORT_UNITS: ClassVar[dict[str, str]] = { + "seconds": "s", + "minutes": "min", + "tesla": "T", + "kilogauss": "kG", + } _DEFAULT_CURRENT_RAMP_LIMIT = 0.06 # [A/s] def __init__( diff --git a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py index cc43ec6e474..41b0620586e 100644 --- a/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py +++ b/src/qcodes/instrument_drivers/american_magnetics/AMI430_visa.py @@ -8,7 +8,7 @@ from collections.abc import Iterable, Sequence from contextlib import ExitStack from functools import partial -from typing import Any, Callable, TypeVar, cast +from typing import Any, Callable, ClassVar, TypeVar, cast import numpy as np from pyvisa import VisaIOError @@ -148,7 +148,12 @@ class AMIModel430(VisaInstrument): current_ramp_limit: A current ramp limit, in units of A/s """ - _SHORT_UNITS = {"seconds": "s", "minutes": "min", "tesla": "T", "kilogauss": "kG"} + _SHORT_UNITS: ClassVar[dict[str, str]] = { + "seconds": "s", + "minutes": "min", + "tesla": "T", + "kilogauss": "kG", + } _DEFAULT_CURRENT_RAMP_LIMIT = 0.06 # [A/s] _RETRY_WRITE_ASK = True _RETRY_TIME = 5 diff --git a/src/qcodes/instrument_drivers/rigol/Rigol_DG1062.py b/src/qcodes/instrument_drivers/rigol/Rigol_DG1062.py index e8c54069371..1df62e9ec60 100644 --- a/src/qcodes/instrument_drivers/rigol/Rigol_DG1062.py +++ b/src/qcodes/instrument_drivers/rigol/Rigol_DG1062.py @@ -1,6 +1,6 @@ import logging from functools import partial -from typing import Any, Union, cast +from typing import Any, ClassVar, Union, cast from qcodes import validators as vals from qcodes.instrument import ChannelList, InstrumentChannel, VisaInstrument @@ -106,19 +106,19 @@ class RigolDG1062Channel(InstrumentChannel): min_impedance = 1 max_impedance = 10000 - waveform_params = { - waveform: ["freq", "ampl", "offset", "phase"] + waveform_params: ClassVar[dict[str, tuple[str, ...]]] = { + waveform: ("freq", "ampl", "offset", "phase") for waveform in ["HARM", "NOIS", "RAMP", "SIN", "SQU", "TRI", "USER", "PULS"] } - waveform_params["DC"] = ["freq", "ampl", "offset"] - waveform_params["ARB"] = ["sample_rate", "ampl", "offset"] + waveform_params["DC"] = ("freq", "ampl", "offset") + waveform_params["ARB"] = ("sample_rate", "ampl", "offset") """ Responses from the machine don't always match the name to set the function, hence a translater """ - waveform_translate = { + waveform_translate: ClassVar[dict[str, str]] = { "HARM": "HARM", "NOISE": "NOIS", "RAMP": "RAMP", @@ -129,7 +129,7 @@ class RigolDG1062Channel(InstrumentChannel): "PULSE": "PULS", } - waveforms = list(waveform_params.keys()) + waveforms: ClassVar[tuple[str, ...]] = tuple(waveform_params.keys()) def __init__(self, parent: "RigolDG1062", name: str, channel: int): """ @@ -279,7 +279,7 @@ def to_float(string: str) -> Union[float, str]: current_waveform = self.waveform_translate[parts[0]] param_vals: list[Union[str, float]] = [current_waveform] param_vals += [to_float(i) for i in parts[1:]] - param_names = ["waveform"] + self.waveform_params[current_waveform] + param_names = ["waveform"] + list(self.waveform_params[current_waveform]) params_dict = dict(zip(param_names, param_vals)) return params_dict diff --git a/src/qcodes/instrument_drivers/stanford_research/SR830.py b/src/qcodes/instrument_drivers/stanford_research/SR830.py index c175e1d125a..611965c7b3e 100644 --- a/src/qcodes/instrument_drivers/stanford_research/SR830.py +++ b/src/qcodes/instrument_drivers/stanford_research/SR830.py @@ -1,7 +1,9 @@ +from __future__ import annotations + import time from collections.abc import Iterable from functools import partial -from typing import Any, Union +from typing import Any, ClassVar import numpy as np @@ -85,7 +87,7 @@ class ChannelBuffer(ArrayParameter): The instrument natively supports this in its TRCL call. """ - def __init__(self, name: str, instrument: 'SR830', channel: int) -> None: + def __init__(self, name: str, instrument: SR830, channel: int) -> None: """ Args: name: The name of the parameter @@ -193,39 +195,81 @@ class SR830(VisaInstrument): QCoDeS driver for the Stanford Research Systems SR830 Lock-in Amplifier. """ - _VOLT_TO_N = {2e-9: 0, 5e-9: 1, 10e-9: 2, - 20e-9: 3, 50e-9: 4, 100e-9: 5, - 200e-9: 6, 500e-9: 7, 1e-6: 8, - 2e-6: 9, 5e-6: 10, 10e-6: 11, - 20e-6: 12, 50e-6: 13, 100e-6: 14, - 200e-6: 15, 500e-6: 16, 1e-3: 17, - 2e-3: 18, 5e-3: 19, 10e-3: 20, - 20e-3: 21, 50e-3: 22, 100e-3: 23, - 200e-3: 24, 500e-3: 25, 1: 26} - _N_TO_VOLT = {v: k for k, v in _VOLT_TO_N.items()} - - _CURR_TO_N = {2e-15: 0, 5e-15: 1, 10e-15: 2, - 20e-15: 3, 50e-15: 4, 100e-15: 5, - 200e-15: 6, 500e-15: 7, 1e-12: 8, - 2e-12: 9, 5e-12: 10, 10e-12: 11, - 20e-12: 12, 50e-12: 13, 100e-12: 14, - 200e-12: 15, 500e-12: 16, 1e-9: 17, - 2e-9: 18, 5e-9: 19, 10e-9: 20, - 20e-9: 21, 50e-9: 22, 100e-9: 23, - 200e-9: 24, 500e-9: 25, 1e-6: 26} - _N_TO_CURR = {v: k for k, v in _CURR_TO_N.items()} + _VOLT_TO_N: ClassVar[dict[float | int, int]] = { + 2e-9: 0, + 5e-9: 1, + 10e-9: 2, + 20e-9: 3, + 50e-9: 4, + 100e-9: 5, + 200e-9: 6, + 500e-9: 7, + 1e-6: 8, + 2e-6: 9, + 5e-6: 10, + 10e-6: 11, + 20e-6: 12, + 50e-6: 13, + 100e-6: 14, + 200e-6: 15, + 500e-6: 16, + 1e-3: 17, + 2e-3: 18, + 5e-3: 19, + 10e-3: 20, + 20e-3: 21, + 50e-3: 22, + 100e-3: 23, + 200e-3: 24, + 500e-3: 25, + 1: 26, + } + _N_TO_VOLT: ClassVar[dict[int, float | int]] = {v: k for k, v in _VOLT_TO_N.items()} + + _CURR_TO_N: ClassVar[dict[float, int]] = { + 2e-15: 0, + 5e-15: 1, + 10e-15: 2, + 20e-15: 3, + 50e-15: 4, + 100e-15: 5, + 200e-15: 6, + 500e-15: 7, + 1e-12: 8, + 2e-12: 9, + 5e-12: 10, + 10e-12: 11, + 20e-12: 12, + 50e-12: 13, + 100e-12: 14, + 200e-12: 15, + 500e-12: 16, + 1e-9: 17, + 2e-9: 18, + 5e-9: 19, + 10e-9: 20, + 20e-9: 21, + 50e-9: 22, + 100e-9: 23, + 200e-9: 24, + 500e-9: 25, + 1e-6: 26, + } + _N_TO_CURR: ClassVar[dict[int, float]] = {v: k for k, v in _CURR_TO_N.items()} _VOLT_ENUM = Enum(*_VOLT_TO_N.keys()) _CURR_ENUM = Enum(*_CURR_TO_N.keys()) - _INPUT_CONFIG_TO_N = { + _INPUT_CONFIG_TO_N: ClassVar[dict[str, int]] = { 'a': 0, 'a-b': 1, 'I 1M': 2, 'I 100M': 3, } - _N_TO_INPUT_CONFIG = {v: k for k, v in _INPUT_CONFIG_TO_N.items()} + _N_TO_INPUT_CONFIG: ClassVar[dict[int, str]] = { + v: k for k, v in _INPUT_CONFIG_TO_N.items() + } def __init__(self, name: str, address: str, **kwargs: Any): super().__init__(name, address, **kwargs) @@ -568,7 +612,7 @@ def parse_offset_get(s: str) -> tuple[float, int]: self.connect_message() - SNAP_PARAMETERS = { + SNAP_PARAMETERS: ClassVar[dict[str, str]] = { 'x': '1', 'y': '2', 'r': '3', @@ -821,13 +865,14 @@ def autorange_once() -> bool: sets += 1 time.sleep(self.time_constant()) - def set_sweep_parameters(self, - sweep_param: Parameter, - start: float, - stop: float, - n_points: int = 10, - label: Union[str, None] = None) -> None: - + def set_sweep_parameters( + self, + sweep_param: Parameter, + start: float, + stop: float, + n_points: int = 10, + label: str | None = None, + ) -> None: self.sweep_setpoints.sweep_array = np.linspace(start, stop, n_points) self.sweep_setpoints.unit = sweep_param.unit if label is not None: @@ -841,9 +886,13 @@ class GeneratedSetPoints(Parameter): A parameter that generates a setpoint array from start, stop and num points parameters. """ - def __init__(self, - sweep_array: Iterable[Union[float, int]] = np.linspace(0, 1, 10), - *args: Any, **kwargs: Any) -> None: + + def __init__( + self, + sweep_array: Iterable[float | int] = np.linspace(0, 1, 10), + *args: Any, + **kwargs: Any, + ) -> None: super().__init__(*args, **kwargs) self.sweep_array = sweep_array self.update_units_if_constant_sample_rate() @@ -860,7 +909,7 @@ def update_units_if_constant_sample_rate(self) -> None: self.unit = 's' self.label = 'Time' - def set_raw(self, value: Iterable[Union[float, int]]) -> None: + def set_raw(self, value: Iterable[float | int]) -> None: self.sweep_array = value def get_raw(self) -> ParamRawDataType: diff --git a/src/qcodes/instrument_drivers/stanford_research/SR86x.py b/src/qcodes/instrument_drivers/stanford_research/SR86x.py index 9a64dfb53fb..f06e5af0a41 100644 --- a/src/qcodes/instrument_drivers/stanford_research/SR86x.py +++ b/src/qcodes/instrument_drivers/stanford_research/SR86x.py @@ -1,6 +1,8 @@ +from __future__ import annotations + import logging from collections.abc import Sequence -from typing import Any, Callable, Optional +from typing import Any, Callable, ClassVar import numpy as np @@ -20,7 +22,8 @@ class SR86xBufferReadout(ArrayParameter): name: Name of the parameter. instrument: The instrument to add this parameter to. """ - def __init__(self, name: str, instrument: 'SR86x', **kwargs: Any) -> None: + + def __init__(self, name: str, instrument: SR86x, **kwargs: Any) -> None: unit = "deg" if name in ["X", "Y", "R"]: @@ -37,7 +40,7 @@ def __init__(self, name: str, instrument: 'SR86x', **kwargs: Any) -> None: 'buffer of one channel.', **kwargs) - self._capture_data: Optional[np.ndarray] = None + self._capture_data: np.ndarray | None = None def prepare_readout(self, capture_data: np.ndarray) -> None: """ @@ -77,7 +80,7 @@ class SR86xBuffer(InstrumentChannel): manual: http://thinksrs.com/downloads/PDFs/Manuals/SR860m.pdf """ - def __init__(self, parent: 'SR86x', name: str) -> None: + def __init__(self, parent: SR86x, name: str) -> None: super().__init__(parent, name) self.add_parameter( @@ -159,8 +162,8 @@ def __init__(self, parent: 'SR86x', name: str) -> None: def snapshot_base( self, - update: Optional[bool] = False, - params_to_skip_update: Optional[Sequence[str]] = None, + update: bool | None = False, + params_to_skip_update: Sequence[str] | None = None, ) -> dict[Any, Any]: if params_to_skip_update is None: params_to_skip_update = [] @@ -569,9 +572,15 @@ class SR86xDataChannel(InstrumentChannel): is being plotted on the instrument's screen; added here only for reference """ - def __init__(self, parent: 'SR86x', name: str, cmd_id: str, - cmd_id_name: Optional[str] = None, - color: Optional[str] = None) -> None: + + def __init__( + self, + parent: SR86x, + name: str, + cmd_id: str, + cmd_id_name: str | None = None, + color: str | None = None, + ) -> None: super().__init__(parent, name) self._cmd_id = cmd_id @@ -594,11 +603,11 @@ def cmd_id(self) -> str: return self._cmd_id @property - def cmd_id_name(self) -> Optional[str]: + def cmd_id_name(self) -> str | None: return self._cmd_id_name @property - def color(self) -> Optional[str]: + def color(self) -> str | None: return self._color @@ -606,40 +615,83 @@ class SR86x(VisaInstrument): """ This is the code for Stanford_SR865 Lock-in Amplifier """ - _VOLT_TO_N = {1: 0, 500e-3: 1, 200e-3: 2, - 100e-3: 3, 50e-3: 4, 20e-3: 5, - 10e-3: 6, 5e-3: 7, 2e-3: 8, - 1e-3: 9, 500e-6: 10, 200e-6: 11, - 100e-6: 12, 50e-6: 13, 20e-6: 14, - 10e-6: 15, 5e-6: 16, 2e-6: 17, - 1e-6: 18, 500e-9: 19, 200e-9: 20, - 100e-9: 21, 50e-9: 22, 20e-9: 23, - 10e-9: 24, 5e-9: 25, 2e-9: 26, - 1e-9: 27} - _N_TO_VOLT = {v: k for k, v in _VOLT_TO_N.items()} - - _CURR_TO_N = {1e-6: 0, 500e-9: 1, 200e-9: 2, - 100e-9: 3, 50e-9: 4, 20e-9: 5, - 10e-9: 6, 5e-9: 7, 2e-9: 8, - 1e-9: 9, 500e-12: 10, 200e-12: 11, - 100e-12: 12, 50e-12: 13, 20e-12: 14, - 10e-12: 15, 5e-12: 16, 2e-12: 17, - 1e-12: 18, 500e-15: 19, 200e-15: 20, - 100e-15: 21, 50e-15: 22, 20e-15: 23, - 10e-15: 24, 5e-15: 25, 2e-15: 26, - 1e-15: 27} - _N_TO_CURR = {v: k for k, v in _CURR_TO_N.items()} + + _VOLT_TO_N: ClassVar[dict[int | float, int]] = { + 1: 0, + 500e-3: 1, + 200e-3: 2, + 100e-3: 3, + 50e-3: 4, + 20e-3: 5, + 10e-3: 6, + 5e-3: 7, + 2e-3: 8, + 1e-3: 9, + 500e-6: 10, + 200e-6: 11, + 100e-6: 12, + 50e-6: 13, + 20e-6: 14, + 10e-6: 15, + 5e-6: 16, + 2e-6: 17, + 1e-6: 18, + 500e-9: 19, + 200e-9: 20, + 100e-9: 21, + 50e-9: 22, + 20e-9: 23, + 10e-9: 24, + 5e-9: 25, + 2e-9: 26, + 1e-9: 27, + } + _N_TO_VOLT: ClassVar[dict[int, int | float]] = {v: k for k, v in _VOLT_TO_N.items()} + + _CURR_TO_N: ClassVar[dict[float, int]] = { + 1e-6: 0, + 500e-9: 1, + 200e-9: 2, + 100e-9: 3, + 50e-9: 4, + 20e-9: 5, + 10e-9: 6, + 5e-9: 7, + 2e-9: 8, + 1e-9: 9, + 500e-12: 10, + 200e-12: 11, + 100e-12: 12, + 50e-12: 13, + 20e-12: 14, + 10e-12: 15, + 5e-12: 16, + 2e-12: 17, + 1e-12: 18, + 500e-15: 19, + 200e-15: 20, + 100e-15: 21, + 50e-15: 22, + 20e-15: 23, + 10e-15: 24, + 5e-15: 25, + 2e-15: 26, + 1e-15: 27, + } + _N_TO_CURR: ClassVar[dict[int, float]] = {v: k for k, v in _CURR_TO_N.items()} _VOLT_ENUM = Enum(*_VOLT_TO_N.keys()) _CURR_ENUM = Enum(*_CURR_TO_N.keys()) - _INPUT_SIGNAL_TO_N = { + _INPUT_SIGNAL_TO_N: ClassVar[dict[str, int]] = { 'voltage': 0, 'current': 1, } - _N_TO_INPUT_SIGNAL = {v: k for k, v in _INPUT_SIGNAL_TO_N.items()} + _N_TO_INPUT_SIGNAL: ClassVar[dict[int, str]] = { + v: k for k, v in _INPUT_SIGNAL_TO_N.items() + } - PARAMETER_NAMES = { + PARAMETER_NAMES: ClassVar[dict[str, str]] = { 'X': '0', # X output, 'X' 'Y': '1', # Y output, 'Y' 'R': '2', # R output, 'R' diff --git a/src/qcodes/instrument_drivers/tektronix/AWG5014.py b/src/qcodes/instrument_drivers/tektronix/AWG5014.py index 5e680e8bba0..ca00f006908 100644 --- a/src/qcodes/instrument_drivers/tektronix/AWG5014.py +++ b/src/qcodes/instrument_drivers/tektronix/AWG5014.py @@ -6,7 +6,7 @@ from collections.abc import Sequence from io import BytesIO from time import localtime, sleep -from typing import Any, Literal, NamedTuple, Optional, Union, cast +from typing import Any, ClassVar, Literal, NamedTuple, Optional, Union, cast import numpy as np from pyvisa.errors import VisaIOError @@ -50,7 +50,8 @@ class TektronixAWG5014(VisaInstrument): corresponding parameters. """ - AWG_FILE_FORMAT_HEAD = { + + AWG_FILE_FORMAT_HEAD: ClassVar[dict[str, str]] = { 'SAMPLING_RATE': 'd', # d 'REPETITION_RATE': 'd', # # NAME? 'HOLD_REPETITION_RATE': 'h', # True | False @@ -79,7 +80,7 @@ class TektronixAWG5014(VisaInstrument): 'INTERLEAVE_ADJ_PHASE': 'd', 'INTERLEAVE_ADJ_AMPLITUDE': 'd', } - AWG_FILE_FORMAT_CHANNEL = { + AWG_FILE_FORMAT_CHANNEL: ClassVar[dict[str, str]] = { # Include NULL.(Output Waveform Name for Non-Sequence mode) 'OUTPUT_WAVEFORM_NAME_N': 's', 'CHANNEL_STATE_N': 'h', # On | Off diff --git a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py index 7b9208cb258..f79228e04e6 100644 --- a/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py +++ b/src/qcodes/instrument_drivers/tektronix/DPO7200xx.py @@ -6,7 +6,7 @@ import textwrap import time from functools import partial -from typing import Any, Callable, Union, cast +from typing import Any, Callable, ClassVar, Union, cast import numpy as np @@ -206,7 +206,8 @@ class TekronixDPOWaveform(InstrumentChannel): This submodule retrieves data from waveform sources, e.g. channels. """ - valid_identifiers = [ + + valid_identifiers: ClassVar[list[str]] = [ f"{source_type}{i}" for source_type in ["CH", "MATH", "REF"] for i in range(1, TektronixDPO7000xx.number_of_channels + 1) @@ -761,21 +762,59 @@ class TektronixDPOMeasurement(InstrumentChannel): # seconds after setting measurement type/source before # calling the measurement value SCPI command. - measurements = [ - ('amplitude', 'V'), ('area', 'Vs'), ('burst', 's'), ('carea', 'Vs'), - ('cmean', 'V'), ('crms', 'V'), ('delay', 's'), ('distduty', '%'), - ('extinctdb', 'dB'), ('extinctpct', '%'), ('extinctratio', ''), - ('eyeheight', 'V'), ('eyewidth', 's'), ('fall', 's'), - ('frequency', 'Hz'), ('high', 'V'), ('hits', 'hits'), ('low', 'V'), - ('maximum', 'V'), ('mean', 'V'), ('median', 'V'), ('minimum', 'V'), - ('ncross', 's'), ('nduty', '%'), ('novershoot', '%'), ('nwidth', 's'), - ('pbase', 'V'), ('pcross', 's'), ('pctcross', '%'), ('pduty', '%'), - ('peakhits', 'hits'), ('period', 's'), ('phase', '°'), ('pk2pk', 'V'), - ('pkpkjitter', 's'), ('pkpknoise', 'V'), ('povershoot', '%'), - ('ptop', 'V'), ('pwidth', 's'), ('qfactor', ''), ('rise', 's'), - ('rms', 'V'), ('rmsjitter', 's'), ('rmsnoise', 'V'), ('sigma1', '%'), - ('sigma2', '%'), ('sigma3', '%'), ('sixsigmajit', 's'), ('snratio', ''), - ('stddev', 'V'), ('undefined', ''), ('waveforms', 'wfms') + measurements: ClassVar[list[tuple[str, str]]] = [ + ("amplitude", "V"), + ("area", "Vs"), + ("burst", "s"), + ("carea", "Vs"), + ("cmean", "V"), + ("crms", "V"), + ("delay", "s"), + ("distduty", "%"), + ("extinctdb", "dB"), + ("extinctpct", "%"), + ("extinctratio", ""), + ("eyeheight", "V"), + ("eyewidth", "s"), + ("fall", "s"), + ("frequency", "Hz"), + ("high", "V"), + ("hits", "hits"), + ("low", "V"), + ("maximum", "V"), + ("mean", "V"), + ("median", "V"), + ("minimum", "V"), + ("ncross", "s"), + ("nduty", "%"), + ("novershoot", "%"), + ("nwidth", "s"), + ("pbase", "V"), + ("pcross", "s"), + ("pctcross", "%"), + ("pduty", "%"), + ("peakhits", "hits"), + ("period", "s"), + ("phase", "°"), + ("pk2pk", "V"), + ("pkpkjitter", "s"), + ("pkpknoise", "V"), + ("povershoot", "%"), + ("ptop", "V"), + ("pwidth", "s"), + ("qfactor", ""), + ("rise", "s"), + ("rms", "V"), + ("rmsjitter", "s"), + ("rmsnoise", "V"), + ("sigma1", "%"), + ("sigma2", "%"), + ("sigma3", "%"), + ("sixsigmajit", "s"), + ("snratio", ""), + ("stddev", "V"), + ("undefined", ""), + ("waveforms", "wfms"), ] def __init__( diff --git a/src/qcodes/math_utils/field_vector.py b/src/qcodes/math_utils/field_vector.py index cef8c4b0728..c408d9bd8e6 100644 --- a/src/qcodes/math_utils/field_vector.py +++ b/src/qcodes/math_utils/field_vector.py @@ -5,7 +5,7 @@ from __future__ import annotations from collections.abc import Sequence -from typing import Any, Literal, TypeVar, Union +from typing import Any, ClassVar, Literal, TypeVar, Union import numpy as np @@ -23,7 +23,8 @@ class FieldVector: or (rho, phi, z) values or (r, theta, phi) values at instantiation for a meaningful computation of the other representation, immediately. """ - attributes = ["x", "y", "z", "r", "theta", "phi", "rho"] + + attributes: ClassVar[list[str]] = ["x", "y", "z", "r", "theta", "phi", "rho"] repr_format = "cartesian" def __init__( diff --git a/src/qcodes/parameters/named_repr.py b/src/qcodes/parameters/named_repr.py index 4d2567cf8cd..e81bcd09dc4 100644 --- a/src/qcodes/parameters/named_repr.py +++ b/src/qcodes/parameters/named_repr.py @@ -5,5 +5,5 @@ def named_repr(obj: Any) -> str: """Enhance the standard repr() with the object's name attribute.""" - s = f"<{obj.__module__}.{type(obj).__name__}: {str(obj.name)} at {id(obj)}>" + s = f"<{obj.__module__}.{type(obj).__name__}: {obj.name!s} at {id(obj)}>" return s diff --git a/src/qcodes/parameters/parameter_base.py b/src/qcodes/parameters/parameter_base.py index 7a8ddbcfd97..e38ee926f09 100644 --- a/src/qcodes/parameters/parameter_base.py +++ b/src/qcodes/parameters/parameter_base.py @@ -9,7 +9,7 @@ from datetime import datetime from functools import cached_property, wraps from types import TracebackType -from typing import TYPE_CHECKING, Any, overload +from typing import TYPE_CHECKING, Any, ClassVar, overload from qcodes.metadatable import Metadatable, MetadatableWithName from qcodes.utils import DelegateAttributes, full_class, qcodes_abstractmethod @@ -1093,8 +1093,8 @@ class GetLatest(DelegateAttributes): def __init__(self, parameter: ParameterBase): self.parameter = parameter - delegate_attr_objects = ["parameter"] - omit_delegate_attrs = ["set"] + delegate_attr_objects: ClassVar[list[str]] = ["parameter"] + omit_delegate_attrs: ClassVar[list[str]] = ["set"] def get(self) -> ParamDataType: """ diff --git a/src/qcodes/station.py b/src/qcodes/station.py index ba1608bd8c3..3c4667e34b4 100644 --- a/src/qcodes/station.py +++ b/src/qcodes/station.py @@ -20,7 +20,7 @@ from io import StringIO from pathlib import Path from types import ModuleType -from typing import IO, Any, AnyStr, NoReturn, Union, cast, overload +from typing import IO, Any, AnyStr, ClassVar, NoReturn, Union, cast, overload import jsonschema import jsonschema.exceptions @@ -116,7 +116,7 @@ class Station(Metadatable, DelegateAttributes): default: Station | None = None "Class attribute to store the default station." - delegate_attr_dicts = ['components'] + delegate_attr_dicts: ClassVar[list[str]] = ["components"] """ A list of names (strings) of dictionaries which are (or will be) attributes of ``self``, diff --git a/src/qcodes/tests/dataset/test_dataset_basic.py b/src/qcodes/tests/dataset/test_dataset_basic.py index c4bbb9c1bfd..8539ae3a77a 100644 --- a/src/qcodes/tests/dataset/test_dataset_basic.py +++ b/src/qcodes/tests/dataset/test_dataset_basic.py @@ -3,7 +3,7 @@ import re from collections.abc import Sequence from copy import copy -from typing import Optional +from typing import ClassVar, Optional import hypothesis.strategies as hst import numpy as np @@ -817,7 +817,7 @@ def test_parent_dataset_links(some_interdeps) -> None: class TestGetData: x = ParamSpecBase("x", paramtype='numeric') n_vals = 5 - xvals = list(range(n_vals)) + xvals: ClassVar[list[int]] = list(range(n_vals)) # this is the format of how data is returned by DataSet.get_data # which means "a list of table rows" xdata = np.array(xvals) diff --git a/src/qcodes/tests/helpers/test_delegate_attribues.py b/src/qcodes/tests/helpers/test_delegate_attribues.py index 228eefc3fa1..42e08497e9c 100644 --- a/src/qcodes/tests/helpers/test_delegate_attribues.py +++ b/src/qcodes/tests/helpers/test_delegate_attribues.py @@ -1,3 +1,5 @@ +from typing import ClassVar + import pytest from qcodes.utils import DelegateAttributes @@ -5,8 +7,8 @@ def test_delegate_dict() -> None: class ToDict(DelegateAttributes): - delegate_attr_dicts = ['d'] - apples = 'green' + delegate_attr_dicts: ClassVar[list[str]] = ["d"] + apples = "green" td = ToDict() # td.d doesn't exist yet @@ -45,7 +47,7 @@ class ToDict(DelegateAttributes): def test_delegate_dicts() -> None: class ToDicts(DelegateAttributes): - delegate_attr_dicts = ['d', 'e'] + delegate_attr_dicts: ClassVar[list[str]] = ["d", "e"] td = ToDicts() e = {"cats": 12, "dogs": 3} @@ -75,8 +77,8 @@ class Recipient: white = '#fff' class ToObject(DelegateAttributes): - delegate_attr_objects = ['recipient'] - gray = '#888' + delegate_attr_objects: ClassVar[list[str]] = ["recipient"] + gray = "#888" to_obj = ToObject() recipient = Recipient() @@ -114,7 +116,7 @@ class R2: d = 6 class ToObjects(DelegateAttributes): - delegate_attr_objects = ['r1', 'r2'] + delegate_attr_objects: ClassVar[list[str]] = ["r1", "r2"] a = 0 e = 7 r1 = R1() @@ -151,10 +153,10 @@ class Recipient: my_recipient_dict = {'paper': 'Petta et al.', 'year': 2005} class ToBoth(DelegateAttributes): - delegate_attr_objects = ['recipient_object'] - delegate_attr_dicts = ['recipient_dict'] - rock = 'Eiger' - water = 'Lac Leman' + delegate_attr_objects: ClassVar[list[str]] = ["recipient_object"] + delegate_attr_dicts: ClassVar[list[str]] = ["recipient_dict"] + rock = "Eiger" + water = "Lac Leman" recipient_dict = my_recipient_dict recipient_object = Recipient() diff --git a/src/qcodes/tests/validators/test_enum.py b/src/qcodes/tests/validators/test_enum.py index ca58bf02716..409177482e4 100644 --- a/src/qcodes/tests/validators/test_enum.py +++ b/src/qcodes/tests/validators/test_enum.py @@ -27,7 +27,7 @@ def test_good() -> None: with pytest.raises((ValueError, TypeError)): e.validate(v) - assert repr(e) == f"" + assert repr(e) == f"" # Enum is never numeric, even if its members are all numbers # because the use of is_numeric is for sweeping diff --git a/src/qcodes/utils/attribute_helpers.py b/src/qcodes/utils/attribute_helpers.py index b2b1dff83f0..bfeae545e25 100644 --- a/src/qcodes/utils/attribute_helpers.py +++ b/src/qcodes/utils/attribute_helpers.py @@ -1,6 +1,6 @@ from collections.abc import Iterator, Sequence from contextlib import contextmanager -from typing import Any, Union +from typing import Any, ClassVar, Union class DelegateAttributes: @@ -17,19 +17,19 @@ class DelegateAttributes: 3. Attributes of each object in ``delegate_attr_objects`` (in order). """ - delegate_attr_dicts: list[str] = [] + delegate_attr_dicts: ClassVar[list[str]] = [] """ A list of names (strings) of dictionaries which are (or will be) attributes of ``self``, whose keys should be treated as attributes of ``self``. """ - delegate_attr_objects: list[str] = [] + delegate_attr_objects: ClassVar[list[str]] = [] """ A list of names (strings) of objects which are (or will be) attributes of ``self``, whose attributes should be passed through to ``self``. """ - omit_delegate_attrs: list[str] = [] + omit_delegate_attrs: ClassVar[list[str]] = [] """ A list of attribute names (strings) to *not* delegate to any other dictionary or object. @@ -45,9 +45,7 @@ def __getattr__(self, key: str) -> Any: if key == name: # needed to prevent infinite loops! raise AttributeError( - "dict '{}' has not been created in object '{}'".format( - key, self.__class__.__name__ - ) + f"dict '{key}' has not been created in object '{self.__class__.__name__}'" ) try: d = getattr(self, name, None) @@ -59,9 +57,7 @@ def __getattr__(self, key: str) -> Any: for name in self.delegate_attr_objects: if key == name: raise AttributeError( - "object '{}' has not been created in object '{}'".format( - key, self.__class__.__name__ - ) + f"object '{key}' has not been created in object '{self.__class__.__name__}'" ) try: obj = getattr(self, name, None) @@ -71,9 +67,7 @@ def __getattr__(self, key: str) -> Any: pass raise AttributeError( - "'{}' object and its delegates have no attribute '{}'".format( - self.__class__.__name__, key - ) + f"'{self.__class__.__name__}' object and its delegates have no attribute '{key}'" ) def __dir__(self) -> list[str]: diff --git a/src/qcodes/utils/installation_info.py b/src/qcodes/utils/installation_info.py index 7ee2670498e..da7a2af17a3 100644 --- a/src/qcodes/utils/installation_info.py +++ b/src/qcodes/utils/installation_info.py @@ -39,7 +39,7 @@ def is_qcodes_installed_editably() -> Optional[bool]: e_pkgs = json.loads(pipproc.stdout.decode('utf-8')) answer = any([d["name"] == 'qcodes' for d in e_pkgs]) except Exception as e: # we actually do want a catch-all here - log.warning(f'{type(e)}: {str(e)}') + log.warning(f"{type(e)}: {e!s}") answer = None return answer diff --git a/src/qcodes/validators/validators.py b/src/qcodes/validators/validators.py index ac272739594..7ccaf8e762e 100644 --- a/src/qcodes/validators/validators.py +++ b/src/qcodes/validators/validators.py @@ -171,7 +171,7 @@ def validate(self, value: bool | np.bool_, context: str = "") -> None: TypeError: IF not a boolean. """ if not isinstance(value, bool) and not isinstance(value, np.bool_): - raise TypeError(f"{repr(value)} is not Boolean; {context}") + raise TypeError(f"{value!r} is not Boolean; {context}") def __repr__(self) -> str: return "" @@ -215,12 +215,12 @@ def validate(self, value: str, context: str = "") -> None: """ if not isinstance(value, str): - raise TypeError(f"{repr(value)} is not a string; {context}") + raise TypeError(f"{value!r} is not a string; {context}") vallen = len(value) if vallen < self._min_length or vallen > self._max_length: raise ValueError( - f"{repr(value)} is invalid: length must be between " + f"{value!r} is invalid: length must be between " f"{self._min_length} and {self._max_length} inclusive; {context}" ) @@ -258,7 +258,6 @@ def __init__( min_value: numbertypes = -float("inf"), max_value: numbertypes = float("inf"), ) -> None: - if isinstance(min_value, self.validtypes): self._min_value = min_value else: @@ -286,11 +285,11 @@ def validate(self, value: numbertypes, context: str = "") -> None: ValueError: If number is not between the min and the max value. """ if not isinstance(value, self.validtypes): - raise TypeError(f"{repr(value)} is not an int or float; {context}") + raise TypeError(f"{value!r} is not an int or float; {context}") if not (self._min_value <= value <= self._max_value): raise ValueError( - f"{repr(value)} is invalid: must be between " + f"{value!r} is invalid: must be between " f"{self._min_value} and {self._max_value} inclusive; {context}" ) @@ -358,11 +357,11 @@ def validate(self, value: inttypes, context: str = "") -> None: ValueError: If not between min_value and max_value. """ if not isinstance(value, self.validtypes): - raise TypeError(f"{repr(value)} is not an int; {context}") + raise TypeError(f"{value!r} is not an int; {context}") if not (self._min_value <= value <= self._max_value): raise ValueError( - f"{repr(value)} is invalid: must be between " + f"{value!r} is invalid: must be between " f"{self._min_value} and {self._max_value} inclusive; {context}" ) @@ -411,7 +410,7 @@ def validate(self, value: numbertypes, context: str = "") -> None: castvalue = intrepr else: raise TypeError( - f"{repr(value)} is not an int or close to an int; {context}" + f"{value!r} is not an int or close to an int; {context}" ) else: castvalue = value @@ -426,7 +425,6 @@ class ComplexNumbers(Validator[Union[complex, "np.complexfloating[Any,Any]"]]): validtypes = (complex, np.complex128, np.complex64) def __init__(self) -> None: - self._valid_values = ((1 + 1j),) def validate( @@ -445,7 +443,7 @@ def validate( # for some reason pyright does not think numpy complex # types as valid types here if not isinstance(value, self.validtypes): # pyright: ignore - raise TypeError(f"{repr(value)} is not complex; {context}") + raise TypeError(f"{value!r} is not complex; {context}") is_numeric = False # there is no meaningful way to sweep a complex number @@ -472,18 +470,16 @@ def __init__(self, *values: Hashable | None) -> None: def validate(self, value: Hashable, context: str = "") -> None: try: if value not in self._values: - raise ValueError( - f"{repr(value)} is not in {repr(self._values)}; {context}" - ) + raise ValueError(f"{value!r} is not in {self._values!r}; {context}") except TypeError as e: # in case of unhashable (mutable) type e.args = e.args + ( - f"error looking for {repr(value)} in {repr(self._values)}; {context}", + f"error looking for {value!r} in {self._values!r}; {context}", ) raise def __repr__(self) -> str: - return f"" + return f"" @property def values(self) -> set[Hashable]: @@ -540,7 +536,7 @@ def validate(self, value: int | np.integer[Any], context: str = "") -> None: super().validate(value=value, context=context) if not value % self._divisor == 0: raise ValueError( - f"{repr(value)} is not a multiple of {repr(self._divisor)}; {context}" + f"{value!r} is not a multiple of {self._divisor!r}; {context}" ) def __repr__(self) -> str: @@ -809,10 +805,8 @@ def __init__( shape: abc.Sequence[shape_type] | None = None, valid_types: abc.Sequence[type] | None = None, ) -> None: - if valid_types is not None: for mytype in valid_types: - is_supported = any( np.issubdtype(mytype, supported_type) for supported_type in self.__supported_types @@ -935,9 +929,8 @@ def shape(self) -> tuple[int, ...] | None: return shape def validate(self, value: np.ndarray, context: str = "") -> None: - if not isinstance(value, np.ndarray): - raise TypeError(f"{repr(value)} is not a numpy array; {context}") + raise TypeError(f"{value!r} is not a numpy array; {context}") if not any( np.issubdtype(value.dtype.type, valid_type) @@ -951,7 +944,7 @@ def validate(self, value: np.ndarray, context: str = "") -> None: shape = self.shape if np.shape(value) != shape: raise ValueError( - f"{repr(value)} does not have expected shape {shape}," + f"{value!r} does not have expected shape {shape}," f" it has shape {np.shape(value)}; {context}" ) @@ -959,7 +952,7 @@ def validate(self, value: np.ndarray, context: str = "") -> None: if self._max_value != (float("inf")) and self._max_value is not None: if not (np.max(value) <= self._max_value): raise ValueError( - f"{repr(value)} is invalid: all values must be between " + f"{value!r} is invalid: all values must be between " f"{self._min_value} and {self._max_value} inclusive; {context}" ) @@ -967,7 +960,7 @@ def validate(self, value: np.ndarray, context: str = "") -> None: if self._min_value != (-float("inf")) and self._min_value is not None: if not (self._min_value <= np.min(value)): raise ValueError( - f"{repr(value)} is invalid: all values must be between " + f"{value!r} is invalid: all values must be between " f"{self._min_value} and {self._max_value} inclusive; {context}" ) @@ -1026,7 +1019,7 @@ def validate(self, value: list[T], context: str = "") -> None: TypeError: If not list. """ if not isinstance(value, list): - raise TypeError(f"{repr(value)} is not a list; {context}") + raise TypeError(f"{value!r} is not a list; {context}") # Does not validate elements if not required to improve performance if not isinstance(self._elt_validator, Anything): for elt in value: @@ -1079,13 +1072,13 @@ def validate(self, value: abc.Sequence[Any], context: str = "") -> None: ValueError: If not of given length or if not sorted. """ if not isinstance(value, abc.Sequence): - raise TypeError(f"{repr(value)} is not a sequence; {context}") + raise TypeError(f"{value!r} is not a sequence; {context}") if self._length and not len(value) == self._length: raise ValueError( - f"{repr(value)} has not length {self._length} but {len(value)}" + f"{value!r} has not length {self._length} but {len(value)}" ) if self._require_sorted and tuple(sorted(value)) != tuple(value): - raise ValueError(f"{repr(value)} is required to be sorted.") + raise ValueError(f"{value!r} is required to be sorted.") # Does not validate elements if not required to improve performance if not isinstance(self._elt_validator, Anything): for elt in value: @@ -1124,7 +1117,7 @@ def validate(self, value: abc.Callable[..., Any], context: str = "") -> None: TypeError: If not a callable. """ if not callable(value): - raise TypeError(f"{repr(value)} is not a callable; {context}") + raise TypeError(f"{value!r} is not a callable; {context}") def __repr__(self) -> str: return "" @@ -1158,7 +1151,7 @@ def validate(self, value: dict[Hashable, Any], context: str = "") -> None: SyntaxError: If keys are not in allowed keys. """ if not isinstance(value, dict): - raise TypeError(f"{repr(value)} is not a dictionary; {context}") + raise TypeError(f"{value!r} is not a dictionary; {context}") allowed_keys = self._allowed_keys if allowed_keys is not None: