diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c9d33856f..517c8e716 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,16 +27,11 @@ jobs: python -m pip install --upgrade pip poetry install --all-extras - name: Run linters - run: | - poetry run ni-python-styleguide lint + run: poetry run ni-python-styleguide lint - name: Run mypy (Linux) - run: | - poetry run mypy generated/nidaqmx - poetry run mypy tests + run: poetry run mypy - name: Run mypy (Windows) - run: | - poetry run mypy generated/nidaqmx --platform win32 - poetry run mypy tests --platform win32 + run: poetry run mypy --platform win32 - name: Generate ni-daqmx files run: | rm -fr generated/nidaqmx diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6e7e272e4..edcf74cef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,7 +29,11 @@ through our [GitHub issues page](http://github.com/ni/nidaqmx-python/issues). > The codegen scripts require Python 3.8 or later. 8. Run all the regression tests again (including the tests you just added), and confirm that they all pass. -9. Send a GitHub Pull Request to the main repository's master branch. GitHub Pull Requests are the +9. Run `poetry run ni-python-styleguide lint` to check that the updated code follows NI's Python coding +conventions. If this reports errors, first run `poetry run ni-python-styleguide fix` in order to sort +imports and format the code with Black, then manually fix any remaining errors. +10. Run `poetry run mypy` to statically type-check the updated code. +11. Send a GitHub Pull Request to the main repository's master branch. GitHub Pull Requests are the expected method of code collaboration on this project. # Testing diff --git a/generated/nidaqmx/_grpc_time.py b/generated/nidaqmx/_grpc_time.py index af218430a..ef3350718 100644 --- a/generated/nidaqmx/_grpc_time.py +++ b/generated/nidaqmx/_grpc_time.py @@ -1,5 +1,6 @@ from datetime import timezone from datetime import datetime as std_datetime +from datetime import tzinfo as dt_tzinfo from hightime import datetime as ht_datetime from hightime import timedelta as ht_timedelta from typing import Optional, Union @@ -41,7 +42,7 @@ def convert_time_to_timestamp(dt: Union[std_datetime, ht_datetime], ts: Optional ts.FromNanoseconds(seconds_since_1970 * _NS_PER_S + nanos) return ts -def convert_timestamp_to_time(ts: GrpcTimestamp, tzinfo: Optional[timezone] = None) -> ht_datetime: +def convert_timestamp_to_time(ts: GrpcTimestamp, tzinfo: Optional[dt_tzinfo] = None) -> ht_datetime: total_nanos = ts.ToNanoseconds() seconds, nanos = divmod(total_nanos, _NS_PER_S) # Convert the nanoseconds to yoctoseconds. diff --git a/generated/nidaqmx/_lib_time.py b/generated/nidaqmx/_lib_time.py index 99c2680e7..703ec8d57 100644 --- a/generated/nidaqmx/_lib_time.py +++ b/generated/nidaqmx/_lib_time.py @@ -4,6 +4,7 @@ import functools from datetime import timezone from datetime import datetime as std_datetime +from datetime import tzinfo as dt_tzinfo from hightime import datetime as ht_datetime from hightime import timedelta as ht_timedelta from typing import Optional, Union @@ -54,7 +55,7 @@ def from_datetime(cls, dt: Union[std_datetime, ht_datetime]) -> AbsoluteTime: return AbsoluteTime(lsb=lsb, msb=seconds_since_1904) - def to_datetime(self, tzinfo: Optional[timezone] = None) -> ht_datetime: + def to_datetime(self, tzinfo: Optional[dt_tzinfo] = None) -> ht_datetime: total_yoctoseconds = int( round(AbsoluteTime._YS_PER_S * self.lsb / AbsoluteTime._NUM_SUBSECONDS) ) diff --git a/pyproject.toml b/pyproject.toml index e63f32b9c..bce44b24c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -127,6 +127,7 @@ requires = ["poetry>=1.2"] build-backend = "poetry.masonry.api" [tool.mypy] +files = "generated/,tests/" check_untyped_defs = true namespace_packages = true plugins = "numpy.typing.mypy_plugin" diff --git a/src/handwritten/_grpc_time.py b/src/handwritten/_grpc_time.py index af218430a..ef3350718 100644 --- a/src/handwritten/_grpc_time.py +++ b/src/handwritten/_grpc_time.py @@ -1,5 +1,6 @@ from datetime import timezone from datetime import datetime as std_datetime +from datetime import tzinfo as dt_tzinfo from hightime import datetime as ht_datetime from hightime import timedelta as ht_timedelta from typing import Optional, Union @@ -41,7 +42,7 @@ def convert_time_to_timestamp(dt: Union[std_datetime, ht_datetime], ts: Optional ts.FromNanoseconds(seconds_since_1970 * _NS_PER_S + nanos) return ts -def convert_timestamp_to_time(ts: GrpcTimestamp, tzinfo: Optional[timezone] = None) -> ht_datetime: +def convert_timestamp_to_time(ts: GrpcTimestamp, tzinfo: Optional[dt_tzinfo] = None) -> ht_datetime: total_nanos = ts.ToNanoseconds() seconds, nanos = divmod(total_nanos, _NS_PER_S) # Convert the nanoseconds to yoctoseconds. diff --git a/src/handwritten/_lib_time.py b/src/handwritten/_lib_time.py index 99c2680e7..703ec8d57 100644 --- a/src/handwritten/_lib_time.py +++ b/src/handwritten/_lib_time.py @@ -4,6 +4,7 @@ import functools from datetime import timezone from datetime import datetime as std_datetime +from datetime import tzinfo as dt_tzinfo from hightime import datetime as ht_datetime from hightime import timedelta as ht_timedelta from typing import Optional, Union @@ -54,7 +55,7 @@ def from_datetime(cls, dt: Union[std_datetime, ht_datetime]) -> AbsoluteTime: return AbsoluteTime(lsb=lsb, msb=seconds_since_1904) - def to_datetime(self, tzinfo: Optional[timezone] = None) -> ht_datetime: + def to_datetime(self, tzinfo: Optional[dt_tzinfo] = None) -> ht_datetime: total_yoctoseconds = int( round(AbsoluteTime._YS_PER_S * self.lsb / AbsoluteTime._NUM_SUBSECONDS) ) diff --git a/tests/acceptance/test_examples.py b/tests/acceptance/test_examples.py index aa5e95b67..f39c82534 100644 --- a/tests/acceptance/test_examples.py +++ b/tests/acceptance/test_examples.py @@ -9,6 +9,7 @@ import pytest import nidaqmx +import nidaqmx.system EXAMPLES_DIRECTORY = Path(__file__).parent.parent.parent / "examples" EXAMPLE_PATHS = [p for p in EXAMPLES_DIRECTORY.glob("**/*.py") if p.name != "__init__.py"] diff --git a/tests/acceptance/test_internationalization.py b/tests/acceptance/test_internationalization.py index 024168fc9..08838d29a 100644 --- a/tests/acceptance/test_internationalization.py +++ b/tests/acceptance/test_internationalization.py @@ -66,6 +66,6 @@ def test___supported_encoding___logging_file_path___returns_assigned_value( ): if _get_encoding(ai_task) not in supported_encodings: pytest.skip("requires compatible encoding") - ai_task.in_stream.logging_file_path = file_path + ai_task.in_stream.logging_file_path = file_path # type: ignore[assignment] # https://github.com/ni/nidaqmx-python/issues/613 assert ai_task.in_stream.logging_file_path == pathlib.Path(file_path) diff --git a/tests/acceptance/test_multi_threading.py b/tests/acceptance/test_multi_threading.py index 6bd434216..624ff9d06 100644 --- a/tests/acceptance/test_multi_threading.py +++ b/tests/acceptance/test_multi_threading.py @@ -114,7 +114,7 @@ def test___multiple_tasks___get_set_float_and_string_properties___no_errors( futures = [] for i in range(num_tasks): task = generate_task() - task.ai_channels.add_ai_voltage_chan( + channel = task.ai_channels.add_ai_voltage_chan( multi_threading_test_devices[i].ai_physical_chans[0].name, min_val=-1.0, max_val=1.0 ) tasks.append(task) @@ -123,7 +123,7 @@ def test___multiple_tasks___get_set_float_and_string_properties___no_errors( _get_set_property_thread_main, start_barrier, stop_semaphore, - task, + channel, "ai_max", [1.0, 2.0, 5.0, 10.0], ) @@ -132,7 +132,7 @@ def test___multiple_tasks___get_set_float_and_string_properties___no_errors( _get_set_property_thread_main, start_barrier, stop_semaphore, - task, + channel, "description", ["ABC", "DEF", "GHI", "JKL"], ) diff --git a/tests/component/system/storage/test_persisted_channel.py b/tests/component/system/storage/test_persisted_channel.py index 1f2b02943..eeb2dc7da 100644 --- a/tests/component/system/storage/test_persisted_channel.py +++ b/tests/component/system/storage/test_persisted_channel.py @@ -1,6 +1,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.system.storage import PersistedChannel diff --git a/tests/component/task/channels/test_channel_properties.py b/tests/component/task/channels/test_channel_properties.py index 8fcfe9da3..4697338b0 100644 --- a/tests/component/task/channels/test_channel_properties.py +++ b/tests/component/task/channels/test_channel_properties.py @@ -7,7 +7,7 @@ RTDType, VoltageUnits, ) -from nidaqmx.scale import Scale +from nidaqmx.system.storage import PersistedScale from nidaqmx.task.channels import AIChannel, CIChannel @@ -211,7 +211,7 @@ def test___channel_with_scale___get_scale_property___shared_interpreter( @pytest.mark.scale_name("polynomial_scale") def test___channel_with_scale___set_scale_property___returns_assigned_scale( - ai_voltage_chan_with_scale: AIChannel, persisted_scale: Scale + ai_voltage_chan_with_scale: AIChannel, persisted_scale: PersistedScale ): ai_voltage_chan_with_scale.ai_custom_scale = persisted_scale.load() diff --git a/tests/component/task/test_in_stream.py b/tests/component/task/test_in_stream.py index a190736e1..9d3ae2103 100644 --- a/tests/component/task/test_in_stream.py +++ b/tests/component/task/test_in_stream.py @@ -4,6 +4,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import AcquisitionType # With a simulated X Series, setting ai_max/min to +/-2.5 V coerces the hardware range diff --git a/tests/component/task/test_in_stream_read_properties.py b/tests/component/task/test_in_stream_read_properties.py index 4bf615baf..b102e0212 100644 --- a/tests/component/task/test_in_stream_read_properties.py +++ b/tests/component/task/test_in_stream_read_properties.py @@ -136,7 +136,7 @@ def test___ai_task___get_string_property___returns_default_value(ai_task: Task): raises=DaqError, ) def test___ai_task___set_string_property___returns_assigned_value(ai_task: Task): - ai_task.in_stream.logging_file_path = "TestData.tdms" + ai_task.in_stream.logging_file_path = "TestData.tdms" # type: ignore[assignment] # https://github.com/ni/nidaqmx-python/issues/613 assert ai_task.in_stream.logging_file_path == pathlib.Path("TestData.tdms") @@ -156,7 +156,7 @@ def test___ai_task___set_string_property_none___returns_default_value(ai_task: T raises=DaqError, ) def test___ai_task___reset_string_property___returns_default_value(ai_task: Task): - ai_task.in_stream.logging_file_path = "TestData.tdms" + ai_task.in_stream.logging_file_path = "TestData.tdms" # type: ignore[assignment] # https://github.com/ni/nidaqmx-python/issues/613 del ai_task.in_stream.logging_file_path diff --git a/tests/component/task/test_out_stream.py b/tests/component/task/test_out_stream.py index 4fca174b1..07930455a 100644 --- a/tests/component/task/test_out_stream.py +++ b/tests/component/task/test_out_stream.py @@ -2,6 +2,7 @@ import pytest import nidaqmx +import nidaqmx.system @pytest.fixture(params=[1, 2]) diff --git a/tests/component/test_interpreter.py b/tests/component/test_interpreter.py index f7433a9f3..093f2af8f 100644 --- a/tests/component/test_interpreter.py +++ b/tests/component/test_interpreter.py @@ -38,7 +38,7 @@ def test___grpc_channel_with_errors___get_error_string___returns_failed_to_retri @pytest.mark.grpc_only(reason="Tests gRPC-specific error message lookup") @pytest.mark.parametrize("error_code", list(_ERROR_MESSAGES)) def test___error_code_with_hardcoded_error_message___get_error_string___returns_hardcoded_error_message( - interpreter: BaseInterpreter, error_code: int + interpreter: BaseInterpreter, error_code: DAQmxErrors ) -> None: error_message = interpreter.get_error_string(error_code) diff --git a/tests/component/test_stream_readers_ai.py b/tests/component/test_stream_readers_ai.py index 682cd24a7..a5216d3e0 100644 --- a/tests/component/test_stream_readers_ai.py +++ b/tests/component/test_stream_readers_ai.py @@ -7,6 +7,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.stream_readers import ( AnalogMultiChannelReader, AnalogSingleChannelReader, diff --git a/tests/component/test_stream_readers_ci.py b/tests/component/test_stream_readers_ci.py index caa7b227d..bb709b949 100644 --- a/tests/component/test_stream_readers_ci.py +++ b/tests/component/test_stream_readers_ci.py @@ -7,6 +7,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.stream_readers import CounterReader SIGNAL_TO_MEASURE = "100kHzTimebase" diff --git a/tests/component/test_stream_readers_di.py b/tests/component/test_stream_readers_di.py index e4bc29f54..ee84de3d4 100644 --- a/tests/component/test_stream_readers_di.py +++ b/tests/component/test_stream_readers_di.py @@ -7,6 +7,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import LineGrouping from nidaqmx.stream_readers import ( DigitalMultiChannelReader, diff --git a/tests/component/test_stream_writers.py b/tests/component/test_stream_writers.py index bdca6ff7f..f7770cf85 100644 --- a/tests/component/test_stream_writers.py +++ b/tests/component/test_stream_writers.py @@ -4,6 +4,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.stream_writers import AnalogMultiChannelWriter, AnalogSingleChannelWriter diff --git a/tests/component/test_stream_writers_ao.py b/tests/component/test_stream_writers_ao.py index 602985c74..63fccef4e 100644 --- a/tests/component/test_stream_writers_ao.py +++ b/tests/component/test_stream_writers_ao.py @@ -5,6 +5,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.stream_writers import ( AnalogMultiChannelWriter, AnalogSingleChannelWriter, diff --git a/tests/component/test_stream_writers_co.py b/tests/component/test_stream_writers_co.py index 68442ce81..558a49d78 100644 --- a/tests/component/test_stream_writers_co.py +++ b/tests/component/test_stream_writers_co.py @@ -6,6 +6,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import AcquisitionType from nidaqmx.stream_writers import CounterWriter from nidaqmx.types import CtrFreq, CtrTick, CtrTime diff --git a/tests/component/test_stream_writers_do.py b/tests/component/test_stream_writers_do.py index 2f245e5a4..4a8322708 100644 --- a/tests/component/test_stream_writers_do.py +++ b/tests/component/test_stream_writers_do.py @@ -6,6 +6,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import LineGrouping from nidaqmx.stream_writers import DigitalMultiChannelWriter, DigitalSingleChannelWriter from nidaqmx.utils import flatten_channel_string diff --git a/tests/component/test_task.py b/tests/component/test_task.py index 90bcc3be5..650db6044 100644 --- a/tests/component/test_task.py +++ b/tests/component/test_task.py @@ -1,6 +1,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import ShuntCalSelect, ShuntCalSource, ShuntElementLocation from nidaqmx.error_codes import DAQmxErrors from nidaqmx.errors import RpcError diff --git a/tests/component/test_task_events.py b/tests/component/test_task_events.py index a6d2f26b3..869907654 100644 --- a/tests/component/test_task_events.py +++ b/tests/component/test_task_events.py @@ -7,6 +7,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import AcquisitionType, EveryNSamplesEventType, Signal from nidaqmx.error_codes import DAQmxErrors from nidaqmx.errors import DaqResourceWarning, RpcError diff --git a/tests/component/test_task_read_ai.py b/tests/component/test_task_read_ai.py index 6eb44ba8e..07f340d1b 100644 --- a/tests/component/test_task_read_ai.py +++ b/tests/component/test_task_read_ai.py @@ -3,6 +3,7 @@ import pytest import nidaqmx +import nidaqmx.system from nidaqmx.constants import AcquisitionType diff --git a/tests/component/test_watchdog.py b/tests/component/test_watchdog.py index 1afb4f05d..4c92968e4 100644 --- a/tests/component/test_watchdog.py +++ b/tests/component/test_watchdog.py @@ -1,11 +1,14 @@ -from nidaqmx import Task +from typing import Callable + from nidaqmx.constants import WatchdogAOExpirState, WatchdogCOExpirState from nidaqmx.system import Device -from nidaqmx.system.watchdog import AOExpirationState, COExpirationState +from nidaqmx.system.watchdog import AOExpirationState, COExpirationState, WatchdogTask def test___watchdog_task___cfg_watchdog_ao_expir_states___no_error( - generate_watchdog_task: Task, sim_9189_device: Device, sim_9263_device: Device + generate_watchdog_task: Callable[..., WatchdogTask], + sim_9189_device: Device, + sim_9263_device: Device, ): watchdog_task = generate_watchdog_task(f"{sim_9189_device.name}", timeout=0.8) expir_states = [ @@ -36,7 +39,9 @@ def test___watchdog_task___cfg_watchdog_ao_expir_states___no_error( def test___watchdog_task___cfg_watchdog_co_expir_states___no_error( - generate_watchdog_task: Task, sim_9189_device: Device, sim_9401_device: Device + generate_watchdog_task: Callable[..., WatchdogTask], + sim_9189_device: Device, + sim_9401_device: Device, ): watchdog_task = generate_watchdog_task(f"{sim_9189_device.name}", timeout=0.8) expir_states = [ @@ -62,7 +67,9 @@ def test___watchdog_task___cfg_watchdog_co_expir_states___no_error( def test___watchdog_task___clear_expiration___no_error( - generate_watchdog_task: Task, sim_9189_device: Device, sim_9263_device: Device + generate_watchdog_task: Callable[..., WatchdogTask], + sim_9189_device: Device, + sim_9263_device: Device, ): watchdog_task = generate_watchdog_task(f"{sim_9189_device.name}", timeout=0.8) expir_states = [ diff --git a/tests/conftest.py b/tests/conftest.py index 37633092a..7e8842e11 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -6,7 +6,7 @@ import pathlib from concurrent.futures import ThreadPoolExecutor from enum import Enum -from typing import TYPE_CHECKING, Generator, List +from typing import TYPE_CHECKING, Callable, Generator, List import pytest @@ -454,7 +454,7 @@ def init_kwargs(request): @pytest.fixture(scope="function") -def task(request, generate_task): +def task(request, generate_task) -> nidaqmx.Task: """Gets a task instance. The closure of task objects will be done by this fixture once the test is complete. @@ -466,7 +466,7 @@ def task(request, generate_task): @pytest.fixture(scope="function") -def generate_task(init_kwargs): +def generate_task(init_kwargs) -> Generator[Callable[..., nidaqmx.Task], None, None]: """Gets a factory function which can be used to generate new tasks. The closure of task objects will be done by this fixture once the test is complete. @@ -475,14 +475,14 @@ def generate_task(init_kwargs): """ with contextlib.ExitStack() as stack: - def _create_task(task_name=""): + def _create_task(task_name: str = ""): return stack.enter_context(nidaqmx.Task(new_task_name=task_name, **init_kwargs)) yield _create_task @pytest.fixture(scope="function") -def persisted_task(request, system: nidaqmx.system.System): +def persisted_task(request, system: nidaqmx.system.System) -> nidaqmx.system.storage.PersistedTask: """Gets the persisted task based on the task name.""" task_name = _get_marker_value(request, "task_name") @@ -497,7 +497,9 @@ def persisted_task(request, system: nidaqmx.system.System): @pytest.fixture(scope="function") -def persisted_scale(request, system: nidaqmx.system.System): +def persisted_scale( + request, system: nidaqmx.system.System +) -> nidaqmx.system.storage.PersistedScale: """Gets the persisted scale based on the scale name.""" scale_name = _get_marker_value(request, "scale_name") if scale_name in system.scales: @@ -510,7 +512,9 @@ def persisted_scale(request, system: nidaqmx.system.System): @pytest.fixture(scope="function") -def persisted_channel(request, system: nidaqmx.system.System): +def persisted_channel( + request, system: nidaqmx.system.System +) -> nidaqmx.system.storage.PersistedChannel: """Gets the persisted channel based on the channel name.""" channel_name = _get_marker_value(request, "channel_name") @@ -535,7 +539,9 @@ def watchdog_task(request, sim_6363_device, generate_watchdog_task) -> nidaqmx.s @pytest.fixture(scope="function") -def generate_watchdog_task(init_kwargs): +def generate_watchdog_task( + init_kwargs, +) -> Generator[Callable[..., nidaqmx.system.WatchdogTask], None, None]: """Gets a factory function which can be used to generate new watchdog tasks. The closure of task objects will be done by this fixture once the test is complete. @@ -544,7 +550,7 @@ def generate_watchdog_task(init_kwargs): """ with contextlib.ExitStack() as stack: - def _create_task(device_name, task_name="", timeout=0.5): + def _create_task(device_name: str, task_name: str = "", timeout: float = 0.5): return stack.enter_context( nidaqmx.system.WatchdogTask(device_name, task_name, timeout, **init_kwargs) ) diff --git a/tests/legacy/test_read_exceptions.py b/tests/legacy/test_read_exceptions.py index f95341f8f..9c1b3da1d 100644 --- a/tests/legacy/test_read_exceptions.py +++ b/tests/legacy/test_read_exceptions.py @@ -4,6 +4,7 @@ import pytest import nidaqmx +import nidaqmx.stream_readers from nidaqmx.constants import AcquisitionType, BusType, Level, TaskMode from nidaqmx.error_codes import DAQmxErrors from nidaqmx.errors import RpcError diff --git a/tests/legacy/test_write_exceptions.py b/tests/legacy/test_write_exceptions.py index eafb3a643..f4df302ff 100644 --- a/tests/legacy/test_write_exceptions.py +++ b/tests/legacy/test_write_exceptions.py @@ -4,6 +4,7 @@ import pytest import nidaqmx +import nidaqmx.stream_writers from nidaqmx.constants import AcquisitionType, BusType, RegenerationMode from nidaqmx.error_codes import DAQmxErrors diff --git a/tests/unit/_task_utils.py b/tests/unit/_task_utils.py index 3f6f979be..68f0a86a8 100644 --- a/tests/unit/_task_utils.py +++ b/tests/unit/_task_utils.py @@ -1,6 +1,6 @@ """Task helper functions.""" -from typing import Dict, Sequence +from typing import Dict, Iterable from unittest.mock import Mock from pytest_mock import MockerFixture @@ -42,7 +42,7 @@ def register_event_handler(mocker: MockerFixture, task: Task, event_type: _TaskE def register_event_handlers( - mocker: MockerFixture, task: Task, event_types: Sequence[_TaskEventType] + mocker: MockerFixture, task: Task, event_types: Iterable[_TaskEventType] ) -> Dict[_TaskEventType, Mock]: """Register mock event handlers and return a dictionary mapping event name -> handler.""" return { diff --git a/tests/unit/test_task.py b/tests/unit/test_task.py index 30c2c87c4..3a6d0c0ba 100644 --- a/tests/unit/test_task.py +++ b/tests/unit/test_task.py @@ -43,7 +43,7 @@ def test___init_with_grpc_options___select_interpreter_called_with_grpc_options( task = Task(grpc_options=grpc_options) with task: - nidaqmx.utils._select_interpreter.mock.assert_called_with(grpc_options) + nidaqmx.utils._select_interpreter.mock.assert_called_with(grpc_options) # type: ignore[attr-defined] def test___init_with_name_and_grpc_options___specified_name_saved(