xulbux 1.6.0__py3-none-any.whl → 1.6.2__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 xulbux might be problematic. Click here for more details.

xulbux/xx_console.py CHANGED
@@ -15,8 +15,8 @@ Functions for logging and other small actions within the console:
15
15
  - `Console.confirm()`
16
16
  - `Console.restricted_input()`
17
17
  - `Console.pwd_input()`\n
18
- ----------------------------------------------------------------------------------------------------------
19
- You can also use special formatting codes directly inside the log message to change their appearance.<br>
18
+ ------------------------------------------------------------------------------------------------------
19
+ You can also use special formatting codes directly inside the log message to change their appearance.
20
20
  For more detailed information about formatting codes, see the the `xx_format_codes` description.
21
21
  """
22
22
 
@@ -29,7 +29,6 @@ from contextlib import suppress
29
29
  import pyperclip as _pyperclip
30
30
  import keyboard as _keyboard
31
31
  import getpass as _getpass
32
- import ctypes as _ctypes
33
32
  import shutil as _shutil
34
33
  import mouse as _mouse
35
34
  import sys as _sys
@@ -67,17 +66,6 @@ class Console:
67
66
  def user() -> str:
68
67
  return _os.getenv("USER") or _os.getenv("USERNAME") or _getpass.getuser()
69
68
 
70
- def is_admin() -> bool:
71
- try:
72
- if _os.name == "nt":
73
- return _ctypes.windll.shell32.IsUserAnAdmin() != 0
74
- elif _os.name == "posix":
75
- return _os.geteuid() == 0
76
- else:
77
- return False
78
- except Exception:
79
- return False
80
-
81
69
  @staticmethod
82
70
  def pause_exit(
83
71
  pause: bool = False,
@@ -86,9 +74,8 @@ class Console:
86
74
  exit_code: int = 0,
87
75
  reset_ansi: bool = False,
88
76
  ) -> None:
89
- """Will print the `last_prompt` and then pause the program if `pause` is set<br>
90
- to `True` and after the pause, exit the program if `exit` is set to `True`.
91
- """
77
+ """Will print the `last_prompt` and then pause the program if `pause` is set
78
+ to `True` and after the pause, exit the program if `exit` is set to `True`."""
92
79
  print(prompt, end="", flush=True)
93
80
  if reset_ansi:
94
81
  FormatCodes.print("[_]", end="")
@@ -114,17 +101,16 @@ class Console:
114
101
  title_bg_color: hexa | rgba = None,
115
102
  default_color: hexa | rgba = None,
116
103
  ) -> None:
117
- """Will print a formatted log message:<br>
118
- `title` -⠀the title of the log message (e.g. `DEBUG`, `WARN`, `FAIL`, etc.)<br>
119
- `prompt` -⠀the log message<br>
120
- `start` -⠀something to print before the log is printed<br>
121
- `end` -⠀something to print after the log is printed (e.g. `\\n\\n`)<br>
122
- `title_bg_color` -⠀the background color of the `title`<br>
123
- `default_color` -⠀the default text color of the `prompt`\n
104
+ """Will print a formatted log message:
105
+ - `title` -⠀the title of the log message (e.g. `DEBUG`, `WARN`, `FAIL`, etc.)
106
+ - `prompt` -⠀the log message
107
+ - `start` -⠀something to print before the log is printed
108
+ - `end` -⠀something to print after the log is printed (e.g. `\\n\\n`)
109
+ - `title_bg_color` -⠀the background color of the `title`
110
+ - `default_color` -⠀the default text color of the `prompt`\n
124
111
  --------------------------------------------------------------------------------
125
- The log message supports special formatting codes. For more detailed<br>
126
- information about formatting codes, see `xx_format_codes` class description.
127
- """
112
+ The log message supports special formatting codes. For more detailed
113
+ information about formatting codes, see `xx_format_codes` class description."""
128
114
  title_color = "_color" if not title_bg_color else Color.text_color_for_on_bg(title_bg_color)
129
115
  if title:
130
116
  FormatCodes.print(
@@ -150,7 +136,7 @@ class Console:
150
136
  pause: bool = False,
151
137
  exit: bool = False,
152
138
  ) -> None:
153
- """A preset for `log()`: `DEBUG` log message with the options to pause<br>
139
+ """A preset for `log()`: `DEBUG` log message with the options to pause
154
140
  at the message and exit the program after the message was printed."""
