machineconfig 5.29__py3-none-any.whl → 5.31__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.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

Files changed (50) hide show
  1. machineconfig/scripts/python/croshell_helpers/__init__.py +0 -0
  2. machineconfig/scripts/python/devops.py +13 -122
  3. machineconfig/scripts/python/devops_helpers/choose_pwsh_theme.ps1 +44 -0
  4. machineconfig/scripts/python/devops_helpers/cli_config.py +43 -0
  5. machineconfig/scripts/python/devops_helpers/cli_data.py +18 -0
  6. machineconfig/scripts/python/devops_helpers/cli_nw.py +39 -0
  7. machineconfig/scripts/python/{repos.py → devops_helpers/cli_repos.py} +43 -7
  8. machineconfig/scripts/python/devops_helpers/cli_self.py +41 -0
  9. machineconfig/scripts/python/devops_helpers/devops_status.py +118 -55
  10. machineconfig/scripts/python/devops_navigator.py +806 -0
  11. machineconfig/scripts/python/helpers/repo_sync_helpers.py +1 -1
  12. machineconfig/scripts/python/helpers_repos/__init__.py +0 -0
  13. machineconfig/scripts/python/helpers_repos/grource.py +2 -3
  14. machineconfig/scripts/python/{secure_repo.py → helpers_repos/secure_repo.py} +1 -1
  15. machineconfig/scripts/python/interactive.py +2 -2
  16. machineconfig/scripts/python/nw/__init__.py +0 -0
  17. machineconfig/scripts/python/sessions.py +1 -1
  18. machineconfig/scripts/python/sessions_helpers/__init__.py +0 -0
  19. machineconfig/settings/linters/.ruff.toml +1 -1
  20. machineconfig/settings/shells/pwsh/init.ps1 +1 -1
  21. machineconfig/setup_windows/uv.ps1 +1 -1
  22. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +2 -3
  23. machineconfig/utils/code.py +13 -3
  24. machineconfig/utils/installer_utils/installer_class.py +3 -5
  25. {machineconfig-5.29.dist-info → machineconfig-5.31.dist-info}/METADATA +2 -1
  26. {machineconfig-5.29.dist-info → machineconfig-5.31.dist-info}/RECORD +45 -40
  27. {machineconfig-5.29.dist-info → machineconfig-5.31.dist-info}/entry_points.txt +1 -0
  28. machineconfig/scripts/python/gh_models.py +0 -104
  29. machineconfig/scripts/python/snapshot.py +0 -25
  30. machineconfig/scripts/python/start_terminals.py +0 -121
  31. machineconfig/scripts/windows/choose_wezterm_theme.ps1 +0 -1
  32. machineconfig/scripts/windows/wifi_conn.ps1 +0 -2
  33. /machineconfig/scripts/python/{pomodoro.py → croshell_helpers/pomodoro.py} +0 -0
  34. /machineconfig/scripts/python/{scheduler.py → croshell_helpers/scheduler.py} +0 -0
  35. /machineconfig/scripts/python/{start_slidev.py → croshell_helpers/start_slidev.py} +0 -0
  36. /machineconfig/scripts/python/{viewer.py → croshell_helpers/viewer.py} +0 -0
  37. /machineconfig/scripts/python/{viewer_template.py → croshell_helpers/viewer_template.py} +0 -0
  38. /machineconfig/scripts/python/{choose_wezterm_theme.py → devops_helpers/choose_wezterm_theme.py} +0 -0
  39. /machineconfig/scripts/python/{dotfile.py → devops_helpers/cli_config_dotfile.py} +0 -0
  40. /machineconfig/scripts/python/{share_terminal.py → devops_helpers/cli_terminal.py} +0 -0
  41. /machineconfig/scripts/python/{cloud_repo_sync.py → helpers_repos/cloud_repo_sync.py} +0 -0
  42. /machineconfig/scripts/python/{mount_nfs.py → nw/mount_nfs.py} +0 -0
  43. /machineconfig/scripts/python/{mount_nw_drive.py → nw/mount_nw_drive.py} +0 -0
  44. /machineconfig/scripts/python/{mount_ssh.py → nw/mount_ssh.py} +0 -0
  45. /machineconfig/scripts/python/{onetimeshare.py → nw/onetimeshare.py} +0 -0
  46. /machineconfig/scripts/python/{wifi_conn.py → nw/wifi_conn.py} +0 -0
  47. /machineconfig/scripts/python/{wsl_windows_transfer.py → nw/wsl_windows_transfer.py} +0 -0
  48. /machineconfig/scripts/python/{sessions_multiprocess.py → sessions_helpers/sessions_multiprocess.py} +0 -0
  49. {machineconfig-5.29.dist-info → machineconfig-5.31.dist-info}/WHEEL +0 -0
  50. {machineconfig-5.29.dist-info → machineconfig-5.31.dist-info}/top_level.txt +0 -0
