xulbux 1.6.2__py3-none-any.whl → 1.6.3__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/__init__.py CHANGED
@@ -19,7 +19,7 @@
19
19
  • REGEX PATTERN TEMPLATES xx.Regex
20
20
  """
21
21
 
22
- __version__ = "1.6.2"
22
+ __version__ = "1.6.3"
23
23
  __author__ = "XulbuX"
24
24
  __email__ = "xulbux.real@gmail.com"
25
25
  __license__ = "MIT"
xulbux/_consts_.py CHANGED
@@ -58,12 +58,12 @@ class ANSI:
58
58
 
59
59
  global CHAR, START, SEP, END
60
60
 
61
- char_esc = r"\x1b"
61
+ escaped_char = "\\x1b"
62
62
  CHAR = char = "\x1b"
63
63
  START = start = "["
64
64
  SEP = sep = ";"
65
65
  END = end = "m"
66
- modifier = {"lighten": "+l", "darken": "-d"}
66
+ default_color_modifiers = {"lighten": "+l", "darken": "-d"}
67
67
 
68
68
  def seq(parts: int = 1) -> str:
69
69
  """Generate an ANSI sequence with `parts` amount of placeholders."""
xulbux/xx_format_codes.py CHANGED
@@ -1,38 +1,78 @@
1
1
  """
2
- Functions to be able to use special (easy) formatting codes directly inside some message (string).\n
3
- These codes, when used within following functions, will change the look of log within the console:
2
+ Methods to transform formatting codes to ANSI and use them for pretty console output:
4
3
  - `FormatCodes.print()` (print a special format-codes containing string)
5
4
  - `FormatCodes.input()` (input with a special format-codes containing prompt)
6
5
  - `FormatCodes.to_ansi()` (transform all special format-codes into ANSI codes in a string)\n
7
- --------------------------------------------------------------------------------------------------------------------
8
- How to change the text format and color?\n
9
- Example string with formatting codes:
10
- ```string
11
- [bold]This is bold text, [#F08]which is pink now [black|BG:#FF0088] and now it changed`
12
- to black with a pink background. [_]And this is the boring text, where everything is reset.
6
+ ------------------------------------------------------------------------------------------------------------------------------------
7
+ ### The Easy Formatting
8
+
9
+ First, let's take a look at a small example of what a highly styled print string with formatting could look like using this module:
10
+ ```regex
11
+ This here is just unformatted text. [b|u|br:blue](Next we have text that is bright blue + bold + underlined.)\\n
12
+ [#000|bg:#F67](Then there's also black text with a red background.) And finally the ([i](boring)) plain text again.
13
13
  ```
14
- ⇾ Instead of writing the formats all separate `[x][y][z]` you can join them like this `[x|y|z]`\n
15
- --------------------------------------------------------------------------------------------------------------------
16
- You can also automatically reset a certain format, behind text like shown in the following example:
17
- ```string
18
- This is normal text [b](which is bold now) but now it was automatically reset to normal.
14
+
15
+ How all of this exactly works is explained in the sections below. 🠫
16
+
17
+ ------------------------------------------------------------------------------------------------------------------------------------
18
+ #### Formatting Codes and Keys
19
+
20
+ In this module, you can apply styles and colors using simple formatting codes.
21
+ These formatting codes consist of one or multiple different formatting keys in between square brackets.
22
+
23
+ If a formatting code is placed in a print-string, the formatting of that code will be applied to everything behind it until its
24
+ formatting is reset. If applying multiple styles and colors in the same place, instead of writing the formatting keys all into
25
+ separate brackets (e.g. `[x][y][z]`), they can also be put in a single pair of brackets, separated by pipes (e.g. `[x|y|z]`).
26
+
27
+ A list of all possible formatting keys can be found under all possible formatting keys.
28
+
29
+ ------------------------------------------------------------------------------------------------------------------------------------
30
+ #### Auto Resetting Formatting Codes
31
+
32
+ Certain formatting can automatically be reset, behind a certain amount of text, just like shown in the following example:
33
+ ```regex
34
+ This is plain text, [br:blue](which is bright blue now.) Now it was automatically reset to plain again.
19
35
  ```
20
- This will only reset formats, that have a reset listed below. Colors and BG-colors won't be reset.\n
21
- This is what will happen, if you use it with a color-format:
22
- ```string
23
- [cyan]This is cyan text [b](which is bold now.) Now it's not bold any more but still cyan.
36
+
37
+ This will only reset formatting codes, that have a specific reset listed below.
38
+ That means if you use it where another formatting is already applied, that formatting is still there after the automatic reset:
39
+ ```regex
40
+ [cyan]This is cyan text, [dim](which is dimmed now.) Now it's not dimmed any more but still cyan.
24
41
  ```