155
141
  if active:
156
142
  Console.log("DEBUG", prompt, start, end, title_bg_color, default_color)
@@ -166,7 +152,7 @@ class Console:
166
152
  pause: bool = False,
167
153
  exit: bool = False,
168
154
  ) -> None:
169
- """A preset for `log()`: `INFO` log message with the options to pause<br>
155
+ """A preset for `log()`: `INFO` log message with the options to pause
170
156
  at the message and exit the program after the message was printed."""
171
157
  Console.log("INFO", prompt, start, end, title_bg_color, default_color)
172
158
  Console.pause_exit(pause, exit)
@@ -181,7 +167,7 @@ class Console:
181
167
  pause: bool = False,
182
168
  exit: bool = False,
183
169
  ) -> None:
184
- """A preset for `log()`: `DONE` log message with the options to pause<br>
170
+ """A preset for `log()`: `DONE` log message with the options to pause
185
171
  at the message and exit the program after the message was printed."""
186
172
  Console.log("DONE", prompt, start, end, title_bg_color, default_color)
187
173
  Console.pause_exit(pause, exit)
@@ -196,7 +182,7 @@ class Console:
196
182
  pause: bool = False,
197
183
  exit: bool = False,
198
184
  ) -> None:
199
- """A preset for `log()`: `WARN` log message with the options to pause<br>
185
+ """A preset for `log()`: `WARN` log message with the options to pause
200
186
  at the message and exit the program after the message was printed."""
201
187
  Console.log("WARN", prompt, start, end, title_bg_color, default_color)
202
188
  Console.pause_exit(pause, exit)
@@ -212,7 +198,7 @@ class Console:
212
198
  exit: bool = True,
213
199
  reset_ansi=True,
214
200
  ) -> None:
215
- """A preset for `log()`: `FAIL` log message with the options to pause<br>
201
+ """A preset for `log()`: `FAIL` log message with the options to pause
216
202
  at the message and exit the program after the message was printed."""
217
203
  Console.log("FAIL", prompt, start, end, title_bg_color, default_color)
218
204
  Console.pause_exit(pause, exit, reset_ansi=reset_ansi)
@@ -228,7 +214,7 @@ class Console:
228
214
  exit: bool = True,
229
215
  reset_ansi=True,
230
216
  ) -> None:
231
- """A preset for `log()`: `EXIT` log message with the options to pause<br>
217
+ """A preset for `log()`: `EXIT` log message with the options to pause
232
218
  at the message and exit the program after the message was printed."""
233
219
  Console.log("EXIT", prompt, start, end, title_bg_color, default_color)
234
220
  Console.pause_exit(pause, exit, reset_ansi=reset_ansi)
@@ -242,10 +228,9 @@ class Console:
242
228
  default_is_yes: bool = True,
243
229
  ) -> bool:
244
230
  """Ask a yes/no question.\n
