scrapli 2.0.0a2__py3-none-musllinux_1_1_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/ffi_types.py
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
"""scrapli.ffi_types"""
|
2
|
+
|
3
|
+
from ctypes import (
|
4
|
+
CFUNCTYPE,
|
5
|
+
POINTER,
|
6
|
+
Structure,
|
7
|
+
c_bool,
|
8
|
+
c_char_p,
|
9
|
+
c_int,
|
10
|
+
c_size_t,
|
11
|
+
c_uint,
|
12
|
+
c_uint8,
|
13
|
+
c_uint64,
|
14
|
+
c_void_p,
|
15
|
+
cast,
|
16
|
+
)
|
17
|
+
from typing import TypeAlias
|
18
|
+
|
19
|
+
DriverPointer = c_void_p
|
20
|
+
OperationId = c_uint
|
21
|
+
|
22
|
+
# mypy seems to dislike the pointer bits, but these do accurately reflect the api surface,
|
23
|
+
# so... we'll just tell mypy to chill out on these
|
24
|
+
OperationIdPointer: TypeAlias = POINTER(OperationId) # type: ignore[valid-type]
|
25
|
+
CancelPointer: TypeAlias = POINTER(c_bool) # type: ignore[valid-type]
|
26
|
+
ZigSlicePointer: TypeAlias = POINTER("ZigSlice") # type: ignore[valid-type, call-overload]
|
27
|
+
StringPointer: TypeAlias = POINTER(c_char_p) # type: ignore[valid-type]
|
28
|
+
IntPointer: TypeAlias = POINTER(c_int) # type: ignore[valid-type]
|
29
|
+
U64Pointer: TypeAlias = POINTER(c_uint64) # type: ignore[valid-type]
|
30
|
+
BoolPointer: TypeAlias = POINTER(c_bool) # type: ignore[valid-type]
|
31
|
+
|
32
|
+
|
33
|
+
class ZigU64Slice(Structure):
|
34
|
+
"""
|
35
|
+
A struct representing a slice of u64 in zig.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
N/A
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
None
|
42
|
+
|
43
|
+
Raises:
|
44
|
+
N/A
|
45
|
+
|
46
|
+
"""
|
47
|
+
|
48
|
+
# fields must be declared this way to be c types compatible
|
49
|
+
_fields_ = [ # noqa: RUF012
|
50
|
+
("ptr", POINTER(c_uint64)),
|
51
|
+
("len", c_size_t),
|
52
|
+
]
|
53
|
+
|
54
|
+
def __init__(self, size: c_int):
|
55
|
+
self.ptr = cast((c_uint64 * size.value)(), POINTER(c_uint64))
|
56
|
+
self.len = size.value
|
57
|
+
|
58
|
+
super().__init__()
|
59
|
+
|
60
|
+
def get_contents(self) -> list[int]:
|
61
|
+
"""
|
62
|
+
Return the contents of the slice as a list of ints.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
N/A
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
list[int]: the slice contents
|
69
|
+
|
70
|
+
Raises:
|
71
|
+
N/A
|
72
|
+
|
73
|
+
"""
|
74
|
+
return [self.ptr[i] for i in range(self.len)]
|
75
|
+
|
76
|
+
|
77
|
+
class ZigSlice(Structure):
|
78
|
+
"""
|
79
|
+
A struct representing a slice of u8 (a string) in zig.
|
80
|
+
|
81
|
+
Args:
|
82
|
+
N/A
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
None
|
86
|
+
|
87
|
+
Raises:
|
88
|
+
N/A
|
89
|
+
|
90
|
+
"""
|
91
|
+
|
92
|
+
_fields_ = [ # noqa: RUF012
|
93
|
+
("ptr", POINTER(c_uint8)),
|
94
|
+
("len", c_size_t),
|
95
|
+
("value", c_char_p),
|
96
|
+
]
|
97
|
+
|
98
|
+
def __init__(self, size: c_int):
|
99
|
+
self.ptr = cast((c_uint8 * size.value)(), POINTER(c_uint8))
|
100
|
+
self.len = size.value
|
101
|
+
|
102
|
+
super().__init__()
|
103
|
+
|
104
|
+
def get_contents(self) -> bytes:
|
105
|
+
"""
|
106
|
+
Return the contents of the slice as bytes.
|
107
|
+
|
108
|
+
Args:
|
109
|
+
N/A
|
110
|
+
|
111
|
+
Returns:
|
112
|
+
bytes: the slice contents
|
113
|
+
|
114
|
+
Raises:
|
115
|
+
N/A
|
116
|
+
|
117
|
+
"""
|
118
|
+
return bytes(cast(self.ptr, POINTER(c_uint8 * self.len)).contents)
|
119
|
+
|
120
|
+
def get_decoded_contents(self) -> str:
|
121
|
+
"""
|
122
|
+
Return the contents of the slice as str.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
N/A
|
126
|
+
|
127
|
+
Returns:
|
128
|
+
bytes: the slice contents
|
129
|
+
|
130
|
+
Raises:
|
131
|
+
N/A
|
132
|
+
|
133
|
+
"""
|
134
|
+
return self.get_contents().decode()
|
135
|
+
|
136
|
+
|
137
|
+
def to_c_string(s: str) -> c_char_p:
|
138
|
+
"""
|
139
|
+
Accepts a string and converts it to a c_char_p.
|
140
|
+
|
141
|
+
Args:
|
142
|
+
s: the string-like thing to convert to a c_char_p
|
143
|
+
|
144
|
+
Returns:
|
145
|
+
c_char_p: the converted string
|
146
|
+
|
147
|
+
Raises:
|
148
|
+
N/A
|
149
|
+
|
150
|
+
"""
|
151
|
+
return c_char_p(s.encode(encoding="utf-8"))
|
152
|
+
|
153
|
+
|
154
|
+
LogFuncCallback: TypeAlias = CFUNCTYPE(None, c_uint8, POINTER(ZigSlice)) # type: ignore[valid-type]
|
scrapli/helper.py
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
"""scrapli.helper"""
|
2
|
+
|
3
|
+
from asyncio import get_event_loop
|
4
|
+
from os import read
|
5
|
+
from pathlib import Path
|
6
|
+
from select import select
|
7
|
+
|
8
|
+
from scrapli.exceptions import OperationException
|
9
|
+
|
10
|
+
|
11
|
+
def resolve_file(file: str) -> str:
|
12
|
+
"""
|
13
|
+
Resolve file from provided string
|
14
|
+
|
15
|
+
Args:
|
16
|
+
file: string path to file
|
17
|
+
|
18
|
+
Returns:
|
19
|
+
str: resolved/expanded (if applicable) string path to file
|
20
|
+
|
21
|
+
Raises:
|
22
|
+
OperationException: if file cannot be resolved
|
23
|
+
|
24
|
+
"""
|
25
|
+
if Path(file).is_file():
|
26
|
+
return str(Path(file))
|
27
|
+
if Path(file).expanduser().is_file():
|
28
|
+
return str(Path(file).expanduser())
|
29
|
+
|
30
|
+
raise OperationException(f"path `{file}` could not be resolved")
|
31
|
+
|
32
|
+
|
33
|
+
def wait_for_available_operation_result(fd: int) -> None:
|
34
|
+
"""
|
35
|
+
Wait for the next operation to be complete.
|
36
|
+
|
37
|
+
Args:
|
38
|
+
fd: the fd to wait on
|
39
|
+
|
40
|
+
Returns:
|
41
|
+
None
|
42
|
+
|
43
|
+
Raises:
|
44
|
+
N/A
|
45
|
+
|
46
|
+
"""
|
47
|
+
_, _, _ = select([fd], [], [])
|
48
|
+
read(fd, 1)
|
49
|
+
|
50
|
+
|
51
|
+
async def _wait_for_fd_readable(fd: int) -> None:
|
52
|
+
"""
|
53
|
+
Wait for fd to be readable.
|
54
|
+
|
55
|
+
Args:
|
56
|
+
fd: the fd to wait on
|
57
|
+
|
58
|
+
Returns:
|
59
|
+
None
|
60
|
+
|
61
|
+
Raises:
|
62
|
+
N/A
|
63
|
+
|
64
|
+
"""
|
65
|
+
loop = get_event_loop()
|
66
|
+
|
67
|
+
fut = loop.create_future()
|
68
|
+
|
69
|
+
def on_ready() -> None:
|
70
|
+
loop.remove_reader(fd)
|
71
|
+
|
72
|
+
fut.set_result(None)
|
73
|
+
|
74
|
+
loop.add_reader(fd, on_ready)
|
75
|
+
|
76
|
+
await fut
|
77
|
+
|
78
|
+
|
79
|
+
async def wait_for_available_operation_result_async(fd: int) -> None:
|
80
|
+
"""
|
81
|
+
Wait for the next operation to be complete.
|
82
|
+
|
83
|
+
Args:
|
84
|
+
fd: the fd to wait on
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
None
|
88
|
+
|
89
|
+
Raises:
|
90
|
+
N/A
|
91
|
+
|
92
|
+
"""
|
93
|
+
await _wait_for_fd_readable(fd)
|
94
|
+
|
95
|
+
read(fd, 1)
|
scrapli/lib/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
"""scrapli.lib"""
|
Binary file
|
Binary file
|