scrapli 2023.7.30__py3-none-any.whl → 2024.7.30__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.
- scrapli/__init__.py +2 -1
- scrapli/channel/__init__.py +1 -0
- scrapli/channel/async_channel.py +35 -12
- scrapli/channel/base_channel.py +25 -3
- scrapli/channel/sync_channel.py +35 -12
- scrapli/decorators.py +1 -0
- scrapli/driver/__init__.py +1 -0
- scrapli/driver/base/__init__.py +1 -0
- scrapli/driver/base/async_driver.py +19 -13
- scrapli/driver/base/base_driver.py +121 -37
- scrapli/driver/base/sync_driver.py +19 -13
- scrapli/driver/core/__init__.py +1 -0
- scrapli/driver/core/arista_eos/__init__.py +1 -0
- scrapli/driver/core/arista_eos/async_driver.py +3 -0
- scrapli/driver/core/arista_eos/base_driver.py +3 -2
- scrapli/driver/core/arista_eos/sync_driver.py +3 -0
- scrapli/driver/core/cisco_iosxe/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxe/async_driver.py +3 -0
- scrapli/driver/core/cisco_iosxe/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxe/sync_driver.py +3 -0
- scrapli/driver/core/cisco_iosxr/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxr/async_driver.py +3 -0
- scrapli/driver/core/cisco_iosxr/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxr/sync_driver.py +3 -0
- scrapli/driver/core/cisco_nxos/__init__.py +1 -0
- scrapli/driver/core/cisco_nxos/async_driver.py +3 -0
- scrapli/driver/core/cisco_nxos/base_driver.py +9 -4
- scrapli/driver/core/cisco_nxos/sync_driver.py +3 -0
- scrapli/driver/core/juniper_junos/__init__.py +1 -0
- scrapli/driver/core/juniper_junos/async_driver.py +3 -0
- scrapli/driver/core/juniper_junos/base_driver.py +1 -0
- scrapli/driver/core/juniper_junos/sync_driver.py +3 -0
- scrapli/driver/generic/__init__.py +1 -0
- scrapli/driver/generic/async_driver.py +45 -3
- scrapli/driver/generic/base_driver.py +2 -1
- scrapli/driver/generic/sync_driver.py +45 -3
- scrapli/driver/network/__init__.py +1 -0
- scrapli/driver/network/async_driver.py +27 -0
- scrapli/driver/network/base_driver.py +1 -0
- scrapli/driver/network/sync_driver.py +27 -0
- scrapli/exceptions.py +1 -0
- scrapli/factory.py +22 -3
- scrapli/helper.py +76 -4
- scrapli/logging.py +1 -0
- scrapli/response.py +1 -0
- scrapli/ssh_config.py +1 -0
- scrapli/transport/base/__init__.py +1 -0
- scrapli/transport/base/async_transport.py +1 -0
- scrapli/transport/base/base_socket.py +1 -0
- scrapli/transport/base/base_transport.py +1 -0
- scrapli/transport/base/sync_transport.py +1 -0
- scrapli/transport/plugins/asyncssh/transport.py +4 -0
- scrapli/transport/plugins/asynctelnet/transport.py +13 -6
- scrapli/transport/plugins/paramiko/transport.py +1 -0
- scrapli/transport/plugins/ssh2/transport.py +6 -3
- scrapli/transport/plugins/system/ptyprocess.py +50 -13
- scrapli/transport/plugins/system/transport.py +27 -6
- scrapli/transport/plugins/telnet/transport.py +13 -7
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/METADATA +74 -47
- scrapli-2024.7.30.dist-info/RECORD +74 -0
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/WHEEL +1 -1
- scrapli-2023.7.30.dist-info/RECORD +0 -74
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/LICENSE +0 -0
- {scrapli-2023.7.30.dist-info → scrapli-2024.7.30.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.generic.sync_driver"""
|
2
|
+
|
2
3
|
import time
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
|
@@ -16,6 +17,23 @@ if TYPE_CHECKING:
|
|
16
17
|
)
|
17
18
|
|
18
19
|
|
20
|
+
def generic_on_open(conn: "GenericDriver") -> None:
|
21
|
+
"""
|
22
|
+
GenericDriver default on-open -- drains initial login by running a simple get_prompt
|
23
|
+
|
24
|
+
Args:
|
25
|
+
conn: GenericDriver object
|
26
|
+
|
27
|
+
Returns:
|
28
|
+
None
|
29
|
+
|
30
|
+
Raises:
|
31
|
+
N/A
|
32
|
+
|
33
|
+
"""
|
34
|
+
conn.get_prompt()
|
35
|
+
|
36
|
+
|
19
37
|
class GenericDriver(Driver, BaseGenericDriver):
|
20
38
|
def __init__(
|
21
39
|
self,
|
@@ -35,10 +53,11 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
35
53
|
timeout_ops: float = 30.0,
|
36
54
|
comms_prompt_pattern: str = r"^\S{0,48}[#>$~@:\]]\s*$",
|
37
55
|
comms_return_char: str = "\n",
|
56
|
+
comms_roughly_match_inputs: bool = False,
|
38
57
|
ssh_config_file: Union[str, bool] = False,
|
39
58
|
ssh_known_hosts_file: Union[str, bool] = False,
|
40
59
|
on_init: Optional[Callable[..., Any]] = None,
|
41
|
-
on_open: Optional[Callable[..., Any]] =
|
60
|
+
on_open: Optional[Callable[..., Any]] = generic_on_open,
|
42
61
|
on_close: Optional[Callable[..., Any]] = None,
|
43
62
|
transport: str = "system",
|
44
63
|
transport_options: Optional[Dict[str, Any]] = None,
|
@@ -64,6 +83,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
64
83
|
timeout_ops=timeout_ops,
|
65
84
|
comms_prompt_pattern=comms_prompt_pattern,
|
66
85
|
comms_return_char=comms_return_char,
|
86
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
67
87
|
ssh_config_file=ssh_config_file,
|
68
88
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
69
89
|
on_init=on_init,
|
@@ -102,6 +122,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
102
122
|
strip_prompt: bool = True,
|
103
123
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
104
124
|
eager: bool = False,
|
125
|
+
eager_input: bool = False,
|
105
126
|
timeout_ops: Optional[float] = None,
|
106
127
|
) -> Response:
|
107
128
|
"""
|
@@ -118,6 +139,8 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
118
139
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
119
140
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
120
141
|
it can make scrapli less reliable!
|
142
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
143
|
+
this should be left alone unless you know what you are doing!
|
121
144
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
122
145
|
the duration of the operation, value is reset to initial value after operation is
|
123
146
|
completed
|
@@ -142,7 +165,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
142
165
|
failed_when_contains=failed_when_contains,
|
143
166
|
)
|
144
167
|
raw_response, processed_response = self.channel.send_input(
|
145
|
-
channel_input=command, strip_prompt=strip_prompt, eager=eager
|
168
|
+
channel_input=command, strip_prompt=strip_prompt, eager=eager, eager_input=eager_input
|
146
169
|
)
|
147
170
|
return self._post_send_command(
|
148
171
|
raw_response=raw_response, processed_response=processed_response, response=response
|
@@ -154,6 +177,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
154
177
|
*,
|
155
178
|
strip_prompt: bool = True,
|
156
179
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
180
|
+
eager_input: bool = False,
|
157
181
|
timeout_ops: Optional[float] = None,
|
158
182
|
) -> Response:
|
159
183
|
"""
|
@@ -163,6 +187,8 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
163
187
|
command: string to send to device in privilege exec mode
|
164
188
|
strip_prompt: strip prompt or not, defaults to True (yes, strip the prompt)
|
165
189
|
failed_when_contains: string or list of strings indicating failure if found in response
|
190
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
191
|
+
this should be left alone unless you know what you are doing!
|
166
192
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
167
193
|
the duration of the operation, value is reset to initial value after operation is
|
168
194
|
completed
|
@@ -178,6 +204,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
178
204
|
command=command,
|
179
205
|
strip_prompt=strip_prompt,
|
180
206
|
failed_when_contains=failed_when_contains,
|
207
|
+
eager_input=eager_input,
|
181
208
|
timeout_ops=timeout_ops,
|
182
209
|
)
|
183
210
|
return response
|
@@ -190,6 +217,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
190
217
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
191
218
|
stop_on_failed: bool = False,
|
192
219
|
eager: bool = False,
|
220
|
+
eager_input: bool = False,
|
193
221
|
timeout_ops: Optional[float] = None,
|
194
222
|
) -> MultiResponse:
|
195
223
|
"""
|
@@ -204,6 +232,8 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
204
232
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
205
233
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
206
234
|
it can make scrapli less reliable!
|
235
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
236
|
+
this should be left alone unless you know what you are doing!
|
207
237
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
208
238
|
the duration of the operation, value is reset to initial value after operation is
|
209
239
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -224,6 +254,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
224
254
|
failed_when_contains=failed_when_contains,
|
225
255
|
timeout_ops=timeout_ops,
|
226
256
|
eager=eager,
|
257
|
+
eager_input=eager_input,
|
227
258
|
)
|
228
259
|
responses.append(response)
|
229
260
|
if stop_on_failed and response.failed is True:
|
@@ -239,6 +270,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
239
270
|
failed_when_contains=failed_when_contains,
|
240
271
|
timeout_ops=timeout_ops,
|
241
272
|
eager=False,
|
273
|
+
eager_input=eager_input,
|
242
274
|
)
|
243
275
|
responses.append(response)
|
244
276
|
|
@@ -252,6 +284,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
252
284
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
253
285
|
stop_on_failed: bool = False,
|
254
286
|
eager: bool = False,
|
287
|
+
eager_input: bool = False,
|
255
288
|
timeout_ops: Optional[float] = None,
|
256
289
|
) -> MultiResponse:
|
257
290
|
"""
|
@@ -266,6 +299,8 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
266
299
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
267
300
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
268
301
|
it can make scrapli less reliable!
|
302
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
303
|
+
this should be left alone unless you know what you are doing!
|
269
304
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
270
305
|
the duration of the operation, value is reset to initial value after operation is
|
271
306
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -286,6 +321,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
286
321
|
failed_when_contains=failed_when_contains,
|
287
322
|
stop_on_failed=stop_on_failed,
|
288
323
|
eager=eager,
|
324
|
+
eager_input=eager_input,
|
289
325
|
timeout_ops=timeout_ops,
|
290
326
|
)
|
291
327
|
|
@@ -531,7 +567,13 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
531
567
|
"""
|
532
568
|
if initial_input is not None:
|
533
569
|
self.channel.write(channel_input=f"{initial_input}{self.comms_return_char}")
|
534
|
-
return self.read_callback(
|
570
|
+
return self.read_callback(
|
571
|
+
callbacks=callbacks,
|
572
|
+
initial_input=None,
|
573
|
+
read_output=read_output,
|
574
|
+
read_delay=read_delay,
|
575
|
+
read_timeout=read_timeout,
|
576
|
+
)
|
535
577
|
|
536
578
|
original_transport_timeout = self.timeout_transport
|
537
579
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.network.async_driver"""
|
2
|
+
|
2
3
|
from collections import defaultdict
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
@@ -29,6 +30,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
29
30
|
timeout_transport: float = 30.0,
|
30
31
|
timeout_ops: float = 30.0,
|
31
32
|
comms_return_char: str = "\n",
|
33
|
+
comms_roughly_match_inputs: bool = False,
|
32
34
|
ssh_config_file: Union[str, bool] = False,
|
33
35
|
ssh_known_hosts_file: Union[str, bool] = False,
|
34
36
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -64,6 +66,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
64
66
|
timeout_transport=timeout_transport,
|
65
67
|
timeout_ops=timeout_ops,
|
66
68
|
comms_return_char=comms_return_char,
|
69
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
67
70
|
ssh_config_file=ssh_config_file,
|
68
71
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
69
72
|
on_init=on_init,
|
@@ -219,6 +222,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
219
222
|
*,
|
220
223
|
strip_prompt: bool = True,
|
221
224
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
225
|
+
eager_input: bool = False,
|
222
226
|
timeout_ops: Optional[float] = None,
|
223
227
|
) -> Response:
|
224
228
|
"""
|
@@ -230,6 +234,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
230
234
|
command: string to send to device in privilege exec mode
|
231
235
|
strip_prompt: True/False strip prompt from returned output
|
232
236
|
failed_when_contains: string or list of strings indicating failure if found in response
|
237
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
238
|
+
this should be left alone unless you know what you are doing!
|
233
239
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
234
240
|
the duration of the operation, value is reset to initial value after operation is
|
235
241
|
completed
|
@@ -250,6 +256,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
250
256
|
command=command,
|
251
257
|
strip_prompt=strip_prompt,
|
252
258
|
failed_when_contains=failed_when_contains,
|
259
|
+
eager_input=eager_input,
|
253
260
|
timeout_ops=timeout_ops,
|
254
261
|
)
|
255
262
|
self._update_response(response)
|
@@ -264,6 +271,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
264
271
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
265
272
|
stop_on_failed: bool = False,
|
266
273
|
eager: bool = False,
|
274
|
+
eager_input: bool = False,
|
267
275
|
timeout_ops: Optional[float] = None,
|
268
276
|
) -> MultiResponse:
|
269
277
|
"""
|
@@ -280,6 +288,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
280
288
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
281
289
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
282
290
|
it can make scrapli less reliable!
|
291
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
292
|
+
this should be left alone unless you know what you are doing!
|
283
293
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
284
294
|
the duration of the operation, value is reset to initial value after operation is
|
285
295
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -303,6 +313,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
303
313
|
failed_when_contains=failed_when_contains,
|
304
314
|
stop_on_failed=stop_on_failed,
|
305
315
|
eager=eager,
|
316
|
+
eager_input=eager_input,
|
306
317
|
timeout_ops=timeout_ops,
|
307
318
|
)
|
308
319
|
|
@@ -319,6 +330,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
319
330
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
320
331
|
stop_on_failed: bool = False,
|
321
332
|
eager: bool = False,
|
333
|
+
eager_input: bool = False,
|
322
334
|
timeout_ops: Optional[float] = None,
|
323
335
|
) -> MultiResponse:
|
324
336
|
"""
|
@@ -333,6 +345,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
333
345
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
334
346
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
335
347
|
it can make scrapli less reliable!
|
348
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
349
|
+
this should be left alone unless you know what you are doing!
|
336
350
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
337
351
|
the duration of the operation, value is reset to initial value after operation is
|
338
352
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -356,6 +370,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
356
370
|
failed_when_contains=failed_when_contains,
|
357
371
|
stop_on_failed=stop_on_failed,
|
358
372
|
eager=eager,
|
373
|
+
eager_input=eager_input,
|
359
374
|
timeout_ops=timeout_ops,
|
360
375
|
)
|
361
376
|
|
@@ -477,6 +492,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
477
492
|
stop_on_failed: bool = False,
|
478
493
|
privilege_level: str = "",
|
479
494
|
eager: bool = False,
|
495
|
+
eager_input: bool = False,
|
480
496
|
timeout_ops: Optional[float] = None,
|
481
497
|
) -> MultiResponse:
|
482
498
|
"""
|
@@ -498,6 +514,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
498
514
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
499
515
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
500
516
|
it can make scrapli less reliable!
|
517
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
518
|
+
this should be left alone unless you know what you are doing!
|
501
519
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
502
520
|
the duration of the operation, value is reset to initial value after operation is
|
503
521
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -525,6 +543,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
525
543
|
failed_when_contains=failed_when_contains,
|
526
544
|
stop_on_failed=stop_on_failed,
|
527
545
|
eager=eager,
|
546
|
+
eager_input=eager_input,
|
528
547
|
timeout_ops=timeout_ops,
|
529
548
|
)
|
530
549
|
|
@@ -542,6 +561,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
542
561
|
stop_on_failed: bool = False,
|
543
562
|
privilege_level: str = "",
|
544
563
|
eager: bool = False,
|
564
|
+
eager_input: bool = False,
|
545
565
|
timeout_ops: Optional[float] = None,
|
546
566
|
) -> Response:
|
547
567
|
"""
|
@@ -563,6 +583,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
563
583
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
564
584
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
565
585
|
it can make scrapli less reliable!
|
586
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
587
|
+
this should be left alone unless you know what you are doing!
|
566
588
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
567
589
|
the duration of the operation, value is reset to initial value after operation is
|
568
590
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -585,6 +607,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
585
607
|
stop_on_failed=stop_on_failed,
|
586
608
|
privilege_level=privilege_level,
|
587
609
|
eager=eager,
|
610
|
+
eager_input=eager_input,
|
588
611
|
timeout_ops=timeout_ops,
|
589
612
|
)
|
590
613
|
return self._post_send_config(config=config, multi_response=multi_response)
|
@@ -598,6 +621,7 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
598
621
|
stop_on_failed: bool = False,
|
599
622
|
privilege_level: str = "",
|
600
623
|
eager: bool = False,
|
624
|
+
eager_input: bool = False,
|
601
625
|
timeout_ops: Optional[float] = None,
|
602
626
|
) -> MultiResponse:
|
603
627
|
"""
|
@@ -619,6 +643,8 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
619
643
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
620
644
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
621
645
|
it can make scrapli less reliable!
|
646
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
647
|
+
this should be left alone unless you know what you are doing!
|
622
648
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
623
649
|
the duration of the operation, value is reset to initial value after operation is
|
624
650
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -640,5 +666,6 @@ class AsyncNetworkDriver(AsyncGenericDriver, BaseNetworkDriver):
|
|
640
666
|
stop_on_failed=stop_on_failed,
|
641
667
|
privilege_level=privilege_level,
|
642
668
|
eager=eager,
|
669
|
+
eager_input=eager_input,
|
643
670
|
timeout_ops=timeout_ops,
|
644
671
|
)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.network.sync_driver"""
|
2
|
+
|
2
3
|
from collections import defaultdict
|
3
4
|
from io import BytesIO
|
4
5
|
from typing import Any, Callable, Dict, List, Optional, Tuple, Union
|
@@ -29,6 +30,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
29
30
|
timeout_transport: float = 30.0,
|
30
31
|
timeout_ops: float = 30.0,
|
31
32
|
comms_return_char: str = "\n",
|
33
|
+
comms_roughly_match_inputs: bool = False,
|
32
34
|
ssh_config_file: Union[str, bool] = False,
|
33
35
|
ssh_known_hosts_file: Union[str, bool] = False,
|
34
36
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -64,6 +66,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
64
66
|
timeout_transport=timeout_transport,
|
65
67
|
timeout_ops=timeout_ops,
|
66
68
|
comms_return_char=comms_return_char,
|
69
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
67
70
|
ssh_config_file=ssh_config_file,
|
68
71
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
69
72
|
on_init=on_init,
|
@@ -219,6 +222,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
219
222
|
*,
|
220
223
|
strip_prompt: bool = True,
|
221
224
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
225
|
+
eager_input: bool = False,
|
222
226
|
timeout_ops: Optional[float] = None,
|
223
227
|
) -> Response:
|
224
228
|
"""
|
@@ -230,6 +234,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
230
234
|
command: string to send to device in privilege exec mode
|
231
235
|
strip_prompt: True/False strip prompt from returned output
|
232
236
|
failed_when_contains: string or list of strings indicating failure if found in response
|
237
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
238
|
+
this should be left alone unless you know what you are doing!
|
233
239
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
234
240
|
the duration of the operation, value is reset to initial value after operation is
|
235
241
|
completed
|
@@ -250,6 +256,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
250
256
|
command=command,
|
251
257
|
strip_prompt=strip_prompt,
|
252
258
|
failed_when_contains=failed_when_contains,
|
259
|
+
eager_input=eager_input,
|
253
260
|
timeout_ops=timeout_ops,
|
254
261
|
)
|
255
262
|
self._update_response(response)
|
@@ -264,6 +271,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
264
271
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
265
272
|
stop_on_failed: bool = False,
|
266
273
|
eager: bool = False,
|
274
|
+
eager_input: bool = False,
|
267
275
|
timeout_ops: Optional[float] = None,
|
268
276
|
) -> MultiResponse:
|
269
277
|
"""
|
@@ -280,6 +288,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
280
288
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
281
289
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
282
290
|
it can make scrapli less reliable!
|
291
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
292
|
+
this should be left alone unless you know what you are doing!
|
283
293
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
284
294
|
the duration of the operation, value is reset to initial value after operation is
|
285
295
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -303,6 +313,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
303
313
|
failed_when_contains=failed_when_contains,
|
304
314
|
stop_on_failed=stop_on_failed,
|
305
315
|
eager=eager,
|
316
|
+
eager_input=eager_input,
|
306
317
|
timeout_ops=timeout_ops,
|
307
318
|
)
|
308
319
|
|
@@ -319,6 +330,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
319
330
|
failed_when_contains: Optional[Union[str, List[str]]] = None,
|
320
331
|
stop_on_failed: bool = False,
|
321
332
|
eager: bool = False,
|
333
|
+
eager_input: bool = False,
|
322
334
|
timeout_ops: Optional[float] = None,
|
323
335
|
) -> MultiResponse:
|
324
336
|
"""
|
@@ -333,6 +345,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
333
345
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
334
346
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
335
347
|
it can make scrapli less reliable!
|
348
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
349
|
+
this should be left alone unless you know what you are doing!
|
336
350
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
337
351
|
the duration of the operation, value is reset to initial value after operation is
|
338
352
|
completed. Note that this is the timeout value PER COMMAND sent, not for the total
|
@@ -356,6 +370,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
356
370
|
failed_when_contains=failed_when_contains,
|
357
371
|
stop_on_failed=stop_on_failed,
|
358
372
|
eager=eager,
|
373
|
+
eager_input=eager_input,
|
359
374
|
timeout_ops=timeout_ops,
|
360
375
|
)
|
361
376
|
|
@@ -477,6 +492,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
477
492
|
stop_on_failed: bool = False,
|
478
493
|
privilege_level: str = "",
|
479
494
|
eager: bool = False,
|
495
|
+
eager_input: bool = False,
|
480
496
|
timeout_ops: Optional[float] = None,
|
481
497
|
) -> MultiResponse:
|
482
498
|
"""
|
@@ -498,6 +514,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
498
514
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
499
515
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
500
516
|
it can make scrapli less reliable!
|
517
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
518
|
+
this should be left alone unless you know what you are doing!
|
501
519
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
502
520
|
the duration of the operation, value is reset to initial value after operation is
|
503
521
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -525,6 +543,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
525
543
|
failed_when_contains=failed_when_contains,
|
526
544
|
stop_on_failed=stop_on_failed,
|
527
545
|
eager=eager,
|
546
|
+
eager_input=eager_input,
|
528
547
|
timeout_ops=timeout_ops,
|
529
548
|
)
|
530
549
|
|
@@ -542,6 +561,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
542
561
|
stop_on_failed: bool = False,
|
543
562
|
privilege_level: str = "",
|
544
563
|
eager: bool = False,
|
564
|
+
eager_input: bool = False,
|
545
565
|
timeout_ops: Optional[float] = None,
|
546
566
|
) -> Response:
|
547
567
|
"""
|
@@ -563,6 +583,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
563
583
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
564
584
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
565
585
|
it can make scrapli less reliable!
|
586
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
587
|
+
this should be left alone unless you know what you are doing!
|
566
588
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
567
589
|
the duration of the operation, value is reset to initial value after operation is
|
568
590
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -585,6 +607,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
585
607
|
stop_on_failed=stop_on_failed,
|
586
608
|
privilege_level=privilege_level,
|
587
609
|
eager=eager,
|
610
|
+
eager_input=eager_input,
|
588
611
|
timeout_ops=timeout_ops,
|
589
612
|
)
|
590
613
|
return self._post_send_config(config=config, multi_response=multi_response)
|
@@ -598,6 +621,7 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
598
621
|
stop_on_failed: bool = False,
|
599
622
|
privilege_level: str = "",
|
600
623
|
eager: bool = False,
|
624
|
+
eager_input: bool = False,
|
601
625
|
timeout_ops: Optional[float] = None,
|
602
626
|
) -> MultiResponse:
|
603
627
|
"""
|
@@ -619,6 +643,8 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
619
643
|
eager: if eager is True we do not read until prompt is seen at each command sent to the
|
620
644
|
channel. Do *not* use this unless you know what you are doing as it is possible that
|
621
645
|
it can make scrapli less reliable!
|
646
|
+
eager_input: when true does *not* try to read our input off the channel -- generally
|
647
|
+
this should be left alone unless you know what you are doing!
|
622
648
|
timeout_ops: timeout ops value for this operation; only sets the timeout_ops value for
|
623
649
|
the duration of the operation, value is reset to initial value after operation is
|
624
650
|
completed. Note that this is the timeout value PER CONFIG sent, not for the total
|
@@ -640,5 +666,6 @@ class NetworkDriver(GenericDriver, BaseNetworkDriver):
|
|
640
666
|
stop_on_failed=stop_on_failed,
|
641
667
|
privilege_level=privilege_level,
|
642
668
|
eager=eager,
|
669
|
+
eager_input=eager_input,
|
643
670
|
timeout_ops=timeout_ops,
|
644
671
|
)
|
scrapli/exceptions.py
CHANGED
scrapli/factory.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.factory"""
|
2
|
+
|
2
3
|
import importlib
|
3
4
|
from copy import deepcopy
|
4
5
|
from io import BytesIO
|
@@ -26,7 +27,7 @@ from scrapli.exceptions import (
|
|
26
27
|
)
|
27
28
|
from scrapli.helper import format_user_warning
|
28
29
|
from scrapli.logging import logger
|
29
|
-
from scrapli.transport import ASYNCIO_TRANSPORTS
|
30
|
+
from scrapli.transport import ASYNCIO_TRANSPORTS, CORE_TRANSPORTS
|
30
31
|
|
31
32
|
|
32
33
|
def _build_provided_kwargs_dict( # pylint: disable=R0914
|
@@ -44,6 +45,7 @@ def _build_provided_kwargs_dict( # pylint: disable=R0914
|
|
44
45
|
timeout_transport: Optional[float],
|
45
46
|
timeout_ops: Optional[float],
|
46
47
|
comms_return_char: Optional[str],
|
48
|
+
comms_roughly_match_inputs: Optional[bool],
|
47
49
|
ssh_config_file: Optional[Union[str, bool]],
|
48
50
|
ssh_known_hosts_file: Optional[Union[str, bool]],
|
49
51
|
on_init: Optional[Callable[..., Any]],
|
@@ -97,6 +99,7 @@ def _build_provided_kwargs_dict( # pylint: disable=R0914
|
|
97
99
|
"timeout_transport": timeout_transport,
|
98
100
|
"timeout_ops": timeout_ops,
|
99
101
|
"comms_return_char": comms_return_char,
|
102
|
+
"comms_roughly_match_inputs": comms_roughly_match_inputs,
|
100
103
|
"ssh_config_file": ssh_config_file,
|
101
104
|
"ssh_known_hosts_file": ssh_known_hosts_file,
|
102
105
|
"on_init": on_init,
|
@@ -351,6 +354,7 @@ class Scrapli(NetworkDriver):
|
|
351
354
|
timeout_transport: Optional[float] = None,
|
352
355
|
timeout_ops: Optional[float] = None,
|
353
356
|
comms_return_char: Optional[str] = None,
|
357
|
+
comms_roughly_match_inputs: Optional[bool] = None,
|
354
358
|
ssh_config_file: Optional[Union[str, bool]] = None,
|
355
359
|
ssh_known_hosts_file: Optional[Union[str, bool]] = None,
|
356
360
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -388,6 +392,12 @@ class Scrapli(NetworkDriver):
|
|
388
392
|
timeout_transport: timeout for ssh|telnet transport in seconds
|
389
393
|
timeout_ops: timeout for ssh channel operations
|
390
394
|
comms_return_char: character to use to send returns to host
|
395
|
+
comms_roughly_match_inputs: indicates if the channel should "roughly" match inputs sent
|
396
|
+
to the device. If False (default) inputs are strictly checked, as in any input
|
397
|
+
*must* be read back exactly on the channel. When set to True all input chars *must*
|
398
|
+
be read back in order in the output and all chars must be present, but the *exact*
|
399
|
+
input string does not need to be seen. This can be useful if a device echoes back
|
400
|
+
extra characters or rewrites the terminal during command input.
|
391
401
|
ssh_config_file: string to path for ssh config file, True to use default ssh config file
|
392
402
|
or False to ignore default ssh config file
|
393
403
|
ssh_known_hosts_file: string to path for ssh known hosts file, True to use default known
|
@@ -455,7 +465,7 @@ class Scrapli(NetworkDriver):
|
|
455
465
|
"""
|
456
466
|
logger.debug("Scrapli factory initialized")
|
457
467
|
|
458
|
-
if transport in ASYNCIO_TRANSPORTS:
|
468
|
+
if transport in CORE_TRANSPORTS and transport in ASYNCIO_TRANSPORTS:
|
459
469
|
raise ScrapliValueError("Use 'AsyncScrapli' if using an async transport!")
|
460
470
|
|
461
471
|
if not isinstance(platform, str):
|
@@ -474,6 +484,7 @@ class Scrapli(NetworkDriver):
|
|
474
484
|
timeout_transport=timeout_transport,
|
475
485
|
timeout_ops=timeout_ops,
|
476
486
|
comms_return_char=comms_return_char,
|
487
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
477
488
|
ssh_config_file=ssh_config_file,
|
478
489
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
479
490
|
on_init=on_init,
|
@@ -642,6 +653,7 @@ class AsyncScrapli(AsyncNetworkDriver):
|
|
642
653
|
timeout_transport: Optional[float] = None,
|
643
654
|
timeout_ops: Optional[float] = None,
|
644
655
|
comms_return_char: Optional[str] = None,
|
656
|
+
comms_roughly_match_inputs: Optional[bool] = None,
|
645
657
|
ssh_config_file: Optional[Union[str, bool]] = None,
|
646
658
|
ssh_known_hosts_file: Optional[Union[str, bool]] = None,
|
647
659
|
on_init: Optional[Callable[..., Any]] = None,
|
@@ -679,6 +691,12 @@ class AsyncScrapli(AsyncNetworkDriver):
|
|
679
691
|
timeout_transport: timeout for ssh|telnet transport in seconds
|
680
692
|
timeout_ops: timeout for ssh channel operations
|
681
693
|
comms_return_char: character to use to send returns to host
|
694
|
+
comms_roughly_match_inputs: indicates if the channel should "roughly" match inputs sent
|
695
|
+
to the device. If False (default) inputs are strictly checked, as in any input
|
696
|
+
*must* be read back exactly on the channel. When set to True all input chars *must*
|
697
|
+
be read back in order in the output and all chars must be present, but the *exact*
|
698
|
+
input string does not need to be seen. This can be useful if a device echoes back
|
699
|
+
extra characters or rewrites the terminal during command input.
|
682
700
|
ssh_config_file: string to path for ssh config file, True to use default ssh config file
|
683
701
|
or False to ignore default ssh config file
|
684
702
|
ssh_known_hosts_file: string to path for ssh known hosts file, True to use default known
|
@@ -746,7 +764,7 @@ class AsyncScrapli(AsyncNetworkDriver):
|
|
746
764
|
"""
|
747
765
|
logger.debug("AsyncScrapli factory initialized")
|
748
766
|
|
749
|
-
if transport not in ASYNCIO_TRANSPORTS:
|
767
|
+
if transport in CORE_TRANSPORTS and transport not in ASYNCIO_TRANSPORTS:
|
750
768
|
raise ScrapliValueError("Use 'Scrapli' if using a synchronous transport!")
|
751
769
|
|
752
770
|
if not isinstance(platform, str):
|
@@ -765,6 +783,7 @@ class AsyncScrapli(AsyncNetworkDriver):
|
|
765
783
|
timeout_transport=timeout_transport,
|
766
784
|
timeout_ops=timeout_ops,
|
767
785
|
comms_return_char=comms_return_char,
|
786
|
+
comms_roughly_match_inputs=comms_roughly_match_inputs,
|
768
787
|
ssh_config_file=ssh_config_file,
|
769
788
|
ssh_known_hosts_file=ssh_known_hosts_file,
|
770
789
|
on_init=on_init,
|