xulbux 1.5.7__py3-none-any.whl → 1.5.8__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 +11 -11
- xulbux/_cli_.py +10 -10
- xulbux/xx_code.py +3 -3
- xulbux/xx_color.py +62 -51
- xulbux/{xx_cmd.py → xx_console.py} +39 -39
- xulbux/xx_data.py +241 -268
- xulbux/xx_env_path.py +113 -0
- xulbux/xx_file.py +2 -2
- xulbux/xx_format_codes.py +2 -3
- xulbux/xx_json.py +2 -2
- xulbux/xx_regex.py +22 -4
- xulbux/xx_string.py +29 -0
- {xulbux-1.5.7.dist-info → xulbux-1.5.8.dist-info}/METADATA +10 -10
- xulbux-1.5.8.dist-info/RECORD +20 -0
- xulbux-1.5.8.dist-info/entry_points.txt +3 -0
- xulbux/xx_env_vars.py +0 -73
- xulbux-1.5.7.dist-info/RECORD +0 -20
- xulbux-1.5.7.dist-info/entry_points.txt +0 -3
- {xulbux-1.5.7.dist-info → xulbux-1.5.8.dist-info}/WHEEL +0 -0
- {xulbux-1.5.7.dist-info → xulbux-1.5.8.dist-info}/licenses/LICENSE +0 -0
xulbux/__init__.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
>>> import
|
|
2
|
+
>>> import xulbux as xx
|
|
3
3
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
4
4
|
• CUSTOM TYPES:
|
|
5
5
|
• rgba(int,int,int,float)
|
|
@@ -9,17 +9,17 @@
|
|
|
9
9
|
• FILE OPERATIONS xx.File
|
|
10
10
|
• JSON FILE OPERATIONS xx.Json
|
|
11
11
|
• SYSTEM ACTIONS xx.System
|
|
12
|
-
• MANAGE
|
|
13
|
-
•
|
|
14
|
-
• PRETTY PRINTING
|
|
15
|
-
•
|
|
12
|
+
• MANAGE THE ENV PATH VAR xx.EnvPath
|
|
13
|
+
• CONSOLE LOG AND ACTIONS xx.Console
|
|
14
|
+
• EASY PRETTY PRINTING xx.FormatCodes
|
|
15
|
+
• WORKING WITH COLORS xx.Color
|
|
16
16
|
• DATA OPERATIONS xx.Data
|
|
17
|
-
•
|
|
17
|
+
• STRING OPERATIONS xx.String
|
|
18
18
|
• CODE STRING OPERATIONS xx.Code
|
|
19
19
|
• REGEX PATTERN TEMPLATES xx.Regex
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
__version__ = "1.5.
|
|
22
|
+
__version__ = "1.5.8"
|
|
23
23
|
__author__ = "XulbuX"
|
|
24
24
|
__email__ = "xulbux.real@gmail.com"
|
|
25
25
|
__license__ = "MIT"
|
|
@@ -28,11 +28,11 @@ __url__ = "https://github.com/XulbuX-dev/Python/tree/main/Libraries/XulbuX"
|
|
|
28
28
|
__description__ = "A library which includes a lot of really helpful functions."
|
|
29
29
|
__all__ = [
|
|
30
30
|
"_consts_",
|
|
31
|
-
"
|
|
31
|
+
"xx_console",
|
|
32
32
|
"xx_code",
|
|
33
33
|
"xx_color",
|
|
34
34
|
"xx_data",
|
|
35
|
-
"
|
|
35
|
+
"xx_env_path",
|
|
36
36
|
"xx_file",
|
|
37
37
|
"xx_format_codes",
|
|
38
38
|
"xx_json",
|
|
@@ -43,11 +43,11 @@ __all__ = [
|
|
|
43
43
|
]
|
|
44
44
|
|
|
45
45
|
from ._consts_ import *
|
|
46
|
-
from .xx_cmd import *
|
|
47
46
|
from .xx_code import *
|
|
48
47
|
from .xx_color import *
|
|
48
|
+
from .xx_console import *
|
|
49
49
|
from .xx_data import *
|
|
50
|
-
from .
|
|
50
|
+
from .xx_env_path import *
|
|
51
51
|
from .xx_file import *
|
|
52
52
|
from .xx_format_codes import *
|
|
53
53
|
from .xx_json import *
|
xulbux/_cli_.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from . import __version__
|
|
2
2
|
from ._consts_ import DEFAULT
|
|
3
|
-
from .xx_format_codes import
|
|
4
|
-
from .
|
|
3
|
+
from .xx_format_codes import FormatCodes
|
|
4
|
+
from .xx_console import Console
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def help_command():
|
|
@@ -24,9 +24,9 @@ def help_command():
|
|
|
24
24
|
|
|
25
25
|
[b|#75A2FF]Usage:[*]
|
|
26
26
|
[{color['punctuators']}]# GENERAL LIBRARY[*]
|
|
27
|
-
[{color['import']}]import [{color['lib']}]
|
|
27
|
+
[{color['import']}]import [{color['lib']}]xulbux [{color['import']}]as [{color['lib']}]xx[*]
|
|
28
28
|
[{color['punctuators']}]# CUSTOM TYPES[*]
|
|
29
|
-
[{color['import']}]from [{color['lib']}]
|
|
29
|
+
[{color['import']}]from [{color['lib']}]xulbux [{color['import']}]import [{color['lib']}]rgba[{color['punctuators']}], [{color['lib']}]hsla[{color['punctuators']}], [{color['lib']}]hexa[*]
|
|
30
30
|
|
|
31
31
|
[b|#75A2FF]Includes:[*]
|
|
32
32
|
[dim](•) CUSTOM TYPES:
|
|
@@ -37,16 +37,16 @@ def help_command():
|
|
|
37
37
|
[dim](•) FILE OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]File[*]
|
|
38
38
|
[dim](•) JSON FILE OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Json[*]
|
|
39
39
|
[dim](•) SYSTEM ACTIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]System[*]
|
|
40
|
-
[dim](•) MANAGE
|
|
41
|
-
[dim](•)
|
|
42
|
-
[dim](•) PRETTY PRINTING
|
|
43
|
-
[dim](•)
|
|
40
|
+
[dim](•) MANAGE THE ENV PATH VAR [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]EnvPath[*]
|
|
41
|
+
[dim](•) CONSOLE LOG AND ACTIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Console[*]
|
|
42
|
+
[dim](•) EASY PRETTY PRINTING [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]FormatCodes[*]
|
|
43
|
+
[dim](•) WORKING WITH COLORS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Color[*]
|
|
44
44
|
[dim](•) DATA OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Data[*]
|
|
45
|
-
[dim](•)
|
|
45
|
+
[dim](•) STRING OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]String[*]
|
|
46
46
|
[dim](•) CODE STRING OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Code[*]
|
|
47
47
|
[dim](•) REGEX PATTERN TEMPLATES [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Regex[*]
|
|
48
48
|
[_]
|
|
49
49
|
[dim](Press any key to exit...)
|
|
50
50
|
"""
|
|
51
51
|
)
|
|
52
|
-
|
|
52
|
+
Console.pause_exit(pause=True)
|
xulbux/xx_code.py
CHANGED
xulbux/xx_color.py
CHANGED
|
@@ -31,7 +31,7 @@ The `Color` class, which contains all sorts of different color-related methods:
|
|
|
31
31
|
- saturation
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
from .xx_regex import
|
|
34
|
+
from .xx_regex import Regex
|
|
35
35
|
|
|
36
36
|
import re as _re
|
|
37
37
|
|
|
@@ -159,10 +159,9 @@ class rgba:
|
|
|
159
159
|
|
|
160
160
|
def blend(self, other: "rgba", ratio: float = 0.5, additive_alpha: bool = False) -> "rgba":
|
|
161
161
|
"""Blends the current color with another color using the specified ratio (`0.0`-`1.0`):<br>
|
|
162
|
-
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (
|
|
162
|
+
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (2:0 mixture)<br>
|
|
163
163
|
If `ratio` is `0.5` it means 50% of both colors (1:1 mixture)<br>
|
|
164
|
-
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:
|
|
165
|
-
"""
|
|
164
|
+
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:2 mixture)"""
|
|
166
165
|
if not (isinstance(ratio, (int, float)) and 0 <= ratio <= 1):
|
|
167
166
|
raise ValueError("'ratio' must be a float/int in [0.0, 1.0]")
|
|
168
167
|
elif not isinstance(other, rgba):
|
|
@@ -193,11 +192,11 @@ class rgba:
|
|
|
193
192
|
return rgba(self.r, self.g, self.b, None if none_alpha else self.a)
|
|
194
193
|
|
|
195
194
|
def is_dark(self) -> bool:
|
|
196
|
-
"""Returns `True` if the color is considered dark (
|
|
195
|
+
"""Returns `True` if the color is considered dark (`lightness < 50%`)"""
|
|
197
196
|
return (0.299 * self.r + 0.587 * self.g + 0.114 * self.b) < 128
|
|
198
197
|
|
|
199
198
|
def is_light(self) -> bool:
|
|
200
|
-
"""Returns `True` if the color is considered light (
|
|
199
|
+
"""Returns `True` if the color is considered light (`lightness >= 50%`)"""
|
|
201
200
|
return not self.is_dark()
|
|
202
201
|
|
|
203
202
|
def is_grayscale(self) -> bool:
|
|
@@ -371,19 +370,18 @@ class hsla:
|
|
|
371
370
|
|
|
372
371
|
def blend(self, other: "hsla", ratio: float = 0.5, additive_alpha: bool = False) -> "rgba":
|
|
373
372
|
"""Blends the current color with another color using the specified ratio (`0.0`-`1.0`):<br>
|
|
374
|
-
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (
|
|
373
|
+
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (2:0 mixture)<br>
|
|
375
374
|
If `ratio` is `0.5` it means 50% of both colors (1:1 mixture)<br>
|
|
376
|
-
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:
|
|
377
|
-
"""
|
|
375
|
+
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:2 mixture)"""
|
|
378
376
|
self.h, self.s, self.l, self.a = self.to_rgba().blend(Color.to_rgba(other), ratio, additive_alpha).to_hsla().values()
|
|
379
377
|
return hsla(self.h, self.s, self.l, self.a)
|
|
380
378
|
|
|
381
379
|
def is_dark(self) -> bool:
|
|
382
|
-
"""Returns `True` if the color is considered dark (`lightness < 50
|
|
380
|
+
"""Returns `True` if the color is considered dark (`lightness < 50%`)"""
|
|
383
381
|
return self.l < 50
|
|
384
382
|
|
|
385
383
|
def is_light(self) -> bool:
|
|
386
|
-
"""Returns `True` if the color is considered light (`lightness >= 50
|
|
384
|
+
"""Returns `True` if the color is considered light (`lightness >= 50%`)"""
|
|
387
385
|
return not self.is_dark()
|
|
388
386
|
|
|
389
387
|
def is_grayscale(self) -> bool:
|
|
@@ -598,19 +596,18 @@ class hexa:
|
|
|
598
596
|
|
|
599
597
|
def blend(self, other: "hexa", ratio: float = 0.5, additive_alpha: bool = False) -> "rgba":
|
|
600
598
|
"""Blends the current color with another color using the specified ratio (`0.0`-`1.0`):<br>
|
|
601
|
-
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (
|
|
599
|
+
If `ratio` is `0.0` it means 100% of the current color and 0% of the `other` color (2:0 mixture)<br>
|
|
602
600
|
If `ratio` is `0.5` it means 50% of both colors (1:1 mixture)<br>
|
|
603
|
-
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:
|
|
604
|
-
"""
|
|
601
|
+
If `ratio` is `1.0` it means 0% of the current color and 100% of the `other` color (0:2 mixture)"""
|
|
605
602
|
self.r, self.g, self.b, self.a = self.to_rgba(False).blend(Color.to_rgba(other), ratio, additive_alpha).values()
|
|
606
603
|
return hexa(f'#{self.r:02X}{self.g:02X}{self.b:02X}{f"{int(self.a * 255):02X}" if self.a else ""}')
|
|
607
604
|
|
|
608
605
|
def is_dark(self) -> bool:
|
|
609
|
-
"""Returns `True` if the color is considered dark (
|
|
606
|
+
"""Returns `True` if the color is considered dark (`lightness < 50%`)"""
|
|
610
607
|
return self.to_hsla(False).is_dark()
|
|
611
608
|
|
|
612
609
|
def is_light(self) -> bool:
|
|
613
|
-
"""Returns `True` if the color is considered light (`lightness >= 50
|
|
610
|
+
"""Returns `True` if the color is considered light (`lightness >= 50%`)"""
|
|
614
611
|
return self.to_hsla(False).is_light()
|
|
615
612
|
|
|
616
613
|
def is_grayscale(self) -> bool:
|
|
@@ -658,7 +655,7 @@ class Color:
|
|
|
658
655
|
)
|
|
659
656
|
return 0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
|
|
660
657
|
elif isinstance(color, str):
|
|
661
|
-
return bool(_re.fullmatch(Regex.rgba_str(), color))
|
|
658
|
+
return bool(_re.fullmatch(Regex.rgba_str(allow_alpha=allow_alpha), color))
|
|
662
659
|
return False
|
|
663
660
|
except Exception:
|
|
664
661
|
return False
|
|
@@ -689,29 +686,29 @@ class Color:
|
|
|
689
686
|
else:
|
|
690
687
|
return 0 <= color["h"] <= 360 and 0 <= color["s"] <= 100 and 0 <= color["l"] <= 100
|
|
691
688
|
elif isinstance(color, str):
|
|
692
|
-
return bool(_re.fullmatch(Regex.hsla_str(), color))
|
|
689
|
+
return bool(_re.fullmatch(Regex.hsla_str(allow_alpha=allow_alpha), color))
|
|
693
690
|
except Exception:
|
|
694
691
|
return False
|
|
695
692
|
|
|
696
693
|
@staticmethod
|
|
697
|
-
def is_valid_hexa(color: str, allow_alpha: bool = True, get_prefix: bool = False) -> bool | tuple[bool, str]:
|
|
694
|
+
def is_valid_hexa(color: str | int, allow_alpha: bool = True, get_prefix: bool = False) -> bool | tuple[bool, str]:
|
|
698
695
|
try:
|
|
699
696
|
if isinstance(color, hexa):
|
|
700
697
|
return (True, "#")
|
|
701
698
|
elif isinstance(color, int):
|
|
702
699
|
is_valid = 0 <= color <= (0xFFFFFFFF if allow_alpha else 0xFFFFFF)
|
|
703
700
|
return (is_valid, "0x") if get_prefix else is_valid
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
color
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
701
|
+
elif isinstance(color, str):
|
|
702
|
+
color, prefix = (
|
|
703
|
+
(color[1:], "#")
|
|
704
|
+
if color.startswith("#")
|
|
705
|
+
else (color[2:], "0x") if color.startswith("0x") else (color, None)
|
|
706
|
+
)
|
|
707
|
+
return (
|
|
708
|
+
(bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color)), prefix)
|
|
709
|
+
if get_prefix
|
|
710
|
+
else bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color))
|
|
713
711
|
)
|
|
714
|
-
return (bool(_re.fullmatch(pattern, color)), prefix) if get_prefix else bool(_re.fullmatch(pattern, color))
|
|
715
712
|
except Exception:
|
|
716
713
|
return (False, None) if get_prefix else False
|
|
717
714
|
|
|
@@ -798,19 +795,30 @@ class Color:
|
|
|
798
795
|
"""Will try to recognize RGBA colors inside a string and output the found ones as RGBA objects.<br>
|
|
799
796
|
If `only_first` is `True` only the first found color will be returned (not as a list).
|
|
800
797
|
"""
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
798
|
+
if only_first:
|
|
799
|
+
match = _re.search(Regex.rgb_str(allow_alpha=True), string)
|
|
800
|
+
if not match:
|
|
801
|
+
return None
|
|
802
|
+
m = match.groups()
|
|
803
|
+
return rgba(
|
|
806
804
|
int(m[0]),
|
|
807
805
|
int(m[1]),
|
|
808
806
|
int(m[2]),
|
|
809
807
|
((int(m[3]) if "." not in m[3] else float(m[3])) if m[3] else None),
|
|
810
808
|
)
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
809
|
+
else:
|
|
810
|
+
matches = _re.findall(Regex.rgb_str(allow_alpha=True), string)
|
|
811
|
+
if not matches:
|
|
812
|
+
return None
|
|
813
|
+
return [
|
|
814
|
+
rgba(
|
|
815
|
+
int(m[0]),
|
|
816
|
+
int(m[1]),
|
|
817
|
+
int(m[2]),
|
|
818
|
+
((int(m[3]) if "." not in m[3] else float(m[3])) if m[3] else None),
|
|
819
|
+
)
|
|
820
|
+
for m in matches
|
|
821
|
+
]
|
|
814
822
|
|
|
815
823
|
@staticmethod
|
|
816
824
|
def rgba_to_hex_int(
|
|
@@ -818,40 +826,43 @@ class Color:
|
|
|
818
826
|
g: int,
|
|
819
827
|
b: int,
|
|
820
828
|
a: float = None,
|
|
821
|
-
|
|
829
|
+
preserve_original: bool = False,
|
|
822
830
|
) -> int:
|
|
823
831
|
"""Convert RGBA channels to a HEXA integer (alpha is optional).\n
|
|
824
832
|
-------------------------------------------------------------------------------------------------------------------------
|
|
825
|
-
To preserve leading zeros, the function will add a `1` at the beginning, if the HEX
|
|
833
|
+
To preserve leading zeros, the function will add a `1` at the beginning, if the HEX integer would start with a `0`.<br>
|
|
826
834
|
This could affect the color a little bit, but will make sure, that it won't be interpreted as a completely different<br>
|
|
827
|
-
color, when initializing it as a `hexa()` color or changing it back to RGBA using `Color.
|
|
828
|
-
⇾ **You can disable this behavior by setting `
|
|
829
|
-
"""
|
|
835
|
+
color, when initializing it as a `hexa()` color or changing it back to RGBA using `Color.hex_int_to_rgba()`.\n
|
|
836
|
+
⇾ **You can disable this behavior by setting `preserve_original` to `True`**"""
|
|
830
837
|
r = max(0, min(255, int(r)))
|
|
831
838
|
g = max(0, min(255, int(g)))
|
|
832
839
|
b = max(0, min(255, int(b)))
|
|
833
840
|
if a is not None:
|
|
834
|
-
|
|
835
|
-
a = int(a * 255)
|
|
836
|
-
a = max(0, min(255, int(a)))
|
|
841
|
+
a = max(0, min(255, int(a * 255)))
|
|
837
842
|
hex_int = (r << 24) | (g << 16) | (b << 8) | a
|
|
838
|
-
if not
|
|
843
|
+
if not preserve_original and r == 0:
|
|
839
844
|
hex_int |= 0x01000000
|
|
840
845
|
else:
|
|
841
846
|
hex_int = (r << 16) | (g << 8) | b
|
|
842
|
-
if not
|
|
847
|
+
if not preserve_original and (hex_int & 0xF00000) == 0:
|
|
843
848
|
hex_int |= 0x010000
|
|
844
849
|
return hex_int
|
|
845
850
|
|
|
846
851
|
@staticmethod
|
|
847
|
-
def hex_int_to_rgba(hex_int: int) -> tuple[int, int, int, float |
|
|
852
|
+
def hex_int_to_rgba(hex_int: int, preserve_original: bool = False) -> tuple[int, int, int, float | None]:
|
|
853
|
+
"""Convert a HEX integer to RGBA channels.\n
|
|
854
|
+
-----------------------------------------------------------------------------------------------
|
|
855
|
+
If the red channel is `1` after conversion, it will be set to `0`, because when converting<br>
|
|
856
|
+
from RGBA to a HEX integer, the first `0` will be set to `1` to preserve leading zeros.<br>
|
|
857
|
+
This is the correction, so the color doesn't even look slightly different.\n
|
|
858
|
+
⇾ **You can disable this behavior by setting `preserve_original` to `True`**"""
|
|
848
859
|
if not isinstance(hex_int, int):
|
|
849
|
-
raise ValueError("Input must be an integer
|
|
860
|
+
raise ValueError("Input must be an integer")
|
|
850
861
|
hex_str = f"{hex_int:x}"
|
|
851
862
|
if len(hex_str) <= 6:
|
|
852
863
|
hex_str = hex_str.zfill(6)
|
|
853
864
|
return (
|
|
854
|
-
int(hex_str[0:2], 16),
|
|
865
|
+
r if (r := int(hex_str[0:2], 16)) != 1 or preserve_original else 0,
|
|
855
866
|
int(hex_str[2:4], 16),
|
|
856
867
|
int(hex_str[4:6], 16),
|
|
857
868
|
None,
|
|
@@ -859,7 +870,7 @@ class Color:
|
|
|
859
870
|
elif len(hex_str) <= 8:
|
|
860
871
|
hex_str = hex_str.zfill(8)
|
|
861
872
|
return (
|
|
862
|
-
int(hex_str[0:2], 16),
|
|
873
|
+
r if (r := int(hex_str[0:2], 16)) != 1 or preserve_original else 0,
|
|
863
874
|
int(hex_str[2:4], 16),
|
|
864
875
|
int(hex_str[4:6], 16),
|
|
865
876
|
int(hex_str[6:8], 16) / 255.0,
|
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Functions for logging and other small actions within the console:
|
|
3
|
-
- `
|
|
4
|
-
- `
|
|
5
|
-
- `
|
|
6
|
-
- `
|
|
7
|
-
- `
|
|
8
|
-
- `
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `
|
|
13
|
-
- `
|
|
14
|
-
- `
|
|
15
|
-
- `
|
|
16
|
-
- `
|
|
17
|
-
- `
|
|
3
|
+
- `Console.get_args()`
|
|
4
|
+
- `Console.user()`
|
|
5
|
+
- `Console.is_admin()`
|
|
6
|
+
- `Console.pause_exit()`
|
|
7
|
+
- `Console.cls()`
|
|
8
|
+
- `Console.log()`
|
|
9
|
+
- `Console.debug()`
|
|
10
|
+
- `Console.info()`
|
|
11
|
+
- `Console.done()`
|
|
12
|
+
- `Console.warn()`
|
|
13
|
+
- `Console.fail()`
|
|
14
|
+
- `Console.exit()`
|
|
15
|
+
- `Console.confirm()`
|
|
16
|
+
- `Console.restricted_input()`
|
|
17
|
+
- `Console.pwd_input()`\n
|
|
18
18
|
----------------------------------------------------------------------------------------------------------
|
|
19
19
|
You can also use special formatting codes directly inside the log message to change their appearance.<br>
|
|
20
20
|
For more detailed information about formatting codes, see the the `xx_format_codes` description.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
23
|
from ._consts_ import DEFAULT, CHARS
|
|
24
|
-
from .xx_format_codes import
|
|
25
|
-
from .xx_string import
|
|
24
|
+
from .xx_format_codes import FormatCodes
|
|
25
|
+
from .xx_string import String
|
|
26
26
|
from .xx_color import *
|
|
27
27
|
|
|
28
28
|
from contextlib import suppress
|
|
@@ -36,7 +36,7 @@ import sys as _sys
|
|
|
36
36
|
import os as _os
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
class
|
|
39
|
+
class Console:
|
|
40
40
|
|
|
41
41
|
@staticmethod
|
|
42
42
|
def get_args(find_args: dict) -> dict[str, dict[str, any]]:
|
|
@@ -62,7 +62,7 @@ class Cmd:
|
|
|
62
62
|
return getattr(_shutil.get_terminal_size(), "lines", 24)
|
|
63
63
|
|
|
64
64
|
def wh() -> tuple[int, int]:
|
|
65
|
-
return
|
|
65
|
+
return Console.w(), Console.h()
|
|
66
66
|
|
|
67
67
|
def user() -> str:
|
|
68
68
|
return _os.getenv("USER") or _os.getenv("USERNAME") or _getpass.getuser()
|
|
@@ -153,8 +153,8 @@ class Cmd:
|
|
|
153
153
|
"""A preset for `log()`: `DEBUG` log message with the options to pause<br>
|
|
154
154
|
at the message and exit the program after the message was printed."""
|
|
155
155
|
if active:
|
|
156
|
-
|
|
157
|
-
|
|
156
|
+
Console.log("DEBUG", prompt, start, end, title_bg_color, default_color)
|
|
157
|
+
Console.pause_exit(pause, exit)
|
|
158
158
|
|
|
159
159
|
@staticmethod
|
|
160
160
|
def info(
|
|
@@ -168,8 +168,8 @@ class Cmd:
|
|
|
168
168
|
) -> None:
|
|
169
169
|
"""A preset for `log()`: `INFO` log message with the options to pause<br>
|
|
170
170
|
at the message and exit the program after the message was printed."""
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
Console.log("INFO", prompt, start, end, title_bg_color, default_color)
|
|
172
|
+
Console.pause_exit(pause, exit)
|
|
173
173
|
|
|
174
174
|
@staticmethod
|
|
175
175
|
def done(
|
|
@@ -183,8 +183,8 @@ class Cmd:
|
|
|
183
183
|
) -> None:
|
|
184
184
|
"""A preset for `log()`: `DONE` log message with the options to pause<br>
|
|
185
185
|
at the message and exit the program after the message was printed."""
|
|
186
|
-
|
|
187
|
-
|
|
186
|
+
Console.log("DONE", prompt, start, end, title_bg_color, default_color)
|
|
187
|
+
Console.pause_exit(pause, exit)
|
|
188
188
|
|
|
189
189
|
@staticmethod
|
|
190
190
|
def warn(
|
|
@@ -198,8 +198,8 @@ class Cmd:
|
|
|
198
198
|
) -> None:
|
|
199
199
|
"""A preset for `log()`: `WARN` log message with the options to pause<br>
|
|
200
200
|
at the message and exit the program after the message was printed."""
|
|
201
|
-
|
|
202
|
-
|
|
201
|
+
Console.log("WARN", prompt, start, end, title_bg_color, default_color)
|
|
202
|
+
Console.pause_exit(pause, exit)
|
|
203
203
|
|
|
204
204
|
@staticmethod
|
|
205
205
|
def fail(
|
|
@@ -214,8 +214,8 @@ class Cmd:
|
|
|
214
214
|
) -> None:
|
|
215
215
|
"""A preset for `log()`: `FAIL` log message with the options to pause<br>
|
|
216
216
|
at the message and exit the program after the message was printed."""
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
Console.log("FAIL", prompt, start, end, title_bg_color, default_color)
|
|
218
|
+
Console.pause_exit(pause, exit, reset_ansi=reset_ansi)
|
|
219
219
|
|
|
220
220
|
@staticmethod
|
|
221
221
|
def exit(
|
|
@@ -230,8 +230,8 @@ class Cmd:
|
|
|
230
230
|
) -> None:
|
|
231
231
|
"""A preset for `log()`: `EXIT` log message with the options to pause<br>
|
|
232
232
|
at the message and exit the program after the message was printed."""
|
|
233
|
-
|
|
234
|
-
|
|
233
|
+
Console.log("EXIT", prompt, start, end, title_bg_color, default_color)
|
|
234
|
+
Console.pause_exit(pause, exit, reset_ansi=reset_ansi)
|
|
235
235
|
|
|
236
236
|
@staticmethod
|
|
237
237
|
def confirm(
|
|
@@ -253,7 +253,7 @@ class Cmd:
|
|
|
253
253
|
)
|
|
254
254
|
).strip().lower() in (("", "y", "yes") if default_is_yes else ("y", "yes"))
|
|
255
255
|
if end:
|
|
256
|
-
|
|
256
|
+
Console.log("", end, end="")
|
|
257
257
|
return confirmed
|
|
258
258
|
|
|
259
259
|
@staticmethod
|
|
@@ -317,7 +317,7 @@ class Cmd:
|
|
|
317
317
|
result, select_all = "", False
|
|
318
318
|
elif result and event.name == "backspace":
|
|
319
319
|
result = result[:-1]
|
|
320
|
-
update_display(
|
|
320
|
+
update_display(Console.w())
|
|
321
321
|
|
|
322
322
|
def handle_paste():
|
|
323
323
|
nonlocal result, select_all
|
|
@@ -326,25 +326,25 @@ class Cmd:
|
|
|
326
326
|
filtered_text = "".join(char for char in _pyperclip.paste() if allowed_chars == CHARS.all or char in allowed_chars)
|
|
327
327
|
if max_len is None or len(result) + len(filtered_text) <= max_len:
|
|
328
328
|
result += filtered_text
|
|
329
|
-
update_display(
|
|
329
|
+
update_display(Console.w())
|
|
330
330
|
|
|
331
331
|
def handle_select_all():
|
|
332
332
|
nonlocal select_all
|
|
333
333
|
select_all = True
|
|
334
|
-
update_display(
|
|
334
|
+
update_display(Console.w())
|
|
335
335
|
|
|
336
336
|
def handle_copy():
|
|
337
337
|
nonlocal select_all
|
|
338
338
|
with suppress(KeyboardInterrupt):
|
|
339
339
|
select_all = False
|
|
340
|
-
update_display(
|
|
340
|
+
update_display(Console.w())
|
|
341
341
|
_pyperclip.copy(result)
|
|
342
342
|
|
|
343
343
|
def handle_character_input():
|
|
344
344
|
nonlocal result
|
|
345
345
|
if (allowed_chars == CHARS.all or event.name in allowed_chars) and (max_len is None or len(result) < max_len):
|
|
346
346
|
result += event.name
|
|
347
|
-
update_display(
|
|
347
|
+
update_display(Console.w())
|
|
348
348
|
|
|
349
349
|
while True:
|
|
350
350
|
event = _keyboard.read_event()
|
|
@@ -367,7 +367,7 @@ class Cmd:
|
|
|
367
367
|
handle_character_input()
|
|
368
368
|
else:
|
|
369
369
|
select_all = False
|
|
370
|
-
update_display(
|
|
370
|
+
update_display(Console.w())
|
|
371
371
|
|
|
372
372
|
@staticmethod
|
|
373
373
|
def pwd_input(
|
|
@@ -378,4 +378,4 @@ class Cmd:
|
|
|
378
378
|
_reset_ansi: bool = True,
|
|
379
379
|
) -> str:
|
|
380
380
|
"""Password input that masks the entered characters with asterisks."""
|
|
381
|
-
return
|
|
381
|
+
return Console.restricted_input(prompt, allowed_chars, min_len, max_len, "*", _reset_ansi)
|