machineconfig 1.8__py3-none-any.whl → 1.91__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 (56) hide show
  1. machineconfig/__init__.py +4 -2
  2. machineconfig/jobs/python/check_installations.py +8 -6
  3. machineconfig/jobs/python/checkout_version.py +27 -32
  4. machineconfig/jobs/python/create_bootable_media.py +1 -1
  5. machineconfig/jobs/python/python_cargo_build_share.py +2 -2
  6. machineconfig/jobs/python/tasks.py +2 -2
  7. machineconfig/jobs/python_custom_installers/gh.py +53 -0
  8. machineconfig/jobs/python_custom_installers/hx.py +55 -0
  9. machineconfig/profile/create.py +26 -21
  10. machineconfig/profile/create_hardlinks.py +101 -0
  11. machineconfig/profile/shell.py +5 -5
  12. machineconfig/scripts/python/choose_wezterm_theme.py +96 -0
  13. machineconfig/scripts/python/cloud_copy.py +24 -17
  14. machineconfig/scripts/python/cloud_mount.py +20 -10
  15. machineconfig/scripts/python/cloud_repo_sync.py +109 -56
  16. machineconfig/scripts/python/cloud_sync.py +73 -68
  17. machineconfig/scripts/python/croshell.py +23 -14
  18. machineconfig/scripts/python/devops.py +19 -20
  19. machineconfig/scripts/python/devops_backup_retrieve.py +19 -10
  20. machineconfig/scripts/python/devops_devapps_install.py +81 -57
  21. machineconfig/scripts/python/devops_update_repos.py +5 -5
  22. machineconfig/scripts/python/dotfile.py +4 -4
  23. machineconfig/scripts/python/fire_jobs.py +139 -66
  24. machineconfig/scripts/python/ftpx.py +17 -7
  25. machineconfig/scripts/python/gh_models.py +53 -0
  26. machineconfig/scripts/python/mount_nfs.py +1 -1
  27. machineconfig/scripts/python/mount_nw_drive.py +3 -3
  28. machineconfig/scripts/python/mount_ssh.py +2 -3
  29. machineconfig/scripts/python/pomodoro.py +1 -1
  30. machineconfig/scripts/python/repos.py +26 -23
  31. machineconfig/scripts/python/scheduler.py +1 -1
  32. machineconfig/scripts/python/start_slidev.py +10 -4
  33. machineconfig/scripts/python/start_terminals.py +6 -5
  34. machineconfig/scripts/python/wifi_conn.py +34 -42
  35. machineconfig/scripts/python/wsl_windows_transfer.py +1 -1
  36. machineconfig/setup_windows/wt_and_pwsh/set_pwsh_theme.py +1 -1
  37. machineconfig/setup_windows/wt_and_pwsh/set_wt_settings.py +3 -2
  38. machineconfig/utils/installer.py +167 -60
  39. machineconfig/utils/procs.py +2 -2
  40. machineconfig/utils/scheduling.py +3 -3
  41. machineconfig/utils/utils.py +137 -56
  42. machineconfig/utils/ve.py +171 -100
  43. machineconfig-1.91.dist-info/LICENSE +201 -0
  44. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/METADATA +31 -11
  45. machineconfig-1.91.dist-info/RECORD +69 -0
  46. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/WHEEL +1 -1
  47. machineconfig/jobs/script_installer/azure_data_studio.py +0 -22
  48. machineconfig/jobs/script_installer/bypass_paywall.py +0 -23
  49. machineconfig/jobs/script_installer/code.py +0 -34
  50. machineconfig/jobs/script_installer/docker_desktop.py +0 -41
  51. machineconfig/jobs/script_installer/ngrok.py +0 -29
  52. machineconfig/jobs/script_installer/skim.py +0 -21
  53. machineconfig/jobs/script_installer/wezterm.py +0 -34
  54. machineconfig-1.8.dist-info/RECORD +0 -70
  55. /machineconfig/jobs/{script_installer → python_custom_installers}/__init__.py +0 -0
  56. {machineconfig-1.8.dist-info → machineconfig-1.91.dist-info}/top_level.txt +0 -0
@@ -1,15 +1,16 @@
1
1
 
2
2
  """
3
3
  fire
4
- """
5
-
6
4
 
