Skip to content

Commit

Permalink
add slots to DAQmx-property-containing classes (#664)
Browse files Browse the repository at this point in the history
* add slots to attribute-containing classes
  • Loading branch information
zhindes authored Dec 17, 2024
1 parent d2e7efc commit 6b14958
Show file tree
Hide file tree
Showing 38 changed files with 175 additions and 1 deletion.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ All notable changes to this project will be documented in this file.
* ...

* ### Resolved Issues
* ...
* [656: Missing usage of slots in classes with DAQmx attributes](https://github.com/ni/nidaqmx-python/issues/656)

* ### Major Changes
* Added support for mioDAQ configurable digital voltage.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class ExpirationState:
"""
Represents a DAQmx Watchdog expiration state.
"""
__slots__ = ('_handle', '_physical_channel', '_interpreter')

def __init__(self, task_handle, physical_channel, interpreter):
self._handle = task_handle
self._physical_channel = physical_channel
Expand Down
1 change: 1 addition & 0 deletions generated/nidaqmx/system/system.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ class System:
operations on DAQ hardware, and creates classes from which you can get
information about the hardware.
"""
__slots__ = ('_interpreter')

def __init__(self, grpc_options=None):
"""
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/system/watchdog.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class WatchdogTask:
"""
Represents the watchdog configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_close_on_exit', '_saved_name', '_interpreter', '_expiration_states', '__weakref__')

def __init__(self, device_name, task_name='', timeout=10, grpc_options=None):
"""
Creates and configures a task that controls the watchdog timer of a
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/_export_signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ class ExportSignals:
"""
Represents the exported signal configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/_in_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class InStream:
used in conjunction with reader classes to read samples from an
NI-DAQmx task.
"""
__slots__ = ('_task', '_handle', '_interpreter', '_timeout')

def __init__(self, task, interpreter):
self._task = task
self._handle = task._handle
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/_out_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class OutStream:
used in conjunction with writer classes to write samples to an
NI-DAQmx task.
"""
__slots__ = ('_task', '_handle', '_interpreter', '_auto_start', '_timeout')

def __init__(self, task, interpreter):
self._task = task
self._handle = task._handle
Expand Down
4 changes: 4 additions & 0 deletions generated/nidaqmx/task/_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class Task:
"""
Represents a DAQmx Task.
"""
__slots__ = ('_handle', '_close_on_exit', '_saved_name', '_grpc_options', '_event_handlers', '_interpreter',
'_ai_channels', '_ao_channels', '_ci_channels', '_co_channels', '_di_channels', '_do_channels',
'_export_signals', '_in_stream', '_timing', '_triggers', '_out_stream', '_event_handler_lock',
'__weakref__')

def __init__(self, new_task_name='', *, grpc_options=None):
"""
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/_timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class Timing:
"""
Represents the timing configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_arm_start_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class ArmStartTrigger:
"""
Represents the arm start trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_handshake_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class HandshakeTrigger:
"""
Represents the handshake trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_pause_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class PauseTrigger:
"""
Represents the pause trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_reference_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class ReferenceTrigger:
"""
Represents the reference trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_start_trigger.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class StartTrigger:
"""
Represents the start trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions generated/nidaqmx/task/triggering/_triggers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ class Triggers:
"""
Represents the trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter', '_arm_start_trigger', '_handshake_trigger', '_pause_trigger', '_reference_trigger', '_start_trigger')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ class ExpirationState:
"""
Represents a DAQmx Watchdog expiration state.
"""
__slots__ = ('_handle', '_physical_channel', '_interpreter')

def __init__(self, task_handle, physical_channel, interpreter):
self._handle = task_handle
self._physical_channel = physical_channel
Expand Down
1 change: 1 addition & 0 deletions src/codegen/templates/system/system.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class System:
operations on DAQ hardware, and creates classes from which you can get
information about the hardware.
"""
__slots__ = ('_interpreter')

def __init__(self, grpc_options=None):
"""
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/system/watchdog.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class WatchdogTask:
"""
Represents the watchdog configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_close_on_exit', '_saved_name', '_interpreter', '_expiration_states', '__weakref__')

def __init__(self, device_name, task_name='', timeout=10, grpc_options=None):
"""
Creates and configures a task that controls the watchdog timer of a
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/_export_signals.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class ExportSignals:
"""
Represents the exported signal configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/_in_stream.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class InStream:
used in conjunction with reader classes to read samples from an
NI-DAQmx task.
"""
__slots__ = ('_task', '_handle', '_interpreter', '_timeout')

def __init__(self, task, interpreter):
self._task = task
self._handle = task._handle
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/_out_stream.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class OutStream:
used in conjunction with writer classes to write samples to an
NI-DAQmx task.
"""
__slots__ = ('_task', '_handle', '_interpreter', '_auto_start', '_timeout')

def __init__(self, task, interpreter):
self._task = task
self._handle = task._handle
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/_timing.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class Timing:
"""
Represents the timing configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class ArmStartTrigger:
"""
Represents the arm start trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class HandshakeTrigger:
"""
Represents the handshake trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/triggering/_pause_trigger.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class PauseTrigger:
"""
Represents the pause trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class ReferenceTrigger:
"""
Represents the reference trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/triggering/_start_trigger.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class StartTrigger:
"""
Represents the start trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
2 changes: 2 additions & 0 deletions src/codegen/templates/task/triggering/_triggers.py.mako
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class Triggers:
"""
Represents the trigger configurations for a DAQmx task.
"""
__slots__ = ('_handle', '_interpreter', '_arm_start_trigger', '_handshake_trigger', '_pause_trigger', '_reference_trigger', '_start_trigger')

def __init__(self, task_handle, interpreter):
self._handle = task_handle
self._interpreter = interpreter
Expand Down
4 changes: 4 additions & 0 deletions src/handwritten/task/_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ class Task:
"""
Represents a DAQmx Task.
"""
__slots__ = ('_handle', '_close_on_exit', '_saved_name', '_grpc_options', '_event_handlers', '_interpreter',
'_ai_channels', '_ao_channels', '_ci_channels', '_co_channels', '_di_channels', '_do_channels',
'_export_signals', '_in_stream', '_timing', '_triggers', '_out_stream', '_event_handler_lock',
'__weakref__')

def __init__(self, new_task_name='', *, grpc_options=None):
"""
Expand Down
6 changes: 6 additions & 0 deletions tests/component/system/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import nidaqmx
from nidaqmx.constants import PowerUpChannelType
from nidaqmx.error_codes import DAQmxErrors
from nidaqmx.system import System
from nidaqmx.types import AOPowerUpState


Expand Down Expand Up @@ -121,3 +122,8 @@ def test_invalid_power_up_states___set_analog_power_up_states___throws_invalid_a
system.set_analog_power_up_states(device_name, power_up_states)

assert exc_info.value.error_code == DAQmxErrors.INVALID_ATTRIBUTE_VALUE


def test___system___set_nonexistent_property___raises_exception(system: System):
with pytest.raises(AttributeError):
system.nonexistent_property = "foo" # type: ignore[attr-defined]
5 changes: 5 additions & 0 deletions tests/component/task/test_in_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,8 @@ def test___valid_path___start_new_file___returns_assigned_value(ai_task: nidaqmx
ai_task.in_stream.start_new_file(expected_file_path)

assert ai_task.in_stream.logging_file_path == pathlib.Path(expected_file_path)


def test___in_stream___set_nonexistent_property___raises_exception(task: nidaqmx.Task):
with pytest.raises(AttributeError):
task.in_stream.nonexistent_property = "foo" # type: ignore[attr-defined]
5 changes: 5 additions & 0 deletions tests/component/task/test_out_stream.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,8 @@ def test___odd_sized_array___write___returns_whole_samples(
samples_written = task.out_stream.write(data)

assert samples_written == 9


def test___out_stream___set_nonexistent_property___raises_exception(task: nidaqmx.Task):
with pytest.raises(AttributeError):
task.out_stream.nonexistent_property = "foo" # type: ignore[attr-defined]
5 changes: 5 additions & 0 deletions tests/component/task/test_timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,3 +156,8 @@ def test___timing___cfg_burst_handshaking_export_clock___sets_properties(
sim_6535_di_single_line_task.export_signals.rdy_for_xfer_event_lvl_active_lvl
== ready_event_active_level
)


def test___timing___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.timing.nonexistent_property = "foo" # type: ignore[attr-defined]
30 changes: 30 additions & 0 deletions tests/component/task/test_triggers_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,33 @@ def test___ai_voltage_time_aware_task___reset_timestamp_property___returns_defau
assert when_value.hour == localized_default_value.hour
assert when_value.minute == localized_default_value.minute
assert when_value.second == localized_default_value.second


def test___trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.nonexistent_property = "foo" # type: ignore[attr-defined]


def test___arm_start_trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.arm_start_trigger.nonexistent_property = "foo" # type: ignore[attr-defined]


def test___handshake_trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.handshake_trigger.nonexistent_property = "foo" # type: ignore[attr-defined]


def test___pause_trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.pause_trigger.nonexistent_property = "foo" # type: ignore[attr-defined]


def test___reference_trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.reference_trigger.nonexistent_property = "foo" # type: ignore[attr-defined]


def test___start_trigger___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.triggers.start_trigger.nonexistent_property = "foo" # type: ignore[attr-defined]
8 changes: 8 additions & 0 deletions tests/component/test_export_signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import pytest

import nidaqmx


def test___export_signals___set_nonexistent_property___raises_exception(task: nidaqmx.Task):
with pytest.raises(AttributeError):
task.export_signals.nonexistent_property = "foo" # type: ignore[attr-defined]
8 changes: 8 additions & 0 deletions tests/component/test_task.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import weakref

import pytest

import nidaqmx
Expand Down Expand Up @@ -197,3 +199,9 @@ def test___task___add_global_channels___adds_to_channel_names(task: nidaqmx.Task
task.add_global_channels([persisted_channel, persisted_channel2])

assert task.channel_names == [persisted_channel.name, persisted_channel2.name]


def test___task___create_weakref___succeeds(task: nidaqmx.Task):
ref = weakref.ref(task)
task2 = ref()
assert task is task2
5 changes: 5 additions & 0 deletions tests/component/test_task_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,8 @@ def test___get_devices___shared_interpreter(ai_task: Task):
devices = ai_task.devices

assert all(dev._interpreter is ai_task._interpreter for dev in devices)


def test___task___set_nonexistent_property___raises_exception(task: Task):
with pytest.raises(AttributeError):
task.nonexistent_property = "foo" # type: ignore[attr-defined]
Loading

0 comments on commit 6b14958

Please sign in to comment.