@@ -40,9 +40,10 @@ def _check_shell_profile_status() -> dict[str, Any]:
40
40
 
41
41
  try:
42
42
  profile_path = get_shell_profile_path()
43
- profile_exists = profile_path.exists()
44
- profile_content = profile_path.read_text(encoding="utf-8") if profile_exists else ""
45
-
43
+ if not profile_path.exists():
44
+ profile_path.parent.mkdir(parents=True, exist_ok=True)
45
+ profile_path.touch()
46
+ profile_content = profile_path.read_text(encoding="utf-8")
46
47
  system_name = platform.system()
47
48
  if system_name == "Windows":
48
49
  init_script = PathExtended(LIBRARY_ROOT).joinpath("settings/shells/pwsh/init.ps1")
@@ -60,14 +61,22 @@ def _check_shell_profile_status() -> dict[str, Any]:
60
61
 
61
62
  return {
62
63
  "profile_path": str(profile_path),
63
- "exists": profile_exists,
64
+ "exists": True,
64
65
  "configured": configured,
65
66
  "method": method,
66
67
  "init_script_exists": init_script.exists(),
67
68
  "init_script_copy_exists": init_script_copy.exists(),
68
69
  }
69
70
  except Exception as ex:
70
- return {"profile_path": "Error", "exists": False, "configured": False, "method": "error", "error": str(ex), "init_script_exists": False, "init_script_copy_exists": False}
71
+ return {
72
+ "profile_path": "Error",
73
+ "exists": False,
74
+ "configured": False,
75
+ "method": "error",
76
+ "error": str(ex),
77
+ "init_script_exists": False,
78
+ "init_script_copy_exists": False,
79
+ }
71
80
 
72
81
 
73
82
  def _check_machineconfig_repo() -> dict[str, Any]:
@@ -116,7 +125,16 @@ def _check_repos_status() -> dict[str, Any]:
116
125
  import git
117
126
 
118
127
  repo = git.Repo(str(repo_path))
119
- repos_info.append({"path": str(repo_path), "name": repo_path.name, "exists": True, "is_repo": True, "clean": not repo.is_dirty(untracked_files=True), "branch": repo.active_branch.name if not repo.head.is_detached else "DETACHED"})
128
+ repos_info.append(
129
+ {
130
+ "path": str(repo_path),
131
+ "name": repo_path.name,
132
+ "exists": True,
133
+ "is_repo": True,
134
+ "clean": not repo.is_dirty(untracked_files=True),
135
+ "branch": repo.active_branch.name if not repo.head.is_detached else "DETACHED",
136
+ }
137
+ )
120
138
  except Exception:
121
139
  repos_info.append({"path": str(repo_path), "name": repo_path.name, "exists": True, "is_repo": False})
122
140
 
@@ -134,7 +152,15 @@ def _check_ssh_status() -> dict[str, Any]:
134
152
  keys = []
135
153
  for pub_key in ssh_dir.glob("*.pub"):
136
154
  private_key = pub_key.with_suffix("")
137
- keys.append({"name": pub_key.stem, "public_exists": True, "private_exists": private_key.exists(), "public_path": str(pub_key), "private_path": str(private_key)})
155
+ keys.append(
156
+ {
157
+ "name": pub_key.stem,
158
+ "public_exists": True,
159
+ "private_exists": private_key.exists(),
160
+ "public_path": str(pub_key),
161
+ "private_path": str(private_key),
162
+ }
163
+ )
138
164
 
139
165
  config_file = ssh_dir.joinpath("config")
140
166
  authorized_keys = ssh_dir.joinpath("authorized_keys")
@@ -187,13 +213,21 @@ def _check_config_files_status() -> dict[str, Any]:
187
213
  "private_configs": private_configs,
188
214
  }
189
215
  except Exception as ex:
190
- return {"public_count": 0, "public_linked": 0, "private_count": 0, "private_linked": 0, "error": str(ex), "public_configs": [], "private_configs": []}
216
+ return {
217
+ "public_count": 0,
218
+ "public_linked": 0,
219
+ "private_count": 0,
220
+ "private_linked": 0,
221
+ "error": str(ex),
222
+ "public_configs": [],
223
+ "private_configs": [],
224
+ }
191
225
 
192
226
 
193
227
  def _check_important_tools() -> dict[str, dict[str, bool]]:
194
228
  """Check if important CLI tools are installed, organized by groups."""
