tdl-xoa-driver 1.4.0__py3-none-any.whl → 1.5.0__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 (50) hide show
  1. {tdl_xoa_driver-1.4.0.dist-info → tdl_xoa_driver-1.5.0.dist-info}/METADATA +8 -8
  2. {tdl_xoa_driver-1.4.0.dist-info → tdl_xoa_driver-1.5.0.dist-info}/RECORD +49 -36
  3. xoa_driver/__init__.py +2 -2
  4. xoa_driver/enums.py +2 -0
  5. xoa_driver/exceptions.py +2 -0
  6. xoa_driver/functions/anlt.py +2 -0
  7. xoa_driver/functions/anlt_ll_debug.py +2 -0
  8. xoa_driver/functions/cli/__init__.py +21 -0
  9. xoa_driver/functions/cli/_cli_manager.py +541 -0
  10. xoa_driver/functions/cli/_config_block.py +334 -0
  11. xoa_driver/functions/cli/_socket_driver.py +111 -0
  12. xoa_driver/functions/cli/port_config.py +116 -0
  13. xoa_driver/functions/cli/testbed_config.py +179 -0
  14. xoa_driver/functions/cmis/__init__.py +8 -0
  15. xoa_driver/functions/cmis/_constants.py +25 -0
  16. xoa_driver/functions/cmis/_replies.py +600 -0
  17. xoa_driver/functions/cmis/_utils.py +49 -0
  18. xoa_driver/functions/cmis/cdb.py +1266 -0
  19. xoa_driver/functions/exceptions.py +2 -0
  20. xoa_driver/functions/headers.py +2 -0
  21. xoa_driver/functions/mgmt.py +42 -19
  22. xoa_driver/functions/tools.py +9 -3
  23. xoa_driver/hlfuncs.py +6 -2
  24. xoa_driver/internals/commands/c_commands.py +6 -10
  25. xoa_driver/internals/commands/enums.py +25 -1
  26. xoa_driver/internals/commands/p_commands.py +38 -2
  27. xoa_driver/internals/commands/pl1_commands.py +130 -73
  28. xoa_driver/internals/commands/pp_commands.py +44 -55
  29. xoa_driver/internals/commands/pr_commands.py +17 -16
  30. xoa_driver/internals/commands/px_commands.py +54 -54
  31. xoa_driver/internals/core/transporter/logger/__state_on_user.py +1 -1
  32. xoa_driver/internals/exceptions/modules.py +4 -3
  33. xoa_driver/internals/hli/modules/modules_l23/family_edun.py +82 -0
  34. xoa_driver/internals/hli/modules/modules_l23/family_g.py +1 -1
  35. xoa_driver/internals/hli/modules/modules_l23/family_l1.py +19 -0
  36. xoa_driver/internals/hli/ports/port_l23/edun_l1.py +181 -0
  37. xoa_driver/internals/hli/ports/port_l23/family_edun.py +82 -0
  38. xoa_driver/internals/hli/ports/port_l23/family_l1.py +14 -8
  39. xoa_driver/internals/state_storage/modules_state.py +20 -0
  40. xoa_driver/internals/state_storage/testers_state.py +10 -0
  41. xoa_driver/lli.py +1 -0
  42. xoa_driver/misc.py +1 -0
  43. xoa_driver/modules.py +22 -0
  44. xoa_driver/ports.py +22 -0
  45. xoa_driver/testers.py +2 -0
  46. xoa_driver/utils.py +2 -0
  47. xoa_driver/functions/cli.py +0 -581
  48. {tdl_xoa_driver-1.4.0.dist-info → tdl_xoa_driver-1.5.0.dist-info}/WHEEL +0 -0
  49. {tdl_xoa_driver-1.4.0.dist-info → tdl_xoa_driver-1.5.0.dist-info}/licenses/LICENSE +0 -0
  50. {tdl_xoa_driver-1.4.0.dist-info → tdl_xoa_driver-1.5.0.dist-info}/top_level.txt +0 -0
xoa_driver/testers.py CHANGED
@@ -1,5 +1,7 @@
1
1
  #: All available tester types.
2
2
 
3
+ """Xena chassis types."""
4
+
3
5
  from .internals.hli.testers.l23_tester import L23Tester
4
6
  from .internals.hli.testers.l23ve_tester import L23VeTester
5
7
  from .internals.hli.testers.l47_tester import L47Tester
