syndesi 0.4.2__py3-none-any.whl → 0.4.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. syndesi/__init__.py +16 -1
  2. syndesi/adapters/adapter.py +147 -72
  3. syndesi/adapters/auto.py +26 -15
  4. syndesi/adapters/backend/adapter_backend.py +3 -3
  5. syndesi/adapters/backend/adapter_session.py +8 -9
  6. syndesi/adapters/backend/backend.py +7 -2
  7. syndesi/adapters/backend/ip_backend.py +44 -41
  8. syndesi/adapters/backend/serialport_backend.py +17 -12
  9. syndesi/adapters/backend/stop_condition_backend.py +8 -5
  10. syndesi/adapters/backend/visa_backend.py +3 -3
  11. syndesi/adapters/ip.py +30 -24
  12. syndesi/adapters/ip_server.py +9 -3
  13. syndesi/adapters/serialport.py +20 -7
  14. syndesi/adapters/stop_condition.py +84 -60
  15. syndesi/adapters/timeout.py +1 -0
  16. syndesi/adapters/visa.py +11 -3
  17. syndesi/cli/console.py +1 -1
  18. syndesi/cli/shell.py +2 -2
  19. syndesi/component.py +79 -0
  20. syndesi/protocols/delimited.py +2 -2
  21. syndesi/protocols/modbus.py +7 -6
  22. syndesi/protocols/protocol.py +7 -1
  23. syndesi/protocols/raw.py +2 -2
  24. syndesi/protocols/scpi.py +1 -1
  25. syndesi/scripts/syndesi.py +1 -1
  26. syndesi/tools/backend_api.py +8 -1
  27. syndesi/tools/errors.py +24 -4
  28. syndesi/tools/log.py +1 -0
  29. syndesi/tools/types.py +1 -0
  30. syndesi/version.py +5 -1
  31. {syndesi-0.4.2.dist-info → syndesi-0.4.4.dist-info}/METADATA +1 -1
  32. syndesi-0.4.4.dist-info/RECORD +61 -0
  33. syndesi-0.4.2.dist-info/RECORD +0 -60
  34. {syndesi-0.4.2.dist-info → syndesi-0.4.4.dist-info}/WHEEL +0 -0
  35. {syndesi-0.4.2.dist-info → syndesi-0.4.4.dist-info}/entry_points.txt +0 -0
  36. {syndesi-0.4.2.dist-info → syndesi-0.4.4.dist-info}/licenses/LICENSE +0 -0
  37. {syndesi-0.4.2.dist-info → syndesi-0.4.4.dist-info}/top_level.txt +0 -0
@@ -10,7 +10,13 @@ from typing import cast
10
10
 
11
11
  import _socket
12
12
 
13
- from ...tools.backend_api import AdapterBackendStatus, Fragment
13
+ from syndesi.tools.errors import AdapterConfigurationError, AdapterFailedToOpen
14
+
15
+ from ...tools.backend_api import (
16
+ DEFAULT_ADAPTER_OPEN_TIMEOUT,
17
+ AdapterBackendStatus,
18
+ Fragment,
19
+ )
14
20
  from .adapter_backend import AdapterBackend, HasFileno
15
21
  from .descriptors import IPDescriptor
16
22
 
@@ -55,42 +61,37 @@ class IPBackend(AdapterBackend):
55
61
  def selectable(self) -> HasFileno | None:
56
62
  return self._socket
57
63
 