195
229
  from machineconfig.jobs.installer.package_groups import PACKAGE_GROUP2NAMES
196
-
230
+
197
231
  group_status = {}
198
232
  for group_name, tools in PACKAGE_GROUP2NAMES.items():
199
233
  tool_status = {}
@@ -257,25 +291,33 @@ def _display_shell_status(status: dict[str, Any]) -> None:
257
291
  return
258
292
 
259
293
  from rich.columns import Columns
260
-
294
+
261
295
  left_table = Table(show_header=False, box=None, padding=(0, 1))
262
296
  left_table.add_column("Item", style="cyan", no_wrap=True)
263
297
  left_table.add_column("Status")
264
-
265
- left_table.add_row("📄 Profile", status['profile_path'])
266
- left_table.add_row(f"{'✅' if status['exists'] else '❌'} Exists", str(status['exists']))
267
- left_table.add_row(f"{'✅' if status['configured'] else '❌'} Configured", str(status['configured']))
268
-
298
+
299
+ left_table.add_row("📄 Profile", status["profile_path"])
300
+ left_table.add_row(f"{'✅' if status['exists'] else '❌'} Exists", str(status["exists"]))
301
+ left_table.add_row(f"{'✅' if status['configured'] else '❌'} Configured", str(status["configured"]))
302
+
269
303
  right_table = Table(show_header=False, box=None, padding=(0, 1))
270
304
  right_table.add_column("Item", style="cyan", no_wrap=True)
271
305
  right_table.add_column("Status")
272
-
273
- right_table.add_row("🔧 Method", status['method'])
274
- right_table.add_row(f"{'✅' if status['init_script_exists'] else '❌'} Init (source)", str(status['init_script_exists']))
275
- right_table.add_row(f"{'✅' if status['init_script_copy_exists'] else '❌'} Init (copy)", str(status['init_script_copy_exists']))
306
+
307
+ right_table.add_row("🔧 Method", status["method"])
308
+ right_table.add_row(f"{'✅' if status['init_script_exists'] else '❌'} Init (source)", str(status["init_script_exists"]))
309
+ right_table.add_row(f"{'✅' if status['init_script_copy_exists'] else '❌'} Init (copy)", str(status["init_script_copy_exists"]))
276
310
 
277
311
  border_style = "green" if status["configured"] else "yellow"
278
- console.print(Panel(Columns([left_table, right_table], equal=True, expand=True), title="Shell Profile", border_style=border_style, padding=(1, 2), expand=False))
312
+ console.print(
313
+ Panel(
314
+ Columns([left_table, right_table], equal=True, expand=True),
315
+ title="Shell Profile",
316
+ border_style=border_style,
317
+ padding=(1, 2),
318
+ expand=False,
319
+ )
320
+ )
279
321
 
280
322
 
281
323
  def _display_machineconfig_repo(info: dict[str, Any]) -> None:
@@ -283,22 +325,38 @@ def _display_machineconfig_repo(info: dict[str, Any]) -> None:
283
325
  console.rule("[bold magenta]📦 Machineconfig Repository[/bold magenta]")
284
326
 
285
327
  if not info["exists"]:
286
- console.print(Panel("❌ Machineconfig repository not found at ~/code/machineconfig", title="Repository Status", border_style="red", padding=(1, 2), expand=False))
328
+ console.print(
329
+ Panel(
330
+ "❌ Machineconfig repository not found at ~/code/machineconfig",
331
+ title="Repository Status",
332
+ border_style="red",
333
+ padding=(1, 2),
334
+ expand=False,
335
+ )
336
+ )
287
337
  return
288
338
 
289
339
  if not info["is_repo"]:
290
- console.print(Panel(f"❌ Directory exists but is not a git repository\n{info.get('error', 'Unknown error')}", title="Repository Status", border_style="red", padding=(1, 2), expand=False))
340
+ console.print(
341
+ Panel(
342
+ f"❌ Directory exists but is not a git repository\n{info.get('error', 'Unknown error')}",
343
+ title="Repository Status",
344
+ border_style="red",
345
+ padding=(1, 2),
346
+ expand=False,
347
+ )
348
+ )
291
349
  return
292
350
 
293
351
  table = Table(show_header=False, box=None, padding=(0, 1), expand=False)
294
352
  table.add_column("Property", style="cyan", no_wrap=True)
295
353
  table.add_column("Value", style="white")
