abstract-utilities 0.2.2.513__py3-none-any.whl → 0.2.2.583__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/class_utils/caller_utils.py +18 -0
- abstract_utilities/class_utils/global_utils.py +3 -2
- 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 +108 -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 +116 -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 +114 -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 +3 -9
- 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 +47 -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 +3 -2
- abstract_utilities/path_utils/path_utils.py +25 -23
- abstract_utilities/safe_utils/safe_utils.py +30 -0
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.583.dist-info}/METADATA +1 -1
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.583.dist-info}/RECORD +68 -28
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.583.dist-info}/WHEEL +0 -0
- {abstract_utilities-0.2.2.513.dist-info → abstract_utilities-0.2.2.583.dist-info}/top_level.txt +0 -0
|
@@ -5,68 +5,78 @@ def combine_params(*values,typ=None):
|
|
|
5
5
|
nu_values = None
|
|
6
6
|
for value in values:
|
|
7
7
|
if value is not None:
|
|
8
|
+
typ = typ or type(value)
|
|
8
9
|
if nu_values is None:
|
|
9
|
-
typ = typ or type(value)
|
|
10
10
|
nu_values = typ()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
|
|
12
|
+
if typ is set:
|
|
13
|
+
nu_values = nu_values | typ(value)
|
|
14
|
+
if typ is list:
|
|
15
|
+
nu_values += typ(value)
|
|
16
16
|
return nu_values
|
|
17
|
-
|
|
18
|
-
#
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
"image", "video", "audio", "presentation",
|
|
30
|
-
"spreadsheet", "archive", "executable"
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
_unallowed = set(get_media_exts(DEFAULT_EXCLUDE_TYPES)) | {
|
|
34
|
-
".bak", ".shp", ".cpg", ".dbf", ".shx", ".geojson",
|
|
35
|
-
".pyc", ".prj", ".sbn", ".sbx"
|
|
36
|
-
}
|
|
37
|
-
DEFAULT_UNALLOWED_EXTS = {e for e in _unallowed if e not in DEFAULT_ALLOWED_EXTS}
|
|
38
|
-
|
|
39
|
-
DEFAULT_EXCLUDE_DIRS: List[str] = [
|
|
40
|
-
"node_modules", "__pycache__", "backups", "backup",
|
|
41
|
-
"trash", "deprecated", "old", "__init__"
|
|
42
|
-
]
|
|
43
|
-
|
|
44
|
-
DEFAULT_EXCLUDE_PATTERNS: List[str] = [
|
|
45
|
-
"__init__*", "*.tmp", "*.log", "*.lock", "*.zip", "*~"
|
|
46
|
-
]
|
|
47
|
-
|
|
48
|
-
DEFAULT_ALLOWED_PATTERNS: List[str] = ["*"]
|
|
49
|
-
DEFAULT_ALLOWED_DIRS: List[str] = ["*"]
|
|
50
|
-
DEFAULT_ALLOWED_TYPES: List[str] = ["*"]
|
|
51
|
-
|
|
52
|
-
REMOTE_RE = re.compile(r"^(?P<host>[^:\s]+@[^:\s]+):(?P<path>/.*)$")
|
|
53
|
-
AllowedPredicate = Optional[Callable[[str], bool]]
|
|
54
|
-
|
|
55
|
-
# -------------------------
|
|
56
|
-
# Config dataclass
|
|
57
|
-
# -------------------------
|
|
17
|
+
def get_safe_kwargs(canonical_map, **kwargs):
|
|
18
|
+
# Lowercase all keys for safety
|
|
19
|
+
canonical_map = canonical_map or CANONICAL_MAP
|
|
20
|
+
norm_kwargs = {k.lower(): v for k, v in kwargs.items() if v is not None}
|
|
21
|
+
|
|
22
|
+
# Inverse lookup: alias → canonical key
|
|
23
|
+
alias_lookup = {
|
|
24
|
+
alias: canon
|
|
25
|
+
for canon, aliases in canonical_map.items()
|
|
26
|
+
if aliases
|
|
27
|
+
for alias in aliases
|
|
28
|
+
}
|
|
58
29
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
allowed_exts: Set[str]
|
|
62
|
-
unallowed_exts: Set[str]
|
|
63
|
-
allowed_types: Set[str]
|
|
64
|
-
exclude_types: Set[str]
|
|
65
|
-
allowed_dirs: List[str] = field(default_factory=list)
|
|
66
|
-
exclude_dirs: List[str] = field(default_factory=list)
|
|
67
|
-
allowed_patterns: List[str] = field(default_factory=list)
|
|
68
|
-
exclude_patterns: List[str] = field(default_factory=list)
|
|
30
|
+
# Preserve correctly named keys
|
|
31
|
+
safe_kwargs = {k: v for k, v in norm_kwargs.items() if k in canonical_map}
|
|
69
32
|
|
|
33
|
+
for k, v in norm_kwargs.items():
|
|
34
|
+
if k in alias_lookup:
|
|
35
|
+
canonical_key = alias_lookup[k]
|
|
36
|
+
prev = safe_kwargs.get(canonical_key)
|
|
37
|
+
if prev is None:
|
|
38
|
+
safe_kwargs[canonical_key] = v
|
|
39
|
+
else:
|
|
40
|
+
# merge intelligently if both exist
|
|
41
|
+
if isinstance(prev, (set, list)) and isinstance(v, (set, list)):
|
|
42
|
+
safe_kwargs[canonical_key] = list(set(prev) | set(v))
|
|
43
|
+
else:
|
|
44
|
+
safe_kwargs[canonical_key] = v # overwrite for non-iterables
|
|
45
|
+
|
|
46
|
+
# fill defaults if missing
|
|
47
|
+
for canon in canonical_map:
|
|
48
|
+
safe_kwargs.setdefault(canon, None)
|
|
49
|
+
|
|
50
|
+
return safe_kwargs
|
|
51
|
+
|
|
52
|
+
def create_canonical_map(*args,canonical_map=None):
|
|
53
|
+
keys = [arg for arg in args if arg]
|
|
54
|
+
if not keys:
|
|
55
|
+
return CANONICAL_MAP
|
|
56
|
+
canonical_map = canonical_map or CANONICAL_MAP
|
|
57
|
+
|
|
58
|
+
return {key:canonical_map.get(key) for key in keys}
|
|
59
|
+
def get_safe_canonical_kwargs(*args,canonical_map=None,**kwargs):
|
|
60
|
+
canonical_map = canonical_map or create_canonical_map(*args)
|
|
61
|
+
|
|
62
|
+
return get_safe_kwargs(canonical_map=canonical_map,**kwargs)
|
|
63
|
+
def get_dir_filter_kwargs(**kwargs):
|
|
64
|
+
canonical_map = create_canonical_map("directories")
|
|
65
|
+
return get_safe_kwargs(canonical_map=canonical_map,**kwargs)
|
|
66
|
+
def get_file_filter_kwargs(**kwargs):
|
|
67
|
+
"""
|
|
68
|
+
Normalize arbitrary keyword arguments for file scanning configuration.
|
|
69
|
+
|
|
70
|
+
Examples:
|
|
71
|
+
- 'excluded_ext' or 'unallowed_exts' → 'exclude_exts'
|
|
72
|
+
- 'include_dirs' or 'allow_dir' → 'allowed_dirs'
|
|
73
|
+
- 'excludePattern' or 'excluded_patterns' → 'exclude_patterns'
|
|
74
|
+
- 'allowed_type' or 'include_types' → 'allowed_types'
|
|
75
|
+
"""
|
|
76
|
+
# Canonical keys and aliases
|
|
77
|
+
canonical_keys =["allowed_exts","exclude_exts","allowed_types","exclude_types","allowed_dirs","exclude_dirs","allowed_patterns","exclude_patterns"]
|
|
78
|
+
|
|
79
|
+
return get_safe_canonical_kwargs(*canonical_keys,**kwargs)
|
|
70
80
|
# -------------------------
|
|
71
81
|
# Utility functions
|
|
72
82
|
# -------------------------
|
|
@@ -110,10 +120,12 @@ def ensure_patterns(patterns):
|
|
|
110
120
|
|
|
111
121
|
def _get_default_modular(value, default, add=False, typ=set):
|
|
112
122
|
"""Merge user and default values intelligently."""
|
|
113
|
-
if value
|
|
123
|
+
if value == None:
|
|
124
|
+
value = add
|
|
125
|
+
if value in [True]:
|
|
114
126
|
return default
|
|
115
127
|
if value is False:
|
|
116
|
-
return
|
|
128
|
+
return value
|
|
117
129
|
if add:
|
|
118
130
|
return combine_params(value,default,typ=None)
|
|
119
131
|
|
|
@@ -122,33 +134,63 @@ def _get_default_modular(value, default, add=False, typ=set):
|
|
|
122
134
|
# -------------------------
|
|
123
135
|
# Default derivation logic
|
|
124
136
|
# -------------------------
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
"
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
137
|
+
def _get_default_modular(value, default, add=None, typ=set):
|
|
138
|
+
"""Merge user and default values intelligently."""
|
|
139
|
+
add = add or False
|
|
140
|
+
if value == None:
|
|
141
|
+
value = add
|
|
142
|
+
if value in [True]:
|
|
143
|
+
return default
|
|
144
|
+
if value is False:
|
|
145
|
+
return value
|
|
146
|
+
if add:
|
|
147
|
+
return combine_params(value,default,typ=None)
|
|
148
|
+
return typ(value)
|
|
149
|
+
def derive_all_defaults(**kwargs):
|
|
150
|
+
kwargs = get_safe_canonical_kwargs(**kwargs)
|
|
151
|
+
add = kwargs.get("add",False)
|
|
152
|
+
nu_defaults = {}
|
|
153
|
+
for key,values in DEFAULT_CANONICAL_MAP.items():
|
|
154
|
+
default = values.get("default")
|
|
155
|
+
typ = values.get("type")
|
|
156
|
+
key_value = kwargs.get(key)
|
|
157
|
+
if key in DEFAULT_ALLOWED_EXCLUDE_MAP:
|
|
158
|
+
|
|
159
|
+
if key.endswith('exts'):
|
|
160
|
+
input_value = ensure_exts(key_value)
|
|
161
|
+
if key.endswith('patterns'):
|
|
162
|
+
input_value = ensure_patterns(key_value)
|
|
163
|
+
else:
|
|
164
|
+
input_value = _normalize_listlike(key_value, typ)
|
|
165
|
+
nu_defaults[key] = _get_default_modular(input_value, default, add, typ)
|
|
166
|
+
else:
|
|
167
|
+
value = default if key_value is None else key_value
|
|
168
|
+
if typ == list:
|
|
169
|
+
value = make_list(value)
|
|
170
|
+
elif typ == bool:
|
|
171
|
+
value = bool(value)
|
|
172
|
+
nu_defaults[key] = value
|
|
173
|
+
|
|
174
|
+
return nu_defaults
|
|
175
|
+
# -------------------------
|
|
176
|
+
# Default derivation logic
|
|
177
|
+
# -------------------------
|
|
178
|
+
def derive_file_defaults(**kwargs):
|
|
179
|
+
kwargs = derive_all_defaults(**kwargs)
|
|
180
|
+
add = kwargs.get("add",False)
|
|
181
|
+
nu_defaults = {}
|
|
182
|
+
for key,values in DEFAULT_ALLOWED_EXCLUDE_MAP.items():
|
|
183
|
+
default = values.get("default")
|
|
184
|
+
typ = values.get("type")
|
|
185
|
+
key_value = kwargs.get(key)
|
|
186
|
+
if key.endswith('exts'):
|
|
187
|
+
input_value = ensure_exts(key_value)
|
|
188
|
+
if key.endswith('patterns'):
|
|
189
|
+
input_value = ensure_patterns(key_value)
|
|
190
|
+
else:
|
|
191
|
+
input_value = _normalize_listlike(key_value, typ)
|
|
192
|
+
nu_defaults[key] = _get_default_modular(input_value, default, add, typ)
|
|
193
|
+
return nu_defaults
|
|
152
194
|
|
|
153
195
|
def define_defaults(**kwargs):
|
|
154
196
|
defaults = derive_file_defaults(**kwargs)
|
|
@@ -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)
|