machineconfig 8.45__py3-none-any.whl → 8.50__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 (32) hide show
  1. machineconfig/jobs/installer/python_scripts/sysabc.py +1 -1
  2. machineconfig/jobs/scripts/powershell_scripts/mount_ssh.ps1 +1 -1
  3. machineconfig/profile/create_links_export.py +36 -20
  4. machineconfig/profile/mapper_dotfiles.toml +31 -31
  5. machineconfig/scripts/python/devops_navigator.py +1 -1
  6. machineconfig/scripts/python/helper_env/path_manager_tui.py +1 -1
  7. machineconfig/scripts/python/helpers/helper_env/env_manager_tui.py +1 -1
  8. machineconfig/scripts/python/helpers/helper_env/path_manager_tui.py +1 -1
  9. machineconfig/scripts/python/helpers/helpers_croshell/croshell_impl.py +4 -4
  10. machineconfig/scripts/python/helpers/helpers_devops/backup_config.py +3 -3
  11. machineconfig/scripts/python/helpers/helpers_devops/cli_backup_retrieve.py +3 -3
  12. machineconfig/scripts/python/helpers/helpers_devops/cli_config_dotfile.py +13 -13
  13. machineconfig/scripts/python/helpers/helpers_devops/cli_repos.py +27 -18
  14. machineconfig/scripts/python/helpers/helpers_devops/cli_self.py +3 -2
  15. machineconfig/scripts/python/helpers/helpers_repos/cloud_repo_sync.py +2 -1
  16. machineconfig/scripts/python/helpers/helpers_sessions/sessions_impl.py +10 -1
  17. machineconfig/scripts/python/helpers/helpers_utils/python.py +2 -1
  18. machineconfig/scripts/python/sessions.py +2 -2
  19. machineconfig/settings/shells/zsh/init.sh +9 -18
  20. machineconfig/setup_linux/web_shortcuts/interactive.sh +10 -10
  21. machineconfig/setup_windows/web_shortcuts/interactive.ps1 +10 -10
  22. machineconfig/utils/installer_utils/github_release_bulk.py +11 -92
  23. machineconfig/utils/installer_utils/github_release_scraper.py +99 -0
  24. machineconfig/utils/io.py +25 -8
  25. machineconfig/utils/ssh_utils/abc.py +1 -1
  26. machineconfig/utils/ssh_utils/copy_from_here.py +17 -12
  27. machineconfig/utils/ssh_utils/utils.py +21 -5
  28. {machineconfig-8.45.dist-info → machineconfig-8.50.dist-info}/METADATA +1 -1
  29. {machineconfig-8.45.dist-info → machineconfig-8.50.dist-info}/RECORD +32 -31
  30. {machineconfig-8.45.dist-info → machineconfig-8.50.dist-info}/WHEEL +0 -0
  31. {machineconfig-8.45.dist-info → machineconfig-8.50.dist-info}/entry_points.txt +0 -0
  32. {machineconfig-8.45.dist-info → machineconfig-8.50.dist-info}/top_level.txt +0 -0
