Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ repos:
- id: remove-tabs
- id: forbid-tabs
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 9b9df9f1d3bd9a5e7a52d8f61a3be3e29e73d127 # frozen: 0.33.3
rev: 83987cd6ad8943c7f029b500b14aaf82c00a01fa # frozen: 0.34.0
hooks:
- id: check-readthedocs
- id: check-dependabot
Expand All @@ -54,7 +54,7 @@ repos:
- id: actionlint
additional_dependencies: [pyflakes, shellcheck-py]
- repo: https://github.com/commitizen-tools/commitizen
rev: 186dd18042ad30269e157e17db271a34b71e3bcd # frozen: v4.8.4
rev: cc981fcb065527b6de0033b0cbf0432e69781901 # frozen: v4.9.1
hooks:
- id: commitizen
stages: [commit-msg]
Expand Down Expand Up @@ -88,7 +88,7 @@ repos:
- mdformat-web
- mdformat-wikilink
- repo: https://github.com/pappasam/toml-sort
rev: 4ec24891e200ae663aa2a7cecd19516080777133 # frozen: v0.24.2
rev: 8c5db1c8081310adb476e1661c4d5d1fb6dbd96e # frozen: v0.24.3
hooks:
- id: toml-sort-fix
- repo: local
Expand Down Expand Up @@ -152,7 +152,7 @@ repos:
pass_filenames: false
args: [scripts/generate_schema.py]
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: 60ef368a6f48dfb4317651017f66dbb055241a6c # frozen: v0.12.12
rev: a113f03edeabb71305f025e6e14bd2cd68660e29 # frozen: v0.13.1
hooks:
- id: ruff-check
args: [--fix, --exit-non-zero-on-fix]
Expand Down
7 changes: 4 additions & 3 deletions docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
beautifulsoup4==4.13.5 ; python_full_version >= "3.9.2" and python_version < "3.14"
black==25.1.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
black==25.9.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
bracex==2.6 ; python_full_version >= "3.9.2" and python_version < "3.14"
certifi==2025.8.3 ; python_full_version >= "3.9.2" and python_version < "3.14"
charset-normalizer==3.4.3 ; python_full_version >= "3.9.2" and python_version < "3.14"
Expand Down Expand Up @@ -30,7 +30,7 @@ mkdocs-macros-plugin==1.3.9 ; python_full_version >= "3.9.2" and python_version
mkdocs-mermaid2-plugin==1.2.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
mkdocs-section-index==0.3.10 ; python_full_version >= "3.9.2" and python_version < "3.14"
mkdocs-spellcheck==1.1.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
mkdocstrings==0.30.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
mkdocstrings==0.30.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
mkdocstrings-python==1.18.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
more-itertools==10.8.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
mypy-extensions==1.1.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
Expand All @@ -41,13 +41,14 @@ platformdirs==4.4.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pygments==2.19.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
pymdown-extensions==10.16.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
python-dateutil==2.9.0.post0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytokens==0.1.10 ; python_full_version >= "3.9.2" and python_version < "3.14"
pyyaml==6.0.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
pyyaml-env-tag==1.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
requests==2.32.5 ; python_full_version >= "3.9.2" and python_version < "3.14"
setuptools==80.9.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
six==1.17.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
soupsieve==2.8 ; python_full_version >= "3.9.2" and python_version < "3.14"
super-collections==0.5.3 ; python_full_version >= "3.9.2" and python_version < "3.14"
super-collections==0.5.7 ; python_full_version >= "3.9.2" and python_version < "3.14"
symspellpy==6.9.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
termcolor==3.1.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
tomli==2.2.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
Expand Down
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ skip_empty = true
[tool.coverage.run]
branch = true
cover_pylib = false
patch = ["subprocess"]
plugins = ["coverage_conditional_plugin"]
source = ["tm_devices"]

Expand Down Expand Up @@ -144,20 +145,20 @@ symspellpy = "^6.7.7"
tomli = "^2.0.1"