7
- from machineconfig.utils.utils import display_options, choose_one_option, PROGRAM_PATH, choose_ssh_host, match_file_name, sanitize_path
8
- # from crocodile.run import *
9
5
  # https://github.com/pallets/click combine with fire. Consider
10
6
  # https://github.com/ceccopierangiolieugenio/pyTermTk for display_options build TUI
11
7
  # https://github.com/chriskiehl/Gooey build commandline interface
12
- from crocodile.file_management import P, install_n_import
8
+
9
+ """
10
+
11
+
12
+ from machineconfig.utils.utils import display_options, choose_one_option, PROGRAM_PATH, choose_ssh_host, match_file_name, sanitize_path
13
+ from crocodile.file_management import P, install_n_import, Read
13
14
  from crocodile.core import Display, randstr
14
15
  import inspect
15
16
  import platform
@@ -18,49 +19,64 @@ from typing import Callable, Any, Optional
18
19
  import argparse
19
20
 
20
21
 
22
+ def search_for_files_of_interest(path_obj: P):
23
+ if path_obj.joinpath(".venv").exists():
24
+ path_objects = path_obj.search("*", not_in=[".venv"]).list
25
+ files: list[P] = []
26
+ for a_path_obj in path_objects:
27
+ files += search_for_files_of_interest(path_obj=a_path_obj)
28
+ return files
29
+ py_files = path_obj.search(pattern="*.py", not_in=["__init__.py"], r=True).list
30
+ ps_files = path_obj.search(pattern="*.ps1", r=True).list
31
+ sh_files = path_obj.search(pattern="*.sh", r=True).list
32
+ files = py_files + ps_files + sh_files
33
+ return files
34
+
35
+
36
+ str2obj = {"True": True, "False": False, "None": None}
37
+
38
+
21
39
  def main() -> None:
22
40
  parser = argparse.ArgumentParser()
23
- parser.add_argument("path", nargs='?', type=str, help="The directory containing the jobs", default=".")
41
+ parser.add_argument("path", nargs='?', type=str, help="The directory containing the jobs", default=".")
24
42
  parser.add_argument("function", nargs='?', type=str, help="Fuction to run", default=None)
25
43
  # parser.add_argument("--function", "-f", type=str, help="The function to run", default="")
26
- parser.add_argument("--ve", "-v", type=str, help="virtual enviroment name", default="")
27
- parser.add_argument("--cmd", "-B", action="store_true", help="Create a cmd fire command to launch the the job asynchronously.")
28
- parser.add_argument("--interactive", "-i", action="store_true", help="Whether to run the job interactively using IPython")
29
- parser.add_argument("--debug", "-d", action="store_true", help="debug")
44
+ parser.add_argument("--ve", "-v", type=str, help="virtual enviroment name", default="")
45
+ parser.add_argument("--cmd", "-B", action="store_true", help="Create a cmd fire command to launch the the job asynchronously.")
46
+ parser.add_argument("--interactive", "-i", action="store_true", help="Whether to run the job interactively using IPython")
47
+ parser.add_argument("--debug", "-d", action="store_true", help="debug")
30
48
  parser.add_argument("--choose_function", "-c", action="store_true", help="debug")
31
- parser.add_argument("--loop", "-l", action="store_true", help="infinite recusion (runs again after completion)")
32
- parser.add_argument("--jupyter", "-j", action="store_true", help="open in a jupyter notebook")
49
+ parser.add_argument("--loop", "-l", action="store_true", help="infinite recusion (runs again after completion)")
50
+ parser.add_argument("--jupyter", "-j", action="store_true", help="open in a jupyter notebook")
33
51
  parser.add_argument("--submit_to_cloud", "-C", action="store_true", help="submit to cloud compute")
34
- parser.add_argument("--remote", "-r", action="store_true", help="launch on a remote machine")
35
- parser.add_argument("--module", "-m", action="store_true", help="launch the main file")
36
- parser.add_argument("--streamlit", "-S", action="store_true", help="run as streamlit app")
37
- parser.add_argument("--history", "-H", action="store_true", help="choose from history")
52
+ parser.add_argument("--remote", "-r", action="store_true", help="launch on a remote machine")
53
+ parser.add_argument("--module", "-m", action="store_true", help="launch the main file")
54
+ parser.add_argument("--streamlit", "-S", action="store_true", help="run as streamlit app")
55
+ parser.add_argument("--history", "-H", action="store_true", help="choose from history")
56
+ # parser.add_argument("--git_pull", "-g", action="store_true", help="Start by pulling the git repo")
57
+ parser.add_argument("--optimized", "-O", action="store_true", help="Run the optimized version of the function")
58
+ parser.add_argument("--Nprocess", "-p", type=int, help="Number of processes to use", default=1)
38
59
  parser.add_argument("--kw", nargs="*", default=None, help="keyword arguments to pass to the function in the form of k1 v1 k2 v2 ...")
39
60
 
40
61
  args = parser.parse_args()
41
62
  if args.kw is not None:
42
63
  assert len(args.kw) % 2 == 0, f"args.kw must be a list of even length. Got {len(args.kw)}"
43
64
  kwargs = dict(zip(args.kw[::2], args.kw[1::2]))
65
+ for key, value in kwargs.items():
66
+ if value in str2obj:
67
+ kwargs[key] = str2obj[value]
44
68
  # print(f"kwargs = {kwargs}")
45
69
  else:
46
70
  kwargs = {}
47
71
 
48
72
  path_obj = sanitize_path(P(args.path))
49
73
  if not path_obj.exists():
50
- print("This pathway")
51
- path_obj = match_file_name(args.path)
52
- print(path_obj)
53
- else:
54
- print("This directory")
55
- print(path_obj)
74
+ path_obj = match_file_name(sub_string=args.path)
75
+ else: pass
56
76
 
57
77
  if path_obj.is_dir():
58
78
  print(f"Seaching recursively for all python file in directory `{path_obj}`")
59
- py_files = path_obj.search(pattern="*.py", not_in=["__init__.py"], r=True).list
60
- ps_files = path_obj.search(pattern="*.ps1", r=True).list
61
- sh_files = path_obj.search(pattern="*.sh", r=True).list
62
- files = py_files + ps_files + sh_files
63
-
79
+ files = search_for_files_of_interest(path_obj)
64
80
  choice_file = choose_one_option(options=files, fzf=True)
65
81
  choice_file = P(choice_file)
66
82
  else:
@@ -68,10 +84,9 @@ def main() -> None:
68
84
 
69
85
  if choice_file.suffix in [".ps1", ".sh"]:
70
86
  PROGRAM_PATH.write_text(f". {choice_file}")
71
- return
87
+ return None
72
88
 
73
89
  if args.choose_function or args.submit_to_cloud:
74
-
75
90
  options, func_args = parse_pyfile(file_path=str(choice_file))
76
91
  choice_function_tmp = display_options(msg="Choose a function to run", options=options, fzf=True, multi=False)
77
92
  assert isinstance(choice_function_tmp, str), f"choice_function must be a string. Got {type(choice_function_tmp)}"
@@ -83,13 +98,28 @@ def main() -> None:
83
98
  if len(choice_function_args) > 0 and len(kwargs) == 0:
84
99
  for item in choice_function_args:
85
100
  kwargs[item.name] = input(f"Please enter a value for argument `{item.name}` (type = {item.type}) (default = {item.default}) : ") or item.default
86
- else: choice_function = args.function
101
+ else:
102
+ choice_function = args.function
87
103
 
88
104
  if args.ve == "":
89
105
  from machineconfig.utils.ve import get_ve_profile # if file name is passed explicitly, then, user probably launched it from cwd different to repo root, so activate_ve can't infer ve from .ve_path, so we attempt to do that manually here
90
106
  args.ve = get_ve_profile(choice_file)
91
107
 
92
- if args.streamlit: exe = "streamlit run --server.address 0.0.0.0 "
108
+ if args.streamlit:
109
+ from crocodile.environment import get_network_addresses
110
+ local_ip_v4 = get_network_addresses()["local_ip_v4"]
111
+ computer_name = platform.node()
112
+ port = 8501
113
+ if choice_file.parent.joinpath(".streamlit/config.toml").exists():
114
+ config = Read.toml(choice_file.parent.joinpath(".streamlit/config.toml"))
115
+ if "server" in config:
116
+ if "port" in config["server"]:
117
+ port = config["server"]["port"]
118
+ message = f"🚀 Streamlit app is running @:\n1- http://{local_ip_v4}:{port}\n2- http://{computer_name}:{port}\n3- http://localhost:{port}"
119
+ from rich.panel import Panel
120
+ from rich import print as rprint
121
+ rprint(Panel(message))
122
+ exe = "streamlit run --server.address 0.0.0.0 --server.headless true"
93
123
  elif args.interactive is False: exe = "python"
94
124
  elif args.jupyter: exe = "jupyter-lab"
95
125
  else:
@@ -97,12 +127,13 @@ def main() -> None:
97
127
  exe = f"ipython -i --no-banner --profile {get_ipython_profile(choice_file)} "
98
128
 
99
129
  if args.module or (args.debug and args.choose_function): # because debugging tools do not support choosing functions and don't interplay with fire module. So the only way to have debugging and choose function options is to import the file as a module into a new script and run the function of interest there and debug the new script.
100
- txt: str = f"""
130
+ import_line = get_import_module_code(str(choice_file))
131
+ txt: str=f"""
101
132
  try:
102
- {get_import_module_code(str(choice_file))}
133
+ {import_line}
103
134
  except (ImportError, ModuleNotFoundError) as ex:
104
- print(fr"Failed to import {choice_file} the proper way. {{ex}} ")
105
- print(fr"The way below is rather hacky and can cause issues in pickling.")
135
+ print(fr"Failed to import `{choice_file}` the proper way. {{ex}} ")
136
+ print(fr"Importing with an ad-hoc `$PATH` manipulation. DO NOT pickle any files in this session as there is no gaurantee of correct deserialization.")
106
137
  import sys
107
138
  sys.path.append(r'{P(choice_file).parent}')
108
139
  from {P(choice_file).stem} import *
@@ -110,11 +141,17 @@ except (ImportError, ModuleNotFoundError) as ex:
110
141
  """
