machineconfig 1.5__py3-none-any.whl → 1.8__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.
- machineconfig/__init__.py +8 -5
- machineconfig/jobs/python/check_installations.py +173 -163
- machineconfig/jobs/python/checkout_version.py +117 -0
- machineconfig/jobs/python/create_bootable_media.py +14 -14
- machineconfig/jobs/python/create_zellij_template.py +59 -56
- machineconfig/jobs/python/python_cargo_build_share.py +50 -45
- machineconfig/jobs/python/python_ve_symlink.py +20 -18
- machineconfig/jobs/python/tasks.py +4 -0
- machineconfig/jobs/script_installer/azure_data_studio.py +22 -0
- machineconfig/jobs/script_installer/bypass_paywall.py +23 -0
- machineconfig/jobs/script_installer/code.py +34 -0
- machineconfig/jobs/script_installer/docker_desktop.py +41 -0
- machineconfig/jobs/script_installer/ngrok.py +29 -0
- machineconfig/jobs/{python_linux_installers → script_installer}/skim.py +21 -19
- machineconfig/jobs/script_installer/wezterm.py +34 -0
- machineconfig/profile/create.py +107 -200
- machineconfig/profile/shell.py +127 -0
- machineconfig/scripts/__init__.py +6 -6
- machineconfig/scripts/python/cloud_copy.py +93 -0
- machineconfig/scripts/python/cloud_manager.py +38 -0
- machineconfig/scripts/python/cloud_mount.py +115 -52
- machineconfig/scripts/python/cloud_repo_sync.py +154 -114
- machineconfig/scripts/python/cloud_sync.py +261 -79
- machineconfig/scripts/python/croshell.py +151 -0
- machineconfig/scripts/python/devops.py +119 -87
- machineconfig/scripts/python/devops_add_identity.py +27 -23
- machineconfig/scripts/python/devops_add_ssh_key.py +70 -55
- machineconfig/scripts/python/devops_backup_retrieve.py +52 -46
- machineconfig/scripts/python/devops_devapps_install.py +120 -91
- machineconfig/scripts/python/devops_update_repos.py +82 -68
- machineconfig/scripts/python/dotfile.py +42 -38
- machineconfig/scripts/python/fire_jobs.py +351 -98
- machineconfig/scripts/python/ftpx.py +82 -0
- machineconfig/scripts/python/mount_nfs.py +54 -3
- machineconfig/scripts/python/mount_nw_drive.py +31 -0
- machineconfig/scripts/python/mount_ssh.py +44 -20
- machineconfig/scripts/python/onetimeshare.py +60 -51
- machineconfig/scripts/python/pomodoro.py +41 -37
- machineconfig/scripts/python/repos.py +195 -128
- machineconfig/scripts/python/scheduler.py +52 -0
- machineconfig/scripts/python/snapshot.py +21 -21
- machineconfig/scripts/python/start_slidev.py +104 -0
- machineconfig/scripts/python/start_terminals.py +97 -0
- machineconfig/scripts/python/wifi_conn.py +90 -71
- machineconfig/scripts/python/{transfer_wsl_win.py → wsl_windows_transfer.py} +47 -39
- machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +44 -48
- machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +136 -130
- machineconfig/utils/installer.py +251 -0
- machineconfig/utils/procs.py +114 -64
- machineconfig/utils/scheduling.py +188 -0
- machineconfig/utils/utils.py +353 -249
- machineconfig/utils/ve.py +222 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/METADATA +140 -110
- machineconfig-1.8.dist-info/RECORD +70 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/WHEEL +1 -1
- machineconfig/jobs/python/python_linux_installers_all.py +0 -73
- machineconfig/jobs/python/python_ve_installer.py +0 -73
- machineconfig/jobs/python/python_windows_installers_all.py +0 -23
- machineconfig/jobs/python_generic_installers/archive/nvim.py +0 -15
- machineconfig/jobs/python_generic_installers/archive/strongbox.py +0 -32
- machineconfig/jobs/python_generic_installers/archive/vtm.py +0 -25
- machineconfig/jobs/python_generic_installers/broot.py +0 -39
- machineconfig/jobs/python_generic_installers/browsh.py +0 -25
- machineconfig/jobs/python_generic_installers/bw.py +0 -26
- machineconfig/jobs/python_generic_installers/chatgpt.py +0 -24
- machineconfig/jobs/python_generic_installers/cpufetch.py +0 -23
- machineconfig/jobs/python_generic_installers/delta.py +0 -59
- machineconfig/jobs/python_generic_installers/dev/__init__.py +0 -0
- machineconfig/jobs/python_generic_installers/dev/autogpt.py +0 -28
- machineconfig/jobs/python_generic_installers/dev/bw.py +0 -29
- machineconfig/jobs/python_generic_installers/dev/evcxr.py +0 -22
- machineconfig/jobs/python_generic_installers/dev/kondo.py +0 -21
- machineconfig/jobs/python_generic_installers/dev/lvim.py +0 -60
- machineconfig/jobs/python_generic_installers/dev/ngrok.py +0 -35
- machineconfig/jobs/python_generic_installers/dev/opencommit.py +0 -21
- machineconfig/jobs/python_generic_installers/dev/qrcp.py +0 -25
- machineconfig/jobs/python_generic_installers/dev/qrscan.py +0 -16
- machineconfig/jobs/python_generic_installers/dev/rust-analyzer.py +0 -24
- machineconfig/jobs/python_generic_installers/dev/termscp.py +0 -23
- machineconfig/jobs/python_generic_installers/dev/tldr.py +0 -25
- machineconfig/jobs/python_generic_installers/dev/tokei.py +0 -24
- machineconfig/jobs/python_generic_installers/diskonaut.py +0 -26
- machineconfig/jobs/python_generic_installers/dua.py +0 -21
- machineconfig/jobs/python_generic_installers/evcxr.py +0 -21
- machineconfig/jobs/python_generic_installers/gitui.py +0 -23
- machineconfig/jobs/python_generic_installers/gopass.py +0 -19
- machineconfig/jobs/python_generic_installers/helix.py +0 -45
- machineconfig/jobs/python_generic_installers/kondo.py +0 -20
- machineconfig/jobs/python_generic_installers/lf.py +0 -25
- machineconfig/jobs/python_generic_installers/lvim.py +0 -34
- machineconfig/jobs/python_generic_installers/mprocs.py +0 -20
- machineconfig/jobs/python_generic_installers/navi.py +0 -20
- machineconfig/jobs/python_generic_installers/ots.py +0 -26
- machineconfig/jobs/python_generic_installers/ouch.py +0 -25
- machineconfig/jobs/python_generic_installers/pomodoro.py +0 -19
- machineconfig/jobs/python_generic_installers/procs.py +0 -20
- machineconfig/jobs/python_generic_installers/qrcp.py +0 -22
- machineconfig/jobs/python_generic_installers/qrscan.py +0 -14
- machineconfig/jobs/python_generic_installers/rclone.py +0 -21
- machineconfig/jobs/python_generic_installers/rust-analyzer.py +0 -24
- machineconfig/jobs/python_generic_installers/tere.py +0 -26
- machineconfig/jobs/python_generic_installers/termscp.py +0 -23
- machineconfig/jobs/python_generic_installers/tldr.py +0 -24
- machineconfig/jobs/python_generic_installers/tokei.py +0 -21
- machineconfig/jobs/python_generic_installers/vtm.py +0 -26
- machineconfig/jobs/python_generic_installers/watchexec.py +0 -21
- machineconfig/jobs/python_linux_installers/archive/__init__.py +0 -0
- machineconfig/jobs/python_linux_installers/archive/ranger.py +0 -18
- machineconfig/jobs/python_linux_installers/bandwhich.py +0 -11
- machineconfig/jobs/python_linux_installers/bottom.py +0 -17
- machineconfig/jobs/python_linux_installers/btop.py +0 -17
- machineconfig/jobs/python_linux_installers/dev/bandwhich.py +0 -13
- machineconfig/jobs/python_linux_installers/dev/bytehound.py +0 -20
- machineconfig/jobs/python_linux_installers/dev/nnn.py +0 -21
- machineconfig/jobs/python_linux_installers/gotty.py +0 -16
- machineconfig/jobs/python_linux_installers/joshuto.py +0 -28
- machineconfig/jobs/python_linux_installers/mcfly.py +0 -12
- machineconfig/jobs/python_linux_installers/nnn.py +0 -18
- machineconfig/jobs/python_linux_installers/topgrade.py +0 -15
- machineconfig/jobs/python_linux_installers/viu.py +0 -19
- machineconfig/jobs/python_linux_installers/xplr.py +0 -22
- machineconfig/jobs/python_linux_installers/zellij.py +0 -31
- machineconfig/jobs/python_windows_installers/archive/ntop.py +0 -20
- machineconfig/jobs/python_windows_installers/bat.py +0 -16
- machineconfig/jobs/python_windows_installers/boxes.py +0 -19
- machineconfig/jobs/python_windows_installers/bypass_paywall.py +0 -18
- machineconfig/jobs/python_windows_installers/dev/bypass_paywall.py +0 -21
- machineconfig/jobs/python_windows_installers/dev/obs_background_removal_plugin.py +0 -20
- machineconfig/jobs/python_windows_installers/fd.py +0 -17
- machineconfig/jobs/python_windows_installers/fzf.py +0 -19
- machineconfig/jobs/python_windows_installers/obs_background_removal_plugin.py +0 -19
- machineconfig/jobs/python_windows_installers/rg.py +0 -15
- machineconfig/jobs/python_windows_installers/ugrep.py +0 -14
- machineconfig/jobs/python_windows_installers/zoomit.py +0 -20
- machineconfig/jobs/python_windows_installers/zoxide.py +0 -20
- machineconfig/profile/fix_shell_profiles.py +0 -8
- machineconfig/scripts/python/archive/__init__.py +0 -0
- machineconfig/scripts/python/archive/bu_gdrive_rx.py +0 -41
- machineconfig/scripts/python/archive/bu_gdrive_sx.py +0 -40
- machineconfig/scripts/python/archive/bu_onedrive_rx.py +0 -59
- machineconfig/scripts/python/archive/bu_onedrive_sx.py +0 -45
- machineconfig/scripts/python/chatgpt.py +0 -28
- machineconfig/scripts/python/choose_ohmybash_theme.py +0 -25
- machineconfig/scripts/python/choose_ohmyposh_theme.py +0 -40
- machineconfig/scripts/python/cloud_rx.py +0 -42
- machineconfig/scripts/python/cloud_sx.py +0 -40
- machineconfig/scripts/python/ftprx.py +0 -37
- machineconfig/scripts/python/ftpsx.py +0 -36
- machineconfig/scripts/python/im2text.py +0 -15
- machineconfig/scripts/python/tmate_conn.py +0 -28
- machineconfig/scripts/python/tmate_start.py +0 -31
- machineconfig/utils/to_exe.py +0 -7
- machineconfig-1.5.dist-info/RECORD +0 -147
- /machineconfig/jobs/{python_generic_installers/archive → script_installer}/__init__.py +0 -0
- {machineconfig-1.5.dist-info → machineconfig-1.8.dist-info}/top_level.txt +0 -0
|
@@ -1,79 +1,261 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
1
|
+
|
|
2
|
+
"""CS
|
|
3
|
+
TODO: use tap typed-argument-parser to parse args
|
|
4
|
+
TODO: use typer to make clis
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from crocodile.file_management import P, Read, Struct
|
|
8
|
+
from crocodile.core import install_n_import
|
|
9
|
+
from machineconfig.utils.utils import PROGRAM_PATH, DEFAULTS_PATH
|
|
10
|
+
from machineconfig.scripts.python.cloud_mount import get_mprocs_mount_txt
|
|
11
|
+
import argparse
|
|
12
|
+
import os
|
|
13
|
+
from typing import Optional
|
|
14
|
+
# from dataclasses import dataclass
|
|
15
|
+
# from tap import Tap
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
ES = "^" # chosen carefully to not mean anything on any shell. `$` was a bad choice.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ArgsDefaults:
|
|
22
|
+
# source: str = None
|
|
23
|
+
# target: str = None
|
|
24
|
+
encrypt: bool = False
|
|
25
|
+
zip_: bool = False
|
|
26
|
+
overwrite: bool = False
|
|
27
|
+
share: bool = False
|
|
28
|
+
rel2home = False
|
|
29
|
+
root = None
|
|
30
|
+
os_specific = False
|
|
31
|
+
key = None
|
|
32
|
+
pwd = None
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
install_n_import("pydantic")
|
|
36
|
+
from pydantic.dataclasses import dataclass # type: ignore # ruffle: ignore
|
|
37
|
+
from pydantic import ConfigDict
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(config=ConfigDict(extra="forbid", frozen=True))
|
|
41
|
+
class Args():
|
|
42
|
+
cloud: Optional[str] = None
|
|
43
|
+
|
|
44
|
+
zip: bool = ArgsDefaults.zip_
|
|
45
|
+
overwrite: bool = ArgsDefaults.overwrite
|
|
46
|
+
share: bool = ArgsDefaults.share
|
|
47
|
+
|
|
48
|
+
root: Optional[str] = ArgsDefaults.root
|
|
49
|
+
os_specific: bool = ArgsDefaults.os_specific
|
|
50
|
+
rel2home: bool = ArgsDefaults.rel2home
|
|
51
|
+
|
|
52
|
+
encrypt: bool = ArgsDefaults.encrypt
|
|
53
|
+
key: Optional[str] = ArgsDefaults.key
|
|
54
|
+
pwd: Optional[str] = ArgsDefaults.pwd
|
|
55
|
+
|
|
56
|
+
config: Optional[str] = None
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def from_config(config_path: P):
|
|
60
|
+
# from crocodile.core import install_n_import
|
|
61
|
+
# install_n_import("pydantic")
|
|
62
|
+
# from pydantic import BaseModel, ConfigDict
|
|
63
|
+
return Args(**Read.json(config_path))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def absolute(path: str) -> P:
|
|
67
|
+
obj = P(path).expanduser()
|
|
68
|
+
if not path.startswith(".") and obj.exists(): return obj
|
|
69
|
+
try_absing = P.cwd().joinpath(path)
|
|
70
|
+
if try_absing.exists(): return try_absing
|
|
71
|
+
print(f"Warning: {path} was not resolved to absolute one, trying out resolving symlinks (This may result in unintended paths)")
|
|
72
|
+
return obj.absolute()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_secure_share_cloud_config(interactive: bool = True) -> Args:
|
|
76
|
+
if os.environ.get("CLOUD_CONFIG_NAME") is not None:
|
|
77
|
+
default_cloud = os.environ.get("CLOUD_CONFIG_NAME")
|
|
78
|
+
assert default_cloud is not None
|
|
79
|
+
cloud = default_cloud
|
|
80
|
+
else:
|
|
81
|
+
try:
|
|
82
|
+
default_cloud__ = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
83
|
+
except Exception:
|
|
84
|
+
default_cloud__ = 'No default cloud found.'
|
|
85
|
+
if default_cloud__ == 'No default cloud found.' or interactive:
|
|
86
|
+
# assert default_cloud is not None
|
|
87
|
+
cloud = input(f"Enter cloud name (default {default_cloud__}): ") or default_cloud__
|
|
88
|
+
else:
|
|
89
|
+
cloud = default_cloud__
|
|
90
|
+
|
|
91
|
+
default_password_path = P.home().joinpath("dotfiles/creds/passwords/quick_password")
|
|
92
|
+
if default_password_path.exists():
|
|
93
|
+
pwd = default_password_path.read_text().strip()
|
|
94
|
+
default_message = "defaults to quick_password"
|
|
95
|
+
else:
|
|
96
|
+
pwd = ""
|
|
97
|
+
default_message = "no default password found"
|
|
98
|
+
pwd = input(f"Enter encryption password ({default_message}): ") or pwd
|
|
99
|
+
res = Args(cloud=cloud,
|
|
100
|
+
pwd=pwd, encrypt=True,
|
|
101
|
+
zip=True, overwrite=True, share=True,
|
|
102
|
+
rel2home=True, root="myshare", os_specific=False,)
|
|
103
|
+
Struct(res.__dict__).print(as_config=True, title=f"⚠️ Using SecureShare cloud config")
|
|
104
|
+
return res
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def find_cloud_config(path: P):
|
|
108
|
+
for _i in range(len(path.parts)):
|
|
109
|
+
if path.joinpath("cloud.json").exists():
|
|
110
|
+
res = Args.from_config(path.joinpath("cloud.json"))
|
|
111
|
+
Struct(res.__dict__).print(as_config=True, title=f"⚠️ Using default cloud config @ {path.joinpath('cloud.json')} ")
|
|
112
|
+
return res
|
|
113
|
+
path = path.parent
|
|
114
|
+
return None
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def parse_cloud_source_target(args: Args, source: str, target: str) -> tuple[str, str, str]:
|
|
118
|
+
if source.startswith(":"): # default cloud name is omitted cloud_name: # or ES in source
|
|
119
|
+
# At the moment, this cloud.json defaults overrides the args and is activated only when source or target are just ":"
|
|
120
|
+
# consider activating it by a flag, and also not not overriding explicitly passed args options.
|
|
121
|
+
assert ES not in target, f"Not Implemented here yet."
|
|
122
|
+
path = absolute(target)
|
|
123
|
+
if args.config is None:
|
|
124
|
+
maybe_config: Optional[Args] = find_cloud_config(path=path)
|
|
125
|
+
else:
|
|
126
|
+
if args.config == "ss": maybe_config = get_secure_share_cloud_config()
|
|
127
|
+
else: maybe_config = Args.from_config(absolute(args.config))
|
|
128
|
+
|
|
129
|
+
if maybe_config is None:
|
|
130
|
+
default_cloud: str = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
131
|
+
print(f"⚠️ Using default cloud: {default_cloud}")
|
|
132
|
+
source = default_cloud + ":" + source[1:]
|
|
133
|
+
else:
|
|
134
|
+
tmp = maybe_config
|
|
135
|
+
source = f"{tmp.cloud}:" + source[1:]
|
|
136
|
+
args.root = tmp.root
|
|
137
|
+
args.rel2home = tmp.rel2home
|
|
138
|
+
args.pwd = tmp.pwd
|
|
139
|
+
args.encrypt = tmp.encrypt
|
|
140
|
+
args.zip = tmp.zip
|
|
141
|
+
args.share = tmp.share
|
|
142
|
+
# args.jh = 22
|
|
143
|
+
|
|
144
|
+
if target.startswith(":"): # default cloud name is omitted cloud_name: # or ES in target
|
|
145
|
+
assert ES not in source, f"Not Implemented here yet."
|
|
146
|
+
path = absolute(source)
|
|
147
|
+
if args.config is None:
|
|
148
|
+
maybe_config = find_cloud_config(path)
|
|
149
|
+
else:
|
|
150
|
+
if args.config == "ss": maybe_config = get_secure_share_cloud_config()
|
|
151
|
+
else: maybe_config = Args.from_config(absolute(args.config))
|
|
152
|
+
|
|
153
|
+
if maybe_config is not None:
|
|
154
|
+
tmp = maybe_config
|
|
155
|
+
target = f"{tmp.cloud}:" + target[1:]
|
|
156
|
+
args.root = tmp.root
|
|
157
|
+
args.rel2home = tmp.rel2home
|
|
158
|
+
args.pwd = tmp.pwd
|
|
159
|
+
args.encrypt = tmp.encrypt
|
|
160
|
+
args.zip = tmp.zip
|
|
161
|
+
args.share = tmp.share
|
|
162
|
+
|
|
163
|
+
else:
|
|
164
|
+
default_cloud = Read.ini(DEFAULTS_PATH)['general']['rclone_config_name']
|
|
165
|
+
print(f"⚠️ Using default cloud: {default_cloud}")
|
|
166
|
+
target = default_cloud + ":" + target[1:]
|
|
167
|
+
|
|
168
|
+
if ":" in source and (source[1] != ":" if len(source) > 1 else True): # avoid the deceptive case of "C:/"
|
|
169
|
+
source_parts: list[str] = source.split(":")
|
|
170
|
+
cloud = source_parts[0]
|
|
171
|
+
|
|
172
|
+
if len(source_parts) > 1 and source_parts[1] == ES: # the source path is to be inferred from target.
|
|
173
|
+
assert ES not in target, f"You can't use expand symbol `{ES}` in both source and target. Cyclical inference dependency arised."
|
|
174
|
+
target_obj = absolute(target)
|
|
175
|
+
remote_path = target_obj.get_remote_path(os_specific=args.os_specific, root=args.root, rel2home=args.rel2home, strict=False)
|
|
176
|
+
source = f"{cloud}:{remote_path.as_posix()}"
|
|
177
|
+
|
|
178
|
+
else: # source path is mentioned, target? maybe.
|
|
179
|
+
if target == ES: # target path is to be inferred from source.
|
|
180
|
+
raise NotImplementedError(f"There is no .get_local_path method yet")
|
|
181
|
+
else:
|
|
182
|
+
target_obj = absolute(target)
|
|
183
|
+
if args.zip and ".zip" not in source: source += ".zip"
|
|
184
|
+
if args.encrypt and ".enc" not in source: source += ".enc"
|
|
185
|
+
|
|
186
|
+
elif ":" in target and (target[1] != ":" if len(target) > 1 else True): # avoid the case of "C:/"
|
|
187
|
+
target_parts: list[str] = target.split(":")
|
|
188
|
+
cloud = target.split(":")[0]
|
|
189
|
+
|
|
190
|
+
if len(target_parts) > 1 and target_parts[1] == ES: # the target path is to be inferred from source.
|
|
191
|
+
assert ES not in source, f"You can't use $ in both source and target. Cyclical inference dependency arised."
|
|
192
|
+
source_obj = absolute(source)
|
|
193
|
+
remote_path = source_obj.get_remote_path(os_specific=args.os_specific, root=args.root, rel2home=args.rel2home, strict=False)
|
|
194
|
+
target = f"{cloud}:{remote_path.as_posix()}"
|
|
195
|
+
else: # target path is mentioned, source? maybe.
|
|
196
|
+
target = str(target)
|
|
197
|
+
if source == ES:
|
|
198
|
+
raise NotImplementedError(f"There is no .get_local_path method yet")
|
|
199
|
+
else:
|
|
200
|
+
source_obj = absolute(source)
|
|
201
|
+
if args.zip and ".zip" not in target: target += ".zip"
|
|
202
|
+
if args.encrypt and ".enc" not in target: target += ".enc"
|
|
203
|
+
else:
|
|
204
|
+
raise ValueError("Either source or target must be a remote path (i.e. machine:path)")
|
|
205
|
+
Struct({"cloud": cloud, "source": str(source), "target": str(target)}).print(as_config=True, title="CLI Resolution")
|
|
206
|
+
return cloud, str(source), str(target)
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def args_parser():
|
|
210
|
+
parser = argparse.ArgumentParser(description="""A wrapper for rclone sync and rclone bisync, with some extra features.""")
|
|
211
|
+
|
|
212
|
+
parser.add_argument("source", help="source", default=None)
|
|
213
|
+
parser.add_argument("target", help="target", default=None)
|
|
214
|
+
|
|
215
|
+
parser.add_argument("--transfers", "-t", help="Number of threads in syncing.", default=10) # default is False
|
|
216
|
+
parser.add_argument("--root", "-R", help="Remote root.", default="myhome") # default is False
|
|
217
|
+
|
|
218
|
+
parser.add_argument("--key", "-k", help="Key for encryption", default=None)
|
|
219
|
+
parser.add_argument("--pwd", "-P", help="Password for encryption", default=None)
|
|
220
|
+
parser.add_argument("--encrypt", "-e", help="Decrypt after receiving.", action="store_true") # default is False
|
|
221
|
+
parser.add_argument("--zip", "-z", help="unzip after receiving.", action="store_true") # default is False
|
|
222
|
+
|
|
223
|
+
parser.add_argument("--bisync", "-b", help="Bidirectional sync.", action="store_true") # default is False
|
|
224
|
+
parser.add_argument("--delete", "-D", help="Delete files in remote that are not in local.", action="store_true") # default is False
|
|
225
|
+
parser.add_argument("--verbose", "-v", help="Verbosity of mprocs to show details of syncing.", action="store_true") # default is False
|
|
226
|
+
|
|
227
|
+
args = parser.parse_args()
|
|
228
|
+
args_dict = vars(args)
|
|
229
|
+
source: str = args_dict.pop("source")
|
|
230
|
+
target: str = args_dict.pop("target")
|
|
231
|
+
verbose: bool = args_dict.pop("verbose")
|
|
232
|
+
delete: bool = args_dict.pop("delete")
|
|
233
|
+
bisync: bool = args_dict.pop("bisync")
|
|
234
|
+
transfers: int = args_dict.pop("transfers")
|
|
235
|
+
args_obj = Args(**args_dict)
|
|
236
|
+
|
|
237
|
+
args_obj.os_specific = False
|
|
238
|
+
args_obj.rel2home = True
|
|
239
|
+
|
|
240
|
+
cloud, source, target = parse_cloud_source_target(args=args_obj, source=source, target=target)
|
|
241
|
+
# map short flags to long flags (-u -> --upload), for easier use in the script
|
|
242
|
+
if bisync:
|
|
243
|
+
print(f"SYNCING 🔄️ {source} {'<>' * 7} {target}`")
|
|
244
|
+
rclone_cmd = f"""rclone bisync '{source}' '{target}' --resync"""
|
|
245
|
+
else:
|
|
246
|
+
print(f"SYNCING {source} {'>' * 15} {target}`")
|
|
247
|
+
rclone_cmd = f"""rclone sync '{source}' '{target}' """
|
|
248
|
+
|
|
249
|
+
rclone_cmd += f" --progress --transfers={transfers} --verbose"
|
|
250
|
+
# rclone_cmd += f" --vfs-cache-mode full"
|
|
251
|
+
if delete: rclone_cmd += " --delete-during"
|
|
252
|
+
|
|
253
|
+
if verbose: txt = get_mprocs_mount_txt(cloud=cloud, rclone_cmd=rclone_cmd, cloud_brand="Unknown")
|
|
254
|
+
else: txt = f"""{rclone_cmd}"""
|
|
255
|
+
print(r'running command'.center(100, '-'))
|
|
256
|
+
print(txt)
|
|
257
|
+
PROGRAM_PATH.write_text(txt)
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if __name__ == '__main__':
|
|
261
|
+
args_parser()
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
croshell
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
# import subprocess
|
|
9
|
+
# import platform
|
|
10
|
+
from crocodile.file_management import P, randstr
|
|
11
|
+
from machineconfig.utils.ve import get_ipython_profile, get_ve_profile
|
|
12
|
+
from machineconfig.utils.utils import PROGRAM_PATH, display_options
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def add_print_header_pycode(path: str, title: str):
|
|
16
|
+
return f"""
|
|
17
|
+
pycode = P(r'{path}').read_text(encoding="utf-8")
|
|
18
|
+
pycode = pycode.split("except Exception: print(pycode)")[2]
|
|
19
|
+
|
|
20
|
+
try:
|
|
21
|
+
from rich.text import Text
|
|
22
|
+
from rich.panel import Panel
|
|
23
|
+
from rich.console import Console
|
|
24
|
+
from rich.syntax import Syntax
|
|
25
|
+
console = Console()
|
|
26
|
+
if pycode.strip() != "":
|
|
27
|
+
console.print(Panel(Syntax(pycode, lexer="python"), title='{title}'), style="bold red")
|
|
28
|
+
except Exception: print(pycode)
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_read_data_pycode(path: str):
|
|
33
|
+
pycode = f"""
|
|
34
|
+
p = P(r\'{path}\').absolute()
|
|
35
|
+
try:
|
|
36
|
+
dat = p.readit()
|
|
37
|
+
if type(dat) == Struct: dat.print(as_config=True, title=p.name)
|
|
38
|
+
else: print(f"Succcesfully read the file {{p.name}}")
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print(e)
|
|
41
|
+
|
|
42
|
+
"""
|
|
43
|
+
return pycode
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_read_pyfile_pycode(path: P, as_module: bool, cmd: str = ""):
|
|
47
|
+
if as_module: pycode = fr"""
|
|
48
|
+
import sys
|
|
49
|
+
sys.path.append(r'{path.parent}')
|
|
50
|
+
from {path.stem} import *
|
|
51
|
+
{cmd}
|
|
52
|
+
"""
|
|
53
|
+
else: pycode = f"""
|
|
54
|
+
__file__ = P(r'{path}')
|
|
55
|
+
{path.read_text(encoding="utf-8")}
|
|
56
|
+
"""
|
|
57
|
+
return pycode
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def build_parser():
|
|
61
|
+
parser = argparse.ArgumentParser(description="Generic Parser to launch crocodile shell.")
|
|
62
|
+
# A FLAG:
|
|
63
|
+
parser.add_argument("--module", '-m', help="flag to run the file as a module as opposed to main.", action="store_true", default=False) # default is running as main, unless indicated by --module flag.
|
|
64
|
+
parser.add_argument("--newWindow", "-w", help="flag for running in new window.", action="store_true", default=False)
|
|
65
|
+
parser.add_argument("--nonInteratctive", "-N", help="flag for a non-interactive session.", action="store_true", default=False)
|
|
66
|
+
parser.add_argument("--python", "-p", help="flag to use python over IPython.", action="store_true", default=False)
|
|
67
|
+
parser.add_argument("--fzf", "-F", help="search with fuzzy finder for python scripts and run them", action="store_true", default=False)
|
|
68
|
+
|
|
69
|
+
# OPTIONAL KEYWORD
|
|
70
|
+
parser.add_argument("--ve", "-v", help="virtual enviroment to use, defaults to activated ve, if existed, else ve.", default=None)
|
|
71
|
+
parser.add_argument("--profile", "-P", help="ipython profile to use, defaults to default profile.", default=None)
|
|
72
|
+
parser.add_argument("--read", "-r", dest="read", help="read a binary file.", default="")
|
|
73
|
+
parser.add_argument("--file", "-f", dest="file", help="python file path to interpret", default="")
|
|
74
|
+
parser.add_argument("--cmd", "-c", dest="cmd", help="python command to interpret", default="")
|
|
75
|
+
parser.add_argument("--terminal", "-t", dest="terminal", help=f"specify which terminal to be used. Default console host.", default="") # can choose `wt`
|
|
76
|
+
parser.add_argument("--shell", "-S", dest="shell", help=f"specify which shell to be used. Defaults to CMD.", default="")
|
|
77
|
+
|
|
78
|
+
args = parser.parse_args()
|
|
79
|
+
# print(f"Crocodile.run: args of the firing command = {args.__dict__}")
|
|
80
|
+
|
|
81
|
+
# ==================================================================================
|
|
82
|
+
# flags processing
|
|
83
|
+
interactivity = '' if args.nonInteratctive else '-i'
|
|
84
|
+
interpreter = 'python' if args.python else 'ipython'
|
|
85
|
+
profile = args.profile
|
|
86
|
+
file = P.cwd() # initialization value, could be modified according to args.
|
|
87
|
+
|
|
88
|
+
if args.cmd != "":
|
|
89
|
+
import textwrap
|
|
90
|
+
program = textwrap.dedent(args.cmd)
|
|
91
|
+
|
|
92
|
+
elif args.fzf:
|
|
93
|
+
options = P.cwd().search("*.py", r=True).apply(str).list
|
|
94
|
+
file = display_options(msg="Choose a python file to run", options=options, fzf=True, multi=False, )
|
|
95
|
+
assert isinstance(file, str)
|
|
96
|
+
if profile is None: profile = profile = get_ipython_profile(P(file))
|
|
97
|
+
program = P(file).read_text(encoding='utf-8')
|
|
98
|
+
|
|
99
|
+
elif args.file != "":
|
|
100
|
+
file = P(args.file.lstrip()).expanduser().absolute()
|
|
101
|
+
if profile is None: profile = profile = get_ipython_profile(P(file))
|
|
102
|
+
program = get_read_pyfile_pycode(file, as_module=args.module, cmd=args.cmd)
|
|
103
|
+
|
|
104
|
+
elif args.read != "":
|
|
105
|
+
file = P(str(args.read).lstrip()).expanduser().absolute()
|
|
106
|
+
if profile is None: profile = profile = get_ipython_profile(P(file))
|
|
107
|
+
program = get_read_data_pycode(str(file))
|
|
108
|
+
|
|
109
|
+
else: # just run croshell.py interactively
|
|
110
|
+
program = ""
|
|
111
|
+
# program = f" --profile {get_ipython_profile(P.cwd())} --no-banner -m crocodile.croshell" # --term-title croshell
|
|
112
|
+
# from IPython import start_ipython
|
|
113
|
+
# start_ipython(argv=program.split(' ')[1:])
|
|
114
|
+
# return
|
|
115
|
+
# Clear-Host;
|
|
116
|
+
# # --autocall 1 in order to enable shell-like behaviour: e.g.: P x is interpretred as P(x)
|
|
117
|
+
|
|
118
|
+
preprogram = """
|
|
119
|
+
from crocodile.croshell import *
|
|
120
|
+
print_header()
|
|
121
|
+
print_logo(logo="crocodile")
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
pyfile = P.tmp().joinpath(f"tmp_scripts/python/croshell/{randstr()}.py").create(parents_only=True)
|
|
125
|
+
|
|
126
|
+
if args.read != "": title = "Reading Data"
|
|
127
|
+
elif args.file != "": title = "Running Python File"
|
|
128
|
+
else: title = "Executed code"
|
|
129
|
+
total_program = preprogram + add_print_header_pycode(str(pyfile), title=title) + program
|
|
130
|
+
|
|
131
|
+
pyfile.write_text(total_program, encoding='utf-8')
|
|
132
|
+
if profile is None: profile = "default"
|
|
133
|
+
|
|
134
|
+
ve = get_ve_profile(P(file)) if args.ve is None else str(args.ve)
|
|
135
|
+
|
|
136
|
+
final_program = f"""
|
|
137
|
+
# deactivate
|
|
138
|
+
. activate_ve {ve}
|
|
139
|
+
{interpreter} """
|
|
140
|
+
if interpreter == "ipython": final_program += f"{interactivity} --profile {profile} --no-banner"
|
|
141
|
+
final_program += f" {str(pyfile)}"
|
|
142
|
+
print(f"🔥 sourcing ... {pyfile}")
|
|
143
|
+
PROGRAM_PATH.write_text(final_program)
|
|
144
|
+
|
|
145
|
+
# if platform.system() == "Windows":
|
|
146
|
+
# return subprocess.run([f"powershell", "-Command", res], shell=True, capture_output=False, text=True, check=True)
|
|
147
|
+
# else: return subprocess.run([res], shell=True, capture_output=False, text=True, check=True)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
build_parser()
|