cgse-common 0.17.0__py3-none-any.whl → 0.17.1__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cgse-common
3
- Version: 0.17.0
3
+ Version: 0.17.1
4
4
  Summary: Software framework to support hardware testing
5
5
  Author: IvS KU Leuven
6
6
  Maintainer-email: Rik Huygen <rik.huygen@kuleuven.be>, Sara Regibo <sara.regibo@kuleuven.be>
@@ -3,12 +3,12 @@ cgse_common/cgse.py,sha256=S8MxwJcSzqYNR0wirEscQw5CTg89AKORa8-NHRdrxJM,6642
3
3
  cgse_common/settings.yaml,sha256=PS8HOoxbhwVoQ7zzDtZyhx25RZB6SGq3uXNuJTgtRIw,443
4
4
  egse/bits.py,sha256=cg6diLN2IwNtnrlZyLgXPfDf9ttcHzS2A7Tjwlwc-lQ,12498
5
5
  egse/calibration.py,sha256=a5JDaXTC6fMwQ1M-qrwNO31Ass-yYSXxDQUK_PPsZg4,8818
6
- egse/config.py,sha256=qNW3uvwuEV9VSjiaoQfM_svBYfz4Kwxd1-jv1eTGqyw,9530
6
+ egse/config.py,sha256=M821_d1IfNT17J3tt_TDjh4bGJgGiYviGBYR0I5v5LA,9639
7
7
  egse/counter.py,sha256=7UwBeTAu213xdNdGAOYpUWNQ4jD4yVM1bOG10Ax4UFs,5097
8
8
  egse/decorators.py,sha256=RT_-TmcHLN3oqha-1xn-YbqT1tEtKA84zr0Qu1KFyKo,27176
9
9
  egse/device.py,sha256=Ga5MNE96ERuPLDzmb0HF7UfjrTqfp0f_r3NDVZY9l28,13595
10
10
  egse/dicts.py,sha256=dUAq7PTPvs73OrZb2Fh3loxvYv4ifUiK6bBcgrFU77Y,3972
11
- egse/env.py,sha256=iJV4gKCd1wFWDMsJbdjtgZJSE4Gr8hBSD4YLTN8xKfM,31630
11
+ egse/env.py,sha256=2ZeEOyVUp9IANy4S0XK53KUMohelbct7S3lR6iWpeks,31704
12
12
  egse/exceptions.py,sha256=QB3MZRJizecWOj1cPbvG0UcIqFn7NRJ6rw1xtdNSFxw,1225
13
13
  egse/heartbeat.py,sha256=2SeZzX3tWFog1rgYThX-iaZPwHYq8TVma2ll7r624Eg,3039
14
14
  egse/hk.py,sha256=AumSpB8SYXes75CB2iiKXfLkMK5IkVDHITFKrf8IT6g,32010
@@ -25,12 +25,12 @@ egse/ratelimit.py,sha256=JdJxD6UIi9LYngKEsG9zh8bTE9r_56D4EZCnp_fkrI0,9161
25
25
  egse/reload.py,sha256=PzOE0m1tmcNcQPVFH8orMe_cMoQIIiH9Gw2anpQTC40,4717
26
26
  egse/resource.py,sha256=kzNI6kJOE6Jd5QKJs2MkVAycUpwpOTLi1qydh3NSRng,15345
27
27
  egse/response.py,sha256=F04uqOYv1ClpHgDLYZlKTuOCSldHs5TezI_4x6zf2Fw,2717
28
- egse/scpi.py,sha256=geIHxoolItjPO1LUFVNzL1c9QxpmxcyVwEV9BIi2ftI,15722
29
- egse/settings.py,sha256=s89xqvS31MOBq7p1dTOj41ODnZnBNB35nHqfknJpqcc,15466
28
+ egse/scpi.py,sha256=4OxgNc7HhQKZ7Gsg_tYstQKw_o4BxH8LVslG_X5ecz8,15965
29
+ egse/settings.py,sha256=m95NuhLYdmRK4-SKZ4awhGp4X_6vCcb_yLvm7dmY-Dg,15656
30
30
  egse/settings.yaml,sha256=mz9O2QqmiptezsMvxJRLhnC1ROwIHENX0nbnhMaXUpE,190
