cgse-common 0.17.0__tar.gz → 0.17.1__tar.gz
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.
- {cgse_common-0.17.0 → cgse_common-0.17.1}/PKG-INFO +1 -1
- {cgse_common-0.17.0 → cgse_common-0.17.1}/pyproject.toml +4 -1
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/config.py +3 -2
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/env.py +2 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/scpi.py +48 -40
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/settings.py +7 -2
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/socketdevice.py +3 -1
- {cgse_common-0.17.0 → cgse_common-0.17.1}/.gitignore +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/README.md +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/justfile +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/noxfile.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/service_registry.db +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/cgse_common/__init__.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/cgse_common/cgse.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/cgse_common/settings.yaml +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/bits.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/calibration.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/counter.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/decorators.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/device.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/dicts.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/exceptions.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/heartbeat.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/hk.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/log.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/metrics.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/observer.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/obsid.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/persistence.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/plugin.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/plugins/metrics/duckdb.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/plugins/metrics/influxdb.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/plugins/metrics/timescaledb.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/process.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/py.typed +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/randomwalk.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/ratelimit.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/reload.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/resource.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/response.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/settings.yaml +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/setup.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/signal.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/state.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/system.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/task.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/version.py +0 -0
- {cgse_common-0.17.0 → cgse_common-0.17.1}/src/egse/zmq_ser.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "cgse-common"
|
|
3
|
-
version = "0.17.
|
|
3
|
+
version = "0.17.1"
|
|
4
4
|
description = "Software framework to support hardware testing"
|
|
5
5
|
authors = [
|
|
6
6
|
{name = "IvS KU Leuven"}
|
|
@@ -64,6 +64,9 @@ log_cli_level = "DEBUG"
|
|
|
64
64
|
filterwarnings = [
|
|
65
65
|
"ignore::DeprecationWarning"
|
|
66
66
|
]
|
|
67
|
+
markers = [
|
|
68
|
+
"slow: marks tests as slow (deselect with '-m \"not slow\"')"
|
|
69
|
+
]
|
|
67
70
|
|
|
68
71
|
[tool.coverage.run]
|
|
69
72
|
omit = [
|
|
@@ -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
|
-
|
|
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))
|
|
@@ -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
|
|
|
@@ -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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
155
|
+
raise ValueError(f"{self._device_name}: Hostname is not initialized.")
|
|
148
156
|
|
|
149
157
|
if not self.port:
|
|
150
|
-
raise ValueError(f"{self.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
259
|
+
raise DeviceConnectionError(self._device_name, "Device not connected, use connect() first")
|
|
252
260
|
|
|
253
|
-
# Ensure command ends with
|
|
254
|
-
if not command.endswith(
|
|
255
|
-
command +=
|
|
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.
|
|
270
|
+
raise DeviceTimeoutError(self._device_name, "Write operation timed out") from exc
|
|
263
271
|
except (ConnectionError, OSError) as exc:
|
|
264
|
-
raise DeviceConnectionError(self.
|
|
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.
|
|
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=
|
|
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.
|
|
296
|
-
return exc.partial if exc.partial else
|
|
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.
|
|
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.
|
|
316
|
+
raise DeviceTimeoutError(self._device_name, "Read operation timed out") from exc
|
|
309
317
|
except Exception as exc:
|
|
310
|
-
raise DeviceConnectionError(self.
|
|
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.
|
|
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(
|
|
335
|
-
command +=
|
|
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=
|
|
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.
|
|
355
|
-
return exc.partial if exc.partial else
|
|
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.
|
|
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.
|
|
375
|
+
raise DeviceTimeoutError(self._device_name, "Communication timed out") from exc
|
|
368
376
|
except (ConnectionError, OSError) as exc:
|
|
369
|
-
raise DeviceConnectionError(self.
|
|
377
|
+
raise DeviceConnectionError(self._device_name, f"Communication error: {exc}") from exc
|
|
370
378
|
except Exception as exc:
|
|
371
|
-
raise DeviceConnectionError(self.
|
|
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."""
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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:
|
|
@@ -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(
|
|
257
|
+
class AsyncSocketDevice(AsyncDeviceInterface, AsyncDeviceTransport):
|
|
256
258
|
"""
|
|
257
259
|
Async socket-backed device using asyncio streams.
|
|
258
260
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|