296
-
297
- table.add_row("📁 Path", info['path'])
298
- table.add_row("🌿 Branch", info['branch'])
299
- table.add_row("🔖 Commit", info['commit'])
300
- table.add_row(f"{'✅' if info['clean'] else '⚠️'} Status", 'Clean' if info['clean'] else 'Uncommitted changes')
301
- table.add_row("📡 Remotes", ', '.join(info['remotes']) if info['remotes'] else 'None')
354
+
355
+ table.add_row("📁 Path", info["path"])
356
+ table.add_row("🌿 Branch", info["branch"])
357
+ table.add_row("🔖 Commit", info["commit"])
358
+ table.add_row(f"{'✅' if info['clean'] else '⚠️'} Status", "Clean" if info["clean"] else "Uncommitted changes")
359
+ table.add_row("📡 Remotes", ", ".join(info["remotes"]) if info["remotes"] else "None")
302
360
 
303
361
  border_style = "green" if info["clean"] else "yellow"
304
362
  console.print(Panel(table, title="Machineconfig Repository", border_style=border_style, padding=(1, 2), expand=False))
@@ -344,15 +402,15 @@ def _display_ssh_status(status: dict[str, Any]) -> None:
344
402
  return
345
403
 
346
404
  from rich.columns import Columns
347
-
405
+
348
406
  config_table = Table(show_header=False, box=None, padding=(0, 1))
349
407
  config_table.add_column("Item", style="cyan", no_wrap=True)
350
408
  config_table.add_column("Status")
351
-
352
- config_table.add_row("📁 Directory", status['ssh_dir_path'])
353
- config_table.add_row(f"{'✅' if status['config_exists'] else '❌'} Config", str(status['config_exists']))
354
- config_table.add_row(f"{'✅' if status['authorized_keys_exists'] else '❌'} Auth Keys", str(status['authorized_keys_exists']))
355
- config_table.add_row(f"{'✅' if status['known_hosts_exists'] else '❌'} Known Hosts", str(status['known_hosts_exists']))
409
+
410
+ config_table.add_row("📁 Directory", status["ssh_dir_path"])
411
+ config_table.add_row(f"{'✅' if status['config_exists'] else '❌'} Config", str(status["config_exists"]))
412
+ config_table.add_row(f"{'✅' if status['authorized_keys_exists'] else '❌'} Auth Keys", str(status["authorized_keys_exists"]))
413
+ config_table.add_row(f"{'✅' if status['known_hosts_exists'] else '❌'} Known Hosts", str(status["known_hosts_exists"]))
356
414
 
357
415
  config_panel = Panel(config_table, title="SSH Config", border_style="yellow", padding=(1, 2), expand=False)
358
416
 
@@ -368,7 +426,7 @@ def _display_ssh_status(status: dict[str, Any]) -> None:
368
426
  keys_table.add_row(key["name"], pub_status, priv_status)
369
427
 
370
428
  keys_panel = Panel(keys_table, title=f"SSH Keys ({len(status['keys'])})", border_style="yellow", padding=(1, 2), expand=False)
371
-
429
+
372
430
  console.print(Columns([config_panel, keys_panel], equal=False, expand=True))
373
431
  else:
374
432
  console.print(config_panel)
@@ -379,7 +437,9 @@ def _display_config_files_status(status: dict[str, Any]) -> None:
379
437
  console.rule("[bold bright_blue]⚙️ Configuration Files[/bold bright_blue]")
380
438
 
381
439
  if "error" in status:
382
- console.print(Panel(f"❌ Error reading configuration: {status['error']}", title="Configuration Files", border_style="red", padding=(1, 2), expand=False))
440
+ console.print(
441
+ Panel(f"❌ Error reading configuration: {status['error']}", title="Configuration Files", border_style="red", padding=(1, 2), expand=False)
442
+ )
383
443
  return
384
444
 
385
445
  public_percentage = (status["public_linked"] / status["public_count"] * 100) if status["public_count"] > 0 else 0
@@ -390,9 +450,9 @@ def _display_config_files_status(status: dict[str, Any]) -> None:
390
450
  table.add_column("Linked", justify="right")
391
451
  table.add_column("Total", justify="right")
392
452
  table.add_column("Progress", justify="right")
393
-
394
- table.add_row("📂 Public", str(status['public_linked']), str(status['public_count']), f"{public_percentage:.0f}%")
395
- table.add_row("🔒 Private", str(status['private_linked']), str(status['private_count']), f"{private_percentage:.0f}%")
453
+
454
+ table.add_row("📂 Public", str(status["public_linked"]), str(status["public_count"]), f"{public_percentage:.0f}%")
455
+ table.add_row("🔒 Private", str(status["private_linked"]), str(status["private_count"]), f"{private_percentage:.0f}%")
396
456
 
397
457
  overall_linked = status["public_linked"] + status["private_linked"]
