xulbux 1.6.9__py3-none-any.whl → 1.7.1__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_format_codes.py CHANGED
@@ -133,7 +133,8 @@ the formatting code:
133
133
  #### Additional Formatting Codes when a `default_color` is set
134
134
 
135
135
  1. `[*]` resets everything, just like `[_]`, but the text color will remain in `default_color`
136
- 2. `[*color]` will reset the text color, just like `[_color]`, but then also make it `default_color`
136
+ (*if no `default_color` it resets everything, including the text color*)
137
+ 2. `[*color]` `[*c]` will reset the text color, just like `[_color]`, but then also make it `default_color`
137
138
  3. `[default]` will just color the text in `default_color`
138
139
  4. `[background:default]` `[BG:default]` will color the background in `default_color`
139
140
 
@@ -152,10 +153,10 @@ Per default, you can also use `+` and `-` to get lighter and darker `default_col
152
153
 
153
154
  from ._consts_ import ANSI
154
155
  from .xx_string import String
155
- from .xx_regex import Regex
156
- from .xx_color import Color, rgba, hexa
156
+ from .xx_regex import Regex, Match, Pattern
157
+ from .xx_color import Color, rgba, Rgba, Hexa
157
158
 
158
- from typing import Optional, Pattern
159
+ from typing import Optional, cast
159
160
  import ctypes as _ctypes
160
161
  import regex as _rx
161
162
  import sys as _sys
@@ -174,7 +175,7 @@ _PREFIX_RX: dict[str, str] = {
174
175
  }
175
176
  _COMPILED: dict[str, Pattern] = { # PRECOMPILE REGULAR EXPRESSIONS
176
177
  "*": _re.compile(r"\[\s*([^]_]*?)\s*\*\s*([^]_]*?)\]"),
177
- "*color": _re.compile(r"\[\s*([^]_]*?)\s*\*color\s*([^]_]*?)\]"),
178
+ "*color": _re.compile(r"\[\s*([^]_]*?)\s*\*c(?:olor)?\s*([^]_]*?)\]"),
178
179
  "ansi_seq": _re.compile(ANSI.char + r"(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])"),
179
180
  "formatting": _rx.compile(
180
181
  Regex.brackets("[", "]", is_group=True, ignore_in_strings=False)
@@ -205,7 +206,7 @@ class FormatCodes:
205
206
  @staticmethod
206
207
  def print(
207
208
  *values: object,
208
- default_color: rgba | hexa = None,
209
+ default_color: Optional[Rgba | Hexa] = None,
209
210
  brightness_steps: int = 20,
210
211
  sep: str = " ",
211
212
  end: str = "\n",
@@ -223,7 +224,7 @@ class FormatCodes:
223
224
  @staticmethod
224
225
  def input(
225
226
  prompt: object = "",
226
- default_color: rgba | hexa = None,
227
+ default_color: Optional[Rgba | Hexa] = None,
227
228
  brightness_steps: int = 20,
228
229
  reset_ansi: bool = False,
229
230
  ) -> str:
@@ -243,7 +244,7 @@ class FormatCodes:
243
244
  @staticmethod
244
245
  def to_ansi(
245
246
  string: str,
246
- default_color: rgba | hexa = None,
247
+ default_color: Optional[Rgba | Hexa] = None,
247
248
  brightness_steps: int = 20,
248
249
  _default_start: bool = True,
249
250
  ) -> str:
@@ -253,20 +254,23 @@ class FormatCodes:
253
254
  `xx_format_codes` module documentation."""
254
255
  if not isinstance(string, str):
255
256
  string = str(string)
256
- if Color.is_valid_rgba(default_color, False):
257
+ if default_color and Color.is_valid_rgba(default_color, False):
257
258
  use_default = True
258
- elif Color.is_valid_hexa(default_color, False):
259
+ elif default_color and Color.is_valid_hexa(default_color, False):
259
260
  use_default, default_color = True, Color.to_rgba(default_color)
260
261
  else:
261
262
  use_default = False
263
+ default_color = cast(rgba, default_color) if use_default else None
262
264
  if use_default:
263
265
  string = _COMPILED["*"].sub(r"[\1_|default\2]", string) # REPLACE `[…|*|…]` WITH `[…|_|default|…]`
264
- string = _COMPILED["*color"].sub(r"[\1default\2]", string) # REPLACE `[…|*color|…]` WITH `[…|default|…]`
266
+ string = _COMPILED["*color"].sub(r"[\1default\2]", string) # REPLACE `[…|*color|…]` OR `[…|*c|…]` WITH `[…|default|…]`
267
+ else:
268
+ string = _COMPILED["*"].sub(r"[\1_\2]", string) # REPLACE `[…|*|…]` WITH `[…|_|…]`
265
269
 
266
270
  def is_valid_color(color: str) -> bool:
267
- return color in ANSI.color_map or Color.is_valid_rgba(color) or Color.is_valid_hexa(color)
271
+ return bool((color in ANSI.color_map) or Color.is_valid_rgba(color) or Color.is_valid_hexa(color))
268
272
 
269
- def replace_keys(match: _re.Match) -> str:
273
+ def replace_keys(match: Match) -> str:
270
274
  _formats = formats = match.group(1)
271
275
  auto_reset_escaped = match.group(2)
272
276
  auto_reset_txt = match.group(3)
@@ -292,7 +296,7 @@ class FormatCodes:
292
296
  if k_set & _PREFIX["BR"]:
293
297
  for i in range(len(k)):
294
298
  if is_valid_color(k[i:]):
295
- reset_keys.extend(["_bg", "_color"])
299
+ reset_keys.extend(["_bg", "default"] if use_default else ["_bg", "_c"])
296
300
  break
297
301
  else:
298
302
  for i in range(len(k)):
@@ -302,7 +306,7 @@ class FormatCodes:
302
306
  elif is_valid_color(k) or any(
303
307
  k_lower.startswith(pref_colon := f"{prefix}:") and is_valid_color(k[len(pref_colon):])
304
308
  for prefix in _PREFIX["BR"]):
305
- reset_keys.append("_color")
309
+ reset_keys.append("default" if use_default else "_c")
306
310
  else:
307
311
  reset_keys.append(f"_{k}")
308
312
  ansi_resets = [
@@ -325,7 +329,8 @@ class FormatCodes:
325
329
  )
326
330
 
327
331
  string = "\n".join(_COMPILED["formatting"].sub(replace_keys, line) for line in string.split("\n"))
328
- return ((FormatCodes.__get_default_ansi(default_color) if _default_start else "") + string) if use_default else string
332
+ return (((FormatCodes.__get_default_ansi(default_color.values()) or "") if _default_start else "")
333
+ + string) if default_color is not None else string
329
334
 
330
335
  @staticmethod
331
336
  def escape_ansi(ansi_string: str) -> str:
@@ -346,7 +351,7 @@ class FormatCodes:
346
351
  if get_removals:
347
352
  removals = []
348
353
 
349
- def replacement(match: _re.Match) -> str:
354
+ def replacement(match: Match) -> str:
350
355
  start_pos = match.start() - sum(len(removed) for _, removed in removals)
351
356
  if removals and removals[-1][0] == start_pos:
352
357
  start_pos = removals[-1][0]
@@ -364,6 +369,7 @@ class FormatCodes:
364
369
  @staticmethod
365
370
  def remove_formatting(
366
371
  string: str,
372
+ default_color: Optional[Rgba | Hexa] = None,
367
373
  get_removals: bool = False,
368
374
  _ignore_linebreaks: bool = False,
369
375
  ) -> str | tuple[str, tuple[tuple[int, str], ...]]:
@@ -373,7 +379,7 @@ class FormatCodes:
373
379
  Each tuple contains the position of the removed formatting code and the removed formatting code.\n
374
380
  If `_ignore_linebreaks` is true, linebreaks will be ignored for the removal positions."""
375
381
  return FormatCodes.remove_ansi(
376
- FormatCodes.to_ansi(string),
382
+ FormatCodes.to_ansi(string, default_color=default_color),
377
383
  get_removals=get_removals,
378
384
  _ignore_linebreaks=_ignore_linebreaks,
379
385
  )
@@ -393,9 +399,9 @@ class FormatCodes:
393
399
 
394
400
  @staticmethod
395
401
  def __get_default_ansi(
396
- default_color: tuple,
397
- format_key: str = None,
398
- brightness_steps: int = None,
402
+ default_color: tuple[int, int, int],
403
+ format_key: Optional[str] = None,
404
+ brightness_steps: Optional[int] = None,
399
405
  _modifiers: tuple[str, str] = (ANSI.default_color_modifiers["lighten"], ANSI.default_color_modifiers["darken"]),
400
406
  ) -> Optional[str]:
401
407
  """Get the `default_color` and lighter/darker versions of it as ANSI code."""
@@ -403,8 +409,9 @@ class FormatCodes:
403
409
  return (ANSI.seq_bg_color if format_key and _COMPILED["bg_default"].search(format_key) else ANSI.seq_color).format(
404
410
  *default_color[:3]
405
411
  )
406
- if not (format_key in _modifiers[0] or format_key in _modifiers[1]):
412
+ if format_key is None or not (format_key in _modifiers[0] or format_key in _modifiers[1]):
407
413
  return None
414
+ assert format_key is not None
408
415
  match = _COMPILED["modifier"].match(format_key)
409
416
  if not match:
410
417
  return None
@@ -415,23 +422,25 @@ class FormatCodes:
415
422
  if adjust and adjust > 0:
416
423
  modifiers = mod
417
424
  break
425
+ new_rgb = default_color
418
426
  if adjust == 0:
419
427
  return None
420
428
  elif modifiers in _modifiers[0]:
421
- new_rgb = Color.adjust_lightness(default_color, (brightness_steps / 100) * adjust)
429
+ new_rgb = tuple(Color.adjust_lightness(default_color, (brightness_steps / 100) * adjust))
422
430
  elif modifiers in _modifiers[1]:
423
- new_rgb = Color.adjust_lightness(default_color, -(brightness_steps / 100) * adjust)
431
+ new_rgb = tuple(Color.adjust_lightness(default_color, -(brightness_steps / 100) * adjust))
424
432
  return (ANSI.seq_bg_color if is_bg else ANSI.seq_color).format(*new_rgb[:3])
425
433
 
426
434
  @staticmethod
427
- def __get_replacement(format_key: str, default_color: rgba = None, brightness_steps: int = 20) -> str:
435
+ def __get_replacement(format_key: str, default_color: Optional[rgba], brightness_steps: int = 20) -> str:
428
436
  """Gives you the corresponding ANSI code for the given format key.
429
437
  If `default_color` is not `None`, the text color will be `default_color` if all formats
430
438
  are reset or you can get lighter or darker version of `default_color` (also as BG)"""
431
439
  use_default = default_color and Color.is_valid_rgba(default_color, False)
440
+ _default_color = tuple(Color.to_rgba(default_color)) if default_color is not None else tuple()
432
441
  _format_key, format_key = format_key, FormatCodes.__normalize_key(format_key) # NORMALIZE KEY AND SAVE ORIGINAL
433
442
  if use_default:
434
- if new_default_color := FormatCodes.__get_default_ansi(default_color, format_key, brightness_steps):
443
+ if new_default_color := FormatCodes.__get_default_ansi(_default_color, format_key, brightness_steps):
435
444
  return new_default_color
436
445
  for map_key in ANSI.codes_map:
437
446
  if (isinstance(map_key, tuple) and format_key in map_key) or format_key == map_key:
@@ -440,8 +449,8 @@ class FormatCodes:
440
449
  v for k, v in ANSI.codes_map.items() if format_key == k or (isinstance(k, tuple) and format_key in k)
441
450
  ), None)
442
451
  )
443
- rgb_match = _re.match(_COMPILED["rgb"], format_key)
444
- hex_match = _re.match(_COMPILED["hex"], format_key)
452
+ rgb_match = _COMPILED["rgb"].match(format_key)
453
+ hex_match = _COMPILED["hex"].match(format_key)
445
454
  try:
446
455
  if rgb_match:
447
456
  is_bg = rgb_match.group(1)
xulbux/xx_json.py CHANGED
@@ -26,13 +26,15 @@ class Json:
26
26
  if not json_file.endswith(".json"):
27
27
  json_file += ".json"
28
28
  file_path = Path.extend_or_make(json_file, prefer_script_dir=True)
29
+ if file_path is None:
30
+ raise FileNotFoundError(f"Could not find JSON file: {json_file}")
29
31
  with open(file_path, "r") as f:
30
32
  content = f.read()
31
33
  try:
32
34
  data = _json.loads(content)
33
35
  except _json.JSONDecodeError as e:
34
36
  raise ValueError(f"Error parsing JSON in '{file_path}': {str(e)}")
35
- processed_data = Data.remove_comments(data, comment_start, comment_end)
37
+ processed_data = dict(Data.remove_comments(data, comment_start, comment_end))
36
38
  if not processed_data:
37
39
  raise ValueError(f"The JSON file '{file_path}' is empty or contains only comments.")
38
40
  return (processed_data, data) if return_original else processed_data
@@ -135,24 +137,23 @@ class Json:
135
137
  raise TypeError(f"Cannot navigate through {type(current).__name__}")
136
138
  return data_obj
137
139
 
140
+ update = {}
138
141
  for value_path, new_value in update_values.items():
139
142
  try:
140
143
  path_id = Data.get_path_id(
141
144
  data=processed_data,
142
145
  value_paths=value_path,
143
146
  path_sep=path_sep,
144
- ignore_not_found=True,
145
147
  )
146
148
  if path_id is not None:
147
- if 'update' not in locals():
148
- update = {}
149
149
  update[path_id] = new_value
150
150
  else:
151
+ keys = value_path.split(path_sep)
151
152
  keys = value_path.split(path_sep)
152
153
  data = create_nested_path(data, keys, new_value)
153
154
  except Exception:
154
155
  keys = value_path.split(path_sep)
155
156
  data = create_nested_path(data, keys, new_value)
156
- if 'update' in locals() and update:
157
+ if "update" in locals() and update:
157
158
  data = Data.set_value_by_path_id(data, update)
158
- Json.create(json_file=json_file, data=data, force=True)
159
+ Json.create(json_file=json_file, data=dict(data), force=True)
xulbux/xx_path.py CHANGED
@@ -23,9 +23,9 @@ class _ScriptDir:
23
23
  base_path = _os.path.dirname(_sys.executable)
24
24
  else:
25
25
  main_module = _sys.modules["__main__"]
26
- if hasattr(main_module, "__file__"):
26
+ if hasattr(main_module, "__file__") and main_module.__file__ is not None:
27
27
  base_path = _os.path.dirname(_os.path.abspath(main_module.__file__))
28
- elif (hasattr(main_module, "__spec__") and main_module.__spec__ and getattr(main_module.__spec__, "origin", None)):
28
+ elif (hasattr(main_module, "__spec__") and main_module.__spec__ and main_module.__spec__.origin is not None):
29
29
  base_path = _os.path.dirname(_os.path.abspath(main_module.__spec__.origin))
30
30
  else:
31
31
  raise RuntimeError("Can only get base directory if accessed from a file.")
@@ -34,15 +34,15 @@ class _ScriptDir:
34
34
 
35
35
  class Path:
36
36
 
37
- cwd: str = _Cwd()
37
+ cwd: str = _Cwd() # type: ignore[assignment]
38
38
  """The path to the current working directory."""
39
- script_dir: str = _ScriptDir()
39
+ script_dir: str = _ScriptDir() # type: ignore[assignment]
40
40
  """The path to the directory of the current script."""
41
41
 
42
42
  @staticmethod
43
43
  def extend(
44
44
  rel_path: str,
45
- search_in: str | list[str] = None,
45
+ search_in: Optional[str | list[str]] = None,
46
46
  raise_error: bool = False,
47
47
  use_closest_match: bool = False,
48
48
  ) -> Optional[str]:
@@ -120,7 +120,7 @@ class Path:
120
120
  @staticmethod
121
121
  def extend_or_make(
122
122
  rel_path: str,
123
- search_in: str | list[str] = None,
123
+ search_in: Optional[str | list[str]] = None,
124
124
  prefer_script_dir: bool = True,
125
125
  use_closest_match: bool = False,
126
126
  ) -> str:
@@ -136,7 +136,7 @@ class Path:
136
136
  If `use_closest_match` is true, it is possible to have typos in the `search_in` path/s
137
137
  and it will still find the file if it is under one of those paths."""
138
138
  try:
139
- return Path.extend(rel_path, search_in, raise_error=True, use_closest_match=use_closest_match)
139
+ return str(Path.extend(rel_path, search_in, raise_error=True, use_closest_match=use_closest_match))
140
140
  except PathNotFoundError:
141
141
  normalized_rel_path = _os.path.normpath(rel_path)
142
142
  base = Path.script_dir if prefer_script_dir else _os.getcwd()
xulbux/xx_regex.py CHANGED
@@ -1,18 +1,23 @@
1
+ from typing import TypeAlias, Optional
1
2
  import regex as _rx
2
3
  import re as _re
3
4
 
4
5
 
6
+ Pattern: TypeAlias = _re.Pattern[str] | _rx.Pattern[str]
7
+ Match: TypeAlias = _re.Match[str] | _rx.Match[str]
8
+
9
+
5
10
  class Regex:
6
11
 
7
12
  @staticmethod
8
13
  def quotes() -> str:
9
- """Matches everything inside quotes. (strings)\n
14
+ """Matches pairs of quotes. (strings)\n
10
15
  --------------------------------------------------------------------------------
11
16
  Will create two named groups:
12
17
  - `quote` the quote type (single or double)
13
18
  - `string` everything inside the found quote pair\n
14
- --------------------------------------------------------------------------------
15
- Attention: Requires non standard library `regex` not standard library `re`!"""
19
+ ---------------------------------------------------------------------------------
20
+ Attention: Requires non-standard library `regex`, not standard library `re`!"""
16
21
  return r'(?P<quote>[\'"])(?P<string>(?:\\.|(?!\g<quote>).)*?)\g<quote>'
17
22
 
18
23
  @staticmethod
@@ -23,16 +28,16 @@ class Regex:
23
28
  strip_spaces: bool = True,
24
29
  ignore_in_strings: bool = True,
25
30
  ) -> str:
26
- """Matches everything inside brackets, including other nested brackets.\n
27
- --------------------------------------------------------------------------------
31
+ """Matches everything inside pairs of brackets, including other nested brackets.\n
32
+ -----------------------------------------------------------------------------------
28
33
  If `is_group` is true, you will be able to reference the matched content as a
29
34
  group (e.g. `match.group(…)` or `r'\\…'`).
30
35
  If `strip_spaces` is true, it will ignore spaces around the content inside the
31
36
  brackets.
32
37
  If `ignore_in_strings` is true and a bracket is inside a string (e.g. `'...'`
33
38
  or `"..."`), it will not be counted as the matching closing bracket.\n
34
- --------------------------------------------------------------------------------
35
- Attention: Requires non standard library `regex` not standard library `re`!"""
39
+ -----------------------------------------------------------------------------------
40
+ Attention: Requires non-standard library `regex`, not standard library `re`!"""
36
41
  g, b1, b2, s1, s2 = (
37
42
  "" if is_group else "?:",
38
43
  _rx.escape(bracket1) if len(bracket1) == 1 else bracket1,
@@ -63,13 +68,13 @@ class Regex:
63
68
  return rf'({"" if is_group else "?:"}(?:(?!{ignore_pattern}).)*(?:(?!{Regex.outside_strings(disallowed_pattern)}).)*)'
64
69
 
65
70
  @staticmethod
66
- def func_call(func_name: str = None) -> str:
71
+ def func_call(func_name: Optional[str] = None) -> str:
67
72
  """Match a function call, and get back two groups:
68
73
  1. function name
69
74
  2. the function's arguments\n
70
75
  If no `func_name` is given, it will match any function call.\n
71
- --------------------------------------------------------------------------------
72
- Attention: Requires non standard library `regex` not standard library `re`!"""
76
+ ---------------------------------------------------------------------------------
77
+ Attention: Requires non-standard library `regex`, not standard library `re`!"""
73
78
  return (
74
79
  r"(?<=\b)(" + (r"[\w_]+" if func_name is None else func_name) + r")\s*" + Regex.brackets("(", ")", is_group=True)
75
80
  )
xulbux/xx_system.py CHANGED
@@ -14,7 +14,7 @@ class _IsElevated:
14
14
  if _os.name == "nt":
15
15
  return _ctypes.windll.shell32.IsUserAnAdmin() != 0
16
16
  elif _os.name == "posix":
17
- return _os.geteuid() == 0
17
+ return _os.geteuid() == 0 # type: ignore[attr-defined]
18
18
  except Exception:
19
19
  pass
20
20
  return False
@@ -22,7 +22,7 @@ class _IsElevated:
22
22
 
23
23
  class System:
24
24
 
25
- is_elevated: bool = _IsElevated()
25
+ is_elevated: bool = _IsElevated() # type: ignore[assignment]
26
26
  """Is `True` if the current process has
27
27
  elevated privileges and `False` otherwise."""
28
28
 
@@ -54,7 +54,7 @@ class System:
54
54
  if len(processes) > 2: # EXCLUDING THE PYTHON PROCESS AND PS
55
55
  raise RuntimeError("Processes are still running. Use the parameter `force=True` to restart anyway.")
56
56
  if prompt:
57
- _subprocess.Popen(["notify-send", "System Restart", prompt])
57
+ _subprocess.Popen(["notify-send", "System Restart", str(prompt)])
58
58
  _time.sleep(wait)
59
59
  try:
60
60
  _subprocess.run(["sudo", "shutdown", "-r", "now"])
@@ -95,7 +95,7 @@ class System:
95
95
  return missing
96
96
 
97
97
  @staticmethod
98
- def elevate(win_title: Optional[str] = None, args: Optional[list] = None) -> bool:
98
+ def elevate(win_title: Optional[str] = None, args: list = []) -> bool:
99
99
  """Attempts to start a new process with elevated privileges.\n
100
100
  ---------------------------------------------------------------------------------
101
101
  The param `win_title` is window the title of the elevated process.
@@ -106,7 +106,7 @@ class System:
106
106
  ---------------------------------------------------------------------------------
107
107
  Returns `True` if the current process already has elevated privileges and raises
108
108
  a `PermissionError` if the user denied the elevation or the elevation failed."""
109
- if System.is_elevated():
109
+ if System.is_elevated:
110
110
  return True
111
111
  if _os.name == "nt": # WINDOWS
112
112
  if win_title:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xulbux
3
- Version: 1.6.9
3
+ Version: 1.7.1
4
4
  Summary: A Python library which includes lots of helpful classes, types and functions aiming to make common programming tasks simpler.
5
5
  Author-email: XulbuX <xulbux.real@gmail.com>
6
6
  License-Expression: MIT
@@ -34,14 +34,14 @@ Requires-Dist: flake8>=6.1.0; extra == "dev"
34
34
  Requires-Dist: flake8-pyproject>=1.2.3; extra == "dev"
35
35
  Dynamic: license-file
36
36
 
37
- # **$\color{#8085FF}\Huge\textsf{XulbuX}$**
37
+ # **$\Huge\textsf{XulbuX}$**
38
38
 
39
- **$\color{#8085FF}\textsf{XulbuX}$** is library that contains many useful classes, types, and functions,
39
+ **XulbuX** is library that contains many useful classes, types, and functions,
40
40
  ranging from console logging and working with colors to file management and system operations.
41
41
  The library is designed to simplify common programming tasks and improve code readability through its collection of tools.
42
42
 
43
- For precise information about the library, see the library's [wiki page](https://github.com/XulbuX/PythonLibraryXulbuX/wiki).<br>
44
- For the libraries latest changes and updates, see the [change log](https://github.com/XulbuX/PythonLibraryXulbuX/blob/main/CHANGELOG.md).
43
+ For precise information about the library, see the library's [**wiki page**](https://github.com/XulbuX/PythonLibraryXulbuX/wiki).<br>
44
+ For the libraries latest changes and updates, see the [**change log**](https://github.com/XulbuX/PythonLibraryXulbuX/blob/main/CHANGELOG.md).
45
45
 
46
46
  <br>
47
47
 
@@ -81,20 +81,20 @@ from xulbux import rgba, hsla, hexa
81
81
 
82
82
  ## Modules
83
83
 
84
- | Module | Short Description |
85
- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |
86
- | [![xx_code](https://img.shields.io/badge/xx__code-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code) | advanced code-string operations (*changing the indent, finding function calls, ...*) |
87
- | [![xx_color](https://img.shields.io/badge/xx__color-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color) | everything around colors (*converting, blending, searching colors in strings, ...*) |
88
- | [![xx_console](https://img.shields.io/badge/xx__console-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console) | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
89
- | [![xx_data](https://img.shields.io/badge/xx__data-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data) | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
84
+ | Module | Short Description |
85
+ | :--------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |
86
+ | [![xx_code](https://img.shields.io/badge/xx__code-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code) | advanced code-string operations (*changing the indent, finding function calls, ...*) |
87
+ | [![xx_color](https://img.shields.io/badge/xx__color-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color) | everything around colors (*converting, blending, searching colors in strings, ...*) |
88
+ | [![xx_console](https://img.shields.io/badge/xx__console-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console) | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
89
+ | [![xx_data](https://img.shields.io/badge/xx__data-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data) | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
90
90
  | [![xx_env_path](https://img.shields.io/badge/xx__env__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_env_path) | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
91
- | [![xx_file](https://img.shields.io/badge/xx__file-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file) | advanced working with files (*create files, rename file-extensions, ...*) |
91
+ | [![xx_file](https://img.shields.io/badge/xx__file-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file) | advanced working with files (*create files, rename file-extensions, ...*) |
92
92
  | [![xx_format_codes](https://img.shields.io/badge/xx__format__codes-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_format_codes) | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
93
- | [![xx_json](https://img.shields.io/badge/xx__json-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_json) | advanced working with json files (*read, create, update, ...*) |
94
- | [![xx_path](https://img.shields.io/badge/xx__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_path) | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
95
- | ![xx_regex](https://img.shields.io/badge/xx__regex-6065FF?style=flat) | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
96
- | [![xx_string](https://img.shields.io/badge/xx__string-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string) | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
97
- | ![xx_system](https://img.shields.io/badge/xx__system-6065FF?style=flat) | advanced system actions (*restart with message, check installed Python libs, ...*) |
93
+ | [![xx_json](https://img.shields.io/badge/xx__json-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_json) | advanced working with json files (*read, create, update, ...*) |
94
+ | [![xx_path](https://img.shields.io/badge/xx__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_path) | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
95
+ | ![xx_regex](https://img.shields.io/badge/xx__regex-6065FF?style=flat) | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
96
+ | [![xx_string](https://img.shields.io/badge/xx__string-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string) | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
97
+ | ![xx_system](https://img.shields.io/badge/xx__system-6065FF?style=flat) | advanced system actions (*restart with message, check installed Python libs, ...*) |
98
98
 
99
99
  <br>
100
100
 
@@ -111,15 +111,15 @@ def main() -> None:
111
111
 
112
112
  # LET THE USER ENTER A HEXA COLOR IN ANY HEXA FORMAT
113
113
  input_clr = FormatCodes.input(
114
- "\n[b](Enter a HEXA color in any format) [dim](>) "
114
+ "\n[b](Enter a HEXA color in any format) [dim](>) "
115
115
  )
116
116
 
117
117
  # ANNOUNCE INDEXING THE INPUT COLOR
118
118
  Console.log(
119
- "INDEX",
120
- "Indexing the input HEXA color...",
121
- start="\n",
122
- title_bg_color=COLOR.blue,
119
+ "INDEX",
120
+ "Indexing the input HEXA color...",
121
+ start="\n",
122
+ title_bg_color=COLOR.blue,
123
123
  )
124
124
 
125
125
  try:
@@ -129,16 +129,16 @@ def main() -> None:
129
129
  except ValueError:
130
130
  # ANNOUNCE THE ERROR AND EXIT THE PROGRAM
131
131
  Console.fail(
132
- "The input HEXA color is invalid.",
133
- end="\n\n",
134
- exit=True,
132
+ "The input HEXA color is invalid.",
133
+ end="\n\n",
134
+ exit=True,
135
135
  )
136
136
 
137
137
  # ANNOUNCE STARTING THE CONVERSION
138
138
  Console.log(
139
- "CONVERT",
140
- "Converting the HEXA color into different types...",
141
- title_bg_color=COLOR.tangerine,
139
+ "CONVERT",
140
+ "Converting the HEXA color into different types...",
141
+ title_bg_color=COLOR.tangerine,
142
142
  )
143
143
 
144
144
  # CONVERT THE HEXA COLOR INTO THE TWO OTHER COLOR TYPES
@@ -147,14 +147,16 @@ def main() -> None:
147
147
 
148
148
  # ANNOUNCE THE SUCCESSFUL CONVERSION
149
149
  Console.done(
150
- "Successfully converted color into different types.",
151
- end="\n\n",
150
+ "Successfully converted color into different types.",
151
+ end="\n\n",
152
152
  )
153
153
 
154
154
  # PRETTY PRINT THE COLOR IN DIFFERENT TYPES
155
- FormatCodes.print(f"[b](HEXA:) [i|white]({hexa_color})")
156
- FormatCodes.print(f"[b](RGBA:) [i|white]({rgba_color})")
157
- FormatCodes.print(f"[b](HSLA:) [i|white]({hsla_color})\n")
155
+ Console.log_box_bordered(
156
+ f"[b](HEXA:) [i|white]({hexa_color})",
157
+ f"[b](RGBA:) [i|white]({rgba_color})",
158
+ f"[b](HSLA:) [i|white]({hsla_color})",
159
+ )
158
160
 
159
161
 
160
162
  if __name__ == "__main__":
@@ -165,4 +167,4 @@ if __name__ == "__main__":
165
167
  <br>
166
168
 
167
169
  --------------------------------------------------------------
168
- [View this library on PyPI](https://pypi.org/project/XulbuX/)
170
+ [View this library on **PyPI**](https://pypi.org/project/XulbuX/)
@@ -0,0 +1,21 @@
1
+ xulbux/__init__.py,sha256=4qceHbARrYX-ui-kl5bufH3BlEvMwJpsXG1TQsbNHgA,815
2
+ xulbux/_cli_.py,sha256=J4vfJHLJEYxCZzA_VJUB46w2WGShfdYFoetsLG5PfKo,3428
3
+ xulbux/_consts_.py,sha256=AuYTTmqrP2lawyVGlPLUaP1syxOoPA-ejJGH7WlwFzk,6314
4
+ xulbux/xx_code.py,sha256=w9yO-GPMeaE-xDi-L3VtpPpWpu5jOwagfMsG93aXANE,6106
5
+ xulbux/xx_color.py,sha256=Thj7fFTc8x-VmYyULI3HQW0uCk9dIihwrGUwuXGn83s,49744
6
+ xulbux/xx_console.py,sha256=mruEcbehVceXuDhIMV_WoFec8MxXf2orvlNQWkdI-zE,34367
7
+ xulbux/xx_data.py,sha256=nEfVwK6-ILaL3K-bLezKpG1G7117CY5ZgC3BGwANrUE,30886
8
+ xulbux/xx_env_path.py,sha256=x56mKK4lSvU5yMCAs8k0RVIqXWUJcpcHYz5HoZ_RklM,4160
9
+ xulbux/xx_file.py,sha256=KerXOvKS93zIoAt36YTYuZboSmxVFVf2WcOrDcdwXfE,2627
10
+ xulbux/xx_format_codes.py,sha256=NihbRkPjDSWJCL2itZBlvhbO0bWx8Mm2P-LpSeaG3po,23732
11
+ xulbux/xx_json.py,sha256=V7vdfpvSe9wpktR_c8zG_Meix7x9IRmn66k5nB3HUyo,7457
12
+ xulbux/xx_path.py,sha256=lLAEVZrW0TAwCewlONFVQcQ_8tVn9LTJZVOZpeGvE5s,7673
13
+ xulbux/xx_regex.py,sha256=_BtMHRDNcD9zF4SL87dQuUVZcYGfZx9H5YNSDiEtzm8,8059
14
+ xulbux/xx_string.py,sha256=QaTo0TQ9m_2USNgQNaVw5ivQt-A1E-e5x8OpIB3xIlY,5561
15
+ xulbux/xx_system.py,sha256=Tsx4wgztUg46KloqcGeiFkarDoM3EgJLXw3XNxgHBmU,6460
16
+ xulbux-1.7.1.dist-info/licenses/LICENSE,sha256=6NflEcvzFEe8_JFVNCPVwZBwBhlLLd4vqQi8WiX_Xk4,1084
17
+ xulbux-1.7.1.dist-info/METADATA,sha256=rMdO8mHMOtT-oLsysIUup9myW_B93Z2UdG1Gvasu_rA,9209
18
+ xulbux-1.7.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ xulbux-1.7.1.dist-info/entry_points.txt,sha256=a3womfLIMZKnOFiyy-xnVb4g2qkZsHR5FbKKkljcGns,94
20
+ xulbux-1.7.1.dist-info/top_level.txt,sha256=FkK4EZajwfP36fnlrPaR98OrEvZpvdEOdW1T5zTj6og,7
21
+ xulbux-1.7.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.0.1)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,21 +0,0 @@
1
- xulbux/__init__.py,sha256=mpAtWO0eumk7FZt6QS1Wvp7KWBsZd8oseSxUPSpAVJk,815
2
- xulbux/_cli_.py,sha256=SaBlkIx73nfU6r2TbjQVWxOM-R0xTBqOAKtgi2FF-KA,3470
3
- xulbux/_consts_.py,sha256=b85O5sePS18z7CJgrVw0V7v88PIG9qnQ7G2bJL71odk,6287
4
- xulbux/xx_code.py,sha256=laA8osWgIW-QSv6P6Am_c6NocOPf8ZSm20EaVfgOC58,6100
5
- xulbux/xx_color.py,sha256=NdNh-J89PXPhVcdgKBXThbRTnq1UpBg3yn4aG0fmRAE,47602
6
- xulbux/xx_console.py,sha256=MJOE3giA6wZW0-VjJmBZaHqnUhOA6vRF41UdkAPIxgk,28019
7
- xulbux/xx_data.py,sha256=zp-DjMJ_VnC-BQQlqdzdgwhnSRzs0MV356AbIjeGgP4,30696
8
- xulbux/xx_env_path.py,sha256=A54TObZZwDvNZwv0iwHzEbNiCoEvz16OId-gMiUTHdo,4086
9
- xulbux/xx_file.py,sha256=Efd7-1FFsXYGd_cH95FwI8Mg6PaA7H11ArBpdBhyVhE,2597
10
- xulbux/xx_format_codes.py,sha256=QXb7ik_JyZJ6agtWykTerkb6NAPhOtOFh7nMpr-bpWo,22912
11
- xulbux/xx_json.py,sha256=-Wzlg8pUIsLlYJKrlxeoXoPprPn8lGJ2Uqc36WYyk6U,7390
12
- xulbux/xx_path.py,sha256=ZCnRJyIO5nigaKJjxNjfEz_4Z_mhBS0ELyJaLU7Lid0,7561
13
- xulbux/xx_regex.py,sha256=oJ7V2ccQNYbnavvCEIyYGVM8001_pjMV1BRu3NGmMJw,7884
14
- xulbux/xx_string.py,sha256=QaTo0TQ9m_2USNgQNaVw5ivQt-A1E-e5x8OpIB3xIlY,5561
15
- xulbux/xx_system.py,sha256=vHuNzxG6fakd4pJ0esJNfGglUtRbqpGJhPODVJqwcV0,6411
16
- xulbux-1.6.9.dist-info/licenses/LICENSE,sha256=6NflEcvzFEe8_JFVNCPVwZBwBhlLLd4vqQi8WiX_Xk4,1084
17
- xulbux-1.6.9.dist-info/METADATA,sha256=1wGLeAPcJPPDMfhB_JsLCM7mphazUEqyVE4HIfoUbHI,9222
18
- xulbux-1.6.9.dist-info/WHEEL,sha256=ooBFpIzZCPdw3uqIQsOo4qqbA4ZRPxHnOH7peeONza0,91
19
- xulbux-1.6.9.dist-info/entry_points.txt,sha256=a3womfLIMZKnOFiyy-xnVb4g2qkZsHR5FbKKkljcGns,94
20
- xulbux-1.6.9.dist-info/top_level.txt,sha256=FkK4EZajwfP36fnlrPaR98OrEvZpvdEOdW1T5zTj6og,7
21
- xulbux-1.6.9.dist-info/RECORD,,