abstract-utilities 0.2.2.480__py3-none-any.whl → 0.2.2.688__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of abstract-utilities might be problematic. Click here for more details.
- abstract_utilities/__init__.py +24 -16
- 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 +144 -0
- abstract_utilities/class_utils/caller_utils.py +92 -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 +71 -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/directory_utils/__init__.py +2 -0
- abstract_utilities/directory_utils/directory_utils.py +94 -0
- 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/name_utils.py +43 -0
- abstract_utilities/directory_utils/size_utils.py +57 -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/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/type_checks.py +2 -1
- abstract_utilities/file_utils/imports/classes.py +59 -55
- abstract_utilities/file_utils/imports/constants.py +84 -4
- abstract_utilities/file_utils/imports/imports.py +2 -21
- abstract_utilities/file_utils/imports/module_imports.py +3 -8
- abstract_utilities/file_utils/module_imports.py +12 -0
- abstract_utilities/file_utils/src/__init__.py +7 -0
- abstract_utilities/file_utils/src/file_filters/__init__.py +1 -0
- abstract_utilities/file_utils/src/file_filters/ensure_utils.py +490 -0
- abstract_utilities/file_utils/src/file_filters/filter_params.py +150 -0
- abstract_utilities/file_utils/src/file_filters/filter_utils.py +78 -0
- abstract_utilities/file_utils/src/file_filters/predicate_utils.py +44 -0
- abstract_utilities/file_utils/src/file_filters.py +177 -0
- abstract_utilities/file_utils/src/file_reader.py +543 -0
- abstract_utilities/file_utils/src/file_utils.py +156 -0
- abstract_utilities/file_utils/src/filter_params.py +197 -0
- abstract_utilities/file_utils/src/find_collect.py +200 -0
- abstract_utilities/file_utils/src/find_content.py +210 -0
- abstract_utilities/file_utils/src/initFunctionsGen.py +293 -0
- abstract_utilities/file_utils/src/initFunctionsGens.py +280 -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/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/src/type_checks.py +91 -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/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/circular_import_finder.py +222 -0
- abstract_utilities/import_utils/circular_import_finder2.py +118 -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/init_imports.py +3 -0
- abstract_utilities/import_utils/imports/module_imports.py +9 -0
- abstract_utilities/import_utils/imports/utils.py +30 -0
- abstract_utilities/import_utils/src/__init__.py +8 -0
- abstract_utilities/import_utils/src/clean_imports.py +278 -0
- abstract_utilities/import_utils/src/dot_utils.py +80 -0
- abstract_utilities/import_utils/src/extract_utils.py +46 -0
- abstract_utilities/import_utils/src/import_functions.py +110 -0
- abstract_utilities/import_utils/src/import_utils.py +349 -0
- abstract_utilities/import_utils/src/layze_import_utils/__init__.py +2 -0
- abstract_utilities/import_utils/src/layze_import_utils/lazy_utils.py +41 -0
- abstract_utilities/import_utils/src/layze_import_utils/nullProxy.py +37 -0
- abstract_utilities/import_utils/src/nullProxy.py +30 -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 +194 -0
- abstract_utilities/import_utils/src/sysroot_utils.py +112 -0
- abstract_utilities/imports.py +21 -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 +777 -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 +202 -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 +162 -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 +539 -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 +248 -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 +439 -0
- abstract_utilities/read_write_utils.py +113 -62
- 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 +166 -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_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 +1 -1
- 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 +7 -0
- abstract_utilities/type_utils/alpha_utils.py +59 -0
- abstract_utilities/type_utils/get_type.py +120 -0
- abstract_utilities/type_utils/imports/__init__.py +3 -0
- abstract_utilities/type_utils/imports/constants.py +134 -0
- abstract_utilities/type_utils/imports/imports.py +4 -0
- abstract_utilities/type_utils/imports/module_imports.py +25 -0
- abstract_utilities/type_utils/is_type.py +455 -0
- abstract_utilities/type_utils/make_type.py +126 -0
- abstract_utilities/type_utils/mime_types.py +68 -0
- abstract_utilities/type_utils/num_utils.py +19 -0
- abstract_utilities/type_utils/type_utils.py +104 -0
- {abstract_utilities-0.2.2.480.dist-info → abstract_utilities-0.2.2.688.dist-info}/METADATA +1 -1
- abstract_utilities-0.2.2.688.dist-info/RECORD +288 -0
- imports/__init__.py +36 -0
- abstract_utilities-0.2.2.480.dist-info/RECORD +0 -92
- {abstract_utilities-0.2.2.480.dist-info → abstract_utilities-0.2.2.688.dist-info}/WHEEL +0 -0
- {abstract_utilities-0.2.2.480.dist-info → abstract_utilities-0.2.2.688.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"""
|
|
2
|
+
read_write_utils.py
|
|
3
|
+
-------------------
|
|
4
|
+
Unified read/write utility for safe file operations.
|
|
5
|
+
Supports:
|
|
6
|
+
- Writing content to a file
|
|
7
|
+
- Reading content from a file
|
|
8
|
+
- Creating and reading if missing
|
|
9
|
+
- Detecting file/content params via positional args or kwargs
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
from abstract_utilities.read_write_utils import *
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .imports import *
|
|
16
|
+
_FILE_PATH_KEYS = ['file', 'filepath', 'file_path', 'path', 'directory', 'f', 'dst', 'dest']
|
|
17
|
+
_CONTENTS_KEYS = ['cont', 'content', 'contents', 'data', 'datas', 'dat', 'src', 'source']
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
import uuid
|
|
20
|
+
import shlex
|
|
21
|
+
|
|
22
|
+
_STAGE_ROOT = Path("/var/tmp/abstract_stage")
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _stage_file(contents: str, suffix=".tmp") -> Path:
|
|
26
|
+
"""
|
|
27
|
+
Write contents to a local staging file.
|
|
28
|
+
"""
|
|
29
|
+
_STAGE_ROOT.mkdir(parents=True, exist_ok=True)
|
|
30
|
+
path = _STAGE_ROOT / f"{uuid.uuid4().hex}{suffix}"
|
|
31
|
+
path.write_text(str(contents), encoding="utf-8")
|
|
32
|
+
return path
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _install_file(staged: Path, dest: str, **kwargs) -> str:
|
|
36
|
+
"""
|
|
37
|
+
Atomically install a staged file to destination using sudo install.
|
|
38
|
+
"""
|
|
39
|
+
cmd = (
|
|
40
|
+
f"sudo install -D -m 0644 "
|
|
41
|
+
f"{shlex.quote(str(staged))} "
|
|
42
|
+
f"{shlex.quote(dest)}"
|
|
43
|
+
)
|
|
44
|
+
return run_local_cmd(
|
|
45
|
+
cmd=cmd,
|
|
46
|
+
password=kwargs.get("password"),
|
|
47
|
+
key=kwargs.get("key"),
|
|
48
|
+
env_path=kwargs.get("env_path"),
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
# --- Helper utilities --------------------------------------------------------
|
|
53
|
+
def string_in_keys(strings, kwargs):
|
|
54
|
+
"""Find a matching keyword in kwargs that contains any of the given substrings."""
|
|
55
|
+
for key in kwargs:
|
|
56
|
+
for s in strings:
|
|
57
|
+
if s.lower() in key.lower():
|
|
58
|
+
return key
|
|
59
|
+
return None
|
|
60
|
+
def make_dirs(path, exist_ok=True, **kwargs):
|
|
61
|
+
remote = get_user_pass_host_key(**kwargs)
|
|
62
|
+
|
|
63
|
+
if remote:
|
|
64
|
+
kwargs['cmd'] = f"mkdir -p {path}"
|
|
65
|
+
|
|
66
|
+
resp = run_pruned_func(run_cmd, **kwargs)
|
|
67
|
+
|
|
68
|
+
else:
|
|
69
|
+
os.makedirs(path, exist_ok=exist_ok)
|
|
70
|
+
return path
|
|
71
|
+
def make_path(path, home_dir=None, file=None, **kwargs):
|
|
72
|
+
if not path:
|
|
73
|
+
return None
|
|
74
|
+
|
|
75
|
+
basename = os.path.basename(path)
|
|
76
|
+
parts = [p for p in path.split('/') if p]
|
|
77
|
+
|
|
78
|
+
# Detect whether this is a file or a folder
|
|
79
|
+
is_file = file if file is not None else ('.' in basename)
|
|
80
|
+
pieces = parts[:-1] if is_file else parts
|
|
81
|
+
|
|
82
|
+
full_dir = home_dir or '/'
|
|
83
|
+
for piece in pieces:
|
|
84
|
+
full_dir = os.path.join(full_dir, piece)
|
|
85
|
+
make_dirs(full_dir, exist_ok=True, **kwargs)
|
|
86
|
+
|
|
87
|
+
if is_file:
|
|
88
|
+
full_dir = os.path.join(full_dir, basename)
|
|
89
|
+
|
|
90
|
+
return full_dir
|
|
91
|
+
def get_rel_path(src,src_rel,dst,**kwargs):
|
|
92
|
+
if src.startswith(src_rel):
|
|
93
|
+
nu_src = src[len(src_rel):]
|
|
94
|
+
nu_src= eatAll(nu_src,'/')
|
|
95
|
+
directory= eatOuter(dst,'/')
|
|
96
|
+
rel_path = os.path.join(dst,nu_src)
|
|
97
|
+
return rel_path
|
|
98
|
+
def make_relative_path(src,src_rel,dst,**kwargs):
|
|
99
|
+
|
|
100
|
+
if src.startswith(src_rel):
|
|
101
|
+
rel_path = get_rel_path(src,src_rel,dst)
|
|
102
|
+
|
|
103
|
+
path = make_path(rel_path,**kwargs)
|
|
104
|
+
|
|
105
|
+
return path
|
|
106
|
+
|
|
107
|
+
def path_join(*args):
|
|
108
|
+
path = None
|
|
109
|
+
for i,arg in enumerate(args):
|
|
110
|
+
if arg:
|
|
111
|
+
if i == 0:
|
|
112
|
+
path = arg
|
|
113
|
+
else:
|
|
114
|
+
path = os.path.join(path,arg)
|
|
115
|
+
return path
|
|
116
|
+
|
|
117
|
+
def get_path(paths,**kwargs):
|
|
118
|
+
"""Return the first valid path among given paths."""
|
|
119
|
+
for path in paths:
|
|
120
|
+
if isinstance(path, str):
|
|
121
|
+
if is_file(path,**kwargs):
|
|
122
|
+
return path
|
|
123
|
+
dirname = os.path.dirname(path)
|
|
124
|
+
if is_exists(dirname,**kwargs):
|
|
125
|
+
return path
|
|
126
|
+
return None
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def break_down_find_existing(path,**kwargs):
|
|
130
|
+
"""Return the first non-existent subpath within a path chain."""
|
|
131
|
+
test_path = ''
|
|
132
|
+
for part in path.split(os.sep):
|
|
133
|
+
test_path = os.path.join(test_path, part)
|
|
134
|
+
if not is_exists(test_path,**kwargs):
|
|
135
|
+
return test_path if test_path else None
|
|
136
|
+
return test_path
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
# --- Parameter parsing --------------------------------------------------------
|
|
140
|
+
def check_read_write_params(*args, **kwargs):
|
|
141
|
+
"""
|
|
142
|
+
Determine file_path and contents from arguments.
|
|
143
|
+
Returns a tuple: (file_path, contents)
|
|
144
|
+
"""
|
|
145
|
+
file_key = string_in_keys(_FILE_PATH_KEYS, kwargs)
|
|
146
|
+
content_key = string_in_keys(_CONTENTS_KEYS, kwargs)
|
|
147
|
+
|
|
148
|
+
file_path = kwargs.get(file_key) if file_key else None
|
|
149
|
+
contents = kwargs.get(content_key) if content_key else None
|
|
150
|
+
|
|
151
|
+
# Handle positional args (fallback)
|
|
152
|
+
if file_path is None and len(args) > 0:
|
|
153
|
+
file_path = args[0]
|
|
154
|
+
if contents is None and len(args) > 1:
|
|
155
|
+
contents = args[1]
|
|
156
|
+
|
|
157
|
+
if file_path is None:
|
|
158
|
+
raise ValueError("Missing file_path argument.")
|
|
159
|
+
return file_path, contents
|
|
160
|
+
|
|
161
|
+
def write_to_path(
|
|
162
|
+
file_path: str,
|
|
163
|
+
contents: str,
|
|
164
|
+
*,
|
|
165
|
+
user_at_host: str = None,
|
|
166
|
+
cwd: str | None = None,
|
|
167
|
+
password=None,
|
|
168
|
+
key=None,
|
|
169
|
+
env_path=None,
|
|
170
|
+
**kwargs
|
|
171
|
+
) -> str:
|
|
172
|
+
"""
|
|
173
|
+
Completely overwrite a file (locally or remotely).
|
|
174
|
+
Supports sudo and password-based remote execution.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
# sanitize for shell safety
|
|
178
|
+
quoted_path = shlex.quote(file_path)
|
|
179
|
+
quoted_data = shlex.quote(str(contents))
|
|
180
|
+
|
|
181
|
+
# shell command that fully overwrites
|
|
182
|
+
# (no append, replaces contents entirely)
|
|
183
|
+
base_cmd = f'sudo sh -c "echo {quoted_data} > {quoted_path}"'
|
|
184
|
+
|
|
185
|
+
# optional sudo password injection
|
|
186
|
+
full_cmd = get_print_sudo_cmd(
|
|
187
|
+
cmd=base_cmd,
|
|
188
|
+
password=password,
|
|
189
|
+
key=key,
|
|
190
|
+
env_path=env_path
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# local or remote dispatch
|
|
194
|
+
if user_at_host:
|
|
195
|
+
return run_remote_cmd(
|
|
196
|
+
user_at_host=user_at_host,
|
|
197
|
+
cmd=full_cmd,
|
|
198
|
+
cwd=cwd,
|
|
199
|
+
password=password,
|
|
200
|
+
key=key,
|
|
201
|
+
env_path=env_path,
|
|
202
|
+
**kwargs
|
|
203
|
+
)
|
|
204
|
+
else:
|
|
205
|
+
return run_local_cmd(
|
|
206
|
+
cmd=full_cmd,
|
|
207
|
+
cwd=cwd,
|
|
208
|
+
password=password,
|
|
209
|
+
key=key,
|
|
210
|
+
env_path=env_path,
|
|
211
|
+
**kwargs
|
|
212
|
+
)
|
|
213
|
+
### --- Core functionality -------------------------------------------------------
|
|
214
|
+
##def write_to_file(*args, **kwargs):
|
|
215
|
+
## """
|
|
216
|
+
## Write contents to a file (create if missing).
|
|
217
|
+
##
|
|
218
|
+
## Returns the file_path written.
|
|
219
|
+
## """
|
|
220
|
+
## file_path, contents = check_read_write_params(*args, **kwargs)
|
|
221
|
+
## if contents is None:
|
|
222
|
+
## raise ValueError("Missing contents to write.")
|
|
223
|
+
##
|
|
224
|
+
## os.makedirs(os.path.dirname(file_path) or ".", exist_ok=True)
|
|
225
|
+
## with open(file_path, "w", encoding="utf-8") as f:
|
|
226
|
+
## f.write(str(contents))
|
|
227
|
+
## return file_path
|
|
228
|
+
# --- Core functionality -------------------------------------------------------
|
|
229
|
+
##def write_to_file(*args, **kwargs):
|
|
230
|
+
## """
|
|
231
|
+
## Write contents to a file (create if missing).
|
|
232
|
+
##
|
|
233
|
+
## Returns the file_path written.
|
|
234
|
+
## """
|
|
235
|
+
## file_path, contents = check_read_write_params(*args, **kwargs)
|
|
236
|
+
## values,kwargs = get_from_kwargs(['file_path','contents'],del_kwarg=True,**kwargs)
|
|
237
|
+
## dirname = os.path.dirname(file_path)
|
|
238
|
+
##
|
|
239
|
+
## if contents is None:
|
|
240
|
+
## raise ValueError("Missing contents to write.")
|
|
241
|
+
## user_at_host = kwargs.get("user_at_host")
|
|
242
|
+
## if get_user_pass_host_key(**kwargs):
|
|
243
|
+
## make_dirs(dirname, exist_ok=True,**kwargs)
|
|
244
|
+
## kwargs["cwd"] = kwargs.get('cwd') or os.path.dirname(file_path)
|
|
245
|
+
## # sanitize for shell safety
|
|
246
|
+
## quoted_path = shlex.quote(file_path)
|
|
247
|
+
## quoted_data = shlex.quote(str(contents))
|
|
248
|
+
## # shell command that fully overwrites
|
|
249
|
+
## # (no append, replaces contents entirely)
|
|
250
|
+
## kwargs["cmd"] = f'sh -c "echo {quoted_data} > {quoted_path}"'
|
|
251
|
+
## if not kwargs.get('password') and not kwargs.get('key'):
|
|
252
|
+
## kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
|
|
253
|
+
## result = run_pruned_func(run_cmd,**kwargs)
|
|
254
|
+
## if 'file_path' in kwargs:
|
|
255
|
+
## del kwargs['file_path']
|
|
256
|
+
## if not is_file(file_path,**kwargs) or str(contents) != read_from_file(file_path,**kwargs):
|
|
257
|
+
## kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
|
|
258
|
+
## result = run_pruned_func(run_cmd,**kwargs)
|
|
259
|
+
## return result
|
|
260
|
+
##
|
|
261
|
+
## make_dirs(dirname or ".", exist_ok=True)
|
|
262
|
+
## with open(file_path, "w", encoding="utf-8") as f:
|
|
263
|
+
## f.write(str(contents))
|
|
264
|
+
## return file_path
|
|
265
|
+
|
|
266
|
+
def _should_use_remote(**kwargs) -> bool:
|
|
267
|
+
"""
|
|
268
|
+
Only use remote mode IF:
|
|
269
|
+
- user_at_host is provided
|
|
270
|
+
- AND password/key is provided
|
|
271
|
+
Otherwise: local write.
|
|
272
|
+
"""
|
|
273
|
+
user = kwargs.get("user_at_host")
|
|
274
|
+
if not user:
|
|
275
|
+
return False # not remote
|
|
276
|
+
|
|
277
|
+
# If user_at_host is provided, then password or key MUST be present
|
|
278
|
+
if kwargs.get("password") or kwargs.get("key"):
|
|
279
|
+
return True
|
|
280
|
+
|
|
281
|
+
return False # user provided but no auth → treat as local
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _write_to_file(contents: str, file_path: str, **kwargs) -> str:
|
|
285
|
+
"""
|
|
286
|
+
Unified writer using stage → install model.
|
|
287
|
+
"""
|
|
288
|
+
|
|
289
|
+
remote = _should_use_remote(**kwargs)
|
|
290
|
+
|
|
291
|
+
# --- Remote path (unchanged conceptually) ---
|
|
292
|
+
if remote:
|
|
293
|
+
tmp_path = _stage_file(contents)
|
|
294
|
+
|
|
295
|
+
user_at_host = kwargs["user_at_host"]
|
|
296
|
+
password = kwargs.get("password")
|
|
297
|
+
key = kwargs.get("key")
|
|
298
|
+
|
|
299
|
+
# copy staged file
|
|
300
|
+
scp_cmd = (
|
|
301
|
+
f"scp {shlex.quote(str(tmp_path))} "
|
|
302
|
+
f"{shlex.quote(user_at_host)}:{shlex.quote(file_path)}"
|
|
303
|
+
)
|
|
304
|
+
return run_pruned_func(
|
|
305
|
+
run_local_cmd,
|
|
306
|
+
cmd=scp_cmd,
|
|
307
|
+
password=password,
|
|
308
|
+
key=key,
|
|
309
|
+
**kwargs
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
# --- Local path ---
|
|
313
|
+
try:
|
|
314
|
+
# Attempt direct write for non-privileged paths
|
|
315
|
+
os.makedirs(os.path.dirname(file_path) or ".", exist_ok=True)
|
|
316
|
+
with open(file_path, "w", encoding="utf-8") as f:
|
|
317
|
+
f.write(str(contents))
|
|
318
|
+
return file_path
|
|
319
|
+
|
|
320
|
+
except (PermissionError, FileNotFoundError):
|
|
321
|
+
# Privileged path → stage + install
|
|
322
|
+
staged = _stage_file(contents)
|
|
323
|
+
return _install_file(staged, file_path, **kwargs)
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
def write_to_file(*, contents: str, file_path: str, **kwargs):
|
|
328
|
+
"""
|
|
329
|
+
Error-handled public writer.
|
|
330
|
+
"""
|
|
331
|
+
try:
|
|
332
|
+
return _write_to_file(contents=contents, file_path=file_path, **kwargs)
|
|
333
|
+
except Exception as e:
|
|
334
|
+
print("WRITE ERROR:", e)
|
|
335
|
+
raise RuntimeError(f"Failed writing: {file_path}")
|
|
336
|
+
def read_from_file(file_path=None,**kwargs):
|
|
337
|
+
if get_user_pass_host_key(**kwargs):
|
|
338
|
+
kwargs["cwd"] = kwargs.get('cwd') or os.path.dirname(file_path)
|
|
339
|
+
basename = os.path.basename(file_path)
|
|
340
|
+
kwargs["cmd"] = f'cat {basename}'
|
|
341
|
+
return run_pruned_func(run_cmd,**kwargs)
|
|
342
|
+
"""Read text content from a file."""
|
|
343
|
+
with open(file_path, "r", encoding="utf-8") as f:
|
|
344
|
+
return f.read()
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
def copy_dirs(dirs, dst_root, src_rel=None, **kwargs):
|
|
348
|
+
"""
|
|
349
|
+
Recursively copy directory structures (without files) from dirs → dst_root.
|
|
350
|
+
"""
|
|
351
|
+
for src in dirs:
|
|
352
|
+
# build destination path preserving relative structure
|
|
353
|
+
dst_path = make_relative_path(src, src_rel, dst_root, **kwargs) if src_rel else dst_root
|
|
354
|
+
make_path(dst_path, **kwargs) # ensures directory exists
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
def copy_file(src, dst_root, src_rel=None, **kwargs):
|
|
359
|
+
"""
|
|
360
|
+
Copy a single file to dst_root, preserving relative structure if src_rel provided.
|
|
361
|
+
Supports remote copy via read/write.
|
|
362
|
+
"""
|
|
363
|
+
# derive destination file path
|
|
364
|
+
dst_path = make_relative_path(src, src_rel, dst_root, **kwargs) if src_rel else os.path.join(dst_root, os.path.basename(src))
|
|
365
|
+
make_path(dst_path, **kwargs)
|
|
366
|
+
|
|
367
|
+
if get_user_pass_host_key(**kwargs): # remote mode
|
|
368
|
+
contents = read_from_file(src, **kwargs)
|
|
369
|
+
write_to_file(contents=contents, file_path=dst_path, **kwargs)
|
|
370
|
+
else: # local
|
|
371
|
+
os.makedirs(os.path.dirname(dst_path), exist_ok=True)
|
|
372
|
+
shutil.copy2(src, dst_path)
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
return dst_path
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
def copy_files(files, dst_root, src_rel=None, **kwargs):
|
|
379
|
+
"""
|
|
380
|
+
Copy a list of files to dst_root.
|
|
381
|
+
"""
|
|
382
|
+
for src in files:
|
|
383
|
+
copy_file(src=src, dst_root=dst_root, src_rel=src_rel, **kwargs)
|
|
384
|
+
|
|
385
|
+
def create_and_read_file(*args, **kwargs):
|
|
386
|
+
"""
|
|
387
|
+
Create the file (if missing) and read contents from it.
|
|
388
|
+
"""
|
|
389
|
+
file_path, contents = check_read_write_params(*args, **kwargs)
|
|
390
|
+
if not os.path.isfile(file_path):
|
|
391
|
+
write_to_file(file_path, contents or "")
|
|
392
|
+
return read_from_file(file_path)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def is_file_extension(obj: str) -> bool:
|
|
396
|
+
"""Return True if obj looks like a filename with extension."""
|
|
397
|
+
if not isinstance(obj, str):
|
|
398
|
+
return False
|
|
399
|
+
root, ext = os.path.splitext(obj)
|
|
400
|
+
return bool(root and ext)
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
def delete_file(file_path: str):
|
|
404
|
+
"""Safely delete a file if it exists."""
|
|
405
|
+
if os.path.isfile(file_path):
|
|
406
|
+
os.remove(file_path)
|
|
407
|
+
return True
|
|
408
|
+
return False
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def get_content_lines(*args, **kwargs):
|
|
412
|
+
"""Return a list of lines from string or file path."""
|
|
413
|
+
file_path, contents = check_read_write_params(*args, **kwargs)
|
|
414
|
+
if os.path.isfile(file_path):
|
|
415
|
+
contents = read_from_file(filepath)
|
|
416
|
+
|
|
417
|
+
if isinstance(contents, str):
|
|
418
|
+
return contents.splitlines()
|
|
419
|
+
elif isinstance(contents, list):
|
|
420
|
+
return contents
|
|
421
|
+
return []
|
|
422
|
+
def collate_text_docs(directory=None):
|
|
423
|
+
return [read_from_file(item) for item in get_all_files(directory=directory)]
|
|
424
|
+
def get_content(*paths):
|
|
425
|
+
item_path = os.path.join(*paths)
|
|
426
|
+
if os.path.isfile(item_path):
|
|
427
|
+
try:
|
|
428
|
+
content = read_from_file(item_path)
|
|
429
|
+
return content
|
|
430
|
+
except:
|
|
431
|
+
pass
|
|
432
|
+
return None
|
|
433
|
+
def get_text_or_read(text=None,file_path=None):
|
|
434
|
+
text = text or ''
|
|
435
|
+
imports_js = {}
|
|
436
|
+
if not text and file_path and os.path.isfile(file_path):
|
|
437
|
+
text=read_from_file(file_path)
|
|
438
|
+
return text
|
|
439
|
+
##
|
|
@@ -12,11 +12,12 @@ Usage:
|
|
|
12
12
|
from abstract_utilities.read_write_utils import *
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
import os
|
|
16
|
-
import
|
|
15
|
+
import os,shlex
|
|
16
|
+
from .string_clean import *
|
|
17
17
|
from .ssh_utils.utils import run_cmd,get_print_sudo_cmd,run_local_cmd,run_remote_cmd
|
|
18
|
-
from .file_utils.file_utils.type_checks import is_file,is_dir,get_user_pass_host_key,is_exists
|
|
19
18
|
from .abstract_classes import run_pruned_func
|
|
19
|
+
from .string_utils import get_from_kwargs
|
|
20
|
+
from .path_utils import get_all_files,is_file,is_dir,get_user_pass_host_key,is_exists
|
|
20
21
|
_FILE_PATH_KEYS = ['file', 'filepath', 'file_path', 'path', 'directory', 'f', 'dst', 'dest']
|
|
21
22
|
_CONTENTS_KEYS = ['cont', 'content', 'contents', 'data', 'datas', 'dat', 'src', 'source']
|
|
22
23
|
|
|
@@ -29,15 +30,53 @@ def string_in_keys(strings, kwargs):
|
|
|
29
30
|
if s.lower() in key.lower():
|
|
30
31
|
return key
|
|
31
32
|
return None
|
|
33
|
+
def make_dirs(path, exist_ok=True, **kwargs):
|
|
34
|
+
remote = get_user_pass_host_key(**kwargs)
|
|
35
|
+
|
|
36
|
+
if remote:
|
|
37
|
+
kwargs['cmd'] = f"mkdir -p {path}"
|
|
38
|
+
|
|
39
|
+
resp = run_pruned_func(run_cmd, **kwargs)
|
|
40
|
+
|
|
41
|
+
else:
|
|
42
|
+
os.makedirs(path, exist_ok=exist_ok)
|
|
43
|
+
return path
|
|
44
|
+
def make_path(path, home_dir=None, file=None, **kwargs):
|
|
45
|
+
if not path:
|
|
46
|
+
return None
|
|
47
|
+
|
|
48
|
+
basename = os.path.basename(path)
|
|
49
|
+
parts = [p for p in path.split('/') if p]
|
|
50
|
+
|
|
51
|
+
# Detect whether this is a file or a folder
|
|
52
|
+
is_file = file if file is not None else ('.' in basename)
|
|
53
|
+
pieces = parts[:-1] if is_file else parts
|
|
54
|
+
|
|
55
|
+
full_dir = home_dir or '/'
|
|
56
|
+
for piece in pieces:
|
|
57
|
+
full_dir = os.path.join(full_dir, piece)
|
|
58
|
+
make_dirs(full_dir, exist_ok=True, **kwargs)
|
|
59
|
+
|
|
60
|
+
if is_file:
|
|
61
|
+
full_dir = os.path.join(full_dir, basename)
|
|
62
|
+
|
|
63
|
+
return full_dir
|
|
64
|
+
def get_rel_path(src,src_rel,dst,**kwargs):
|
|
65
|
+
if src.startswith(src_rel):
|
|
66
|
+
nu_src = src[len(src_rel):]
|
|
67
|
+
nu_src= eatAll(nu_src,'/')
|
|
68
|
+
directory= eatOuter(dst,'/')
|
|
69
|
+
rel_path = os.path.join(dst,nu_src)
|
|
70
|
+
return rel_path
|
|
71
|
+
def make_relative_path(src,src_rel,dst,**kwargs):
|
|
72
|
+
|
|
73
|
+
if src.startswith(src_rel):
|
|
74
|
+
rel_path = get_rel_path(src,src_rel,dst)
|
|
75
|
+
|
|
76
|
+
path = make_path(rel_path,**kwargs)
|
|
77
|
+
|
|
78
|
+
return path
|
|
32
79
|
|
|
33
|
-
def make_dirs(path,exist_ok=True,**kwargs):
|
|
34
|
-
if exist_ok or (not exist_ok and not is_dir(path,**kwargs)):
|
|
35
|
-
if get_user_pass_host_key(**kwargs):
|
|
36
|
-
kwargs['cmd']=f"mkdir {path}"
|
|
37
|
-
run_cmd(**kwargs)
|
|
38
|
-
else:
|
|
39
|
-
os.makedirs(path,exist_ok=exist_ok)
|
|
40
|
-
return ext_dir
|
|
41
80
|
def path_join(*args):
|
|
42
81
|
path = None
|
|
43
82
|
for i,arg in enumerate(args):
|
|
@@ -47,25 +86,7 @@ def path_join(*args):
|
|
|
47
86
|
else:
|
|
48
87
|
path = os.path.join(path,arg)
|
|
49
88
|
return path
|
|
50
|
-
|
|
51
|
-
if path:
|
|
52
|
-
basename = os.path.basename(path)
|
|
53
|
-
parts = path.split('/')
|
|
54
|
-
parts = [part for part in parts if part]
|
|
55
|
-
|
|
56
|
-
full_dir = home_dir or ''
|
|
57
|
-
if file == True or (file == None and ('.' in basename)):
|
|
58
|
-
pieces = parts[:-1] if len(parts) > 1 else []
|
|
59
|
-
else:
|
|
60
|
-
pieces=parts
|
|
61
|
-
basename=None
|
|
62
|
-
for piece in pieces:
|
|
63
|
-
full_dir = os.path.join(full_dir,piece)
|
|
64
|
-
make_dirs(full_dir,exist_ok=True,**kwargs)
|
|
65
|
-
if basename:
|
|
66
|
-
full_dir=path_join(full_dir,basename)
|
|
67
|
-
print(f"full_dir == {full_dir}")
|
|
68
|
-
return full_dir
|
|
89
|
+
|
|
69
90
|
def get_path(paths,**kwargs):
|
|
70
91
|
"""Return the first valid path among given paths."""
|
|
71
92
|
for path in paths:
|
|
@@ -73,7 +94,7 @@ def get_path(paths,**kwargs):
|
|
|
73
94
|
if is_file(path,**kwargs):
|
|
74
95
|
return path
|
|
75
96
|
dirname = os.path.dirname(path)
|
|
76
|
-
if is_exists(dirname):
|
|
97
|
+
if is_exists(dirname,**kwargs):
|
|
77
98
|
return path
|
|
78
99
|
return None
|
|
79
100
|
|
|
@@ -83,7 +104,7 @@ def break_down_find_existing(path,**kwargs):
|
|
|
83
104
|
test_path = ''
|
|
84
105
|
for part in path.split(os.sep):
|
|
85
106
|
test_path = os.path.join(test_path, part)
|
|
86
|
-
if not is_exists(test_path):
|
|
107
|
+
if not is_exists(test_path,**kwargs):
|
|
87
108
|
return test_path if test_path else None
|
|
88
109
|
return test_path
|
|
89
110
|
|
|
@@ -133,7 +154,7 @@ def write_to_path(
|
|
|
133
154
|
# shell command that fully overwrites
|
|
134
155
|
# (no append, replaces contents entirely)
|
|
135
156
|
base_cmd = f'sudo sh -c "echo {quoted_data} > {quoted_path}"'
|
|
136
|
-
|
|
157
|
+
|
|
137
158
|
# optional sudo password injection
|
|
138
159
|
full_cmd = get_print_sudo_cmd(
|
|
139
160
|
cmd=base_cmd,
|
|
@@ -185,6 +206,7 @@ def write_to_file(*args, **kwargs):
|
|
|
185
206
|
Returns the file_path written.
|
|
186
207
|
"""
|
|
187
208
|
file_path, contents = check_read_write_params(*args, **kwargs)
|
|
209
|
+
values,kwargs = get_from_kwargs(['file_path','contents'],del_kwarg=True,**kwargs)
|
|
188
210
|
dirname = os.path.dirname(file_path)
|
|
189
211
|
|
|
190
212
|
if contents is None:
|
|
@@ -202,6 +224,8 @@ def write_to_file(*args, **kwargs):
|
|
|
202
224
|
if not kwargs.get('password') and not kwargs.get('key'):
|
|
203
225
|
kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
|
|
204
226
|
result = run_pruned_func(run_cmd,**kwargs)
|
|
227
|
+
if 'file_path' in kwargs:
|
|
228
|
+
del kwargs['file_path']
|
|
205
229
|
if not is_file(file_path,**kwargs) or str(contents) != read_from_file(file_path,**kwargs):
|
|
206
230
|
kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
|
|
207
231
|
result = run_pruned_func(run_cmd,**kwargs)
|
|
@@ -222,36 +246,45 @@ def read_from_file(file_path,**kwargs):
|
|
|
222
246
|
"""Read text content from a file."""
|
|
223
247
|
with open(file_path, "r", encoding="utf-8") as f:
|
|
224
248
|
return f.read()
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
print(f"src == {src}\nsrc_rel == {src_rel}\ndirectory == {directory}")
|
|
232
|
-
if src.startswith(src_rel):
|
|
233
|
-
rel_path = get_rel_path(src,src_rel,directory)
|
|
234
|
-
path = make_path(src,home_dir=rel_path,**kwargs)
|
|
235
|
-
print(f"path == {path}")
|
|
236
|
-
return path
|
|
237
|
-
def copy_dirs(dirs,dst,src_rel=None,**kwargs):
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def copy_dirs(dirs, dst_root, src_rel=None, **kwargs):
|
|
252
|
+
"""
|
|
253
|
+
Recursively copy directory structures (without files) from dirs → dst_root.
|
|
254
|
+
"""
|
|
238
255
|
for src in dirs:
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
make_path(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
# build destination path preserving relative structure
|
|
257
|
+
dst_path = make_relative_path(src, src_rel, dst_root, **kwargs) if src_rel else dst_root
|
|
258
|
+
make_path(dst_path, **kwargs) # ensures directory exists
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def copy_file(src, dst_root, src_rel=None, **kwargs):
|
|
263
|
+
"""
|
|
264
|
+
Copy a single file to dst_root, preserving relative structure if src_rel provided.
|
|
265
|
+
Supports remote copy via read/write.
|
|
266
|
+
"""
|
|
267
|
+
# derive destination file path
|
|
268
|
+
dst_path = make_relative_path(src, src_rel, dst_root, **kwargs) if src_rel else os.path.join(dst_root, os.path.basename(src))
|
|
269
|
+
make_path(dst_path, **kwargs)
|
|
270
|
+
|
|
271
|
+
if get_user_pass_host_key(**kwargs): # remote mode
|
|
272
|
+
contents = read_from_file(src, **kwargs)
|
|
273
|
+
write_to_file(contents=contents, file_path=dst_path, **kwargs)
|
|
274
|
+
else: # local
|
|
275
|
+
os.makedirs(os.path.dirname(dst_path), exist_ok=True)
|
|
276
|
+
shutil.copy2(src, dst_path)
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
return dst_path
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
def copy_files(files, dst_root, src_rel=None, **kwargs):
|
|
283
|
+
"""
|
|
284
|
+
Copy a list of files to dst_root.
|
|
285
|
+
"""
|
|
286
|
+
for src in files:
|
|
287
|
+
copy_file(src=src, dst_root=dst_root, src_rel=src_rel, **kwargs)
|
|
255
288
|
|
|
256
289
|
def create_and_read_file(*args, **kwargs):
|
|
257
290
|
"""
|
|
@@ -290,3 +323,21 @@ def get_content_lines(*args, **kwargs):
|
|
|
290
323
|
elif isinstance(contents, list):
|
|
291
324
|
return contents
|
|
292
325
|
return []
|
|
326
|
+
def collate_text_docs(directory=None):
|
|
327
|
+
return [read_from_file(item) for item in get_all_files(directory=directory)]
|
|
328
|
+
def get_content(*paths):
|
|
329
|
+
item_path = os.path.join(*paths)
|
|
330
|
+
if os.path.isfile(item_path):
|
|
331
|
+
try:
|
|
332
|
+
content = read_from_file(item_path)
|
|
333
|
+
return content
|
|
334
|
+
except:
|
|
335
|
+
pass
|
|
336
|
+
return None
|
|
337
|
+
def get_text_or_read(text=None,file_path=None):
|
|
338
|
+
text = text or ''
|
|
339
|
+
imports_js = {}
|
|
340
|
+
if not text and file_path and os.path.isfile(file_path):
|
|
341
|
+
text=read_from_file(file_path)
|
|
342
|
+
return text
|
|
343
|
+
##
|