abstract-utilities 0.2.2.513__py3-none-any.whl → 0.2.2.627__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 +11 -3
- abstract_utilities/class_utils/caller_utils.py +19 -0
- abstract_utilities/class_utils/global_utils.py +35 -20
- abstract_utilities/class_utils/imports/imports.py +1 -1
- abstract_utilities/directory_utils/__init__.py +2 -4
- abstract_utilities/directory_utils/imports/__init__.py +2 -0
- abstract_utilities/directory_utils/imports/imports.py +1 -0
- abstract_utilities/directory_utils/imports/module_imports.py +2 -0
- abstract_utilities/directory_utils/src/__init__.py +4 -0
- abstract_utilities/directory_utils/src/directory_utils.py +110 -0
- abstract_utilities/directory_utils/src/name_utils.py +43 -0
- abstract_utilities/directory_utils/src/size_utils.py +57 -0
- abstract_utilities/directory_utils/src/utils.py +116 -0
- abstract_utilities/file_utils/imports/constants.py +81 -7
- abstract_utilities/file_utils/imports/imports.py +0 -4
- abstract_utilities/file_utils/imports/module_imports.py +1 -1
- abstract_utilities/file_utils/src/__init__.py +2 -4
- abstract_utilities/file_utils/src/file_filters/__init__.py +4 -0
- abstract_utilities/file_utils/src/file_filters/ensure_utils.py +118 -0
- abstract_utilities/file_utils/src/file_filters/filter_params.py +86 -0
- abstract_utilities/file_utils/src/file_filters/filter_utils.py +78 -0
- abstract_utilities/file_utils/src/file_filters/predicate_utils.py +116 -0
- abstract_utilities/file_utils/src/file_filters.py +114 -47
- abstract_utilities/file_utils/src/file_reader.py +0 -64
- abstract_utilities/file_utils/src/file_utils.py +7 -130
- abstract_utilities/file_utils/src/filter_params.py +128 -86
- abstract_utilities/file_utils/src/find_collect.py +85 -165
- abstract_utilities/file_utils/src/find_content.py +210 -0
- abstract_utilities/file_utils/src/initFunctionsGen.py +35 -28
- abstract_utilities/file_utils/src/initFunctionsGens.py +280 -0
- abstract_utilities/file_utils/src/reader_utils/__init__.py +4 -0
- abstract_utilities/file_utils/src/reader_utils/directory_reader.py +53 -0
- abstract_utilities/file_utils/src/reader_utils/file_reader.py +543 -0
- abstract_utilities/file_utils/src/reader_utils/file_readers.py +376 -0
- abstract_utilities/file_utils/src/reader_utils/imports.py +18 -0
- abstract_utilities/file_utils/src/reader_utils/pdf_utils.py +300 -0
- abstract_utilities/file_utils (2)/__init__.py +2 -0
- abstract_utilities/file_utils (2)/imports/__init__.py +2 -0
- abstract_utilities/file_utils (2)/imports/constants.py +118 -0
- abstract_utilities/file_utils (2)/imports/imports/__init__.py +3 -0
- abstract_utilities/file_utils (2)/imports/imports/constants.py +119 -0
- abstract_utilities/file_utils (2)/imports/imports/imports.py +46 -0
- abstract_utilities/file_utils (2)/imports/imports/module_imports.py +8 -0
- abstract_utilities/file_utils (2)/imports/utils/__init__.py +3 -0
- abstract_utilities/file_utils (2)/imports/utils/classes.py +379 -0
- abstract_utilities/file_utils (2)/imports/utils/clean_imps.py +155 -0
- abstract_utilities/file_utils (2)/imports/utils/filter_utils.py +341 -0
- abstract_utilities/file_utils (2)/src/__init__.py +8 -0
- abstract_utilities/file_utils (2)/src/file_filters.py +155 -0
- abstract_utilities/file_utils (2)/src/file_reader.py +604 -0
- abstract_utilities/file_utils (2)/src/find_collect.py +258 -0
- abstract_utilities/file_utils (2)/src/initFunctionsGen.py +286 -0
- abstract_utilities/file_utils (2)/src/map_utils.py +28 -0
- abstract_utilities/file_utils (2)/src/pdf_utils.py +300 -0
- abstract_utilities/import_utils/circular_import_finder.py +222 -0
- abstract_utilities/import_utils/circular_import_finder2.py +118 -0
- abstract_utilities/import_utils/imports/module_imports.py +3 -1
- abstract_utilities/import_utils/src/clean_imports.py +156 -25
- abstract_utilities/import_utils/src/dot_utils.py +11 -0
- abstract_utilities/import_utils/src/extract_utils.py +4 -0
- abstract_utilities/import_utils/src/import_functions.py +66 -2
- abstract_utilities/import_utils/src/pkg_utils.py +58 -4
- abstract_utilities/import_utils/src/sysroot_utils.py +56 -1
- abstract_utilities/log_utils/log_file.py +73 -24
- abstract_utilities/parse_utils/parse_utils.py +23 -0
- abstract_utilities/path_utils/path_utils.py +25 -23
- abstract_utilities/read_write_utils/imports/imports.py +1 -1
- abstract_utilities/read_write_utils/read_write_utils.py +99 -31
- abstract_utilities/safe_utils/safe_utils.py +30 -0
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.627.dist-info}/METADATA +1 -1
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.627.dist-info}/RECORD +73 -32
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.627.dist-info}/WHEEL +0 -0
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.627.dist-info}/top_level.txt +0 -0
|
@@ -1,79 +1,15 @@
|
|
|
1
1
|
from ..imports import *
|
|
2
|
-
from .
|
|
3
|
-
from .file_filters import enumerate_source_files
|
|
2
|
+
from .file_filters import *
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Optional, List, Set
|
|
6
5
|
|
|
7
|
-
def check_path_type(
|
|
8
|
-
path: str,
|
|
9
|
-
user: Optional[str] = None,
|
|
10
|
-
host: Optional[str] = None,
|
|
11
|
-
user_as_host: Optional[str] = None,
|
|
12
|
-
use_shell: bool = False
|
|
13
|
-
) -> Literal["file", "directory", "missing", "unknown"]:
|
|
14
|
-
"""
|
|
15
|
-
Determine whether a given path is a file, directory, or missing.
|
|
16
|
-
Works locally or remotely (via SSH).
|
|
17
6
|
|
|
18
|
-
Args:
|
|
19
|
-
path: The path to check.
|
|
20
|
-
user, host, user_as_host: SSH parameters if remote.
|
|
21
|
-
use_shell: Force shell test instead of Python os.path.
|
|
22
|
-
Returns:
|
|
23
|
-
One of: 'file', 'directory', 'missing', or 'unknown'
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
# --- remote check if user/host is given ---
|
|
27
|
-
if user_as_host or (user and host):
|
|
28
|
-
remote_target = user_as_host or f"{user}@{host}"
|
|
29
|
-
cmd = f"if [ -f '{path}' ]; then echo file; elif [ -d '{path}' ]; then echo directory; else echo missing; fi"
|
|
30
|
-
try:
|
|
31
|
-
result = subprocess.check_output(
|
|
32
|
-
["ssh", remote_target, cmd],
|
|
33
|
-
stderr=subprocess.DEVNULL,
|
|
34
|
-
text=True,
|
|
35
|
-
timeout=5
|
|
36
|
-
).strip()
|
|
37
|
-
return result if result in ("file", "directory", "missing") else "unknown"
|
|
38
|
-
except Exception:
|
|
39
|
-
return "unknown"
|
|
40
|
-
|
|
41
|
-
# --- local check ---
|
|
42
|
-
if not use_shell:
|
|
43
|
-
if os.path.isfile(path):
|
|
44
|
-
return "file"
|
|
45
|
-
elif os.path.isdir(path):
|
|
46
|
-
return "directory"
|
|
47
|
-
elif not os.path.exists(path):
|
|
48
|
-
return "missing"
|
|
49
|
-
return "unknown"
|
|
50
|
-
else:
|
|
51
|
-
# fallback using shell tests (useful for sandboxed contexts)
|
|
52
|
-
cmd = f"if [ -f '{path}' ]; then echo file; elif [ -d '{path}' ]; then echo directory; else echo missing; fi"
|
|
53
|
-
try:
|
|
54
|
-
output = subprocess.check_output(
|
|
55
|
-
cmd, shell=True, stderr=subprocess.DEVNULL, text=True
|
|
56
|
-
).strip()
|
|
57
|
-
return output if output in ("file", "directory", "missing") else "unknown"
|
|
58
|
-
except Exception:
|
|
59
|
-
return "unknown"
|
|
60
7
|
|
|
61
8
|
|
|
62
9
|
|
|
63
10
|
|
|
64
11
|
def get_find_cmd(
|
|
65
|
-
|
|
66
|
-
*,
|
|
67
|
-
cfg: Optional["ScanConfig"] = None,
|
|
68
|
-
*,
|
|
69
|
-
allowed_exts: Optional[Set[str]] = False,
|
|
70
|
-
unallowed_exts: Optional[Set[str]] = False,
|
|
71
|
-
allowed_types: Optional[Set[str]] = False,
|
|
72
|
-
exclude_types: Optional[Set[str]] = False,
|
|
73
|
-
allowed_dirs: Optional[List[str]] = False,
|
|
74
|
-
exclude_dirs: Optional[List[str]] = False,
|
|
75
|
-
allowed_patterns: Optional[List[str]] = False,
|
|
76
|
-
exclude_patterns: Optional[List[str]] = False,
|
|
12
|
+
*args,
|
|
77
13
|
mindepth: Optional[int] = None,
|
|
78
14
|
maxdepth: Optional[int] = None,
|
|
79
15
|
depth: Optional[int] = None,
|
|
@@ -86,14 +22,23 @@ def get_find_cmd(
|
|
|
86
22
|
**kwargs
|
|
87
23
|
) -> str:
|
|
88
24
|
"""
|
|
89
|
-
Construct a Unix `find` command string
|
|
90
|
-
|
|
91
|
-
- Honors allowed/excluded patterns, dirs, and extensions from ScanConfig.
|
|
92
|
-
- Automatically applies mindepth/maxdepth/depth/file_type filters.
|
|
25
|
+
Construct a Unix `find` command string that supports multiple directories.
|
|
26
|
+
Accepts filtering via ScanConfig-compatible kwargs.
|
|
93
27
|
"""
|
|
94
|
-
|
|
28
|
+
# Normalize inputs into canonical form
|
|
29
|
+
kwargs = get_safe_canonical_kwargs(*args, **kwargs)
|
|
30
|
+
cfg = kwargs.get('cfg') or define_defaults(**kwargs)
|
|
95
31
|
|
|
96
|
-
#
|
|
32
|
+
# Get directory list (may come from args or kwargs)
|
|
33
|
+
kwargs["directories"] = ensure_directories(*args, **kwargs)
|
|
34
|
+
if not kwargs["directories"]:
|
|
35
|
+
return []
|
|
36
|
+
|
|
37
|
+
# Build base command for all directories
|
|
38
|
+
dir_expr = " ".join(shlex.quote(d) for d in kwargs["directories"])
|
|
39
|
+
cmd = [f"find {dir_expr}"]
|
|
40
|
+
|
|
41
|
+
# --- depth filters ---
|
|
97
42
|
if depth is not None:
|
|
98
43
|
cmd += [f"-mindepth {depth}", f"-maxdepth {depth}"]
|
|
99
44
|
else:
|
|
@@ -106,7 +51,7 @@ def get_find_cmd(
|
|
|
106
51
|
if file_type in ("f", "d"):
|
|
107
52
|
cmd.append(f"-type {file_type}")
|
|
108
53
|
|
|
109
|
-
# ---
|
|
54
|
+
# --- basic attributes ---
|
|
110
55
|
if name:
|
|
111
56
|
cmd.append(f"-name {shlex.quote(name)}")
|
|
112
57
|
if size:
|
|
@@ -117,63 +62,53 @@ def get_find_cmd(
|
|
|
117
62
|
cmd.append(f"-perm {shlex.quote(perm)}")
|
|
118
63
|
if user:
|
|
119
64
|
cmd.append(f"-user {shlex.quote(user)}")
|
|
120
|
-
|
|
121
|
-
allowed_exts = allowed_exts,
|
|
122
|
-
unallowed_exts = unallowed_exts,
|
|
123
|
-
allowed_types = allowed_types,
|
|
124
|
-
exclude_types = exclude_types,
|
|
125
|
-
allowed_dirs = allowed_dirs,
|
|
126
|
-
exclude_dirs = exclude_dirs,
|
|
127
|
-
allowed_patterns = allowed_patterns,
|
|
128
|
-
exclude_patterns = exclude_patterns,
|
|
129
|
-
add = add
|
|
130
|
-
)
|
|
65
|
+
|
|
131
66
|
# --- cfg-based filters ---
|
|
132
67
|
if cfg:
|
|
133
|
-
#
|
|
68
|
+
# Allowed extensions
|
|
134
69
|
if cfg.allowed_exts and cfg.allowed_exts != {"*"}:
|
|
135
70
|
ext_expr = " -o ".join(
|
|
136
71
|
[f"-name '*{e}'" for e in cfg.allowed_exts if e]
|
|
137
72
|
)
|
|
138
73
|
cmd.append(f"\\( {ext_expr} \\)")
|
|
139
74
|
|
|
140
|
-
#
|
|
141
|
-
if cfg.
|
|
142
|
-
for e in cfg.
|
|
75
|
+
# Excluded extensions
|
|
76
|
+
if cfg.exclude_exts:
|
|
77
|
+
for e in cfg.exclude_exts:
|
|
143
78
|
cmd.append(f"! -name '*{e}'")
|
|
144
79
|
|
|
145
|
-
#
|
|
80
|
+
# Allowed directories
|
|
146
81
|
if cfg.allowed_dirs and cfg.allowed_dirs != ["*"]:
|
|
147
82
|
dir_expr = " -o ".join(
|
|
148
83
|
[f"-path '*{d}*'" for d in cfg.allowed_dirs if d]
|
|
149
84
|
)
|
|
150
85
|
cmd.append(f"\\( {dir_expr} \\)")
|
|
151
86
|
|
|
152
|
-
#
|
|
87
|
+
# Excluded directories
|
|
153
88
|
if cfg.exclude_dirs:
|
|
154
89
|
for d in cfg.exclude_dirs:
|
|
155
90
|
cmd.append(f"! -path '*{d}*'")
|
|
156
91
|
|
|
157
|
-
#
|
|
92
|
+
# Allowed patterns
|
|
158
93
|
if cfg.allowed_patterns and cfg.allowed_patterns != ["*"]:
|
|
159
94
|
pat_expr = " -o ".join(
|
|
160
95
|
[f"-name '{p}'" for p in cfg.allowed_patterns if p]
|
|
161
96
|
)
|
|
162
97
|
cmd.append(f"\\( {pat_expr} \\)")
|
|
163
98
|
|
|
164
|
-
#
|
|
99
|
+
# Excluded patterns
|
|
165
100
|
if cfg.exclude_patterns:
|
|
166
101
|
for p in cfg.exclude_patterns:
|
|
167
102
|
cmd.append(f"! -name '{p}'")
|
|
168
103
|
|
|
169
|
-
#
|
|
104
|
+
# Allowed types (semantic, not `-type`)
|
|
170
105
|
if cfg.allowed_types and cfg.allowed_types != {"*"}:
|
|
171
106
|
type_expr = " -o ".join(
|
|
172
107
|
[f"-path '*{t}*'" for t in cfg.allowed_types if t]
|
|
173
108
|
)
|
|
174
109
|
cmd.append(f"\\( {type_expr} \\)")
|
|
175
110
|
|
|
176
|
-
#
|
|
111
|
+
# Excluded types
|
|
177
112
|
if cfg.exclude_types:
|
|
178
113
|
for t in cfg.exclude_types:
|
|
179
114
|
cmd.append(f"! -path '*{t}*'")
|
|
@@ -183,24 +118,12 @@ def get_find_cmd(
|
|
|
183
118
|
|
|
184
119
|
|
|
185
120
|
def collect_globs(
|
|
186
|
-
|
|
187
|
-
cfg: Optional["ScanConfig"] = None,
|
|
188
|
-
*,
|
|
189
|
-
allowed_exts: Optional[Set[str]] = False,
|
|
190
|
-
unallowed_exts: Optional[Set[str]] = False,
|
|
191
|
-
allowed_types: Optional[Set[str]] = False,
|
|
192
|
-
exclude_types: Optional[Set[str]] = False,
|
|
193
|
-
allowed_dirs: Optional[List[str]] = False,
|
|
194
|
-
exclude_dirs: Optional[List[str]] = False,
|
|
195
|
-
allowed_patterns: Optional[List[str]] = False,
|
|
196
|
-
exclude_patterns: Optional[List[str]] = False,
|
|
197
|
-
patterns: Optional[List[str]] = None,
|
|
121
|
+
*args,
|
|
198
122
|
mindepth: Optional[int] = None,
|
|
199
123
|
maxdepth: Optional[int] = None,
|
|
200
124
|
depth: Optional[int] = None,
|
|
201
125
|
file_type: Optional[str] = None, # "f", "d", or None
|
|
202
|
-
|
|
203
|
-
add: bool = False,
|
|
126
|
+
allowed: Optional[Callable[[str], bool]] = None,
|
|
204
127
|
**kwargs
|
|
205
128
|
) -> List[str] | dict:
|
|
206
129
|
"""
|
|
@@ -210,61 +133,58 @@ def collect_globs(
|
|
|
210
133
|
- If file_type is "f" or "d" → returns a list of that type
|
|
211
134
|
- Supports SSH mode via `user_at_host`
|
|
212
135
|
"""
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
if user_at_host:
|
|
136
|
+
user_pass_host_key = get_user_pass_host_key(**kwargs)
|
|
137
|
+
kwargs["directories"] = ensure_directories(*args, **kwargs)
|
|
138
|
+
kwargs= get_safe_canonical_kwargs(**kwargs)
|
|
139
|
+
kwargs["cfg"] = kwargs.get('cfg') or define_defaults(**kwargs)
|
|
140
|
+
|
|
141
|
+
type_strs = {"f":"files","d":"dirs"}
|
|
142
|
+
file_type = get_proper_type_str(file_type)
|
|
143
|
+
file_types = make_list(file_type)
|
|
144
|
+
if file_type == None:
|
|
145
|
+
file_types = ["f","d"]
|
|
146
|
+
return_results = {}
|
|
147
|
+
return_result=[]
|
|
148
|
+
for file_type in file_types:
|
|
149
|
+
type_str = type_strs.get(file_type)
|
|
150
|
+
# Remote path (SSH)
|
|
229
151
|
find_cmd = get_find_cmd(
|
|
230
|
-
|
|
231
|
-
cfg=cfg,
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
152
|
+
directories=kwargs.get("directories"),
|
|
153
|
+
cfg=kwargs.get('cfg'),
|
|
154
|
+
mindepth=mindepth,
|
|
155
|
+
maxdepth=maxdepth,
|
|
156
|
+
depth=depth,
|
|
157
|
+
file_type=file_type,
|
|
158
|
+
**user_pass_host_key,
|
|
159
|
+
)
|
|
160
|
+
result = run_pruned_func(run_cmd,find_cmd,
|
|
161
|
+
**kwargs
|
|
162
|
+
|
|
163
|
+
)
|
|
164
|
+
return_result = [res for res in result.split('\n') if res]
|
|
165
|
+
return_results[type_str]=return_result
|
|
166
|
+
if len(file_types) == 1:
|
|
167
|
+
return return_result
|
|
168
|
+
return return_results
|
|
169
|
+
def get_files_and_dirs(
|
|
170
|
+
*args,
|
|
171
|
+
recursive: bool = True,
|
|
172
|
+
include_files: bool = True,
|
|
173
|
+
**kwargs
|
|
174
|
+
):
|
|
175
|
+
if recursive == False:
|
|
176
|
+
kwargs['maxdepth']=1
|
|
177
|
+
if include_files == False:
|
|
178
|
+
kwargs['file_type']='d'
|
|
179
|
+
result = collect_globs(*args,**kwargs)
|
|
180
|
+
if include_files == False:
|
|
181
|
+
return result,[]
|
|
182
|
+
dirs = result.get("dirs")
|
|
183
|
+
files = result.get("files")
|
|
184
|
+
return dirs,files
|
|
185
|
+
def collect_filepaths(
|
|
186
|
+
*args,
|
|
187
|
+
**kwargs
|
|
188
|
+
) -> List[str]:
|
|
189
|
+
kwargs['file_type']='f'
|
|
190
|
+
return collect_globs(*args,**kwargs)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
from .file_filters import *
|
|
2
|
+
from .reader_utils import *
|
|
3
|
+
from .find_collect import *
|
|
4
|
+
STOP_SEARCH = False
|
|
5
|
+
|
|
6
|
+
def request_find_console_stop():
|
|
7
|
+
global STOP_SEARCH
|
|
8
|
+
STOP_SEARCH = True
|
|
9
|
+
|
|
10
|
+
def reset_find_console_stop():
|
|
11
|
+
global STOP_SEARCH
|
|
12
|
+
STOP_SEARCH = False
|
|
13
|
+
|
|
14
|
+
def get_contents(
|
|
15
|
+
full_path=None,
|
|
16
|
+
parse_lines=False,
|
|
17
|
+
content=None
|
|
18
|
+
):
|
|
19
|
+
if full_path:
|
|
20
|
+
content = content or read_any_file(full_path)
|
|
21
|
+
if content:
|
|
22
|
+
if parse_lines:
|
|
23
|
+
content = str(content).split('\n')
|
|
24
|
+
return make_list(content)
|
|
25
|
+
return []
|
|
26
|
+
|
|
27
|
+
def _normalize(s: str, strip_comments=True, collapse_ws=True, lower=True):
|
|
28
|
+
if s is None:
|
|
29
|
+
return ""
|
|
30
|
+
if strip_comments:
|
|
31
|
+
s = s.split('//', 1)[0]
|
|
32
|
+
if collapse_ws:
|
|
33
|
+
s = re.sub(r'\s+', ' ', s)
|
|
34
|
+
if lower:
|
|
35
|
+
s = s.lower()
|
|
36
|
+
return s.strip()
|
|
37
|
+
|
|
38
|
+
def stringInContent(content, strings, total_strings=False, normalize=False):
|
|
39
|
+
if not content:
|
|
40
|
+
return False
|
|
41
|
+
if normalize:
|
|
42
|
+
c = _normalize(str(content))
|
|
43
|
+
|
|
44
|
+
found = [s for s in strings if _normalize(s) and _normalize(s) in c]
|
|
45
|
+
else:
|
|
46
|
+
c = str(content)
|
|
47
|
+
found = [s for s in strings if s and s in c]
|
|
48
|
+
if not found:
|
|
49
|
+
return False
|
|
50
|
+
return len(found) == len(strings) if total_strings else True
|
|
51
|
+
def find_file(content, spec_line, strings, total_strings=False):
|
|
52
|
+
lines = content.split('\n')
|
|
53
|
+
if 1 <= spec_line <= len(lines):
|
|
54
|
+
return stringInContent(lines[spec_line - 1], strings, total_strings=total_strings)
|
|
55
|
+
return False
|
|
56
|
+
def find_lines(content, strings, total_strings=False, normalize=True, any_per_line=True):
|
|
57
|
+
lines = content.split('\n')
|
|
58
|
+
hits = []
|
|
59
|
+
for i, line in enumerate(lines):
|
|
60
|
+
# match one line either if ANY string matches or if ALL match (configurable)
|
|
61
|
+
if any_per_line:
|
|
62
|
+
match = stringInContent(line, strings, total_strings=False, normalize=normalize)
|
|
63
|
+
else:
|
|
64
|
+
match = stringInContent(line, strings, total_strings=True, normalize=normalize)
|
|
65
|
+
if match:
|
|
66
|
+
hits.append({"line": i+1, "content": line})
|
|
67
|
+
return hits
|
|
68
|
+
def getPaths(files, strings):
|
|
69
|
+
tot_strings = strings
|
|
70
|
+
nu_files, found_paths = [], []
|
|
71
|
+
if isinstance(strings,list):
|
|
72
|
+
if len(strings) >1:
|
|
73
|
+
tot_strings = '\n'.join(strings)
|
|
74
|
+
else:
|
|
75
|
+
if len(strings) == 0:
|
|
76
|
+
return nu_files, found_paths
|
|
77
|
+
tot_strings = strings[0]
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
for file_path in files:
|
|
81
|
+
try:
|
|
82
|
+
og_content = read_any_file(file_path)
|
|
83
|
+
if tot_strings not in og_content:
|
|
84
|
+
continue
|
|
85
|
+
if file_path not in nu_files:
|
|
86
|
+
nu_files.append(file_path)
|
|
87
|
+
ogLines = og_content.split('\n')
|
|
88
|
+
# find all occurrences of the block
|
|
89
|
+
for m in re.finditer(re.escape(tot_strings), og_content):
|
|
90
|
+
start_line = og_content[:m.start()].count('\n') + 1 # 1-based
|
|
91
|
+
curr = {'file_path': file_path, 'lines': []}
|
|
92
|
+
for j in range(len(strings)):
|
|
93
|
+
ln = start_line + j
|
|
94
|
+
curr['lines'].append({'line': ln, 'content': ogLines[ln - 1]})
|
|
95
|
+
found_paths.append(curr)
|
|
96
|
+
except Exception as e:
|
|
97
|
+
print(f"{e}")
|
|
98
|
+
return nu_files, found_paths
|
|
99
|
+
|
|
100
|
+
def findContent(
|
|
101
|
+
*args,
|
|
102
|
+
strings: list=[],
|
|
103
|
+
total_strings=True,
|
|
104
|
+
parse_lines=False,
|
|
105
|
+
spec_line=False,
|
|
106
|
+
get_lines=True,
|
|
107
|
+
diffs=False,
|
|
108
|
+
**kwargs
|
|
109
|
+
):
|
|
110
|
+
global STOP_SEARCH
|
|
111
|
+
kwargs["directories"] = ensure_directories(*args,**kwargs)
|
|
112
|
+
|
|
113
|
+
found_paths = []
|
|
114
|
+
|
|
115
|
+
dirs, files = get_files_and_dirs(
|
|
116
|
+
**kwargs
|
|
117
|
+
)
|
|
118
|
+
nu_files, found_paths = getPaths(files, strings)
|
|
119
|
+
|
|
120
|
+
if diffs and found_paths:
|
|
121
|
+
return found_paths
|
|
122
|
+
|
|
123
|
+
for file_path in nu_files:
|
|
124
|
+
if STOP_SEARCH:
|
|
125
|
+
return found_paths # early exit
|
|
126
|
+
|
|
127
|
+
if file_path:
|
|
128
|
+
og_content = read_any_file(file_path)
|
|
129
|
+
contents = get_contents(
|
|
130
|
+
file_path,
|
|
131
|
+
parse_lines=parse_lines,
|
|
132
|
+
content=og_content
|
|
133
|
+
)
|
|
134
|
+
found = False
|
|
135
|
+
for content in contents:
|
|
136
|
+
if STOP_SEARCH:
|
|
137
|
+
return found_paths # bail out cleanly
|
|
138
|
+
|
|
139
|
+
if stringInContent(content, strings, total_strings=True, normalize=True):
|
|
140
|
+
found = True
|
|
141
|
+
if spec_line:
|
|
142
|
+
found = find_file(og_content, spec_line, strings, total_strings=True)
|
|
143
|
+
if found:
|
|
144
|
+
if get_lines:
|
|
145
|
+
lines = find_lines(
|
|
146
|
+
og_content,
|
|
147
|
+
strings=strings,
|
|
148
|
+
total_strings=False,
|
|
149
|
+
normalize=True,
|
|
150
|
+
any_per_line=True
|
|
151
|
+
)
|
|
152
|
+
if lines:
|
|
153
|
+
file_path = {"file_path": file_path, "lines": lines}
|
|
154
|
+
found_paths.append(file_path)
|
|
155
|
+
break
|
|
156
|
+
return found_paths
|
|
157
|
+
def return_function(start_dir=None,preferred_dir=None,basenames=None,functionName=None):
|
|
158
|
+
if basenames:
|
|
159
|
+
basenames = make_list(basenames)
|
|
160
|
+
abstract_file_finder = AbstractFileFinderImporter(start_dir=start_dir,preferred_dir=preferred_dir)
|
|
161
|
+
paths = abstract_file_finder.find_paths(basenames)
|
|
162
|
+
func = abstract_file_finder.import_function_from_path(paths[0], functionName)
|
|
163
|
+
return func
|
|
164
|
+
def getLineNums(file_path):
|
|
165
|
+
lines=[]
|
|
166
|
+
if file_path and isinstance(file_path,dict):
|
|
167
|
+
lines = file_path.get('lines')
|
|
168
|
+
file_path = file_path.get('file_path')
|
|
169
|
+
return file_path,lines
|
|
170
|
+
def get_line_content(obj):
|
|
171
|
+
line,content=None,None
|
|
172
|
+
if obj and isinstance(obj,dict):
|
|
173
|
+
line=obj.get('line')
|
|
174
|
+
content = obj.get('content')
|
|
175
|
+
#print(f"line: {line}\ncontent: {content}")
|
|
176
|
+
return line,content
|
|
177
|
+
def get_edit(file_path):
|
|
178
|
+
if file_path and os.path.isfile(file_path):
|
|
179
|
+
os.system(f"code {file_path}")
|
|
180
|
+
input()
|
|
181
|
+
def editLines(file_paths):
|
|
182
|
+
for file_path in file_paths:
|
|
183
|
+
file_path,lines = getLineNums(file_path)
|
|
184
|
+
for obj in lines:
|
|
185
|
+
line,content = get_line_content(obj)
|
|
186
|
+
get_edit(file_path)
|
|
187
|
+
def findContentAndEdit(*args,
|
|
188
|
+
strings: list=[],
|
|
189
|
+
total_strings=True,
|
|
190
|
+
parse_lines=False,
|
|
191
|
+
spec_line=False,
|
|
192
|
+
get_lines=True,
|
|
193
|
+
edit_lines=False,
|
|
194
|
+
diffs=False,
|
|
195
|
+
**kwargs
|
|
196
|
+
):
|
|
197
|
+
file_paths = findContent(
|
|
198
|
+
*args,
|
|
199
|
+
strings=strings,
|
|
200
|
+
total_strings=total_strings,
|
|
201
|
+
parse_lines=parse_lines,
|
|
202
|
+
spec_line=spec_line,
|
|
203
|
+
get_lines=get_lines,
|
|
204
|
+
diffs=diffs,
|
|
205
|
+
**kwargs
|
|
206
|
+
)
|
|
207
|
+
if edit_lines:
|
|
208
|
+
editLines(file_paths)
|
|
209
|
+
return file_paths
|
|
210
|
+
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# attach_functions.py — single helper you can import anywhere
|
|
2
2
|
# attach_dynamic.py
|
|
3
3
|
from __future__ import annotations
|
|
4
|
-
from .
|
|
4
|
+
from .find_collect import get_files_and_dirs
|
|
5
5
|
from ..imports import *
|
|
6
6
|
ABSPATH = os.path.abspath(__file__)
|
|
7
7
|
ABSROOT = os.path.dirname(ABSPATH)
|
|
8
|
+
|
|
8
9
|
def caller_path():
|
|
9
10
|
frame = inspect.stack()[1]
|
|
10
11
|
return os.path.abspath(frame.filename)
|
|
@@ -210,33 +211,37 @@ def get_for_all_tabs(root = None):
|
|
|
210
211
|
root = root or caller_path()
|
|
211
212
|
if os.path.isfile(root):
|
|
212
213
|
root = os.path.dirname(root)
|
|
213
|
-
all_tabs =
|
|
214
|
+
all_tabs = get_files_and_dirs(root,allowed_patterns='*Tab')[0]
|
|
215
|
+
|
|
214
216
|
for ROOT in all_tabs:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
else:
|
|
220
|
-
apply_inits(ROOT)
|
|
217
|
+
if os.path.isdir(ROOT):
|
|
218
|
+
[apply_inits(os.path.join(ROOT,func)) for func in os.listdir(ROOT) if 'functions' == os.path.splitext(func)[0]]
|
|
219
|
+
|
|
220
|
+
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
def apply_inits(ROOT):
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
224
|
+
filepaths=[ROOT]
|
|
225
|
+
TAB_DIR = os.path.dirname(ROOT)
|
|
226
|
+
INIT_FUNCS_PAPTH = os.path.join(TAB_DIR, "initFuncs.py")
|
|
227
|
+
if_fun_dir=False
|
|
228
|
+
## if os.path.isfile(ROOT):
|
|
229
|
+
## dirname= os.path.dirname(ROOT)
|
|
230
|
+
## basename= os.path.basename(ROOT)
|
|
231
|
+
## functions_dir = os.path.join(dirname,'functions')
|
|
232
|
+
## functions_path = os.path.join(functions_dir,basename)
|
|
233
|
+
## input(get_clean_imports(ROOT))
|
|
234
|
+
##
|
|
235
|
+
## os.makedirs(functions_dir,exist_ok=True)
|
|
236
|
+
## shutil.move(ROOT,functions_path)
|
|
237
|
+
## ROOT=functions_dir
|
|
238
|
+
if os.path.isdir(ROOT):
|
|
239
|
+
INIT_PATH = os.path.join(ROOT, "__init__.py")
|
|
237
240
|
|
|
238
|
-
|
|
239
|
-
|
|
241
|
+
filepaths = get_files_and_dirs(directory=ROOT,allowed_exts='py',add=True)[-1]
|
|
242
|
+
if_fun_dir=True
|
|
243
|
+
|
|
244
|
+
|
|
240
245
|
|
|
241
246
|
# Parse top-level def names
|
|
242
247
|
def extract_funcs(path: str):
|
|
@@ -246,7 +251,7 @@ def apply_inits(ROOT):
|
|
|
246
251
|
if m:
|
|
247
252
|
funcs.append(m.group(1))
|
|
248
253
|
return funcs
|
|
249
|
-
|
|
254
|
+
|
|
250
255
|
# Build functions/__init__.py that re-exports all discovered functions
|
|
251
256
|
import_lines = []
|
|
252
257
|
all_funcs = []
|
|
@@ -258,7 +263,7 @@ def apply_inits(ROOT):
|
|
|
258
263
|
all_funcs.extend(funcs)
|
|
259
264
|
if if_fun_dir:
|
|
260
265
|
functions_init = "\n".join(import_lines) + ("\n" if import_lines else "")
|
|
261
|
-
write_to_file(contents=functions_init, file_path=
|
|
266
|
+
write_to_file(contents=functions_init, file_path=INIT_PATH)
|
|
262
267
|
|
|
263
268
|
# Prepare the tuple literal of function names for import + loop
|
|
264
269
|
uniq_funcs = sorted(set(all_funcs))
|
|
@@ -267,9 +272,10 @@ def apply_inits(ROOT):
|
|
|
267
272
|
# Generate apiConsole/initFuncs.py using the safer setattr-loop
|
|
268
273
|
init_funcs_src = textwrap.dedent(f"""\
|
|
269
274
|
|
|
270
|
-
|
|
275
|
+
|
|
276
|
+
from abstract_utilities import get_logFile
|
|
271
277
|
from .functions import ({func_tuple})
|
|
272
|
-
|
|
278
|
+
logger=get_logFile(__name__)
|
|
273
279
|
def initFuncs(self):
|
|
274
280
|
try:
|
|
275
281
|
for f in ({func_tuple}):
|
|
@@ -279,8 +285,9 @@ def apply_inits(ROOT):
|
|
|
279
285
|
return self
|
|
280
286
|
""")
|
|
281
287
|
|
|
282
|
-
write_to_file(contents=init_funcs_src, file_path=
|
|
288
|
+
write_to_file(contents=init_funcs_src, file_path=INIT_FUNCS_PAPTH)
|
|
283
289
|
|
|
284
290
|
def call_for_all_tabs():
|
|
285
291
|
root = get_caller_dir(2)
|
|
292
|
+
|
|
286
293
|
get_for_all_tabs(root)
|