abstract-utilities 0.2.2.540__py3-none-any.whl → 0.2.2.667__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.

Files changed (66) hide show
  1. abstract_utilities/__init__.py +13 -4
  2. abstract_utilities/class_utils/abstract_classes.py +104 -34
  3. abstract_utilities/class_utils/caller_utils.py +57 -0
  4. abstract_utilities/class_utils/global_utils.py +35 -20
  5. abstract_utilities/class_utils/imports/imports.py +1 -1
  6. abstract_utilities/directory_utils/src/directory_utils.py +19 -1
  7. abstract_utilities/file_utils/imports/classes.py +59 -55
  8. abstract_utilities/file_utils/imports/imports.py +0 -4
  9. abstract_utilities/file_utils/imports/module_imports.py +1 -1
  10. abstract_utilities/file_utils/src/__init__.py +2 -3
  11. abstract_utilities/file_utils/src/file_filters/__init__.py +1 -0
  12. abstract_utilities/file_utils/src/file_filters/ensure_utils.py +490 -0
  13. abstract_utilities/file_utils/src/file_filters/filter_params.py +150 -0
  14. abstract_utilities/file_utils/src/file_filters/filter_utils.py +78 -0
  15. abstract_utilities/file_utils/src/file_filters/predicate_utils.py +44 -0
  16. abstract_utilities/file_utils/src/file_reader.py +0 -1
  17. abstract_utilities/file_utils/src/find_collect.py +10 -86
  18. abstract_utilities/file_utils/src/find_content.py +210 -0
  19. abstract_utilities/file_utils/src/initFunctionsGen.py +36 -23
  20. abstract_utilities/file_utils/src/initFunctionsGens.py +280 -0
  21. abstract_utilities/file_utils/src/reader_utils/__init__.py +4 -0
  22. abstract_utilities/file_utils/src/reader_utils/directory_reader.py +53 -0
  23. abstract_utilities/file_utils/src/reader_utils/file_reader.py +543 -0
  24. abstract_utilities/file_utils/src/reader_utils/file_readers.py +376 -0
  25. abstract_utilities/file_utils/src/reader_utils/imports.py +18 -0
  26. abstract_utilities/file_utils/src/reader_utils/pdf_utils.py +300 -0
  27. abstract_utilities/import_utils/circular_import_finder.py +222 -0
  28. abstract_utilities/import_utils/circular_import_finder2.py +118 -0
  29. abstract_utilities/import_utils/imports/__init__.py +1 -1
  30. abstract_utilities/import_utils/imports/init_imports.py +3 -0
  31. abstract_utilities/import_utils/imports/module_imports.py +4 -1
  32. abstract_utilities/import_utils/imports/utils.py +1 -1
  33. abstract_utilities/import_utils/src/__init__.py +1 -0
  34. abstract_utilities/import_utils/src/clean_imports.py +156 -25
  35. abstract_utilities/import_utils/src/dot_utils.py +11 -0
  36. abstract_utilities/import_utils/src/extract_utils.py +4 -0
  37. abstract_utilities/import_utils/src/import_functions.py +66 -2
  38. abstract_utilities/import_utils/src/import_utils.py +39 -0
  39. abstract_utilities/import_utils/src/layze_import_utils/__init__.py +2 -0
  40. abstract_utilities/import_utils/src/layze_import_utils/lazy_utils.py +41 -0
  41. abstract_utilities/import_utils/src/layze_import_utils/nullProxy.py +32 -0
  42. abstract_utilities/import_utils/src/nullProxy.py +30 -0
  43. abstract_utilities/import_utils/src/pkg_utils.py +58 -4
  44. abstract_utilities/import_utils/src/sysroot_utils.py +56 -1
  45. abstract_utilities/imports.py +3 -2
  46. abstract_utilities/json_utils/json_utils.py +11 -3
  47. abstract_utilities/log_utils/log_file.py +73 -24
  48. abstract_utilities/parse_utils/parse_utils.py +23 -0
  49. abstract_utilities/path_utils/imports/module_imports.py +1 -1
  50. abstract_utilities/path_utils/path_utils.py +32 -35
  51. abstract_utilities/read_write_utils/imports/imports.py +1 -1
  52. abstract_utilities/read_write_utils/read_write_utils.py +102 -32
  53. abstract_utilities/safe_utils/safe_utils.py +30 -0
  54. abstract_utilities/type_utils/__init__.py +5 -1
  55. abstract_utilities/type_utils/get_type.py +116 -0
  56. abstract_utilities/type_utils/imports/__init__.py +1 -0
  57. abstract_utilities/type_utils/imports/constants.py +134 -0
  58. abstract_utilities/type_utils/imports/module_imports.py +25 -1
  59. abstract_utilities/type_utils/is_type.py +455 -0
  60. abstract_utilities/type_utils/make_type.py +126 -0
  61. abstract_utilities/type_utils/mime_types.py +68 -0
  62. abstract_utilities/type_utils/type_utils.py +0 -877
  63. {abstract_utilities-0.2.2.540.dist-info → abstract_utilities-0.2.2.667.dist-info}/METADATA +1 -1
  64. {abstract_utilities-0.2.2.540.dist-info → abstract_utilities-0.2.2.667.dist-info}/RECORD +66 -41
  65. {abstract_utilities-0.2.2.540.dist-info → abstract_utilities-0.2.2.667.dist-info}/WHEEL +0 -0
  66. {abstract_utilities-0.2.2.540.dist-info → abstract_utilities-0.2.2.667.dist-info}/top_level.txt +0 -0
