scrapli 2.0.0a2__py3-none-manylinux2010_x86_64.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.
- scrapli/__init__.py +30 -0
- scrapli/auth.py +216 -0
- scrapli/cli.py +1414 -0
- scrapli/cli_decorators.py +148 -0
- scrapli/cli_parse.py +161 -0
- scrapli/cli_result.py +197 -0
- scrapli/definitions/__init__.py +1 -0
- scrapli/definitions/arista_eos.yaml +64 -0
- scrapli/definitions/cisco_iosxe.yaml +63 -0
- scrapli/definitions/cisco_iosxr.yaml +47 -0
- scrapli/definitions/cisco_nxos.yaml +64 -0
- scrapli/definitions/juniper_junos.yaml +85 -0
- scrapli/definitions/nokia_srlinux.yaml +35 -0
- scrapli/exceptions.py +49 -0
- scrapli/ffi.py +76 -0
- scrapli/ffi_mapping.py +202 -0
- scrapli/ffi_mapping_cli.py +646 -0
- scrapli/ffi_mapping_netconf.py +1612 -0
- scrapli/ffi_mapping_options.py +1031 -0
- scrapli/ffi_types.py +154 -0
- scrapli/helper.py +95 -0
- scrapli/lib/__init__.py +1 -0
- scrapli/lib/libscrapli.0.0.1-alpha.10.dylib +0 -0
- scrapli/lib/libscrapli.so.0.0.1-alpha.10 +0 -0
- scrapli/netconf.py +2804 -0
- scrapli/netconf_decorators.py +148 -0
- scrapli/netconf_result.py +72 -0
- scrapli/py.typed +0 -0
- scrapli/session.py +122 -0
- scrapli/transport.py +401 -0
- scrapli-2.0.0a2.dist-info/METADATA +49 -0
- scrapli-2.0.0a2.dist-info/RECORD +35 -0
- scrapli-2.0.0a2.dist-info/WHEEL +5 -0
- scrapli-2.0.0a2.dist-info/licenses/LICENSE +21 -0
- scrapli-2.0.0a2.dist-info/top_level.txt +1 -0
scrapli/cli.py
ADDED
@@ -0,0 +1,1414 @@
|
|
1
|
+
"""scrapli.cli"""
|
2
|
+
|
3
|
+
import importlib.resources
|
4
|
+
from collections.abc import Callable
|
5
|
+
from ctypes import (
|
6
|
+
c_bool,
|
7
|
+
c_char_p,
|
8
|
+
c_int,
|
9
|
+
c_uint,
|
10
|
+
c_uint64,
|
11
|
+
)
|
12
|
+
from enum import Enum
|
13
|
+
from logging import getLogger
|
14
|
+
from os import environ
|
15
|
+
from pathlib import Path
|
16
|
+
from types import TracebackType
|
17
|
+
from typing import Any
|
18
|
+
|
19
|
+
from scrapli.auth import Options as AuthOptions
|
20
|
+
from scrapli.cli_decorators import handle_operation_timeout, handle_operation_timeout_async
|
21
|
+
from scrapli.cli_result import Result
|
22
|
+
from scrapli.exceptions import (
|
23
|
+
AllocationException,
|
24
|
+
CloseException,
|
25
|
+
GetResultException,
|
26
|
+
NotOpenedException,
|
27
|
+
OpenException,
|
28
|
+
OperationException,
|
29
|
+
OptionsException,
|
30
|
+
SubmitOperationException,
|
31
|
+
)
|
32
|
+
from scrapli.ffi_mapping import LibScrapliMapping
|
33
|
+
from scrapli.ffi_types import (
|
34
|
+
CancelPointer,
|
35
|
+
DriverPointer,
|
36
|
+
IntPointer,
|
37
|
+
LogFuncCallback,
|
38
|
+
OperationIdPointer,
|
39
|
+
U64Pointer,
|
40
|
+
ZigSlice,
|
41
|
+
ZigU64Slice,
|
42
|
+
to_c_string,
|
43
|
+
)
|
44
|
+
from scrapli.helper import (
|
45
|
+
resolve_file,
|
46
|
+
wait_for_available_operation_result,
|
47
|
+
wait_for_available_operation_result_async,
|
48
|
+
)
|
49
|
+
from scrapli.session import Options as SessionOptions
|
50
|
+
from scrapli.transport import Options as TransportOptions
|
51
|
+
|
52
|
+
CLI_DEFINITIONS_PATH_OVERRIDE_ENV = "SCRAPLI_DEFINITIONS_PATH"
|
53
|
+
CLI_DEFINITIONS_PATH_OVERRIDE = environ.get(CLI_DEFINITIONS_PATH_OVERRIDE_ENV)
|
54
|
+
|
55
|
+
|
56
|
+
class InputHandling(str, Enum):
|
57
|
+
"""
|
58
|
+
Enum representing the input handling flavor.
|
59
|
+
|
60
|
+
Args:
|
61
|
+
N/A
|
62
|
+
|
63
|
+
Returns:
|
64
|
+
None
|
65
|
+
|
66
|
+
Raises:
|
67
|
+
N/A
|
68
|
+
|
69
|
+
"""
|
70
|
+
|
71
|
+
EXACT = "exact"
|
72
|
+
FUZZY = "fuzzy"
|
73
|
+
IGNORE = "ignore"
|
74
|
+
|
75
|
+
|
76
|
+
class Cli:
|
77
|
+
"""
|
78
|
+
Cli represents a cli connection object.
|
79
|
+
|
80
|
+
Args:
|
81
|
+
N/A
|
82
|
+
|
83
|
+
Returns:
|
84
|
+
None
|
85
|
+
|
86
|
+
Raises:
|
87
|
+
N/A
|
88
|
+
|
89
|
+
"""
|
90
|
+
|
91
|
+
def __init__( # noqa: PLR0913
|
92
|
+
self,
|
93
|
+
definition_file_or_name: str,
|
94
|
+
host: str,
|
95
|
+
*,
|
96
|
+
logger_callback: Callable[[int, str], None] | None = None,
|
97
|
+
port: int = 22,
|
98
|
+
auth_options: AuthOptions | None = None,
|
99
|
+
session_options: SessionOptions | None = None,
|
100
|
+
transport_options: TransportOptions | None = None,
|
101
|
+
logging_uid: str | None = None,
|
102
|
+
) -> None:
|
103
|
+
logger_name = f"{__name__}.{host}:{port}"
|
104
|
+
if logging_uid is not None:
|
105
|
+
logger_name += f":{logging_uid}"
|
106
|
+
|
107
|
+
self.logger = getLogger(logger_name)
|
108
|
+
self._logging_uid = logging_uid
|
109
|
+
|
110
|
+
self.ffi_mapping = LibScrapliMapping()
|
111
|
+
|
112
|
+
self.definition_file_or_name = definition_file_or_name
|
113
|
+
self._load_definition(definition_file_or_name=definition_file_or_name)
|
114
|
+
|
115
|
+
# note: many places have encodings done prior to function calls such that the encoded
|
116
|
+
# result is not gc'd prior to being used in zig-land, so it looks a bit weird, but thats
|
117
|
+
# why. in this case we also just store the host since thats cheap and we need it as a string
|
118
|
+
# in places too
|
119
|
+
self.host = host
|
120
|
+
self._host = to_c_string(host)
|
121
|
+
|
122
|
+
self.logger_callback = (
|
123
|
+
LogFuncCallback(logger_callback) if logger_callback else LogFuncCallback(0)
|
124
|
+
)
|
125
|
+
self._logger_callback = logger_callback
|
126
|
+
|
127
|
+
self.port = port
|
128
|
+
|
129
|
+
self.auth_options = auth_options or AuthOptions()
|
130
|
+
self.session_options = session_options or SessionOptions()
|
131
|
+
self.transport_options = transport_options or TransportOptions()
|
132
|
+
|
133
|
+
self.ptr: DriverPointer | None = None
|
134
|
+
self.poll_fd: int = 0
|
135
|
+
|
136
|
+
self._ntc_templates_platform: str | None = None
|
137
|
+
self._genie_platform: str | None = None
|
138
|
+
|
139
|
+
def __enter__(self: "Cli") -> "Cli":
|
140
|
+
"""
|
141
|
+
Enter method for context manager.
|
142
|
+
|
143
|
+
Args:
|
144
|
+
N/A
|
145
|
+
|
146
|
+
Returns:
|
147
|
+
Cli: a concrete implementation of the opened Cli object
|
148
|
+
|
149
|
+
Raises:
|
150
|
+
N/A
|
151
|
+
|
152
|
+
"""
|
153
|
+
self.open()
|
154
|
+
|
155
|
+
return self
|
156
|
+
|
157
|
+
def __exit__(
|
158
|
+
self,
|
159
|
+
exception_type: BaseException | None,
|
160
|
+
exception_value: BaseException | None,
|
161
|
+
traceback: TracebackType | None,
|
162
|
+
) -> None:
|
163
|
+
"""
|
164
|
+
Exit method to cleanup for context manager.
|
165
|
+
|
166
|
+
Args:
|
167
|
+
exception_type: exception type being raised
|
168
|
+
exception_value: message from exception being raised
|
169
|
+
traceback: traceback from exception being raised
|
170
|
+
|
171
|
+
Returns:
|
172
|
+
None
|
173
|
+
|
174
|
+
Raises:
|
175
|
+
N/A
|
176
|
+
|
177
|
+
"""
|
178
|
+
self.close()
|
179
|
+
|
180
|
+
async def __aenter__(self: "Cli") -> "Cli":
|
181
|
+
"""
|
182
|
+
Enter method for context manager.
|
183
|
+
|
184
|
+
Args:
|
185
|
+
N/A
|
186
|
+
|
187
|
+
Returns:
|
188
|
+
Cli: a concrete implementation of the opened Cli object
|
189
|
+
|
190
|
+
Raises:
|
191
|
+
N/A
|
192
|
+
|
193
|
+
"""
|
194
|
+
await self.open_async()
|
195
|
+
|
196
|
+
return self
|
197
|
+
|
198
|
+
async def __aexit__(
|
199
|
+
self,
|
200
|
+
exception_type: BaseException | None,
|
201
|
+
exception_value: BaseException | None,
|
202
|
+
traceback: TracebackType | None,
|
203
|
+
) -> None:
|
204
|
+
"""
|
205
|
+
Exit method to cleanup for context manager.
|
206
|
+
|
207
|
+
Args:
|
208
|
+
exception_type: exception type being raised
|
209
|
+
exception_value: message from exception being raised
|
210
|
+
traceback: traceback from exception being raised
|
211
|
+
|
212
|
+
Returns:
|
213
|
+
None
|
214
|
+
|
215
|
+
Raises:
|
216
|
+
N/A
|
217
|
+
|
218
|
+
"""
|
219
|
+
await self.close_async()
|
220
|
+
|
221
|
+
def __str__(self) -> str:
|
222
|
+
"""
|
223
|
+
Magic str method for Cli object.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
N/A
|
227
|
+
|
228
|
+
Returns:
|
229
|
+
str: str representation of Cli
|
230
|
+
|
231
|
+
Raises:
|
232
|
+
N/A
|
233
|
+
|
234
|
+
"""
|
235
|
+
return f"scrapli.Cli {self.host}:{self.port}"
|
236
|
+
|
237
|
+
def __repr__(self) -> str:
|
238
|
+
"""
|
239
|
+
Magic repr method for Cli object.
|
240
|
+
|
241
|
+
Args:
|
242
|
+
N/A
|
243
|
+
|
244
|
+
Returns:
|
245
|
+
str: repr for Cli object
|
246
|
+
|
247
|
+
Raises:
|
248
|
+
N/A
|
249
|
+
|
250
|
+
"""
|
251
|
+
return (
|
252
|
+
f"{self.__class__.__name__}("
|
253
|
+
f"definition_file_or_name={self.definition_file_or_name!r}, "
|
254
|
+
f"host={self.host!r}, "
|
255
|
+
f"port={self.port!r}, "
|
256
|
+
f"auth_options={self.auth_options!r} "
|
257
|
+
f"session_options={self.auth_options!r} "
|
258
|
+
f"transport_options={self.transport_options!r}) "
|
259
|
+
)
|
260
|
+
|
261
|
+
def __copy__(self, memodict: dict[Any, Any] = {}) -> "Cli":
|
262
|
+
# reasonably safely copy of the object... *reasonably*... basically assumes that options
|
263
|
+
# will never be mutated during an objects lifetime, which *should* be the case. probably.
|
264
|
+
return Cli(
|
265
|
+
host=self.host,
|
266
|
+
definition_file_or_name=self.definition_file_or_name,
|
267
|
+
logger_callback=self._logger_callback,
|
268
|
+
port=self.port,
|
269
|
+
auth_options=self.auth_options,
|
270
|
+
session_options=self.session_options,
|
271
|
+
transport_options=self.transport_options,
|
272
|
+
logging_uid=self._logging_uid,
|
273
|
+
)
|
274
|
+
|
275
|
+
def _load_definition(self, definition_file_or_name: str) -> None:
|
276
|
+
if CLI_DEFINITIONS_PATH_OVERRIDE is not None:
|
277
|
+
definition_path = f"{CLI_DEFINITIONS_PATH_OVERRIDE}/{definition_file_or_name}.yaml"
|
278
|
+
else:
|
279
|
+
definitions_path = importlib.resources.files("scrapli.definitions")
|
280
|
+
definition_path = f"{definitions_path}/{definition_file_or_name}.yaml"
|
281
|
+
|
282
|
+
if Path(definition_path).exists():
|
283
|
+
with open(definition_path, "rb") as f:
|
284
|
+
self.definition_string = f.read()
|
285
|
+
|
286
|
+
return
|
287
|
+
|
288
|
+
if Path(definition_file_or_name).exists():
|
289
|
+
with open(definition_file_or_name, "rb") as f:
|
290
|
+
self.definition_string = f.read()
|
291
|
+
|
292
|
+
raise OptionsException(
|
293
|
+
f"definition platform name or filename '{definition_file_or_name}' not found"
|
294
|
+
)
|
295
|
+
|
296
|
+
def _ptr_or_exception(self) -> DriverPointer:
|
297
|
+
if self.ptr is None:
|
298
|
+
raise NotOpenedException
|
299
|
+
|
300
|
+
return self.ptr
|
301
|
+
|
302
|
+
def _alloc(
|
303
|
+
self,
|
304
|
+
) -> None:
|
305
|
+
ptr = self.ffi_mapping.cli_mapping.alloc(
|
306
|
+
definition_string=c_char_p(self.definition_string),
|
307
|
+
logger_callback=self.logger_callback,
|
308
|
+
host=self._host,
|
309
|
+
port=c_int(self.port),
|
310
|
+
transport_kind=c_char_p(self.transport_options.get_transport_kind()),
|
311
|
+
)
|
312
|
+
if ptr == 0: # type: ignore[comparison-overlap]
|
313
|
+
raise AllocationException("failed to allocate cli")
|
314
|
+
|
315
|
+
self.ptr = ptr
|
316
|
+
|
317
|
+
poll_fd = int(
|
318
|
+
self.ffi_mapping.shared_mapping.get_poll_fd(
|
319
|
+
ptr=self._ptr_or_exception(),
|
320
|
+
)
|
321
|
+
)
|
322
|
+
if poll_fd == 0:
|
323
|
+
raise AllocationException("failed to allocate cli")
|
324
|
+
|
325
|
+
self.poll_fd = poll_fd
|
326
|
+
|
327
|
+
def _free(
|
328
|
+
self,
|
329
|
+
) -> None:
|
330
|
+
self.ffi_mapping.shared_mapping.free(ptr=self._ptr_or_exception())
|
331
|
+
|
332
|
+
@property
|
333
|
+
def ntc_templates_platform(self) -> str:
|
334
|
+
"""
|
335
|
+
Returns the ntc templates platform for the cli object.
|
336
|
+
|
337
|
+
Args:
|
338
|
+
N/A
|
339
|
+
|
340
|
+
Returns:
|
341
|
+
str: the ntc templates platform name
|
342
|
+
|
343
|
+
Raises:
|
344
|
+
N/A
|
345
|
+
|
346
|
+
"""
|
347
|
+
if self._ntc_templates_platform is not None:
|
348
|
+
return self._ntc_templates_platform
|
349
|
+
|
350
|
+
ntc_templates_platform = ZigSlice(size=c_int(256))
|
351
|
+
|
352
|
+
status = self.ffi_mapping.cli_mapping.get_ntc_templates_platform(
|
353
|
+
ptr=self._ptr_or_exception(),
|
354
|
+
ntc_templates_platform=ntc_templates_platform,
|
355
|
+
)
|
356
|
+
if status != 0:
|
357
|
+
raise GetResultException("failed to retrieve ntc templates platform")
|
358
|
+
|
359
|
+
self._ntc_templates_platform = ntc_templates_platform.get_decoded_contents().strip("\x00")
|
360
|
+
|
361
|
+
return self._ntc_templates_platform
|
362
|
+
|
363
|
+
@property
|
364
|
+
def genie_platform(self) -> str:
|
365
|
+
"""
|
366
|
+
Returns the genie platform for the cli object.
|
367
|
+
|
368
|
+
Args:
|
369
|
+
N/A
|
370
|
+
|
371
|
+
Returns:
|
372
|
+
str: the genie platform name
|
373
|
+
|
374
|
+
Raises:
|
375
|
+
N/A
|
376
|
+
|
377
|
+
"""
|
378
|
+
if self._genie_platform is not None:
|
379
|
+
return self._genie_platform
|
380
|
+
|
381
|
+
genie_platform = ZigSlice(size=c_int(256))
|
382
|
+
|
383
|
+
status = self.ffi_mapping.cli_mapping.get_ntc_templates_platform(
|
384
|
+
ptr=self._ptr_or_exception(),
|
385
|
+
ntc_templates_platform=genie_platform,
|
386
|
+
)
|
387
|
+
if status != 0:
|
388
|
+
raise GetResultException("failed to retrieve genie templates platform")
|
389
|
+
|
390
|
+
self._genie_platform = genie_platform.get_decoded_contents().strip("\x00")
|
391
|
+
|
392
|
+
return self._genie_platform
|
393
|
+
|
394
|
+
def _open(
|
395
|
+
self,
|
396
|
+
operation_id: OperationIdPointer,
|
397
|
+
cancel: CancelPointer,
|
398
|
+
) -> c_uint:
|
399
|
+
self._alloc()
|
400
|
+
|
401
|
+
self.auth_options.apply(self.ffi_mapping, self._ptr_or_exception())
|
402
|
+
self.session_options.apply(self.ffi_mapping, self._ptr_or_exception())
|
403
|
+
self.transport_options.apply(self.ffi_mapping, self._ptr_or_exception())
|
404
|
+
|
405
|
+
status = self.ffi_mapping.cli_mapping.open(
|
406
|
+
ptr=self._ptr_or_exception(),
|
407
|
+
operation_id=operation_id,
|
408
|
+
cancel=cancel,
|
409
|
+
)
|
410
|
+
if status != 0:
|
411
|
+
self._free()
|
412
|
+
|
413
|
+
raise OpenException("failed to submit open operation")
|
414
|
+
|
415
|
+
return c_uint(operation_id.contents.value)
|
416
|
+
|
417
|
+
def open(
|
418
|
+
self,
|
419
|
+
) -> Result:
|
420
|
+
"""
|
421
|
+
Open the cli connection.
|
422
|
+
|
423
|
+
Args:
|
424
|
+
N/A
|
425
|
+
|
426
|
+
Returns:
|
427
|
+
None
|
428
|
+
|
429
|
+
Raises:
|
430
|
+
OpenException: if the operation fails
|
431
|
+
|
432
|
+
"""
|
433
|
+
operation_id = OperationIdPointer(c_uint(0))
|
434
|
+
cancel = CancelPointer(c_bool(False))
|
435
|
+
|
436
|
+
operation_id = self._open(operation_id=operation_id, cancel=cancel)
|
437
|
+
|
438
|
+
return self._get_result(operation_id=operation_id)
|
439
|
+
|
440
|
+
async def open_async(self) -> Result:
|
441
|
+
"""
|
442
|
+
Open the cli connection.
|
443
|
+
|
444
|
+
Args:
|
445
|
+
N/A
|
446
|
+
|
447
|
+
Returns:
|
448
|
+
None
|
449
|
+
|
450
|
+
Raises:
|
451
|
+
OpenException: if the operation fails
|
452
|
+
|
453
|
+
"""
|
454
|
+
operation_id = OperationIdPointer(c_uint(0))
|
455
|
+
cancel = CancelPointer(c_bool(False))
|
456
|
+
|
457
|
+
operation_id = self._open(operation_id=operation_id, cancel=cancel)
|
458
|
+
|
459
|
+
return await self._get_result_async(operation_id=operation_id)
|
460
|
+
|
461
|
+
def _close(self) -> c_uint:
|
462
|
+
operation_id = OperationIdPointer(c_uint(0))
|
463
|
+
cancel = CancelPointer(c_bool(False))
|
464
|
+
|
465
|
+
status = self.ffi_mapping.cli_mapping.close(
|
466
|
+
ptr=self._ptr_or_exception(), operation_id=operation_id, cancel=cancel
|
467
|
+
)
|
468
|
+
if status != 0:
|
469
|
+
raise CloseException("submitting close operation")
|
470
|
+
|
471
|
+
return c_uint(operation_id.contents.value)
|
472
|
+
|
473
|
+
def close(
|
474
|
+
self,
|
475
|
+
) -> Result:
|
476
|
+
"""
|
477
|
+
Close the cli connection.
|
478
|
+
|
479
|
+
Args:
|
480
|
+
N/A
|
481
|
+
|
482
|
+
Returns:
|
483
|
+
None
|
484
|
+
|
485
|
+
Raises:
|
486
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
487
|
+
CloseException: if the operation fails
|
488
|
+
|
489
|
+
"""
|
490
|
+
operation_id = self._close()
|
491
|
+
|
492
|
+
result = self._get_result(operation_id=operation_id)
|
493
|
+
|
494
|
+
self._free()
|
495
|
+
|
496
|
+
return result
|
497
|
+
|
498
|
+
async def close_async(
|
499
|
+
self,
|
500
|
+
) -> Result:
|
501
|
+
"""
|
502
|
+
Close the cli connection.
|
503
|
+
|
504
|
+
Args:
|
505
|
+
N/A
|
506
|
+
|
507
|
+
Returns:
|
508
|
+
None
|
509
|
+
|
510
|
+
Raises:
|
511
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
512
|
+
CloseException: if the operation fails
|
513
|
+
|
514
|
+
"""
|
515
|
+
operation_id = self._close()
|
516
|
+
|
517
|
+
result = await self._get_result_async(operation_id=operation_id)
|
518
|
+
|
519
|
+
self._free()
|
520
|
+
|
521
|
+
return result
|
522
|
+
|
523
|
+
def _get_result(
|
524
|
+
self,
|
525
|
+
operation_id: c_uint,
|
526
|
+
) -> Result:
|
527
|
+
wait_for_available_operation_result(self.poll_fd)
|
528
|
+
|
529
|
+
operation_count = IntPointer(c_int())
|
530
|
+
inputs_size = IntPointer(c_int())
|
531
|
+
results_raw_size = IntPointer(c_int())
|
532
|
+
results_size = IntPointer(c_int())
|
533
|
+
results_failed_indicator_size = IntPointer(c_int())
|
534
|
+
err_size = IntPointer(c_int())
|
535
|
+
|
536
|
+
status = self.ffi_mapping.cli_mapping.fetch_sizes(
|
537
|
+
ptr=self._ptr_or_exception(),
|
538
|
+
operation_id=operation_id,
|
539
|
+
operation_count=operation_count,
|
540
|
+
inputs_size=inputs_size,
|
541
|
+
results_raw_size=results_raw_size,
|
542
|
+
results_size=results_size,
|
543
|
+
results_failed_indicator_size=results_failed_indicator_size,
|
544
|
+
err_size=err_size,
|
545
|
+
)
|
546
|
+
if status != 0:
|
547
|
+
raise GetResultException("wait operation failed")
|
548
|
+
|
549
|
+
start_time = U64Pointer(c_uint64())
|
550
|
+
splits = ZigU64Slice(size=operation_count.contents)
|
551
|
+
|
552
|
+
inputs_slice = ZigSlice(size=inputs_size.contents)
|
553
|
+
results_raw_slice = ZigSlice(size=results_raw_size.contents)
|
554
|
+
results_slice = ZigSlice(size=results_size.contents)
|
555
|
+
|
556
|
+
results_failed_indicator_slice = ZigSlice(size=results_failed_indicator_size.contents)
|
557
|
+
err_slice = ZigSlice(size=err_size.contents)
|
558
|
+
|
559
|
+
status = self.ffi_mapping.cli_mapping.fetch(
|
560
|
+
ptr=self._ptr_or_exception(),
|
561
|
+
operation_id=operation_id,
|
562
|
+
start_time=start_time,
|
563
|
+
splits=splits,
|
564
|
+
inputs_slice=inputs_slice,
|
565
|
+
results_raw_slice=results_raw_slice,
|
566
|
+
results_slice=results_slice,
|
567
|
+
results_failed_indicator_slice=results_failed_indicator_slice,
|
568
|
+
err_slice=err_slice,
|
569
|
+
)
|
570
|
+
if status != 0:
|
571
|
+
raise GetResultException("fetch operation failed")
|
572
|
+
|
573
|
+
err_contents = err_slice.get_decoded_contents()
|
574
|
+
if err_contents:
|
575
|
+
raise OperationException(err_contents)
|
576
|
+
|
577
|
+
return Result(
|
578
|
+
inputs=inputs_slice.get_decoded_contents(),
|
579
|
+
host=self.host,
|
580
|
+
port=self.port,
|
581
|
+
start_time=start_time.contents.value,
|
582
|
+
splits=splits.get_contents(),
|
583
|
+
results_raw=results_raw_slice.get_contents(),
|
584
|
+
results=results_slice.get_decoded_contents(),
|
585
|
+
results_failed_indicator=results_failed_indicator_slice.get_decoded_contents(),
|
586
|
+
textfsm_platform=self.ntc_templates_platform,
|
587
|
+
genie_platform=self.genie_platform,
|
588
|
+
)
|
589
|
+
|
590
|
+
async def _get_result_async(
|
591
|
+
self,
|
592
|
+
operation_id: c_uint,
|
593
|
+
) -> Result:
|
594
|
+
await wait_for_available_operation_result_async(fd=self.poll_fd)
|
595
|
+
|
596
|
+
operation_count = IntPointer(c_int())
|
597
|
+
inputs_size = IntPointer(c_int())
|
598
|
+
results_raw_size = IntPointer(c_int())
|
599
|
+
results_size = IntPointer(c_int())
|
600
|
+
results_failed_indicator_size = IntPointer(c_int())
|
601
|
+
err_size = IntPointer(c_int())
|
602
|
+
|
603
|
+
status = self.ffi_mapping.cli_mapping.fetch_sizes(
|
604
|
+
ptr=self._ptr_or_exception(),
|
605
|
+
operation_id=operation_id,
|
606
|
+
operation_count=operation_count,
|
607
|
+
inputs_size=inputs_size,
|
608
|
+
results_raw_size=results_raw_size,
|
609
|
+
results_size=results_size,
|
610
|
+
results_failed_indicator_size=results_failed_indicator_size,
|
611
|
+
err_size=err_size,
|
612
|
+
)
|
613
|
+
if status != 0:
|
614
|
+
raise GetResultException("fetch operation sizes failed")
|
615
|
+
|
616
|
+
start_time = U64Pointer(c_uint64())
|
617
|
+
splits = ZigU64Slice(size=operation_count.contents)
|
618
|
+
|
619
|
+
inputs_slice = ZigSlice(size=inputs_size.contents)
|
620
|
+
results_raw_slice = ZigSlice(size=results_raw_size.contents)
|
621
|
+
results_slice = ZigSlice(size=results_size.contents)
|
622
|
+
|
623
|
+
results_failed_indicator_slice = ZigSlice(size=results_failed_indicator_size.contents)
|
624
|
+
err_slice = ZigSlice(size=err_size.contents)
|
625
|
+
|
626
|
+
status = self.ffi_mapping.cli_mapping.fetch(
|
627
|
+
ptr=self._ptr_or_exception(),
|
628
|
+
operation_id=operation_id,
|
629
|
+
start_time=start_time,
|
630
|
+
splits=splits,
|
631
|
+
inputs_slice=inputs_slice,
|
632
|
+
results_raw_slice=results_raw_slice,
|
633
|
+
results_slice=results_slice,
|
634
|
+
results_failed_indicator_slice=results_failed_indicator_slice,
|
635
|
+
err_slice=err_slice,
|
636
|
+
)
|
637
|
+
if status != 0:
|
638
|
+
raise GetResultException("fetch operation failed")
|
639
|
+
|
640
|
+
err_contents = err_slice.get_decoded_contents()
|
641
|
+
if err_contents:
|
642
|
+
raise OperationException(err_contents)
|
643
|
+
|
644
|
+
return Result(
|
645
|
+
inputs=inputs_slice.get_decoded_contents(),
|
646
|
+
host=self.host,
|
647
|
+
port=self.port,
|
648
|
+
start_time=start_time.contents.value,
|
649
|
+
splits=splits.get_contents(),
|
650
|
+
results_raw=results_raw_slice.get_contents(),
|
651
|
+
results=results_slice.get_decoded_contents(),
|
652
|
+
results_failed_indicator=results_failed_indicator_slice.get_decoded_contents(),
|
653
|
+
textfsm_platform=self.ntc_templates_platform,
|
654
|
+
genie_platform=self.genie_platform,
|
655
|
+
)
|
656
|
+
|
657
|
+
def _enter_mode(
|
658
|
+
self,
|
659
|
+
*,
|
660
|
+
operation_id: OperationIdPointer,
|
661
|
+
cancel: CancelPointer,
|
662
|
+
requested_mode: c_char_p,
|
663
|
+
) -> c_uint:
|
664
|
+
status = self.ffi_mapping.cli_mapping.enter_mode(
|
665
|
+
ptr=self._ptr_or_exception(),
|
666
|
+
operation_id=operation_id,
|
667
|
+
cancel=cancel,
|
668
|
+
requested_mode=requested_mode,
|
669
|
+
)
|
670
|
+
if status != 0:
|
671
|
+
raise SubmitOperationException("submitting get prompt operation failed")
|
672
|
+
|
673
|
+
return c_uint(operation_id.contents.value)
|
674
|
+
|
675
|
+
@handle_operation_timeout
|
676
|
+
def enter_mode(
|
677
|
+
self,
|
678
|
+
requested_mode: str,
|
679
|
+
*,
|
680
|
+
operation_timeout_ns: int | None = None,
|
681
|
+
) -> Result:
|
682
|
+
"""
|
683
|
+
Enter the given mode on the cli connection.
|
684
|
+
|
685
|
+
Args:
|
686
|
+
requested_mode: name of the mode to enter
|
687
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
688
|
+
|
689
|
+
Returns:
|
690
|
+
Result: a Result object representing the operation
|
691
|
+
|
692
|
+
Raises:
|
693
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
694
|
+
SubmitOperationException: if the operation fails
|
695
|
+
|
696
|
+
"""
|
697
|
+
# only used in the decorator
|
698
|
+
_ = operation_timeout_ns
|
699
|
+
|
700
|
+
operation_id = OperationIdPointer(c_uint(0))
|
701
|
+
cancel = CancelPointer(c_bool(False))
|
702
|
+
|
703
|
+
_requested_mode = to_c_string(requested_mode)
|
704
|
+
|
705
|
+
operation_id = self._enter_mode(
|
706
|
+
operation_id=operation_id, cancel=cancel, requested_mode=_requested_mode
|
707
|
+
)
|
708
|
+
|
709
|
+
return self._get_result(operation_id=operation_id)
|
710
|
+
|
711
|
+
@handle_operation_timeout_async
|
712
|
+
async def enter_mode_async(
|
713
|
+
self,
|
714
|
+
requested_mode: str,
|
715
|
+
*,
|
716
|
+
operation_timeout_ns: int | None = None,
|
717
|
+
) -> Result:
|
718
|
+
"""
|
719
|
+
Enter the given mode on the cli connection.
|
720
|
+
|
721
|
+
Args:
|
722
|
+
requested_mode: name of the mode to enter
|
723
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
724
|
+
|
725
|
+
Returns:
|
726
|
+
Result: a Result object representing the operation
|
727
|
+
|
728
|
+
Raises:
|
729
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
730
|
+
SubmitOperationException: if the operation fails
|
731
|
+
|
732
|
+
"""
|
733
|
+
# only used in the decorator
|
734
|
+
_ = operation_timeout_ns
|
735
|
+
|
736
|
+
operation_id = OperationIdPointer(c_uint(0))
|
737
|
+
cancel = CancelPointer(c_bool(False))
|
738
|
+
|
739
|
+
_requested_mode = to_c_string(requested_mode)
|
740
|
+
|
741
|
+
operation_id = self._enter_mode(
|
742
|
+
operation_id=operation_id, cancel=cancel, requested_mode=_requested_mode
|
743
|
+
)
|
744
|
+
|
745
|
+
return await self._get_result_async(operation_id=operation_id)
|
746
|
+
|
747
|
+
def _get_prompt(
|
748
|
+
self,
|
749
|
+
*,
|
750
|
+
operation_id: OperationIdPointer,
|
751
|
+
cancel: CancelPointer,
|
752
|
+
) -> c_uint:
|
753
|
+
status = self.ffi_mapping.cli_mapping.get_prompt(
|
754
|
+
ptr=self._ptr_or_exception(),
|
755
|
+
operation_id=operation_id,
|
756
|
+
cancel=cancel,
|
757
|
+
)
|
758
|
+
if status != 0:
|
759
|
+
raise SubmitOperationException("submitting get prompt operation failed")
|
760
|
+
|
761
|
+
return c_uint(operation_id.contents.value)
|
762
|
+
|
763
|
+
@handle_operation_timeout
|
764
|
+
def get_prompt(
|
765
|
+
self,
|
766
|
+
*,
|
767
|
+
operation_timeout_ns: int | None = None,
|
768
|
+
) -> Result:
|
769
|
+
"""
|
770
|
+
Get the current prompt of the cli connection.
|
771
|
+
|
772
|
+
Args:
|
773
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
774
|
+
|
775
|
+
Returns:
|
776
|
+
Result: a Result object representing the operation
|
777
|
+
|
778
|
+
Raises:
|
779
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
780
|
+
SubmitOperationException: if the operation fails
|
781
|
+
|
782
|
+
"""
|
783
|
+
# only used in the decorator
|
784
|
+
_ = operation_timeout_ns
|
785
|
+
|
786
|
+
operation_id = OperationIdPointer(c_uint(0))
|
787
|
+
cancel = CancelPointer(c_bool(False))
|
788
|
+
|
789
|
+
operation_id = self._get_prompt(operation_id=operation_id, cancel=cancel)
|
790
|
+
|
791
|
+
return self._get_result(operation_id=operation_id)
|
792
|
+
|
793
|
+
@handle_operation_timeout_async
|
794
|
+
async def get_prompt_async(
|
795
|
+
self,
|
796
|
+
*,
|
797
|
+
operation_timeout_ns: int | None = None,
|
798
|
+
) -> Result:
|
799
|
+
"""
|
800
|
+
Get the current prompt of the cli connection.
|
801
|
+
|
802
|
+
Args:
|
803
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
804
|
+
|
805
|
+
Returns:
|
806
|
+
Result: a Result object representing the operation
|
807
|
+
|
808
|
+
Raises:
|
809
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
810
|
+
SubmitOperationException: if the operation fails
|
811
|
+
|
812
|
+
"""
|
813
|
+
# only used in the decorator
|
814
|
+
_ = operation_timeout_ns
|
815
|
+
|
816
|
+
operation_id = OperationIdPointer(c_uint(0))
|
817
|
+
cancel = CancelPointer(c_bool(False))
|
818
|
+
|
819
|
+
operation_id = self._get_prompt(operation_id=operation_id, cancel=cancel)
|
820
|
+
|
821
|
+
return await self._get_result_async(operation_id=operation_id)
|
822
|
+
|
823
|
+
def _send_input( # noqa: PLR0913
|
824
|
+
self,
|
825
|
+
*,
|
826
|
+
operation_id: OperationIdPointer,
|
827
|
+
cancel: CancelPointer,
|
828
|
+
input_: c_char_p,
|
829
|
+
requested_mode: c_char_p,
|
830
|
+
input_handling: c_char_p,
|
831
|
+
retain_input: c_bool,
|
832
|
+
retain_trailing_prompt: c_bool,
|
833
|
+
) -> c_uint:
|
834
|
+
status = self.ffi_mapping.cli_mapping.send_input(
|
835
|
+
ptr=self._ptr_or_exception(),
|
836
|
+
operation_id=operation_id,
|
837
|
+
cancel=cancel,
|
838
|
+
input_=input_,
|
839
|
+
requested_mode=requested_mode,
|
840
|
+
input_handling=input_handling,
|
841
|
+
retain_input=retain_input,
|
842
|
+
retain_trailing_prompt=retain_trailing_prompt,
|
843
|
+
)
|
844
|
+
if status != 0:
|
845
|
+
raise SubmitOperationException("submitting send input operation failed")
|
846
|
+
|
847
|
+
return c_uint(operation_id.contents.value)
|
848
|
+
|
849
|
+
@handle_operation_timeout
|
850
|
+
def send_input( # noqa: PLR0913
|
851
|
+
self,
|
852
|
+
input_: str,
|
853
|
+
*,
|
854
|
+
requested_mode: str = "",
|
855
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
856
|
+
retain_input: bool = False,
|
857
|
+
retain_trailing_prompt: bool = False,
|
858
|
+
operation_timeout_ns: int | None = None,
|
859
|
+
) -> Result:
|
860
|
+
"""
|
861
|
+
Send an input on the cli connection.
|
862
|
+
|
863
|
+
Args:
|
864
|
+
input_: the input to send
|
865
|
+
requested_mode: name of the mode to send the input at
|
866
|
+
input_handling: how to handle the input
|
867
|
+
retain_input: retain the input in the final "result"
|
868
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
869
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
870
|
+
|
871
|
+
Returns:
|
872
|
+
Result: a Result object representing the operation
|
873
|
+
|
874
|
+
Raises:
|
875
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
876
|
+
SubmitOperationException: if the operation fails
|
877
|
+
|
878
|
+
"""
|
879
|
+
# only used in the decorator
|
880
|
+
_ = operation_timeout_ns
|
881
|
+
|
882
|
+
operation_id = OperationIdPointer(c_uint(0))
|
883
|
+
cancel = CancelPointer(c_bool(False))
|
884
|
+
|
885
|
+
_input = to_c_string(input_)
|
886
|
+
_requested_mode = to_c_string(requested_mode)
|
887
|
+
_input_handling = to_c_string(input_handling)
|
888
|
+
|
889
|
+
operation_id = self._send_input(
|
890
|
+
operation_id=operation_id,
|
891
|
+
cancel=cancel,
|
892
|
+
input_=_input,
|
893
|
+
requested_mode=_requested_mode,
|
894
|
+
input_handling=_input_handling,
|
895
|
+
retain_input=c_bool(retain_input),
|
896
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
897
|
+
)
|
898
|
+
|
899
|
+
return self._get_result(operation_id=operation_id)
|
900
|
+
|
901
|
+
@handle_operation_timeout_async
|
902
|
+
async def send_input_async( # noqa: PLR0913
|
903
|
+
self,
|
904
|
+
input_: str,
|
905
|
+
*,
|
906
|
+
requested_mode: str = "",
|
907
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
908
|
+
retain_input: bool = False,
|
909
|
+
retain_trailing_prompt: bool = False,
|
910
|
+
operation_timeout_ns: int | None = None,
|
911
|
+
) -> Result:
|
912
|
+
"""
|
913
|
+
Send an input on the cli connection.
|
914
|
+
|
915
|
+
Args:
|
916
|
+
input_: the input to send
|
917
|
+
requested_mode: name of the mode to send the input at
|
918
|
+
input_handling: how to handle the input
|
919
|
+
retain_input: retain the input in the final "result"
|
920
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
921
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
922
|
+
|
923
|
+
Returns:
|
924
|
+
Result: a Result object representing the operation
|
925
|
+
|
926
|
+
Raises:
|
927
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
928
|
+
SubmitOperationException: if the operation fails
|
929
|
+
|
930
|
+
"""
|
931
|
+
# only used in the decorator
|
932
|
+
_ = operation_timeout_ns
|
933
|
+
|
934
|
+
operation_id = OperationIdPointer(c_uint(0))
|
935
|
+
cancel = CancelPointer(c_bool(False))
|
936
|
+
|
937
|
+
_input = to_c_string(input_)
|
938
|
+
_requested_mode = to_c_string(requested_mode)
|
939
|
+
_input_handling = to_c_string(input_handling)
|
940
|
+
|
941
|
+
operation_id = self._send_input(
|
942
|
+
operation_id=operation_id,
|
943
|
+
cancel=cancel,
|
944
|
+
input_=_input,
|
945
|
+
requested_mode=_requested_mode,
|
946
|
+
input_handling=_input_handling,
|
947
|
+
retain_input=c_bool(retain_input),
|
948
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
949
|
+
)
|
950
|
+
|
951
|
+
return await self._get_result_async(operation_id=operation_id)
|
952
|
+
|
953
|
+
@handle_operation_timeout
|
954
|
+
def send_inputs( # noqa: PLR0913
|
955
|
+
self,
|
956
|
+
inputs: list[str],
|
957
|
+
*,
|
958
|
+
requested_mode: str = "",
|
959
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
960
|
+
retain_input: bool = False,
|
961
|
+
retain_trailing_prompt: bool = False,
|
962
|
+
stop_on_indicated_failure: bool = True,
|
963
|
+
operation_timeout_ns: int | None = None,
|
964
|
+
) -> Result:
|
965
|
+
"""
|
966
|
+
Send inputs (plural!) on the cli connection.
|
967
|
+
|
968
|
+
Args:
|
969
|
+
inputs: the inputs to send
|
970
|
+
requested_mode: name of the mode to send the input at`
|
971
|
+
input_handling: how to handle the input
|
972
|
+
retain_input: retain the input in the final "result"
|
973
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
974
|
+
stop_on_indicated_failure: stops sending inputs at first indicated failure
|
975
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
976
|
+
|
977
|
+
Returns:
|
978
|
+
Result: a Result object representing the operation
|
979
|
+
|
980
|
+
Raises:
|
981
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
982
|
+
SubmitOperationException: if the operation fails
|
983
|
+
|
984
|
+
"""
|
985
|
+
# only used in the decorator; note that the timeout here is for the whole operation,
|
986
|
+
# meaning all the "inputs" combined, not individually
|
987
|
+
_ = operation_timeout_ns
|
988
|
+
|
989
|
+
cancel = CancelPointer(c_bool(False))
|
990
|
+
|
991
|
+
result: Result | None = None
|
992
|
+
|
993
|
+
for input_ in inputs:
|
994
|
+
operation_id = OperationIdPointer(c_uint(0))
|
995
|
+
|
996
|
+
_input = to_c_string(input_)
|
997
|
+
_requested_mode = to_c_string(requested_mode)
|
998
|
+
_input_handling = to_c_string(input_handling)
|
999
|
+
|
1000
|
+
operation_id = self._send_input(
|
1001
|
+
operation_id=operation_id,
|
1002
|
+
cancel=cancel,
|
1003
|
+
input_=_input,
|
1004
|
+
requested_mode=_requested_mode,
|
1005
|
+
input_handling=_input_handling,
|
1006
|
+
retain_input=c_bool(retain_input),
|
1007
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
1008
|
+
)
|
1009
|
+
|
1010
|
+
_result = self._get_result(operation_id=operation_id)
|
1011
|
+
|
1012
|
+
if result is None:
|
1013
|
+
result = _result
|
1014
|
+
else:
|
1015
|
+
result.extend(result=_result)
|
1016
|
+
|
1017
|
+
if result.failed and stop_on_indicated_failure:
|
1018
|
+
return result
|
1019
|
+
|
1020
|
+
return result # type: ignore[return-value]
|
1021
|
+
|
1022
|
+
@handle_operation_timeout_async
|
1023
|
+
async def send_inputs_async( # noqa: PLR0913
|
1024
|
+
self,
|
1025
|
+
inputs: list[str],
|
1026
|
+
*,
|
1027
|
+
requested_mode: str = "",
|
1028
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
1029
|
+
retain_input: bool = False,
|
1030
|
+
retain_trailing_prompt: bool = False,
|
1031
|
+
stop_on_indicated_failure: bool = True,
|
1032
|
+
operation_timeout_ns: int | None = None,
|
1033
|
+
) -> Result:
|
1034
|
+
"""
|
1035
|
+
Send inputs (plural!) on the cli connection.
|
1036
|
+
|
1037
|
+
Args:
|
1038
|
+
inputs: the inputs to send
|
1039
|
+
requested_mode: name of the mode to send the input at`
|
1040
|
+
input_handling: how to handle the input
|
1041
|
+
retain_input: retain the input in the final "result"
|
1042
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
1043
|
+
stop_on_indicated_failure: stops sending inputs at first indicated failure
|
1044
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
1045
|
+
|
1046
|
+
Returns:
|
1047
|
+
MultiResult: a MultiResult object representing the operations
|
1048
|
+
|
1049
|
+
Raises:
|
1050
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
1051
|
+
SubmitOperationException: if the operation fails
|
1052
|
+
|
1053
|
+
"""
|
1054
|
+
# only used in the decorator; note that the timeout here is for the whole operation,
|
1055
|
+
# meaning all the "inputs" combined, not individually
|
1056
|
+
_ = operation_timeout_ns
|
1057
|
+
|
1058
|
+
cancel = CancelPointer(c_bool(False))
|
1059
|
+
|
1060
|
+
result: Result | None = None
|
1061
|
+
|
1062
|
+
for input_ in inputs:
|
1063
|
+
operation_id = OperationIdPointer(c_uint(0))
|
1064
|
+
|
1065
|
+
_input = to_c_string(input_)
|
1066
|
+
_requested_mode = to_c_string(requested_mode)
|
1067
|
+
_input_handling = to_c_string(input_handling)
|
1068
|
+
|
1069
|
+
operation_id = self._send_input(
|
1070
|
+
operation_id=operation_id,
|
1071
|
+
cancel=cancel,
|
1072
|
+
input_=_input,
|
1073
|
+
requested_mode=_requested_mode,
|
1074
|
+
input_handling=_input_handling,
|
1075
|
+
retain_input=c_bool(retain_input),
|
1076
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
1077
|
+
)
|
1078
|
+
|
1079
|
+
_result = await self._get_result_async(operation_id=operation_id)
|
1080
|
+
if result is None:
|
1081
|
+
result = _result
|
1082
|
+
else:
|
1083
|
+
result.extend(result=_result)
|
1084
|
+
|
1085
|
+
if result.failed and stop_on_indicated_failure:
|
1086
|
+
return result
|
1087
|
+
|
1088
|
+
return result # type: ignore[return-value]
|
1089
|
+
|
1090
|
+
def send_inputs_from_file( # noqa: PLR0913
|
1091
|
+
self,
|
1092
|
+
f: str,
|
1093
|
+
*,
|
1094
|
+
requested_mode: str = "",
|
1095
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
1096
|
+
retain_input: bool = False,
|
1097
|
+
retain_trailing_prompt: bool = False,
|
1098
|
+
stop_on_indicated_failure: bool = True,
|
1099
|
+
operation_timeout_ns: int | None = None,
|
1100
|
+
) -> Result:
|
1101
|
+
"""
|
1102
|
+
Send inputs (plural! from a file, line-by-line) on the cli connection.
|
1103
|
+
|
1104
|
+
Args:
|
1105
|
+
f: the file to load -- each line will be sent, tralining newlines ignored
|
1106
|
+
requested_mode: name of the mode to send the input at`
|
1107
|
+
input_handling: how to handle the input
|
1108
|
+
retain_input: retain the input in the final "result"
|
1109
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
1110
|
+
stop_on_indicated_failure: stops sending inputs at first indicated failure
|
1111
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
1112
|
+
|
1113
|
+
Returns:
|
1114
|
+
MultiResult: a MultiResult object representing the operations
|
1115
|
+
|
1116
|
+
Raises:
|
1117
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
1118
|
+
SubmitOperationException: if the operation fails
|
1119
|
+
|
1120
|
+
"""
|
1121
|
+
with open(resolve_file(f), encoding="utf-8", mode="r") as _f:
|
1122
|
+
inputs = _f.read().splitlines()
|
1123
|
+
|
1124
|
+
return self.send_inputs(
|
1125
|
+
inputs=inputs,
|
1126
|
+
requested_mode=requested_mode,
|
1127
|
+
input_handling=input_handling,
|
1128
|
+
retain_input=retain_input,
|
1129
|
+
retain_trailing_prompt=retain_trailing_prompt,
|
1130
|
+
stop_on_indicated_failure=stop_on_indicated_failure,
|
1131
|
+
operation_timeout_ns=operation_timeout_ns,
|
1132
|
+
)
|
1133
|
+
|
1134
|
+
async def send_inputs_from_file_async( # noqa: PLR0913
|
1135
|
+
self,
|
1136
|
+
f: str,
|
1137
|
+
*,
|
1138
|
+
requested_mode: str = "",
|
1139
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
1140
|
+
retain_input: bool = False,
|
1141
|
+
retain_trailing_prompt: bool = False,
|
1142
|
+
stop_on_indicated_failure: bool = True,
|
1143
|
+
operation_timeout_ns: int | None = None,
|
1144
|
+
) -> Result:
|
1145
|
+
"""
|
1146
|
+
Send inputs (plural! from a file, line-by-line) on the cli connection.
|
1147
|
+
|
1148
|
+
Args:
|
1149
|
+
f: the file to load -- each line will be sent, tralining newlines ignored
|
1150
|
+
requested_mode: name of the mode to send the input at`
|
1151
|
+
input_handling: how to handle the input
|
1152
|
+
retain_input: retain the input in the final "result"
|
1153
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
1154
|
+
stop_on_indicated_failure: stops sending inputs at first indicated failure
|
1155
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
1156
|
+
|
1157
|
+
Returns:
|
1158
|
+
MultiResult: a MultiResult object representing the operations
|
1159
|
+
|
1160
|
+
Raises:
|
1161
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
1162
|
+
SubmitOperationException: if the operation fails
|
1163
|
+
|
1164
|
+
"""
|
1165
|
+
with open(resolve_file(f), encoding="utf-8", mode="r") as _f:
|
1166
|
+
inputs = _f.read().splitlines()
|
1167
|
+
|
1168
|
+
return await self.send_inputs_async(
|
1169
|
+
inputs=inputs,
|
1170
|
+
requested_mode=requested_mode,
|
1171
|
+
input_handling=input_handling,
|
1172
|
+
retain_input=retain_input,
|
1173
|
+
retain_trailing_prompt=retain_trailing_prompt,
|
1174
|
+
stop_on_indicated_failure=stop_on_indicated_failure,
|
1175
|
+
operation_timeout_ns=operation_timeout_ns,
|
1176
|
+
)
|
1177
|
+
|
1178
|
+
def _send_prompted_input( # noqa: PLR0913
|
1179
|
+
self,
|
1180
|
+
*,
|
1181
|
+
operation_id: OperationIdPointer,
|
1182
|
+
cancel: CancelPointer,
|
1183
|
+
input_: c_char_p,
|
1184
|
+
prompt: c_char_p,
|
1185
|
+
prompt_pattern: c_char_p,
|
1186
|
+
response: c_char_p,
|
1187
|
+
hidden_response: c_bool,
|
1188
|
+
abort_input: c_char_p,
|
1189
|
+
requested_mode: c_char_p,
|
1190
|
+
input_handling: c_char_p,
|
1191
|
+
retain_trailing_prompt: c_bool,
|
1192
|
+
) -> c_uint:
|
1193
|
+
status = self.ffi_mapping.cli_mapping.send_prompted_input(
|
1194
|
+
ptr=self._ptr_or_exception(),
|
1195
|
+
operation_id=operation_id,
|
1196
|
+
cancel=cancel,
|
1197
|
+
input_=input_,
|
1198
|
+
prompt=prompt,
|
1199
|
+
prompt_pattern=prompt_pattern,
|
1200
|
+
response=response,
|
1201
|
+
hidden_response=hidden_response,
|
1202
|
+
abort_input=abort_input,
|
1203
|
+
requested_mode=requested_mode,
|
1204
|
+
input_handling=input_handling,
|
1205
|
+
retain_trailing_prompt=retain_trailing_prompt,
|
1206
|
+
)
|
1207
|
+
if status != 0:
|
1208
|
+
raise SubmitOperationException("submitting send prompted input operation failed")
|
1209
|
+
|
1210
|
+
return c_uint(operation_id.contents.value)
|
1211
|
+
|
1212
|
+
@handle_operation_timeout
|
1213
|
+
def send_prompted_input( # noqa: PLR0913
|
1214
|
+
self,
|
1215
|
+
input_: str,
|
1216
|
+
prompt: str,
|
1217
|
+
prompt_pattern: str,
|
1218
|
+
response: str,
|
1219
|
+
*,
|
1220
|
+
requested_mode: str = "",
|
1221
|
+
abort_input: str = "",
|
1222
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
1223
|
+
hidden_response: bool = False,
|
1224
|
+
retain_trailing_prompt: bool = False,
|
1225
|
+
operation_timeout_ns: int | None = None,
|
1226
|
+
) -> Result:
|
1227
|
+
"""
|
1228
|
+
Send a prompted input on the cli connection.
|
1229
|
+
|
1230
|
+
Args:
|
1231
|
+
input_: the input to send
|
1232
|
+
prompt: the prompt to respond to (must set this or prompt_pattern)
|
1233
|
+
prompt_pattern: the prompt pattern to respond to (must set this or prompt)
|
1234
|
+
response: the response to send to the prompt
|
1235
|
+
abort_input: the input to send to abort the "prompted input" operation if an error
|
1236
|
+
is encountered
|
1237
|
+
requested_mode: name of the mode to send the input at
|
1238
|
+
input_handling: how to handle the input
|
1239
|
+
hidden_response: if the response input will be hidden (like for a password prompt)
|
1240
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
1241
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
1242
|
+
|
1243
|
+
Returns:
|
1244
|
+
Result: a Result object representing the operation
|
1245
|
+
|
1246
|
+
Raises:
|
1247
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
1248
|
+
SubmitOperationException: if the operation fails
|
1249
|
+
|
1250
|
+
"""
|
1251
|
+
# only used in the decorator
|
1252
|
+
_ = operation_timeout_ns
|
1253
|
+
|
1254
|
+
operation_id = OperationIdPointer(c_uint(0))
|
1255
|
+
cancel = CancelPointer(c_bool(False))
|
1256
|
+
|
1257
|
+
_input = to_c_string(input_)
|
1258
|
+
_prompt = to_c_string(prompt)
|
1259
|
+
_prompt_pattern = to_c_string(prompt_pattern)
|
1260
|
+
_response = to_c_string(response)
|
1261
|
+
_abort_input = to_c_string(abort_input)
|
1262
|
+
_requested_mode = to_c_string(requested_mode)
|
1263
|
+
_input_handling = to_c_string(input_handling)
|
1264
|
+
|
1265
|
+
operation_id = self._send_prompted_input(
|
1266
|
+
operation_id=operation_id,
|
1267
|
+
cancel=cancel,
|
1268
|
+
input_=_input,
|
1269
|
+
prompt=_prompt,
|
1270
|
+
prompt_pattern=_prompt_pattern,
|
1271
|
+
response=_response,
|
1272
|
+
abort_input=_abort_input,
|
1273
|
+
requested_mode=_requested_mode,
|
1274
|
+
input_handling=_input_handling,
|
1275
|
+
hidden_response=c_bool(hidden_response),
|
1276
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
1277
|
+
)
|
1278
|
+
|
1279
|
+
return self._get_result(operation_id=operation_id)
|
1280
|
+
|
1281
|
+
@handle_operation_timeout_async
|
1282
|
+
async def send_prompted_input_async( # noqa: PLR0913
|
1283
|
+
self,
|
1284
|
+
input_: str,
|
1285
|
+
prompt: str,
|
1286
|
+
prompt_pattern: str,
|
1287
|
+
response: str,
|
1288
|
+
*,
|
1289
|
+
abort_input: str = "",
|
1290
|
+
requested_mode: str = "",
|
1291
|
+
input_handling: InputHandling = InputHandling.FUZZY,
|
1292
|
+
hidden_response: bool = False,
|
1293
|
+
retain_trailing_prompt: bool = False,
|
1294
|
+
operation_timeout_ns: int | None = None,
|
1295
|
+
) -> Result:
|
1296
|
+
"""
|
1297
|
+
Send a prompted input on the cli connection.
|
1298
|
+
|
1299
|
+
Args:
|
1300
|
+
input_: the input to send
|
1301
|
+
prompt: the prompt to respond to (must set this or prompt_pattern)
|
1302
|
+
prompt_pattern: the prompt pattern to respond to (must set this or prompt)
|
1303
|
+
response: the response to send to the prompt
|
1304
|
+
abort_input: the input to send to abort the "prompted input" operation if an error
|
1305
|
+
is encountered
|
1306
|
+
requested_mode: name of the mode to send the input at
|
1307
|
+
input_handling: how to handle the input
|
1308
|
+
hidden_response: if the response input will be hidden (like for a password prompt)
|
1309
|
+
retain_trailing_prompt: retain the trailing prompt in the final "result"
|
1310
|
+
operation_timeout_ns: operation timeout in ns for this operation
|
1311
|
+
|
1312
|
+
Returns:
|
1313
|
+
Result: a Result object representing the operation
|
1314
|
+
|
1315
|
+
Raises:
|
1316
|
+
NotOpenedException: if the ptr to the cli object is None (via _ptr_or_exception)
|
1317
|
+
SubmitOperationException: if the operation fails
|
1318
|
+
|
1319
|
+
"""
|
1320
|
+
# only used in the decorator
|
1321
|
+
_ = operation_timeout_ns
|
1322
|
+
|
1323
|
+
operation_id = OperationIdPointer(c_uint(0))
|
1324
|
+
cancel = CancelPointer(c_bool(False))
|
1325
|
+
|
1326
|
+
_input = to_c_string(input_)
|
1327
|
+
_prompt = to_c_string(prompt)
|
1328
|
+
_prompt_pattern = to_c_string(prompt_pattern)
|
1329
|
+
_response = to_c_string(response)
|
1330
|
+
_abort_input = to_c_string(abort_input)
|
1331
|
+
_requested_mode = to_c_string(requested_mode)
|
1332
|
+
_input_handling = to_c_string(input_handling)
|
1333
|
+
|
1334
|
+
operation_id = self._send_prompted_input(
|
1335
|
+
operation_id=operation_id,
|
1336
|
+
cancel=cancel,
|
1337
|
+
input_=_input,
|
1338
|
+
prompt=_prompt,
|
1339
|
+
prompt_pattern=_prompt_pattern,
|
1340
|
+
response=_response,
|
1341
|
+
abort_input=_abort_input,
|
1342
|
+
requested_mode=_requested_mode,
|
1343
|
+
input_handling=_input_handling,
|
1344
|
+
hidden_response=c_bool(hidden_response),
|
1345
|
+
retain_trailing_prompt=c_bool(retain_trailing_prompt),
|
1346
|
+
)
|
1347
|
+
|
1348
|
+
return await self._get_result_async(operation_id=operation_id)
|
1349
|
+
|
1350
|
+
@staticmethod
|
1351
|
+
def ___getwide___() -> None: # pragma: no cover
|
1352
|
+
"""
|
1353
|
+
Dumb inside joke easter egg :)
|
1354
|
+
|
1355
|
+
Args:
|
1356
|
+
N/A
|
1357
|
+
|
1358
|
+
Returns:
|
1359
|
+
None
|
1360
|
+
|
1361
|
+
Raises:
|
1362
|
+
N/A
|
1363
|
+
|
1364
|
+
"""
|
1365
|
+
wide = r"""
|
1366
|
+
KKKXXXXXXXXXXNNNNNNNNNNNNNNNWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW
|
1367
|
+
000000000000KKKKKKKKKKXXXXXXXXXXXXXXXXXNNXXK0Okxdoolllloodxk0KXNNWWNWWWWWWWWWWWWWWWWWWWWWWWWWWWWNNNN
|
1368
|
+
kkkkkkkOOOOOOOOOOO00000000000000000000kdl:,... ..';coxOKKKKKKKKKKKKXKKXXKKKXXXXXKKKK000
|
1369
|
+
kkkkkkkOOOOOOOOOOOO000000000000000Od:,. .,cdOKKKKKKKKKKKK0000OOOOOOOOOOOO
|
1370
|
+
kkkkkkkkOOOOOOOOOOO0000000000000kc' .:d0KKKKKKKKK0KKOkOOOOOOOOOO0
|
1371
|
+
kkkkkkkkOOOOOOOOOOOO00000000000o' ,o0KKKKKKKKKKOkOOOOOOOOO00
|
1372
|
+
kkkkkkkkOOOOOOOOOOOOO000000000o. ;kKKKKKKKKKOkOOOOOOOOO00
|
1373
|
+
OOOOOOOOOO0000000000000000K0Kk' 'xKKKKKKKKOkOOOOOOOOO00
|
1374
|
+
KKKKKKKKKXXXXXXXXXXXXXXNNNNNNd. cXNNNNNNNK0000O00O0000
|
1375
|
+
KKKKKKKKKXXXXXXXXXXXXNNNNNNNXl ............... :XWWWWWWWX000000000000
|
1376
|
+
KKKKKKKKKXXXXXXXXXXXXXXNNNNNXc ...''',,,,,,;;,,,,,,'''...... .xWWWWWWWWX000000000000
|
1377
|
+
KKKKKKKKKKKXXXXXXXXXXXXXNNNNK; ...',,,,;;;;;;;:::::::;;;;;;,,'. .oNWWWWWWWNK000000OOOO00
|
1378
|
+
KKKKKKKKKKKKXXXXXXXXXXXXXXXN0, ...'',,,;;;;;;:::::::::::::::;;;;,'. .dNWWWWWWWWNK0000OOOOOOOO
|
1379
|
+
0000KKKKKKKKKKKKKXXXXXXXXXXN0, ..'',,,,;;;;;;:::::::::::::::::;;;;,,.. ;ONNNNNWWWWWNK00OOOOOOOOOO
|
1380
|
+
kkkkkkOOOOOOOOOOOOOOOOOOO000k; ..,,,,,,'',,;;::::::::::::::::;;;;;;,'. .lOKKKKXXKXXKK0OOOOOOOOOOOOO
|
1381
|
+
xxxkkkkkkkkkkkkkkkkkkOOOOkdll;..',,,,,,,''...';::ccccc:::::::::;;;;;,...o0000000000000OkkOOOkkOOOOOO
|
1382
|
+
xxxxxxkkkkkkkkkkkkkkkkkkOd:;;,..,;;;;;;;;;;,'',,;:ccccccccc:::;;;;;;,..cO0000000000000Oxkkkkkkkkkkkk
|
1383
|
+
xxxxxxxxkkkkkkkkkkkkkkkkkl:;;,'';;;;;,'''''',,,,,;::ccc::;,,'.'''',;,,lO00000000000000kxkkkkkkkkkkkk
|
1384
|
+
xxxxxxxxkkkkkkkkkkkkkkkkko::;'';;;;;;,''....,'',,,,;:c:;,,'''',,;;;;,:x00000000000000Okxkkkkkkkkkkkk
|
1385
|
+
xxxxxxxxxxkkkkkkkkkkkkkkkxl;,,;;;;:::;;;,,,,,,,,,,,,:c:;,'....''',;;,;cxO000000000000Okxkkkkkkkkkkkk
|
1386
|
+
kkkkOOOOOOOOOOOOOO00000000x:;;;;;:::c::::::;;;;;;;;;:c:;,,,,'',,',;:::lOKKKKKKXXXXXXKKOkkkkkkkkkkkkk
|
1387
|
+
000000000000000KKKKKKKKKKK0dc;,;;:::ccccccc::::;;;;;:cc:;;;;:::::::::lOXXXXXNNNNNNNNXX0Okkkkkkkkkkkk
|
1388
|
+
OO00000000000000000KKKKKKKK0d::;;;::ccccccccc:;;;;;;;:c:;::ccccccc::cOXXXXXXXXXNNNNNXX0kkkkkkkkkkkkk
|
1389
|
+
OOO00000000000000000000KKKKKOxxc;;;::ccccccc:;;;;;;;:ccc:::cccllcc;:kKXXXXXXXXXXXXXXXKOkkkkkkkkkkkkk
|
1390
|
+
OOOOO00000000000000000000KKK0kdl;;;;;:ccccc::;,,,,;;:clc:::cclllcc:oKXXXXXXXXXXXXXXXXKOkkkkkkkkkkkkk
|
1391
|
+
OOOOOOO0000000000000000Okxdlc;,,;;::;;::cc::;;,,,,,;:::;;:cccccc::clxkO00KKKKKKKKKXKK0kkkkkkkkkkkxkk
|
1392
|
+
kkkkkkkkkkkkkkkkkkkxdoc:,''.....,;:::;;;::;;;;;;;;;;;;;;;:ccc:::;,',;;:clodxkOOOOOOOOkxxxxxxxxxxxxxx
|
1393
|
+
ddddddddddddddoolc;,'''..........,;;:;;;::;,,,,,;;;;;::::::c:::;'.',,;;;;;::clodxkkkkxdxxxxxxxxxxxxx
|
1394
|
+
dddddddoolc::;,'''....... ..',;;;;;;;;,'........',;::::::;;,,;;;;;;;;:::::ccloddddxxxxxxxxxxxxx
|
1395
|
+
dollc:;,,''......... ..'''',,,,;;;;;,'''.....'',::::;,,;;;::::;;,,;;;;;;;;;::cldxxxxxxdxxdxx
|
1396
|
+
l;'''.''...... ..'',,''',,,,;;;::;;,,,,,,;;::;;'.....',;;,,''',,,,,,'',,,',:odxddddddddd
|
1397
|
+
............. .'',,,,,''',,,;;;;::::;::::::;;;........'''''''..'.....,,'...';cdddddddddd
|
1398
|
+
. ....... .',,,,,;,,'',,,,;;;::::::::::;;cc. .....''...'''.......','......':odxdddddd
|
1399
|
+
... .',,;;;;;;,'',;;,,,;;;::::::::;cxo....................''''.......'';lddddddd
|
1400
|
+
.. .,;,;;;;;;,,,',;;;,,,,;;;;;;;;:dKO:..................''''.. .......',cdddddd
|
1401
|
+
,:;;;;;,,,,;,,;::;,,,,,;::::::dK0c..................'''.. ........',codddd
|
1402
|
+
.;:;;;;;,,;;;,,;:;;:;,,;:::::clc,... ...........'''.... .... .....':oddd
|
1403
|
+
.',;;;;;;;;;,,;:;;;;,;::::::;'...... ......'......... .....'',cood
|
1404
|
+
..,;;;;;;;;;;;:;;;;:::::;'. . .............. ...''',:od
|
1405
|
+
..',;;;;:;;;:::::::,,'. ............... ....''.':o
|
1406
|
+
...',,;;,,;,,'.. ............... .. .....'c
|
1407
|
+
__ _ __.... ................ .... ......'
|
1408
|
+
____ ____ / /_ _ __(_)___/ /__ .............. .. ... .......
|
1409
|
+
/ __ `/ _ \/ __/ | | /| / / / __ / _ \ ................ . ......
|
1410
|
+
/ /_/ / __/ /_ | |/ |/ / / /_/ / __/ ................. ......
|
1411
|
+
\__, /\___/\__/ |__/|__/_/\__,_/\___/ ............... ......
|
1412
|
+
/____/ ............... .. ........
|
1413
|
+
"""
|
1414
|
+
print(wide)
|