58
- def open(self) -> bool:
59
- output = False
60
- if self._status == AdapterBackendStatus.DISCONNECTED:
61
- if self.descriptor.port is None: # TODO : Check if this is even possible
62
- raise ValueError("Cannot open adapter without specifying a port")
63
-
64
- if self._socket is None:
65
- if self.descriptor.transport == IPDescriptor.Transport.TCP:
66
- self._socket = cast(
67
- _socket.socket,
68
- socket.socket(socket.AF_INET, socket.SOCK_STREAM),
69
- )
70
- elif self.descriptor.transport == IPDescriptor.Transport.UDP:
71
- self._socket = cast(
72
- _socket.socket, socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
73
- )
74
- else:
75
- raise ValueError(
76
- f"Invalid transport protocol : {self.descriptor.transport}"
77
- )
78
- try:
79
- self._socket.settimeout(
80
- 0.5
81
- ) # TODO : Configure this cleanly, it has to be less than the receive timeout of the frontend
82
- self._socket.connect((self.descriptor.address, self.descriptor.port))
83
- except OSError as e: # TODO : Maybe change the exception ?
84
- self._logger.error(f"Failed to open adapter {self.descriptor} : {e}")
64
+ def open(self):
65
+ if self._status == AdapterBackendStatus.CONNECTED:
66
+ self._logger.warning(f"Adapter {self.descriptor} already openend")
67
+ return
68
+
69
+ if self.descriptor.port is None:
70
+ raise AdapterConfigurationError("Cannot open adapter without specifying a port")
71
+
72
+ if self._socket is None:
73
+ if self.descriptor.transport == IPDescriptor.Transport.TCP:
74
+ self._socket = cast(
75
+ _socket.socket,
76
+ socket.socket(socket.AF_INET, socket.SOCK_STREAM),
77
+ )
78
+ elif self.descriptor.transport == IPDescriptor.Transport.UDP:
79
+ self._socket = cast(
80
+ _socket.socket, socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
81
+ )
85
82
  else:
86
- self._status = AdapterBackendStatus.CONNECTED
87
- self._logger.info(f"IP Adapter {self.descriptor} opened")
88
- output = True
83
+ raise AdapterConfigurationError(
84
+ f"Invalid transport protocol : {self.descriptor.transport}"
85
+ )
86
+ try:
87
+ self._socket.settimeout(DEFAULT_ADAPTER_OPEN_TIMEOUT)
88
+ self._socket.connect((self.descriptor.address, self.descriptor.port))
89
+ except OSError as e:
90
+ self._logger.error(f"Failed to open adapter {self.descriptor} : {e}")
91
+ raise AdapterFailedToOpen(str(e))
89
92
  else:
90
- self._logger.info(f"Adapter {self.descriptor} already openend")
91
- output = True
92
-
93
- return output
93
+ self._status = AdapterBackendStatus.CONNECTED
94
+ self._logger.info(f"IP Adapter {self.descriptor} opened")
94
95
 
95
96
  def close(self) -> bool:
96
97
  super().close()
@@ -118,14 +119,16 @@ class IPBackend(AdapterBackend):
118
119
  self._logger.error(f"Cannot write to closed adapter {self.descriptor}")
119
120
  return False
120
121
  try:
121
- self._socket.send(data)
122
- except (BrokenPipeError, OSError) as e:
122
+ ok = self._socket.send(data) == len(data)
123
+ except (BrokenPipeError, OSError):
123
124
  # Socket has been disconnected by the remote peer
124
- self._logger.error(f"Failed to write to adapter {self.descriptor} ({e})")
125
+ ok = False
126
+
127
+ if not ok:
128
+ self._logger.error(f"Failed to write to adapter {self.descriptor}")
125
129
  self.close()
126
- return False
127
- else:
128
- return True
130
+
131
+ return ok
129
132
 
130
133
  def _socket_read(self) -> Fragment:
131
134
  # This function is called only if the socket was ready
@@ -7,9 +7,10 @@
7
7
  import time
8
8
 
9
9
  import serial
10
- from serial.serialutil import PortNotOpenError
10
+ from serial.serialutil import PortNotOpenError, SerialException
11
11
 
12
12
  from syndesi.tools.backend_api import AdapterBackendStatus, Fragment
13
+ from syndesi.tools.errors import AdapterConfigurationError, AdapterFailedToOpen
13
14
 
14
15
  from .adapter_backend import AdapterBackend, HasFileno
15
16
  from .descriptors import SerialPortDescriptor
@@ -31,8 +32,6 @@ class SerialPortBackend(AdapterBackend):
31
32
  self._port: serial.Serial | None = None