@@ -107,17 +107,6 @@ def path_join(*paths, isfile=False):
107
107
  os.makedirs(final_path, exist_ok=True)
108
108
  return final_path
109
109
 
110
- def is_file(*paths):
111
- item_path = os.path.join(*paths)
112
- return os.path.isfile(item_path)
113
-
114
- def is_dir(*paths):
115
- item_path = os.path.join(*paths)
116
- return os.path.isdir(item_path)
117
-
118
- def is_path(*paths):
119
- item_path = os.path.join(*paths)
120
- return item_path if os.path.exists(item_path) else None
121
110
 
122
111
  def get_all_directories(directory):
123
112
  dir_list = os.listdir(directory)
@@ -132,7 +121,7 @@ def get_all_files(directory=None):
132
121
 
133
122
  def get_all_items(directory):
134
123
  dir_list = os.listdir(directory)
135
- file_list = [item for item in dir_list if is_path(directory,item)]
124
+ file_list = [item for item in dir_list if is_exists(directory,item)]
136
125
  return file_list
137
126
 
138
127
 
@@ -176,6 +165,7 @@ def get_safe_splitext(path=None,basename=None):
176
165
  basename_str = str(basename)
177
166
  filename,ext = os.path.splitext(basename_str)
178
167
  return filename,ext
168
+ return None,None
179
169
  def get_safe_filename(path=None,basename=None):
180
170
  filename,_ = get_safe_splitext(path=path,basename=basename)
181
171
  return filename
@@ -223,29 +213,36 @@ def create_base_dir(directory=None, child=None):
223
213
 
224
214
 
225
215
 
226
-
227
- def get_file_parts(path):
216
+ def get_abs_path(path,i=None):
217
+ abs_dir = get_initial_caller_dir()
218
+ return os.path.join(abs_dir,path)
228
219
 
229
- basename = get_safe_basename(path)
230
- filename, ext = get_safe_splitext(basename=basename)
231
220
 
232
- dirname = get_safe_dirname(path)
233
- dirbase = get_safe_basename(dirname)
234
-
235
- parent_dirname = get_safe_dirname(dirname)
236
- parent_dirbase = get_safe_basename(parent_dirname)
237
-
238
- super_dirname = get_safe_dirname(parent_dirname)
239
- super_dirbase = get_safe_basename(super_dirname)
240
-
241
- return {"dirname": dirname,
242
- "basename": basename,
243
- "filename": filename,
244
- "ext": ext,
245
- "dirbase":dirbase,
246
- "parent_dirname":parent_dirname,
247
- "parent_dirbase":parent_dirbase,
248
- "super_dirname":super_dirname,
249
- "super_dirbase":super_dirbase
250
- }
221
+
222
+ def get_file_parts(path):
223
+ if path:
224
+ path= str(path)
225
+ basename = get_safe_basename(path)
226
+ filename, ext = get_safe_splitext(basename=basename)
227
+
228
+ dirname = get_safe_dirname(path)
229
+ dirbase = get_safe_basename(dirname)
230
+
231
+ parent_dirname = get_safe_dirname(dirname)
232
+ parent_dirbase = get_safe_basename(parent_dirname)
233
+
234
+ super_dirname = get_safe_dirname(parent_dirname)
235
+ super_dirbase = get_safe_basename(super_dirname)
236
+
237
+ return {"file_path":path,
238
+ "dirname": dirname,
239
+ "basename": basename,
240
+ "filename": filename,
241
+ "ext": ext,
242
+ "dirbase":dirbase,
243
+ "parent_dirname":parent_dirname,
244
+ "parent_dirbase":parent_dirbase,
245
+ "super_dirname":super_dirname,
246
+ "super_dirbase":super_dirbase
247
+ }
251
248
 