111
142
  if choice_function is not None:
112
143
  txt = txt + f"""
113
- {choice_function}({('**' + str(kwargs)) if kwargs else ''})
144
+ res = {choice_function}({('**' + str(kwargs)) if kwargs else ''})
114
145
  """
115
146
  txt = f"""
116
- from machineconfig.utils.utils import print_code
117
- print_code(code=r'''{txt}''', lexer='python', desc='Import Script')
147
+ try:
148
+ from rich.panel import Panel
149
+ from rich.console import Console
150
+ from rich.syntax import Syntax
151
+ console = Console()
152
+ console.print(Panel(Syntax(code=r'''{txt}''', lexer='python'), title='Import Script'), style="bold red")
153
+ except ImportError as _ex:
154
+ print(r'''{txt}''')
118
155
  """ + txt
119
156
  choice_file = P.tmp().joinpath(f'tmp_scripts/python/{P(choice_file).parent.name}_{P(choice_file).stem}_{randstr()}.py').create(parents_only=True).write_text(txt)
120
157
 
@@ -131,15 +168,19 @@ print_code(code=r'''{txt}''', lexer='python', desc='Import Script')
131
168
  if not kwargs: # empty dict
132
169
  kwargs_str = ''
133
170
  else:
134
- tmp_list: list[str] = []
135
- for k, v in kwargs.items():
136
- if v is not None:
137
- item = f'"{k}": "{v}"'
138
- else:
139
- item = f'"{k}": None'
140
- tmp_list.append(item)
141
- tmp__ = ", ".join(tmp_list)
142
- kwargs_str = "'{" + tmp__ + "}'"
171
+ if len(kwargs) == 1:
172
+ kwargs_str = f""" --{list(kwargs.keys())[0]} {list(kwargs.values())[0]} """
173
+ else:
174
+ # print(f"len(kwargs) = {len(kwargs)}")
175
+ tmp_list: list[str] = []
176
+ for k, v in kwargs.items():
177
+ if v is not None:
178
+ item = f'"{k}": "{v}"'
179
+ else:
180
+ item = f'"{k}": None'
181
+ tmp_list.append(item)
182
+ tmp__ = ", ".join(tmp_list)
183
+ kwargs_str = "'{" + tmp__ + "}'"
143
184
  command = f"{exe} -m fire {choice_file} {choice_function} {kwargs_str}"
