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,175 @@
|
|
|
1
|
+
from ...read_write_utils import read_from_file,write_to_file
|
|
2
|
+
from ...string_clean import eatAll,eatElse,clean_line
|
|
3
|
+
from ...class_utils import get_caller_path
|
|
4
|
+
from ...list_utils import make_list
|
|
5
|
+
import os
|
|
6
|
+
import_tag = 'import '
|
|
7
|
+
from_tag = 'from '
|
|
8
|
+
def get_text_or_read(text=None,file_path=None):
|
|
9
|
+
text = text or ''
|
|
10
|
+
imports_js = {}
|
|
11
|
+
if not text and file_path and os.path.isfile(file_path):
|
|
12
|
+
text=read_from_file(file_path)
|
|
13
|
+
return text
|
|
14
|
+
def is_line_import(line):
|
|
15
|
+
if line and (line.startswith(from_tag) or line.startswith(import_tag)):
|
|
16
|
+
return True
|
|
17
|
+
return False
|
|
18
|
+
def is_line_group_import(line):
|
|
19
|
+
if line and (line.startswith(from_tag) and import_tag in line):
|
|
20
|
+
return True
|
|
21
|
+
return False
|
|
22
|
+
def get_import_pkg(line):
|
|
23
|
+
if is_line_group_import(line):
|
|
24
|
+
return clean_line(line.split(from_tag)[1].split(import_tag)[0])
|
|
25
|
+
def get_imports_from_import_pkg(line):
|
|
26
|
+
if is_line_group_import(line):
|
|
27
|
+
return get_cleaned_import_list(line,commaClean=True)
|
|
28
|
+
|
|
29
|
+
def add_imports_to_import_pkg_js(import_pkg,imports,import_pkg_js=None):
|
|
30
|
+
import_pkg_js = import_pkg_js or {}
|
|
31
|
+
imports = clean_imports(imports)
|
|
32
|
+
if import_pkg not in import_pkg_js:
|
|
33
|
+
i = len(import_pkg_js["nulines"])
|
|
34
|
+
import_pkg_js[import_pkg]={"imports":imports,"line":i}
|
|
35
|
+
import_line = f"from {import_pkg} import "
|
|
36
|
+
if import_pkg == "import":
|
|
37
|
+
import_line = import_tag
|
|
38
|
+
import_pkg_js["nulines"].append(import_line)
|
|
39
|
+
else:
|
|
40
|
+
import_pkg_js[import_pkg]["imports"]+=imports
|
|
41
|
+
return import_pkg_js
|
|
42
|
+
def update_import_pkg_js(line,import_pkg_js=None):
|
|
43
|
+
import_pkg_js = import_pkg_js or {}
|
|
44
|
+
if is_line_group_import(line):
|
|
45
|
+
import_pkg = get_import_pkg(line)
|
|
46
|
+
imports = get_imports_from_import_pkg(line)
|
|
47
|
+
import_pkg_js = add_imports_to_import_pkg_js(import_pkg,imports,import_pkg_js=import_pkg_js)
|
|
48
|
+
else:
|
|
49
|
+
if len(import_pkg_js["nulines"]) >0 and line == '' and is_line_import(import_pkg_js["nulines"][-1]):
|
|
50
|
+
pass
|
|
51
|
+
else:
|
|
52
|
+
import_pkg_js["nulines"].append(line)
|
|
53
|
+
return import_pkg_js
|
|
54
|
+
def is_from_line_group(line):
|
|
55
|
+
if line and line.startswith(from_tag) and import_tag in line and '(' in line:
|
|
56
|
+
import_spl = line.split(import_tag)[-1]
|
|
57
|
+
import_spl_clean = clean_line(line)
|
|
58
|
+
if not import_spl_clean.endswith(')'):
|
|
59
|
+
return True
|
|
60
|
+
return False
|
|
61
|
+
def clean_imports(imports,commaClean=True):
|
|
62
|
+
chars=["*"]
|
|
63
|
+
if not commaClean:
|
|
64
|
+
chars.append(',')
|
|
65
|
+
if isinstance(imports,str):
|
|
66
|
+
imports = imports.split(',')
|
|
67
|
+
return [eatElse(imp,chars=chars) for imp in imports if imp]
|
|
68
|
+
def get_cleaned_import_list(line,commaClean=True):
|
|
69
|
+
cleaned_import_list=[]
|
|
70
|
+
if import_tag in line:
|
|
71
|
+
imports = line.split(import_tag)[1]
|
|
72
|
+
cleaned_import_list+=clean_imports(imports,commaClean=commaClean)
|
|
73
|
+
return cleaned_import_list
|
|
74
|
+
def get_all_imports(text=None,file_path=None,import_pkg_js=None):
|
|
75
|
+
text = get_text_or_read(text=text,file_path=file_path)
|
|
76
|
+
lines = text.split('\n')
|
|
77
|
+
cleaned_import_list=[]
|
|
78
|
+
nu_lines = []
|
|
79
|
+
is_from_group = False
|
|
80
|
+
import_pkg_js = import_pkg_js or {}
|
|
81
|
+
if "nulines" not in import_pkg_js:
|
|
82
|
+
import_pkg_js["nulines"]=[]
|
|
83
|
+
if "file_path" not in import_pkg_js:
|
|
84
|
+
import_pkg_js["file_path"]=file_path
|
|
85
|
+
if "all_data" not in import_pkg_js:
|
|
86
|
+
import_pkg_js["all_data"]=[]
|
|
87
|
+
if file_path and file_path != import_pkg_js["file_path"]:
|
|
88
|
+
found=False
|
|
89
|
+
nu_data = {"file_path":import_pkg_js["file_path"],"nulines":import_pkg_js["nulines"]}
|
|
90
|
+
for i,data in enumerate(import_pkg_js["all_data"]):
|
|
91
|
+
if data.get('file_path') == import_pkg_js["file_path"]:
|
|
92
|
+
import_pkg_js["all_data"][i] = nu_data
|
|
93
|
+
found = True
|
|
94
|
+
break
|
|
95
|
+
if found == False:
|
|
96
|
+
import_pkg_js["all_data"].append(nu_data)
|
|
97
|
+
import_pkg_js["nulines"]=[]
|
|
98
|
+
import_pkg_js["file_path"]=file_path
|
|
99
|
+
|
|
100
|
+
for line in lines:
|
|
101
|
+
if line.startswith(import_tag) and ' from ' not in line:
|
|
102
|
+
cleaned_import_list = get_cleaned_import_list(line)
|
|
103
|
+
import_pkg_js = add_imports_to_import_pkg_js("import",cleaned_import_list,import_pkg_js=import_pkg_js)
|
|
104
|
+
else:
|
|
105
|
+
if is_from_group:
|
|
106
|
+
import_pkg=is_from_group
|
|
107
|
+
line = clean_line(line)
|
|
108
|
+
if line.endswith(')'):
|
|
109
|
+
is_from_group=False
|
|
110
|
+
line=line[:-1]
|
|
111
|
+
imports_from_import_pkg = clean_imports(line)
|
|
112
|
+
import_pkg_js = add_imports_to_import_pkg_js(import_pkg,imports_from_import_pkg,import_pkg_js=import_pkg_js)
|
|
113
|
+
|
|
114
|
+
else:
|
|
115
|
+
import_pkg_js=update_import_pkg_js(line,import_pkg_js=import_pkg_js)
|
|
116
|
+
if is_from_line_group(line) and is_from_group == False:
|
|
117
|
+
is_from_group=get_import_pkg(line)
|
|
118
|
+
return import_pkg_js
|
|
119
|
+
def clean_all_imports(text=None,file_path=None,import_pkg_js=None):
|
|
120
|
+
if not import_pkg_js:
|
|
121
|
+
import_pkg_js = get_all_imports(text=text,file_path=file_path)
|
|
122
|
+
nu_lines = import_pkg_js["nulines"]
|
|
123
|
+
for pkg,values in import_pkg_js.items():
|
|
124
|
+
comments = []
|
|
125
|
+
if pkg not in ["nulines","file_path","all_data"]:
|
|
126
|
+
line = values.get('line')
|
|
127
|
+
imports = values.get('imports')
|
|
128
|
+
for i,imp in enumerate(imports):
|
|
129
|
+
if '#' in imp:
|
|
130
|
+
imp_spl = imp.split('#')
|
|
131
|
+
comments.append(imp_spl[-1])
|
|
132
|
+
imports[i] = clean_line(imp_spl[0])
|
|
133
|
+
imports = list(set(imports))
|
|
134
|
+
if '*' in imports:
|
|
135
|
+
imports="*"
|
|
136
|
+
else:
|
|
137
|
+
imports=','.join(imports)
|
|
138
|
+
if comments:
|
|
139
|
+
comments=','.join(comments)
|
|
140
|
+
imports+=f" #{comments}"
|
|
141
|
+
import_pkg_js[pkg]["imports"]=imports
|
|
142
|
+
nu_lines[line] += imports
|
|
143
|
+
import_pkg_js["nulines"]=nu_lines
|
|
144
|
+
return import_pkg_js
|
|
145
|
+
|
|
146
|
+
def get_all_real_imps(file):
|
|
147
|
+
contents = read_from_file(file)
|
|
148
|
+
lines = contents.split('\n')
|
|
149
|
+
for line in lines:
|
|
150
|
+
if line.startswith('from '):
|
|
151
|
+
from_line = line.split('from ')[-1]
|
|
152
|
+
dot_fro = ""
|
|
153
|
+
dirname = file
|
|
154
|
+
for char in from_line:
|
|
155
|
+
if char != '.':
|
|
156
|
+
line = f"from {dot_fro}{eatAll(from_line,'.')}"
|
|
157
|
+
if line in all_imps:
|
|
158
|
+
line = ""
|
|
159
|
+
break
|
|
160
|
+
if dot_fro == "":
|
|
161
|
+
dot_fro = ""
|
|
162
|
+
dirname = os.path.dirname(dirname)
|
|
163
|
+
dirbase = os.path.basename(dirname)
|
|
164
|
+
dot_fro = f"{dirbase}.{dot_fro}"
|
|
165
|
+
if line:
|
|
166
|
+
all_imps.append(line)
|
|
167
|
+
|
|
168
|
+
return '\n'.join(all_imps)
|
|
169
|
+
def save_cleaned_imports(text=None,file_path=None,write=False,import_pkg_js=None):
|
|
170
|
+
import_pkg_js=get_all_imports(text=text,file_path=file_path,import_pkg_js=import_pkg_js)
|
|
171
|
+
import_pkg_js = clean_all_imports(text=text,file_path=file_path,import_pkg_js=import_pkg_js)
|
|
172
|
+
contents = '\n'.join(import_pkg_js["nulines"])
|
|
173
|
+
if file_path and write:
|
|
174
|
+
write_to_file(contents=contents,file_path=file_path)
|
|
175
|
+
return contents
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""
|
|
2
|
+
abstract_safeops.py
|
|
3
|
+
-------------------
|
|
4
|
+
Utility functions for safely splitting, slicing, and retrieving elements from iterable or string objects
|
|
5
|
+
without raising exceptions on invalid input or out-of-range indices.
|
|
6
|
+
|
|
7
|
+
Designed for compatibility with the abstract_ ecosystem (e.g. abstract_utilities, abstract_math, etc.).
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .imports import *
|
|
11
|
+
_BASE_DIR = get_caller_dir()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def safe_split(
|
|
15
|
+
string: Any,
|
|
16
|
+
char: Any,
|
|
17
|
+
i: Optional[int] = None,
|
|
18
|
+
default: Union[bool, Any] = False
|
|
19
|
+
) -> Union[str, List[str], Any, None]:
|
|
20
|
+
"""
|
|
21
|
+
Safely split a string by a character and optionally return index i.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
string: Input string (or any object convertible to string).
|
|
25
|
+
char: Delimiter to split on.
|
|
26
|
+
i: Optional index to retrieve from the split result.
|
|
27
|
+
default: If True, return the original string on error.
|
|
28
|
+
If any other value, return that instead of raising.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
The split list, or the element at index i, or default behavior on error.
|
|
32
|
+
"""
|
|
33
|
+
if string is None or char is None:
|
|
34
|
+
return string
|
|
35
|
+
|
|
36
|
+
s, c = str(string), str(char)
|
|
37
|
+
if c not in s:
|
|
38
|
+
return string
|
|
39
|
+
|
|
40
|
+
parts = s.split(c)
|
|
41
|
+
|
|
42
|
+
if i is None:
|
|
43
|
+
return parts
|
|
44
|
+
|
|
45
|
+
if is_number(i):
|
|
46
|
+
idx = int(i)
|
|
47
|
+
if 0 <= idx < len(parts):
|
|
48
|
+
return parts[idx]
|
|
49
|
+
|
|
50
|
+
if default:
|
|
51
|
+
return string if default is True else default
|
|
52
|
+
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def safe_slice(
|
|
57
|
+
obj: Any,
|
|
58
|
+
i: Optional[int] = None,
|
|
59
|
+
k: Optional[int] = None,
|
|
60
|
+
default: Union[bool, Any] = False
|
|
61
|
+
) -> Any:
|
|
62
|
+
"""
|
|
63
|
+
Safely slice an iterable object or string, with fallback behavior on invalid indices.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
obj: Iterable or string-like object.
|
|
67
|
+
i: Start index (can be negative).
|
|
68
|
+
k: End index (can be negative).
|
|
69
|
+
default: If True, returns the original object on error.
|
|
70
|
+
If any other value, return that value on error.
|
|
71
|
+
|
|
72
|
+
Returns:
|
|
73
|
+
The sliced object, or default behavior on error.
|
|
74
|
+
"""
|
|
75
|
+
# Null or invalid base case
|
|
76
|
+
if obj is None or isinstance(obj, bool):
|
|
77
|
+
return obj if default is True else default if default else None
|
|
78
|
+
|
|
79
|
+
# Non-iterable guard
|
|
80
|
+
if not hasattr(obj, "__getitem__"):
|
|
81
|
+
return obj if default is True else default if default else None
|
|
82
|
+
|
|
83
|
+
obj_len = len(obj)
|
|
84
|
+
|
|
85
|
+
# Normalize negative indices
|
|
86
|
+
if isinstance(i, int) and i < 0:
|
|
87
|
+
i = obj_len + i
|
|
88
|
+
if isinstance(k, int) and k < 0:
|
|
89
|
+
k = obj_len + k
|
|
90
|
+
|
|
91
|
+
# Bound indices
|
|
92
|
+
if i is not None:
|
|
93
|
+
i = max(0, min(i, obj_len))
|
|
94
|
+
if k is not None:
|
|
95
|
+
k = max(0, min(k, obj_len))
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
return obj[i:k]
|
|
99
|
+
except Exception:
|
|
100
|
+
return obj if default is True else default if default else None
|
|
101
|
+
|
|
102
|
+
def safe_join(*paths):
|
|
103
|
+
paths = list(paths)
|
|
104
|
+
paths = [path for path in paths if path]
|
|
105
|
+
return os.path.join(*paths)
|
|
106
|
+
def safe_get(
|
|
107
|
+
obj: Any,
|
|
108
|
+
key: Union[int, str, None] = None,
|
|
109
|
+
default: Union[bool, Any] = False
|
|
110
|
+
) -> Any:
|
|
111
|
+
"""
|
|
112
|
+
Generalized safe getter for both indexable and mapping types.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
obj: The object to access (list, dict, string, etc.).
|
|
116
|
+
key: Index or key to retrieve.
|
|
117
|
+
default: Fallback value or True for "return obj".
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Retrieved element, or default value on failure.
|
|
121
|
+
"""
|
|
122
|
+
if obj is None or key is None:
|
|
123
|
+
return obj if default is True else default if default else None
|
|
124
|
+
|
|
125
|
+
try:
|
|
126
|
+
if isinstance(obj, dict):
|
|
127
|
+
return obj.get(key, obj if default is True else default if default else None)
|
|
128
|
+
return obj[key]
|
|
129
|
+
except Exception:
|
|
130
|
+
return obj if default is True else default if default else None
|
|
131
|
+
def get_slash(path):
|
|
132
|
+
if '/' in path:
|
|
133
|
+
return '/'
|
|
134
|
+
else:
|
|
135
|
+
return '//'
|
|
136
|
+
join_path=safe_join
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
from .imports import *
|
|
2
|
+
def get_output(p):
|
|
3
|
+
"""
|
|
4
|
+
Get the output of a subprocess command.
|
|
5
|
+
|
|
6
|
+
This function takes a subprocess Popen object as an argument and returns
|
|
7
|
+
the output generated by the command's execution.
|
|
8
|
+
|
|
9
|
+
Args:
|
|
10
|
+
p (subprocess.Popen): A Popen object representing a subprocess command.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
tuple: A tuple containing the standard output and standard error streams
|
|
14
|
+
of the executed command.
|
|
15
|
+
"""
|
|
16
|
+
return p.communicate()
|
|
17
|
+
|
|
18
|
+
def get_cmd_out(st):
|
|
19
|
+
"""
|
|
20
|
+
Get the output of a shell command.
|
|
21
|
+
|
|
22
|
+
This function executes a shell command using the 'cmd_input' function and
|
|
23
|
+
retrieves the output generated by the command's execution.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
st (str): The shell command to execute.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
tuple: A tuple containing the standard output and standard error streams
|
|
30
|
+
of the executed shell command.
|
|
31
|
+
"""
|
|
32
|
+
return get_output(cmd_input(st))
|
|
33
|
+
def cmd_input(st):
|
|
34
|
+
"""
|
|
35
|
+
Execute a shell command using subprocess.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
- st (str): Command to be executed.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
- subprocess.Popen: A Popen object for communication.
|
|
42
|
+
"""
|
|
43
|
+
return subprocess.Popen(st, stdout=subprocess.PIPE, shell=True)
|
|
44
|
+
def get_output_text(parent_dir: str = os.getcwd()) -> str:
|
|
45
|
+
"""
|
|
46
|
+
Get the path to the 'output.txt' file in the given directory.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
parent_dir (str, optional): Directory path. Defaults to the current working directory.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
str: Path to the 'output.txt' file.
|
|
53
|
+
"""
|
|
54
|
+
return os.path.join(parent_dir,'output.txt')
|
|
55
|
+
def get_env_value(key: str = None, env_path: str = None) -> str:
|
|
56
|
+
"""
|
|
57
|
+
Retrieve environment value based on a key from a specified .env file.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
key (str, optional): Environment key to search for. Defaults to None.
|
|
61
|
+
env_path (str, optional): Path to start searching for the .env file. Defaults to None.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
str: Value corresponding to the given environment key.
|
|
65
|
+
"""
|
|
66
|
+
args={}
|
|
67
|
+
if key != None:
|
|
68
|
+
args["key"]=key
|
|
69
|
+
if env_path != None:
|
|
70
|
+
args["start_path"]=env_path
|
|
71
|
+
return find_and_read_env_file(**args)
|
|
72
|
+
def print_cmd(input: str, output: str) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Print the input command and its corresponding output.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
input (str): The command that was run.
|
|
78
|
+
output (str): Output produced by the command.
|
|
79
|
+
"""
|
|
80
|
+
print(f"Command Line Arguments: {input}")
|
|
81
|
+
print(f"Output:\n{output}")
|
|
82
|
+
def get_sudo_password(key: str = "SUDO_PASSWORD") -> str:
|
|
83
|
+
"""
|
|
84
|
+
Retrieve the sudo password from an environment file.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
key (str, optional): Environment key for the sudo password. Defaults to "SUDO_PASSWORD".
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
str: The sudo password.
|
|
91
|
+
"""
|
|
92
|
+
return find_and_read_env_file(key=key)
|
|
93
|
+
def cmd_run_sudo(cmd: str, password: str = None, key: str = None, output_text: str = None) -> None:
|
|
94
|
+
"""
|
|
95
|
+
Execute a command with sudo privileges using either provided password or retrieving it from an environment file.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
cmd (str): Command to be executed.
|
|
99
|
+
password (str, optional): Password for sudo. Defaults to None.
|
|
100
|
+
key (str, optional): Environment key to retrieve sudo password. Defaults to None.
|
|
101
|
+
output_text (str, optional): Path to store the command output. Defaults to None.
|
|
102
|
+
"""
|
|
103
|
+
if password !=None:
|
|
104
|
+
cmd_run(f'echo "{password}" | sudo -S -k {cmd}',output_text)
|
|
105
|
+
elif key != None:
|
|
106
|
+
cmd_run(f'echo "{get_env_value(key)}" | sudo -S -k {cmd}',output_text)
|
|
107
|
+
else:
|
|
108
|
+
cmd_run(f'echo "{get_sudo_password()}" | sudo -S -k {cmd}',output_text)
|
|
109
|
+
def cmd_run(cmd: str, output_text: str = None, print_output: bool = False) -> None:
|
|
110
|
+
if output_text is None:
|
|
111
|
+
output_text = get_output_text()
|
|
112
|
+
|
|
113
|
+
# Clear output file
|
|
114
|
+
with open(output_text, 'w') as f:
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
# Append output redirection
|
|
118
|
+
full_cmd = f'{cmd} >> {output_text}; echo END_OF_CMD >> {output_text}'
|
|
119
|
+
|
|
120
|
+
if print_output:
|
|
121
|
+
print(full_cmd)
|
|
122
|
+
|
|
123
|
+
subprocess.call(full_cmd, shell=True)
|
|
124
|
+
|
|
125
|
+
# Wait until END_OF_CMD appears
|
|
126
|
+
while True:
|
|
127
|
+
get_sleep(sleep_timer=0.5)
|
|
128
|
+
with open(output_text, 'r') as f:
|
|
129
|
+
lines = f.readlines()
|
|
130
|
+
if lines and lines[-1].strip() == 'END_OF_CMD':
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
if print_output:
|
|
134
|
+
with open(output_text, 'r') as f:
|
|
135
|
+
print_cmd(full_cmd, f.read().strip())
|
|
136
|
+
|
|
137
|
+
os.remove(output_text)
|
|
138
|
+
|
|
139
|
+
def pexpect_cmd_with_args(command: str, child_runs: list, output_text: str = os.getcwd(),print_output:bool=False) -> int:
|
|
140
|
+
"""
|
|
141
|
+
Run a command using pexpect and handle its prompts with specified responses.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
command (str): Command to be executed.
|
|
145
|
+
child_runs (list): List of prompts and their respective responses.
|
|
146
|
+
output_text (str, optional): Path to store the command output. Defaults to the current working directory.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
int: Exit status of the command.
|
|
150
|
+
"""
|
|
151
|
+
child = pexpect.spawn(command)
|
|
152
|
+
|
|
153
|
+
for each in child_runs:
|
|
154
|
+
# Wait for the process to prompt for the input and respond with it
|
|
155
|
+
child.expect(each["prompt"])
|
|
156
|
+
|
|
157
|
+
# Respond with the corresponding input
|
|
158
|
+
if each["pass"] is not None:
|
|
159
|
+
pass_phrase = each["pass"]
|
|
160
|
+
else:
|
|
161
|
+
args = {}
|
|
162
|
+
if "key" in each:
|
|
163
|
+
if each["key"] is not None:
|
|
164
|
+
args["key"] = each["key"]
|
|
165
|
+
if "env_path" in each:
|
|
166
|
+
if each["env_path"] is not None:
|
|
167
|
+
args["start_path"] = each["env_path"]
|
|
168
|
+
|
|
169
|
+
pass_phrase = get_env_value(**args)
|
|
170
|
+
|
|
171
|
+
child.sendline(pass_phrase)
|
|
172
|
+
if print_output:
|
|
173
|
+
print("Output after handling prompt:")
|
|
174
|
+
print(each["prompt"])
|
|
175
|
+
|
|
176
|
+
# Wait for the process to finish
|
|
177
|
+
child.expect(pexpect.EOF)
|
|
178
|
+
output = child.before.decode("utf-8")
|
|
179
|
+
|
|
180
|
+
# Write output to the output file
|
|
181
|
+
with open(get_output_text(), "w") as f:
|
|
182
|
+
f.write(output)
|
|
183
|
+
if print_output:
|
|
184
|
+
print_cmd(command, output)
|
|
185
|
+
|
|
186
|
+
return child.exitstatus
|
|
187
|
+
def get_user_pass_host_key(**kwargs):
|
|
188
|
+
args = ['password','user_at_host','host','key','user']
|
|
189
|
+
kwargs['del_kwarg']=kwargs.get('del_kwarg',False)
|
|
190
|
+
values,kwargs = get_from_kwargs(*args,**kwargs)
|
|
191
|
+
return values
|
|
192
|
+
|
|
193
|
+
# --- Base remote checker -----------------------------------------------------
|
|
194
|
+
def _remote_test(path: str, test_flag: str, timeout: int = 5,*args, **kwargs) -> bool:
|
|
195
|
+
"""
|
|
196
|
+
Run a remote shell test (e.g. -f, -d) via SSH.
|
|
197
|
+
Returns True if test succeeds, False otherwise.
|
|
198
|
+
"""
|
|
199
|
+
try:
|
|
200
|
+
kwargs['cmd']=f"[ {test_flag} {shlex.quote(path)} ] && echo 1 || echo 0"
|
|
201
|
+
kwargs['text']=True
|
|
202
|
+
kwargs['timeout']=timeout
|
|
203
|
+
kwargs['stderr']=subprocess.DEVNULL
|
|
204
|
+
result = run_pruned_func(run_cmd,**kwargs)
|
|
205
|
+
return result.strip() == "1"
|
|
206
|
+
except Exception:
|
|
207
|
+
return False
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from ...string_utils import get_from_kwargs,eatAll,eatOuter
|
|
2
|
+
from ...type_utils import make_list # whatever you already have
|
|
3
|
+
from ...time_utils import get_sleep
|
|
4
|
+
from abstract_security import *
|
|
5
|
+
|
|
6
|
+
from ...class_utils import get_caller, get_caller_path, get_caller_dir,SingletonMeta,run_pruned_func
|