@@ -1,2 +1,2 @@
1
1
  from ...imports import os,shlex
2
-
2
+ import base64
@@ -194,45 +194,115 @@ def write_to_path(
194
194
  ## f.write(str(contents))
195
195
  ## return file_path
196
196
  # --- Core functionality -------------------------------------------------------
197
- def write_to_file(*args, **kwargs):
197
+ ##def write_to_file(*args, **kwargs):
198
+ ## """
199
+ ## Write contents to a file (create if missing).
200
+ ##
201
+ ## Returns the file_path written.
202
+ ## """
203
+ ## file_path, contents = check_read_write_params(*args, **kwargs)
204
+ ## values,kwargs = get_from_kwargs(['file_path','contents'],del_kwarg=True,**kwargs)
205
+ ## dirname = os.path.dirname(file_path)
206
+ ##
207
+ ## if contents is None:
208
+ ## raise ValueError("Missing contents to write.")
209
+ ## user_at_host = kwargs.get("user_at_host")
210
+ ## if get_user_pass_host_key(**kwargs):
211
+ ## make_dirs(dirname, exist_ok=True,**kwargs)
212
+ ## kwargs["cwd"] = kwargs.get('cwd') or os.path.dirname(file_path)
213
+ ## # sanitize for shell safety
214
+ ## quoted_path = shlex.quote(file_path)
215
+ ## quoted_data = shlex.quote(str(contents))
216
+ ## # shell command that fully overwrites
217
+ ## # (no append, replaces contents entirely)
218
+ ## kwargs["cmd"] = f'sh -c "echo {quoted_data} > {quoted_path}"'
219
+ ## if not kwargs.get('password') and not kwargs.get('key'):
220
+ ## kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
221
+ ## result = run_pruned_func(run_cmd,**kwargs)
222
+ ## if 'file_path' in kwargs:
223
+ ## del kwargs['file_path']
224
+ ## if not is_file(file_path,**kwargs) or str(contents) != read_from_file(file_path,**kwargs):
225
+ ## kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
226
+ ## result = run_pruned_func(run_cmd,**kwargs)
227
+ ## return result
228
+ ##
229
+ ## make_dirs(dirname or ".", exist_ok=True)
230
+ ## with open(file_path, "w", encoding="utf-8") as f:
231
+ ## f.write(str(contents))
232
+ ## return file_path
233
+
234
+ def _should_use_remote(**kwargs) -> bool:
235
+ """
236
+ Only use remote mode IF:
237
+ - user_at_host is provided
238
+ - AND password/key is provided
239
+ Otherwise: local write.
198
240
  """
199
- Write contents to a file (create if missing).
241
+ user = kwargs.get("user_at_host")
242
+ if not user:
243
+ return False # not remote
244
+
245
+ # If user_at_host is provided, then password or key MUST be present
246
+ if kwargs.get("password") or kwargs.get("key"):
247
+ return True
200
248
 
201
- Returns the file_path written.
249
+ return False # user provided but no auth → treat as local
250
+
251
+
252
+ def _write_to_file(contents: str, file_path: str, **kwargs) -> str:
202
253
  """
203
- file_path, contents = check_read_write_params(*args, **kwargs)
204
- values,kwargs = get_from_kwargs(['file_path','contents'],del_kwarg=True,**kwargs)
254
+ Safe writer that handles arbitrarily large files.
255
+ Uses native I/O for local writes and streams for remote.
256
+ """
257
+
258
+ remote = _should_use_remote(**kwargs)
205
259
  dirname = os.path.dirname(file_path)
206
-
207
- if contents is None:
208
- raise ValueError("Missing contents to write.")
209
- user_at_host = kwargs.get("user_at_host")
210
- if get_user_pass_host_key(**kwargs):
211
- make_dirs(dirname, exist_ok=True,**kwargs)
212
- kwargs["cwd"] = kwargs.get('cwd') or os.path.dirname(file_path)
213
- # sanitize for shell safety
214
- quoted_path = shlex.quote(file_path)
215
- quoted_data = shlex.quote(str(contents))
216
- # shell command that fully overwrites
217
- # (no append, replaces contents entirely)
218
- kwargs["cmd"] = f'sh -c "echo {quoted_data} > {quoted_path}"'
219
- if not kwargs.get('password') and not kwargs.get('key'):
220
- kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
221
- result = run_pruned_func(run_cmd,**kwargs)
222
- if 'file_path' in kwargs:
223
- del kwargs['file_path']
224
- if not is_file(file_path,**kwargs) or str(contents) != read_from_file(file_path,**kwargs):
225
- kwargs["cmd"]=f'sudo {kwargs["cmd"]}'
226
- result = run_pruned_func(run_cmd,**kwargs)
227
- return result
260
+ make_dirs(dirname, exist_ok=True, **kwargs)
261
+
262
+ # --- Local write (always robust) ---
263
+ if not remote:
264
+ with open(file_path, "w", encoding="utf-8") as f:
265
+ f.write(contents)
266
+ return file_path
267
+
268
+ # --- Remote write ---
269
+ # Stream data through SSH using base64 chunks instead of huge one-liner
270
+ import io
271
+ import base64
272
+
273
+ # Write to a temporary file locally first
274
+ tmp_path = "/tmp/_abstract_write.tmp"
275
+ with open(tmp_path, "w", encoding="utf-8") as tmpf:
276
+ tmpf.write(contents)
277
+
278
+ user_at_host = kwargs["user_at_host"]
279
+ password = kwargs.get("password")
280
+ key = kwargs.get("key")
281
+
282
+ # Use scp for remote write — no shell arg limits
283
+ scp_cmd = f"scp {shlex.quote(tmp_path)} {user_at_host}:{shlex.quote(file_path)}"
284
+ return run_pruned_func(
285
+ run_local_cmd,
286
+ cmd=scp_cmd,
287
+ password=password,
288
+ key=key,
289
+ **kwargs
290
+ )
228
291
 
229
- make_dirs(dirname or ".", exist_ok=True)
230
- with open(file_path, "w", encoding="utf-8") as f:
231
- f.write(str(contents))
232
- return file_path
233
292
 
293
+ def write_to_file(*, contents: str, file_path: str, **kwargs):
294
+ """
295
+ Error-handled wrapper.
296
+ """
297
+
298
+ try:
299
+ result = _write_to_file(contents=contents, file_path=file_path, **kwargs)
300
+ return result
234
301
 
235
- def read_from_file(file_path,**kwargs):
302
+ except Exception as e:
303
+ print("WRITE ERROR:", e)
304
+ raise RuntimeError(f"Failed writing: {file_path}")
305
+ def read_from_file(file_path=None,**kwargs):
236
306
  if get_user_pass_host_key(**kwargs):
237
307
  kwargs["cwd"] = kwargs.get('cwd') or os.path.dirname(file_path)
238
308
  basename = os.path.basename(file_path)
@@ -10,7 +10,37 @@ Designed for compatibility with the abstract_ ecosystem (e.g. abstract_utilities
10
10
  from .imports import *
11
11
  _BASE_DIR = get_caller_dir()
12
12
 
13
+ class PathOutsideBase(Exception):
14
+ pass
13
15
 
16
+ def safe_join_base(base: Union[str, Path], *parts: Union[str, Path], must_exist: bool = False) -> Path:
17
+ """
18
+ Join base with parts, normalize, and ensure the result lives under base.
19
+ Prevents '../' traversal and ignores leading slashes in parts.
20
+ """
21
+ base = Path(base).resolve(strict=True)
22
+ # Disallow absolute/drive-anchored parts by stripping their anchors before joining.
23
+ cleaned = []
24
+ for p in parts:
25
+ p = Path(p)
26
+ # Convert absolute to relative (security: we won't allow escaping base anyway)
27
+ if p.is_absolute():
28
+ p = Path(*p.parts[1:]) # drop leading '/'
29
+ cleaned.append(p)
30
+
31
+ # Build and resolve (non-strict so missing files are allowed unless must_exist=True)
32
+ target = (base.joinpath(*cleaned)).resolve(strict=False)
33
+
34
+ # Containment check (works even if target doesn't exist)
35
+ try:
36
+ target.relative_to(base)
37
+ except ValueError:
38
+ raise PathOutsideBase(f"{target} escapes base {base}")
39
+
40
+ if must_exist and not target.exists():
41
+ raise FileNotFoundError(target)
42
+
43
+ return target
14
44
  def safe_split(
15
45
  string: Any,
16
46
  char: Any,
@@ -1,3 +1,7 @@
1
+ from .imports import *
1
2
  from .alpha_utils import *
2
3
  from .num_utils import *
3
- from .type_utils import *
4
+ from .is_type import *
5
+ from .make_type import *
6
+ from .get_type import *
7
+ from .mime_types import *
@@ -0,0 +1,116 @@
1
+ from .imports import *
2
+ from .alpha_utils import *
3
+ from .num_utils import *
4
+ from .is_type import *
5
+ from .make_type import *
6
+ def get_obj_obj(obj_type: str, obj: any) -> any:
7
+ """
8
+ Returns the object converted according to the given type string.
9
+
10
+ Args:
11
+ obj_type: The string representing the type to convert to.
12
+ obj: The object to convert.
13
+
14
+ Returns:
15
+ any: The object converted to the specified type.
16
+ """
17
+ if obj_type == 'str':
18
+ return make_str(obj)
19
+ elif obj_type == 'bool':
20
+ return make_bool(obj)
21
+ elif obj_type == 'float':
22
+ return make_float(obj)
23
+ elif obj_type == 'int':
24
+ try:
25
+ return int(obj)
26
+ except (TypeError, ValueError):
27
+ return obj
28
+ else:
29
+ return obj
30
+ def get_len_or_num(obj: any) -> int:
31
+ """
32
+ Returns the length of the object if it can be converted to a string, else the integer representation of the object.
33
+
34
+ Args:
35
+ obj: The object to process.
36
+
37
+ Returns:
38
+ int: The length of the object as a string or the integer representation of the object.
39
+ """
40
+ if is_int(obj) or is_float(obj):
41
+ return int(obj)
42
+ else:
43
+ try:
44
+ return len(str(obj))
45
+ except (TypeError, ValueError):
46
+ return 0
47
+ def get_types_list()->list:
48
+ return ['list', 'bool', 'str', 'int', 'float', 'set', 'dict', 'frozenset', 'bytearray', 'bytes', 'memoryview', 'range', 'enumerate', 'zip', 'filter', 'map', 'property', 'slice', 'super', 'type', 'Exception', 'NoneType']
49
+
50
+
51
+ def str_lower(obj):
52
+ try:
53
+ obj=str(obj).lower()
54
+ except Exception as e:
55
+ print(f"{e}")
56
+ return obj
57
+
58
+ def get_bool_response(bool_response,json_data):
59
+ if not is_instance(bool_response,bool):
60
+ try:
61
+ bool_response = json_data.get(bool_response) in [None,'',[],"",{}]
62
+ except:
63
+ pass
64
+ return bool_response
65
+ def get_alphabet_str():
66
+ return 'abcdefghijklmnopqrstuvwxyz'
67
+ def get_alphabet_upper_str():
68
+ alphabet_str = get_alphabet_str()
69
+ return alphabet_str.upper()
70
+ def get_alphabet_comp_str():
71
+ return get_alphabet_str() + get_alphabet_upper_str()
72
+
73
+ def get_alphabet():
74
+ alphabet_str = get_alphabet_str()
75
+ return break_string(alphabet_str)
76
+ def get_alphabet_upper():
77
+ alphabet_upper_str = get_alphabet_upper_str()
78
+ return break_string(alphabet_upper_str)
79
+ def get_alphabet_comp():
80
+ alphabet_comp_str = get_alphabet_comp_str()
81
+ return break_string(alphabet_comp_str)
82
+ def get_numbers_str():
83
+ return '0123457890'
84
+ def get_numbers_int():
85
+ numbers_str = get_numbers_str()
86
+ return [int(number) for number in numbers_str]
87
+ def get_numbers():
88
+ numbers_str = get_numbers_str()
89
+ return break_string(numbers_str)
90
+ def get_numbers_comp():
91
+ numbers_str = get_numbers()
92
+ numbers_int = get_numbers_int()
93
+ return numbers_str + numbers_int
94
+ def break_string(string):
95
+ string_str = str(string)
96
+ return list(string_str)
97
+ def get_alpha_ints(ints=True,alpha=True,lower=True,capitalize=True,string=True,listObj=True):
98
+ objs = [] if listObj else ""
99
+ if ints:
100
+ objs+=getInts(string=string,listObj=listObj)
101
+ if alpha:
102
+ objs+=getAlphas(lower=lower,capitalize=capitalize,listObj=listObj)
103
+ return objs
104
+ def if_true_get_string(data, key):
105
+ return key if data.get(key) else None
106
+ def find_for_string(string, parts):
107
+ return [part for part in parts if string.lower() in str(part).lower()]
108
+
109
+
110
+ def is_strings_in_string(strings, parts):
111
+ strings = make_list(strings)
112
+ for string in strings:
113
+ parts = find_for_string(string, parts)
114
+ if not parts:
115
+ return []
116
+ return parts
@@ -1,2 +1,3 @@
1
1
  from .imports import *
2
2
  from .module_imports import *
3
+ from .constants import *
@@ -0,0 +1,134 @@
1
+ from .module_imports import *
2
+ MIME_TYPES = {
3
+ 'image': {
4
+ '.jpg': 'image/jpeg',
5
+ '.jpeg': 'image/jpeg',
6
+ '.png': 'image/png',
7
+ '.gif': 'image/gif',
8
+ '.bmp': 'image/bmp',
9
+ '.tiff': 'image/tiff',
10
+ '.webp': 'image/webp',
11
+ '.svg': 'image/svg+xml',
12
+ '.ico': 'image/vnd.microsoft.icon',
13
+ '.heic': 'image/heic',
14
+ '.psd': 'image/vnd.adobe.photoshop',
15
+ '.raw': 'image/x-raw',
16
+ },
17
+ 'video': {
18
+ '.mp4': 'video/mp4',
19
+ '.webm': 'video/webm',
20
+ '.ogg': 'video/ogg',
21
+ '.mov': 'video/quicktime',
22
+ '.avi': 'video/x-msvideo',
23
+ '.mkv': 'video/x-matroska',
24
+ '.flv': 'video/x-flv',
25
+ '.wmv': 'video/x-ms-wmv',
26
+ '.3gp': 'video/3gpp',
27
+ '.ts': 'video/mp2t',
28
+ '.mpeg': 'video/mpeg',
29
+ '.mpg': 'video/mpg'
30
+ },
31
+ 'audio': {
32
+ '.mp3': 'audio/mpeg',
33
+ '.wav': 'audio/wav',
34
+ '.flac': 'audio/flac',
35
+ '.aac': 'audio/aac',
36
+ '.ogg': 'audio/ogg',
37
+ '.m4a': 'audio/mp4',
38
+ '.opus': 'audio/opus',
39
+ },
40
+ 'document': {
41
+ '.pdf': 'application/pdf',
42
+ '.doc': 'application/msword',
43
+ '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
44
+ '.odt': 'application/vnd.oasis.opendocument.text',
45
+ '.txt': 'text/plain',
46
+ '.rtf': 'application/rtf',
47
+ '.md': 'text/markdown',
48
+ '.markdown': 'text/markdown',
49
+ '.tex': 'application/x-tex',
50
+ '.log': 'text/plain',
51
+ '.json': 'application/json',
52
+ '.xml': 'application/xml',
53
+ '.yaml': 'application/x-yaml',
54
+ '.yml': 'application/x-yaml',
55
+ '.ini': 'text/plain',
56
+ '.cfg': 'text/plain',
57
+ '.toml': 'application/toml',
58
+ '.csv': 'text/csv',
59
+ '.tsv': 'text/tab-separated-values'
60
+ },
61
+ 'presentation': {
62
+ '.ppt': 'application/vnd.ms-powerpoint',
63
+ '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
64
+ '.odp': 'application/vnd.oasis.opendocument.presentation',
65
+ },
66
+ 'spreadsheet': {
67
+ '.xls': 'application/vnd.ms-excel',
68
+ '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
69
+ '.ods': 'application/vnd.oasis.opendocument.spreadsheet',
70
+ '.csv': 'text/csv',
71
+ '.tsv': 'text/tab-separated-values'
72
+ },
73
+ 'code': {
74
+ '.py': 'text/x-python',
75
+ '.java': 'text/x-java-source',
76
+ '.c': 'text/x-c',
77
+ '.cpp': 'text/x-c++',
78
+ '.h': 'text/x-c',
79
+ '.hpp': 'text/x-c++',
80
+ '.js': 'application/javascript',
81
+ '.cjs': 'application/javascript',
82
+ '.mjs': 'application/javascript',
83
+ '.jsx': 'application/javascript',
84
+ '.ts': 'application/typescript',
85
+ '.tsx': 'application/typescript',
86
+ '.rb': 'text/x-ruby',
87
+ '.php': 'application/x-php',
88
+ '.go': 'text/x-go',
89
+ '.rs': 'text/rust',
90
+ '.swift': 'text/x-swift',
91
+ '.kt': 'text/x-kotlin',
92
+ '.sh': 'application/x-shellscript',
93
+ '.bash': 'application/x-shellscript',
94
+ '.ps1': 'application/x-powershell',
95
+ '.sql': 'application/sql',
96
+ '.yml': 'application/x-yaml',
97
+ '.coffee':'text/coffeescript',
98
+ '.lua': 'text/x-lua',
99
+ },
100
+ 'archive': {
101
+ '.zip': 'application/zip',
102
+ '.tar': 'application/x-tar',
103
+ '.gz': 'application/gzip',
104
+ '.tgz': 'application/gzip',
105
+ '.bz2': 'application/x-bzip2',
106
+ '.xz': 'application/x-xz',
107
+ '.rar': 'application/vnd.rar',
108
+ '.7z': 'application/x-7z-compressed',
109
+ '.iso': 'application/x-iso9660-image',
110
+ '.dmg': 'application/x-apple-diskimage',
111
+ '.jar': 'application/java-archive',
112
+ '.war': 'application/java-archive',
113
+ '.whl': 'application/python-wheel',
114
+ '.egg': 'application/python-egg',
115
+ },
116
+ 'font': {
117
+ '.ttf': 'font/ttf',
118
+ '.otf': 'font/otf',
119
+ '.woff': 'font/woff',
120
+ '.woff2': 'font/woff2',
121
+ '.eot': 'application/vnd.ms-fontobject'
122
+ },
123
+ 'executable': {
124
+ '.exe': 'application/vnd.microsoft.portable-executable',
125
+ '.dll': 'application/vnd.microsoft.portable-executable',
126
+ '.bin': 'application/octet-stream',
127
+ '.deb': 'application/vnd.debian.binary-package',
128
+ '.rpm': 'application/x-rpm'
129
+ }
130
+ }
131
+
132
+ # And just the sets, if you only need to test ext‐membership:
133
+ MEDIA_TYPES = make_key_map(MIME_TYPES)
134
+
@@ -1 +1,25 @@
1
- from ...list_utils import make_list
1
+ def make_list(obj:any) -> list:
2
+ """
3
+ Converts the input object to a list. If the object is already a list, it is returned as is.
4
+
5
+ Args:
6
+ obj: The object to convert.
7
+
8
+ Returns:
9
+ list: The object as a list.
10
+ """
11
+ if isinstance(obj,str):
12
+ if ',' in obj:
13
+ obj = obj.split(',')
14
+ if isinstance(obj,set) or isinstance(obj,tuple):
15
+ return list(obj)
16
+ if isinstance(obj, list):
17
+ return obj
18
+ return [obj]
19
+ def get_keys(mapping,typ=None):
20
+ typ = typ or set
21
+ if isinstance(mapping,dict):
22
+ mapping = mapping.keys()
23
+ return typ(mapping)
24
+ def make_key_map(dict_obj):
25
+ return {k:get_keys(v) for k,v in dict_obj.items()}