Skip to content

Commit 6d4ac4e

Browse files
committed
AI review comments
1 parent 7ce7b16 commit 6d4ac4e

5 files changed

Lines changed: 61 additions & 36 deletions

File tree

src/fastcs_secop/_controllers.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -95,33 +95,44 @@ async def initialise(self) -> None:
9595
@command()
9696
async def execute(self) -> None:
9797
"""Execute the command."""
98-
prefix = f"do {self._module_name}:{self._command_name}"
99-
response_prefix = f"done {self._module_name}:{self._command_name}"
100-
101-
if self.args is not None:
102-
if self.raw_args:
103-
cmd = f"{prefix} {self.args.get()}\n"
104-
else:
105-
cmd = f"{prefix} {encode(self.args.get(), self._datainfo['argument'])}\n"
106-
else:
107-
cmd = f"{prefix}\n"
108-
109-
logger.debug("Sending command: '%s'", cmd)
110-
response = await self._connection.send_query(cmd)
111-
logger.debug("Response: '%s'", response)
112-
113-
response = response.strip()
114-
if not response.startswith(response_prefix):
115-
logger.warning("command '%s' failed (response='%s')", prefix, response)
116-
return
117-
118-
response = response[len(response_prefix) :].strip()
119-
120-
if self.result is not None:
121-
if self.raw_result:
122-
await self.result.update(orjson.dumps(orjson.loads(response)[0]).decode())
98+
try:
99+
prefix = f"do {self._module_name}:{self._command_name}"
100+
response_prefix = f"done {self._module_name}:{self._command_name}"
101+
102+
if self.args is not None:
103+
if self.raw_args:
104+
cmd = f"{prefix} {self.args.get()}\n"
105+
else:
106+
cmd = f"{prefix} {encode(self.args.get(), self._datainfo['argument'])}\n"
123107
else:
124-
await self.result.update(decode(response, self._datainfo["result"], self.result))
108+
cmd = f"{prefix}\n"
109+
110+
logger.debug("Sending command: '%s'", cmd)
111+
response = await self._connection.send_query(cmd)
112+
logger.debug("Response: '%s'", response)
113+
114+
response = response.strip()
115+
if not response.startswith(response_prefix):
116+
logger.warning("command '%s' failed (response='%s')", prefix, response)
117+
return
118+
119+
response = response[len(response_prefix) :].strip()
120+
121+
if self.result is not None:
122+
if self.raw_result:
123+
await self.result.update(orjson.dumps(orjson.loads(response)[0]).decode())
124+
else:
125+
await self.result.update(
126+
decode(response, self._datainfo["result"], self.result)
127+
)
128+
except Exception as e:
129+
logger.error(
130+
"command %s:%s failed: %s: %s",
131+
self._module_name,
132+
self._command_name,
133+
e.__class__.__name__,
134+
e,
135+
)
125136

126137

127138
class SecopModuleController(Controller):
@@ -318,7 +329,7 @@ async def check_idn(self) -> None:
318329
f"Not a SECoP device?"
319330
)
320331

321-
print(f"Connected to SECoP device with IDN='{identification}'.")
332+
logger.info("Connected to SECoP device with IDN='%s'.", identification)
322333

323334
async def initialise(self) -> None:
324335
"""Set up FastCS for this SECoP node.

src/fastcs_secop/_io.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,12 @@ def encode(value: T, datainfo: dict[str, Any]) -> str:
151151
assert isinstance(value, enum.Enum)
152152
return orjson.dumps(value.value).decode()
153153
case "scaled":
154-
return orjson.dumps(round(value / datainfo["scale"])).decode()
154+
val = round(value / datainfo["scale"])
155+
assert isinstance(val, int)
156+
return orjson.dumps(val).decode()
155157
case "blob":
156158
assert isinstance(value, np.ndarray)
157-
return orjson.dumps(
158-
base64.b64encode("".join(chr(c) for c in value).encode("utf-8")).decode()
159-
).decode()
159+
return orjson.dumps(base64.b64encode(value.tobytes()).decode()).decode()
160160
case "array":
161161
return orjson.dumps(value, option=orjson.OPT_SERIALIZE_NUMPY).decode()
162162
case "tuple":
@@ -217,8 +217,8 @@ async def send(self, attr: AttrW[T, SecopAttributeIORef], value: T) -> None:
217217
except ConnectionError:
218218
# Reconnect will be attempted in a periodic scan task
219219
pass
220-
except Exception:
221-
logger.exception("Exception during send()")
220+
except Exception as e:
221+
logger.error("Exception during send() for %s: %s: %s", attr, e.__class__.__name__, e)
222222

223223

224224
class SecopRawAttributeIO(AttributeIO[str, SecopRawAttributeIORef]):

src/fastcs_secop/_util.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ def secop_datainfo_to_fastcs_dtype(datainfo: dict[str, Any], raw: bool = False)
159159
case "bool":
160160
return Bool()
161161
case "enum":
162-
enum_type = enum.Enum("enum_type", datainfo["members"])
162+
enum_type = enum.Enum("GeneratedSecopEnum", datainfo["members"])
163163
return Enum(enum_type)
164164
case "string":
165165
return String()

tests/test_against_emulator.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ async def controller():
4545
ip="127.0.0.1",
4646
port=57677,
4747
),
48-
quirks={},
4948
)
5049

5150
for _ in range(100):

tests/test_controller.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ async def test_secop_module_controller_initialise():
142142
assert "skipped_accessible" not in controller.attributes
143143

144144

145-
async def test_command_controller_execute_fails():
145+
async def test_command_controller_execute_invalid_response():
146146
connection = AsyncMock()
147147
controller = SecopCommandController(
148148
connection=connection,
@@ -157,6 +157,21 @@ async def test_command_controller_execute_fails():
157157
await controller.execute() # No exception thrown
158158

159159

160+
async def test_command_controller_execute_fails():
161+
connection = AsyncMock()
162+
controller = SecopCommandController(
163+
connection=connection,
164+
command_name="some_command",
165+
module_name="some_module",
166+
datainfo={},
167+
quirks=SecopQuirks(),
168+
)
169+
await controller.initialise()
170+
171+
connection.send_query.side_effect = Exception
172+
await controller.execute() # No exception thrown
173+
174+
160175
async def test_command_controller_execute_no_args_no_return():
161176
connection = AsyncMock()
162177
controller = SecopCommandController(

0 commit comments

Comments
 (0)