-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtfile.py
More file actions
342 lines (277 loc) · 12.8 KB
/
Copy pathtfile.py
File metadata and controls
342 lines (277 loc) · 12.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Copyright (c) 2025 Arthur Y.T. Hsu (許以德)
# This file is part of [Your Project Name].
# License: MIT
# import standard libraries
import os
from pathlib import Path
import json
# import third-party libraries
# import self-defined libraries
try:
from .tmodel import TModelV1
except:
from tmodel import TModelV1
class TreatFilesV1():
"""
## Desc:
this model can easily save/load a file, it focus on file path treatment and open file and release
## Functions:
- get_abs_file_path: get absolute file path
- get_folder_file_list: get all files in a folder
- get_files_name_from_abs_paths: get file name from absolute file path or files path list
- save_dict_to_json: save a dict or list to a json file
- get_file_bytes: open a file and read its bytes data
"""
@staticmethod
def get_abs_file_path(path: str) -> TModelV1:
"""
## Desc:
get absolute file path
## Args:
- path: the file path which support multiple type like relative path, absolute path, etc.
## Returns Data:
- str: absolute file path
"""
result_model = TModelV1(func="TreatFilesV1.get_abs_file_path")
# check input
if not path or not isinstance(path, str):
result_model.success = False
result_model.message = "file_path is empty or not string"
return result_model
# treat input
try:
path = Path(path).expanduser().resolve()
result_model.data = str(path).replace("\\", "/")
# catch exceptions
except (OSError, ValueError) as e:
result_model.success = False
result_model.message = f"Invalid file path: {str(e)}"
return result_model
@staticmethod
def get_folder_file_list(folder_path: str, only_first_layer: bool=True) -> TModelV1:
"""
## Desc:
get all files in a folder
## Args:
- folder_path: the folder path which support multiple type like relative path, absolute path, etc.
- only_first_layer: if True, only get files in the first layer of the folder, default is True
## Returns Data:
- list[str]: list of file paths
"""
result_model = TModelV1(func="TreatFilesV1.get_folder_file_list")
# check input
if not folder_path or not isinstance(folder_path, str):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_folder_file_list"
result_model.message = "folder_path is empty or not string"
return result_model
if not isinstance(only_first_layer, bool):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_folder_file_list"
result_model.message = "only_first_layer is not boolean"
return result_model
# treat input
try:
## try to get abs path of folder
abs_path_model = TreatFilesV1.get_abs_file_path(folder_path)
if not abs_path_model.success:
result_model.success = False
result_model.message = f"error when try get folder abs path: {abs_path_model.message}"
result_model.errFunc = "TreatFilesV1.get_abs_file_path"
return abs_path_model
abs_path = abs_path_model.data
## check if folder exists
if not os.path.isdir(abs_path):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_folder_file_list"
result_model.message = f"Folder does not exist: {abs_path}"
return result_model
## get all files in the folder
file_list = []
if only_first_layer:
for entry in os.scandir(abs_path):
if entry.is_file():
file_list.append(entry.path.replace("\\", "/"))
else:
for root, _, files in os.walk(abs_path):
for file in files:
file_list.append(os.path.join(root, file).replace("\\", "/"))
result_model.data = file_list
# catch exceptions
except (OSError, ValueError) as e:
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_folder_file_list"
result_model.message = f"Error accessing folder: {str(e)}"
return result_model
@staticmethod
def get_files_name_from_abs_paths(path: str|list[str], extension: bool=True) -> TModelV1:
"""
## Desc:
get file name from absolute file path or files path list\n
string in string out, list in list out
## Args:
- path: the absolute file path
- extension: if True, include file extension, default is True
## Returns Data:
- str: file name
- list[str]: list of file names
"""
result_model = TModelV1(func="TreatFilesV1.get_files_name_from_abs_paths")
# check input
if not path or not isinstance(path, (str, list)):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = "path is empty or not string or list[str]"
return result_model
if isinstance(path, list):
for p in path:
if not isinstance(p, str):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = "path list contains non-string element"
return result_model
if not isinstance(extension, bool):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = "extension is not boolean"
return result_model
# treat input
try:
## treat path if is not list
if isinstance(path, str):
abs_path_model = TreatFilesV1.get_abs_file_path(path)
if not abs_path_model.success:
result_model.success = False
result_model.message = f"error when try get abs path: {abs_path_model.message}"
result_model.errFunc = "TreatFilesV1.get_abs_file_path"
return result_model
abs_path = abs_path_model.data
if os.path.isdir(abs_path):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = f"path is a directory, not a file: {path}"
return result_model
file_name = os.path.basename(abs_path) if extension else os.path.splitext(os.path.basename(abs_path))[0]
result_model.data = file_name
## treat path if is list
else:
abs_paths_list = []
for p in path:
abs_path_model = TreatFilesV1.get_abs_file_path(p)
if not abs_path_model.success:
result_model.success = False
result_model.message = f"error when try get abs path: {abs_path_model.message}"
result_model.errFunc = "TreatFilesV1.get_abs_file_path"
return result_model
abs_path = abs_path_model.data
if os.path.isdir(abs_path_model.data):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = f"path is a directory, not a file: {abs_path_model.data}"
return result_model
abs_paths_list.append(abs_path_model.data)
file_names = [os.path.basename(p) if extension else os.path.splitext(os.path.basename(p))[0] for p in path]
result_model.data = file_names
# catch exceptions
except (OSError, ValueError) as e:
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_name_from_abs_path"
result_model.message = f"Error getting file name: {str(e)}"
return result_model
@staticmethod
def save_dict_to_json(data: list|dict, output_path: str, indent: int = 4) -> TModelV1:
"""
## Desc:
save a dict or list to a json file
## Args:
- data: the data which can be saved to json file
- json_file_path: the json file path
- indent: the indent space number, default is 4
## Returns Data:
- str: absolute file path
"""
result_model = TModelV1(func="TreatFilesV1.save_dict_to_json")
# check input
if not isinstance(data, (dict, list)):
result_model.success = False
result_model.errFunc = "TreatFilesV1.save_dict_to_json"
result_model.message = "data is not dict or list"
return result_model
if not output_path or not isinstance(output_path, str):
result_model.success = False
result_model.errFunc = "TreatFilesV1.save_dict_to_json"
result_model.message = "json_file_path is empty or not string"
return result_model
if not isinstance(indent, int) or indent < 0:
result_model.success = False
result_model.errFunc = "TreatFilesV1.save_dict_to_json"
result_model.message = "indent is not a non-negative integer"
return result_model
# treat input
try:
## try to get abs path of json file
abs_path_model = TreatFilesV1.get_abs_file_path(output_path)
if not abs_path_model.success:
result_model.success = False
result_model.message = f"error when try get json abs path: {abs_path_model.message}"
result_model.errFunc = "TreatFilesV1.get_abs_file_path"
return abs_path_model
abs_path = abs_path_model.data
## create parent directory if not exists
parent_dir = os.path.dirname(abs_path)
os.makedirs(parent_dir, exist_ok=True)
## open json file and transform to dict or list
with open(abs_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=indent)
result_model.data = abs_path
# catch exceptions
except (OSError, ValueError, json.JSONDecodeError) as e:
result_model.success = False
result_model.errFunc = "TreatFilesV1.save_dict_to_json"
result_model.message = f"Error saving JSON file: {str(e)}"
return result_model
@staticmethod
def get_file_bytes(file_path: str) -> TModelV1:
"""
## Desc:
open a file and read its bytes data
## Args:
- file_path: the image file path
## Returns Data:
- bytes: the image bytes data
"""
result_model = TModelV1(func="TreatFilesV1.get_file_bytes")
# check input
if not file_path or not isinstance(file_path, str):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_bytes"
result_model.message = "file_path is empty or not string"
return result_model
# treat input
try:
## try to get abs path of file
abs_path_model = TreatFilesV1.get_abs_file_path(file_path)
if not abs_path_model.success:
result_model.success = False
result_model.message = f"error when try get file abs path: {abs_path_model.message}"
result_model.errFunc = "TreatFilesV1.get_abs_file_path"
return abs_path_model
abs_path = abs_path_model.data
## check if file exists
if not os.path.isfile(abs_path):
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_bytes"
result_model.message = f"File does not exist: {abs_path}"
return result_model
## open file and read bytes data
with open(abs_path, 'rb') as f:
file_bytes = f.read()
result_model.data = file_bytes
# catch exceptions
except (OSError, ValueError) as e:
result_model.success = False
result_model.errFunc = "TreatFilesV1.get_file_bytes"
result_model.message = f"Error reading file: {str(e)}"
return result_model