398
458
  overall_total = status["public_count"] + status["private_count"]
@@ -400,7 +460,9 @@ def _display_config_files_status(status: dict[str, Any]) -> None:
400
460
 
401
461
  border_style = "green" if overall_percentage > 80 else ("yellow" if overall_percentage > 50 else "red")
402
462
 
403
- console.print(Panel(table, title=f"Configuration Files ({overall_percentage:.0f}% configured)", border_style=border_style, padding=(1, 2), expand=False))
463
+ console.print(
464
+ Panel(table, title=f"Configuration Files ({overall_percentage:.0f}% configured)", border_style=border_style, padding=(1, 2), expand=False)
465
+ )
404
466
 
405
467
 
406
468
  def _display_tools_status(grouped_tools: dict[str, dict[str, bool]]) -> None:
@@ -408,60 +470,61 @@ def _display_tools_status(grouped_tools: dict[str, dict[str, bool]]) -> None:
408
470
  console.rule("[bold bright_magenta]🛠️ Important Tools[/bold bright_magenta]")
409
471
 
410
472
  from rich.columns import Columns
411
-
473
+
412
474
  all_group_panels = []
413
475
  total_installed = 0
414
476
  total_tools = 0
415
-
477
+
416
478
  for group_name, tools in grouped_tools.items():
417
479
  sorted_tools = sorted(tools.keys())
418
480
  installed = [tool for tool, status in tools.items() if status]
419
481
  total_installed += len(installed)
420
482
  total_tools += len(tools)
421
-
483
+
422
484
  num_columns = 8
423
485
  tools_per_column = (len(sorted_tools) + num_columns - 1) // num_columns
424
-
486
+
425
487
  tables = []
426
488
  for col_idx in range(num_columns):
427
489
  table = Table(show_header=False, box=None, padding=(0, 0), collapse_padding=True)
428
490
  table.add_column("Tool", style="cyan", no_wrap=True, width=None)
429
491
  table.add_column("", justify="center", width=2, no_wrap=True)
430
-
492
+
431
493
  start_idx = col_idx * tools_per_column
432
494
  end_idx = min(start_idx + tools_per_column, len(sorted_tools))
433
-
495
+
434
496
  for i in range(start_idx, end_idx):
435
497
  tool = sorted_tools[i]
436
498
  status_icon = "✅" if tools[tool] else "❌"
437
499
  table.add_row(tool, status_icon)
438
-
500
+
439
501
  if start_idx < len(sorted_tools):
440
502
  tables.append(table)
441
503
 
442
504
  installed_percentage = (len(installed) / len(tools) * 100) if tools else 0
443
505
  border_style = "green" if installed_percentage > 80 else ("yellow" if installed_percentage > 50 else "red")
444
-
506
+
445
507
  group_display_name = group_name.replace("_", " ").title()
446
508
  group_panel = Panel(
447
509
  Columns(tables, equal=False, expand=False, padding=(0, 1)),
448
510
  title=f"{group_display_name} ({len(installed)}/{len(tools)})",
449
511
  border_style=border_style,
450
512
  padding=(0, 1),
451
- expand=False
513
+ expand=False,
452
514
  )
453
515
  all_group_panels.append(group_panel)
454
-
516
+
455
517
  overall_percentage = (total_installed / total_tools * 100) if total_tools else 0
456
518
  master_border_style = "green" if overall_percentage > 80 else ("yellow" if overall_percentage > 50 else "red")
457
-
519
+
458
520
  from rich.console import Group
521
+
459
522
  master_panel = Panel(
460
523
  Group(*all_group_panels),
461
524
  title=f"🛠️ Tools Overview ({total_installed}/{total_tools} installed - {overall_percentage:.0f}%)",
462
525
  border_style=master_border_style,
463
526
  padding=(1, 2),
464
- expand=False
527
+ expand=False,
465
528
  )
466
529
  console.print(master_panel)
467
530
 
@@ -473,9 +536,9 @@ def _display_backup_status(status: dict[str, Any]) -> None:
473
536
  table = Table(show_header=False, box=None, padding=(0, 1), expand=False)
474
537
  table.add_column("Property", style="cyan", no_wrap=True)
475
538
  table.add_column("Value", style="white")
476
-
477
- table.add_row("🌥️ Cloud Config", status['cloud_config'])
478
- table.add_row("📦 Backup Items", str(status['backup_items_count']))
539
+
540
+ table.add_row("🌥️ Cloud Config", status["cloud_config"])
541
+ table.add_row("📦 Backup Items", str(status["backup_items_count"]))
479
542
 
480
543
  border_style = "green" if status["cloud_config"] != "Not configured" else "yellow"
481
544