32
33
  self._rts_cts = False
33
34
 
34
- self.open()
35
-
36
35
  def set_baudrate(self, baudrate: int) -> None:
37
36
  """
38
37
  Set baudrate
@@ -72,27 +71,33 @@ class SerialPortBackend(AdapterBackend):
72
71
  self.close()
73
72
  self.open()
74
73
 
75
- def open(self) -> bool:
74
+ def open(self) -> None:
76
75
  if self.descriptor.baudrate is None:
77
- raise ValueError("Baudrate must be set, please use set_baudrate")
76
+ raise AdapterConfigurationError("Baudrate must be set, please use set_baudrate")
78
77
 
79
78
  if self._port is None:
80
- self._port = serial.Serial(
81
- port=self.descriptor.port,
82
- baudrate=self.descriptor.baudrate,
83
- rtscts=self._rts_cts,
84
- )
79
+ try:
80
+ self._port = serial.Serial(
81
+ port=self.descriptor.port,
82
+ baudrate=self.descriptor.baudrate,
83
+ rtscts=self._rts_cts,
84
+ )
85
+ except SerialException as e:
86
+ if 'No such file' in str(e):
87
+ raise AdapterFailedToOpen(f"No such file or directory '{self.descriptor.port}'") from e
88
+ else:
89
+ raise AdapterFailedToOpen('Unknown error') from e
90
+
85
91
  elif not self._port.isOpen(): # type: ignore
86
92
  self._port.open()
87
93
 
88
94
  if self._port.isOpen(): # type: ignore
89
95
  self._logger.info(f"Adapter {self.descriptor} opened")
90
96
  self._status = AdapterBackendStatus.CONNECTED
91
- return True
92
97
  else:
93
98
  self._logger.error(f"Failed to open adapter {self.descriptor}")
94
99
  self._status = AdapterBackendStatus.DISCONNECTED
95
- return False
100
+ raise AdapterFailedToOpen('Unknown error')
96
101
 
97
102
  def close(self) -> bool:
98
103
  super().close()
@@ -63,9 +63,12 @@ class StopConditionBackend:
63
63
 
64
64
 
65
65
  class TerminationBackend(StopConditionBackend):
66
- def __init__(self, sequence: bytes) -> None:
66
+ def __init__(self, sequence: bytes | str) -> None:
67
67
  super().__init__()
68
- self._sequence = sequence
68
+ if isinstance(sequence, str):
69
+ self._sequence = sequence.encode('utf-8')
70
+ else:
71
+ self._sequence = sequence
69
72
  self._sequence_found_length = 0
70
73
 
71
74
  def initiate_read(self) -> None:
@@ -210,10 +213,10 @@ def stop_condition_to_backend(stop_condition: StopCondition) -> StopConditionBac
210
213
  if isinstance(stop_condition, Termination):
211
214
  return TerminationBackend(stop_condition.sequence)
212
215
  elif isinstance(stop_condition, Length):
213
- return LengthBackend(stop_condition.N)
216
+ return LengthBackend(stop_condition.n)
214
217
  elif isinstance(stop_condition, Continuation):
215
- return ContinuationBackend(stop_condition.continuation)
218
+ return ContinuationBackend(stop_condition.time)
216
219
  elif isinstance(stop_condition, Total):
217
- return TotalBackend(stop_condition.total)
220
+ return TotalBackend(stop_condition.time)
218
221
  else:
219
222
  raise RuntimeError(f"Invalid stop condition : {stop_condition}")
@@ -16,7 +16,7 @@ from typing import TYPE_CHECKING
16
16
  from ...tools.backend_api import AdapterBackendStatus, Fragment
17
17
  from .adapter_backend import (
18
18
  AdapterBackend,
19
- AdapterDisconnected,
19
+ AdapterDisconnectedSignal,
20
20
  AdapterSignal,
21
21
  HasFileno,
22
22
  )
@@ -143,7 +143,7 @@ class VisaBackend(AdapterBackend):
143
143
  self._notify_recv.recv(1)
144
144
  if not self._event_queue.empty():
145
145
  event = self._event_queue.get()
146
- if isinstance(event, AdapterDisconnected):
146
+ if isinstance(event, AdapterDisconnectedSignal):
147
147
  return Fragment(b"", None)
148
148
 
149
149
  with self._fragment_lock:
@@ -181,7 +181,7 @@ class VisaBackend(AdapterBackend):
181
181
  # Tell the session that there's data (write to a virtual socket)
182
182
  self._notify_send.send(b"1")
183
183
  except (TypeError, pyvisa.InvalidSession, BrokenPipeError):
184
- event_queue.put(AdapterDisconnected())
184
+ event_queue.put(AdapterDisconnectedSignal())
185
185
  self._notify_send.send(b"1")
186
186
  with self._stop_lock:
187
187
  if self.stop:
syndesi/adapters/ip.py CHANGED
@@ -1,10 +1,10 @@
1
1
  # File : ip.py
2
2
  # Author : Sébastien Deriaz
3
3
  # License : GPL
4
- #
5
- # IP adapter, communicates with TCP or UDP
6
-
7
4
 
5
+ """
6
+ IP adapter, communicates with TCP or UDP
7
+ """
8
8
  from collections.abc import Callable
9
9
  from types import EllipsisType
10
10
 
@@ -18,10 +18,33 @@ from .timeout import Timeout
18
18
 
19
19
  # TODO : Server ? create an adapter from a socket ?
20
20
 
21
- # TODO : Manage opening and closing, modes ? open at instance or at write/read ? close after read ? error if already opened before / strict mode ?
21
+ # TODO : Manage opening and closing, modes ? open at instance or at write/read ?
22
+ # close after read ? error if already opened before / strict mode ?
22
23
 
23
24
 
24
25
  class IP(Adapter):
26
+ """
27
+ IP Adapter, allows for communication with IP devices through UDP or TCP
28
+
29
+ Parameters
30
+ ----------
31
+ address : str
32
+ IP description
33
+ port : int
34
+ IP port
35
+ transport : str
36
+ 'TCP' or 'UDP'
37
+ timeout : Timeout | float
38
+ Specify communication timeout
39
+ stop_condition : StopCondition
40
+ Specify a read stop condition (None by default)
41
+ auto_open : bool
42
+ Automatically open the adapter
43
+ socket : socket.socket
44
+ Specify a custom socket, this is reserved for server application
45
+
46
+
47
+ """
25
48
  DEFAULT_PROTOCOL = IPDescriptor.Transport.TCP
26
49
 
27
50
  def __init__(
@@ -29,6 +52,7 @@ class IP(Adapter):
29
52
  address: str,
30
53
  port: int | None = None,
31
54
  transport: str = DEFAULT_PROTOCOL.value,
55
+ *,
32
56
  timeout: Timeout | NumberLike | None | EllipsisType = ...,
33
57
  stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
34
58
  alias: str = "",
@@ -39,25 +63,7 @@ class IP(Adapter):
39
63
  backend_port: int | None = None,
40
64
  ):
41
65
  """