144
185
  # else:
145
186
  # print(f"{kwargs=}")
@@ -152,19 +193,22 @@ print_code(code=r'''{txt}''', lexer='python', desc='Import Script')
152
193
  else:
153
194
  if not args.cmd:
154
195
  # for .streamlit config to work, it needs to be in the current directory.
155
- command = f"cd {choice_file.parent}; {exe} {choice_file.name}; cd {P.cwd()}"
196
+ command = f"cd {choice_file.parent}\n\n{exe} {choice_file.name}\n\ncd {P.cwd()}"
156
197
  else:
157
198
  command = rf""" cd /d {choice_file.parent} & {exe} {choice_file.name} """
158
- # command = f"cd {choice_file.parent}; {exe} {choice_file.name}; cd {P.cwd()}"
199
+ # command = f"cd {choice_file.parent}\n\n{exe} {choice_file.name}\n\ncd {P.cwd()}"
159
200
 
160
201
  # this installs in ve env, which is not execution env
161
202
  # if "ipdb" in command: install_n_import("ipdb")
162
203
  # if "pudb" in command: install_n_import("pudb")
163
204
 
164
205
  if not args.cmd:
165
- if "ipdb" in command: command = f"pip install ipdb; {command}"
166
- if "pudb" in command: command = f"pip install pudb; {command}"
167
- command = f". activate_ve {args.ve}; {command}"
206
+ if "ipdb" in command: command = f"pip install ipdb\n\n{command}"
207
+ if "pudb" in command: command = f"pip install pudb\n\n{command}"
208
+ if platform.system() == "Windows":
209
+ command = f". $HOME/scripts/activate_ve {args.ve}\n\n{command}"
210
+ else:
211
+ command = f". $HOME/scripts/activate_ve {args.ve}\n\n{command}"
168
212
  else:
