ntermqt 0.1.7__py3-none-any.whl → 0.1.9__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.
- nterm/parser/api_help_dialog.py +426 -223
- nterm/scripting/api.py +421 -701
- nterm/scripting/models.py +195 -0
- nterm/scripting/platform_data.py +272 -0
- nterm/scripting/platform_utils.py +596 -0
- nterm/scripting/repl.py +527 -131
- nterm/scripting/repl_interactive.py +356 -213
- nterm/scripting/ssh_connection.py +632 -0
- nterm/scripting/test_api_repl.py +290 -0
- {ntermqt-0.1.7.dist-info → ntermqt-0.1.9.dist-info}/METADATA +89 -29
- {ntermqt-0.1.7.dist-info → ntermqt-0.1.9.dist-info}/RECORD +14 -9
- {ntermqt-0.1.7.dist-info → ntermqt-0.1.9.dist-info}/WHEEL +0 -0
- {ntermqt-0.1.7.dist-info → ntermqt-0.1.9.dist-info}/entry_points.txt +0 -0
- {ntermqt-0.1.7.dist-info → ntermqt-0.1.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test script to verify new API backend works with REPL.
|
|
4
|
+
|
|
5
|
+
Run from nterm project directory:
|
|
6
|
+
python -m nterm.scripting.test_api_repl
|
|
7
|
+
|
|
8
|
+
Or in IPython:
|
|
9
|
+
%run nterm/scripting/test_api_repl.py
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import sys
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def test_api_imports():
|
|
17
|
+
"""Test that all new API components import correctly."""
|
|
18
|
+
print("=" * 60)
|
|
19
|
+
print("Testing API Imports")
|
|
20
|
+
print("=" * 60)
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from nterm.scripting.api import NTermAPI, get_api
|
|
24
|
+
print("✓ NTermAPI imported")
|
|
25
|
+
except ImportError as e:
|
|
26
|
+
print(f"✗ NTermAPI import failed: {e}")
|
|
27
|
+
return False
|
|
28
|
+
|
|
29
|
+
try:
|
|
30
|
+
from nterm.scripting.models import ActiveSession, CommandResult, DeviceInfo, CredentialInfo
|
|
31
|
+
print("✓ Models imported")
|
|
32
|
+
except ImportError as e:
|
|
33
|
+
print(f"✗ Models import failed: {e}")
|
|
34
|
+
return False
|
|
35
|
+
|
|
36
|
+
try:
|
|
37
|
+
from nterm.scripting.platform_data import PLATFORM_COMMANDS, PLATFORM_PATTERNS
|
|
38
|
+
print("✓ Platform data imported")
|
|
39
|
+
print(f" - {len(PLATFORM_PATTERNS)} platforms defined")
|
|
40
|
+
print(f" - {len(list(PLATFORM_COMMANDS.get('cisco_ios', {}).keys()))} command types for cisco_ios")
|
|
41
|
+
except ImportError as e:
|
|
42
|
+
print(f"✗ Platform data import failed: {e}")
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
from nterm.scripting.platform_utils import (
|
|
47
|
+
detect_platform,
|
|
48
|
+
get_platform_command,
|
|
49
|
+
extract_version_info,
|
|
50
|
+
extract_field,
|
|
51
|
+
)
|
|
52
|
+
print("✓ Platform utils imported")
|
|
53
|
+
except ImportError as e:
|
|
54
|
+
print(f"✗ Platform utils import failed: {e}")
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
from nterm.scripting.ssh_connection import (
|
|
59
|
+
connect_ssh,
|
|
60
|
+
send_command,
|
|
61
|
+
wait_for_prompt,
|
|
62
|
+
filter_ansi_sequences,
|
|
63
|
+
PagingNotDisabledError,
|
|
64
|
+
)
|
|
65
|
+
print("✓ SSH connection imported")
|
|
66
|
+
except ImportError as e:
|
|
67
|
+
print(f"✗ SSH connection import failed: {e}")
|
|
68
|
+
return False
|
|
69
|
+
|
|
70
|
+
print()
|
|
71
|
+
return True
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def test_platform_utils():
|
|
75
|
+
"""Test platform utility functions."""
|
|
76
|
+
print("=" * 60)
|
|
77
|
+
print("Testing Platform Utils")
|
|
78
|
+
print("=" * 60)
|
|
79
|
+
|
|
80
|
+
from nterm.scripting.platform_utils import (
|
|
81
|
+
detect_platform,
|
|
82
|
+
get_platform_command,
|
|
83
|
+
extract_field,
|
|
84
|
+
extract_version_info,
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# Test detect_platform
|
|
88
|
+
test_cases = [
|
|
89
|
+
("Cisco IOS Software, IOSv Software", "cisco_ios"),
|
|
90
|
+
("Arista vEOS", "arista_eos"),
|
|
91
|
+
("Cisco Nexus Operating System", "cisco_nxos"),
|
|
92
|
+
("JUNOS 20.4R1", "juniper_junos"),
|
|
93
|
+
("Unknown device", None),
|
|
94
|
+
]
|
|
95
|
+
|
|
96
|
+
print("\ndetect_platform():")
|
|
97
|
+
for version_output, expected in test_cases:
|
|
98
|
+
result = detect_platform(version_output)
|
|
99
|
+
status = "✓" if result == expected else "✗"
|
|
100
|
+
print(f" {status} '{version_output[:30]}...' -> {result} (expected: {expected})")
|
|
101
|
+
|
|
102
|
+
# Test get_platform_command
|
|
103
|
+
print("\nget_platform_command():")
|
|
104
|
+
|
|
105
|
+
cmd = get_platform_command('cisco_ios', 'config')
|
|
106
|
+
print(f" cisco_ios + config -> '{cmd}'")
|
|
107
|
+
|
|
108
|
+
cmd = get_platform_command('juniper_junos', 'config')
|
|
109
|
+
print(f" juniper_junos + config -> '{cmd}'")
|
|
110
|
+
|
|
111
|
+
cmd = get_platform_command('cisco_ios', 'interface_detail', name='Gi0/1')
|
|
112
|
+
print(f" cisco_ios + interface_detail(name='Gi0/1') -> '{cmd}'")
|
|
113
|
+
|
|
114
|
+
cmd = get_platform_command('arista_eos', 'neighbors')
|
|
115
|
+
print(f" arista_eos + neighbors -> '{cmd}'")
|
|
116
|
+
|
|
117
|
+
# Test extract_field
|
|
118
|
+
print("\nextract_field():")
|
|
119
|
+
test_data = {'VERSION': '15.2(4)M', 'HARDWARE': ['ISR4451', 'ISR4451-X']}
|
|
120
|
+
|
|
121
|
+
result = extract_field(test_data, ['version', 'VERSION', 'SOFTWARE'])
|
|
122
|
+
print(f" Extract version from {test_data}: '{result}'")
|
|
123
|
+
|
|
124
|
+
result = extract_field(test_data, ['HARDWARE', 'MODEL'], first_element=True)
|
|
125
|
+
print(f" Extract hardware (first): '{result}'")
|
|
126
|
+
|
|
127
|
+
result = extract_field(test_data, ['HARDWARE', 'MODEL'], first_element=False)
|
|
128
|
+
print(f" Extract hardware (list): '{result}'")
|
|
129
|
+
|
|
130
|
+
# Test extract_version_info
|
|
131
|
+
print("\nextract_version_info():")
|
|
132
|
+
parsed_data = [{'VERSION': '15.2', 'HARDWARE': 'C3850', 'SERIAL': 'FCW1234'}]
|
|
133
|
+
info = extract_version_info(parsed_data, 'cisco_ios')
|
|
134
|
+
print(f" Extracted: {info}")
|
|
135
|
+
|
|
136
|
+
print()
|
|
137
|
+
return True
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_ansi_filtering():
|
|
141
|
+
"""Test ANSI sequence filtering."""
|
|
142
|
+
print("=" * 60)
|
|
143
|
+
print("Testing ANSI Filtering")
|
|
144
|
+
print("=" * 60)
|
|
145
|
+
|
|
146
|
+
from nterm.scripting.ssh_connection import filter_ansi_sequences
|
|
147
|
+
|
|
148
|
+
test_cases = [
|
|
149
|
+
# (input, expected_output_contains)
|
|
150
|
+
("\x1b[24;1Hdevice#", "device#"),
|
|
151
|
+
("\x1b[0m\x1b[2Kshow version\x1b[0m", "show version"),
|
|
152
|
+
("\x1b[?25hrouter>", "router>"),
|
|
153
|
+
("clean text", "clean text"),
|
|
154
|
+
("\x07bell\x07", "bell"),
|
|
155
|
+
]
|
|
156
|
+
|
|
157
|
+
for raw, expected_contains in test_cases:
|
|
158
|
+
filtered = filter_ansi_sequences(raw)
|
|
159
|
+
status = "✓" if expected_contains in filtered else "✗"
|
|
160
|
+
print(f" {status} Input: {repr(raw)[:40]}")
|
|
161
|
+
print(f" Output: '{filtered}'")
|
|
162
|
+
|
|
163
|
+
print()
|
|
164
|
+
return True
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def test_api_initialization():
|
|
168
|
+
"""Test API can be initialized."""
|
|
169
|
+
print("=" * 60)
|
|
170
|
+
print("Testing API Initialization")
|
|
171
|
+
print("=" * 60)
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
from nterm.scripting.api import NTermAPI
|
|
175
|
+
|
|
176
|
+
# This will fail if tfsm_templates.db doesn't exist
|
|
177
|
+
# That's expected in some environments
|
|
178
|
+
api = NTermAPI()
|
|
179
|
+
print(f"✓ API initialized: {api}")
|
|
180
|
+
|
|
181
|
+
# Test status
|
|
182
|
+
status = api.status()
|
|
183
|
+
print(f" Devices: {status['devices']}")
|
|
184
|
+
print(f" Folders: {status['folders']}")
|
|
185
|
+
print(f" Vault: {'unlocked' if status['vault_unlocked'] else 'locked'}")
|
|
186
|
+
print(f" Parser DB: {status['parser_db']}")
|
|
187
|
+
|
|
188
|
+
# Test new methods exist
|
|
189
|
+
print("\nNew API methods:")
|
|
190
|
+
print(f" ✓ session() context manager: {hasattr(api, 'session')}")
|
|
191
|
+
print(f" ✓ send_first(): {hasattr(api, 'send_first')}")
|
|
192
|
+
print(f" ✓ send_platform_command(): {hasattr(api, 'send_platform_command')}")
|
|
193
|
+
print(f" ✓ disconnect_all(): {hasattr(api, 'disconnect_all')}")
|
|
194
|
+
|
|
195
|
+
# Test active_sessions returns correct type
|
|
196
|
+
sessions = api.active_sessions()
|
|
197
|
+
print(f" ✓ active_sessions() returns list: {isinstance(sessions, list)}")
|
|
198
|
+
|
|
199
|
+
print()
|
|
200
|
+
return True
|
|
201
|
+
|
|
202
|
+
except Exception as e:
|
|
203
|
+
print(f"✗ API initialization failed: {e}")
|
|
204
|
+
print(" (This is expected if tfsm_templates.db is not present)")
|
|
205
|
+
print()
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def test_repl_imports():
|
|
210
|
+
"""Test REPL imports."""
|
|
211
|
+
print("=" * 60)
|
|
212
|
+
print("Testing REPL Imports")
|
|
213
|
+
print("=" * 60)
|
|
214
|
+
|
|
215
|
+
try:
|
|
216
|
+
from nterm.scripting.repl import NTermREPL, REPLPolicy, REPLState
|
|
217
|
+
print("✓ REPL classes imported")
|
|
218
|
+
except ImportError as e:
|
|
219
|
+
print(f"✗ REPL import failed: {e}")
|
|
220
|
+
return False
|
|
221
|
+
|
|
222
|
+
try:
|
|
223
|
+
from nterm.scripting.repl_interactive import start_repl
|
|
224
|
+
print("✓ Interactive REPL imported")
|
|
225
|
+
except ImportError as e:
|
|
226
|
+
print(f"✗ Interactive REPL import failed: {e}")
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
# Test policy
|
|
230
|
+
policy = REPLPolicy(mode="read_only")
|
|
231
|
+
print(f"\nPolicy tests (mode={policy.mode}):")
|
|
232
|
+
|
|
233
|
+
test_commands = [
|
|
234
|
+
("show version", True),
|
|
235
|
+
("show interfaces", True),
|
|
236
|
+
("configure terminal", False),
|
|
237
|
+
("write memory", False),
|
|
238
|
+
("reload", False),
|
|
239
|
+
("copy running-config startup-config", False),
|
|
240
|
+
]
|
|
241
|
+
|
|
242
|
+
for cmd, expected in test_commands:
|
|
243
|
+
allowed = policy.is_allowed(cmd)
|
|
244
|
+
status = "✓" if allowed == expected else "✗"
|
|
245
|
+
print(
|
|
246
|
+
f" {status} '{cmd}' -> {'allowed' if allowed else 'blocked'} (expected: {'allowed' if expected else 'blocked'})")
|
|
247
|
+
|
|
248
|
+
print()
|
|
249
|
+
return True
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def run_all_tests():
|
|
253
|
+
"""Run all tests."""
|
|
254
|
+
print("\n" + "=" * 60)
|
|
255
|
+
print("nterm API Backend Tests")
|
|
256
|
+
print("=" * 60 + "\n")
|
|
257
|
+
|
|
258
|
+
results = []
|
|
259
|
+
|
|
260
|
+
results.append(("Imports", test_api_imports()))
|
|
261
|
+
results.append(("Platform Utils", test_platform_utils()))
|
|
262
|
+
results.append(("ANSI Filtering", test_ansi_filtering()))
|
|
263
|
+
results.append(("API Init", test_api_initialization()))
|
|
264
|
+
results.append(("REPL", test_repl_imports()))
|
|
265
|
+
|
|
266
|
+
print("=" * 60)
|
|
267
|
+
print("Test Summary")
|
|
268
|
+
print("=" * 60)
|
|
269
|
+
|
|
270
|
+
passed = 0
|
|
271
|
+
failed = 0
|
|
272
|
+
for name, result in results:
|
|
273
|
+
status = "✓ PASS" if result else "✗ FAIL"
|
|
274
|
+
print(f" {status}: {name}")
|
|
275
|
+
if result:
|
|
276
|
+
passed += 1
|
|
277
|
+
else:
|
|
278
|
+
failed += 1
|
|
279
|
+
|
|
280
|
+
print()
|
|
281
|
+
print(f"Passed: {passed}/{len(results)}")
|
|
282
|
+
print(f"Failed: {failed}/{len(results)}")
|
|
283
|
+
print()
|
|
284
|
+
|
|
285
|
+
return failed == 0
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
if __name__ == "__main__":
|
|
289
|
+
success = run_all_tests()
|
|
290
|
+
sys.exit(0 if success else 1)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ntermqt
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.9
|
|
4
4
|
Summary: Modern SSH terminal widget for PyQt6 with credential vault and jump host support
|
|
5
5
|
Author: Scott Peterman
|
|
6
6
|
License: GPL-3.0
|
|
@@ -85,10 +85,11 @@ Built for managing hundreds of devices through bastion hosts with hardware secur
|
|
|
85
85
|
- Cross-platform keychain: macOS Keychain, Windows Credential Locker, Linux Secret Service
|
|
86
86
|
- Full PyQt6 management UI
|
|
87
87
|
|
|
88
|
-
**Scripting API**
|
|
88
|
+
**Scripting API**
|
|
89
89
|
- Query device inventory and credentials programmatically
|
|
90
90
|
- Built-in IPython console with API pre-loaded
|
|
91
|
-
-
|
|
91
|
+
- **Platform-aware commands** - one API, correct syntax everywhere
|
|
92
|
+
- **Interactive REPL** with quick commands and structured output
|
|
92
93
|
- Foundation for MCP tools and agentic workflows
|
|
93
94
|
|
|
94
95
|
---
|
|
@@ -111,7 +112,7 @@ nterm includes a built-in development console accessible via **Dev → IPython**
|
|
|
111
112
|
|
|
112
113
|

|
|
113
114
|
|
|
114
|
-

|
|
115
116
|
|
|
116
117
|
The IPython console runs in the same Python environment as nterm, with the scripting API pre-loaded. Query your device inventory, inspect credentials, and prototype automation workflows without leaving the app.
|
|
117
118
|
|
|
@@ -192,9 +193,9 @@ python -m nterm
|
|
|
192
193
|
|
|
193
194
|
---
|
|
194
195
|
|
|
195
|
-
## Scripting API
|
|
196
|
+
## Scripting API
|
|
196
197
|
|
|
197
|
-
nterm includes a scripting API for programmatic access to your device inventory and
|
|
198
|
+
nterm includes a full scripting API for programmatic access to your device inventory, credential vault, and network devices. Use it from IPython, CLI, or Python scripts.
|
|
198
199
|
|
|
199
200
|
### IPython Console
|
|
200
201
|
|
|
@@ -204,49 +205,103 @@ Open **Dev → IPython → Open in Tab** to get an interactive console with the
|
|
|
204
205
|
api.devices() # List all saved devices
|
|
205
206
|
api.search("leaf") # Search by name/hostname
|
|
206
207
|
api.devices("eng-*") # Glob pattern filter
|
|
208
|
+
api.folders() # List all folders
|
|
207
209
|
|
|
208
210
|
api.unlock("vault-password") # Unlock credential vault
|
|
209
211
|
api.credentials() # List credentials (metadata only)
|
|
210
212
|
|
|
213
|
+
# Connect and execute commands
|
|
214
|
+
with api.session("usa-leaf-1") as s:
|
|
215
|
+
result = api.send(s, "show version")
|
|
216
|
+
print(result.parsed_data)
|
|
217
|
+
|
|
211
218
|
api.help() # Show all commands
|
|
212
219
|
```
|
|
213
220
|
|
|
214
|
-
###
|
|
221
|
+
### Interactive REPL
|
|
215
222
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
223
|
+
Start the REPL for interactive device exploration with platform-aware quick commands:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
api.repl()
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
nterm> :unlock
|
|
231
|
+
nterm> :connect usa-leaf-1
|
|
232
|
+
|
|
233
|
+
📊 usa-leaf-1> :version
|
|
234
|
+
──────────────────────────────────────────────────
|
|
235
|
+
Version: 15.2(4.0.55)E
|
|
236
|
+
Hardware: IOSv
|
|
237
|
+
Serial: 9J0PD0QB9W1
|
|
238
|
+
Uptime: 1 week, 4 days, 7 minutes
|
|
239
|
+
──────────────────────────────────────────────────
|
|
240
|
+
|
|
241
|
+
📊 usa-leaf-1> :neighbors
|
|
242
|
+
Local Interface Neighbor Remote Port
|
|
243
|
+
----------------------------------------------------------------
|
|
244
|
+
Gi0/0 usa-spine-2.lab.local Ethernet1
|
|
245
|
+
Gi0/1 usa-spine-1.lab.local Ethernet1
|
|
246
|
+
|
|
247
|
+
📊 usa-leaf-1> :interfaces
|
|
248
|
+
[Rich formatted interface table]
|
|
222
249
|
```
|
|
223
250
|
|
|
251
|
+
**Quick Commands:**
|
|
252
|
+
- `:version` - Structured version info
|
|
253
|
+
- `:config` - Running configuration
|
|
254
|
+
- `:interfaces` - Interface status
|
|
255
|
+
- `:neighbors` - CDP/LLDP neighbors (auto-detects)
|
|
256
|
+
- `:bgp` - BGP summary
|
|
257
|
+
- `:routes` - Routing table
|
|
258
|
+
|
|
224
259
|
### Python Scripts
|
|
225
260
|
|
|
226
261
|
```python
|
|
227
262
|
from nterm.scripting import NTermAPI
|
|
228
263
|
|
|
229
264
|
api = NTermAPI()
|
|
265
|
+
api.unlock("vault-password")
|
|
230
266
|
|
|
231
|
-
#
|
|
267
|
+
# Context manager for automatic cleanup
|
|
232
268
|
for device in api.devices("*spine*"):
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
269
|
+
with api.session(device.name) as s:
|
|
270
|
+
# Platform-aware commands - works on Cisco, Arista, Juniper
|
|
271
|
+
result = api.send_platform_command(s, 'version')
|
|
272
|
+
print(f"{device.name}: {result.parsed_data[0].get('VERSION')}")
|
|
273
|
+
|
|
274
|
+
# Try multiple commands until one works
|
|
275
|
+
with api.session("router1") as s:
|
|
276
|
+
result = api.send_first(s, [
|
|
277
|
+
"show cdp neighbors detail",
|
|
278
|
+
"show lldp neighbors detail",
|
|
279
|
+
])
|
|
239
280
|
```
|
|
240
281
|
|
|
241
|
-
###
|
|
282
|
+
### CLI
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
nterm-cli devices # List all devices
|
|
286
|
+
nterm-cli search leaf # Search devices
|
|
287
|
+
nterm-cli device eng-leaf-1 # Device details
|
|
288
|
+
nterm-cli credentials --unlock # List credentials
|
|
289
|
+
nterm-cli --json devices # JSON output for scripting
|
|
290
|
+
```
|
|
242
291
|
|
|
243
|
-
|
|
292
|
+
### Key Features
|
|
244
293
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
294
|
+
| Feature | Description |
|
|
295
|
+
|---------|-------------|
|
|
296
|
+
| **Context Manager** | `with api.session()` auto-disconnects |
|
|
297
|
+
| **Platform-Aware** | `send_platform_command()` picks correct syntax |
|
|
298
|
+
| **Fallback Commands** | `send_first()` tries alternatives |
|
|
299
|
+
| **Structured Output** | TextFSM parsing to List[Dict] |
|
|
300
|
+
| **ANSI Filtering** | Clean output, no escape sequences |
|
|
301
|
+
| **Paging Detection** | Raises error if paging not disabled |
|
|
248
302
|
|
|
249
|
-
See [scripting/
|
|
303
|
+
See [scripting/README_API_IPython.md](nterm/scripting/README_API_IPython.md) for full API documentation.
|
|
304
|
+
See [scripting/README_REPL.md](nterm/scripting/README_REPL.md) for REPL documentation.
|
|
250
305
|
|
|
251
306
|
---
|
|
252
307
|
|
|
@@ -436,9 +491,14 @@ nterm/
|
|
|
436
491
|
│ ├── resolver.py # Pattern-based resolution
|
|
437
492
|
│ └── manager_ui.py # PyQt6 credential manager
|
|
438
493
|
├── manager/ # Session tree, connection dialogs
|
|
439
|
-
└── scripting/ # API,
|
|
440
|
-
├── api.py
|
|
441
|
-
|
|
494
|
+
└── scripting/ # API, REPL, automation support
|
|
495
|
+
├── api.py # NTermAPI class
|
|
496
|
+
├── models.py # ActiveSession, CommandResult, DeviceInfo
|
|
497
|
+
├── platform_data.py # Platform commands and patterns
|
|
498
|
+
├── platform_utils.py # Platform detection, extraction helpers
|
|
499
|
+
├── ssh_connection.py # Low-level SSH with ANSI filtering
|
|
500
|
+
├── repl.py # NTermREPL command router
|
|
501
|
+
└── repl_interactive.py # Interactive REPL display
|
|
442
502
|
```
|
|
443
503
|
|
|
444
504
|
---
|
|
@@ -14,16 +14,21 @@ nterm/manager/models.py,sha256=cvC2HzCRadNG1EYsnZN4C9YS6uolHGcUGGZtt-wzGF4,12237
|
|
|
14
14
|
nterm/manager/settings.py,sha256=r6MTw_9r1Wl2UX_ALpXIuPbDvJ0D91Y8wRKq6Bfr_3g,9210
|
|
15
15
|
nterm/manager/tree.py,sha256=I78wSjkSuyM6903II-XNyPug9saMSODUNBCHCDrq4ls,22397
|
|
16
16
|
nterm/parser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
17
|
-
nterm/parser/api_help_dialog.py,sha256=
|
|
17
|
+
nterm/parser/api_help_dialog.py,sha256=pz7AYCMZ8o0dr4NezOK7Rl7e7mJvcZUndnrTrJv17lo,23990
|
|
18
18
|
nterm/parser/ntc_download_dialog.py,sha256=TGaMCxKBTIOhGNUoLEJLnD0uAnwYWdbHdb9PRZEY604,14151
|
|
19
19
|
nterm/parser/tfsm_engine.py,sha256=6p4wrNa9tQRuCmWgsR4E3rZTprpLmii5PNjoGpCQBCw,7954
|
|
20
20
|
nterm/parser/tfsm_fire.py,sha256=AHbN6p4HlgcYDjLWb67CF9YfMSTk-3aetMswmEZyRVc,9222
|
|
21
21
|
nterm/parser/tfsm_fire_tester.py,sha256=h2CAqTS6ZNHMUr4di2DBRHAWbBGiUTliOvm5jVG4ltI,79146
|
|
22
22
|
nterm/scripting/__init__.py,sha256=vxbODaXR0IPneja3BuDHmjsHzQg03tFWtHO4Rc6vCTk,1099
|
|
23
|
-
nterm/scripting/api.py,sha256=
|
|
23
|
+
nterm/scripting/api.py,sha256=nWuANeYyT8mI1OsP9g3Z2lZohrrCpAZVss6t9Ba5Avg,39011
|
|
24
24
|
nterm/scripting/cli.py,sha256=W2DK4ZnuutaArye_to7CBchg0ogClURxVbGsMdnj1y0,9187
|
|
25
|
-
nterm/scripting/
|
|
26
|
-
nterm/scripting/
|
|
25
|
+
nterm/scripting/models.py,sha256=zX90xtFYz0fqIPc0G8mRaoiZ1aRLm0koiHIvklUBflg,6858
|
|
26
|
+
nterm/scripting/platform_data.py,sha256=uCWBDS1HqmOdYNPojNlKBWLYhLiME9eoE0LWL-w6dkQ,10200
|
|
27
|
+
nterm/scripting/platform_utils.py,sha256=_vb1tMstlD9pQ4blD2keAkVbs9lkbFlTBEavI5oMd3Q,18478
|
|
28
|
+
nterm/scripting/repl.py,sha256=URcgs-c-bEYsw2JNCewEonNy1oLsGpzsBcq5xpYWseM,29152
|
|
29
|
+
nterm/scripting/repl_interactive.py,sha256=yQ-XjyELBCE5t4Gk3hBnO8eZCbCXquddLBqcQIKPhY8,17870
|
|
30
|
+
nterm/scripting/ssh_connection.py,sha256=p9EGPE3hgbceDVh7UdGz44cSi79Vl7g9Q4fKd-2T314,19270
|
|
31
|
+
nterm/scripting/test_api_repl.py,sha256=deeA_epPnBxgDGYMKcyXEWQOOpIXQNjDZL01FmOpKvs,8762
|
|
27
32
|
nterm/session/__init__.py,sha256=FkgHF1WPz78JBOWHSC7LLynG2NqoR6aanNTRlEzsO6I,1612
|
|
28
33
|
nterm/session/askpass_ssh.py,sha256=U-frmLBIXwE2L5ZCEtai91G1dVRSWKLCtxn88t_PqGs,14083
|
|
29
34
|
nterm/session/base.py,sha256=NNFt2uy-rTkwigrHcdnfREk_QZDxNe0CoP16C-7oIWs,2475
|
|
@@ -61,8 +66,8 @@ nterm/vault/manager_ui.py,sha256=qle-W40j6L_pOR0AaOCeyU8myizFTRkISNrloCn0H_Y,345
|
|
|
61
66
|
nterm/vault/profile.py,sha256=qM9TJf68RKdjtxo-sJehO7wS4iTi2G26BKbmlmHLA5M,6246
|
|
62
67
|
nterm/vault/resolver.py,sha256=GWB2YR9H1MH98RGQBKvitIsjWT_-wSMLuddZNz4wbns,7800
|
|
63
68
|
nterm/vault/store.py,sha256=_0Lfe0WKjm3uSAtxgn9qAPlpBOLCuq9SVgzqsE_qaGQ,21199
|
|
64
|
-
ntermqt-0.1.
|
|
65
|
-
ntermqt-0.1.
|
|
66
|
-
ntermqt-0.1.
|
|
67
|
-
ntermqt-0.1.
|
|
68
|
-
ntermqt-0.1.
|
|
69
|
+
ntermqt-0.1.9.dist-info/METADATA,sha256=ICYH7EjefVJLe_Hp-prpK8GPQE2TTqEaoX7-x2M0cOo,16040
|
|
70
|
+
ntermqt-0.1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
71
|
+
ntermqt-0.1.9.dist-info/entry_points.txt,sha256=Gunr-_3w-aSpfqoMuGKM2PJSCRo9hZ7K1BksUtp1yd8,130
|
|
72
|
+
ntermqt-0.1.9.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
|
|
73
|
+
ntermqt-0.1.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|