[tool.poetry.group.tests.dependencies]
coverage = "^7.5.0"
coverage = "^7.10.6"
coverage-conditional-plugin = "^0.9.0"
flask = "^3.0.3"
http-server-mock = "^1.7"
linkchecker = "^10.0.0"
pytest = "^8.2.0"
pytest-cov = "^6.1.1"
pytest-cov = "^7.0.0"
pytest-depends = "^1.0.1"
pytest-env = "^1.1.3"
pytest-github-report = "^0.0.1"
pytest-html = "^4.1.1"
pytest-order = "^1.2.1"
pytest-repeat = "^0.9.4"
ruff = "0.12.12"
ruff = "0.13.1"

[tool.poetry.scripts]
list-visa-resources = "tm_devices:print_available_visa_devices"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class SourceDeviceConstants:


class SignalGeneratorMixin(
_ExtendableMixin, Generic[_SignalGeneratorFunctionsTypeVar, _SourceDeviceConstantsTypeVar], ABC
_ExtendableMixin, ABC, Generic[_SignalGeneratorFunctionsTypeVar, _SourceDeviceConstantsTypeVar]
):
"""A mixin class which adds methods and properties for generating signals."""

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

class _TektronixPIAFGAWGMixin( # pyright: ignore[reportUnusedClass]
CommonPISystemErrorCheckMixin,
Generic[_SignalGeneratorFunctionsTypeVar, _SourceDeviceConstantsTypeVar],
SignalGeneratorMixin[_SignalGeneratorFunctionsTypeVar, _SourceDeviceConstantsTypeVar],
_ExtendableMixin,
ABC,
Generic[_SignalGeneratorFunctionsTypeVar, _SourceDeviceConstantsTypeVar],
):
"""A private mixin for common methods and attributes for Tektronix AFG and AWG devices.

Expand Down
4 changes: 2 additions & 2 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pluggy==1.6.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pygments==2.19.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytablewriter==1.2.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest==8.4.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest-cov==6.3.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest-cov==7.0.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest-depends==1.0.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest-env==1.1.5 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytest-github-report==0.0.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
Expand All @@ -40,7 +40,7 @@ pytest-repeat==0.9.4 ; python_full_version >= "3.9.2" and python_version < "3.14
python-dateutil==2.9.0.post0 ; python_full_version >= "3.9.2" and python_version < "3.14"
pytz==2025.2 ; python_full_version >= "3.9.2" and python_version < "3.14"
requests==2.32.5 ; python_full_version >= "3.9.2" and python_version < "3.14"
ruff==0.12.12 ; python_full_version >= "3.9.2" and python_version < "3.14"
ruff==0.13.1 ; python_full_version >= "3.9.2" and python_version < "3.14"
setuptools==80.9.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
six==1.17.0 ; python_full_version >= "3.9.2" and python_version < "3.14"
soupsieve==2.8 ; python_full_version >= "3.9.2" and python_version < "3.14"
Expand Down
6 changes: 3 additions & 3 deletions tests/test_afgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ def test_afg3k(device_manager: DeviceManager) -> None: # noqa: PLR0915 # pylin

with pytest.raises(
TypeError,
match="Generate Waveform does not accept functions as non Enums. "
"Please use 'source_device_constants.functions'.",
match=r"Generate Waveform does not accept functions as non Enums\. "
r"Please use 'source_device_constants\.functions'\.",
):
afg3252c.generate_function(
25e6,
Expand Down Expand Up @@ -180,7 +180,7 @@ def test_afg3k(device_manager: DeviceManager) -> None: # noqa: PLR0915 # pylin
ramp_symmetry_range=None,
)

with pytest.raises(ValueError, match="AFGs must have a function defined."):
with pytest.raises(ValueError, match=r"AFGs must have a function defined\."):
afg3252c.get_waveform_constraints()

with pytest.raises(ValueError, match=r"Output state value must be 1 \(ON\) or 0 \(OFF\)\."):
Expand Down
8 changes: 4 additions & 4 deletions tests/test_awgs.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def test_awg5200(device_manager: DeviceManager, capsys: pytest.CaptureFixture[st
assert sasset_waveform_cmd in stdout

# Invalid file type for waveform file.
with pytest.raises(ValueError, match=".txt is an invalid waveform file extension."):
with pytest.raises(ValueError, match=r"\.txt is an invalid waveform file extension\."):
awg520050.load_waveform_set(
"unittest.txt",
)
Expand Down Expand Up @@ -224,7 +224,7 @@ def test_awg70k( # noqa: PLR0915 # pylint: disable=too-many-locals
)

# Invalid output signal path.
with pytest.raises(ValueError, match="DCHB is an invalid output signal path for AWG70001."):
with pytest.raises(ValueError, match=r"DCHB is an invalid output signal path for AWG70001."):
awg70ka150.source_channel["SOURCE1"].set_output_signal_path(
SignalGeneratorOutputPaths5200.DCHB
)
Expand All @@ -241,7 +241,7 @@ def test_awg70k( # noqa: PLR0915 # pylint: disable=too-many-locals
# Cannot set offset with output signal path set to DIR.
with pytest.raises(
ValueError,
match="The offset can only be set with an output signal path of DCA.",
match=r"The offset can only be set with an output signal path of DCA\.",
):
awg70ka150.source_channel["SOURCE1"].set_offset(0.1)

Expand Down Expand Up @@ -278,7 +278,7 @@ def test_awg70k( # noqa: PLR0915 # pylint: disable=too-many-locals
assert sasset_waveform_cmd in stdout

# Invalid file type for waveform file.
with pytest.raises(ValueError, match=".txt is an invalid waveform file extension."):
with pytest.raises(ValueError, match=r"\.txt is an invalid waveform file extension\."):
awg70ka150.load_waveform_set(
"unittest.txt",
)
Expand Down
2 changes: 1 addition & 1 deletion tests/test_device_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ def test_exceptions(self, device_manager: DeviceManager) -> None:
assert device_manager.is_open
with pytest.raises(
AssertionError,
match="The .* method should only be used if the DeviceManager has already been closed",
match=r"The .* method should only be used if the DeviceManager has already been closed",
):
device_manager.open()

Expand Down
12 changes: 6 additions & 6 deletions tests/test_generate_waveform.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,14 @@ def test_awg5200_gen_waveform(
# Frequency is too high to produce CLOCK function on this AWG.
with pytest.raises(
ValueError,
match="Unable to generate Clock waveform with provided frequency of 10000000000.0 Hz.",
match=r"Unable to generate Clock waveform with provided frequency of 10000000000\.0 Hz\.",
):
awg520050.generate_function(
10e9, awg520050.source_device_constants.functions.CLOCK, 1.0, 0.0, channel="SOURCE1"
)

# Invalid output signal path.
with pytest.raises(ValueError, match="DIR is an invalid output signal path for AWG5204."):
with pytest.raises(ValueError, match=r"DIR is an invalid output signal path for AWG5204\."):
awg520050.generate_function(
10e3,
awg520050.source_device_constants.functions.SIN,
Expand Down Expand Up @@ -193,7 +193,7 @@ def test_awg7k_gen_waveform(device_manager: DeviceManager) -> None:
)

# DCHB is not a valid output signal path for AWG7k's.
with pytest.raises(ValueError, match="DCHB is an invalid output signal path for AWG7051."):
with pytest.raises(ValueError, match=r"DCHB is an invalid output signal path for AWG7051\."):
awg7k01.generate_function(
10e3,
awg7k01.source_device_constants.functions.SIN,
Expand Down Expand Up @@ -427,8 +427,8 @@ def test_internal_afg_gen_waveform(

with pytest.raises(
TypeError,
match="Generate Waveform does not accept functions as non Enums. "
"Please use 'source_device_constants.functions'.",
match=r"Generate Waveform does not accept functions as non Enums\. "
r"Please use 'source_device_constants\.functions'\.",
):
scope.generate_function(
25e6,
Expand All @@ -442,6 +442,6 @@ def test_internal_afg_gen_waveform(

with pytest.raises(
AttributeError,
match="No AFG License, the class instance attributes are not accessible.",
match=r"No AFG License, the class instance attributes are not accessible\.",
):
mso2_scope.internal_afg.set_offset(1.0)
4 changes: 2 additions & 2 deletions tests/test_ieee_scpi_cmds.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ def test_ieee_scpi_cmds(device: AFG) -> None:
assert device.ieee_cmds.ese() == "0"
device.ieee_cmds.ese(255)
with pytest.raises(
ValueError, match="value=256 is not a valid value. The value must be between 0 and 255."
ValueError, match=r"value=256 is not a valid value\. The value must be between 0 and 255\."
):
device.ieee_cmds.ese(256)
assert device.ieee_cmds.sre() == "0"
device.ieee_cmds.sre(255)
with pytest.raises(
ValueError, match="value=256 is not a valid value. The value must be between 0 and 255."
ValueError, match=r"value=256 is not a valid value\. The value must be between 0 and 255\."
):
device.ieee_cmds.sre(256)
assert device.ieee_cmds.opc(write=True) == ""
Expand Down
2 changes: 1 addition & 1 deletion tests/test_rest_api_device.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ def test_unsupported_request_type(rest_api_control: CustomRestApiDevice) -> None
Args:
rest_api_control: Rest API Device.
"""
with pytest.raises(ValueError, match="UNSUPPORTED is an unsupported request type."):
with pytest.raises(ValueError, match=r"UNSUPPORTED is an unsupported request type\."):
rest_api_control._send_request( # noqa: SLF001
request_type="UNSUPPORTED", # type: ignore[arg-type]
url="/api",
Expand Down
12 changes: 6 additions & 6 deletions tests/test_scopes.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ def test_tekscope(device_manager: DeviceManager) -> None: # noqa: PLR0915
scope.setup_burst(10e3, scope.source_device_constants.functions.RAMP, 0.5, 0.0, burst_count=1)
with pytest.raises(
TypeError,
match="Generate Waveform does not accept functions as non Enums. "
"Please use 'source_device_constants.functions'.",
match=r"Generate Waveform does not accept functions as non Enums\. "
r"Please use 'source_device_constants\.functions'\.",
):
scope.generate_function(
25e6,
Expand Down Expand Up @@ -226,7 +226,7 @@ def test_tekscope(device_manager: DeviceManager) -> None: # noqa: PLR0915
assert scope.visa_timeout == UNIT_TEST_TIMEOUT

# test some internal assertions
with pytest.raises(AssertionError, match="none is not a valid item.*"):
with pytest.raises(AssertionError, match=r"none is not a valid item.*"):
scope._add_or_delete_dynamic_item("none", 1) # noqa: SLF001

# Assert no errors after completing testing
Expand Down Expand Up @@ -354,7 +354,7 @@ def test_iafg(device_manager: DeviceManager) -> None:
ramp_symmetry_range=ParameterBounds(lower=0.0, upper=100.0),
)

with pytest.raises(ValueError, match="IAFGs must have a function defined."):
with pytest.raises(ValueError, match=r"IAFGs must have a function defined\."):
mso56b.get_waveform_constraints()

with pytest.raises(ValueError, match=r"Output state value must be 1 \(ON\) or 0 \(OFF\)\."):
Expand Down Expand Up @@ -514,10 +514,10 @@ def test_tekscopepc(
assert scope.usb_drives == ("E:",)
assert scope.ip_address == ""
assert scope.total_channels == 8
with pytest.warns(UserWarning, match="Rebooting is not supported for the TekScopePC driver."):
with pytest.warns(UserWarning, match=r"Rebooting is not supported for the TekScopePC driver.*"):
scope.reboot()

with pytest.raises(ValueError, match="Invalid image extension: '.txt', valid extensions are"):
with pytest.raises(ValueError, match=r"Invalid image extension: '\.txt', valid extensions are"):
scope.save_screenshot("temp.txt")
with pytest.raises(
ValueError, match=r"Local folder path \(filename.txt\) is a file, not a directory."
Expand Down
4 changes: 2 additions & 2 deletions tests/test_smu.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def test_smu( # noqa: PLR0915
# Currently there is no way to unit test the cls function. Called to get full coverage.
tspieee.cls()
with pytest.raises(
ValueError, match="value=300 is not a valid value. The value must be between 0 and 255."
ValueError, match=r"value=300 is not a valid value\. The value must be between 0 and 255\."
):
tspieee.ese(300)
assert tspieee.ese(1) == "1"
Expand All @@ -125,7 +125,7 @@ def test_smu( # noqa: PLR0915
# Currently there is no way to unit test the rst function. Called to get full coverage.
tspieee.rst()
with pytest.raises(
ValueError, match="value=300 is not a valid value. The value must be between 0 and 255."
ValueError, match=r"value=300 is not a valid value\. The value must be between 0 and 255\."
):
tspieee.sre(300)
assert tspieee.sre(1) == "1"
Expand Down
Loading