169
213
  # CMD equivalent
170
214
  if "ipdb" in command: command = f"pip install ipdb & {command}"
@@ -174,19 +218,40 @@ print_code(code=r'''{txt}''', lexer='python', desc='Import Script')
174
218
 
175
219
  if args.submit_to_cloud:
176
220
  command = f"""
177
- . activate_ve {args.ve}
221
+ . $HOME/scripts/activate_ve {args.ve}
178
222
  python -m crocodile.cluster.templates.cli_click --file {choice_file} """
179
223
  if choice_function is not None: command += f"--function {choice_function} "
180
224
  try: install_n_import("clipboard").copy(command)
181
225
  except Exception as ex: print(f"Failed to copy command to clipboard. {ex}")
182
226
 
183
227
  if args.loop:
184
- command = command + f"\n" + f". {PROGRAM_PATH}"
228
+ command = command + "\n" + f". {PROGRAM_PATH}"
229
+
230
+ if args.Nprocess > 1:
231
+ lines = [f""" zellij action new-tab --name nProcess{randstr(2)}"""]
232
+ command = command.replace(". activate_ve", ". $HOME/scripts/activate_ve")
233
+ for an_arg in range(args.Nprocess):
234
+ sub_command = f"{command} --idx={an_arg} --idx_max={args.Nprocess}"
235
+ if args.optimized:
236
+ sub_command = sub_command.replace("python ", "python -OO ")
237
+ sub_command_path = P.tmpfile(suffix=".sh").write_text(sub_command)
238
+ lines.append(f"""zellij action new-pane -- bash {sub_command_path} """)
239
+ lines.append("sleep 1") # python tends to freeze if you launch instances within 1 microsecond of each other
240
+ command = "\n".join(lines)
185
241
 
186
242
  # TODO: send this command to terminal history. In powershell & bash there is no way to do it with a command other than goiing to history file. In Mcfly there is a way but its linux only tool. # if platform.system() == "Windows": command = f" ({command}) | Add-History -PassThru "
187
- print(f"🔥 command:\n{command}\n\n")
243
+ # mcfly add --exit 0 command
244
+ if args.optimized:
245
+ # note that in ipython, optimization is meaningless.
246
+ command = command.replace("python ", "python -OO ")
188
247
  # if platform.system() == "Linux":
189
248
  # command = "timeout 1s aafire -driver slang\nclear\n" + command
249
+
250
+ from rich.panel import Panel
251
+ from rich.console import Console
252
+ from rich.syntax import Syntax
253
+ console = Console()
254
+ console.print(Panel(Syntax(command, lexer="shell"), title=f"🔥 fire command @ {PROGRAM_PATH}: "), style="bold red")
190
255
  PROGRAM_PATH.write_text(command)
191
256
 
192
257
 
@@ -235,11 +300,11 @@ def parse_pyfile(file_path: str):
235
300
  return options, func_args
236
301
 
237
302
 
238
- def get_attrs(obj: Any):
303
+ def get_attrs_recursively(obj: Any):
239
304
  if hasattr(obj, '__dict__'):
240
305
  res = {}
241
306
  for k, v in obj.__dict__.items():
242
- res[k] = get_attrs(v)
307
+ res[k] = get_attrs_recursively(v)
243
308
  return res
244
309
  return obj
245
310
 
@@ -258,7 +323,8 @@ def interactively_run_function(func: Callable[[Any], Any]):
258
323
  if value == "": value = default
259
324
  else: value = input(f"Please enter a value for argument `{param.name}` (type = {hint}) : ")
260
325
  try:
261
- if param.annotation is not inspect.Parameter.empty: value = param.annotation(value)
326
+ if param.annotation is not inspect.Parameter.empty:
327
+ value = param.annotation
262
328
  except (TypeError, ValueError) as err:
263
329
  raise ValueError(f"Invalid input: {value} is not of type {param.annotation}") from err
264
330
  if param.kind == inspect.Parameter.KEYWORD_ONLY: kwargs[param.name] = value
@@ -281,25 +347,32 @@ def run_on_remote(func_file: str, args: argparse.Namespace):
281
347
  m.run()
282
348
 
283
349
 
284
- def find_root_path(start_path: str):
350
+ def find_repo_root_path(start_path: str) -> Optional[str]:
285
351
  root_files = ['setup.py', 'pyproject.toml', '.git']
286
- path = start_path
287
- while path != '/':
352
+ path: str=start_path
353
+ trials = 0
354
+ root_path = os.path.abspath(os.sep)
355
+ while path != root_path and trials < 20:
288
356
  for root_file in root_files:
289
357
  if os.path.exists(os.path.join(path, root_file)):
358
+ print(f"Found repo root path: {path}")
290
359
  return path
291
360
  path = os.path.dirname(path)
361
+ trials += 1
292
362
  return None
293
363
 
294
364
 
295
365
  def get_import_module_code(module_path: str):
296
- root_path = find_root_path(module_path)
366
+ root_path = find_repo_root_path(module_path)
297
367
  if root_path is None: # just make a desperate attempt to import it
298
368
  module_name = module_path.lstrip(os.sep).replace(os.sep, '.').replace('.py', '')
299
- return f"from {module_path} import *"
300
- relative_path = module_path.replace(root_path, '')
301
- module_name = relative_path.lstrip(os.sep).replace(os.sep, '.').replace('.py', '')
302
- module_name = module_name.replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("resources.", "").replace("source.", "")
369
+ else:
370
+ relative_path = module_path.replace(root_path, '')
371
+ module_name = relative_path.lstrip(os.sep).replace(os.sep, '.').replace('.py', '')
372
+ module_name = module_name.replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("myresources.", "").replace("resources.", "").replace("source.", "").replace("src.", "").replace("resources.", "").replace("source.", "")
373
+ if any(char in module_name for char in "- :/\\"):
374
+ module_name = "IncorrectModuleName"
375
+ # TODO: use py_compile to check if the statement is valid code to avoid syntax errors that can't be caught.
303
376
  return f"from {module_name} import *"
304
377
 
305
378
 
@@ -3,6 +3,7 @@
3
3
 
4
4
  TODO: add support for cases in which source or target has non 22 default port number and is defineda as user@host:port:path which makes 2 colons in the string.
5
5
  Currently, the only way to work around this is to predifine the host in ~/.ssh/config and use the alias in the source or target which is inconvenient when dealing with newly setup machines.
6
+
6
7
  """
7
8
 
8
9
  import argparse
@@ -19,6 +20,7 @@ def main():
19
20
  # FLAGS
20
21
  parser.add_argument("--recursive", "-r", help="Send recursively.", action="store_true") # default is False
21
22
  parser.add_argument("--zipFirst", "-z", help="Zip before sending.", action="store_true") # default is False
23
+ parser.add_argument("--cloud", "-c", help="Transfer through the cloud.", action="store_true") # default is False
22
24
 
23
25
  args = parser.parse_args()
24
26
 
@@ -54,6 +56,7 @@ def main():
54
56
  raise ValueError("Either source or target must be a remote path (i.e. machine:path)")
55
57
 
56
58
  Struct({"source": str(source), "target": str(target), "machine": machine}).print(as_config=True, title="CLI Resolution")
59
+
57
60
  from paramiko.ssh_exception import AuthenticationException # type: ignore
58
61
  try:
59
62
  ssh = SSH(rf'{machine}')
@@ -64,14 +67,21 @@ def main():
64
67
  pwd = getpass.getpass()
65
68
  ssh = SSH(rf'{machine}', pwd=pwd)
66
69
 
67
- if source_is_remote:
68
- assert source is not None, "source must be a remote path (i.e. machine:path)"
69
- print(f"Running: received_file = ssh.copy_to_here(source={source}, target={target}, z={args.zipFirst}, r={args.recursive})")
70
- received_file = ssh.copy_to_here(source=source, target=target, z=args.zipFirst, r=args.recursive)
70
+ if args.cloud:
71
+ print("Uploading from remote to cloud ...")
72
+ ssh.run(f"cloud_copy {source} :^", desc="Uploading from remote to the cloud.").print()
73
+ print("Downloading from cloud to local ...")
74
+ ssh.run_locally(f"cloud_copy :^ {target}").print()
75
+ received_file = P(target) # type: ignore
71
76
  else:
72
- assert source is not None, "target must be a remote path (i.e. machine:path)"
73
- print(f"Running: received_file = ssh.copy_from_here(source={source}, target={target}, z={args.zipFirst}, r={args.recursive})")
74
- received_file = ssh.copy_from_here(source=source, target=target, z=args.zipFirst, r=args.recursive)
77
+ if source_is_remote:
78
+ assert source is not None, "source must be a remote path (i.e. machine:path)"
79
+ print(f"Running: received_file = ssh.copy_to_here(source=r'{source}', target=r'{target}', z={args.zipFirst}, r={args.recursive})")
80
+ received_file = ssh.copy_to_here(source=source, target=target, z=args.zipFirst, r=args.recursive)
81
+ else:
82
+ assert source is not None, "target must be a remote path (i.e. machine:path)"
83
+ print(f"Running: received_file = ssh.copy_from_here(source=r'{source}', target=r'{target}', z={args.zipFirst}, r={args.recursive})")
84
+ received_file = ssh.copy_from_here(source=source, target=target, z=args.zipFirst, r=args.recursive)
75
85
  # ssh.print_summary()
76
86
  # if P(args.file).is_dir(): print(f"Use: cd {repr(P(args.file).expanduser())}")
77
87
  if source_is_remote and isinstance(received_file, P):
@@ -0,0 +1,53 @@
1
+
2
+ # as per https://github.com/marketplace/models/azure-openai/o1-preview
3
+ from openai import OpenAI
4
+ from crocodile.file_management import Read, P
5
+
6
+
7
+ gh_token = Read.ini(P.home().joinpath("dotfiles/creds/git/git_host_tokens.ini"))['thisismygitrepo']['newLongterm']
8
+ endpoint = "https://models.inference.ai.azure.com"
9
+ model_name_preferences = ["o1-preview", "o1-mini", "GPT-4o", "GPT-4-o-mini"]
10
+ client__ = OpenAI(
11
+ base_url=endpoint,
12
+ api_key=gh_token,
13
+ )
14
+
15
+ def get_response(client, model_name, messages):
16
+ try:
17
+ response = client.chat.completions.create(
18
+ messages=messages,
19
+ model=model_name
20
+ )
21
+ return response.choices
22
+ except Exception as e:
23
+ print(f"Error with model {model_name}: {e}")
24
+ return None
25
+
26
+
27
+ def interactive_chat():
28
+ conversation_history = []
29
+ model_index = 0
30
+ model_name = model_name_preferences[model_index]
31
+ while True:
32
+ print(f"Using model {model_name}".center(80, "="))
33
+ while True:
34
+ user_input = input("You: ")
35
+ conversation_history.append({"role": "user", "content": user_input})
36
+
37
+ while True:
38
+ choices = get_response(client__, model_name, conversation_history)
39
+ if choices is None:
40
+ model_index += 1
41
+ model_name = model_name_preferences[model_index % len(model_name_preferences)]
42
+ print(f"Switching to model {model_name}".center(80, "="))
43
+ continue
44
+ else:
45
+ break
46
+
47
+ for a_choice in choices:
48
+ response_content = a_choice.message.content
49
+ print("\n" * 5)
50
+ print(f"AI: {response_content}")
51
+ conversation_history.append({"role": "assistant", "content": response_content})
52
+
53
+ interactive_chat()
@@ -11,7 +11,7 @@ import platform
11
11
 
12
12
 
13
13
  def main():
14
- print(f"Mounting NFS Share ... ")
14
+ print("Mounting NFS Share ... ")
15
15
  share_info = input("share path? (e.g. machine:~/data/share_nfs) [press enter for interactive choice] = ")
16
16
  if share_info == "":
17
17
  tmp = choose_ssh_host(multi=False)
@@ -6,15 +6,15 @@ import platform
6
6
 
7
7
 
8
8
  def main():
9
- print(f"Welcome to the WindowsNetworkDrive Mounting Wizard")
9
+ print("Welcome to the WindowsNetworkDrive Mounting Wizard")
10
10
  drive_location = input("Enter the network drive location (ex: //192.168.1.100/Share): ")
11
11
  machine_name = drive_location.split("//")[1].split("/")[0]
12
12
  mount_point = input(f"Enter the mount point directory (ex: /mnt/network) [default: ~/data/mount_nw/{machine_name}]: ")
13
13
  if mount_point == "": mount_point = P.home().joinpath(fr"data/mount_nw/{machine_name}")
14
14
  else: mount_point = P(mount_point).expanduser()
15
15
 
16
- username = input(f"Enter the username: ")
17
- password = input(f"Enter the password: ")
16
+ username = input("Enter the username: ")
17
+ password = input("Enter the password: ")
18
18
  if platform.system() == "Linux":
19
19
  PROGRAM_PATH.write_text(f"""