31
31
  egse/setup.py,sha256=ezPYA3n1P3navdPR3qDxh0qJvZCzGl2bIREEP9n2w3Y,34116
32
32
  egse/signal.py,sha256=f5pyOiNW9iTSIxV_ce5stIfG0ub9MRbaekE85kQOVzs,7992
33
- egse/socketdevice.py,sha256=rsLJRm4AQhfO3VcM16Q9qwtPbKI-iynVlZqKZ3tc3Fk,14636
33
+ egse/socketdevice.py,sha256=7Q1DstV94pgilOD_e5BnqprTGcXi-XNijdLTw4m4dRY,14726
34
34
  egse/state.py,sha256=HdU2MFOlYRbawYRZmizV6Y8MgnZrUF0bx4fXaYU-M_s,3023
35
35
  egse/system.py,sha256=3aycoK15UvNdk2yxQ8hx4N-s2Ag4BqTTPQ8eFuJa3Ko,76111
36
36
  egse/task.py,sha256=ODSLE05f31CgWsSVcVFFq1WYUZrJMb1LioPTx6VM824,2804
@@ -39,7 +39,7 @@ egse/zmq_ser.py,sha256=YJFupsxuvhI8TJMeS2Hem9oMMcVmSBx0rZv93gvN-hA,3263
39
39
  egse/plugins/metrics/duckdb.py,sha256=E2eeNo3I7ajRuByodaYiPNvC0Zwyc7hsIlhr1W_eXdo,16148
40
40
  egse/plugins/metrics/influxdb.py,sha256=WnAqTWRkAyMSd7W2ASwUAIEwFborrv55iX-umceevFA,8162
41
41
  egse/plugins/metrics/timescaledb.py,sha256=Ug0NWDV1Ky2VeFY6tDZL9xg6AFgnAEh2F_llVPnlRBA,21191
