ntermqt 0.1.8__py3-none-any.whl → 0.1.10__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/scripting/repl.py CHANGED
@@ -102,6 +102,8 @@ class NTermREPL:
102
102
  :folders List folders
103
103
  :connect <device> Connect to device [--cred name] [--debug]
104
104
  :disconnect Disconnect current session
105
+ :disconnect_all Disconnect all sessions
106
+ :switch <device> Switch to another active session
105
107
  :sessions List all active sessions
106
108
  :policy [mode] Get/set policy (read_only|ops)
107
109
  :mode [raw|parsed] Get/set output mode
@@ -120,7 +122,7 @@ class NTermREPL:
120
122
  :neighbors Fetch CDP/LLDP neighbors (tries both)
121
123
  :bgp Fetch BGP summary
122
124
  :routes Fetch routing table
123
- :intf <name> Fetch specific interface details
125
+ :intf <n> Fetch specific interface details
124
126
 
125
127
  Raw Commands:
126
128
  (anything else) Runs as CLI on the connected session
@@ -232,9 +234,26 @@ class NTermREPL:
232
234
  if not self.state.api.vault_unlocked:
233
235
  return self._err("Vault is locked. Run :unlock first.")
234
236
 
235
- # Disconnect existing session if any
236
- if self.state.session:
237
- self._safe_disconnect()
237
+ # Check if already connected to this device
238
+ existing_sessions = self.state.api.active_sessions()
239
+ for sess in existing_sessions:
240
+ if sess.device_name == device:
241
+ # Already connected - just switch to it
242
+ self.state.session = sess
243
+ self.state.connected_device = sess.device_name
244
+ return self._ok({
245
+ "type": "switch",
246
+ "device": sess.device_name,
247
+ "hostname": sess.hostname,
248
+ "port": sess.port,
249
+ "platform": sess.platform,
250
+ "prompt": sess.prompt,
251
+ "message": "Already connected - switched to existing session",
252
+ })
253
+
254
+ # NOTE: We no longer disconnect the existing session!
255
+ # Old sessions stay active in the background.
256
+ # User can switch back with :switch or disconnect with :disconnect
238
257
 
239
258
  try:
240
259
  sess = self.state.api.connect(device, credential=cred, debug=debug)
@@ -255,8 +274,60 @@ class NTermREPL:
255
274
  if cmd == ":disconnect":
256
275
  if not self.state.session:
257
276
  return self._ok({"type": "disconnect", "message": "No active session"})
277
+
278
+ device_name = self.state.connected_device
258
279
  self._safe_disconnect()
259
- return self._ok({"type": "disconnect"})
280
+
281
+ # Try to switch to another active session if available
282
+ remaining = self.state.api.active_sessions()
283
+ if remaining:
284
+ self.state.session = remaining[0]
285
+ self.state.connected_device = remaining[0].device_name
286
+ return self._ok({
287
+ "type": "disconnect",
288
+ "disconnected": device_name,
289
+ "switched_to": self.state.connected_device,
290
+ "message": f"Disconnected {device_name}, switched to {self.state.connected_device}",
291
+ })
292
+
293
+ return self._ok({"type": "disconnect", "disconnected": device_name})
294
+
295
+ if cmd == ":disconnect_all":
296
+ count = self.state.api.disconnect_all()
297
+ self.state.session = None
298
+ self.state.connected_device = None
299
+ return self._ok({"type": "disconnect_all", "count": count})
300
+
301
+ if cmd == ":switch":
302
+ if len(parts) < 2:
303
+ # Show available sessions
304
+ sessions = self.state.api.active_sessions()
305
+ if not sessions:
306
+ return self._err("No active sessions. Use :connect <device> first.")
307
+
308
+ session_names = [s.device_name for s in sessions]
309
+ return self._err(f"Usage: :switch <device>\nActive sessions: {', '.join(session_names)}")
310
+
311
+ target_device = parts[1]
312
+
313
+ # Find the session
314
+ sessions = self.state.api.active_sessions()
315
+ for sess in sessions:
316
+ if sess.device_name == target_device:
317
+ self.state.session = sess
318
+ self.state.connected_device = sess.device_name
319
+ return self._ok({
320
+ "type": "switch",
321
+ "device": sess.device_name,
322
+ "hostname": sess.hostname,
323
+ "port": sess.port,
324
+ "platform": sess.platform,
325
+ "prompt": sess.prompt,
326
+ })
327
+
328
+ # Not found
329
+ session_names = [s.device_name for s in sessions]
330
+ return self._err(f"Session '{target_device}' not found.\nActive sessions: {', '.join(session_names)}")
260
331
 