245
- -----------------------------------------------------------------------------------
246
- The question can be formatted with special formatting codes. For more detailed<br>
247
- information about formatting codes, see the `xx_format_codes` description.
248
- """
231
+ -------------------------------------------------------------------------------
232
+ The question can be formatted with special formatting codes. For more detailed
233
+ information about formatting codes, see the `xx_format_codes` description."""
249
234
  confirmed = input(
250
235
  FormatCodes.to_ansi(
251
236
  f'{start} {str(prompt)} [_|dim](({"Y" if default_is_yes else "y"}/{"n" if default_is_yes else "N"}): )',
@@ -271,9 +256,8 @@ class Console:
271
256
  - optional mask character (hide user input, e.g. for passwords)
272
257
  - reset the ANSI formatting codes after the user continues\n
273
258
  -----------------------------------------------------------------------------------
274
- The input can be formatted with special formatting codes. For more detailed<br>
275
- information about formatting codes, see the `xx_format_codes` description.
276
- """
259
+ The input can be formatted with special formatting codes. For more detailed
260
+ information about formatting codes, see the `xx_format_codes` description."""
277
261
  FormatCodes.print(prompt, end="", flush=True)
278
262
  result = ""
279
263
  select_all = False
@@ -377,5 +361,6 @@ class Console:
377
361
  max_len: int = None,
378
362
  _reset_ansi: bool = True,
379
363
  ) -> str:
380
- """Password input that masks the entered characters with asterisks."""
364
+ """Password input (preset for `Console.restricted_input()`)
365
+ that always masks the entered characters with asterisks."""
381
366
  return Console.restricted_input(prompt, allowed_chars, min_len, max_len, "*", _reset_ansi)
xulbux/xx_data.py CHANGED
@@ -26,7 +26,7 @@ class Data:
26
26
 
27
27
  @staticmethod
28
28
  def remove_empty_items(data: DataStructure, spaces_are_empty: bool = False) -> DataStructure:
29
- """Removes empty items from the data structure.<br>
29
+ """Removes empty items from the data structure.
30
30
  If `spaces_are_empty` is true, it will count items with only spaces as empty."""
31
31
  if isinstance(data, dict):
32
32
  return {
@@ -79,14 +79,15 @@ class Data:
79
79
  comment_sep: str = "",
80
80
  ) -> DataStructure:
81
81
  """Remove comments from a list, tuple or dictionary.\n
82
- --------------------------------------------------------------------------------------------------------------------
83
- The `data` parameter is your list, tuple or dictionary, where the comments should get removed from.<br>
84
- The `comment_start` parameter is the string that marks the start of a comment inside `data`. (default: `>>`)<br>
85
- The `comment_end` parameter is the string that marks the end of a comment inside `data`. (default: `<<`)<br>
86
- The `comment_sep` parameter is a string with which a comment will be replaced, if it is in the middle of a value.\n
87
- --------------------------------------------------------------------------------------------------------------------
88
- Examples:\n
89
- ```python\n data = {
82
+ ----------------------------------------------------------------------------------------------------------------------
83
+ - The `data` parameter is your list, tuple or dictionary, where the comments should get removed from.
84
+ - The `comment_start` parameter is the string that marks the start of a comment inside `data`. (default: `>>`)
85
+ - The `comment_end` parameter is the string that marks the end of a comment inside `data`. (default: `<<`)
86
+ - The `comment_sep` parameter is a string with which a comment will be replaced, if it is in the middle of a value.\n
87
+ ----------------------------------------------------------------------------------------------------------------------
88
+ Examples:
89
+ ```python
90
+ data = {
90
91
  "key1": [
91
92
  ">> COMMENT IN THE BEGINNING OF THE STRING << value1",
92
93
  "value2 >> COMMENT IN THE END OF THE STRING",
@@ -106,24 +107,25 @@ class Data:
106
107
  comment_start=">>",
107
108
  comment_end="<<",
108
109
  comment_sep="__"
109
- )\n```
110
- --------------------------------------------------------------------------------------------------------------------
110
+ )
111
+ ```\n
112
+ ----------------------------------------------------------------------------------------------------------------------
111
113
  For this example, `processed_data` will be:
112
- ```python\n {
114
+ ```python
115
+ {
113
116
  "key1": [
114
117
  "value1",
115
118
  "value2",
116
119
  "val__ue3"
117
120
  ],
118
121
  "key3": None
119
- }\n```
120
- For `key1`, all the comments will just be removed, except at `value3` and `value4`:<br>
121
-  `value3` The comment is removed and the parts left and right are joined through `comment_sep`.<br>
122
- `value4`The whole value is removed, since the whole value was a comment.<br>
123
- For `key2`, the key, including its whole values will be removed.<br>
124
- For `key3`, since all its values are just comments, the key will still exist, but with a value of `None`.
125
- """
126
-
122
+ }
123
+ ```\n
124
+ - For `key1`, all the comments will just be removed, except at `value3` and `value4`:
125
+ - `value3` The comment is removed and the parts left and right are joined through `comment_sep`.
126
+ - `value4` The whole value is removed, since the whole value was a comment.
127
+ - For `key2`, the key, including its whole values will be removed.
128
+ - For `key3`, since all its values are just comments, the key will still exist, but with a value of `None`."""
127
129
  if comment_end:
128
130
  pattern = _re.compile(
129
131
  rf"^((?:(?!{_re.escape(comment_start)}).)*){_re.escape(comment_start)}(?:(?:(?!{_re.escape(comment_end)}).)*)(?:{_re.escape(comment_end)})?(.*?)$"
@@ -163,13 +165,13 @@ class Data:
163
165
  comment_end: str = "<<",
164
166
  ) -> bool:
165
167
  """Compares two structures and returns `True` if they are equal and `False` otherwise.\n
166
- ⇾ **Will not detect, if a key-name has changed, only if removed or added.**\n
167
- ------------------------------------------------------------------------------------------------
168
- Ignores the specified (found) key/s or item/s from `ignore_paths`. Comments are not ignored<br>
169
- when comparing. `comment_start` and `comment_end` are only used to correctly recognize the<br>
168
+ ⇾ Will not detect, if a key-name has changed, only if removed or added.\n
169
+ --------------------------------------------------------------------------------------------
170
+ Ignores the specified (found) key/s or item/s from `ignore_paths`. Comments are not ignored
171
+ when comparing. `comment_start` and `comment_end` are only used to correctly recognize the
170
172
  keys in the `ignore_paths`.\n
171
- ------------------------------------------------------------------------------------------------
172
- The paths from `ignore_paths` and the `path_sep` parameter work exactly the same way as for<br>
173
+ --------------------------------------------------------------------------------------------
174
+ The paths from `ignore_paths` and the `path_sep` parameter work exactly the same way as for
173
175
  the function `Data.get_path_id()`. See its documentation for more details."""
174
176
 
175
177
  def process_ignore_paths(
@@ -222,26 +224,28 @@ class Data:
222
224
  -------------------------------------------------------------------------------------------------
223
225
  The `data` parameter is the list, tuple, or dictionary, which the id should be generated for.\n
224
226
  -------------------------------------------------------------------------------------------------
225
- The param `value_path` is a sort of path (or a list of paths) to the value/s to be updated.<br>
227
+ The param `value_path` is a sort of path (or a list of paths) to the value/s to be updated.
226
228
  In this example:
227
- ```\n {
229
+ ```python
230
+ {
228
231
  "healthy": {
229
232
  "fruit": ["apples", "bananas", "oranges"],
230
233
  "vegetables": ["carrots", "broccoli", "celery"]
231
234
  }
232
- }\n```
233
- ... if you want to change the value of `"apples"` to `"strawberries"`, the value path<br>
234
- would be `healthy->fruit->apples` or if you don't know that the value is `"apples"`<br>
235
- you can also use the index of the value, so `healthy->fruit->0`.\n
235
+ }
236
+ ```
237
+ ... if you want to change the value of `"apples"` to `"strawberries"`, the value path would be
238
+ `healthy->fruit->apples` or if you don't know that the value is `"apples"` you can also use the
239
+ index of the value, so `healthy->fruit->0`.\n
236
240
  -------------------------------------------------------------------------------------------------
237
- The comments marked with `comment_start` and `comment_end` will be removed,<br>
238
- before trying to get the path id.\n
241
+ The comments marked with `comment_start` and `comment_end` will be removed, before trying to get
242
+ the path id.\n
239
243
  -------------------------------------------------------------------------------------------------
240
- The `path_sep` param is the separator between the keys/indexes in the path<br>
241
- (default is `->` just like in the example above).\n
244
+ The `path_sep` param is the separator between the keys/indexes in the path (default is `->` just
245
+ like in the example above).\n
242
246
  -------------------------------------------------------------------------------------------------
243
- If `ignore_not_found` is `True`, the function will return `None` if the value is not<br>
244
- found instead of raising an error."""
247
+ If `ignore_not_found` is `True`, the function will return `None` if the value is not found
248
+ instead of raising an error."""
245
249
 
246
250
  def process_path(path: str, data_obj: list | tuple | set | frozenset | dict) -> str | None:
247
251
  keys = path.split(path_sep)
@@ -289,11 +293,11 @@ class Data:
289
293
  @staticmethod
290
294
  def get_value_by_path_id(data: DataStructure, path_id: str, get_key: bool = False) -> any:
291
295
  """Retrieves the value from `data` using the provided `path_id`.\n
292
- ----------------------------------------------------------------------------------------------------
293
- Input your `data` along with a `path_id` that was created before using `Data.get_path_id()`.<br>
296
+ -------------------------------------------------------------------------------------------------
297
+ Input your `data` along with a `path_id` that was created before using `Data.get_path_id()`.
294
298
  If `get_key` is true and the final item is in a dict, it returns the key instead of the value.\n
295
- ----------------------------------------------------------------------------------------------------
296
- The function will return the value (or key) from the path ID location, as long as the structure<br>
299
+ -------------------------------------------------------------------------------------------------
300
+ The function will return the value (or key) from the path ID location, as long as the structure
297
301
  of `data` hasn't changed since creating the path ID to that value."""
298
302
 
299
303
  def get_nested(data: list | tuple | set | frozenset | dict, path: list[int], get_key: bool) -> any:
@@ -326,12 +330,12 @@ class Data:
326
330
  ) -> list | tuple | dict:
327
331
  """Updates the value/s from `update_values` in the `data`.\n
328
332
  --------------------------------------------------------------------------------
329
- Input a list, tuple or dict as `data`, along with `update_values`, which is<br>
330
- a path ID that was created before using `Data.get_path_id()`, together<br>
331
- with the new value to be inserted where the path ID points to. The path ID<br>
332
- and the new value are separated by `sep`, which per default is `::`.\n
333
+ Input a list, tuple or dict as `data`, along with `update_values`, which is a
334
+ path ID that was created before using `Data.get_path_id()`, together with the
335
+ new value to be inserted where the path ID points to. The path ID and the new
336
+ value are separated by `sep`, which per default is `::`.\n
333
337
  --------------------------------------------------------------------------------
334
- The value from path ID will be changed to the new value, as long as the<br>
338
+ The value from path ID will be changed to the new value, as long as the
335
339
  structure of `data` hasn't changed since creating the path ID to that value."""
336
340
 
337
341
  def update_nested(
@@ -383,16 +387,15 @@ class Data:
383
387
  end: str = "\n",
384
388
  ) -> None:
385
389
  """Print nicely formatted data structures.\n
386
- ------------------------------------------------------------------------------------
387
- The indentation spaces-amount can be set with with `indent`.<br>
388
- There are three different levels of `compactness`:<br>
389
- `0` expands everything possible<br>
390
- `1` only expands if there's other lists, tuples or dicts inside of data or,<br>
391
-  ⠀if the data's content is longer than `max_width`<br>
392
- `2` keeps everything collapsed (all on one line)\n
393
- ------------------------------------------------------------------------------------
394
- If `as_json` is set to `True`, the output will be in valid JSON format.
395
- """
390
+ ------------------------------------------------------------------------------
391
+ The indentation spaces-amount can be set with with `indent`.
392
+ There are three different levels of `compactness`:
393
+ - `0` expands everything possible
394
+ - `1` only expands if there's other lists, tuples or dicts inside of data or,
395
+ if the data's content is longer than `max_width`
396
+ - `2` keeps everything collapsed (all on one line)\n
397
+ ------------------------------------------------------------------------------
398
+ If `as_json` is set to `True`, the output will be in valid JSON format."""
396
399
  print(
397
400
  Data.to_str(data, indent, compactness, sep, max_width, as_json),
398
401
  end=end,
@@ -409,14 +412,14 @@ class Data:
409
412
  as_json: bool = False,
410
413
  ) -> str:
411
414
  """Get nicely formatted data structure-strings.\n
412
- ------------------------------------------------------------------------------------
413
- The indentation spaces-amount can be set with with `indent`.<br>
414
- There are three different levels of `compactness`:<br>
415
- `0` expands everything possible<br>
416
- `1` only expands if there's other lists, tuples or dicts inside of data or,<br>
417
-  ⠀if the data's content is longer than `max_width`<br>
418
- `2` keeps everything collapsed (all on one line)\n
419
- ------------------------------------------------------------------------------------
415
+ ------------------------------------------------------------------------------
416
+ The indentation spaces-amount can be set with with `indent`.
417
+ There are three different levels of `compactness`:
418
+ - `0` expands everything possible
419
+ - `1` only expands if there's other lists, tuples or dicts inside of data or,
420
+ if the data's content is longer than `max_width`
421
+ - `2` keeps everything collapsed (all on one line)\n
422
+ ------------------------------------------------------------------------------
420
423
  If `as_json` is set to `True`, the output will be in valid JSON format."""
421
424
 
422
425
  def format_value(value: any, current_indent: int) -> str:
@@ -495,7 +498,7 @@ class Data:
495
498
  def _is_key(data: DataStructure, path_id: str) -> bool:
496
499
  """Returns `True` if the path ID points to a key in `data` and `False` otherwise.\n
497
500
  ------------------------------------------------------------------------------------
498
- Input a list, tuple or dict as `data`, along with `path_id`, which is a path ID<br>
501
+ Input a list, tuple or dict as `data`, along with `path_id`, which is a path ID
499
502
  that was created before using `Data.get_path_id()`."""
500
503
 
501
504
  def check_nested(data: list | tuple | set | frozenset | dict, path: list[int]) -> bool:
xulbux/xx_env_path.py CHANGED
@@ -8,8 +8,8 @@ Functions for modifying and checking the systems environment-variables:
8
8
 
9
9
  from .xx_path import Path
10
10
 
11
- import os as _os
12
11
  import sys as _sys
12
+ import os as _os
13
13
 
14
14
 
15
15
  class EnvPath:
@@ -60,9 +60,9 @@ class EnvPath:
60
60
  cwd: bool = False,
61
61
  base_dir: bool = False,
62
62
  ) -> list:
63
- """Get and/or normalize the paths.<br>
64
- Raise an error if no path is provided and<br>
65
- neither `cwd` or `base_dir` is `True`."""
63
+ """Get and/or normalize the paths.\n
64
+ ------------------------------------------------------------------------------------
65
+ Raise an error if no path is provided and neither `cwd` or `base_dir` is `True`."""
66
66
  if cwd:
67
67
  path = _os.getcwd()
68
68
  elif base_dir:
xulbux/xx_file.py CHANGED
@@ -7,20 +7,31 @@ import os as _os
7
7
  class File:
8
8
 
9
9
  @staticmethod
10
- def rename_extension(file_path: str, new_extension: str) -> str:
11
- directory, filename_with_ext = _os.path.split(file_path)
10
+ def rename_extension(
11
+ file: str,
12
+ new_extension: str,
13
+ camel_case_filename: bool = False,
14
+ ) -> str:
15
+ """Rename the extension of a file.\n
16
+ --------------------------------------------------------------------------
17
+ If the `camel_case_filename` parameter is true, the filename will be made
18
+ CamelCase in addition to changing the files extension."""
19
+ directory, filename_with_ext = _os.path.split(file)
12
20
  filename = filename_with_ext.split(".")[0]
13
- camel_case_filename = String.to_camel_case(filename)
14
- new_filename = f"{camel_case_filename}{new_extension}"
15
- new_file_path = _os.path.join(directory, new_filename)
16
- return new_file_path
21
+ if camel_case_filename:
22
+ filename = String.to_camel_case(filename)
23
+ return _os.path.join(directory, f"{filename}{new_extension}")
17
24
 
18
25
  @staticmethod
19
- def create(content: str = "", file: str = "new_file.txt", force: bool = False) -> str:
26
+ def create(
27
+ file: str,
28
+ content: str = "",
29
+ force: bool = False,
30
+ ) -> str:
20
31
  """Create a file with ot without content.\n
21
- ----------------------------------------------------------------------------
22
- The function will throw a `FileExistsError` if the file already exists.<br>
23
- To overwrite the file, set the `force` parameter to `True`."""
32
+ ------------------------------------------------------------------------
33
+ The function will throw a `FileExistsError` if the file already exists.
34
+ To always overwrite the file, set the `force` parameter to `True`."""
24
35
  if _os.path.exists(file) and not force:
25
36
  with open(file, "r", encoding="utf-8") as existing_file:
26
37
  existing_content = existing_file.read()
@@ -33,24 +44,22 @@ class File:
33
44
  return full_path
34
45
 
35
46
  @staticmethod
36
- def make_path(
37
- filename: str,
38
- filetype: str,
47
+ def extend_or_make_path(
48
+ file: str,
39
49
  search_in: str | list[str] = None,
40
50
  prefer_base_dir: bool = True,
41
- correct_path: bool = False,
51
+ correct_paths: bool = False,
42
52
  ) -> str:
43
- """Create the path to a file in the cwd, the base-dir, or predefined directories.\n
44
- --------------------------------------------------------------------------------------
45
- If the `filename` is not found in the above directories, it will be searched<br>
46
- in the `search_in` directory/directories. If the file is still not found, it will<br>
47
- return the path to the file in the base-dir per default or to the file in the<br>
48
- cwd if `prefer_base_dir` is set to `False`."""
49
- if not filename.lower().endswith(f".{filetype.lower()}"):
50
- filename = f"{filename}.{filetype.lower()}"
53
+ """Tries to find the file and extend the path to be absolute and if the file was not found:\n
54
+ Generate the absolute path to the file in the CWD or the running program's base-directory.\n
55
+ ----------------------------------------------------------------------------------------------
56
+ If the `file` is not found in the above directories, it will be searched in the `search_in`
57
+ directory/directories. If the file is still not found, it will return the path to the file in
58
+ the base-dir per default or to the file in the CWD if `prefer_base_dir` is set to `False`.\n
59
+ ----------------------------------------------------------------------------------------------
60
+ If `correct_paths` is true, it is possible to have typos in the `search_in` path/s and it
61
+ will still find the file if it is under one of those paths."""
51
62
  try:
52
- return Path.extend(filename, search_in, True, correct_path)
63
+ return Path.extend(file, search_in, raise_error=True, correct_path=correct_paths)
53
64
  except FileNotFoundError:
54
- return (
55
- _os.path.join(Path.get(base_dir=True), filename) if prefer_base_dir else _os.path.join(_os.getcwd(), filename)
56
- )
65
+ return _os.path.join(Path.get(base_dir=True), file) if prefer_base_dir else _os.path.join(_os.getcwd(), file)