42
- IP adapter
43
-
44
- Parameters
45
- ----------
46
- address : str
47
- IP description
48
- port : int
49
- IP port
50
- transport : str
51
- 'TCP' or 'UDP'
52
- timeout : Timeout | float
53
- Specify communication timeout
54
- stop_condition : StopCondition
55
- Specify a read stop condition (None by default)
56
- auto_open : bool
57
- Automatically open the adapter
58
- socket : socket.socket
59
- Specify a custom socket, this is reserved for server application
60
-
66
+ Instanciate new IP adapter
61
67
  """
62
68
  super().__init__(
63
69
  descriptor=IPDescriptor(
@@ -107,4 +113,4 @@ class IP(Adapter):
107
113
  transport : str | IPDescriptor.Transport
108
114
  """
109
115
  if self.descriptor.transport is None:
110
- self.descriptor.transport = IPDescriptor.Transport(transport)
116
+ self.descriptor.transport = IPDescriptor.Transport(transport)
@@ -91,12 +91,18 @@
91
91
  # self._logger.info("Adapter closed !")
92
92
  # self._opened = False
93
93
 
94
- # def get_client(self, stop_condition : StopConditionBackend = None, timeout : Timeout = None) -> IP:
94
+ # def get_client(self,
95
+ # stop_condition : StopConditionBackend = None,
96
+ # timeout : Timeout = None) -> IP:
95
97
  # """