261
332
  if cmd == ":sessions":
262
333
  sessions = self.state.api.active_sessions()
@@ -295,7 +366,7 @@ class NTermREPL:
295
366
  })
296
367
  mode = parts[1].lower()
297
368
  if mode not in ["raw", "parsed"]:
298
- return self._err("Mode must be 'raw' or 'parsed'")
369
+ return self._err("Mode must be raw or parsed")
299
370
  self.state.output_mode = mode
300
371
  return self._ok({"type": "mode", "mode": mode})
301
372
 
@@ -304,113 +375,87 @@ class NTermREPL:
304
375
  return self._ok({"type": "format", "format": self.state.output_format})
305
376
  fmt = parts[1].lower()
306
377
  if fmt not in ["text", "rich", "json"]:
307
- return self._err("Format must be 'text', 'rich', or 'json'")
378
+ return self._err("Format must be text, rich, or json")
308
379
  self.state.output_format = fmt
309
380
  return self._ok({"type": "format", "format": fmt})
310
381
 
311
382
  if cmd == ":set_hint":
312
383
  if len(parts) < 2:
313
384
  return self._err("Usage: :set_hint <platform> (e.g., cisco_ios, arista_eos)")
314
- platform = parts[1].lower()
315
- self.state.platform_hint = platform
316
- return self._ok({"type": "set_hint", "platform_hint": platform})
385
+ self.state.platform_hint = parts[1]
386
+ return self._ok({"type": "set_hint", "platform_hint": self.state.platform_hint})
317
387
 
318
388
  if cmd == ":clear_hint":
319
389
  self.state.platform_hint = None
320
390
  return self._ok({"type": "clear_hint"})
321
391
 
322
392
  if cmd == ":debug":
323
- if len(parts) >= 2:
324
- mode = parts[1].lower()
325
- if mode in ["on", "true", "1"]:
326
- self.state.debug_mode = True
327
- elif mode in ["off", "false", "0"]:
328
- self.state.debug_mode = False
329
- else:
330
- return self._err("Debug mode must be on or off")
331
- else:
332
- self.state.debug_mode = not self.state.debug_mode
393
+ if len(parts) < 2:
394
+ return self._ok({"type": "debug", "debug_mode": self.state.debug_mode})
395
+ val = parts[1].lower()
396
+ self.state.debug_mode = val in ["on", "true", "1", "yes"]
333
397
  return self._ok({"type": "debug", "debug_mode": self.state.debug_mode})
334
398
 
335
399
  if cmd == ":dbinfo":
336
- try:
337
- db_info = self.state.api.db_info()
338
- return self._ok({"type": "dbinfo", "db_info": db_info})
339
- except Exception as e:
340
- return self._err(f"Failed to get DB info: {e}")
400
+ info = self.state.api.db_info()
401
+ return self._ok({"type": "dbinfo", "db_info": info})
341
402
 
342
- # ===== Quick Commands (Platform-Aware) =====
403
+ # ===== Quick Commands =====
343
404
  if cmd == ":config":
344
- return self._quick_command('config', parse=False, timeout=120)
405
+ return self._quick_config()
345
406
 
346
407
  if cmd == ":version":
347
408
  return self._quick_version()
348
409
 
349
410
  if cmd == ":interfaces":
350
- return self._quick_command('interfaces_status', parse=True)
411
+ return self._quick_interfaces()
351
412
 
352
413
  if cmd == ":neighbors":
353
414
  return self._quick_neighbors()
354
415
 
355
416
  if cmd == ":bgp":
356
- return self._quick_command('bgp_summary', parse=True)
417
+ return self._quick_bgp()
357
418
 
358
419
  if cmd == ":routes":
359
- return self._quick_command('routing_table', parse=True, timeout=60)
420
+ return self._quick_routes()
360
421
 
361
422
  if cmd == ":intf":
362
423
  if len(parts) < 2:
363
- return self._err("Usage: :intf <interface_name> (e.g., :intf Gi0/1)")
364
- intf_name = parts[1]
365
- return self._quick_command('interface_detail', parse=True, name=intf_name)
424
+ return self._err("Usage: :intf <interface> (e.g., :intf Gi0/1)")
425
+ return self._quick_interface_detail(parts[1])
366
426
 
367
427
  return self._err(f"Unknown REPL command: {cmd}")