xoa_driver/utils.py CHANGED
@@ -1,5 +1,7 @@
1
1
  #: Helper functions
2
2
 
3
+ """Helper functions."""
4
+
3
5
  from xoa_driver.internals.core.funcs import (
4
6
  apply,
5
7
  apply_iter,
@@ -1,581 +0,0 @@
1
- from __future__ import annotations
2
- from dataclasses import dataclass, field
3
- import re
4
- import typing as t
5
- import inspect
6
- import ipaddress
7
- from enum import Enum
8
- from xoa_driver.internals import commands
9
- from xoa_driver import enums
10
- from xoa_driver.testers import GenericAnyTester
11
- from xoa_driver.modules import GenericAnyModule
12
- from xoa_driver.ports import GenericAnyPort
13
- from xoa_driver.misc import ArpChunk, NdpChunk
14
- from xoa_driver.utils import apply_iter
15
- from xoa_driver.internals.core.token import Token
16
- from xoa_driver.internals.core.transporter.protocol.payload import Hex
17
- from xoa_driver.internals.core.transporter.protocol.struct_request import Request
18
- from xoa_driver.internals.core.transporter.protocol._constants import CommandType
19
- from xoa_driver.internals.core.transporter._typings import (XoaCommandType, ICmdOnlyGet, ICmdOnlySet)
20
-
21
-
22
- class ICmdOnlyGett(ICmdOnlyGet, t.Protocol):
23
- __name__: t.ClassVar[str]
24
-
25
-
26
- class ICmdOnlySett(ICmdOnlySet, t.Protocol):
27
- __name__: t.ClassVar[str]
28
-
29
-
30
- def build_set_requestt(cls: ICmdOnlySett, **kwargs) -> Request:
31
- indices = kwargs.pop("indices", [])
32
- module = kwargs.pop("module", None)
33
- port = kwargs.pop("port", None)
34
- req_values = cls.SetDataAttr(**kwargs)
35
- return Request(class_name=cls.__name__, cmd_type=CommandType.COMMAND_VALUE, cmd_code=cls.code, module_index=module, port_index=port, indices=indices, values=req_values)
36
-
37
-
38
- def build_get_requestt(cls: ICmdOnlyGett, **kwargs) -> Request:
39
- indices = kwargs.pop("indices", [])
40
- module = kwargs.pop("module", None)
41
- port = kwargs.pop("port", None)
42
- req_values = None
43
- return Request(class_name=cls.__name__, cmd_type=CommandType.COMMAND_QUERY, cmd_code=cls.code, module_index=module, port_index=port, indices=indices, values=req_values)
44
-
45
-
46
- module = port = r"\d+"
47
- index = r"((0x|0X)?[A-Fa-f\d]+)"
48
- zero_or_more_space = r"\s*"
49
- module_port_group = r"((?P<module>\d+)(/(?P<port>\d+))?\s*)?"
50
- command_name_group = r"(?P<command_name>[A-Z_a-z0-9]+\s*)"
51
- indices_group = r"(?P<indices>(\[((0x|0X)?[A-Fa-f\d]+)(,?\s*((0x|0X)?[A-Fa-f\d]+))?(,?\s*((0x|0X)?[A-Fa-f\d]+))?\]\s*)?)"
52
- params_group = r"(?P<params>.*)"
53
- command_pattern = re.compile(module_port_group + command_name_group + indices_group + params_group)
54
-
55
-
56
- class Unpassed:
57
- """
58
- None has special meaning, so this empty type is needed for parameters which are not passed.
59
- """
60
-
61
- pass
62
-
63
-
64
- @dataclass
65
- class Body:
66
- command_name: str = ""
67
- cmd_class: XoaCommandType = XoaCommandType # type: ignore
68
- type: CommandType = CommandType.COMMAND_STATUS
69
- module: t.Optional[int] = None
70
- port: t.Optional[int] = None
71
- square_indices: list[int] = field(default_factory=list)
72
- values: dict = field(default_factory=dict)
73
-
74
- def as_request(
75
- self,
76
- module_num: int | None | Unpassed = Unpassed(),
77
- port_num: int | None | Unpassed = Unpassed(),
78
- indices_num: list[int] | Unpassed = Unpassed(),
79
- ) -> Request:
80
- if not isinstance(indices_num, Unpassed):
81
- self.square_indices = indices_num
82
- if not isinstance(module_num, Unpassed):
83
- self.module = module_num
84
- if not isinstance(port_num, Unpassed):
85
- self.port = port_num
86
-
87
- dic = dict(indices=self.square_indices, module=self.module, port=self.port, **self.values,)
88
- return build_get_requestt(self.cmd_class, **dic) if self.type == CommandType.COMMAND_QUERY else build_set_requestt(self.cmd_class, **dic) # type: ignore
89
-
90
-
91
- class CLIConverter:
92
- @classmethod
93
- def _read_indices(cls, indices_str: str) -> list[int]:
94
- result = []
95
- ind = indices_str.strip().strip("[").strip("]").split(",")
96
- for i in ind:
97
- if not i:
98
- continue
99
- try:
100
- if "0x" in i or "0X" in i:
101
- result.append(int(i.strip(), 16))
102
- else:
103
- result.append(int(i.strip()))
104
- except Exception:
105
- raise ValueError(f"Invalid indices str {indices_str}!")
106
- return result
107
-
108
- @classmethod
109
- def _special_read(cls, class_name: str, or_params: list[str]) -> list[str]:
110
- params = or_params
111
- if class_name == "C_DOWN" and params.index("-1480937026") == 0:
112
- params.pop(0)
113
- elif class_name == "P_ARPRXTABLE":
114
- params = []
115
- if or_params:
116
- orr_params = or_params[0].replace("0x", "").replace("0X", "")
117
- params = [orr_params[i: i + 26] for i in range(0, len(orr_params), 26)]
118
- elif class_name == "P_NDPRXTABLE":
119
- params = []
120
- if or_params:
121
- orr_params = or_params[0].replace("0x", "").replace("0X", "")
122
- params = [orr_params[i: i + 50] for i in range(0, len(orr_params), 50)]
123
-
124
- return params
125
-
126
- @classmethod
127
- def _special_add(cls, class_name: str, dic: dict) -> dict:
128
- if class_name in ("C_DOWN", "C_FILEFINISH", "M_UPGRADE"):
129
- dic["magic"] = -1480937026
130
- elif class_name == "M_FPGAREIMAGE":
131
- dic["key_code"] = 42
132
- elif class_name == "PP_EYEMEASURE":
133
- dic["dummy"] = []
134
- elif class_name == "PP_PHYTXEQ":
135
- dic["mode"] = 4
136
- return dic
137
-
138
- @classmethod
139
- def _read_response_values(cls, or_params: list[str], cmd_class: t.Type) -> dict:
140
- dic = {}
141
- attr_set = getattr(cmd_class, "set")
142
- class_name = cmd_class.__name__
143
- values = list(inspect.signature(attr_set).parameters.values())
144
- params = cls._special_read(class_name, or_params)
145
- func_sigs: list[inspect.Parameter] = []
146
- list_index = -1
147
- for i, v in enumerate(values):
148
- if v.name == "self":
149
- continue
150
- if "list[" in str(v.annotation).lower():
151
- list_index = i - 1
152
- func_sigs.append(v)
153
-
154
- if list_index == -1:
155
- dic = {f.name: cls._bind_one_param(class_name, p, f.annotation, f.name) for p, f in zip(params, func_sigs)}
156
- else:
157
- element_sig = (values[list_index + 1].annotation.replace("typing.", "").replace("list[", "").replace("List[", "").replace("]", ""))
158
- dic = cls._bind_has_list(class_name, params, func_sigs, list_index, element_sig)
159
- dic = cls._special_add(class_name, dic)
160
- return dic
161
-
162
- @classmethod
163
- def _bind_has_list(cls, class_name: str, params: list[str], func_sigs: list[inspect.Parameter], list_index: int, element_sig: str,) -> dict[str, t.Any]:
164
- dic = {}
165
- name = func_sigs[list_index].name
166
- fore_sigs = func_sigs[:list_index]
167
- fore_params = params[:list_index]
168
-
169
- back_sigs = func_sigs[list_index + 1:]
170
- back_params = params[-len(back_sigs):]
171
-
172
- if len(func_sigs) == 1: # only one param and is list
173
- dic.update({name: [cls._bind_one_param(class_name, p, element_sig) for p in params]})
174
- elif len(fore_params) == len(fore_sigs) != 0: # others followed by a list
175
- list_params = params[list_index:]
176
- dic.update({f.name: cls._bind_one_param(class_name, p, f.annotation, f.name) for p, f in zip(fore_params, fore_sigs)})
177
- dic[name] = [cls._bind_one_param(class_name, b, element_sig) for b in list_params]
178
- elif len(back_params) == len(back_sigs) != 0: # a list follow by others
179
- list_params = params[: -(len(func_sigs) - list_index - 1)]
180
- dic.update({f.name: cls._bind_one_param(class_name, p, f.annotation, f.name) for p, f in zip(back_params, back_sigs)})
181
- dic[name] = [cls._bind_one_param(class_name, b, element_sig) for b in list_params]
182
- return dic
183
-
184
- @classmethod
185
- def _basic_cast(
186
- cls, string_param: str, type_name: str
187
- ) -> str | int | float | Hex | None:
188
- basics = {"str": str, "int": int, "float": float, "Hex": Hex}
189
- basic_type = basics.get(type_name, None)
190
- if basic_type is not None:
191
- try:
192
- if basic_type is str:
193
- return str(string_param).strip('"').strip("'")
194
- elif basic_type is Hex:
195
- s = string_param.replace("0x", "").replace("0X", "")
196
- if len(s) % 2:
197
- s = "0" + s
198
- return Hex(s)
199
- return basic_type(string_param)
200
- except ValueError:
201
- return None
202
-
203
- @classmethod
204
- def _ip_cast(
205
- cls,
206
- string_param: str,
207
- type_name: str,
208
- ) -> ipaddress.IPv4Address | ipaddress.IPv6Address | None:
209
- ips = {"ipaddress.IPv4Address": ipaddress.IPv4Address, "IPv4Address": ipaddress.IPv4Address,
210
- "ipaddress.IPv6Address": ipaddress.IPv6Address, "IPv6Address": ipaddress.IPv6Address}
211
- ips_cast = ips.get(type_name, None)
212
- if ips_cast is not None:
213
- try:
214
- return ips_cast(string_param)
215
- except Exception:
216
- pass
217
- try:
218
- # input is int-IPv4 but in a str form:
219
- # ipaddress.ip_address(3232235788) -> IPv4Address('192.168.1.12')
220
- return ips_cast(int(string_param))
221
- except Exception:
222
- pass
223
- try:
224
- # input is IPV6 but in a str form:
225
- # ipaddress.ip_address(int('0x10000000000000000000000000000000'), 16) -> IPv6Address('1000::')
226
- return ips_cast(int(string_param, 16))
227
- except Exception:
228
- pass
229
- return None
230
-
231
- @classmethod
232
- def _enum_cast(cls, string_param: str, type_name: str) -> Enum | None:
233
- enum_cast = getattr(enums, type_name, None)
234
- if enum_cast is not None:
235
- try:
236
- return enum_cast(int(string_param))
237
- except Exception:
238
- pass
239
- try:
240
- return enum_cast[string_param.upper()]
241
- except Exception:
242
- pass
243
- return None
244
-
245
- @classmethod
246
- def _special_cast(cls, class_name: str, string_param: str, type_name: str, param_name: str) -> t.Any:
247
- if type_name == "ProtocolOption":
248
- enum_cast = getattr(enums, type_name, None)
249
- if enum_cast is not None:
250
- try:
251
- i = int(string_param)
252
- return enum_cast(256 + i)
253
- except Exception:
254
- return None
255
- elif type_name == "SMAInputFunction":
256
- enum_cast = getattr(enums, type_name, None)
257
- if enum_cast is not None and string_param == "NOTUSED":
258
- return enum_cast["NOT_USED"]
259
- elif type_name == "SourceType":
260
- enum_cast = getattr(enums, type_name, None)
261
- if enum_cast is not None:
262
- return {"TXIFG": enum_cast["TX_IFG"], "TXLEN": enum_cast["TX_LEN"],
263
- "RXIFG": enum_cast["RX_IFG"], "RXLEN": enum_cast["RX_LEN"],
264
- "RXLAT": enum_cast["RX_LATENCY"], "RXJIT": enum_cast["RX_JITTER"]}.get(string_param, None)
265
- elif type_name == "LinkTrainingMode":
266
- enum_cast = getattr(enums, type_name, None)
267
- if enum_cast is not None and string_param == "AUTO":
268
- return enum_cast["START_AFTER_AUTONEG"]
269
- elif type_name == "TimeoutMode":
270
- enum_cast = getattr(enums, type_name, None)
271
- if enum_cast is not None and string_param == "DEFAULT_TIMEOUT":
272
- return enum_cast["DEFAULT"]
273
- elif class_name == "P_MULTICASTHDR":
274
- enum_cast = getattr(enums, type_name, None)
275
- if enum_cast is not None:
276
- return enum_cast[string_param.upper().replace("DEI_", "")]
277
- elif class_name == "P_CHECKSUM":
278
- return {"ON": 14, "OFF": 0}.get(string_param, None)
279
- elif class_name == "P_ARPRXTABLE":
280
- ipv4_address = ipaddress.IPv4Address(bytes.fromhex(string_param[0:8]))
281
- prefix = int.from_bytes(bytes.fromhex(string_param[8:12]), "big")
282
- patched_mac = enums.OnOff(int.from_bytes(bytes.fromhex(string_param[12:14]), "big"))
283
- mac_address = Hex(string_param[14:])
284
- chunk = ArpChunk(ipv4_address, prefix, patched_mac, mac_address)
285
- return chunk
286
- elif class_name == "P_NDPRXTABLE":
287
- ipv6_address = ipaddress.IPv6Address(bytes.fromhex(string_param[0:32]))
288
- prefix = int.from_bytes(bytes.fromhex(string_param[32:36]), "big")
289
- patched_mac = enums.OnOff(int.from_bytes(bytes.fromhex(string_param[36:38]), "big"))
290
- mac_address = Hex(string_param[38:])
291
- chunk = NdpChunk(ipv6_address, prefix, patched_mac, mac_address)
292
- return chunk
293
- elif class_name == "PL1_LINKTRAIN_CMD":
294
- s = string_param.upper()
295
- t1 = ("PRE1", "MAIN", "POST", "PRE2", "PRE3")
296
- t2 = ("PRESET_1", "PRESET_2", "PRESET_3", "PRESET_4", "PRESET_5")
297
- t3 = ("PAM2", "PAM4", "PAM4_WITH_PRECODING")
298
- if s in t1:
299
- return t1.index(s)
300
- elif s in t2:
301
- return t2.index(s)
302
- elif s in t3:
303
- return t3.index(s)
304
- elif class_name == "PP_LINKFLAP_PARAMS" and param_name == "repetition":
305
- if string_param.upper() == "INFINITE":
306
- return 0
307
- else:
308
- return int(string_param)
309
-
310
-
311
- @classmethod
312
- def _bind_one_param(
313
- cls, class_name: str, string_param: str, type_name: str, param_name: str = ""
314
- ) -> t.Any:
315
- basic_cast = cls._basic_cast(string_param, type_name)
316
- if basic_cast is not None:
317
- return basic_cast
318
-
319
- ip_cast = cls._ip_cast(string_param, type_name)
320
- if ip_cast is not None:
321
- return ip_cast
322
-
323
- enum_cast = cls._enum_cast(string_param, type_name)
324
- if enum_cast is not None:
325
- return enum_cast
326
-
327
- special_cast = cls._special_cast(class_name, string_param, type_name, param_name)
328
- if special_cast is not None:
329
- return special_cast
330
-
331
- raise ValueError(f"Cannot bind param '{string_param}' to type '{type_name}'!")
332
-
333
- @classmethod
334
- def _parse_param_string(cls, param_string: str) -> list[str]:
335
- """Handle extreme cases where \',\",\\\',\\\" or string inside param_string."""
336
- (
337
- OUTSIDE,
338
- INSIDE_DOUBLE_QUOTE,
339
- INSIDE_SINGLE_QUOTE,
340
- ESCAPED_DOUBLE_QUOTE,
341
- ESCAPED_SINGLE_QUOTE,
342
- ) = range(5)
343
- state = OUTSIDE
344
- string_list = []
345
- buf = []
346
- for c in param_string:
347
- if state == OUTSIDE:
348
- if c in (" ", "\t", "\r", "\n", "\f"):
349
- string = "".join(buf).strip()
350
- if string:
351
- string_list.append(string)
352
- if buf:
353
- buf = []
354
- elif c == '"':
355
- state = INSIDE_DOUBLE_QUOTE
356
- elif c == "'":
357
- state = INSIDE_SINGLE_QUOTE
358
- else:
359
- buf.append(c)
360
- elif state == INSIDE_DOUBLE_QUOTE:
361
- if c == "\\":
362
- state = ESCAPED_DOUBLE_QUOTE
363
- elif c == '"':
364
- string_list.append("".join(buf))
365
- buf = []
366
- state = OUTSIDE
367
- else:
368
- buf.append(c)
369
- elif state == INSIDE_SINGLE_QUOTE:
370
- if c == "\\":
371
- state = ESCAPED_SINGLE_QUOTE
372
- elif c == "'":
373
- string_list.append("".join(buf))
374
- buf = []
375
- state = OUTSIDE
376
- else:
377
- buf.append(c)
378
- elif state == ESCAPED_DOUBLE_QUOTE:
379
- buf.append(c)
380
- state = INSIDE_DOUBLE_QUOTE
381
- elif state == ESCAPED_SINGLE_QUOTE:
382
- buf.append(c)
383
- state = INSIDE_SINGLE_QUOTE
384
- if state != OUTSIDE:
385
- s = '"' if state == INSIDE_DOUBLE_QUOTE else "'"
386
- raise ValueError(f"String not complete: ({s}{''.join(buf)}).")
387
- if buf:
388
- string_list.append("".join(buf).strip())
389
- return string_list
390
-
391
- @classmethod
392
- def _read_params(
393
- cls, param_string: str, cmd_class: t.Type
394
- ) -> tuple[CommandType, dict]:
395
- params = cls._parse_param_string(param_string)
396
- if params == ["?"]:
397
- return CommandType.COMMAND_QUERY, {}
398
- return CommandType.COMMAND_VALUE, cls._read_response_values(params, cmd_class)
399
-
400
- @classmethod
401
- def _read_command_name(cls, command_name: str) -> t.Type:
402
- return getattr(commands, command_name.upper())
403
-
404
- @classmethod
405
- def _read_int(cls, n: str | int | None) -> int | None:
406
- if n is None:
407
- return None
408
- try:
409
- if isinstance(n, str) and ("0x" in n or "0X" in n):
410
- return int(n.strip(), 16)
411
- return int(n)
412
- except Exception:
413
- return None
414
-
415
- @classmethod
416
- def convert_each_command(cls, command: str) -> Body | None:
417
- result = re.search(command_pattern, command)
418
- if not result:
419
- return None
420
- command_name = result.group("command_name").strip() or ""
421
- cmd_class = cls._read_command_name(command_name)
422
- module_index = cls._read_int(result.group("module"))
423
- port_index = cls._read_int(result.group("port"))
424
- indices = cls._read_indices(result.group("indices"))
425
- body_type, values = cls._read_params(result.group("params") or "", cmd_class)
426
- body = Body(command_name, cmd_class, body_type, module_index, port_index, indices, values)
427
- return body
428
-
429
- @classmethod
430
- def read_commands_from_file(
431
- cls, path: str, comment_start: tuple[str, ...] = (";", "#", "//")
432
- ) -> t.Generator[Body, None, None]:
433
- with open(path, "r") as f:
434
- for line in f:
435
- buf = line.strip()
436
- for i, char in enumerate(buf):
437
- if char in comment_start:
438
- buf = buf[:i]
439
- break
440
- if not buf:
441
- continue
442
- r = cls.convert_each_command(buf)
443
- if r is not None:
444
- yield r
445
-
446
- @classmethod
447
- def read_commands_from_string(
448
- cls, long_str: str, comment_start: tuple[str, ...] = (";", "#", "//")
449
- ) -> t.Generator[Body, None, None]:
450
- for line in long_str.split("\n"):
451
- buf = line.strip()
452
- for i, char in enumerate(buf):
453
- if char in comment_start:
454
- buf = buf[:i]
455
- break
456
- if not buf:
457
- continue
458
- r = cls.convert_each_command(buf)
459
- if r is not None:
460
- yield r
461
-
462
-
463
- read_commands_from_file = CLIConverter.read_commands_from_file
464
- read_commands_from_string = CLIConverter.read_commands_from_string
465
-
466
-
467
- def upload_config_from(obj: GenericAnyTester | GenericAnyModule | GenericAnyPort, long_str: str,
468
- is_file: bool, mode: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> t.Generator[Token, None, None]:
469
- func = read_commands_from_file if is_file else read_commands_from_string
470
- for command in func(long_str, comment_start):
471
- if not command.command_name.startswith(mode):
472
- continue
473
- if mode == "M":
474
- request = command.as_request(module_num=getattr(obj, "module_id", None))
475
- elif mode == "P":
476
- request = command.as_request(
477
- module_num=getattr(getattr(obj, "kind", None), "module_id", None),
478
- port_num=getattr(getattr(obj, "kind", None), "port_id", None),
479
- )
480
- else:
481
- request = command.as_request()
482
- yield Token(obj._conn, request)
483
-
484
-
485
- async def _helper(obj: GenericAnyTester | GenericAnyModule | GenericAnyPort, long_str: str, is_file: bool, mode: str, comment_start: tuple[str, ...]) -> None:
486
- async for f in apply_iter(*upload_config_from(obj, long_str, is_file, mode, comment_start), return_exceptions=True):
487
- pass
488
-
489
-
490
- async def tester_config_from_string(tester: GenericAnyTester, long_str: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
491
- """Send tester configuration from a string. The CLI commands must all start with `C_` prefix.
492
-
493
- :param tester: the tester object
494
- :type tester: GenericAnyTester
495
- :param long_str: the string containing the CLI commands
496
- :type long_str: str
497
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
498
- :type comment_start: tuple[str, ...], optional
499
- """
500
- await _helper(tester, long_str, False, "C", comment_start)
501
-
502
-
503
- async def tester_config_from_file(tester: GenericAnyTester, path: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
504
- """Send tester configuration from a configuration file. The CLI commands must all start with `C_` prefix.
505
-
506
- :param tester: the tester object
507
- :type tester: GenericAnyTester
508
- :param path: the path to the configuration file
509
- :type path: str
510
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
511
- :type comment_start: tuple[str, ...], optional
512
- """
513
- await _helper(tester, path, True, "C", comment_start)
514
-
515
-
516
- async def module_config_from_string(module: GenericAnyModule, long_str: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
517
- """Send module configuration from a string. The CLI commands must all start with `M_` prefix.
518
-
519
- :param module: the module object
520
- :type module: GenericAnyModule
521
- :param long_str: the string containing the CLI commands
522
- :type long_str: str
523
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
524
- :type comment_start: tuple[str, ...], optional
525
- """
526
- assert (module.is_reserved_by_me()), f"Please reserve Module {module.module_id} first!"
527
- await _helper(module, long_str, False, "M", comment_start)
528
-
529
-
530
- async def module_config_from_file(module: GenericAnyModule, path: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
531
- """Send module configuration from a configuration file. The CLI commands must all start with `M_` prefix.
532
-
533
- :param module: the module object
534
- :type module: GenericAnyModule
535
- :param path: the path to the configuration file
536
- :type path: str
537
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
538
- :type comment_start: tuple[str, ...], optional
539
- """
540
- assert (module.is_reserved_by_me()), f"Please reserve Module {module.module_id} first!"
541
- await _helper(module, path, True, "M", comment_start)
542
-
543
-
544
- async def port_config_from_string(port: GenericAnyPort, long_str: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
545
- """Send port configuration from a string. The CLI commands must all start with `P_` prefix.
546
-
547
- :param port: the port object
548
- :type port: GenericAnyPort
549
- :param long_str: the string containing the CLI commands
550
- :type long_str: str
551
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
552
- :type comment_start: tuple[str, ...], optional
553
- """
554
- assert (port.is_reserved_by_me()), f"Please reserve Port {port.kind.module_id}/{port.kind.port_id} first!"
555
- await _helper(port, long_str, False, "P", comment_start)
556
-
557
-
558
- async def port_config_from_file(port: GenericAnyPort, path: str, comment_start: tuple[str, ...] = (";", "#", "//")) -> None:
559
- """Send port configuration from a port configuration file (.xpc file).
560
-
561
- :param port: the port object
562
- :type port: GenericAnyPort
563
- :param path: the path to the configuration file
564
- :type path: str
565
- :param comment_start: symbol used to start a comment, defaults to (";", "#", "//")
566
- :type comment_start: tuple[str, ...], optional
567
- """
568
- assert (port.is_reserved_by_me()), f"Please reserve Port {port.kind.module_id}/{port.kind.port_id} first!"
569
- await _helper(port, path, True, "P", comment_start)
570
-
571
-
572
- __all__ = (
573
- "read_commands_from_file",
574
- "read_commands_from_string",
575
- "tester_config_from_string",
576
- "module_config_from_string",
577
- "port_config_from_string",
578
- "tester_config_from_file",
579
- "module_config_from_file",
580
- "port_config_from_file",
581
- )