96
98
  # Wait for a client to connect to the server and return the corresponding adapter
97
99
  # """
98
100
  # if not self._opened:
99
101
  # raise RuntimeError("open() must be called before getting client")
100
102
  # client_socket, address = self._socket.accept()
101
- # default_timeout = Timeout(response=None, continuation=IP.DEFAULT_CONTINUATION_TIMEOUT, total=None)
102
- # return IP(_socket=client_socket, address=address, stop_condition=stop_condition, timeout=timeout_fuse(timeout, default_timeout))
103
+ # default_timeout = Timeout(response=None,
104
+ # continuation=IP.DEFAULT_CONTINUATION_TIMEOUT,
105
+ # total=None)
106
+ # return IP(_socket=client_socket, address=address,
107
+ # stop_condition=stop_condition,
108
+ # timeout=timeout_fuse(timeout, default_timeout))
@@ -2,6 +2,12 @@
2
2
  # Author : Sébastien Deriaz
3
3
  # License : GPL
4
4
 
5
+ """
6
+ SerialPort module, allows communication with serial devices using
7
+ the OS layers (COMx, /dev/ttyUSBx or /dev/ttyACMx)
8
+
9
+ """
10
+
5
11
  from collections.abc import Callable
6
12
  from types import EllipsisType
7
13
 
@@ -15,10 +21,21 @@ from .timeout import Timeout
15
21
 
16
22
 
17
23
  class SerialPort(Adapter):
24
+ """
25
+ Serial communication adapter
26
+
27
+ Parameters
28
+ ----------
29
+ port : str
30
+ Serial port (COMx or ttyACMx)
31
+ baudrate : int
32
+ Baudrate
33
+ """
18
34
  def __init__(
19
35
  self,
20
36
  port: str,
21
37
  baudrate: int | None = None,
38
+ *,
22
39
  timeout: Timeout | NumberLike | None | EllipsisType = ...,
23
40
  stop_conditions: StopCondition | list[StopCondition] | EllipsisType = ...,
24
41
  alias: str = "",
@@ -28,12 +45,7 @@ class SerialPort(Adapter):
28
45
  backend_port: int | None = None,
29
46
  ) -> None:
30
47
  """
31
- Serial communication adapter
32
-
33
- Parameters
34
- ----------
35
- port : str
36
- Serial port (COMx or ttyACMx)
48
+ Instanciate new SerialPort adapter
37
49
  """
38
50
  descriptor = SerialPortDescriptor(port, baudrate)