368
428
 
369
429
  # -----------------------
370
- # Quick Command Helpers
430
+ # Quick commands
371
431
  # -----------------------
372
432
 
373
- def _quick_command(
374
- self,
375
- command_type: str,
376
- parse: bool = True,
377
- timeout: int = 30,
378
- **kwargs
379
- ) -> Dict[str, Any]:
380
- """Execute a platform-aware command."""
433
+ def _quick_config(self) -> Dict[str, Any]:
434
+ """Fetch running configuration."""
381
435
  if not self.state.session:
382
436
  return self._err("Not connected. Use :connect <device>")
383
437
 
384
- platform = self.state.platform_hint or self.state.session.platform
385
- cmd = get_platform_command(platform, command_type, **kwargs)
386
-
387
- if not cmd:
388
- return self._err(f"Command '{command_type}' not available for platform '{platform}'")
389
-
390
438
  try:
391
439
  started = time.time()
392
- result = self.state.api.send(
440
+ result = self.state.api.send_platform_command(
393
441
  self.state.session,
394
- cmd,
395
- timeout=timeout,
396
- parse=parse,
397
- normalize=True,
442
+ 'config',
443
+ parse=False, # Config is typically not parsed
444
+ timeout=60,
398
445
  )
399
446
  elapsed = time.time() - started
400
447
 
448
+ if not result:
449
+ return self._err("Config command not available for this platform")
450
+
401
451
  payload = result.to_dict()
402
452
  payload["elapsed_seconds"] = round(elapsed, 3)
403
- payload["command_type"] = command_type
404
-
405
- # Truncate if needed
406
- raw = payload.get("raw_output", "")
407
- if len(raw) > self.state.policy.max_output_chars:
408
- payload["raw_output"] = raw[:self.state.policy.max_output_chars] + "\n...<truncated>..."
453
+ payload["command_type"] = "config"
409
454
 
410
- return self._ok({"type": "result", "result": payload})
455
+ return self._ok({"type": "config", "result": payload})
411
456
 
412
457
  except Exception as e:
413
- return self._err(f"Command failed: {e}")
458
+ return self._err(f"Config fetch failed: {e}")
414
459
 
415
460
  def _quick_version(self) -> Dict[str, Any]:
416
461
  """Fetch and extract version info."""
@@ -446,6 +491,33 @@ class NTermREPL:
446
491
  except Exception as e:
447
492
  return self._err(f"Version command failed: {e}")
448
493
 
494
+ def _quick_interfaces(self) -> Dict[str, Any]:
495
+ """Fetch interface status."""
496
+ if not self.state.session:
497
+ return self._err("Not connected. Use :connect <device>")
498
+
499
+ try:
500
+ started = time.time()
501
+ result = self.state.api.send_platform_command(
502
+ self.state.session,
503
+ 'interfaces_status',
504
+ parse=True,
505
+ timeout=30,
506
+ )
507
+ elapsed = time.time() - started
508
+
509
+ if not result:
510
+ return self._err("Interfaces command not available for this platform")
511
+
512
+ payload = result.to_dict()
513
+ payload["elapsed_seconds"] = round(elapsed, 3)
514
+ payload["command_type"] = "interfaces"
515
+
516
+ return self._ok({"type": "interfaces", "result": payload})
517
+
518
+ except Exception as e:
519
+ return self._err(f"Interfaces command failed: {e}")
520
+
449
521
  def _quick_neighbors(self) -> Dict[str, Any]:
450
522
  """Fetch CDP/LLDP neighbors with fallback."""
451
523
  if not self.state.session:
@@ -513,6 +585,89 @@ class NTermREPL:
513
585
  except Exception as e:
514
586
  return self._err(f"Neighbor discovery failed: {e}")
515
587
 
588
+ def _quick_bgp(self) -> Dict[str, Any]:
589
+ """Fetch BGP summary."""
590
+ if not self.state.session:
591
+ return self._err("Not connected. Use :connect <device>")
592
+
593
+ try:
594
+ started = time.time()
595
+ result = self.state.api.send_platform_command(
596
+ self.state.session,
597
+ 'bgp_summary',
598
+ parse=True,
599
+ timeout=30,
600
+ )
601
+ elapsed = time.time() - started
602
+
603
+ if not result:
604
+ return self._err("BGP command not available for this platform")
605
+
606
+ payload = result.to_dict()
607
+ payload["elapsed_seconds"] = round(elapsed, 3)
608
+ payload["command_type"] = "bgp"
609
+
610
+ return self._ok({"type": "bgp", "result": payload})
611
+
612
+ except Exception as e:
613
+ return self._err(f"BGP command failed: {e}")
614
+
615
+ def _quick_routes(self) -> Dict[str, Any]:
616
+ """Fetch routing table."""
617
+ if not self.state.session:
618
+ return self._err("Not connected. Use :connect <device>")
619
+
620
+ try:
621
+ started = time.time()
622
+ result = self.state.api.send_platform_command(
623
+ self.state.session,
624
+ 'routing_table',
625
+ parse=True,
626
+ timeout=30,
627
+ )
628
+ elapsed = time.time() - started
629
+
630
+ if not result:
631
+ return self._err("Routing command not available for this platform")
632
+
633
+ payload = result.to_dict()
634
+ payload["elapsed_seconds"] = round(elapsed, 3)
635
+ payload["command_type"] = "routes"
636
+
637
+ return self._ok({"type": "routes", "result": payload})
638
+
639
+ except Exception as e:
640
+ return self._err(f"Routing command failed: {e}")
641
+
642
+ def _quick_interface_detail(self, interface: str) -> Dict[str, Any]:
643
+ """Fetch specific interface details."""
644
+ if not self.state.session:
645
+ return self._err("Not connected. Use :connect <device>")
646
+
647
+ try:
648
+ started = time.time()
649
+ result = self.state.api.send_platform_command(
650
+ self.state.session,
651
+ 'interface_detail',
652
+ name=interface,
653
+ parse=True,
654
+ timeout=30,
655
+ )
656
+ elapsed = time.time() - started
657
+
658
+ if not result:
659
+ return self._err(f"Interface detail command not available for this platform")
660
+
661
+ payload = result.to_dict()
662
+ payload["elapsed_seconds"] = round(elapsed, 3)
663
+ payload["command_type"] = "interface_detail"
664
+ payload["interface"] = interface
665
+
666
+ return self._ok({"type": "interface_detail", "result": payload})
667
+
668
+ except Exception as e:
669
+ return self._err(f"Interface detail command failed: {e}")
670
+
516
671
  # -----------------------
517
672
  # CLI send path
518
673
  # -----------------------
@@ -568,6 +723,7 @@ class NTermREPL:
568
723
  # -----------------------
569
724
 
570
725
  def _safe_disconnect(self) -> None:
726
+ """Disconnect current session only (not all sessions)."""
571
727
  if self.state.session:
572
728
  try:
573
729
  self.state.api.disconnect(self.state.session)
@@ -601,6 +757,8 @@ Inventory:
601
757
  Sessions:
602
758
  :connect <device> Connect to device [--cred name] [--debug]
603
759
  :disconnect Disconnect current session
760
+ :disconnect_all Disconnect all sessions
761
+ :switch <device> Switch to another active session
604
762
  :sessions List all active sessions
605
763
 
606
764
  Quick Commands (platform-aware, auto-selects correct syntax):
@@ -610,7 +768,7 @@ Quick Commands (platform-aware, auto-selects correct syntax):
610
768
  :neighbors Fetch CDP/LLDP neighbors (tries both)
611
769
  :bgp Fetch BGP summary
612
770
  :routes Fetch routing table
613
- :intf <name> Fetch specific interface details
771
+ :intf <n> Fetch specific interface details
614
772
 
615
773
  Settings:
616
774
  :policy [mode] Get/set policy mode (read_only|ops)
@@ -628,15 +786,16 @@ Info:
628
786
  Raw Commands:
629
787
  (anything else) Sends as CLI command to connected device
630
788
 
631
- Examples:
632
- :unlock
633
- :devices *leaf*
634
- :connect usa-leaf-1
635
- :version
636
- :interfaces
637
- :neighbors
638
- show ip route
639
- :disconnect
789
+ Multi-Session Example:
790
+ :connect spine-1 # Connect to first device
791
+ show version # Run command on spine-1
792
+ :connect spine-2 # Connect to second (spine-1 stays active!)
793
+ show version # Run command on spine-2
794
+ :sessions # See both sessions
795
+ :switch spine-1 # Switch back to spine-1
796
+ show ip route # Run command on spine-1
797
+ :disconnect # Disconnect spine-1, auto-switch to spine-2
798
+ :disconnect_all # Disconnect all remaining sessions
640
799
  :exit
641
800
  """
642
801
 
@@ -200,9 +200,34 @@ def _display_result(repl: NTermREPL, result: Dict) -> None:
200
200
  print(f" Prompt: {data.get('prompt', '')}")
201
201
  return
202
202
 
203
+ if cmd_type == "switch":
204
+ msg = data.get('message', '')
205
+ if msg:
206
+ print(f"✓ {msg}")
207
+ else:
208
+ print(f"✓ Switched to {data['device']} ({data['hostname']}:{data['port']})")
209
+ print(f" Platform: {data.get('platform', 'unknown')}")
210
+ print(f" Prompt: {data.get('prompt', '')}")
211
+ return
212
+
203
213
  if cmd_type == "disconnect":
204
- msg = data.get("message", "Disconnected")
205
- print(f"✓ {msg}")
214
+ disconnected = data.get("disconnected")
215
+ switched_to = data.get("switched_to")
216
+ msg = data.get("message")
217
+
218
+ if msg:
219
+ print(f"✓ {msg}")
220
+ elif disconnected:
221
+ print(f"✓ Disconnected from {disconnected}")
222
+ if switched_to:
223
+ print(f" Switched to: {switched_to}")
224
+ else:
225
+ print("✓ Disconnected")
226
+ return
227
+
228
+ if cmd_type == "disconnect_all":
229
+ count = data.get("count", 0)
230
+ print(f"✓ Disconnected {count} session(s)")
206
231
  return
207
232
 
208
233
  if cmd_type == "sessions":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ntermqt
3
- Version: 0.1.8
3
+ Version: 0.1.10
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
@@ -112,7 +112,7 @@ nterm includes a built-in development console accessible via **Dev → IPython**
112
112
 
113
113
  ![IPython Console](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/ipython.png)
114
114
 
115
- ![IPython Console](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/repl.png)
115
+ ![IPython Console](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/repl_dark3.png)
116
116
 
117
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.
118
118
 
@@ -6,10 +6,11 @@ nterm/askpass/__init__.py,sha256=UpJBk0EOm0nkRwMVv7YdIB4v75ZJpSYmNsU_GlgzbUg,495
6
6
  nterm/askpass/server.py,sha256=5tvjYryyfu-n8Cw2KbucwaZfWiqYnFk-iBAVBI8FMfw,12873
7
7
  nterm/connection/__init__.py,sha256=2qQ9LGxUxmwem8deOD2WZVkeD6rIVlTlx5Zh2cUEmxY,261
8
8
  nterm/connection/profile.py,sha256=4RMgnRNKCc-dFGEIpmQc_bob5MtzxO04_PljP-qUGLs,9450
9
+ nterm/examples/basic_terminal.py,sha256=vbDI1xl-Radv6GYZ0yC6QUafQp_tSX2pWIf7tk58W8E,15256
9
10
  nterm/manager/__init__.py,sha256=_QIeTap5CTL3jdTS1Q16fAt-PrqcNPUVr9gtJ22f0ng,774
10
11
  nterm/manager/connect_dialog.py,sha256=yd8g_gYttT_UdflRxSfyss8OQTfrvKLUOMg4Kj8FPNo,11711
11
12
  nterm/manager/editor.py,sha256=Fn2YWHJ1EwPYrhKhsi4GTBYwRfCYsHsqgKkLY-LQ8JI,8469
12
- nterm/manager/io.py,sha256=R5ksWgpEz0VdVCokcgTN5G3PFgp5QYhjjt40OypSWkY,21687
13
+ nterm/manager/io.py,sha256=59ehTfnS1sAKEEEwMxujHuccV7rYSoRx4vfS1ExDqW4,32572
13
14
  nterm/manager/models.py,sha256=cvC2HzCRadNG1EYsnZN4C9YS6uolHGcUGGZtt-wzGF4,12237
14
15
  nterm/manager/settings.py,sha256=r6MTw_9r1Wl2UX_ALpXIuPbDvJ0D91Y8wRKq6Bfr_3g,9210
15
16
  nterm/manager/tree.py,sha256=I78wSjkSuyM6903II-XNyPug9saMSODUNBCHCDrq4ls,22397
@@ -20,13 +21,13 @@ nterm/parser/tfsm_engine.py,sha256=6p4wrNa9tQRuCmWgsR4E3rZTprpLmii5PNjoGpCQBCw,7
20
21
  nterm/parser/tfsm_fire.py,sha256=AHbN6p4HlgcYDjLWb67CF9YfMSTk-3aetMswmEZyRVc,9222
21
22
  nterm/parser/tfsm_fire_tester.py,sha256=h2CAqTS6ZNHMUr4di2DBRHAWbBGiUTliOvm5jVG4ltI,79146
22
23
  nterm/scripting/__init__.py,sha256=vxbODaXR0IPneja3BuDHmjsHzQg03tFWtHO4Rc6vCTk,1099
23
- nterm/scripting/api.py,sha256=2Q6p07pUVOzye15NHoHUNE0PY4anla4jUsnu87yym0s,32740
24
+ nterm/scripting/api.py,sha256=nWuANeYyT8mI1OsP9g3Z2lZohrrCpAZVss6t9Ba5Avg,39011
24
25
  nterm/scripting/cli.py,sha256=W2DK4ZnuutaArye_to7CBchg0ogClURxVbGsMdnj1y0,9187
25
26
  nterm/scripting/models.py,sha256=zX90xtFYz0fqIPc0G8mRaoiZ1aRLm0koiHIvklUBflg,6858
26
27
  nterm/scripting/platform_data.py,sha256=uCWBDS1HqmOdYNPojNlKBWLYhLiME9eoE0LWL-w6dkQ,10200
27
- nterm/scripting/platform_utils.py,sha256=7SrvZvrcoQwOFAIjzXVvbFH04bFW6nOXar5JU3YEbr8,9560
28
- nterm/scripting/repl.py,sha256=BUISW1FX7EDh-1AV5UFpn2DB20CIYq_SdiCHea_6Ku0,22738
29
- nterm/scripting/repl_interactive.py,sha256=qcHpubo9GBcz-EpUrR_nHbfSIqwIx-gDXdNJP7rZVbU,17045
28
+ nterm/scripting/platform_utils.py,sha256=_vb1tMstlD9pQ4blD2keAkVbs9lkbFlTBEavI5oMd3Q,18478
29
+ nterm/scripting/repl.py,sha256=URcgs-c-bEYsw2JNCewEonNy1oLsGpzsBcq5xpYWseM,29152
30
+ nterm/scripting/repl_interactive.py,sha256=yQ-XjyELBCE5t4Gk3hBnO8eZCbCXquddLBqcQIKPhY8,17870
30
31
  nterm/scripting/ssh_connection.py,sha256=p9EGPE3hgbceDVh7UdGz44cSi79Vl7g9Q4fKd-2T314,19270
31
32
  nterm/scripting/test_api_repl.py,sha256=deeA_epPnBxgDGYMKcyXEWQOOpIXQNjDZL01FmOpKvs,8762
32
33
  nterm/session/__init__.py,sha256=FkgHF1WPz78JBOWHSC7LLynG2NqoR6aanNTRlEzsO6I,1612
@@ -66,8 +67,8 @@ nterm/vault/manager_ui.py,sha256=qle-W40j6L_pOR0AaOCeyU8myizFTRkISNrloCn0H_Y,345
66
67
  nterm/vault/profile.py,sha256=qM9TJf68RKdjtxo-sJehO7wS4iTi2G26BKbmlmHLA5M,6246
67
68
  nterm/vault/resolver.py,sha256=GWB2YR9H1MH98RGQBKvitIsjWT_-wSMLuddZNz4wbns,7800
68
69
  nterm/vault/store.py,sha256=_0Lfe0WKjm3uSAtxgn9qAPlpBOLCuq9SVgzqsE_qaGQ,21199
69
- ntermqt-0.1.8.dist-info/METADATA,sha256=m9M46bSjV7s_trY8RfJMPodSxNLkAk1EQTY4RqqR2IY,16034
70
- ntermqt-0.1.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
71
- ntermqt-0.1.8.dist-info/entry_points.txt,sha256=Gunr-_3w-aSpfqoMuGKM2PJSCRo9hZ7K1BksUtp1yd8,130
72
- ntermqt-0.1.8.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
73
- ntermqt-0.1.8.dist-info/RECORD,,
70
+ ntermqt-0.1.10.dist-info/METADATA,sha256=Pa4Oytg8jq0W5pU0bmmJR9nryjKRwewy54qejJValjM,16041
71
+ ntermqt-0.1.10.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
72
+ ntermqt-0.1.10.dist-info/entry_points.txt,sha256=Gunr-_3w-aSpfqoMuGKM2PJSCRo9hZ7K1BksUtp1yd8,130
73
+ ntermqt-0.1.10.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
74
+ ntermqt-0.1.10.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.9.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5