@@ -37,7 +37,7 @@ else {
37
37
 
38
38
  winget install --no-upgrade --name "Powershell" --Id "Microsoft.PowerShell" --source winget --scope user --accept-package-agreements --accept-source-agreements # powershell require admin
39
39
  winget install --no-upgrade --name "Windows Terminal" --Id "Microsoft.WindowsTerminal" --source winget --scope user --accept-package-agreements --accept-source-agreements # Terminal is is installed by default on W 11
40
- winget isntall --no-upgrade --name "Git" --Id "Git.Git" --source winget --scope user --accept-package-agreements --accept-source-agreements
40
+ winget install --no-upgrade --name "Git" --Id "Git.Git" --source winget --scope user --accept-package-agreements --accept-source-agreements
41
41
  powershell -c "irm bun.sh/install.ps1|iex"
42
42
 
43
43
  # --GROUP:gui:Brave+VSCode+Git+WezTerm
@@ -7,7 +7,7 @@ $user = ''
7
7
  $sharePath = ''
8
8
  $driveLetter = ''
9
9
 
10
- uv run --python 3.14 --with "machineconfig>=8.45" python -m machineconfig.scripts.python.mount_ssh
10
+ uv run --python 3.14 --with "machineconfig>=8.50" python -m machineconfig.scripts.python.mount_ssh
11
11
 
12
12
  net use T: \\sshfs.kr\$user@$host.local
13
13
  # this worked: net use T: \\sshfs\alex@alex-p51s-5.local
@@ -11,9 +11,7 @@ ON_CONFLICT_LOOSE: TypeAlias = Literal[
11
11
  "backup-default-path", "bd"
12
12
  ]
13
13
  ON_CONFLICT_STRICT: TypeAlias = Literal["throw-error", "overwrite-self-managed", "backup-self-managed", "overwrite-default-path", "backup-default-path"]
14
- SENSITIVITY_LOOSE: TypeAlias = Literal["private", "p", "public", "b", "all", "a"]
15
- REPO_LOOSE: TypeAlias = Literal["library", "l", "user", "u", "all", "a"]
16
- ON_CONFLICT_MAPPER: dict[str, ON_CONFLICT_STRICT] = {
14
+ ON_CONFLICT_MAPPER: dict[ON_CONFLICT_LOOSE, ON_CONFLICT_STRICT] = {
17
15
  "t": "throw-error",
18
16
  "os": "overwrite-self-managed",
19
17
  "bs": "backup-self-managed",
@@ -26,10 +24,42 @@ ON_CONFLICT_MAPPER: dict[str, ON_CONFLICT_STRICT] = {
26
24
  "backup-default-path": "backup-default-path",
27
25
  }
28
26
 
27
+ SENSITIVITY_LOOSE: TypeAlias = Literal["private", "p", "public", "b", "all", "a"]
28
+ SENSITIVITY_STRICT: TypeAlias = Literal["private", "public", "all"]
29
+ SENSITIVITY_MAP: dict[SENSITIVITY_LOOSE, SENSITIVITY_STRICT] = {
30
+ "private": "private",
31
+ "p": "private",
32
+ "public": "public",
33
+ "b": "public",
34
+ "all": "all",
35
+ "a": "all",
36
+ }
37
+
38
+ REPO_STRICT: TypeAlias = Literal["library", "user", "all"]
39
+ REPO_LOOSE: TypeAlias = Literal["library", "l", "user", "u", "all", "a"]
40
+ REPO_MAP: dict[REPO_LOOSE, REPO_STRICT] = {
41
+ "library": "library",
42
+ "l": "library",
43
+ "user": "user",
44
+ "u": "user",
45
+ "a": "all",
46
+ "all": "all",
47
+ }
48
+
49
+ METHOD_STRICT: TypeAlias = Literal["symlink", "copy"]
50
+ METHOD_LOOSE: TypeAlias = Literal["symlink", "s", "copy", "c"]
51
+ METHOD_MAP: dict[METHOD_LOOSE, METHOD_STRICT] = {
52
+ "symlink": "symlink",
53
+ "s": "symlink",
54
+ "copy": "copy",
55
+ "c": "copy",
56
+ }
57
+
58
+
29
59
 
30
60
  def main_from_parser(
31
61
  sensitivity: Annotated[SENSITIVITY_LOOSE, typer.Option(..., "--sensitivity", "-s", help="Sensitivity of the configuration files to manage.")],
32
- method: Annotated[Literal["symlink", "s", "copy", "c"], typer.Option(..., "--method", "-m", help="Method to use for linking files")],
62
+ method: Annotated[METHOD_LOOSE, typer.Option(..., "--method", "-m", help="Method to use for linking files")],
33
63
  repo: Annotated[REPO_LOOSE, typer.Option(..., "--repo", "-r", help="Mapper source to use for config files.")] = "library",
34
64
  on_conflict: Annotated[ON_CONFLICT_LOOSE, typer.Option(..., "--on-conflict", "-o", help="Action to take on conflict")] = "throw-error",
35
65
  which: Annotated[Optional[str], typer.Option(..., "--which", "-w", help="Specific items to process ('all' for all items) (default is None, selection is interactive)")] = None,
@@ -39,15 +69,7 @@ def main_from_parser(
39
69
  TARGET = Config-File-Default-Path
40
70
  For public config files in the library repo, the source always exists."""
41
71
  from machineconfig.profile.create_links import ConfigMapper, read_mapper
42
- repo_map: dict[REPO_LOOSE, Literal["library", "user", "all"]] = {
43
- "library": "library",
44
- "l": "library",
45
- "user": "user",
46
- "u": "user",
47
- "a": "all",
48
- "all": "all",
49
- }
50
- repo_key = repo_map[repo]
72
+ repo_key = REPO_MAP[repo]
51
73
  mapper_full_obj = read_mapper(repo=repo_key)
52
74
  match sensitivity:
53
75
  case "private" | "p":
@@ -78,12 +100,6 @@ def main_from_parser(
78
100
  from machineconfig.profile.create_helper import copy_assets_to_machine
79
101
  copy_assets_to_machine(which="settings") # config files live here and will be linked to.
80
102
 
81
- method_map: dict[str, Literal["symlink", "copy"]] = {
82
- "s": "symlink",
83
- "symlink": "symlink",
84
- "c": "copy",
85
- "copy": "copy",
86
- }
87
- method = method_map[method]
103
+ method = METHOD_MAP[method]
88
104
  from machineconfig.profile.create_links import apply_mapper
89
105
  apply_mapper(mapper_data=items_objections, on_conflict=ON_CONFLICT_MAPPER[on_conflict], method=method)
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
  # =================== PRIVATE ================================
4
- # os can be 'windows', 'linux,macos', 'macos' or 'any'
4
+ # os can be 'windows', 'linux,darwin', 'darwin' or 'any'
5
5
 
6
6
  [git]
7
7
  gitconfig = {original = '~/.gitconfig', self_managed = '~/dotfiles/creds/git/.gitconfig', os = 'any'}
@@ -17,14 +17,14 @@ keys = {original = '~/.gnupg', self_managed = '~/dotfiles/creds/.gnupg', content
17
17
  creds = {original = '~/.pypirc', self_managed = '~/dotfiles/creds/msc/.pypirc', os = 'any'}
18
18
 
19
19
  [rclone]
20
- config_xdg = {original = '~/.config/rclone/rclone.conf', self_managed = '~/dotfiles/creds/rclone/rclone.conf', os = 'linux,macos'}
20
+ config_xdg = {original = '~/.config/rclone/rclone.conf', self_managed = '~/dotfiles/creds/rclone/rclone.conf', os = 'linux,darwin'}
21
21
  config_windows = {original = '~/AppData/Roaming/rclone/rclone.conf', self_managed = '~/dotfiles/creds/rclone/rclone.conf', os = 'windows'}
22
22
 
23
23
  [cloudflare]
24
24
  config = {original = '~/.cloudflared', self_managed = '~/dotfiles/creds/cloudflare/.cloudflared', os = 'any'}
25
25
 
26
26
  [ngrok]
27
- config_linux = {original = '~/.config/ngrok/ngrok.yml', self_managed = '~/dotfiles/creds/tokens/ngrok.yml', os = 'linux,macos'}
27
+ config_linux = {original = '~/.config/ngrok/ngrok.yml', self_managed = '~/dotfiles/creds/tokens/ngrok.yml', os = 'linux,darwin'}
28
28
  config_windows = {original = '~/AppData/Local/ngrok/ngrok.yml', self_managed = '~/dotfiles/creds/tokens/ngrok.yml', os = 'windows'}
29
29
 
30
30
  [m365]
@@ -37,7 +37,7 @@ config3 = {original = '~/.cli-m365-connection.json', self_managed = '~/dotf
37
37
  data = {original = '~/.var/app/org.remmina.Remmina/data/remmina', self_managed = '~/dotfiles/creds/RDP/remmina/data/remmina', os = 'any'}
38
38
 
39
39
  [webapp_linux]
40
- brave = {original = '~/.local/share/applications', self_managed = '~/dotfiles/config/webapps/linux/brave', contents = true, os = 'linux,macos'}
40
+ brave = {original = '~/.local/share/applications', self_managed = '~/dotfiles/config/webapps/linux/brave', contents = true, os = 'linux,darwin'}
41
41
 
42
42
  # [startup_windows]
43
43
  # startup = {original = '~/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup', self_managed = '~/dotfiles/scripts/windows_startup', contents = true}
@@ -90,26 +90,26 @@ config = {original = '~/.procs.toml', self_managed = 'CONFIG_ROOT/settings/procs
90
90
  config_again = {original = '~/.config/procs/config.toml', self_managed = 'CONFIG_ROOT/settings/procs/.procs.toml', os = 'any'}
91
91
 
92
92
  [rofi_linux]
93
- config = {original = '~/.config/rofi/config.rasi', self_managed = 'CONFIG_ROOT/settings/rofi/config.rasi', os = 'linux,macos'}
93
+ config = {original = '~/.config/rofi/config.rasi', self_managed = 'CONFIG_ROOT/settings/rofi/config.rasi', os = 'linux,darwin'}
94
94
 
95
95
  [yazi]
96
96
  yazi_windows = {original = '~/AppData/Roaming/yazi/config/yazi.toml', self_managed = 'CONFIG_ROOT/settings/yazi/yazi_windows.toml', os = 'windows'}
97
97
  keymap_windows = {original = '~/AppData/Roaming/yazi/config/keymap.toml', self_managed = 'CONFIG_ROOT/settings/yazi/keymap_windows.toml', os = 'windows'}
98
98
  theme_windows = {original = '~/AppData/Roaming/yazi/config/theme.toml', self_managed = 'CONFIG_ROOT/settings/yazi/theme.toml', os = 'windows'}
99
99
  init_windows = {original = '~/AppData/Roaming/yazi/config/init.lua', self_managed = 'CONFIG_ROOT/settings/yazi/init.lua', os = 'windows'}
100
- yazi_linux = {original = '~/.config/yazi/yazi.toml', self_managed = 'CONFIG_ROOT/settings/yazi/yazi_linux.toml', os = 'linux,macos'}
101
- keymap_linux = {original = '~/.config/yazi/keymap.toml', self_managed = 'CONFIG_ROOT/settings/yazi/keymap_linux.toml', os = 'linux,macos'}
102
- theme_linux = {original = '~/.config/yazi/theme.toml', self_managed = 'CONFIG_ROOT/settings/yazi/theme.toml', os = 'linux,macos'}
103
- init_linux = {original = '~/.config/yazi/init.lua', self_managed = 'CONFIG_ROOT/settings/yazi/init.lua', os = 'linux,macos'}
104
- yazi_picker_linux = { original = '~/.config/helix/yazi-picker.sh', self_managed = 'CONFIG_ROOT/settings/helix/yazi-picker.sh' , os = 'linux,macos'}
100
+ yazi_linux = {original = '~/.config/yazi/yazi.toml', self_managed = 'CONFIG_ROOT/settings/yazi/yazi_linux.toml', os = 'linux,darwin'}
101
+ keymap_linux = {original = '~/.config/yazi/keymap.toml', self_managed = 'CONFIG_ROOT/settings/yazi/keymap_linux.toml', os = 'linux,darwin'}
102
+ theme_linux = {original = '~/.config/yazi/theme.toml', self_managed = 'CONFIG_ROOT/settings/yazi/theme.toml', os = 'linux,darwin'}
103
+ init_linux = {original = '~/.config/yazi/init.lua', self_managed = 'CONFIG_ROOT/settings/yazi/init.lua', os = 'linux,darwin'}
104
+ yazi_picker_linux = { original = '~/.config/helix/yazi-picker.sh', self_managed = 'CONFIG_ROOT/settings/helix/yazi-picker.sh' , os = 'linux,darwin'}
105
105
 
106
106
  [television]
107
- cable_linux = {original = '~/.config/television/cable', self_managed = 'CONFIG_ROOT/settings/television/cable_unix', contents = true, os = 'linux,macos'}
107
+ cable_linux = {original = '~/.config/television/cable', self_managed = 'CONFIG_ROOT/settings/television/cable_unix', contents = true, os = 'linux,darwin'}
108
108
  cable_windows = {original = '~/AppData/Local/television/config/cable', self_managed = 'CONFIG_ROOT/settings/television/cable_windows', contents = true, os = 'windows'}
109
109
 
110
110
  [tv]
111
- config_linux = {original = '~/.config/television/config.toml', self_managed = 'CONFIG_ROOT/settings/tv/config.toml', os = 'linux,macos'}
112
- themes_linux = {original = '~/.config/television/themes', self_managed = 'CONFIG_ROOT/settings/tv/themes', contents = true, os = 'linux,macos'}
111
+ config_linux = {original = '~/.config/television/config.toml', self_managed = 'CONFIG_ROOT/settings/tv/config.toml', os = 'linux,darwin'}
112
+ themes_linux = {original = '~/.config/television/themes', self_managed = 'CONFIG_ROOT/settings/tv/themes', contents = true, os = 'linux,darwin'}
113
113
  config_windows = {original = '~/AppData/Local/television/config.toml', self_managed = 'CONFIG_ROOT/settings/tv/config.toml', os = 'windows'}
114
114
  themes_windows = {original = '~/AppData/Local/television/themes', self_managed = 'CONFIG_ROOT/settings/tv/themes', contents = true, os = 'windows'}
115
115
 
@@ -117,21 +117,21 @@ themes_windows = {original = '~/AppData/Local/television/themes', self_managed =
117
117
  config_windows = {original = '~/AppData/Local/lf/lfrc', self_managed = 'CONFIG_ROOT/settings/lf/windows/lfrc', os = 'windows'}
118
118
  colors_windows = {original = '~/AppData/Local/lf/colors', self_managed = 'CONFIG_ROOT/settings/lf/windows/colors', os = 'windows'}
119
119
  icons_windows = {original = '~/AppData/Local/lf/icons', self_managed = 'CONFIG_ROOT/settings/lf/windows/icons', os = 'windows'}
120
- config_linux = {original = '~/.config/lf/lfrc', self_managed = 'CONFIG_ROOT/settings/lf/linux/lfrc', os = 'linux,macos'}
121
- colors_linux = {original = '~/.config/lf/colors', self_managed = 'CONFIG_ROOT/settings/lf/linux/colors', os = 'linux,macos'}
122
- icons_linux = {original = '~/.config/lf/icons', self_managed = 'CONFIG_ROOT/settings/lf/linux/icons', os = 'linux,macos'}
120
+ config_linux = {original = '~/.config/lf/lfrc', self_managed = 'CONFIG_ROOT/settings/lf/linux/lfrc', os = 'linux,darwin'}
121
+ colors_linux = {original = '~/.config/lf/colors', self_managed = 'CONFIG_ROOT/settings/lf/linux/colors', os = 'linux,darwin'}
122
+ icons_linux = {original = '~/.config/lf/icons', self_managed = 'CONFIG_ROOT/settings/lf/linux/icons', os = 'linux,darwin'}
123
123
 
124
124
  [broot]
125
125
  config = {original = '~/.config/broot/conf.toml', self_managed = 'CONFIG_ROOT/settings/broot/conf.toml', os = 'any'}
126
126
 
127
127
  [pistol_linux]
128
- config = {original = '~/.config/pistol/pistol.conf', self_managed = 'CONFIG_ROOT/settings/pistol/pistol.conf', os = 'linux,macos'}
128
+ config = {original = '~/.config/pistol/pistol.conf', self_managed = 'CONFIG_ROOT/settings/pistol/pistol.conf', os = 'linux,darwin'}
129
129
 
130
130
  [glow]
131
131
  config = {original = '~/.config/glow/glow.yml', self_managed = 'CONFIG_ROOT/settings/glow/glow.yml', os = 'any'}
132
132
 
133
133
  [gromit_linux]
134
- config = {original = '~/.var/app/net.christianbeier.Gromit-MPX/config/gromit-mpx.cfg', self_managed = 'CONFIG_ROOT/settings/gromit-mpx/gromit-mpx.cfg', copy = true, os = 'linux,macos'}
134
+ config = {original = '~/.var/app/net.christianbeier.Gromit-MPX/config/gromit-mpx.cfg', self_managed = 'CONFIG_ROOT/settings/gromit-mpx/gromit-mpx.cfg', copy = true, os = 'linux,darwin'}
135
135
 
136
136
 
137
137
  #[broot_windows]
@@ -171,15 +171,15 @@ config = {original = '~/.config/pudb/pudb.cfg', self_managed = 'CONFIG_ROOT/sett
171
171
  [nushell]
172
172
  config_windows = {original = '~/AppData/Roaming/nushell/config.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/config.nu', os = 'windows'}
173
173
  env_windows = {original = '~/AppData/Roaming/nushell/env.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/env.nu', os = 'windows'}
174
- config_linux = {original = '~/.config/nushell/config.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/config.nu', os = 'linux,macos'}
175
- env_linux = {original = '~/.config/nushell/env.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/env.nu', os = 'linux,macos'}
174
+ config_linux = {original = '~/.config/nushell/config.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/config.nu', os = 'linux,darwin'}
175
+ env_linux = {original = '~/.config/nushell/env.nu', self_managed = 'CONFIG_ROOT/settings/shells/nushell/env.nu', os = 'linux,darwin'}
176
176
 
177
177
  [kitty_linux]
178
- config = {original = '~/.config/kitty/kitty.conf', self_managed = 'CONFIG_ROOT/settings/shells/kitty/kitty.conf', os = 'linux,macos'}
178
+ config = {original = '~/.config/kitty/kitty.conf', self_managed = 'CONFIG_ROOT/settings/shells/kitty/kitty.conf', os = 'linux,darwin'}
179
179
 
180
180
  [alacritty]
181
- config_linux = {original = '~/.config/alacritty/alacritty.toml', self_managed = 'CONFIG_ROOT/settings/shells/alacritty/alacritty.toml', os = 'linux,macos'}
182
- config_yaml_linux = {original = '~/.config/alacritty/alacritty.yml', self_managed = 'CONFIG_ROOT/settings/shells/alacritty/alacritty.yml', os = 'linux,macos'}
181
+ config_linux = {original = '~/.config/alacritty/alacritty.toml', self_managed = 'CONFIG_ROOT/settings/shells/alacritty/alacritty.toml', os = 'linux,darwin'}
182
+ config_yaml_linux = {original = '~/.config/alacritty/alacritty.yml', self_managed = 'CONFIG_ROOT/settings/shells/alacritty/alacritty.yml', os = 'linux,darwin'}
183
183
  config_windows = {original = '~/AppData/Roaming/alacritty/alacritty.toml', self_managed = 'CONFIG_ROOT/settings/shells/alacritty/alacritty.toml', os = 'windows'}
184
184
 
185
185
  [hyper_terminal]
@@ -207,7 +207,7 @@ config = {original = '~/mprocs.yaml', self_managed = 'CONFIG_ROOT/settings/mproc
207
207
 
208
208
 
209
209
  [zellij_linux]
210
- config = { original = '~/.config/zellij', self_managed = 'CONFIG_ROOT/settings/zellij' , os = 'linux,macos'}
210
+ config = { original = '~/.config/zellij', self_managed = 'CONFIG_ROOT/settings/zellij' , os = 'linux,darwin'}
211
211
  #themes = { original = '~/.config/zellij/themes', self_managed = 'CONFIG_ROOT/settings/zellij/themes' }
212
212
  #layouts = { original = '~/.config/zellij/layouts', self_managed = 'CONFIG_ROOT/settings/zellij/layouts' }
213
213
 
@@ -215,22 +215,22 @@ config = { original = '~/.config/zellij', self_managed = 'CONFIG_ROOT/settings/z
215
215
  # ===================== IDEs ============================
216
216
 
217
217
  [zed_linux]
218
- settings = {original = '~/.config/zed/settings.json', self_managed = 'CONFIG_ROOT/settings/zed/settings.json', os = 'linux,macos'}
218
+ settings = {original = '~/.config/zed/settings.json', self_managed = 'CONFIG_ROOT/settings/zed/settings.json', os = 'linux,darwin'}
219
219
 
220
220
  [helix]
221
221
  languages_windows = { original = '~/AppData/Roaming/helix/languages.toml', self_managed = 'CONFIG_ROOT/settings/helix/languages.toml' , os = 'windows'}
222
222
  config_windows = { original = '~/AppData/Roaming/helix/config.toml', self_managed = 'CONFIG_ROOT/settings/helix/config.toml' , os = 'windows'}
223
- languages_linux = { original = '~/.config/helix/languages.toml', self_managed = 'CONFIG_ROOT/settings/helix/languages.toml' , os = 'linux,macos'}
224
- config_linux = { original = '~/.config/helix/config.toml', self_managed = 'CONFIG_ROOT/settings/helix/config.toml' , os = 'linux,macos'}
223
+ languages_linux = { original = '~/.config/helix/languages.toml', self_managed = 'CONFIG_ROOT/settings/helix/languages.toml' , os = 'linux,darwin'}
224
+ config_linux = { original = '~/.config/helix/config.toml', self_managed = 'CONFIG_ROOT/settings/helix/config.toml' , os = 'linux,darwin'}
225
225
 
226
226
  [lvim]
227
227
  config_windows = { original = '~/AppData/Local/lvim/config.lua', self_managed = 'CONFIG_ROOT/settings/lvim/windows/config.lua' , os = 'windows'}
228
- config_linux = { original = '~/.config/lvim/config.lua', self_managed = 'CONFIG_ROOT/settings/lvim/linux/config.lua' , os = 'linux,macos'}
228
+ config_linux = { original = '~/.config/lvim/config.lua', self_managed = 'CONFIG_ROOT/settings/lvim/linux/config.lua' , os = 'linux,darwin'}
229
229
 
230
230
 
231
231
  [svim]
232
232
  init_windows = { original = '~/.SpaceVim.d/init.toml', self_managed = 'CONFIG_ROOT/settings/svim/windows/init.toml' , os = 'windows'}
233
- init_linux = { original = '~/.SpaceVim.d/init.toml', self_managed = 'CONFIG_ROOT/settings/svim/linux/init.toml' , os = 'linux,macos'}
233
+ init_linux = { original = '~/.SpaceVim.d/init.toml', self_managed = 'CONFIG_ROOT/settings/svim/linux/init.toml' , os = 'linux,darwin'}
234
234
 
235
235
  [linters]
236
236
  flake8 = {original = '~/.flake8', self_managed = 'CONFIG_ROOT/settings/linters/.flake8', os = 'any'}
@@ -247,7 +247,7 @@ notepadpp = {original = '~/AppData/Local/Microsoft/WindowsApps/notepad++.exe', s
247
247
  # tesseract = {original = '~/AppData/Local/Microsoft/WindowsApps/tesseract.exe', self_managed = '~/AppData/Local/Tesseract-OCR/tesseract.exe'} # doesn't work without whole installation dir is on PATH.
248
248
 
249
249
  [atuin]
250
- config_linux = {original = '~/.config/atuin/config.toml', self_managed = 'CONFIG_ROOT/settings/atuin/config.toml', os = 'linux,macos'}
251
- themes_linux = {original = '~/.config/atuin/themes', self_managed = 'CONFIG_ROOT/settings/atuin/themes', contents = true, os = 'linux,macos'}
250
+ config_linux = {original = '~/.config/atuin/config.toml', self_managed = 'CONFIG_ROOT/settings/atuin/config.toml', os = 'linux,darwin'}
251
+ themes_linux = {original = '~/.config/atuin/themes', self_managed = 'CONFIG_ROOT/settings/atuin/themes', contents = true, os = 'linux,darwin'}
252
252
  config_windows = {original = '~/AppData/Roaming/atuin/config.toml', self_managed = 'CONFIG_ROOT/settings/atuin/config.toml', os = 'windows'}
253
253
  themes_windows = {original = '~/AppData/Roaming/atuin/themes', self_managed = 'CONFIG_ROOT/settings/atuin/themes', contents = true, os = 'windows'}
@@ -2,7 +2,7 @@
2
2
  # /// script
3
3
  # requires-python = ">=3.13"
4
4
  # dependencies = [
5
- # "machineconfig>=8.45",
5
+ # "machineconfig>=8.50",
6
6
  # "textual",
7
7
  # ]
8
8
  # ///
@@ -2,7 +2,7 @@
2
2
  # /// script
3
3
  # requires-python = ">=3.13"
4
4
  # dependencies = [
5
- # "machineconfig>=8.45",
5
+ # "machineconfig>=8.50",
6
6
  # "textual",
7
7
  # "pyperclip",
8
8
  # ]
@@ -2,7 +2,7 @@
2
2
  # /// script
3
3
  # requires-python = ">=3.13"
4
4
  # dependencies = [
5
- # "machineconfig>=8.45",
5
+ # "machineconfig>=8.50",
6
6
  # "textual",
7
7
  # "pyperclip",
8
8
  # ]
@@ -2,7 +2,7 @@
2
2
  # /// script
3
3
  # requires-python = ">=3.13"
4
4
  # dependencies = [
5
- # "machineconfig>=8.45",
5
+ # "machineconfig>=8.50",
6
6
  # "textual",
7
7
  # "pyperclip",
8
8
  # ]
@@ -188,7 +188,7 @@ def _build_fire_line(
188
188
  if Path.home().joinpath("code/machineconfig").exists():
189
189
  requirements = f"""{user_uv_with_line} {uv_project_line} --with marimo,sqlglot """
190
190
  else:
191
- requirements = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "marimo,sqlglot,cowsay,machineconfig[plot]>=8.45" """
191
+ requirements = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "marimo,sqlglot,cowsay,machineconfig[plot]>=8.50" """
192
192
  fire_line = f"""
193
193
  cd {str(pyfile.parent)}
194
194
  uv run {uv_python_line} --with "marimo" marimo convert {pyfile.name} -o marimo_nb.py
@@ -198,7 +198,7 @@ uv run {requirements} marimo edit --host 0.0.0.0 marimo_nb.py
198
198
  if Path.home().joinpath("code/machineconfig").exists():
199
199
  requirements = f"""{user_uv_with_line} {uv_project_line} --with jupyterlab """
200
200
  else:
201
- requirements = f"""{user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.45" """
201
+ requirements = f"""{user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.50" """
202
202
  fire_line = f"uv run {requirements} {uv_project_line} jupyter-lab {str(nb_target)}"
203
203
  elif vscode:
204
204
  user_uv_add = f"uv add {uv_with}" if uv_with is not None else ""
@@ -206,7 +206,7 @@ uv run {requirements} marimo edit --host 0.0.0.0 marimo_nb.py
206
206
  cd {str(pyfile.parent)}
207
207
  uv init {uv_python_line}
208
208
  uv venv
209
- uv add "cowsay,machineconfig[plot]>=8.45"
209
+ uv add "cowsay,machineconfig[plot]>=8.50"
210
210
  uv add {user_uv_add}
211
211
  # code serve-web
212
212
  code --new-window {str(pyfile)}
@@ -219,7 +219,7 @@ code --new-window {str(pyfile)}
219
219
  if Path.home().joinpath("code/machineconfig").exists():
220
220
  ve_line = f"""{user_uv_with_line} {uv_project_line} """
221
221
  else:
222
- ve_line = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.45" """
222
+ ve_line = f"""{uv_python_line} {user_uv_with_line} {uv_project_line} --with "cowsay,machineconfig[plot]>=8.50" """
223
223
  fire_line = f"uv run {ve_line} {interpreter} {interactivity} {profile} {str(pyfile)}"
224
224
 
225
225
  return fire_line
@@ -1,14 +1,14 @@
1
1
  """Backup configuration types, parsing, and reading utilities."""
2
2
 
3
3
  from collections.abc import Mapping
4
- from typing import Literal, TypedDict
4
+ from typing import TypedDict
5
5
  from pathlib import Path
6
6
  from rich.console import Console
7
7
  from rich.panel import Panel
8
8
  import tomllib
9
9
 
10
10
  from machineconfig.utils.source_of_truth import LIBRARY_ROOT
11
-
11
+ from machineconfig.profile.create_links_export import REPO_LOOSE
12
12
 
13
13
  LIBRARY_BACKUP_PATH = LIBRARY_ROOT.joinpath("profile/mapper_data.toml")
14
14
  USER_BACKUP_PATH = Path.home().joinpath("dotfiles/machineconfig/mapper_data.toml")
@@ -125,7 +125,7 @@ def _parse_backup_config(raw: Mapping[str, object]) -> BackupConfig:
125
125
  return config
126
126
 
127
127
 
128
- def read_backup_config(repo: Literal["library", "l", "user", "u", "all", "a"]) -> BackupConfig:
128
+ def read_backup_config(repo: REPO_LOOSE) -> BackupConfig:
129
129
  match repo:
130
130
  case "library" | "l":
131
131
  path = LIBRARY_BACKUP_PATH
@@ -11,13 +11,13 @@ from rich.panel import Panel
11
11
  from machineconfig.utils.io import read_ini
12
12
  from machineconfig.utils.source_of_truth import DEFAULTS_PATH
13
13
  from machineconfig.utils.code import print_code
14
- from machineconfig.utils.options import choose_cloud_interactively, choose_from_options
14
+ from machineconfig.utils.options import choose_cloud_interactively
15
15
  from machineconfig.scripts.python.helpers.helpers_cloud.helpers2 import ES
16
16
  from machineconfig.scripts.python.helpers.helpers_devops.backup_config import (
17
17
  BackupConfig, BackupGroup, VALID_OS, USER_BACKUP_PATH, DEFAULT_BACKUP_HEADER,
18
18
  normalize_os_name, os_applies, read_backup_config,
19
19
  )
20
-
20
+ from machineconfig.profile.create_links_export import REPO_LOOSE
21
21
 
22
22
  DIRECTION = Literal["BACKUP", "RETRIEVE"]
23
23
 
@@ -146,7 +146,7 @@ def register_backup_entry(
146
146
  return USER_BACKUP_PATH, entry_name, replaced
147
147
 
148
148
 
149
- def main_backup_retrieve(direction: DIRECTION, which: Optional[str], cloud: Optional[str], repo: Literal["library", "l", "user", "u", "all", "a"]) -> None:
149
+ def main_backup_retrieve(direction: DIRECTION, which: Optional[str], cloud: Optional[str], repo: REPO_LOOSE) -> None:
150
150
  console = Console()
151
151
  if cloud is None or not cloud.strip():
152
152
  try:
@@ -2,11 +2,16 @@
2
2
  """Like yadm and dotter."""
3
3
 
4
4
  from git import Optional
5
- from machineconfig.profile.create_links_export import ON_CONFLICT_LOOSE, ON_CONFLICT_MAPPER
5
+ from machineconfig.profile.create_links_export import ON_CONFLICT_LOOSE, ON_CONFLICT_MAPPER, METHOD_LOOSE, METHOD_MAP
6
6
  from typing import Annotated, Literal
7
7
  from pathlib import Path
8
8
  import typer
9
9
 
10
+ from machineconfig.utils.source_of_truth import CONFIG_ROOT
11
+ BACKUP_ROOT_PRIVATE = Path.home().joinpath("dotfiles/machineconfig/mapper/files")
12
+ BACKUP_ROOT_PUBLIC = Path(CONFIG_ROOT).joinpath("dotfiles/mapper")
13
+
14
+
10
15
 
11
16
  def _write_to_user_mapper(section: str, entry_name: str, original_path: Path, self_managed_path: Path, method: Literal["symlink", "copy"], is_contents: bool, os_filter: str) -> Path:
12
17
  from machineconfig.profile.create_links import USER_MAPPER_PATH
@@ -51,9 +56,9 @@ def _write_to_user_mapper(section: str, entry_name: str, original_path: Path, se
51
56
  mapper_path.write_text(content, encoding="utf-8")
52
57
  return mapper_path
53
58
 
54
- def record_mapping(orig_path: Path, new_path: Path, method: Literal["symlink", "s", "copy", "c"], section: str, os_filter: str) -> None:
59
+ def record_mapping(orig_path: Path, new_path: Path, method: METHOD_LOOSE, section: str, os_filter: str) -> None:
55
60
  entry_name = orig_path.stem.replace(".", "_").replace("-", "_")
56
- method_resolved: Literal["symlink", "copy"] = "symlink" if method in ("symlink", "s") else "copy"
61
+ method_resolved = METHOD_MAP[method]
57
62
  mapper_file = _write_to_user_mapper(section=section, entry_name=entry_name, original_path=orig_path, self_managed_path=new_path, method=method_resolved, is_contents=False, os_filter=os_filter)
58
63
  home = Path.home()
59
64
  orig_display = f"~/{orig_path.relative_to(home)}" if orig_path.is_relative_to(home) else orig_path.as_posix()
@@ -64,17 +69,12 @@ def record_mapping(orig_path: Path, new_path: Path, method: Literal["symlink", "
64
69
  console.print(Panel(f"📝 Mapping recorded in: [cyan]{mapper_file}[/cyan]\n[{section}]\n{entry_name} = {{ original = '{orig_display}', self_managed = '{new_display}', os = '{os_filter}' }}", title="Mapper Entry Saved", border_style="cyan", padding=(1, 2),))
65
70
 
66
71
 
67
- backup_root_private = Path.home().joinpath("dotfiles/machineconfig/mapper/files")
68
- from machineconfig.utils.source_of_truth import CONFIG_ROOT
69
- backup_root_public = Path(CONFIG_ROOT).joinpath("dotfiles/mapper")
70
-
71
-
72
72
  def get_backup_path(orig_path: Path, sensitivity: Literal["private", "v", "public", "b"], destination: Optional[str], shared: bool) -> Path:
73
73
  match sensitivity:
74
74
  case "private" | "v":
75
- backup_root = backup_root_private
75
+ backup_root = BACKUP_ROOT_PRIVATE
76
76
  case "public" | "b":
77
- backup_root = backup_root_public
77
+ backup_root = BACKUP_ROOT_PUBLIC
78
78
  if destination is None:
79
79
  if shared:
80
80
  new_path = backup_root.joinpath("shared").joinpath(orig_path.name)
@@ -93,9 +93,9 @@ def get_backup_path(orig_path: Path, sensitivity: Literal["private", "v", "publi
93
93
  def get_original_path_from_backup_path(backup_path: Path, sensitivity: Literal["private", "v", "public", "b"], destination: Optional[str], shared: bool) -> Path:
94
94
  match sensitivity:
95
95
  case "private" | "v":
96
- backup_root = backup_root_private
96
+ backup_root = BACKUP_ROOT_PRIVATE
97
97
  case "public" | "b":
98
- backup_root = backup_root_public
98
+ backup_root = BACKUP_ROOT_PUBLIC
99
99
  if destination is None:
100
100
  if shared:
101
101
  relative_part = backup_path.relative_to(backup_root.joinpath("shared"))
@@ -114,7 +114,7 @@ def get_original_path_from_backup_path(backup_path: Path, sensitivity: Literal["
114
114
 
115
115
  def register_dotfile(
116
116
  file: Annotated[str, typer.Argument(help="file/folder path.")],
117
- method: Annotated[Literal["symlink", "s", "copy", "c"], typer.Option(..., "--method", "-m", help="Method to use for linking files")] = "copy",
117
+ method: Annotated[METHOD_LOOSE, typer.Option(..., "--method", "-m", help="Method to use for linking files")] = "copy",
118
118
  on_conflict: Annotated[ON_CONFLICT_LOOSE, typer.Option(..., "--on-conflict", "-o", help="Action to take on conflict")] = "throw-error",
119
119
  sensitivity: Annotated[Literal["private", "v", "public", "b"], typer.Option(..., "--sensitivity", "-s", help="Sensitivity of the config file.")] = "private",
120
120
  destination: Annotated[Optional[str], typer.Option("--destination", "-d", help="destination folder (override the default, use at your own risk)")] = None,
@@ -63,16 +63,16 @@ def clone(directory: Annotated[str, typer.Argument(help="📁 Directory containi
63
63
  ) -> None:
64
64
  """📥 Clone repositories described by a repos.json specification."""
65
65
  if interactive:
66
- from machineconfig.scripts.python.helpers.helpers_devops.cli_config_dotfile import backup_root_private, backup_root_public, get_original_path_from_backup_path
67
- results_public = list(backup_root_public.rglob("repos.json"))
68
- results_private = list(backup_root_private.rglob("repos.json"))
66
+ from machineconfig.scripts.python.helpers.helpers_devops.cli_config_dotfile import BACKUP_ROOT_PRIVATE, BACKUP_ROOT_PUBLIC, get_original_path_from_backup_path
67
+ results_public = list(BACKUP_ROOT_PUBLIC.rglob("repos.json"))
68
+ results_private = list(BACKUP_ROOT_PRIVATE.rglob("repos.json"))
69
69
  if len(results_public) + len(results_private) == 0:
70
70
  print("❌ No repos.json specifications found in backup directories.")
71
71
  return
72
72
  from machineconfig.utils.options import choose_from_options
73
73
  chosen_files = choose_from_options(options=[str(p) for p in results_public + results_private], msg="Select a repos.json specification to clone from:", multi=True, tv=True)
74
74
  for file in chosen_files:
75
- if str(file).startswith(str(backup_root_private)):
75
+ if str(file).startswith(str(BACKUP_ROOT_PRIVATE)):
76
76
  original_path = get_original_path_from_backup_path(Path(file), sensitivity="private", destination=None, shared=False)
77
77
  else:
78
78
  original_path = get_original_path_from_backup_path(Path(file), sensitivity="public", destination=None, shared=False)
@@ -121,27 +121,36 @@ def checkout_to_branch_command(directory: Annotated[Optional[str], typer.Argumen
121
121
 
122
122
 
123
123
  def count_lines_in_repo(repo_path: Annotated[str, typer.Argument(..., help="Path to the git repository")]):
124
- def func(repo_path: str):
125
- from machineconfig.scripts.python.helpers.helpers_repos import repo_analyzer_1
124
+ # def func(repo_path: str):
125
+ # from machineconfig.scripts.python.helpers.helpers_repos import repo_analyzer_1
126
+ # repo_analyzer_1.count_historical_line_edits(repo_path=repo_path)
127
+ # from machineconfig.utils.code import run_lambda_function
128
+ # run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig>=8.50"])
129
+ from machineconfig.scripts.python.helpers.helpers_repos import repo_analyzer_1
130
+ try:
126
131
  repo_analyzer_1.count_historical_line_edits(repo_path=repo_path)
127
- from machineconfig.utils.code import run_lambda_function
128
- run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig>=8.45"])
132
+ except Exception as e:
133
+ typer.echo(f"❌ Error counting lines in repo {repo_path}: {e}")
129
134
 
130
135
 
131
136
  def print_python_files_by_size(repo_path: Annotated[str, typer.Argument(..., help="Path to the git repository")]):
132
- def func(repo_path: str):
133
- from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import print_python_files_by_size_impl
134
- print_python_files_by_size_impl(repo_path=repo_path)
135
- from machineconfig.utils.code import run_lambda_function
136
- run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.45"])
137
+ # def func(repo_path: str):
138
+ # from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import print_python_files_by_size_impl
139
+ # print_python_files_by_size_impl(repo_path=repo_path)
140
+ # from machineconfig.utils.code import run_lambda_function
141
+ # run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.50"])
142
+ from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import print_python_files_by_size_impl
143
+ print_python_files_by_size_impl(repo_path=repo_path)
137
144
 
138
145
 
139
146
  def analyze_repo_development(repo_path: Annotated[str, typer.Argument(..., help="Path to the git repository")]):
140
- def func(repo_path: str):
141
- from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import analyze_over_time
142
- analyze_over_time(repo_path=repo_path)
143
- from machineconfig.utils.code import run_lambda_function
144
- run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.45"])
147
+ # def func(repo_path: str):
148
+ # from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import analyze_over_time
149
+ # analyze_over_time(repo_path=repo_path)
150
+ # from machineconfig.utils.code import run_lambda_function
151
+ # run_lambda_function(lambda: func(repo_path=repo_path), uv_project_dir=None, uv_with=["machineconfig[plot]>=8.50"])
152
+ from machineconfig.scripts.python.helpers.helpers_repos.repo_analyzer_2 import analyze_over_time
153
+ analyze_over_time(repo_path=repo_path)
145
154
 
146
155
 
147
156
  def gource_viz(
@@ -1,6 +1,7 @@
1
1
 
2
2
  import typer
3
3
  from typing import Annotated, Literal
4
+ from machineconfig.utils.ssh_utils.abc import MACHINECONFIG_VERSION
4
5
 
5
6
 
6
7
  def copy_both_assets():
@@ -129,7 +130,7 @@ cd {str(mcfg_path)}
129
130
  """)
130
131
  else:
131
132
  exit_then_run_shell_script(rf"""
132
- {uv_command} tool install --upgrade "machineconfig>=8.45"
133
+ {uv_command} tool install --upgrade "{MACHINECONFIG_VERSION}"
133
134
  {uv_command2}
134
135
  """)
135
136
 
@@ -153,7 +154,7 @@ def navigate():
153
154
  path = Path(navigator.__file__).resolve().parent.joinpath("devops_navigator.py")
154
155
  from machineconfig.utils.code import exit_then_run_shell_script
155
156
  if Path.home().joinpath("code/machineconfig").exists(): executable = f"""--project "{str(Path.home().joinpath("code/machineconfig"))}" --with textual"""
156
- else: executable = """--with "machineconfig>=8.45,textual" """
157
+ else: executable = f"""--with "{MACHINECONFIG_VERSION},textual" """
157
158
  exit_then_run_shell_script(f"""uv run {executable} {path}""")
158
159
 
159
160
  def readme():
@@ -2,6 +2,7 @@
2
2
 
3
3
  from typing import Optional, Literal, Annotated
4
4
  import typer
5
+ from machineconfig.utils.ssh_utils.abc import MACHINECONFIG_VERSION
5
6
 
6
7
 
7
8
  def get_tmp_file():
@@ -165,7 +166,7 @@ exit $LASTEXITCODE
165
166
  uv_project_dir = f"""{str(Path.home().joinpath("code/machineconfig"))}"""
166
167
  uv_with = None
167
168
  else:
168
- uv_with = ["machineconfig>=8.45"]
169
+ uv_with = [MACHINECONFIG_VERSION]
169
170
  uv_project_dir = None
170
171
 
171
172
  shell_path = get_tmp_file()
@@ -40,7 +40,16 @@ def select_layout(layouts_json_file: str, selected_layouts_names: Optional[list[
40
40
  json_str = json_str.replace("""Command": "f """, """Command": "~/.config/machineconfig/scripts/wrap_mcfg fire """)
41
41
  json_str = json_str.replace("""Command": "s """, """Command": "~/.config/machineconfig/scripts/wrap_mcfg sessions """)
42
42
 
43
- layout_file: LayoutsFile = json.loads(json_str)
43
+ try:
44
+ # src/machineconfig/utils/io.py
45
+ layout_file: LayoutsFile = json.loads(json_str)
46
+ except Exception:
47
+ print(f"Failed to parse the json file {layouts_json_file}, trying to clean the comments and giving it another shot ... ")
48
+ from machineconfig.utils.io import remove_c_style_comments
49
+ json_str = remove_c_style_comments(json_str)
50
+ # print(json_str)
51
+ layout_file: LayoutsFile = json.loads(json_str)
52
+
44
53
  if len(layout_file["layouts"]) == 0:
45
54
  raise ValueError(f"No layouts found in {layouts_json_file}")
46
55
  if selected_layouts_names is None: