abstract-utilities 0.2.2.467__py3-none-any.whl → 0.2.2.513__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.
- abstract_utilities/__init__.py +6 -10
- abstract_utilities/circular_import_finder.py +222 -0
- abstract_utilities/circular_import_finder2.py +118 -0
- abstract_utilities/class_utils/__init__.py +7 -0
- abstract_utilities/class_utils/abstract_classes.py +74 -0
- abstract_utilities/class_utils/caller_utils.py +35 -0
- abstract_utilities/class_utils/class_utils.py +109 -0
- abstract_utilities/class_utils/function_utils.py +153 -0
- abstract_utilities/class_utils/global_utils.py +56 -0
- abstract_utilities/class_utils/imports/__init__.py +2 -0
- abstract_utilities/class_utils/imports/imports.py +2 -0
- abstract_utilities/class_utils/imports/utils.py +40 -0
- abstract_utilities/class_utils/module_utils.py +63 -0
- abstract_utilities/class_utils.py +0 -1
- abstract_utilities/directory_utils/__init__.py +4 -0
- abstract_utilities/directory_utils/directory_utils.py +94 -0
- abstract_utilities/directory_utils/name_utils.py +43 -0
- abstract_utilities/directory_utils/size_utils.py +57 -0
- abstract_utilities/directory_utils/utils.py +116 -0
- abstract_utilities/env_utils/imports/imports.py +5 -3
- abstract_utilities/error_utils/__init__.py +2 -0
- abstract_utilities/error_utils/error_utils.py +25 -0
- abstract_utilities/error_utils/imports/__init__.py +2 -0
- abstract_utilities/error_utils/imports/imports.py +1 -0
- abstract_utilities/error_utils/imports/module_imports.py +1 -0
- abstract_utilities/file_utils/__init__.py +1 -2
- abstract_utilities/file_utils/file_utils/imports/__init__.py +0 -2
- abstract_utilities/file_utils/file_utils/imports/module_imports.py +2 -1
- abstract_utilities/file_utils/file_utils/type_checks.py +34 -24
- abstract_utilities/file_utils/imports/__init__.py +0 -1
- abstract_utilities/file_utils/imports/clean_imps.py +158 -0
- abstract_utilities/file_utils/imports/constants.py +6 -0
- abstract_utilities/file_utils/imports/file_functions.py +1 -1
- abstract_utilities/file_utils/imports/imports.py +20 -10
- abstract_utilities/file_utils/imports/module_imports.py +2 -7
- abstract_utilities/file_utils/module_imports.py +12 -0
- abstract_utilities/file_utils/src/__init__.py +9 -0
- abstract_utilities/file_utils/src/file_filters.py +110 -0
- abstract_utilities/file_utils/src/file_reader.py +607 -0
- abstract_utilities/file_utils/src/file_utils.py +279 -0
- abstract_utilities/file_utils/src/filter_params.py +155 -0
- abstract_utilities/file_utils/src/find_collect.py +270 -0
- abstract_utilities/file_utils/src/initFunctionsGen.py +286 -0
- abstract_utilities/file_utils/src/map_utils.py +29 -0
- abstract_utilities/file_utils/src/pdf_utils.py +300 -0
- abstract_utilities/file_utils/src/type_checks.py +91 -0
- abstract_utilities/hash_utils/__init__.py +2 -0
- abstract_utilities/hash_utils/hash_utils.py +5 -0
- abstract_utilities/hash_utils/imports/__init__.py +2 -0
- abstract_utilities/hash_utils/imports/imports.py +1 -0
- abstract_utilities/hash_utils/imports/module_imports.py +0 -0
- abstract_utilities/history_utils/__init__.py +2 -0
- abstract_utilities/history_utils/history_utils.py +37 -0
- abstract_utilities/history_utils/imports/__init__.py +2 -0
- abstract_utilities/history_utils/imports/imports.py +1 -0
- abstract_utilities/history_utils/imports/module_imports.py +0 -0
- abstract_utilities/import_utils/__init__.py +2 -0
- abstract_utilities/import_utils/imports/__init__.py +4 -0
- abstract_utilities/import_utils/imports/constants.py +2 -0
- abstract_utilities/import_utils/imports/imports.py +4 -0
- abstract_utilities/import_utils/imports/module_imports.py +6 -0
- abstract_utilities/import_utils/imports/utils.py +30 -0
- abstract_utilities/import_utils/src/__init__.py +7 -0
- abstract_utilities/import_utils/src/clean_imports.py +147 -0
- abstract_utilities/import_utils/src/dot_utils.py +69 -0
- abstract_utilities/import_utils/src/extract_utils.py +42 -0
- abstract_utilities/import_utils/src/import_functions.py +46 -0
- abstract_utilities/import_utils/src/import_utils.py +299 -0
- abstract_utilities/import_utils/src/package_utils/__init__.py +139 -0
- abstract_utilities/import_utils/src/package_utils/context_utils.py +27 -0
- abstract_utilities/import_utils/src/package_utils/import_collectors.py +53 -0
- abstract_utilities/import_utils/src/package_utils/path_utils.py +28 -0
- abstract_utilities/import_utils/src/package_utils/safe_import.py +27 -0
- abstract_utilities/import_utils/src/package_utils.py +140 -0
- abstract_utilities/import_utils/src/package_utilss/__init__.py +139 -0
- abstract_utilities/import_utils/src/package_utilss/context_utils.py +27 -0
- abstract_utilities/import_utils/src/package_utilss/import_collectors.py +53 -0
- abstract_utilities/import_utils/src/package_utilss/path_utils.py +28 -0
- abstract_utilities/import_utils/src/package_utilss/safe_import.py +27 -0
- abstract_utilities/import_utils/src/pkg_utils.py +140 -0
- abstract_utilities/import_utils/src/sysroot_utils.py +57 -0
- abstract_utilities/imports.py +18 -0
- abstract_utilities/json_utils/__init__.py +2 -0
- abstract_utilities/json_utils/imports/__init__.py +2 -0
- abstract_utilities/json_utils/imports/imports.py +2 -0
- abstract_utilities/json_utils/imports/module_imports.py +5 -0
- abstract_utilities/json_utils/json_utils.py +743 -0
- abstract_utilities/list_utils/__init__.py +2 -0
- abstract_utilities/list_utils/imports/__init__.py +2 -0
- abstract_utilities/list_utils/imports/imports.py +1 -0
- abstract_utilities/list_utils/imports/module_imports.py +0 -0
- abstract_utilities/list_utils/list_utils.py +199 -0
- abstract_utilities/log_utils/__init__.py +5 -0
- abstract_utilities/log_utils/abstractLogManager.py +64 -0
- abstract_utilities/log_utils/call_response.py +68 -0
- abstract_utilities/log_utils/imports/__init__.py +2 -0
- abstract_utilities/log_utils/imports/imports.py +7 -0
- abstract_utilities/log_utils/imports/module_imports.py +2 -0
- abstract_utilities/log_utils/log_file.py +58 -0
- abstract_utilities/log_utils/logger_callable.py +49 -0
- abstract_utilities/math_utils/__init__.py +2 -0
- abstract_utilities/math_utils/imports/__init__.py +2 -0
- abstract_utilities/math_utils/imports/imports.py +2 -0
- abstract_utilities/math_utils/imports/module_imports.py +1 -0
- abstract_utilities/math_utils/math_utils.py +208 -0
- abstract_utilities/parse_utils/__init__.py +2 -0
- abstract_utilities/parse_utils/imports/__init__.py +3 -0
- abstract_utilities/parse_utils/imports/constants.py +10 -0
- abstract_utilities/parse_utils/imports/imports.py +2 -0
- abstract_utilities/parse_utils/imports/module_imports.py +4 -0
- abstract_utilities/parse_utils/parse_utils.py +516 -0
- abstract_utilities/path_utils/__init__.py +2 -0
- abstract_utilities/path_utils/imports/__init__.py +3 -0
- abstract_utilities/path_utils/imports/imports.py +1 -0
- abstract_utilities/path_utils/imports/module_imports.py +8 -0
- abstract_utilities/path_utils/path_utils.py +251 -0
- abstract_utilities/path_utils.py +95 -14
- abstract_utilities/read_write_utils/__init__.py +1 -0
- abstract_utilities/read_write_utils/imports/__init__.py +2 -0
- abstract_utilities/read_write_utils/imports/imports.py +2 -0
- abstract_utilities/read_write_utils/imports/module_imports.py +5 -0
- abstract_utilities/read_write_utils/read_write_utils.py +338 -0
- abstract_utilities/read_write_utils.py +142 -20
- abstract_utilities/robust_reader/imports/imports.py +0 -9
- abstract_utilities/robust_readers/import_utils/__init__.py +1 -0
- abstract_utilities/robust_readers/import_utils/clean_imports.py +175 -0
- abstract_utilities/safe_utils/__init__.py +2 -0
- abstract_utilities/safe_utils/imports/__init__.py +3 -0
- abstract_utilities/safe_utils/imports/imports.py +2 -0
- abstract_utilities/safe_utils/imports/module_imports.py +2 -0
- abstract_utilities/safe_utils/safe_utils.py +136 -0
- abstract_utilities/ssh_utils/__init__.py +3 -1
- abstract_utilities/ssh_utils/classes.py +0 -1
- abstract_utilities/ssh_utils/cmd_utils.py +207 -0
- abstract_utilities/ssh_utils/imports/__init__.py +3 -0
- abstract_utilities/ssh_utils/imports/imports.py +5 -0
- abstract_utilities/ssh_utils/imports/module_imports.py +6 -0
- abstract_utilities/ssh_utils/imports/utils.py +189 -0
- abstract_utilities/ssh_utils/pexpect_utils.py +11 -18
- abstract_utilities/ssh_utils/type_checks.py +92 -0
- abstract_utilities/string_clean.py +40 -1
- abstract_utilities/string_utils/__init__.py +4 -0
- abstract_utilities/string_utils/clean_utils.py +28 -0
- abstract_utilities/string_utils/eat_utils.py +103 -0
- abstract_utilities/string_utils/imports/__init__.py +3 -0
- abstract_utilities/string_utils/imports/imports.py +2 -0
- abstract_utilities/string_utils/imports/module_imports.py +2 -0
- abstract_utilities/string_utils/imports/utils.py +81 -0
- abstract_utilities/string_utils/replace_utils.py +27 -0
- abstract_utilities/string_utils.py +39 -0
- abstract_utilities/thread_utils/__init__.py +2 -0
- abstract_utilities/thread_utils/imports/__init__.py +2 -0
- abstract_utilities/thread_utils/imports/imports.py +2 -0
- abstract_utilities/thread_utils/imports/module_imports.py +2 -0
- abstract_utilities/thread_utils/thread_utils.py +140 -0
- abstract_utilities/time_utils/__init__.py +2 -0
- abstract_utilities/time_utils/imports/__init__.py +2 -0
- abstract_utilities/time_utils/imports/imports.py +3 -0
- abstract_utilities/time_utils/imports/module_imports.py +1 -0
- abstract_utilities/time_utils/time_utils.py +392 -0
- abstract_utilities/type_utils/__init__.py +3 -0
- abstract_utilities/type_utils/alpha_utils.py +59 -0
- abstract_utilities/type_utils/imports/__init__.py +2 -0
- abstract_utilities/type_utils/imports/imports.py +4 -0
- abstract_utilities/type_utils/imports/module_imports.py +1 -0
- abstract_utilities/type_utils/num_utils.py +19 -0
- abstract_utilities/type_utils/type_utils.py +981 -0
- abstract_utilities/type_utils.py +25 -1
- {abstract_utilities-0.2.2.467.dist-info → abstract_utilities-0.2.2.513.dist-info}/METADATA +1 -1
- abstract_utilities-0.2.2.513.dist-info/RECORD +237 -0
- imports/__init__.py +36 -0
- abstract_utilities-0.2.2.467.dist-info/RECORD +0 -90
- {abstract_utilities-0.2.2.467.dist-info → abstract_utilities-0.2.2.513.dist-info}/WHEEL +0 -0
- {abstract_utilities-0.2.2.467.dist-info → abstract_utilities-0.2.2.513.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
from .imports import *
|
|
2
|
+
from .module_imports import *
|
|
3
|
+
def get_pass_from_key(key=None,env_path=None):
|
|
4
|
+
if key:
|
|
5
|
+
return get_env_value(key=key,path=env_path)
|
|
6
|
+
def get_password(password=None,key=None,env_path=None):
|
|
7
|
+
password = password or get_pass_from_key(key=key,env_path=env_path)
|
|
8
|
+
return password
|
|
9
|
+
|
|
10
|
+
def get_print_sudo_cmd(
|
|
11
|
+
cmd: str,
|
|
12
|
+
password=None,
|
|
13
|
+
key=None,
|
|
14
|
+
env_path=None
|
|
15
|
+
):
|
|
16
|
+
password = get_password(password=password,key=key,env_path=env_path)
|
|
17
|
+
if password != None:
|
|
18
|
+
|
|
19
|
+
cmd = get_password_cmd(password=password,cmd=cmd)
|
|
20
|
+
return cmd
|
|
21
|
+
def get_password_cmd(password:str,cmd:str):
|
|
22
|
+
sudo_cmd = get_sudo_cmd(cmd)
|
|
23
|
+
password_sudo_cmd = get_raw_password_sudo_cmd(password=password,sudo_cmd=sudo_cmd)
|
|
24
|
+
return password_sudo_cmd
|
|
25
|
+
def get_sudo_cmd(cmd: str):
|
|
26
|
+
return f"sudo -S -k {cmd}"
|
|
27
|
+
def get_raw_password_sudo_cmd(password:str,sudo_cmd:str):
|
|
28
|
+
return f"printf %s {shlex.quote(password)} | {sudo_cmd}"
|
|
29
|
+
def get_remote_bash(
|
|
30
|
+
cmd: str,
|
|
31
|
+
cwd: str | None = None
|
|
32
|
+
):
|
|
33
|
+
return f"bash -lc {shlex.quote((f'cd {shlex.quote(cwd)} && {cmd}') if cwd else cmd)}"
|
|
34
|
+
def get_remote_ssh(
|
|
35
|
+
user_at_host: str=None,
|
|
36
|
+
remote:str=None
|
|
37
|
+
):
|
|
38
|
+
return f"ssh {shlex.quote(user_at_host)} {shlex.quote(remote)}"
|
|
39
|
+
def get_remote_cmd(
|
|
40
|
+
cmd: str,
|
|
41
|
+
user_at_host: str,
|
|
42
|
+
cwd: str | None = None,
|
|
43
|
+
password=None,
|
|
44
|
+
key=None,
|
|
45
|
+
env_path=None
|
|
46
|
+
|
|
47
|
+
):
|
|
48
|
+
cmd = get_print_sudo_cmd(
|
|
49
|
+
cmd=cmd,
|
|
50
|
+
password=password,
|
|
51
|
+
key=key,
|
|
52
|
+
env_path=env_path
|
|
53
|
+
)
|
|
54
|
+
remote = get_remote_bash(
|
|
55
|
+
cmd=cmd,
|
|
56
|
+
cwd=cwd
|
|
57
|
+
)
|
|
58
|
+
full = get_remote_ssh(
|
|
59
|
+
user_at_host=user_at_host,
|
|
60
|
+
remote=remote
|
|
61
|
+
)
|
|
62
|
+
return full
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def execute_cmd(
|
|
66
|
+
*args,
|
|
67
|
+
outfile=None,
|
|
68
|
+
**kwargs
|
|
69
|
+
) -> str:
|
|
70
|
+
proc = subprocess.run(*args, **kwargs)
|
|
71
|
+
output = (proc.stdout or "") + (proc.stderr or "")
|
|
72
|
+
if outfile:
|
|
73
|
+
try:
|
|
74
|
+
with open(outfile, "w", encoding="utf-8", errors="ignore") as f:
|
|
75
|
+
f.write(output)
|
|
76
|
+
except Exception:
|
|
77
|
+
pass
|
|
78
|
+
return output
|
|
79
|
+
|
|
80
|
+
def run_local_cmd(
|
|
81
|
+
cmd: str,
|
|
82
|
+
cwd: str | None = None,
|
|
83
|
+
outfile: Optional[str] = None,
|
|
84
|
+
shell=True,
|
|
85
|
+
text=True,
|
|
86
|
+
capture_output=True,
|
|
87
|
+
user_at_host: str=None,
|
|
88
|
+
password=None,
|
|
89
|
+
key=None,
|
|
90
|
+
env_path=None
|
|
91
|
+
) -> str:
|
|
92
|
+
cmd = get_print_sudo_cmd(
|
|
93
|
+
cmd=cmd,
|
|
94
|
+
password=password,
|
|
95
|
+
key=key,
|
|
96
|
+
env_path=env_path
|
|
97
|
+
)
|
|
98
|
+
return execute_cmd(
|
|
99
|
+
cmd,
|
|
100
|
+
outfile=outfile,
|
|
101
|
+
shell=shell,
|
|
102
|
+
cwd=cwd,
|
|
103
|
+
text=text,
|
|
104
|
+
capture_output=capture_output
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def run_remote_cmd(
|
|
108
|
+
user_at_host: str,
|
|
109
|
+
cmd: str,
|
|
110
|
+
cwd: str | None = None,
|
|
111
|
+
outfile: Optional[str] = None,
|
|
112
|
+
shell=True,
|
|
113
|
+
text=True,
|
|
114
|
+
capture_output=True,
|
|
115
|
+
password=None,
|
|
116
|
+
key=None,
|
|
117
|
+
env_path=None
|
|
118
|
+
) -> str:
|
|
119
|
+
"""
|
|
120
|
+
Run on remote via SSH; capture stdout+stderr locally; write to local outfile.
|
|
121
|
+
NOTE: we do *not* try to write the file on the remote to avoid later scp.
|
|
122
|
+
"""
|
|
123
|
+
cmd = get_print_sudo_cmd(
|
|
124
|
+
cmd=cmd,
|
|
125
|
+
password=password,
|
|
126
|
+
key=key,
|
|
127
|
+
env_path=env_path
|
|
128
|
+
)
|
|
129
|
+
# wrap in bash -lc for PATH/profile + allow 'cd && ...'
|
|
130
|
+
cmd = get_remote_cmd(
|
|
131
|
+
cmd=cmd,
|
|
132
|
+
user_at_host=user_at_host,
|
|
133
|
+
cwd=cwd
|
|
134
|
+
)
|
|
135
|
+
return execute_cmd(
|
|
136
|
+
cmd,
|
|
137
|
+
outfile=outfile,
|
|
138
|
+
shell=shell,
|
|
139
|
+
text=text,
|
|
140
|
+
capture_output=capture_output
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
def run_cmd(
|
|
144
|
+
cmd: str=None,
|
|
145
|
+
cwd: str | None = None,
|
|
146
|
+
outfile: Optional[str] = None,
|
|
147
|
+
shell=True,
|
|
148
|
+
text=True,
|
|
149
|
+
capture_output=True,
|
|
150
|
+
user_at_host: str=None,
|
|
151
|
+
password=None,
|
|
152
|
+
key=None,
|
|
153
|
+
env_path=None
|
|
154
|
+
) -> str:
|
|
155
|
+
|
|
156
|
+
if user_at_host:
|
|
157
|
+
return run_ssh_cmd(
|
|
158
|
+
user_at_host=user_at_host,
|
|
159
|
+
cmd=cmd,
|
|
160
|
+
cwd=cwd,
|
|
161
|
+
outfile=outfile,
|
|
162
|
+
shell=shell,
|
|
163
|
+
text=text,
|
|
164
|
+
capture_output=capture_output,
|
|
165
|
+
password=password,
|
|
166
|
+
key=key,
|
|
167
|
+
env_path=env_path
|
|
168
|
+
)
|
|
169
|
+
return run_local_cmd(
|
|
170
|
+
cmd=cmd,
|
|
171
|
+
cwd=cwd,
|
|
172
|
+
outfile=outfile,
|
|
173
|
+
shell=shell,
|
|
174
|
+
text=text,
|
|
175
|
+
capture_output=capture_output,
|
|
176
|
+
password=password,
|
|
177
|
+
key=key,
|
|
178
|
+
env_path=env_path
|
|
179
|
+
)
|
|
180
|
+
run_ssh_cmd = run_remote_cmd
|
|
181
|
+
remote_cmd = run_remote_cmd
|
|
182
|
+
ssh_cmd = run_remote_cmd
|
|
183
|
+
|
|
184
|
+
local_cmd = run_local_cmd
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
run_any_cmd = run_cmd
|
|
188
|
+
any_cmd = run_cmd
|
|
189
|
+
cmd_run = run_cmd
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
from .
|
|
2
|
-
from .utils import *
|
|
3
|
-
from ..env_utils import *
|
|
1
|
+
from .imports import *
|
|
4
2
|
# pexpect is optional; import lazily if you prefer
|
|
5
3
|
|
|
6
4
|
# keep your execute_cmd; add a thin wrapper that supports stdin text cleanly
|
|
@@ -36,17 +34,17 @@ def exec_sudo_capture(
|
|
|
36
34
|
"""
|
|
37
35
|
if password is None:
|
|
38
36
|
password = get_env_value(key=key) if key else get_sudo_password()
|
|
39
|
-
|
|
37
|
+
|
|
40
38
|
sudo_cmd = f"sudo -S -k {cmd}"
|
|
41
39
|
|
|
42
40
|
if user_at_host:
|
|
43
41
|
# build the remote command (bash -lc + optional cd)
|
|
44
42
|
remote = get_remote_cmd(cmd=sudo_cmd, user_at_host=user_at_host, cwd=cwd)
|
|
45
43
|
# feed password to remote's stdin (ssh forwards stdin)
|
|
46
|
-
out = execute_cmd_input(remote, input_text=password,
|
|
44
|
+
out = execute_cmd_input(remote, input_text=password + "\n",
|
|
47
45
|
shell=True, text=True, capture_output=True)
|
|
48
46
|
else:
|
|
49
|
-
out = execute_cmd_input(sudo_cmd, input_text=password,
|
|
47
|
+
out = execute_cmd_input(sudo_cmd, input_text=password + "\n",
|
|
50
48
|
shell=True, text=True, capture_output=True, cwd=cwd)
|
|
51
49
|
|
|
52
50
|
if print_output:
|
|
@@ -123,8 +121,8 @@ def cmd_run(
|
|
|
123
121
|
out = execute_cmd(remote, shell=True, text=True, capture_output=True)
|
|
124
122
|
else:
|
|
125
123
|
out = execute_cmd(cmd, shell=True, text=True, capture_output=True, cwd=cwd)
|
|
126
|
-
|
|
127
|
-
|
|
124
|
+
if print_output:
|
|
125
|
+
print_cmd(cmd, out or "")
|
|
128
126
|
return out or ""
|
|
129
127
|
|
|
130
128
|
# ---- legacy file-backed path (unchanged in spirit) ----
|
|
@@ -150,10 +148,9 @@ def cmd_run(
|
|
|
150
148
|
if lines and lines[-1].strip() == 'END_OF_CMD':
|
|
151
149
|
break
|
|
152
150
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
## print_cmd(full_cmd, f.read().strip())
|
|
151
|
+
if print_output:
|
|
152
|
+
with open(output_text, 'r') as f:
|
|
153
|
+
print_cmd(full_cmd, f.read().strip())
|
|
157
154
|
|
|
158
155
|
try:
|
|
159
156
|
os.remove(output_text)
|
|
@@ -212,8 +209,8 @@ def exec_expect(
|
|
|
212
209
|
|
|
213
210
|
child.expect(pexpect.EOF)
|
|
214
211
|
out = child.before.decode("utf-8", errors="ignore")
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
if print_output:
|
|
213
|
+
print_cmd(command, out)
|
|
217
214
|
|
|
218
215
|
return child.exitstatus if child.exitstatus is not None else 0
|
|
219
216
|
|
|
@@ -261,7 +258,6 @@ def cmd_run_sudo(
|
|
|
261
258
|
remote_sudo_line = f'printf %s {shlex.quote(pw)} | {sudo_cmd}'
|
|
262
259
|
remote_full = get_remote_cmd(cmd=remote_sudo_line, user_at_host=user_at_host, cwd=cwd)
|
|
263
260
|
return cmd_run(remote_full, output_text=output_text, print_output=print_output)
|
|
264
|
-
|
|
265
261
|
def pexpect_cmd_with_args(
|
|
266
262
|
command: str,
|
|
267
263
|
child_runs: list,
|
|
@@ -310,6 +306,3 @@ def pexpect_cmd_with_args(
|
|
|
310
306
|
else:
|
|
311
307
|
if print_output:
|
|
312
308
|
print_cmd(command, out)
|
|
313
|
-
|
|
314
|
-
return child.exitstatus if child.exitstatus is not None else 0
|
|
315
|
-
cmd_input = execute_cmd_input
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from .imports import *
|
|
2
|
+
|
|
3
|
+
def get_user_pass_host_key(**kwargs):
|
|
4
|
+
args = ['password','user_at_host','host','key','user']
|
|
5
|
+
kwargs['del_kwarg']=kwargs.get('del_kwarg',False)
|
|
6
|
+
values,kwargs = get_from_kwargs(*args,**kwargs)
|
|
7
|
+
return values
|
|
8
|
+
|
|
9
|
+
# --- Base remote checker -----------------------------------------------------
|
|
10
|
+
def _remote_test(path: str, test_flag: str, timeout: int = 5,*args, **kwargs) -> bool:
|
|
11
|
+
"""
|
|
12
|
+
Run a remote shell test (e.g. -f, -d) via SSH.
|
|
13
|
+
Returns True if test succeeds, False otherwise.
|
|
14
|
+
"""
|
|
15
|
+
try:
|
|
16
|
+
kwargs['cmd']=f"[ {test_flag} {shlex.quote(path)} ] && echo 1 || echo 0"
|
|
17
|
+
kwargs['text']=True
|
|
18
|
+
kwargs['timeout']=timeout
|
|
19
|
+
kwargs['stderr']=subprocess.DEVNULL
|
|
20
|
+
result = run_pruned_func(run_cmd,**kwargs)
|
|
21
|
+
return result.strip() == "1"
|
|
22
|
+
except Exception:
|
|
23
|
+
return False
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
# --- Individual path checks --------------------------------------------------
|
|
27
|
+
def is_remote_file(path: str,*args, **kwargs) -> bool:
|
|
28
|
+
"""True if remote path is a file."""
|
|
29
|
+
return _remote_test(path, "-f", **kwargs)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def is_remote_dir(path: str,*args, **kwargs) -> bool:
|
|
33
|
+
"""True if remote path is a directory."""
|
|
34
|
+
return _remote_test(path, "-d", **kwargs)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def is_local_file(path: str) -> bool:
|
|
38
|
+
"""True if local path is a file."""
|
|
39
|
+
return os.path.isfile(path)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def is_local_dir(path: str) -> bool:
|
|
43
|
+
"""True if local path is a directory."""
|
|
44
|
+
return os.path.isdir(path)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
# --- Unified interface -------------------------------------------------------
|
|
48
|
+
|
|
49
|
+
def is_file(path: str,*args,**kwargs) -> bool:
|
|
50
|
+
"""Determine if path is a file (works local or remote)."""
|
|
51
|
+
if get_user_pass_host_key(**kwargs):
|
|
52
|
+
return is_remote_file(path, **kwargs)
|
|
53
|
+
return is_local_file(path)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def is_dir(path: str, *args,**kwargs) -> bool:
|
|
57
|
+
"""Determine if path is a directory (works local or remote)."""
|
|
58
|
+
if get_user_pass_host_key(**kwargs):
|
|
59
|
+
return is_remote_dir(path, **kwargs)
|
|
60
|
+
return is_local_dir(path)
|
|
61
|
+
|
|
62
|
+
def is_exists(path: str, *args,**kwargs) -> bool:
|
|
63
|
+
if is_file(path,**kwargs):
|
|
64
|
+
return True
|
|
65
|
+
if is_dir(path,**kwargs):
|
|
66
|
+
return True
|
|
67
|
+
return False
|
|
68
|
+
# --- Optional: keep your original all-in-one wrapper ------------------------
|
|
69
|
+
def check_path_type(
|
|
70
|
+
path: str,
|
|
71
|
+
*args,
|
|
72
|
+
**kwargs
|
|
73
|
+
) -> str:
|
|
74
|
+
"""
|
|
75
|
+
Return 'file', 'directory', 'missing', or 'unknown'.
|
|
76
|
+
Uses isolated is_file/is_dir functions.
|
|
77
|
+
"""
|
|
78
|
+
if get_user_pass_host_key(**kwargs):
|
|
79
|
+
if is_remote_file(path,**kwargs):
|
|
80
|
+
return "file"
|
|
81
|
+
elif is_remote_dir(path,**kwargs):
|
|
82
|
+
return "directory"
|
|
83
|
+
else:
|
|
84
|
+
return "missing"
|
|
85
|
+
else:
|
|
86
|
+
if os.path.isfile(path):
|
|
87
|
+
return "file"
|
|
88
|
+
elif os.path.isdir(path):
|
|
89
|
+
return "directory"
|
|
90
|
+
elif not os.path.exists(path):
|
|
91
|
+
return "missing"
|
|
92
|
+
return "unknown"
|
|
@@ -22,6 +22,8 @@ Date: 05/31/2023
|
|
|
22
22
|
Version: 0.1.2
|
|
23
23
|
"""
|
|
24
24
|
import os
|
|
25
|
+
from .list_utils import make_list
|
|
26
|
+
from .type_utils import get_alpha_ints
|
|
25
27
|
def quoteIt(st: str, ls: list) -> str:
|
|
26
28
|
"""
|
|
27
29
|
Quotes specific elements in a string.
|
|
@@ -110,6 +112,42 @@ def eatAll(string: str, list_objects:(str or list)) -> any:
|
|
|
110
112
|
if string and list_objects:
|
|
111
113
|
string = eatOuter(string, list_objects)
|
|
112
114
|
return string
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def eatElse(
|
|
119
|
+
stringObj,
|
|
120
|
+
chars=None,
|
|
121
|
+
ints=True,
|
|
122
|
+
alpha=True,
|
|
123
|
+
lower=True,
|
|
124
|
+
capitalize=True,
|
|
125
|
+
string=True,
|
|
126
|
+
listObj=True
|
|
127
|
+
):
|
|
128
|
+
alpha_ints = get_alpha_ints(
|
|
129
|
+
ints=True,
|
|
130
|
+
alpha=True,
|
|
131
|
+
lower=True,
|
|
132
|
+
capitalize=True,
|
|
133
|
+
string=True,
|
|
134
|
+
listObj=True
|
|
135
|
+
)
|
|
136
|
+
chars = make_list(chars or [])+alpha_ints
|
|
137
|
+
|
|
138
|
+
while True:
|
|
139
|
+
if stringObj:
|
|
140
|
+
str_0 = stringObj[0] not in chars
|
|
141
|
+
str_1 = stringObj[-1] not in chars
|
|
142
|
+
str_eat = str_0 or str_1
|
|
143
|
+
if not str_eat:
|
|
144
|
+
return stringObj
|
|
145
|
+
if stringObj and str_0:
|
|
146
|
+
stringObj = stringObj[1:] if len(stringObj) !=1 else ""
|
|
147
|
+
if stringObj and str_1:
|
|
148
|
+
stringObj = stringObj[:-1] if len(stringObj) !=1 else ""
|
|
149
|
+
else:
|
|
150
|
+
return stringObj
|
|
113
151
|
def safe_split(obj, ls):
|
|
114
152
|
"""
|
|
115
153
|
Safely splits a string using multiple delimiters.
|
|
@@ -185,6 +223,7 @@ def url_join(*paths):
|
|
|
185
223
|
final_path = f"{final_path}/{path}"
|
|
186
224
|
return final_path
|
|
187
225
|
|
|
188
|
-
|
|
226
|
+
def clean_line(line):
|
|
227
|
+
return eatAll(line,[' ','','\t','\n'])
|
|
189
228
|
def capitalize(string):
|
|
190
229
|
return string[:1].upper() + string[1:].lower() if string else string
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
from .eat_utils import eatAll
|
|
2
|
+
def clean_spaces(obj: str) -> str:
|
|
3
|
+
"""
|
|
4
|
+
Removes leading spaces and tabs from a string.
|
|
5
|
+
|
|
6
|
+
Args:
|
|
7
|
+
obj (str): The input string.
|
|
8
|
+
|
|
9
|
+
Returns:
|
|
10
|
+
str: The string with leading spaces and tabs removed.
|
|
11
|
+
"""
|
|
12
|
+
if len(obj) == 0:
|
|
13
|
+
return obj
|
|
14
|
+
while obj[0] in [' ', '\t']:
|
|
15
|
+
obj = obj[1:]
|
|
16
|
+
return obj
|
|
17
|
+
def clean_line(line):
|
|
18
|
+
return eatAll(line,[' ','','\t','\n'])
|
|
19
|
+
def url_join(*paths):
|
|
20
|
+
final_url = os.path.join(*paths)
|
|
21
|
+
for i,path in enumerate(paths):
|
|
22
|
+
if i == 0:
|
|
23
|
+
final_path = path # Note: Fixed bug; original code had `final_path = paths`
|
|
24
|
+
else:
|
|
25
|
+
final_path = eatOuter(final_path, '/')
|
|
26
|
+
path = eatInner(path, '/')
|
|
27
|
+
final_path = f"{final_path}/{path}"
|
|
28
|
+
return final_path
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
from .imports import *
|
|
2
|
+
def eatInner(string: str, list_objects:(str or list)) -> any:
|
|
3
|
+
"""
|
|
4
|
+
Removes characters from the inner part of a string or list.
|
|
5
|
+
|
|
6
|
+
Args:
|
|
7
|
+
x (str or list): The input string or list.
|
|
8
|
+
ls (list): The list of characters to remove.
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
any: The modified string or list.
|
|
12
|
+
"""
|
|
13
|
+
if not isinstance(list_objects,list):
|
|
14
|
+
list_objects = [list_objects]
|
|
15
|
+
if not isinstance(string,str):
|
|
16
|
+
string = str(string)
|
|
17
|
+
if string and list_objects:
|
|
18
|
+
for char in string:
|
|
19
|
+
if string:
|
|
20
|
+
if char not in list_objects:
|
|
21
|
+
return string
|
|
22
|
+
string = string[1:]
|
|
23
|
+
return string
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def eatOuter(string: str, list_objects:(str or list)) -> any:
|
|
27
|
+
"""
|
|
28
|
+
Removes characters from the outer part of a string or list.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
x (str or list): The input string or list.
|
|
32
|
+
ls (list): The list of characters to remove.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
any: The modified string or list.
|
|
36
|
+
"""
|
|
37
|
+
if not isinstance(list_objects,list):
|
|
38
|
+
list_objects = [list_objects]
|
|
39
|
+
if not isinstance(string,str):
|
|
40
|
+
string = str(string)
|
|
41
|
+
if string and list_objects:
|
|
42
|
+
for i in range(len(string)):
|
|
43
|
+
if string:
|
|
44
|
+
if string[-1] not in list_objects:
|
|
45
|
+
return string
|
|
46
|
+
string = string[:-1]
|
|
47
|
+
return string
|
|
48
|
+
def eatAll(string: str, list_objects:(str or list)) -> any:
|
|
49
|
+
"""
|
|
50
|
+
Removes characters from both the inner and outer parts of a string or list.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
x (str or list): The input string or list.
|
|
54
|
+
ls (list): The list of characters to remove.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
any: The modified string or list.
|
|
58
|
+
"""
|
|
59
|
+
if not isinstance(list_objects,list):
|
|
60
|
+
list_objects = [list_objects]
|
|
61
|
+
if not isinstance(string,str):
|
|
62
|
+
string = str(string)
|
|
63
|
+
if string and list_objects:
|
|
64
|
+
string = eatInner(string, list_objects)
|
|
65
|
+
if string and list_objects:
|
|
66
|
+
string = eatOuter(string, list_objects)
|
|
67
|
+
return string
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def eatElse(
|
|
72
|
+
stringObj,
|
|
73
|
+
chars=None,
|
|
74
|
+
ints=True,
|
|
75
|
+
alpha=True,
|
|
76
|
+
lower=True,
|
|
77
|
+
capitalize=True,
|
|
78
|
+
string=True,
|
|
79
|
+
listObj=True
|
|
80
|
+
):
|
|
81
|
+
alpha_ints = get_alpha_ints(
|
|
82
|
+
ints=True,
|
|
83
|
+
alpha=True,
|
|
84
|
+
lower=True,
|
|
85
|
+
capitalize=True,
|
|
86
|
+
string=True,
|
|
87
|
+
listObj=True
|
|
88
|
+
)
|
|
89
|
+
chars = make_list(chars or [])+alpha_ints
|
|
90
|
+
|
|
91
|
+
while True:
|
|
92
|
+
if stringObj:
|
|
93
|
+
str_0 = stringObj[0] not in chars
|
|
94
|
+
str_1 = stringObj[-1] not in chars
|
|
95
|
+
str_eat = str_0 or str_1
|
|
96
|
+
if not str_eat:
|
|
97
|
+
return stringObj
|
|
98
|
+
if stringObj and str_0:
|
|
99
|
+
stringObj = stringObj[1:] if len(stringObj) !=1 else ""
|
|
100
|
+
if stringObj and str_1:
|
|
101
|
+
stringObj = stringObj[:-1] if len(stringObj) !=1 else ""
|
|
102
|
+
else:
|
|
103
|
+
return stringObj
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
def quoteIt(st: str, ls: list) -> str:
|
|
2
|
+
"""
|
|
3
|
+
Quotes specific elements in a string.
|
|
4
|
+
|
|
5
|
+
Args:
|
|
6
|
+
st (str): The input string.
|
|
7
|
+
ls (list): The list of elements to quote.
|
|
8
|
+
|
|
9
|
+
Returns:
|
|
10
|
+
str: The modified string with quoted elements.
|
|
11
|
+
"""
|
|
12
|
+
lsQ = ["'", '"']
|
|
13
|
+
for i in range(len(ls)):
|
|
14
|
+
for k in range(2):
|
|
15
|
+
if lsQ[k] + ls[i] in st:
|
|
16
|
+
st = st.replace(lsQ[k] + ls[i], ls[i])
|
|
17
|
+
if ls[i] + lsQ[k] in st:
|
|
18
|
+
st = st.replace(ls[i] + lsQ[k], ls[i])
|
|
19
|
+
st = st.replace(ls[i], '"' + str(ls[i]) + '"')
|
|
20
|
+
return st
|
|
21
|
+
|
|
22
|
+
def truncate_text(text, max_chars):
|
|
23
|
+
"""
|
|
24
|
+
Truncates a text to a specified maximum number of characters, preserving the last complete sentence or word.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
text (str): The input text.
|
|
28
|
+
max_chars (int): The maximum number of characters.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
str: The truncated text.
|
|
32
|
+
"""
|
|
33
|
+
if len(text) <= max_chars:
|
|
34
|
+
return text
|
|
35
|
+
truncated = text[:max_chars]
|
|
36
|
+
# Find the last complete sentence
|
|
37
|
+
last_sentence_end = max(truncated.rfind('.'), truncated.rfind('!'), truncated.rfind('?'))
|
|
38
|
+
# If a complete sentence is found, truncate up to its end
|
|
39
|
+
if last_sentence_end != -1:
|
|
40
|
+
truncated = truncated[:last_sentence_end + 1]
|
|
41
|
+
else:
|
|
42
|
+
# If no complete sentence is found, find the last complete word
|
|
43
|
+
last_word_end = truncated.rfind(' ')
|
|
44
|
+
|
|
45
|
+
# If a complete word is found, truncate up to its end
|
|
46
|
+
if last_word_end != -1:
|
|
47
|
+
truncated = truncated[:last_word_end]
|
|
48
|
+
return truncated
|
|
49
|
+
def capitalize(string):
|
|
50
|
+
return string[:1].upper() + string[1:].lower() if string else string
|
|
51
|
+
def get_from_kwargs(*args,**kwargs):
|
|
52
|
+
del_kwarg = kwargs.get('del_kwargs',False)
|
|
53
|
+
values = {}
|
|
54
|
+
for key in args:
|
|
55
|
+
if key:
|
|
56
|
+
key = str(key)
|
|
57
|
+
if key in kwargs:
|
|
58
|
+
values[key] = kwargs.get(key)
|
|
59
|
+
if del_kwarg:
|
|
60
|
+
del kwargs[key]
|
|
61
|
+
return values,kwargs
|
|
62
|
+
def get_lines(string,strip=True):
|
|
63
|
+
lines = string.split('\n')
|
|
64
|
+
if strip:
|
|
65
|
+
lines = [line for line in lines if line]
|
|
66
|
+
return lines
|
|
67
|
+
def clean_spaces(obj: str) -> str:
|
|
68
|
+
"""
|
|
69
|
+
Removes leading spaces and tabs from a string.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
obj (str): The input string.
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
str: The string with leading spaces and tabs removed.
|
|
76
|
+
"""
|
|
77
|
+
if len(obj) == 0:
|
|
78
|
+
return obj
|
|
79
|
+
while obj[0] in [' ', '\t']:
|
|
80
|
+
obj = obj[1:]
|
|
81
|
+
return obj
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from .imports import *
|
|
2
|
+
def replace_it(string,item,rep):
|
|
3
|
+
if item in string:
|
|
4
|
+
string = string.replace(item,rep)
|
|
5
|
+
return string
|
|
6
|
+
def while_replace(string,item,rep):
|
|
7
|
+
while True:
|
|
8
|
+
string = replace_it(string,item,rep)
|
|
9
|
+
if item not in string or item in rep:
|
|
10
|
+
return string
|
|
11
|
+
def for_replace(string,item,replace):
|
|
12
|
+
replace = make_list(replace)
|
|
13
|
+
for rep in replace:
|
|
14
|
+
string = while_replace(string,item,rep)
|
|
15
|
+
return string
|
|
16
|
+
def replace_all(string,*args,**kwargs):
|
|
17
|
+
for items in args:
|
|
18
|
+
if items and isinstance(items,list):
|
|
19
|
+
item = items[0]
|
|
20
|
+
replace = items[1:] if len(items)>1 else items[-1]
|
|
21
|
+
string = for_replace(string,item,replace)
|
|
22
|
+
values,kwargs = get_from_kwargs('item','replace',**kwargs)
|
|
23
|
+
if values:
|
|
24
|
+
string = for_replace(string,**values)
|
|
25
|
+
for item,rep in kwargs.items():
|
|
26
|
+
string = for_replace(string,item,rep)
|
|
27
|
+
return string
|