25
- If you want to ignore the `()` brackets you can put a `\\` or `/` between:
26
- ```string
27
- [cyan]This is cyan text [b]/(which is bold now.) And now it is still bold and cyan.
42
+
43
+ If you want to ignore the auto-reset functionality of `()` brackets, you can put a `\\` or `/` between them and
44
+ the formatting code:
45
+ ```regex
46
+ [cyan]This is cyan text, [u]/(which is underlined now.) And now it is still underlined and cyan.
28
47
  ```
29
- ⇾ To see these examples in action, you can put them into the `FormatCodes.print()` function.\n
30
- --------------------------------------------------------------------------------------------------------------------
31
- All possible formatting codes:
32
- - HEX colors: `[#F08]` or `[#FF0088]` (with or without leading #)
33
- - RGB colors: `[rgb(255, 0, 136)]`
34
- - background colors: `[BG:#F08]`
35
- - standard cmd colors:
48
+
49
+ ------------------------------------------------------------------------------------------------------------------------------------
50
+ #### All possible Formatting Keys
51
+
52
+ - RGB colors:
53
+ Change the text color directly with an RGB color inside the square brackets. (With or without `rgb()` brackets doesn't matter.)
54
+ Examples:
55
+ - `[rgb(115, 117, 255)]`
56
+ - `[(255, 0, 136)]`
57
+ - `[255, 0, 136]`
58
+ - HEX colors:
59
+ Change the text color directly with a HEX color inside the square brackets. (If `RGB` or `RRGGBB` formatting code is used,
60
+ and if there's a `#` or `0x` prefix, doesn't matter.)
61
+ Examples:
62
+ - `[#7788FF]`
63
+ - `[7788FF]`
64
+ - `[#78F]`
65
+ - `[78F]`
66
+ - background RGB / HEX colors:
67
+ Change the background color directly with an RGB or HEX color inside the square brackets, using the `background:` `BG:` prefix.
68
+ (Same RGB / HEX formatting code rules as for text color.)
69
+ Examples:
70
+ - `[background:rgb(115, 117, 255)]`
71
+ - `[BG:(255, 0, 136)]`
72
+ - `[background:#7788FF]`
73
+ - `[BG:#78F]`
74
+ - standard console colors:
75
+ Change the text color to one of the standard console colors by just writing the color name in the square brackets.
36
76
  - `[black]`
37
77
  - `[red]`
38
78
  - `[green]`
@@ -41,39 +81,64 @@ All possible formatting codes:
41
81
  - `[magenta]`
42
82
  - `[cyan]`
43
83
  - `[white]`
44
- - bright cmd colors: `[bright:black]` or `[br:black]`, `[bright:red]` or `[br:red]`, ...
45
- - background cmd colors: `[BG:black]`, `[BG:red]`, ...
46
- - bright background cmd colors: `[BG:bright:black]` or `[BG:br:black]`, `[BG:bright:red]` or `[BG:br:red]`, ...\n
47
- ⇾ The order of `BG:` and `bright:` or `br:` does not matter.
48
- - text formats:
49
- - `[bold]` or `[b]`
84
+ - bright console colors:
85
+ Use the prefix `bright:` `BR:` to use the bright variant of the standard console color.
86
+ Examples:
87
+ - `[bright:black]` `[BR:black]`
88
+ - `[bright:red]` `[BR:red]`
89
+ - ...
90
+ - Background console colors:
91
+ Use the prefix `background:` `BG:` to set the background to a standard console color. (Not all consoles support bright
92
+ standard colors.)
93
+ Examples:
94
+ - `[background:black]` `[BG:black]`
95
+ - `[background:red]` `[BG:red]`
96
+ - ...
97
+ - Bright background console colors:
98
+ Combine the prefixes `background:` / `BG:` and `bright:` / `BR:` to set the background to a bright console color.
99
+ (The order of the prefixes doesn't matter.)
100
+ Examples:
101
+ - `[background:bright:black]` `[BG:BR:black]`
102
+ - `[background:bright:red]` `[BG:BR:red]`
103
+ - ...
104
+ - Text styles:
105
+ Use the built-in text formatting to change the style of the text. There are long and short forms for each formatting code.
106
+ (Not all consoles support all text styles.)
107
+ - `[bold]` `[b]`
50
108
  - `[dim]`
51
- - `[italic]` or `[i]`
52
- - `[underline]` or `[u]`
53
- - `[inverse]`, `[invert]` or `[in]`
54
- - `[hidden]`, `[hide]` or `[h]`
55
- - `[strikethrough]` or `[s]`
56
- - `[double-underline]` or `[du]`
57
- - specific reset:
58
- - `[_bold]` or `[_b]`
109
+ - `[italic]` `[i]`
110
+ - `[underline]` `[u]`
111
+ - `[inverse]` `[invert]` `[in]`
112
+ - `[hidden]` `[hide]` `[h]`
113
+ - `[strikethrough]` `[s]`
114
+ - `[double-underline]` `[du]`
115
+ - Specific reset:
116
+ Use these reset codes to remove a specific style, color or background. Again, there are long and
117
+ short forms for each reset code.
118
+ - `[_bold]` `[_b]`
59
119
  - `[_dim]`
60
- - `[_italic]` or `[_i]`
61
- - `[_underline]` or `[_u]`
62
- - `[_inverse]`, `[_invert]` or `[_in]`
63
- - `[_hidden]`, `[_hide]` or `[_h]`
64
- - `[_strikethrough]` or `[_s]`
65
- - `[_double-underline]` or `[_du]`
66
- - `[_color]` or `[_c]`
67
- - `[_background]` or `[_bg]`
68
- - total reset:
120
+ - `[_italic]` `[_i]`
121
+ - `[_underline]` `[_u]`
122
+ - `[_inverse]` `[_invert]` `[_in]`
123
+ - `[_hidden]` `[_hide]` `[_h]`
124
+ - `[_strikethrough]` `[_s]`
125
+ - `[_double-underline]` `[_du]`
126
+ - `[_color]` `[_c]`
127
+ - `[_background]` `[_bg]`
128
+ - Total reset:
129
+ This will reset all previously applied formatting codes.
69
130
  - `[_]`
70
- --------------------------------------------------------------------------------------------------------------------
71
- Additional formats when a `default_color` is set:
72
- - `[*]` will reset everything, just like `[_]`, but the text-color will remain in `default_color`
73
- - `[*color]` will reset the text-color, just like `[_color]`, but then also make it `default_color`
74
- - `[default]` will just color the text in `default_color`,
75
- - `[BG:default]` will color the background in `default_color`\n
76
- Unlike the standard cmd colors, the default color can be changed by using the following modifiers:
131
+
132
+ ------------------------------------------------------------------------------------------------------------------------------------
133
+ #### Additional Formatting Codes when a `default_color` is set
134
+
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`
137
+ 3. `[default]` will just color the text in `default_color`
138
+ 4. `[background:default]` `[BG:default]` will color the background in `default_color`
139
+
140
+ Unlike the standard console colors, the default color can be changed by using the following modifiers:
141
+
77
142
  - `[l]` will lighten the `default_color` text by `brightness_steps`%
78
143
  - `[ll]` will lighten the `default_color` text by `2 × brightness_steps`%
79
144
  - `[lll]` will lighten the `default_color` text by `3 × brightness_steps`%
@@ -81,7 +146,7 @@ Unlike the standard cmd colors, the default color can be changed by using the fo
81
146
  - `[d]` will darken the `default_color` text by `brightness_steps`%
82
147
  - `[dd]` will darken the `default_color` text by `2 × brightness_steps`%
83
148
  - `[ddd]` will darken the `default_color` text by `3 × brightness_steps`%
84
- - ... etc.\n
149
+ - ... etc.
85
150
  Per default, you can also use `+` and `-` to get lighter and darker `default_color` versions.
86
151
  """
87
152
 
@@ -90,38 +155,43 @@ from .xx_string import String
90
155
  from .xx_regex import Regex
91
156
  from .xx_color import *
92
157
 
93
- from functools import lru_cache
94
158
  import ctypes as _ctypes
95
159
  import regex as _rx
96
160
  import sys as _sys
97
161
  import re as _re
98
162
 
99
- PREFIX = {
163
+ _CONSOLE_ANSI_CONFIGURED = False
164
+
165
+ _PREFIX = {
100
166
  "BG": {"background", "bg"},
101
167
  "BR": {"bright", "br"},
102
168
  }
103
- PREFIXES = {val for values in PREFIX.values() for val in values}
104
- PREFIX_RX = {
105
- "BG": rf"(?:{'|'.join(PREFIX['BG'])})\s*:",
106
- "BR": rf"(?:{'|'.join(PREFIX['BR'])})\s*:",
169
+ _PREFIX_RX = {
170
+ "BG": rf"(?:{'|'.join(_PREFIX['BG'])})\s*:",
171
+ "BR": rf"(?:{'|'.join(_PREFIX['BR'])})\s*:",
107
172
  }
108
- COMPILED = { # PRECOMPILE REGULAR EXPRESSIONS
173
+ _COMPILED = { # PRECOMPILE REGULAR EXPRESSIONS
109
174
  "*": _re.compile(r"\[\s*([^]_]*?)\s*\*\s*([^]_]*?)\]"),
110
175
  "*color": _re.compile(r"\[\s*([^]_]*?)\s*\*color\s*([^]_]*?)\]"),
111
- "format": _rx.compile(
112
- Regex.brackets("[", "]", is_group=True) + r"(?:\s*([/\\]?)\s*" + Regex.brackets("(", ")", is_group=True) + r")?"
176
+ "formatting": _rx.compile(
177
+ Regex.brackets("[", "]", is_group=True)
178
+ + r"(?:\s*([/\\]?)\s*"
179
+ + Regex.brackets("(", ")", is_group=True, ignore_in_strings=False)
180
+ + r")?"
113
181
  ),
114
- "bg?_default": _re.compile(r"(?i)((?:" + PREFIX_RX["BG"] + r")?)\s*default"),
115
- "bg_default": _re.compile(r"(?i)" + PREFIX_RX["BG"] + r"\s*default"),
182
+ "bg?_default": _re.compile(r"(?i)((?:" + _PREFIX_RX["BG"] + r")?)\s*default"),
183
+ "bg_default": _re.compile(r"(?i)" + _PREFIX_RX["BG"] + r"\s*default"),
116
184
  "modifier": _re.compile(
117
185
  r"(?i)((?:BG\s*:)?)\s*("
118
- + "|".join([f"{_re.escape(m)}+" for m in ANSI.modifier["lighten"] + ANSI.modifier["darken"]])
186
+ + "|".join(
187
+ [f"{_re.escape(m)}+" for m in ANSI.default_color_modifiers["lighten"] + ANSI.default_color_modifiers["darken"]]
188
+ )
119
189
  + r")$"
120
190
  ),
121
191
  "rgb": _re.compile(
122
- r"(?i)^\s*(" + PREFIX_RX["BG"] + r")?\s*(?:rgb|rgba)?\s*\(?\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)?\s*$"
192
+ r"(?i)^\s*(" + _PREFIX_RX["BG"] + r")?\s*(?:rgb|rgba)?\s*\(?\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)?\s*$"
123
193
  ),
124
- "hex": _re.compile(r"(?i)^\s*(" + PREFIX_RX["BG"] + r")?\s*(?:#|0x)?([0-9A-F]{6}|[0-9A-F]{3})\s*$"),
194
+ "hex": _re.compile(r"(?i)^\s*(" + _PREFIX_RX["BG"] + r")?\s*(?:#|0x)?([0-9A-F]{6}|[0-9A-F]{3})\s*$"),
125
195
  }
126
196
 
127
197
 
@@ -130,14 +200,14 @@ class FormatCodes:
130
200
  @staticmethod
131
201
  def print(
132
202
  *values: object,
133
- default_color: hexa | rgba = None,
203
+ default_color: rgba | hexa = None,
134
204
  brightness_steps: int = 20,
135
205
  sep: str = " ",
136
206
  end: str = "\n",
137
207
  flush: bool = True,
138
208
  ) -> None:
139
- """Print a string that can be formatted using special formatting codes.\n
140
- --------------------------------------------------------------------------
209
+ """A print function, whose print values can be formatted using formatting codes.\n
210
+ -----------------------------------------------------------------------------------
141
211
  For exact information about how to use special formatting codes, see the
142
212
  `xx_format_codes` module documentation."""
143
213
  FormatCodes.__config_console()
@@ -148,29 +218,32 @@ class FormatCodes:
148
218
  @staticmethod
149
219
  def input(
150
220
  prompt: object = "",
151
- default_color: hexa | rgba = None,
221
+ default_color: rgba | hexa = None,
152
222
  brightness_steps: int = 20,
153
223
  reset_ansi: bool = False,
154
224
  ) -> str:
155
- """An input, which's prompt can be formatted using special formatting codes.\n
156
- -------------------------------------------------------------------------------
157
- If `reset_ansi` is true, all ANSI formatting will be reset, after the user has
158
- confirmed the input and the program continues.\n
159
- -------------------------------------------------------------------------------
225
+ """An input, whose prompt can be formatted using formatting codes.\n
226
+ -------------------------------------------------------------------------
227
+ If `reset_ansi` is true, all ANSI formatting will be reset, after the
228
+ user confirms the input and the program continues to run.\n
229
+ -------------------------------------------------------------------------
160
230
  For exact information about how to use special formatting codes, see the
161
231
  `xx_format_codes` module documentation."""
162
232
  FormatCodes.__config_console()
163
- user_input = input(FormatCodes.to_ansi(prompt, default_color, brightness_steps))
233
+ user_input = input(FormatCodes.to_ansi(str(prompt), default_color, brightness_steps))
164
234
  if reset_ansi:
165
235
  _sys.stdout.write("\x1b[0m")
166
236
  return user_input
167
237
 
168
238
  @staticmethod
169
239
  def to_ansi(
170
- string: str, default_color: hexa | rgba = None, brightness_steps: int = 20, _default_start: bool = True
240
+ string: str,
241
+ default_color: rgba | hexa = None,
242
+ brightness_steps: int = 20,
243
+ _default_start: bool = True,
171
244
  ) -> str:
172
- """Convert the special formatting codes inside a string to printable ANSI codes.\n
173
- -----------------------------------------------------------------------------------
245
+ """Convert the formatting codes inside a string to ANSI formatting.\n
246
+ -------------------------------------------------------------------------
174
247
  For exact information about how to use special formatting codes, see the
175
248
  `xx_format_codes` module documentation."""
176
249
  if Color.is_valid_rgba(default_color, False):
@@ -180,8 +253,8 @@ class FormatCodes:
180
253
  else:
181
254
  use_default = False
182
255
  if use_default:
183
- string = COMPILED["*"].sub(r"[\1_|default\2]", string) # REPLACE `[…|*|…]` WITH `[…|_|default|…]`
184
- string = COMPILED["*color"].sub(r"[\1default\2]", string) # REPLACE `[…|*color|…]` WITH `[…|default|…]`
256
+ string = _COMPILED["*"].sub(r"[\1_|default\2]", string) # REPLACE `[…|*|…]` WITH `[…|_|default|…]`
257
+ string = _COMPILED["*color"].sub(r"[\1default\2]", string) # REPLACE `[…|*color|…]` WITH `[…|default|…]`
185
258
 
186
259
  def is_valid_color(color: str) -> bool:
187
260
  return color in ANSI.color_map or Color.is_valid_rgba(color) or Color.is_valid_hexa(color)
@@ -206,8 +279,8 @@ class FormatCodes:
206
279
  for k in format_keys:
207
280
  k_lower = k.lower()
208
281
  k_set = set(k_lower.split(":"))
209
- if PREFIX["BG"] & k_set and len(k_set) <= 3:
210
- if k_set & PREFIX["BR"]:
282
+ if _PREFIX["BG"] & k_set and len(k_set) <= 3:
283
+ if k_set & _PREFIX["BR"]:
211
284
  for i in range(len(k)):
212
285
  if is_valid_color(k[i:]):
213
286
  reset_keys.extend(["_bg", "_color"])
@@ -219,7 +292,7 @@ class FormatCodes:
219
292
  break
220
293
  elif is_valid_color(k) or any(
221
294
  k_lower.startswith(pref_colon := f"{prefix}:") and is_valid_color(k[len(pref_colon) :])
222
- for prefix in PREFIX["BR"]
295
+ for prefix in _PREFIX["BR"]
223
296
  ):
224
297
  reset_keys.append("_color")
225
298
  else:
@@ -247,40 +320,42 @@ class FormatCodes:
247
320
  + ("" if escaped else "".join(ansi_resets))
248
321
  )
249
322
 
250
- string = "\n".join(COMPILED["format"].sub(replace_keys, line) for line in string.split("\n"))
323
+ string = "\n".join(_COMPILED["formatting"].sub(replace_keys, line) for line in string.split("\n"))
251
324
  return (FormatCodes.__get_default_ansi(default_color) if _default_start else "") + string if use_default else string
252
325
 
253
326
  @staticmethod
254
- def escape_ansi(ansi_string: str, escaped_char: str = ANSI.char_esc) -> str:
255
- """Makes the string printable with the ANSI formats visible."""
256
- return ansi_string.replace(ANSI.char, escaped_char)
327
+ def escape_ansi(ansi_string: str) -> str:
328
+ """Escapes all ANSI codes in a string, so they are visible when output to the console."""
329
+ return ansi_string.replace(ANSI.char, ANSI.escaped_char)
257
330
 
258
331
  @staticmethod
259
- @lru_cache(maxsize=64)
260
332
  def __config_console() -> None:
261
333
  """Configure the console to be able to interpret ANSI formatting."""
262
- _sys.stdout.flush()
263
- kernel32 = _ctypes.windll.kernel32
264
- h = kernel32.GetStdHandle(-11)
265
- mode = _ctypes.c_ulong()
266
- kernel32.GetConsoleMode(h, _ctypes.byref(mode))
267
- kernel32.SetConsoleMode(h, mode.value | 0x0004)
334
+ if not _CONSOLE_ANSI_CONFIGURED:
335
+ _sys.stdout.flush()
336
+ kernel32 = _ctypes.windll.kernel32
337
+ h = kernel32.GetStdHandle(-11)
338
+ mode = _ctypes.c_ulong()
339
+ kernel32.GetConsoleMode(h, _ctypes.byref(mode))
340
+ kernel32.SetConsoleMode(h, mode.value | 0x0004)
341
+ global _CONSOLE_ANSI_CONFIGURED
342
+ _CONSOLE_ANSI_CONFIGURED = True
268
343
 
269
344
  @staticmethod
270
345
  def __get_default_ansi(
271
346
  default_color: tuple,
272
347
  format_key: str = None,
273
348
  brightness_steps: int = None,
274
- _modifiers: tuple[str, str] = (ANSI.modifier["lighten"], ANSI.modifier["darken"]),
349
+ _modifiers: tuple[str, str] = (ANSI.default_color_modifiers["lighten"], ANSI.default_color_modifiers["darken"]),
275
350
  ) -> str | None:
276
- """Get the `default_color` and lighter/darker versions of it in ANSI format."""
277
- if not brightness_steps or (format_key and COMPILED["bg?_default"].search(format_key)):
278
- return (ANSI.seq_bg_color if format_key and COMPILED["bg_default"].search(format_key) else ANSI.seq_color).format(
351
+ """Get the `default_color` and lighter/darker versions of it as ANSI code."""
352
+ if not brightness_steps or (format_key and _COMPILED["bg?_default"].search(format_key)):
353
+ return (ANSI.seq_bg_color if format_key and _COMPILED["bg_default"].search(format_key) else ANSI.seq_color).format(
279
354
  *default_color[:3]
280
355
  )
281
356
  if not (format_key in _modifiers[0] or format_key in _modifiers[1]):
282
357
  return None
283
- match = COMPILED["modifier"].match(format_key)
358
+ match = _COMPILED["modifier"].match(format_key)
284
359
  if not match:
285
360
  return None
286
361
  is_bg, modifiers = match.groups()
@@ -320,8 +395,8 @@ class FormatCodes:
320
395
  None,
321
396
  )
322
397
  )
323
- rgb_match = _re.match(COMPILED["rgb"], format_key)
324
- hex_match = _re.match(COMPILED["hex"], format_key)
398
+ rgb_match = _re.match(_COMPILED["rgb"], format_key)
399
+ hex_match = _re.match(_COMPILED["hex"], format_key)
325
400
  try:
326
401
  if rgb_match:
327
402
  is_bg = rgb_match.group(1)
@@ -341,15 +416,14 @@ class FormatCodes:
341
416
  return _format_key
342
417
 
343
418
  @staticmethod
344
- @lru_cache(maxsize=64)
345
419
  def __normalize_key(format_key: str) -> str:
346
420
  """Normalizes the given format key."""
347
421
  k_parts = format_key.replace(" ", "").lower().split(":")
348
422
  prefix_str = "".join(
349
423
  f"{prefix_key.lower()}:"
350
- for prefix_key, prefix_values in PREFIX.items()
424
+ for prefix_key, prefix_values in _PREFIX.items()
351
425
  if any(k_part in prefix_values for k_part in k_parts)
352
426
  )
353
427
  return prefix_str + ":".join(
354
- part for part in k_parts if part not in {val for values in PREFIX.values() for val in values}
428
+ part for part in k_parts if part not in {val for values in _PREFIX.values() for val in values}
355
429
  )
xulbux/xx_regex.py CHANGED
@@ -9,6 +9,7 @@ Really long regex code presets:
9
9
  `hsla_str` match a HSLA color
10
10
  """
11
11
 
12
+ import regex as _rx
12
13
  import re as _re
13
14
 
14
15
 
@@ -17,25 +18,33 @@ class Regex:
17
18
  @staticmethod
18
19
  def quotes() -> str:
19
20
  """Matches everything inside quotes. (strings)\n
20
- ------------------------------------------------------------------------------------
21
+ --------------------------------------------------------------------------------
21
22
  Will create two named groups:
22
23
  - `quote` the quote type (single or double)
23
24
  - `string` everything inside the found quote pair\n
24
- ------------------------------------------------------------------------------------
25
+ --------------------------------------------------------------------------------
25
26
  Attention: Requires non standard library `regex` not standard library `re`!"""
26
27
  return r'(?P<quote>[\'"])(?P<string>(?:\\.|(?!\g<quote>).)*?)\g<quote>'
27
28
 
28
29
  @staticmethod
29
- def brackets(bracket1: str = "(", bracket2: str = ")", is_group: bool = False) -> str:
30
+ def brackets(bracket1: str = "(", bracket2: str = ")", is_group: bool = False, ignore_in_strings: bool = True) -> str:
30
31
  """Matches everything inside brackets, including other nested brackets.\n
31
- ------------------------------------------------------------------------------------
32
+ --------------------------------------------------------------------------------
33
+ If `is_group` is true, you will be able to reference the matched content as a
34
+ group (e.g. `match.group(…)` or `r'\\…'`).
35
+ If `ignore_in_strings` is true and a bracket is inside a string (e.g. `'...'`
36
+ or `"..."`), it will not be counted as the matching closing bracket.\n
37
+ --------------------------------------------------------------------------------
32
38
  Attention: Requires non standard library `regex` not standard library `re`!"""
33
39
  g, b1, b2 = (
34
40
  "" if is_group else "?:",
35
- _re.escape(bracket1) if len(bracket1) == 1 else bracket1,
36
- _re.escape(bracket2) if len(bracket2) == 1 else bracket2,
41
+ _rx.escape(bracket1) if len(bracket1) == 1 else bracket1,
42
+ _rx.escape(bracket2) if len(bracket2) == 1 else bracket2,
37
43
  )
38
- return rf'{b1}\s*({g}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|{b1}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|(?R))*{b2})*)\s*{b2}'
44
+ if ignore_in_strings:
45
+ return rf'{b1}\s*({g}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|{b1}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|(?R))*{b2})*)\s*{b2}'
46
+ else:
47
+ return rf"{b1}\s*({g}(?:[^{b1}{b2}]|{b1}(?:[^{b1}{b2}]|(?R))*{b2})*)\s*{b2}"
39
48
 
40
49
  @staticmethod
41
50
  def outside_strings(pattern: str = r".*") -> str:
@@ -48,22 +57,27 @@ class Regex:
48
57
  ignore_pattern: str = "",
49
58
  is_group: bool = False,
50
59
  ) -> str:
51
- """Matches everything except `disallowed_pattern`, unless the `disallowed_pattern` is found inside a string (`'...'` or `"..."`).\n
52
- ------------------------------------------------------------------------------------------------------------------------------------
53
- The `ignore_pattern` is just always ignored. For example if `disallowed_pattern` is `>` and `ignore_pattern` is `->`, the `->`
54
- -arrows will be allowed, even though they have `>` in them. If `is_group` is `True`, you will be able to reference the matched
55
- content as a group (e.g. `match.group(int)` or `r'\\int'`)."""
60
+ """Matches everything except `disallowed_pattern`, unless the `disallowed_pattern`
61
+ is found inside a string (`'...'` or `"..."`).\n
62
+ ------------------------------------------------------------------------------------
63
+ The `ignore_pattern` is just always ignored. For example if `disallowed_pattern` is
64
+ `>` and `ignore_pattern` is `->`, the `->`-arrows will be allowed, even though they
65
+ have `>` in them.
66
+ If `is_group` is true, you will be able to reference the matched content as a group
67
+ (e.g. `match.group(…)` or `r'\\…'`)."""
56
68
  return rf'({"" if is_group else "?:"}(?:(?!{ignore_pattern}).)*(?:(?!{Regex.outside_strings(disallowed_pattern)}).)*)'
57
69
 
58
70
  @staticmethod
59
71
  def func_call(func_name: str = None) -> str:
60
- """Match a function call
61
- - `1` function name
62
- - `2` the function's arguments\n
72
+ """Match a function call, and get back two groups:
73
+ 1. function name
74
+ 2. the function's arguments\n
63
75
  If no `func_name` is given, it will match any function call.\n
64
- ------------------------------------------------------------------------------------
76
+ --------------------------------------------------------------------------------
65
77
  Attention: Requires non standard library `regex` not standard library `re`!"""
66
- return r"(?<=\b)(" + (func_name if func_name else r"[\w_]+") + r")\s*" + Regex.brackets("(", ")", is_group=True)
78
+ return (
79
+ r"(?<=\b)(" + (r"[\w_]+" if func_name is None else func_name) + r")\s*" + Regex.brackets("(", ")", is_group=True)
80
+ )
67
81
 
68
82
  @staticmethod
69
83
  def rgba_str(fix_sep: str = ",", allow_alpha: bool = True) -> str:
@@ -76,11 +90,10 @@ class Regex:
76
90
  - `(r, g, b, a)` (if `allow_alpha=True`)
77
91
  - `r, g, b`
78
92
  - `r, g, b, a` (if `allow_alpha=True`)\n
79
- ----------------------------------------------------------------------------
80
- ### Valid ranges:
81
- - `r` 0-255 (amount: red)
82
- - `g` 0-255 (amount: green)
83
- - `b` 0-255 (amount: blue)
93
+ #### Valid ranges:
94
+ - `r` 0-255 (int: red)
95
+ - `g` 0-255 (int: green)
96
+ - `b` 0-255 (int: blue)
84
97
  - `a` 0-1 (float: opacity)\n
85
98
  ----------------------------------------------------------------------------
86
99
  If the `fix_sep` is set to nothing, any char that is not a letter or number
@@ -112,11 +125,10 @@ class Regex:
112
125
  - `(h, s, l, a)` (if `allow_alpha=True`)
113
126
  - `h, s, l`
114
127
  - `h, s, l, a` (if `allow_alpha=True`)\n
115
- ----------------------------------------------------------------------------
116
- ### Valid ranges:
117
- - `h` 0-360 (degrees: hue)
118
- - `s` 0-100 (percentage: saturation)
119
- - `l` 0-100 (percentage: lightness)
128
+ #### Valid ranges:
129
+ - `h` 0-360 (int: hue)
130
+ - `s` 0-100 (int: saturation)
131
+ - `l` 0-100 (int: lightness)
120
132
  - `a` 0-1 (float: opacity)\n
121
133
  ----------------------------------------------------------------------------
122
134
  If the `fix_sep` is set to nothing, any char that is not a letter or number
@@ -146,9 +158,8 @@ class Regex:
146
158
  - `RGBA` (if `allow_alpha=True`)
147
159
  - `RRGGBB`
148
160
  - `RRGGBBAA` (if `allow_alpha=True`)\n
149
- ----------------------------------------------------------------------
150
- ### Valid ranges:
151
- each channel from 0-9 and A-F (case insensitive)"""
161
+ #### Valid ranges:
162
+ every channel from 0-9 and A-F (case insensitive)"""
152
163
  return (
153
164
  r"(?i)^(?:#|0x)?[0-9A-F]{8}|[0-9A-F]{6}|[0-9A-F]{4}|[0-9A-F]{3}$"
154
165
  if allow_alpha
xulbux/xx_system.py CHANGED
@@ -41,7 +41,7 @@ class System:
41
41
  if not force:
42
42
  output = _subprocess.check_output("tasklist", shell=True).decode()
43
43
  processes = [line.split()[0] for line in output.splitlines()[3:] if line.strip()]
44
- if len(processes) > 2: # EXCLUDING THE PYTHON PROCESS AND CMD
44
+ if len(processes) > 2: # EXCLUDING THE PYTHON PROCESS AND CONSOLE
45
45
  raise RuntimeError("Processes are still running. Use the parameter `force=True` to restart anyway.")
46
46
  if prompt:
47
47
  _os.system(f'shutdown /r /t {wait} /c "{prompt}"')
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: xulbux
3
- Version: 1.6.2
3
+ Version: 1.6.3
4
4
  Summary: A library which includes a lot of really helpful functions.
5
5
  Author-email: XulbuX <xulbux.real@gmail.com>
6
6
  License: MIT License
@@ -31,7 +31,7 @@ Project-URL: Documentation, https://github.com/XulbuX-dev/PythonLibraryXulbuX/wi
31
31
  Project-URL: Homepage, https://github.com/XulbuX-dev/PythonLibraryXulbuX
32
32
  Project-URL: License, https://github.com/XulbuX-dev/PythonLibraryXulbuX/blob/main/LICENSE
33
33
  Project-URL: Source Code, https://github.com/XulbuX-dev/PythonLibraryXulbuX/tree/main/src
34
- Keywords: xulbux,python,library,utility,helper,functions,tools,classes,types,methods,cmd,code,color,data,structures,env,environment,file,format,json,path,regex,string,system,operations,presets
34
+ Keywords: xulbux,python,library,utility,helper,functions,tools,classes,types,methods,cmd,console,code,color,data,structures,env,environment,file,format,json,path,regex,string,system,operations,presets
35
35
  Classifier: Intended Audience :: Developers
36
36
  Classifier: Programming Language :: Python :: 3
37
37
  Classifier: Programming Language :: Python :: 3.10
@@ -89,19 +89,19 @@ from xulbux import rgba, hsla, hexa
89
89
  # Modules
90
90
 
91
91
  | | |
92
- | :------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------- |
93
- | <h3>[`xx_code`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_code)</h3> | advanced code-string operations (*changing the indent, finding function calls, ...*) |
94
- | <h3>[`xx_color`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_color)</h3> | everything around colors (*converting, blending, searching colors in strings, ...*) |
95
- | <h3>[`xx_console`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_console)</h3> | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
96
- | <h3>[`xx_data`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_data)</h3> | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
97
- | <h3>[`xx_env_path`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_env_path)</h3> | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
98
- | <h3>[`xx_file`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_file)</h3> | advanced working with files (*create files, rename file-extensions, ...*) |
99
- | <h3>`xx_format_codes`</h3> | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
100
- | <h3>`xx_json`</h3> | advanced working with json files (*read, create, update, ...*) |
101
- | <h3>`xx_path`</h3> | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
102
- | <h3>`xx_regex`</h3> | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
103
- | <h3>[`xx_string`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_string)</h3> | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
104
- | <h3>`xx_system`</h3> | advanced system actions (*restart with message, check installed Python libs, ...*) |
92
+ | :--------------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------- |
93
+ | <h3>[`xx_code`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_code)</h3> | advanced code-string operations (*changing the indent, finding function calls, ...*) |
94
+ | <h3>[`xx_color`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_color)</h3> | everything around colors (*converting, blending, searching colors in strings, ...*) |
95
+ | <h3>[`xx_console`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_console)</h3> | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
96
+ | <h3>[`xx_data`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_data)</h3> | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
97
+ | <h3>[`xx_env_path`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_env_path)</h3> | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
98
+ | <h3>[`xx_file`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_file)</h3> | advanced working with files (*create files, rename file-extensions, ...*) |
99
+ | <h3>[`xx_format_codes`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_format_codes)</h3> | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
100
+ | <h3>`xx_json`</h3> | advanced working with json files (*read, create, update, ...*) |
101
+ | <h3>`xx_path`</h3> | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
102
+ | <h3>`xx_regex`</h3> | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
103
+ | <h3>[`xx_string`](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki/xx_string)</h3> | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
104
+ | <h3>`xx_system`</h3> | advanced system actions (*restart with message, check installed Python libs, ...*) |
105
105
 
106
106
 
107
107
  <br>
@@ -1,21 +1,21 @@
1
- xulbux/__init__.py,sha256=fxqdXSxUa_iDtV2MWdq4aBXV3B0pQWgz2xHpLnm84zw,1658
1
+ xulbux/__init__.py,sha256=h83nzup1ahYhyQLejyU2uA3Ddb-gDTkGeQh6vV1naL0,1658
2
2
  xulbux/_cli_.py,sha256=U25ZrtpQgpKXtvOSTBBbh7-AJ_WTeZ95A66DQARAqzo,3558
3
- xulbux/_consts_.py,sha256=qAkg6ZwTKhQFcpHpfXjF4QEao8hpDEECRGqrv8oxkCo,4572
3
+ xulbux/_consts_.py,sha256=0JWj691rOojP8KKE_AJpF8O5WwMRJH4fAvzkwLXd1VM,4591
4
4
  xulbux/xx_code.py,sha256=yBP5WxCxNxjBiS6nVAmUBJpD0hX6fgnh5RWq-NmrnaY,5222
5
5
  xulbux/xx_color.py,sha256=cDlgrekH88ZEBj8leIIlJbYzsf1RdS8RW3oGvuUfvC0,45129
6
6
  xulbux/xx_console.py,sha256=rd31686X9eXB8__lcLaV7unWzIdXGM2yMOt9zNCsGbs,15079
7
7
  xulbux/xx_data.py,sha256=OEKLbI1XeNTrittdz3s3mvQk8YrBoSovj9O1H-b7ArY,25844
8
8
  xulbux/xx_env_path.py,sha256=iv3Jw0TsNDbbL_NySnazvIP9Iv9swymhiJIr2B3EG8k,4388
9
9
  xulbux/xx_file.py,sha256=-58YnqKvrs5idIF91UzEki7o7qnskFvnQYkBaRrp7Vw,3122
10
- xulbux/xx_format_codes.py,sha256=hTQBowcFX0gyAtjsYvgrEZK2EQ83b0W-IyqIUTkJAig,16986
10
+ xulbux/xx_format_codes.py,sha256=Qibr5CbV-Ow7l-TTPElfnU_yZELFaD86CFkdKU-7m4Y,19832
11
11
  xulbux/xx_json.py,sha256=q60lOj8Xg8c4L9cBu6SBZdJzFC7QbjDfFwcKKzBKj5w,5173
12
12
  xulbux/xx_path.py,sha256=_xkH9cowPdi3nHw2q_TvN_i_5oG6GJut-QwPBLxnrAQ,4519
13
- xulbux/xx_regex.py,sha256=zyxkS1bLlrSq26ErhO4UtrimIhW71_a7kox6ArCoK58,7670
13
+ xulbux/xx_regex.py,sha256=S1-MIk2qG4vHdxuaHGhMe5PHfY1SF9kncg8iQ8HJgS4,8002
14
14
  xulbux/xx_string.py,sha256=Wa3qHxnk7AIpAVAn1vI_GBtkfYFwy4F_Xtj83ojEPKc,7168
15
- xulbux/xx_system.py,sha256=uBpB1eKbR-bddO87jbWdoi5NScLnrxJONbyqU49LmCs,6426
16
- xulbux-1.6.2.dist-info/LICENSE,sha256=6NflEcvzFEe8_JFVNCPVwZBwBhlLLd4vqQi8WiX_Xk4,1084
17
- xulbux-1.6.2.dist-info/METADATA,sha256=PyPr14LhmMVg952AQ-5uxp5jd3GSFRVCOxjPfsQ7ebo,6836
18
- xulbux-1.6.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
19
- xulbux-1.6.2.dist-info/entry_points.txt,sha256=a3womfLIMZKnOFiyy-xnVb4g2qkZsHR5FbKKkljcGns,94
20
- xulbux-1.6.2.dist-info/top_level.txt,sha256=FkK4EZajwfP36fnlrPaR98OrEvZpvdEOdW1T5zTj6og,7
21
- xulbux-1.6.2.dist-info/RECORD,,
15
+ xulbux/xx_system.py,sha256=M3VGU3Tf3nDU59DjIJgDXJOqNB80Vr0wf15Vcnb5UCo,6430
16
+ xulbux-1.6.3.dist-info/LICENSE,sha256=6NflEcvzFEe8_JFVNCPVwZBwBhlLLd4vqQi8WiX_Xk4,1084
17
+ xulbux-1.6.3.dist-info/METADATA,sha256=dYwkecrzpal4hVChJVdbk0HYdJXluT5-8xxBqTj33xM,6948
18
+ xulbux-1.6.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
19
+ xulbux-1.6.3.dist-info/entry_points.txt,sha256=a3womfLIMZKnOFiyy-xnVb4g2qkZsHR5FbKKkljcGns,94
20
+ xulbux-1.6.3.dist-info/top_level.txt,sha256=FkK4EZajwfP36fnlrPaR98OrEvZpvdEOdW1T5zTj6og,7
21
+ xulbux-1.6.3.dist-info/RECORD,,
File without changes