42
- cgse_common-0.17.0.dist-info/METADATA,sha256=YIF0aWp-_8lG-Js0EVRZHUqVVVqG5uqspV2Nfsgwsew,3068
43
- cgse_common-0.17.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
- cgse_common-0.17.0.dist-info/entry_points.txt,sha256=xJsPRIDjtADVgd_oEDHVW10wS5LG30Ox_3brVKeyCGw,168
45
- cgse_common-0.17.0.dist-info/RECORD,,
42
+ cgse_common-0.17.1.dist-info/METADATA,sha256=DKZF-wlYPiRujjFleFHI1IIgWL2GdLDJ3ySq-gOK1xk,3068
43
+ cgse_common-0.17.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
+ cgse_common-0.17.1.dist-info/entry_points.txt,sha256=xJsPRIDjtADVgd_oEDHVW10wS5LG30Ox_3brVKeyCGw,168
45
+ cgse_common-0.17.1.dist-info/RECORD,,
egse/config.py CHANGED
@@ -154,13 +154,14 @@ def find_files(pattern: str, root: Path | str, in_dir: str = None) -> Generator[
154
154
  Returns:
155
155
  Paths of files matching pattern, from root.
156
156
  """
157
- root = Path(root).resolve()
157
+ root = Path(root).expanduser().resolve()
158
158
  if not root.is_dir():
159
159
  root = root.parent
160
160
  if not root.exists():
161
161
  raise ValueError(f"The root argument didn't resolve into a valid directory: {root}.")
162
162
 
163
- exclude_dirs = ("venv", "venv38", ".venv", ".nox", ".git", ".idea", ".DS_Store")
163
+ # FIXME: at some point we might want to make this configurable, through env?
164
+ exclude_dirs = ("venv", "venv38", ".venv", ".nox", ".git", ".idea", ".DS_Store", "__pycache__")
164
165
 
165
166
  for path, folders, files in os.walk(root):
166
167
  folders[:] = list(filter(lambda x: x not in exclude_dirs, folders))
egse/env.py CHANGED
@@ -678,6 +678,7 @@ def env_var(**kwargs: str | int | float | bool | None):
678
678
  else:
679
679
  os.environ[k] = v
680
680
 
681
+ setup_env.is_initialized = False
681
682
  setup_env()
682
683
 
683
684
  yield
@@ -689,6 +690,7 @@ def env_var(**kwargs: str | int | float | bool | None):
689
690
  else:
690
691
  os.environ[k] = v
691
692
 
693
+ setup_env.is_initialized = False
692
694
  setup_env()
693
695
 
694
696
 
egse/scpi.py CHANGED
@@ -15,6 +15,9 @@ DEFAULT_READ_TIMEOUT = 1.0 # seconds
15
15
  DEFAULT_CONNECT_TIMEOUT = 3.0 # seconds
16
16
  IDENTIFICATION_QUERY = "*IDN?"
17
17
 
18
+ SEPARATOR = b"\n"
19
+ SEPARATOR_STR = SEPARATOR.decode()
20
+
18
21
 
19
22
  class SCPICommand:
20
23
  """Base class for SCPI commands."""
@@ -57,7 +60,8 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
57
60
  id_validation: String that should appear in the device's identification response
58
61
  """
59
62
  super().__init__()
60
- self.device_name = device_name
63
+
64
+ self._device_name = device_name
61
65
  self.hostname = hostname
62
66
  self.port = port
63
67
  self.settings = settings or {}
@@ -77,6 +81,10 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
77
81
  def is_simulator(self) -> bool:
78
82
  return False
79
83
 
84
+ @property
85
+ def device_name(self) -> str:
86
+ return self._device_name
87
+
80
88
  async def initialize(self, commands: list[tuple[str, bool]] = None, reset_device: bool = False) -> list[str | None]:
81
89
  """Initialize the device with optional reset and command sequence.
82
90
 
@@ -113,7 +121,7 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
113
121
  responses = []
114
122
 
115
123
  if reset_device:
116
- logger.info(f"Resetting the {self.device_name}...")
124
+ logger.info(f"Resetting the {self._device_name}...")
117
125
  await self.write("*RST") # this also resets the user-defined buffer
118
126
 
119
127
  for cmd, expects_response in commands:
@@ -140,47 +148,47 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
140
148
  async with self._connect_lock:
141
149
  # Sanity checks
142
150
  if self._is_connection_open:
143
- logger.warning(f"{self.device_name}: Trying to connect to an already connected device.")
151
+ logger.warning(f"{self._device_name}: Trying to connect to an already connected device.")
144
152
  return
145
153
 
146
154
  if not self.hostname:
147
- raise ValueError(f"{self.device_name}: Hostname is not initialized.")
155
+ raise ValueError(f"{self._device_name}: Hostname is not initialized.")
148
156
 
149
157
  if not self.port:
150
- raise ValueError(f"{self.device_name}: Port number is not initialized.")
158
+ raise ValueError(f"{self._device_name}: Port number is not initialized.")
151
159
 
152
160
  # Attempt to establish a connection
153
161
  try:
154
- logger.debug(f'Connecting to {self.device_name} at "{self.hostname}" using port {self.port}')
162
+ logger.debug(f'Connecting to {self._device_name} at "{self.hostname}" using port {self.port}')
155
163
 
156
164
  connect_task = asyncio.open_connection(self.hostname, self.port)
157
165
  self._reader, self._writer = await asyncio.wait_for(connect_task, timeout=self.connect_timeout)
158
166
 
159
167
  self._is_connection_open = True
160
168
 
161
- logger.debug(f"Successfully connected to {self.device_name}.")
169
+ logger.debug(f"Successfully connected to {self._device_name}.")
162
170
 
163
171
  except asyncio.TimeoutError as exc:
164
172
  raise DeviceTimeoutError(
165
- self.device_name, f"Connection to {self.hostname}:{self.port} timed out"
173
+ self._device_name, f"Connection to {self.hostname}:{self.port} timed out"
166
174
  ) from exc
167
175
  except ConnectionRefusedError as exc:
168
176
  raise DeviceConnectionError(
169
- self.device_name, f"Connection refused to {self.hostname}:{self.port}"
177
+ self._device_name, f"Connection refused to {self.hostname}:{self.port}"
170
178
  ) from exc
171
179
  except socket.gaierror as exc:
172
- raise DeviceConnectionError(self.device_name, f"Address resolution error for {self.hostname}") from exc
180
+ raise DeviceConnectionError(self._device_name, f"Address resolution error for {self.hostname}") from exc
173
181
  except socket.herror as exc:
174
- raise DeviceConnectionError(self.device_name, f"Host address error for {self.hostname}") from exc
182
+ raise DeviceConnectionError(self._device_name, f"Host address error for {self.hostname}") from exc
175
183
  except OSError as exc:
176
- raise DeviceConnectionError(self.device_name, f"OS error: {exc}") from exc
184
+ raise DeviceConnectionError(self._device_name, f"OS error: {exc}") from exc
177
185
 
178
186
  # Validate device identity if requested
179
187
  if self.id_validation:
180
188
  logger.debug("Validating connection..")
181
189
  if not await self.is_connected():
182
190
  await self.disconnect()
183
- raise DeviceConnectionError(self.device_name, "Device connected but failed identity verification")
191
+ raise DeviceConnectionError(self._device_name, "Device connected but failed identity verification")
184
192
 
185
193
  async def disconnect(self) -> None:
186
194
  """Disconnect from the device asynchronously.
@@ -191,14 +199,14 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
191
199
  async with self._connect_lock:
192
200
  try:
193
201
  if self._is_connection_open and self._writer is not None:
194
- logger.debug(f"Disconnecting from {self.device_name} at {self.hostname}")
202
+ logger.debug(f"Disconnecting from {self._device_name} at {self.hostname}")
195
203
  self._writer.close()
196
204
  await self._writer.wait_closed()
197
205
  self._writer = None
198
206
  self._reader = None
199
207
  self._is_connection_open = False
200
208
  except Exception as exc:
201
- raise DeviceConnectionError(self.device_name, f"Could not close connection: {exc}") from exc
209
+ raise DeviceConnectionError(self._device_name, f"Could not close connection: {exc}") from exc
202
210
 
203
211
  async def reconnect(self) -> None:
204
212
  """Reconnect to the device asynchronously."""
@@ -222,7 +230,7 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
222
230
  # Validate the response if validation string is provided
223
231
  if self.id_validation and self.id_validation not in id_response:
224
232
  logger.error(
225
- f"{self.device_name}: Device did not respond correctly to identification query. "
233
+ f"{self._device_name}: Device did not respond correctly to identification query. "
226
234
  f'Expected "{self.id_validation}" in response, got: {id_response}'
227
235
  )
228
236
  await self.disconnect()
@@ -231,7 +239,7 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
231
239
  return True
232
240
 
233
241
  except DeviceError as exc:
234
- logger.error(f"{self.device_name}: Connection test failed: {exc}", exc_info=True)
242
+ logger.error(f"{self._device_name}: Connection test failed: {exc}", exc_info=True)
235
243
  await self.disconnect()
236
244
  return False
237
245
 
@@ -248,20 +256,20 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
248
256
  async with self._io_lock:
249
257
  try:
250
258
  if not self._is_connection_open or self._writer is None:
251
- raise DeviceConnectionError(self.device_name, "Device not connected, use connect() first")
259
+ raise DeviceConnectionError(self._device_name, "Device not connected, use connect() first")
252
260
 
253
- # Ensure command ends with newline
254
- if not command.endswith("\n"):
255
- command += "\n"
261
+ # Ensure command ends with the proper separator or terminator
262
+ if not command.endswith(SEPARATOR_STR):
263
+ command += SEPARATOR_STR
256
264
 
257
265
  logger.info(f"-----> {command}")
258
266
  self._writer.write(command.encode())
259
267
  await self._writer.drain()
260
268
 
261
269
  except asyncio.TimeoutError as exc:
262
- raise DeviceTimeoutError(self.device_name, "Write operation timed out") from exc
270
+ raise DeviceTimeoutError(self._device_name, "Write operation timed out") from exc
263
271
  except (ConnectionError, OSError) as exc:
264
- raise DeviceConnectionError(self.device_name, f"Communication error: {exc}") from exc
272
+ raise DeviceConnectionError(self._device_name, f"Communication error: {exc}") from exc
265
273
 
266
274
  async def read(self) -> bytes:
267
275
  """
@@ -276,7 +284,7 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
276
284
  """
277
285
  async with self._io_lock:
278
286
  if not self._is_connection_open or self._reader is None:
279
- raise DeviceConnectionError(self.device_name, "Device not connected, use connect() first")
287
+ raise DeviceConnectionError(self._device_name, "Device not connected, use connect() first")
280
288
 
281
289
  try:
282
290
  # First, small delay to allow device to prepare response
@@ -285,19 +293,19 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
285
293
  # Try to read until newline (common SCPI terminator)
286
294
  try:
287
295
  response = await asyncio.wait_for(
288
- self._reader.readuntil(separator=b"\n"), timeout=self.read_timeout
296
+ self._reader.readuntil(separator=SEPARATOR), timeout=self.read_timeout
289
297
  )
290
298
  logger.info(f"<----- {response}")
291
299
  return response
292
300
 
293
301
  except asyncio.IncompleteReadError as exc:
294
302
  # Connection closed before receiving full response
295
- logger.warning(f"{self.device_name}: Incomplete read, got {len(exc.partial)} bytes")
296
- return exc.partial if exc.partial else b"\r\n"
303
+ logger.warning(f"{self._device_name}: Incomplete read, got {len(exc.partial)} bytes")
304
+ return exc.partial if exc.partial else SEPARATOR
297
305
 
298
306
  except asyncio.LimitOverrunError:
299
307
  # Response too large for buffer
300
- logger.warning(f"{self.device_name}: Response exceeded buffer limits")
308
+ logger.warning(f"{self._device_name}: Response exceeded buffer limits")
301
309
  # Fall back to reading a large chunk
302
310
  return await asyncio.wait_for(
303
311
  self._reader.read(8192), # Larger buffer for exceptional cases
@@ -305,9 +313,9 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
305
313
  )
306
314
 
307
315
  except asyncio.TimeoutError as exc:
308
- raise DeviceTimeoutError(self.device_name, "Read operation timed out") from exc
316
+ raise DeviceTimeoutError(self._device_name, "Read operation timed out") from exc
309
317
  except Exception as exc:
310
- raise DeviceConnectionError(self.device_name, f"Read error: {exc}") from exc
318
+ raise DeviceConnectionError(self._device_name, f"Read error: {exc}") from exc
311
319
 
312
320
  async def trans(self, command: str) -> bytes:
313
321
  """
@@ -328,11 +336,11 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
328
336
  async with self._io_lock:
329
337
  try:
330
338
  if not self._is_connection_open or self._writer is None:
331
- raise DeviceConnectionError(self.device_name, "Device not connected, use connect() first")
339
+ raise DeviceConnectionError(self._device_name, "Device not connected, use connect() first")
332
340
 
333
341
  # Ensure command ends with newline
334
- if not command.endswith("\n"):
335
- command += "\n"
342
+ if not command.endswith(SEPARATOR_STR):
343
+ command += SEPARATOR_STR
336
344
 
337
345
  logger.info(f"-----> {command}")
338
346
  self._writer.write(command.encode())
@@ -344,19 +352,19 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
344
352
  # Try to read until newline (common SCPI terminator)
345
353
  try:
346
354
  response = await asyncio.wait_for(
347
- self._reader.readuntil(separator=b"\n"), timeout=self.read_timeout
355
+ self._reader.readuntil(separator=SEPARATOR), timeout=self.read_timeout
348
356
  )
349
357
  logger.info(f"<----- {response}")
350
358
  return response
351
359
 
352
360
  except asyncio.IncompleteReadError as exc:
353
361
  # Connection closed before receiving full response
354
- logger.warning(f"{self.device_name}: Incomplete read, got {len(exc.partial)} bytes")
355
- return exc.partial if exc.partial else b"\r\n"
362
+ logger.warning(f"{self._device_name}: Incomplete read, got {len(exc.partial)} bytes")
363
+ return exc.partial if exc.partial else SEPARATOR
356
364
 
357
365
  except asyncio.LimitOverrunError:
358
366
  # Response too large for buffer
359
- logger.warning(f"{self.device_name}: Response exceeded buffer limits")
367
+ logger.warning(f"{self._device_name}: Response exceeded buffer limits")
360
368
  # Fall back to reading a large chunk
361
369
  return await asyncio.wait_for(
362
370
  self._reader.read(8192), # Larger buffer for exceptional cases
@@ -364,11 +372,11 @@ class AsyncSCPIInterface(AsyncDeviceInterface, AsyncDeviceTransport):
364
372
  )
365
373
 
366
374
  except asyncio.TimeoutError as exc:
367
- raise DeviceTimeoutError(self.device_name, "Communication timed out") from exc
375
+ raise DeviceTimeoutError(self._device_name, "Communication timed out") from exc
368
376
  except (ConnectionError, OSError) as exc:
369
- raise DeviceConnectionError(self.device_name, f"Communication error: {exc}") from exc
377
+ raise DeviceConnectionError(self._device_name, f"Communication error: {exc}") from exc
370
378
  except Exception as exc:
371
- raise DeviceConnectionError(self.device_name, f"Transaction error: {exc}") from exc
379
+ raise DeviceConnectionError(self._device_name, f"Transaction error: {exc}") from exc
372
380
 
373
381
  async def __aenter__(self):
374
382
  """Async context manager entry."""
egse/settings.py CHANGED
@@ -72,13 +72,14 @@ from typing import Any
72
72
 
73
73
  import yaml # This module is provided by the pip package PyYaml - pip install pyyaml
74
74
 
75
+ from egse.env import bool_env
75
76
  from egse.env import get_local_settings_env_name
76
77
  from egse.env import get_local_settings_path
77
78
  from egse.log import logger
78
79
  from egse.system import attrdict
79
80
  from egse.system import recursive_dict_update
80
81
 
81
- _HERE = Path(__file__).resolve().parent
82
+ VERBOSE_DEBUG = bool_env("VERBOSE_DEBUG")
82
83
 
83
84
 
84
85
  class SettingsError(Exception):
@@ -192,6 +193,9 @@ def load_local_settings(force: bool = False) -> attrdict:
192
193
  local_settings = attrdict()
193
194
 
194
195
  local_settings_path = get_local_settings_path()
196
+ if VERBOSE_DEBUG:
197
+ logger.debug(f"{get_local_settings_env_name()=}")
198
+ logger.debug(f"{local_settings_path=}")
195
199
 
196
200
  if local_settings_path:
197
201
  path = Path(local_settings_path).expanduser()
@@ -218,7 +222,8 @@ def read_configuration_file(filename: Path, *, force=False) -> dict:
218
222
  filename = str(filename)
219
223
 
220
224
  if force or not Settings.is_memoized(filename):
221
- logger.debug(f"Parsing YAML configuration file {filename}.")
225
+ if VERBOSE_DEBUG:
226
+ logger.debug(f"Parsing YAML configuration file {filename}.")
222
227
 
223
228
  with open(filename, "r") as stream:
224
229
  try:
egse/socketdevice.py CHANGED
@@ -8,6 +8,8 @@ import socket
8
8
  import time
9
9
  from typing import Optional
10
10
 
11
+ from egse.device import AsyncDeviceInterface
12
+ from egse.device import AsyncDeviceTransport
11
13
  from egse.device import DeviceConnectionError
12
14
  from egse.device import DeviceConnectionInterface
13
15
  from egse.device import DeviceTimeoutError
@@ -252,7 +254,7 @@ class SocketDevice(DeviceConnectionInterface, DeviceTransport):
252
254
  raise DeviceConnectionError(self.device_name, "Socket communication error.") from exc
253
255
 
254
256
 
255
- class AsyncSocketDevice(DeviceConnectionInterface, DeviceTransport):
257
+ class AsyncSocketDevice(AsyncDeviceInterface, AsyncDeviceTransport):
256
258
  """
257
259
  Async socket-backed device using asyncio streams.
258
260