scrapli 2024.1.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 +16 -7
- scrapli/channel/base_channel.py +10 -5
- scrapli/channel/sync_channel.py +16 -7
- 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 +33 -36
- 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 +1 -0
- scrapli/driver/core/arista_eos/base_driver.py +1 -0
- scrapli/driver/core/arista_eos/sync_driver.py +1 -0
- scrapli/driver/core/cisco_iosxe/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxe/async_driver.py +1 -0
- scrapli/driver/core/cisco_iosxe/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxe/sync_driver.py +1 -0
- scrapli/driver/core/cisco_iosxr/__init__.py +1 -0
- scrapli/driver/core/cisco_iosxr/async_driver.py +1 -0
- scrapli/driver/core/cisco_iosxr/base_driver.py +1 -0
- scrapli/driver/core/cisco_iosxr/sync_driver.py +1 -0
- scrapli/driver/core/cisco_nxos/__init__.py +1 -0
- scrapli/driver/core/cisco_nxos/async_driver.py +1 -0
- scrapli/driver/core/cisco_nxos/base_driver.py +9 -4
- scrapli/driver/core/cisco_nxos/sync_driver.py +1 -0
- scrapli/driver/core/juniper_junos/__init__.py +1 -0
- scrapli/driver/core/juniper_junos/async_driver.py +1 -0
- scrapli/driver/core/juniper_junos/base_driver.py +1 -0
- scrapli/driver/core/juniper_junos/sync_driver.py +1 -0
- scrapli/driver/generic/__init__.py +1 -0
- scrapli/driver/generic/async_driver.py +19 -1
- scrapli/driver/generic/base_driver.py +1 -0
- scrapli/driver/generic/sync_driver.py +19 -1
- scrapli/driver/network/__init__.py +1 -0
- scrapli/driver/network/async_driver.py +1 -0
- scrapli/driver/network/base_driver.py +1 -0
- scrapli/driver/network/sync_driver.py +1 -0
- scrapli/exceptions.py +1 -0
- scrapli/factory.py +4 -3
- scrapli/helper.py +9 -1
- 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 +37 -0
- scrapli/transport/plugins/system/transport.py +27 -6
- scrapli/transport/plugins/telnet/transport.py +13 -7
- {scrapli-2024.1.30.dist-info → scrapli-2024.7.30.dist-info}/METADATA +33 -6
- scrapli-2024.7.30.dist-info/RECORD +74 -0
- {scrapli-2024.1.30.dist-info → scrapli-2024.7.30.dist-info}/WHEEL +1 -1
- scrapli-2024.1.30.dist-info/RECORD +0 -74
- {scrapli-2024.1.30.dist-info → scrapli-2024.7.30.dist-info}/LICENSE +0 -0
- {scrapli-2024.1.30.dist-info → scrapli-2024.7.30.dist-info}/top_level.txt +0 -0
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.driver.generic.async_driver"""
|
2
|
+
|
2
3
|
import asyncio
|
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
|
+
async def generic_on_open(conn: "AsyncGenericDriver") -> 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
|
+
await conn.get_prompt()
|
35
|
+
|
36
|
+
|
19
37
|
class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
20
38
|
def __init__(
|
21
39
|
self,
|
@@ -39,7 +57,7 @@ class AsyncGenericDriver(AsyncDriver, BaseGenericDriver):
|
|
39
57
|
ssh_config_file: Union[str, bool] = False,
|
40
58
|
ssh_known_hosts_file: Union[str, bool] = False,
|
41
59
|
on_init: Optional[Callable[..., Any]] = None,
|
42
|
-
on_open: Optional[Callable[..., Any]] =
|
60
|
+
on_open: Optional[Callable[..., Any]] = generic_on_open,
|
43
61
|
on_close: Optional[Callable[..., Any]] = None,
|
44
62
|
transport: str = "system",
|
45
63
|
transport_options: Optional[Dict[str, Any]] = None,
|
@@ -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,
|
@@ -39,7 +57,7 @@ class GenericDriver(Driver, BaseGenericDriver):
|
|
39
57
|
ssh_config_file: Union[str, bool] = False,
|
40
58
|
ssh_known_hosts_file: Union[str, bool] = False,
|
41
59
|
on_init: Optional[Callable[..., Any]] = None,
|
42
|
-
on_open: Optional[Callable[..., Any]] =
|
60
|
+
on_open: Optional[Callable[..., Any]] = generic_on_open,
|
43
61
|
on_close: Optional[Callable[..., Any]] = None,
|
44
62
|
transport: str = "system",
|
45
63
|
transport_options: Optional[Dict[str, Any]] = None,
|
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
|
@@ -464,7 +465,7 @@ class Scrapli(NetworkDriver):
|
|
464
465
|
"""
|
465
466
|
logger.debug("Scrapli factory initialized")
|
466
467
|
|
467
|
-
if transport in ASYNCIO_TRANSPORTS:
|
468
|
+
if transport in CORE_TRANSPORTS and transport in ASYNCIO_TRANSPORTS:
|
468
469
|
raise ScrapliValueError("Use 'AsyncScrapli' if using an async transport!")
|
469
470
|
|
470
471
|
if not isinstance(platform, str):
|
@@ -763,7 +764,7 @@ class AsyncScrapli(AsyncNetworkDriver):
|
|
763
764
|
"""
|
764
765
|
logger.debug("AsyncScrapli factory initialized")
|
765
766
|
|
766
|
-
if transport not in ASYNCIO_TRANSPORTS:
|
767
|
+
if transport in CORE_TRANSPORTS and transport not in ASYNCIO_TRANSPORTS:
|
767
768
|
raise ScrapliValueError("Use 'Scrapli' if using a synchronous transport!")
|
768
769
|
|
769
770
|
if not isinstance(platform, str):
|
scrapli/helper.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.helper"""
|
2
|
+
|
2
3
|
import importlib
|
3
4
|
import importlib.resources
|
4
5
|
import sys
|
@@ -18,7 +19,14 @@ def _textfsm_get_template_directory() -> str:
|
|
18
19
|
if sys.version_info >= (3, 9):
|
19
20
|
return f"{importlib.resources.files('ntc_templates')}/templates"
|
20
21
|
|
21
|
-
|
22
|
+
if sys.version_info >= (3, 11):
|
23
|
+
# https://docs.python.org/3/library/importlib.resources.html#importlib.resources.path
|
24
|
+
with importlib.resources.as_file(
|
25
|
+
importlib.resources.files("ntc_templates").joinpath("templates")
|
26
|
+
) as path:
|
27
|
+
return str(path)
|
28
|
+
|
29
|
+
with importlib.resources.path("ntc_templates", "templates") as path: # pylint: disable=W4902
|
22
30
|
return str(path)
|
23
31
|
|
24
32
|
|
scrapli/logging.py
CHANGED
scrapli/response.py
CHANGED
scrapli/ssh_config.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.transport.plugins.asyncssh.transport"""
|
2
|
+
|
2
3
|
import asyncio
|
3
4
|
from contextlib import suppress
|
4
5
|
from dataclasses import dataclass
|
@@ -259,6 +260,9 @@ class AsyncsshTransport(AsyncTransport):
|
|
259
260
|
if not self.stdout:
|
260
261
|
raise ScrapliConnectionNotOpened
|
261
262
|
|
263
|
+
if self.stdout.at_eof():
|
264
|
+
raise ScrapliConnectionError("transport at EOF; no more data to be read")
|
265
|
+
|
262
266
|
try:
|
263
267
|
buf: bytes = await self.stdout.read(65535)
|
264
268
|
except ConnectionLost as exc:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.transport.plugins.asynctelnet.transport"""
|
2
|
+
|
2
3
|
import asyncio
|
3
4
|
import socket
|
4
5
|
from contextlib import suppress
|
@@ -116,6 +117,18 @@ class AsynctelnetTransport(AsyncTransport):
|
|
116
117
|
if not self.stdout:
|
117
118
|
raise ScrapliConnectionNotOpened
|
118
119
|
|
120
|
+
if self._raw_buf.find(NULL) != -1:
|
121
|
+
raise ScrapliConnectionNotOpened("server returned EOF, connection not opened")
|
122
|
+
|
123
|
+
index = self._raw_buf.find(IAC)
|
124
|
+
if index == -1:
|
125
|
+
self._cooked_buf = self._raw_buf
|
126
|
+
self._raw_buf = b""
|
127
|
+
return
|
128
|
+
|
129
|
+
self._cooked_buf = self._raw_buf[:index]
|
130
|
+
self._raw_buf = self._raw_buf[index:]
|
131
|
+
|
119
132
|
# control_buf is the buffer for control characters, we reset this after being "done" with
|
120
133
|
# responding to a control sequence, so it always represents the "current" control sequence
|
121
134
|
# we are working on responding to
|
@@ -123,9 +136,6 @@ class AsynctelnetTransport(AsyncTransport):
|
|
123
136
|
|
124
137
|
while self._raw_buf:
|
125
138
|
c, self._raw_buf = self._raw_buf[:1], self._raw_buf[1:]
|
126
|
-
if not c:
|
127
|
-
raise ScrapliConnectionNotOpened("server returned EOF, connection not opened")
|
128
|
-
|
129
139
|
control_buf = self._handle_control_chars_response(control_buf=control_buf, c=c)
|
130
140
|
|
131
141
|
async def open(self) -> None:
|
@@ -204,9 +214,6 @@ class AsynctelnetTransport(AsyncTransport):
|
|
204
214
|
if not self.stdout:
|
205
215
|
raise ScrapliConnectionNotOpened
|
206
216
|
|
207
|
-
if self._control_char_sent_counter < self._control_char_sent_limit:
|
208
|
-
self._handle_control_chars()
|
209
|
-
|
210
217
|
while not self._cooked_buf and not self._eof:
|
211
218
|
await self._read()
|
212
219
|
if self._control_char_sent_counter < self._control_char_sent_limit:
|
@@ -1,12 +1,15 @@
|
|
1
1
|
"""scrapli.transport.plugins.ssh2.transport"""
|
2
|
+
|
2
3
|
import base64
|
3
4
|
from contextlib import suppress
|
4
5
|
from dataclasses import dataclass
|
5
6
|
from typing import Optional
|
6
7
|
|
7
|
-
|
8
|
-
|
9
|
-
from ssh2.
|
8
|
+
# ignoring unable to import complaints for linters as ssh2 support is a bit lackluster due to
|
9
|
+
# upstream library staleness
|
10
|
+
from ssh2.channel import Channel # pylint: disable=E0401,E0611
|
11
|
+
from ssh2.exceptions import AuthenticationError, SSH2Error # pylint: disable=E0401,E0611
|
12
|
+
from ssh2.session import Session # pylint: disable=E0401,E0611
|
10
13
|
|
11
14
|
from scrapli.exceptions import (
|
12
15
|
ScrapliAuthenticationFailed,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.transport.plugins.system.ptyprocess"""
|
2
|
+
|
2
3
|
"""
|
3
4
|
Ptyprocess is under the ISC license, as code derived from Pexpect.
|
4
5
|
http://opensource.org/licenses/ISC
|
@@ -33,6 +34,7 @@ from shutil import which
|
|
33
34
|
from typing import List, Optional, Type, TypeVar
|
34
35
|
|
35
36
|
from scrapli.exceptions import ScrapliValueError
|
37
|
+
from scrapli.helper import user_warning
|
36
38
|
|
37
39
|
|
38
40
|
class PtyProcessError(Exception):
|
@@ -175,6 +177,35 @@ def _setecho(fd: int, state: bool) -> None:
|
|
175
177
|
raise
|
176
178
|
|
177
179
|
|
180
|
+
def _setonlcr(fd: int, state: bool) -> None:
|
181
|
+
import termios
|
182
|
+
|
183
|
+
try:
|
184
|
+
attr = termios.tcgetattr(fd)
|
185
|
+
except termios.error as err:
|
186
|
+
if err.args[0] == errno.EINVAL:
|
187
|
+
raise OSError(err.args[0], "{}: {}.".format(err.args[1], errmsg))
|
188
|
+
raise
|
189
|
+
|
190
|
+
if state:
|
191
|
+
attr[1] = attr[1] | termios.ONLCR
|
192
|
+
else:
|
193
|
+
attr[1] = attr[1] & ~termios.ONLCR
|
194
|
+
|
195
|
+
try:
|
196
|
+
termios.tcsetattr(fd, termios.TCSANOW, attr)
|
197
|
+
except OSError as err:
|
198
|
+
if err.args[0] == errno.EINVAL:
|
199
|
+
title = "Set ONLCR!"
|
200
|
+
message = (
|
201
|
+
"_setonlcr() failed -- if you encounter this error please open an issue! unless you "
|
202
|
+
"are seeing this when using scrapli_netconf you can *probably* ignore this though!"
|
203
|
+
)
|
204
|
+
|
205
|
+
user_warning(title=title, message=message)
|
206
|
+
raise
|
207
|
+
|
208
|
+
|
178
209
|
class PtyProcess:
|
179
210
|
def __init__(self, pid: int, fd: int) -> None:
|
180
211
|
"""
|
@@ -354,6 +385,12 @@ class PtyProcess:
|
|
354
385
|
if err.args[0] not in (errno.EINVAL, errno.ENOTTY, errno.ENXIO):
|
355
386
|
raise
|
356
387
|
|
388
|
+
# attrs = termios.tcgetattr(fd)
|
389
|
+
# attrs[1] &= ~termios.ONLCR
|
390
|
+
# termios.tcsetattr(fd, termios.TCSANOW, attrs)
|
391
|
+
|
392
|
+
_setonlcr(fd, True)
|
393
|
+
|
357
394
|
return inst
|
358
395
|
|
359
396
|
def __repr__(self) -> str:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.transport.plugins.system.transport"""
|
2
|
+
|
2
3
|
import sys
|
3
4
|
from dataclasses import dataclass
|
4
5
|
from typing import List, Optional
|
@@ -23,6 +24,9 @@ class PluginTransportArgs(BasePluginTransportArgs):
|
|
23
24
|
|
24
25
|
|
25
26
|
class SystemTransport(Transport):
|
27
|
+
SSH_SYSTEM_CONFIG_MAGIC_STRING: str = "SYSTEM_TRANSPORT_SSH_CONFIG_TRUE"
|
28
|
+
SSH_SYSTEM_KNOWN_HOSTS_FILE_MAGIC_STRING: str = "SYSTEM_TRANSPORT_KNOWN_HOSTS_TRUE"
|
29
|
+
|
26
30
|
def __init__(
|
27
31
|
self, base_transport_args: BaseTransportArgs, plugin_transport_args: PluginTransportArgs
|
28
32
|
) -> None:
|
@@ -99,15 +103,32 @@ class SystemTransport(Transport):
|
|
99
103
|
self.open_cmd.extend(["-o", "UserKnownHostsFile=/dev/null"])
|
100
104
|
else:
|
101
105
|
self.open_cmd.extend(["-o", "StrictHostKeyChecking=yes"])
|
102
|
-
|
106
|
+
|
107
|
+
if (
|
108
|
+
self.plugin_transport_args.ssh_known_hosts_file
|
109
|
+
== self.SSH_SYSTEM_KNOWN_HOSTS_FILE_MAGIC_STRING
|
110
|
+
):
|
111
|
+
self.logger.debug(
|
112
|
+
"Using system transport and ssh_known_hosts_file is True, not specifying any "
|
113
|
+
"known_hosts file"
|
114
|
+
)
|
115
|
+
elif self.plugin_transport_args.ssh_known_hosts_file:
|
103
116
|
self.open_cmd.extend(
|
104
|
-
[
|
117
|
+
[
|
118
|
+
"-o",
|
119
|
+
f"UserKnownHostsFile={self.plugin_transport_args.ssh_known_hosts_file}",
|
120
|
+
]
|
105
121
|
)
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
else:
|
122
|
+
else:
|
123
|
+
self.logger.debug("No known hosts file specified")
|
124
|
+
if not self.plugin_transport_args.ssh_config_file:
|
110
125
|
self.open_cmd.extend(["-F", "/dev/null"])
|
126
|
+
elif self.plugin_transport_args.ssh_config_file == self.SSH_SYSTEM_CONFIG_MAGIC_STRING:
|
127
|
+
self.logger.debug(
|
128
|
+
"Using system transport and ssh_config is True, not specifying any SSH config"
|
129
|
+
)
|
130
|
+
else:
|
131
|
+
self.open_cmd.extend(["-F", self.plugin_transport_args.ssh_config_file])
|
111
132
|
|
112
133
|
open_cmd_user_args = self._base_transport_args.transport_options.get("open_cmd", [])
|
113
134
|
if isinstance(open_cmd_user_args, str):
|
@@ -1,4 +1,5 @@
|
|
1
1
|
"""scrapli.transport.plugins.telnet.transport"""
|
2
|
+
|
2
3
|
from dataclasses import dataclass
|
3
4
|
from typing import Optional
|
4
5
|
|
@@ -147,13 +148,21 @@ class TelnetTransport(Transport):
|
|
147
148
|
if not self.socket:
|
148
149
|
raise ScrapliConnectionNotOpened
|
149
150
|
|
151
|
+
if self._raw_buf.find(NULL) != -1:
|
152
|
+
raise ScrapliConnectionNotOpened("server returned EOF, connection not opened")
|
153
|
+
|
154
|
+
index = self._raw_buf.find(IAC)
|
155
|
+
if index == -1:
|
156
|
+
self._cooked_buf = self._raw_buf
|
157
|
+
self._raw_buf = b""
|
158
|
+
return
|
159
|
+
|
160
|
+
self._cooked_buf = self._raw_buf[:index]
|
161
|
+
self._raw_buf = self._raw_buf[index:]
|
150
162
|
control_buf = b""
|
151
163
|
|
152
164
|
while self._raw_buf:
|
153
165
|
c, self._raw_buf = self._raw_buf[:1], self._raw_buf[1:]
|
154
|
-
if not c:
|
155
|
-
raise ScrapliConnectionNotOpened("server returned EOF, connection not opened")
|
156
|
-
|
157
166
|
control_buf = self._handle_control_chars_response(control_buf=control_buf, c=c)
|
158
167
|
|
159
168
|
def open(self) -> None:
|
@@ -217,7 +226,7 @@ class TelnetTransport(Transport):
|
|
217
226
|
self._raw_buf += buf
|
218
227
|
else:
|
219
228
|
self._cooked_buf += buf
|
220
|
-
except
|
229
|
+
except EOFError as exc:
|
221
230
|
raise ScrapliConnectionError(
|
222
231
|
"encountered EOF reading from transport; typically means the device closed the "
|
223
232
|
"connection"
|
@@ -228,9 +237,6 @@ class TelnetTransport(Transport):
|
|
228
237
|
if not self.socket:
|
229
238
|
raise ScrapliConnectionNotOpened
|
230
239
|
|
231
|
-
if self._control_char_sent_counter < self._control_char_sent_limit:
|
232
|
-
self._handle_control_chars()
|
233
|
-
|
234
240
|
while not self._cooked_buf and not self._eof:
|
235
241
|
self._read()
|
236
242
|
if self._control_char_sent_counter < self._control_char_sent_limit:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: scrapli
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.7.30
|
4
4
|
Summary: Fast, flexible, sync/async, Python 3.7+ screen scraping client specifically for network devices
|
5
5
|
Author-email: Carl Montanari <carl.r.montanari@gmail.com>
|
6
6
|
License: MIT License
|
@@ -48,14 +48,14 @@ Requires-Dist: asyncssh <3.0.0,>=2.2.1 ; extra == 'asyncssh'
|
|
48
48
|
Provides-Extra: community
|
49
49
|
Requires-Dist: scrapli-community >=2021.01.30 ; extra == 'community'
|
50
50
|
Provides-Extra: dev
|
51
|
-
Requires-Dist: black <
|
51
|
+
Requires-Dist: black <25.0.0,>=23.3.0 ; extra == 'dev'
|
52
52
|
Requires-Dist: darglint <2.0.0,>=1.8.1 ; extra == 'dev'
|
53
53
|
Requires-Dist: isort <6.0.0,>=5.10.1 ; extra == 'dev'
|
54
54
|
Requires-Dist: mypy <2.0.0,>=1.4.1 ; extra == 'dev'
|
55
|
-
Requires-Dist: nox ==
|
55
|
+
Requires-Dist: nox ==2024.4.15 ; extra == 'dev'
|
56
56
|
Requires-Dist: pycodestyle <3.0.0,>=2.8.0 ; extra == 'dev'
|
57
57
|
Requires-Dist: pydocstyle <7.0.0,>=6.1.1 ; extra == 'dev'
|
58
|
-
Requires-Dist: pyfakefs <6.0.0,>=5.
|
58
|
+
Requires-Dist: pyfakefs <6.0.0,>=5.4.1 ; extra == 'dev'
|
59
59
|
Requires-Dist: pylama <9.0.0,>=8.4.0 ; extra == 'dev'
|
60
60
|
Requires-Dist: pylint <4.0.0,>=3.0.0 ; extra == 'dev'
|
61
61
|
Requires-Dist: pytest-asyncio <1.0.0,>=0.17.0 ; extra == 'dev'
|
@@ -72,8 +72,35 @@ Requires-Dist: ttp <1.0.0,>=0.5.0 ; extra == 'dev'
|
|
72
72
|
Requires-Dist: paramiko <4.0.0,>=2.6.0 ; extra == 'dev'
|
73
73
|
Requires-Dist: asyncssh <3.0.0,>=2.2.1 ; extra == 'dev'
|
74
74
|
Requires-Dist: scrapli-community >=2021.01.30 ; extra == 'dev'
|
75
|
+
Provides-Extra: dev-darwin
|
76
|
+
Requires-Dist: black <25.0.0,>=23.3.0 ; extra == 'dev-darwin'
|
77
|
+
Requires-Dist: darglint <2.0.0,>=1.8.1 ; extra == 'dev-darwin'
|
78
|
+
Requires-Dist: isort <6.0.0,>=5.10.1 ; extra == 'dev-darwin'
|
79
|
+
Requires-Dist: mypy <2.0.0,>=1.4.1 ; extra == 'dev-darwin'
|
80
|
+
Requires-Dist: nox ==2024.4.15 ; extra == 'dev-darwin'
|
81
|
+
Requires-Dist: pycodestyle <3.0.0,>=2.8.0 ; extra == 'dev-darwin'
|
82
|
+
Requires-Dist: pydocstyle <7.0.0,>=6.1.1 ; extra == 'dev-darwin'
|
83
|
+
Requires-Dist: pyfakefs <6.0.0,>=5.4.1 ; extra == 'dev-darwin'
|
84
|
+
Requires-Dist: pylama <9.0.0,>=8.4.0 ; extra == 'dev-darwin'
|
85
|
+
Requires-Dist: pylint <4.0.0,>=3.0.0 ; extra == 'dev-darwin'
|
86
|
+
Requires-Dist: pytest-asyncio <1.0.0,>=0.17.0 ; extra == 'dev-darwin'
|
87
|
+
Requires-Dist: pytest-cov <5.0.0,>=3.0.0 ; extra == 'dev-darwin'
|
88
|
+
Requires-Dist: pytest <8.0.0,>=7.0.0 ; extra == 'dev-darwin'
|
89
|
+
Requires-Dist: scrapli-cfg ==2023.7.30 ; extra == 'dev-darwin'
|
90
|
+
Requires-Dist: scrapli-replay ==2023.7.30 ; extra == 'dev-darwin'
|
91
|
+
Requires-Dist: toml <1.0.0,>=0.10.2 ; extra == 'dev-darwin'
|
92
|
+
Requires-Dist: types-paramiko <4.0.0,>=2.8.6 ; extra == 'dev-darwin'
|
93
|
+
Requires-Dist: types-pkg-resources <1.0.0,>=0.1.3 ; extra == 'dev-darwin'
|
94
|
+
Requires-Dist: ntc-templates <5.0.0,>=1.1.0 ; extra == 'dev-darwin'
|
95
|
+
Requires-Dist: textfsm <2.0.0,>=1.1.0 ; extra == 'dev-darwin'
|
96
|
+
Requires-Dist: ttp <1.0.0,>=0.5.0 ; extra == 'dev-darwin'
|
97
|
+
Requires-Dist: paramiko <4.0.0,>=2.6.0 ; extra == 'dev-darwin'
|
98
|
+
Requires-Dist: asyncssh <3.0.0,>=2.2.1 ; extra == 'dev-darwin'
|
99
|
+
Requires-Dist: scrapli-community >=2021.01.30 ; extra == 'dev-darwin'
|
100
|
+
Requires-Dist: genie <24.4,>=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'dev-darwin'
|
101
|
+
Requires-Dist: pyats >=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'dev-darwin'
|
75
102
|
Requires-Dist: ssh2-python <2.0.0,>=0.23.0 ; (python_version < "3.12") and extra == 'dev'
|
76
|
-
Requires-Dist: genie
|
103
|
+
Requires-Dist: genie <24.4,>=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'dev'
|
77
104
|
Requires-Dist: pyats >=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'dev'
|
78
105
|
Provides-Extra: docs
|
79
106
|
Requires-Dist: mdx-gh-links <1.0,>=0.2 ; extra == 'docs'
|
@@ -85,7 +112,7 @@ Requires-Dist: mkdocs-material-extensions <2.0.0,>=1.0.3 ; extra == 'docs'
|
|
85
112
|
Requires-Dist: mkdocs-section-index <1.0.0,>=0.3.4 ; extra == 'docs'
|
86
113
|
Requires-Dist: mkdocstrings[python] <1.0.0,>=0.19.0 ; extra == 'docs'
|
87
114
|
Provides-Extra: genie
|
88
|
-
Requires-Dist: genie
|
115
|
+
Requires-Dist: genie <24.4,>=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'genie'
|
89
116
|
Requires-Dist: pyats >=20.2 ; (sys_platform != "win32" and python_version < "3.11") and extra == 'genie'
|
90
117
|
Provides-Extra: paramiko
|
91
118
|
Requires-Dist: paramiko <4.0.0,>=2.6.0 ; extra == 'paramiko'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
scrapli/__init__.py,sha256=uxxnFUBmyzthxJtctiapxFoYkCiphAypRtRkdTqxrzU,228
|
2
|
+
scrapli/decorators.py,sha256=KlxKugMnfpAUgbkR_Ok7MPDRY98BNvCorXnpeakQcFE,10422
|
3
|
+
scrapli/exceptions.py,sha256=AlWmOIGpdZhcEGgv4H7Tpw9B9QdoXBG-DPYooSKHlxM,1938
|
4
|
+
scrapli/factory.py,sha256=SDVtvhqF8tAj5-cbwu3NWY31rkb508wHolMpGyDp3x0,37673
|
5
|
+
scrapli/helper.py,sha256=M4TiGiLYqdpaPVLP_ffK87eG20Uwzd8dLbG9f0JBi4o,11553
|
6
|
+
scrapli/logging.py,sha256=HJkDXhL9j9HfHkcEap3WSfKO3FnLHBg4v7wCFqgV99k,9802
|
7
|
+
scrapli/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
scrapli/response.py,sha256=bQGuH-cKlOIlCfBHf3QVYzz852INUstiS_ivzKUMbqM,8866
|
9
|
+
scrapli/settings.py,sha256=bbbNa5Aj4aR-rMaxGCLwogpdedadrQfar6sj9y95rlw,235
|
10
|
+
scrapli/ssh_config.py,sha256=NJ0t4Waq1D5-k27Q93AU4FJGie0pDiag2PvJFMVhhG4,17911
|
11
|
+
scrapli/channel/__init__.py,sha256=U06VyCKvvjUU4VDdwt5IrciwSvoigxClwQ72bVwvs7A,177
|
12
|
+
scrapli/channel/async_channel.py,sha256=z3BbNt_l6wO_yvi-nkE90ZcbYtbupZsiE21OSRNeRa8,23234
|
13
|
+
scrapli/channel/base_channel.py,sha256=hXKfzjkP1VD2v6hOgb2MUQuhksfkTdT1BEN2VVMeiKY,22033
|
14
|
+
scrapli/channel/sync_channel.py,sha256=mSlAdvkX6GklOoHsoB-GUfB477arLRyPpeDVPdeidLE,23217
|
15
|
+
scrapli/driver/__init__.py,sha256=oXZkMs5nZlDsLsUMdEShxxtx5-bakQ2xzf8EZLIQAfE,354
|
16
|
+
scrapli/driver/base/__init__.py,sha256=-RPF8z1Qo7wXBCUZZMLjDYBTaXg4qZ0ofB_uMWi6hD4,183
|
17
|
+
scrapli/driver/base/async_driver.py,sha256=pEf0B6TmkdOm6ytNmhgUHbUcyFasn9b5hMmcqQ2IPWM,9843
|
18
|
+
scrapli/driver/base/base_driver.py,sha256=-owg7qqbmrFtFqQn7Lncc4t0hV1630sRf7RK04cw5bY,36622
|
19
|
+
scrapli/driver/base/sync_driver.py,sha256=KsYvueu_gFFL0VQ0t4NFXLWHYjfLxFCsiT00JsDdrc8,6156
|
20
|
+
scrapli/driver/core/__init__.py,sha256=dnxS1ibXoma7FMzb_6iMDdoC0ioivleDrzOAq6pD7BQ,615
|
21
|
+
scrapli/driver/core/arista_eos/__init__.py,sha256=HoOP-do1Nb-6AAGEprUbJFdE3cziBzSB3so6tZASRKk,228
|
22
|
+
scrapli/driver/core/arista_eos/async_driver.py,sha256=siHyelArMaV_TgOcrNwkciHUXrPpXYAxwRN1kXSX1Ic,7412
|
23
|
+
scrapli/driver/core/arista_eos/base_driver.py,sha256=06BRyGH_iZT3cDccBdwmm5ElFMQz8FsljsgUsuAbpLs,2794
|
24
|
+
scrapli/driver/core/arista_eos/sync_driver.py,sha256=rzdWaGbb14hOW-O19co1azDXzNnifST9RxMTX_OzIKQ,7367
|
25
|
+
scrapli/driver/core/cisco_iosxe/__init__.py,sha256=gAIKcWEyuCKD7U6s7C8Tr60YRVpT2h3RMgbeqcXwKLQ,239
|
26
|
+
scrapli/driver/core/cisco_iosxe/async_driver.py,sha256=beWsOkNRrdb8etTsdYZYe60BXomEMwMyMkuKdFI6Z70,6357
|
27
|
+
scrapli/driver/core/cisco_iosxe/base_driver.py,sha256=qewpK9mJPDM_WEIJnqCRPJ3Lp1F243WtJ6CrA9tW3bc,1568
|
28
|
+
scrapli/driver/core/cisco_iosxe/sync_driver.py,sha256=YcYFcuakjIFRSyzLXTR_pQjYcIyyl0vE7kMNyizgt0g,6280
|
29
|
+
scrapli/driver/core/cisco_iosxr/__init__.py,sha256=mCyGrWDxDsCK-2lPidOkmgWz7p6ibISxkbmJTnLrNqc,239
|
30
|
+
scrapli/driver/core/cisco_iosxr/async_driver.py,sha256=9efUWy-xJ3tXS274QuGmvYhbqK-JVZIxClfqgDIWzXc,6699
|
31
|
+
scrapli/driver/core/cisco_iosxr/base_driver.py,sha256=TWkI6uBzfCniPPpK4HpSeJzpbKMjTgLfLHfCHPU-nBQ,1262
|
32
|
+
scrapli/driver/core/cisco_iosxr/sync_driver.py,sha256=fskRc_ZQMXnyu9sIHhEh44VAwcr3YQXAx5SbQLHP-uY,6733
|
33
|
+
scrapli/driver/core/cisco_nxos/__init__.py,sha256=vtq65EDKjYqhg9HUGnZrdaRqpYVuz24Oe_WWdzqzQJs,232
|
34
|
+
scrapli/driver/core/cisco_nxos/async_driver.py,sha256=92DkZkiSy3PXY5pr1BwMRlQWZRKzqMS71sjEYtmhQaE,7443
|
35
|
+
scrapli/driver/core/cisco_nxos/base_driver.py,sha256=eNjYkMjWyOn6oLZ4vTc0rHpqOHUU8Yt09tZZQwFyUVg,3519
|
36
|
+
scrapli/driver/core/cisco_nxos/sync_driver.py,sha256=icih-fn9yrU23XAH-J8BOLjSt2QXb5-yE53wPisRYU8,7359
|
37
|
+
scrapli/driver/core/juniper_junos/__init__.py,sha256=kKVB77xdHTVyL3sGzQFUPYGshMCqxoIJAHSxkw_wfZA,245
|
38
|
+
scrapli/driver/core/juniper_junos/async_driver.py,sha256=b33RLXu1BWPy019w-T_ozO0IhhvqW96FpPdn8XjBZi4,6746
|
39
|
+
scrapli/driver/core/juniper_junos/base_driver.py,sha256=uZMW5F8zOOE5TeAqVIA71OyiYh4gOUN4t5vj63glteM,2326
|
40
|
+
scrapli/driver/core/juniper_junos/sync_driver.py,sha256=_3HmTv6Kz66x83KxBJ7Y6zkjFqrxAywy-H8vX0VrlGA,6683
|
41
|
+
scrapli/driver/generic/__init__.py,sha256=0mtOYfBKHqcjSwswPs0Bj2QQnmzW4ugaCAPgx1d9ddU,300
|
42
|
+
scrapli/driver/generic/async_driver.py,sha256=oUb4RyTetu6eWzXDPAJB07jwUYGOsi_9Z2_2f8YFnRg,25951
|
43
|
+
scrapli/driver/generic/base_driver.py,sha256=k-3FjbiGVG5QZKrE4ZGFkBpNuI0zqiMG7OMMWfVIabc,11715
|
44
|
+
scrapli/driver/generic/sync_driver.py,sha256=1K4u-rd-xyFssap_AkS_UnH0g4nmDZdmaZNZIPPEXUY,25674
|
45
|
+
scrapli/driver/network/__init__.py,sha256=RAF9vpgJgcpkFgogfSyoE6P_JMqf-ycLLcoBMaRFdeY,220
|
46
|
+
scrapli/driver/network/async_driver.py,sha256=sMR3xb5iaKT7Je6LDmw-UJT6qwXo3q6t4KJnTCFeLwE,28099
|
47
|
+
scrapli/driver/network/base_driver.py,sha256=P5G95FVoqpHrewcP0Pfcth8ICSBvssTHeauch_ZE0fY,21166
|
48
|
+
scrapli/driver/network/sync_driver.py,sha256=B49sUt_1CJyOmbdnAn0n1pmrdCGJ0C7qmfQZjMt28Xg,27901
|
49
|
+
scrapli/transport/__init__.py,sha256=wHs6v4o_a_EWYfbItBgCy8lZOsOH3wFSTeImrPJhEcs,235
|
50
|
+
scrapli/transport/base/__init__.py,sha256=VW-80qXrzoCRhiWXY2yLTRBZT-6q1RSc34-1dbLNiPw,359
|
51
|
+
scrapli/transport/base/async_transport.py,sha256=yOBv6VnsPwZ-H_0PNhe_w-fUq20-z084atwFrrFNM2U,624
|
52
|
+
scrapli/transport/base/base_socket.py,sha256=eSPBWCEJvNCE0hTvBAkHM4LCzOqwHqPxbevSbfKooOI,5897
|
53
|
+
scrapli/transport/base/base_transport.py,sha256=Ft7nbtwVdgcbCGZTe7yEwidh9eE0HZmhqQvNIuP8BDI,2952
|
54
|
+
scrapli/transport/base/sync_transport.py,sha256=LpTtsZPLSw8_ZiSQB3NzS4PiVFB5Z0vXee2PW-LaEbQ,606
|
55
|
+
scrapli/transport/base/telnet_common.py,sha256=Wm0D3wOmRfj4jlqEuAIth85KrLiVYHbdeyfbLZ77zZ4,214
|
56
|
+
scrapli/transport/plugins/__init__.py,sha256=ZHtpJzgUgiuNI7-24rp-TcTRvpq8fpef9iOKHxNUmx0,32
|
57
|
+
scrapli/transport/plugins/asyncssh/__init__.py,sha256=0Gk32fKg-7uPTOQLP_kqj6T5GSt26zE86fzRAqhCjtc,41
|
58
|
+
scrapli/transport/plugins/asyncssh/transport.py,sha256=4kIuXJspknLLGgzJwwDYEZ1FIEs5BpIbIHGHbC1_avU,10402
|
59
|
+
scrapli/transport/plugins/asynctelnet/__init__.py,sha256=eR0je4izyYOZtlyKkUTXwi_FtzJhzSoLZvCaJx31E70,44
|
60
|
+
scrapli/transport/plugins/asynctelnet/transport.py,sha256=toAKK7jRd-p8cuupueSqRvke4RM7bak8W-LYAcQC7FI,8582
|
61
|
+
scrapli/transport/plugins/paramiko/__init__.py,sha256=6TD1vWG7vxDrSu33Olcs0Q_9mU2lita0Au6gTtq6-NE,41
|
62
|
+
scrapli/transport/plugins/paramiko/transport.py,sha256=vFkVC_NJuKcalxdRirzsXnY9sSRCZ5iFdrDuqQYSS3I,9869
|
63
|
+
scrapli/transport/plugins/ssh2/__init__.py,sha256=uM4oUBrI1lhw6IAhfRa_ixhwVqMeb9RoEe157QM4XIA,37
|
64
|
+
scrapli/transport/plugins/ssh2/transport.py,sha256=qTVJpYXNE_wtHndPIR2JtUDOyegOiQ14ZZ8Rj8bt23Y,9073
|
65
|
+
scrapli/transport/plugins/system/__init__.py,sha256=Fhudt-5pwvGZxbzb9JSzX2BkyPHU6SjmyNaaD00-510,39
|
66
|
+
scrapli/transport/plugins/system/ptyprocess.py,sha256=wzy-z3UkKZY1ADZQVAOjsEdNaJ74b5LVPD2amP-dE8U,25165
|
67
|
+
scrapli/transport/plugins/system/transport.py,sha256=asuq7tU_D9fWJEIvblKOELNbSdoUkvSMVpdTF71TptI,6935
|
68
|
+
scrapli/transport/plugins/telnet/__init__.py,sha256=ce0syarhrpeD1NHtqbazPI09VLvF2n5oC2UE9G_Rbr0,39
|
69
|
+
scrapli/transport/plugins/telnet/transport.py,sha256=VyIamvT_I8IyEqTv-DabJErbYZrBKDscHNFY1kto2wU,8293
|
70
|
+
scrapli-2024.7.30.dist-info/LICENSE,sha256=IeyhkG2h_dAvJ7nAF0S4GSUg045jwI27YADV_KSJi50,1071
|
71
|
+
scrapli-2024.7.30.dist-info/METADATA,sha256=qwRvwRUyCiYCpXTQ-ny2lsRoA7FHiBSIAcXn7ZGhAL4,11664
|
72
|
+
scrapli-2024.7.30.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
73
|
+
scrapli-2024.7.30.dist-info/top_level.txt,sha256=piC9TaaPt0z-1Ryrs69hDvsIQkmE5ceDAAW5donUvsI,8
|
74
|
+
scrapli-2024.7.30.dist-info/RECORD,,
|