39
51
  super().__init__(
@@ -48,7 +60,8 @@ class SerialPort(Adapter):
48
60
  self.descriptor: SerialPortDescriptor
49
61
 
50
62
  self._logger.info(
51
- f"Setting up SerialPort adapter {self.descriptor}, timeout={timeout} and stop_conditions={self._stop_conditions}"
63
+ f"Setting up SerialPort adapter {self.descriptor}, \
64
+ timeout={timeout} and stop_conditions={self._stop_conditions}"
52
65
  )
53
66
 
54
67
  self.open()
@@ -2,89 +2,113 @@
2
2
  # Author : Sébastien Deriaz
3
3
  # License : GPL
4
4
 
5
- from abc import abstractmethod
5
+ """
6
+ Stop-condition module
7
+
8
+ This is the frontend of the stop-conditions, the part that is imported by the user
9
+ """
10
+
11
+ #from abc import abstractmethod
6
12
  from enum import Enum
13
+ from dataclasses import dataclass
14
+
7
15
 
8
16
  class StopConditionType(Enum):
17
+ """
18
+ Stop-condition type
19
+ """
9
20
  TERMINATION = "termination"
10
21
  LENGTH = "length"
11
22
  TIMEOUT = "timeout"
12
23
 
24
+ @dataclass
13
25
  class StopCondition:
14
- @abstractmethod
15
- def type(self) -> StopConditionType:
16
- pass
17
-
18
- def __init__(self) -> None:
19
- """
20
- A condition to stop reading from a device
21
-
22
- Cannot be used on its own
23
- """
24
-
25
-
26
- class Termination(StopCondition):
27
- def __init__(self, sequence: bytes | str) -> None:
28
- """
29
- Stop reading once the desired sequence is detected
30
-
31
- Parameters
32
- ----------
33
- sequence : bytes
34
- """
35
- self.sequence: bytes
36
- if isinstance(sequence, str):
37
- self.sequence = sequence.encode("utf-8")
38
- elif isinstance(sequence, bytes):
39
- self.sequence = sequence
40
- else:
41
- raise ValueError(f"Invalid termination sequence type : {type(sequence)}")
26
+ """
27
+ Stop-condition base class, cannot be used on its own
28
+ """
29
+ # @abstractmethod
30
+ # def type(self) -> StopConditionType:
31
+ # pass
42
32
 
43
33
  def __repr__(self) -> str:
44
34
  return self.__str__()
45
35
 
36
+ @dataclass
37
+ class Termination(StopCondition):
38
+ """
39
+ Termination stop-condition, used to stop when a specified sequence is received
40
+
41
+ Parameters
42
+ ----------
43
+ sequence : bytes | str
44
+ """
45
+ #TYPE = StopConditionType.TERMINATION
46
+ sequence : bytes | str
47
+ # def __init__(self, sequence: bytes | str) -> None:
48
+ # """
49
+ # Instanciate a new Termination class
50
+ # """
51
+ # self.sequence: bytes
52
+ # if isinstance(sequence, str):
53
+ # self.sequence = sequence.encode("utf-8")
54
+ # elif isinstance(sequence, bytes):
55
+ # self.sequence = sequence
56
+ # else:
57
+ # raise ValueError(f"Invalid termination sequence type : {type(sequence)}")
58
+
46
59
  def __str__(self) -> str:
47
60
  return f"Termination({repr(self.sequence)})"
48
61
 
49
- def type(self) -> StopConditionType:
50
- return StopConditionType.TERMINATION
51
-
52
62
 
63
+ @dataclass
53
64
  class Length(StopCondition):
54
- def __init__(self, N: int) -> None:
55
- """
56
- Stop condition when the desired number of bytes is reached or passed
57
-
58
- Parameters
59
- ----------
60
- N : int
61
- Number of bytes
62
- """
63
- self.N = N
64
-
65
- def __repr__(self) -> str:
66
- return self.__str__()
65
+ """
66
+ Length stop-condition, used to stop when the specified number of bytes (or more) have been read
67
+
68
+ Parameters
69
+ ----------
70
+ N : int
71
+ Number of bytes
72
+ """
73
+ #TYPE = StopConditionType.LENGTH
74
+ n : int
67
75
 
68
76
  def __str__(self) -> str:
69
- return f"Length({self.N})"
70
-
71
- def type(self) -> StopConditionType:
72
- return StopConditionType.LENGTH
77
+ return f"Length({self.n})"
73
78
 
79
+ # def type(self) -> StopConditionType:
80
+ # return StopConditionType.LENGTH
74
81
 
82
+ @dataclass
75
83
  class Continuation(StopCondition):
76
- def __init__(self, time: float) -> None:
77
- super().__init__()
78
- self.continuation = time
84
+ """
85
+ Continuation stop-condition, used to stop reading when data has already been received
86
+ and nothing has been received since then for the specified amount of time
79
87
 
80
- def type(self) -> StopConditionType:
81
- return StopConditionType.TIMEOUT
88
+ Parameters
89
+ ----------
90
+ time : float
91
+ """
92
+ #TYPE = StopConditionType.TIMEOUT
93
+ time : float
82
94
 
83
95
 
84
- class Total(StopCondition):
85
- def __init__(self, time: float) -> None:
86
- super().__init__()
87
- self.total = time
88
96
 
89
- def type(self) -> StopConditionType:
90
- return StopConditionType.TIMEOUT
97
+ # def type(self) -> StopConditionType:
98
+ # return StopConditionType.TIMEOUT
99
+
100
+ @dataclass
101
+ class Total(StopCondition):
102
+ """
103
+ Total stop-condition, used to stop reading when data has already been received
104
+ and the total read time exceeds the specified amount
105
+
106
+ """
107
+ #TYPE = StopConditionType.TIMEOUT
108
+ time : float
109
+ # def __init__(self, time: float) -> None:
110
+ # super().__init__()
111
+ # self.total = time
112
+
113
+ # def type(self) -> StopConditionType:
114
+ # return StopConditionType.TIMEOUT
@@ -8,6 +8,7 @@ from typing import Any, Protocol
8
8
 
9
9
  from ..tools.types import NumberLike, is_number
10
10
 
11
+
11
12
  class TimeoutAction(Enum):
12
13
  ERROR = "error"
13
14
  RETURN_EMPTY = "return_empty"
syndesi/adapters/visa.py CHANGED
@@ -1,8 +1,10 @@
1
1
  # File : visa.py
2
2
  # Author : Sébastien Deriaz
3
3
  # License : GPL
4
- #
5
- # VISA adatper, uses a VISA backend like pyvisa-py or NI to communicate with instruments
4
+
5
+ """
6
+ VISA adatper, uses a VISA backend like pyvisa-py or NI to communicate with instruments
7
+ """
6
8
 
7
9
  from collections.abc import Callable
8
10
  from types import EllipsisType
@@ -16,9 +18,15 @@ from .timeout import Timeout
16
18
 
17
19
 
18
20
  class Visa(Adapter):
21
+ """
22
+ VISA Adapter, allows for communication with VISA-compatible devices.
23
+ It uses pyvisa under the hood
24
+
25
+ """
19
26
  def __init__(
20
27
  self,
21
28
  descriptor: str,
29
+ *,
22
30
  alias: str = "",
23
31
  stop_conditions: StopCondition | EllipsisType | list[StopCondition] = ...,
24
32
  timeout: None | float | Timeout | EllipsisType = ...,
@@ -28,7 +36,7 @@ class Visa(Adapter):
28
36
  backend_port: int | None = None,
29
37
  ) -> None:
30
38
  super().__init__(
31
- VisaDescriptor.from_string(descriptor),
39
+ descriptor=VisaDescriptor.from_string(descriptor),
32
40
  alias=alias,
33
41
  stop_conditions=stop_conditions,
34
42
  timeout=timeout,
syndesi/cli/console.py CHANGED
@@ -225,4 +225,4 @@ class Shell:
225
225
  def ask(self, question: str, callback: Callable[[str], None]) -> None:
226
226
  self.ask_event.set()
227
227
  self.ask_callback = callback
228
- self.reprompt(question)
228
+ self.reprompt(question)
syndesi/cli/shell.py CHANGED
@@ -8,7 +8,7 @@ from enum import Enum
8
8
 
9
9
  from syndesi.adapters.adapter import Adapter
10
10
  from syndesi.adapters.backend.adapter_backend import (
11
- AdapterDisconnected,
11
+ AdapterDisconnectedSignal,
12
12
  AdapterReadPayload,
13
13
  AdapterSignal,
14
14
  )
@@ -214,7 +214,7 @@ class AdapterShell:
214
214
  self._protocol.write(command)
215
215
 
216
216
  def event(self, signal: AdapterSignal) -> None:
217
- if isinstance(signal, AdapterDisconnected):
217
+ if isinstance(signal, AdapterDisconnectedSignal):
218
218
 
219
219
  def f(answer: str) -> None:
220
220
  if answer.lower() == "y":