20
20
  drive_location='{drive_location}'
@@ -11,8 +11,7 @@ from machineconfig.utils.utils import PROGRAM_PATH, choose_ssh_host
11
11
 
12
12
 
13
13
  def main():
14
-
15
- print(f"Mounting SSHFS ... ")
14
+ print("Mounting SSHFS ... ")
16
15
  share_info = input("share path? (e.g. user@host:/path) [press enter for interactive choice] = ")
17
16
  if share_info == "":
18
17
  tmp = choose_ssh_host(multi=False)
@@ -28,7 +27,7 @@ def main():
28
27
  if mount_point == "": mount_point = P.home().joinpath(fr"data/mount_ssh/{ssh.hostname}")
29
28
 
30
29
  if system() == "Linux":
31
- txt = fr"""
30
+ txt = """
32
31
  sshfs alex@:/media/dbhdd /media/dbhdd\
33
32
  """
34
33
  elif system() == "Windows":
@@ -16,7 +16,7 @@ def pomodoro(work: int = 25, rest: int = 5, repeats: int = 4):
16
16
  while (diff := rest - ((datetime.now() - start).seconds / 60)) > 0: logger.critical(f"Keep Resting. Time Left: {round(diff)} minutes"); time.sleep(60 * 1)
17
17
  def speak(txt: str):
18
18
  install_n_import("gtts").gTTS(txt, lang='en', tld='com.au').save(tmp := P.tmpfile(suffix=".mp3")); time.sleep(0.5)
19
- pyglet = install_n_import("pyglet"); pyglet.resource.path = [tmp.parent.str]; pyglet.resource.reindex(); pyglet.resource.media(tmp.name).play()
19
+ pyglet = install_n_import("pyglet"); pyglet.resource.path = [tmp.parent.to_str()]; pyglet.resource.reindex(); pyglet.resource.media(tmp.name).play()
20
20
  def beep(duration: int = 1, frequency: int = 3000):
21
21
  try: import winsound
22
22
  except ImportError: __import__("os").system(f'beep -f {frequency} -l {1000 * duration}')