xulbux 1.6.5__py3-none-any.whl → 1.6.7__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 +1 -1
- xulbux/_cli_.py +9 -9
- xulbux/_consts_.py +98 -62
- xulbux/xx_code.py +37 -42
- xulbux/xx_color.py +27 -55
- xulbux/xx_console.py +205 -110
- xulbux/xx_data.py +176 -128
- xulbux/xx_env_path.py +3 -7
- xulbux/xx_file.py +10 -4
- xulbux/xx_format_codes.py +26 -37
- xulbux/xx_json.py +2 -5
- xulbux/xx_path.py +33 -23
- xulbux/xx_regex.py +18 -20
- xulbux/xx_string.py +23 -76
- xulbux/xx_system.py +16 -19
- {xulbux-1.6.5.dist-info → xulbux-1.6.7.dist-info}/METADATA +92 -13
- xulbux-1.6.7.dist-info/RECORD +21 -0
- {xulbux-1.6.5.dist-info → xulbux-1.6.7.dist-info}/WHEEL +1 -1
- xulbux-1.6.5.dist-info/RECORD +0 -21
- {xulbux-1.6.5.dist-info → xulbux-1.6.7.dist-info}/LICENSE +0 -0
- {xulbux-1.6.5.dist-info → xulbux-1.6.7.dist-info}/entry_points.txt +0 -0
- {xulbux-1.6.5.dist-info → xulbux-1.6.7.dist-info}/top_level.txt +0 -0
xulbux/__init__.py
CHANGED
xulbux/_cli_.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from . import __version__
|
|
2
|
-
from ._consts_ import
|
|
2
|
+
from ._consts_ import COLOR
|
|
3
3
|
from .xx_format_codes import FormatCodes
|
|
4
4
|
from .xx_console import Console
|
|
5
5
|
|
|
@@ -7,20 +7,20 @@ from .xx_console import Console
|
|
|
7
7
|
def help_command():
|
|
8
8
|
"""Show some info about the library, with a brief explanation of how to use it."""
|
|
9
9
|
color = {
|
|
10
|
-
"lib":
|
|
11
|
-
"import":
|
|
12
|
-
"class":
|
|
13
|
-
"types":
|
|
14
|
-
"punctuators":
|
|
10
|
+
"lib": COLOR.ice,
|
|
11
|
+
"import": COLOR.red,
|
|
12
|
+
"class": COLOR.lavender,
|
|
13
|
+
"types": COLOR.lightblue,
|
|
14
|
+
"punctuators": COLOR.darkgray,
|
|
15
15
|
}
|
|
16
16
|
FormatCodes.print(
|
|
17
17
|
rf""" [_|b|#7075FF] __ __
|
|
18
18
|
[b|#7075FF] _ __ __ __/ / / /_ __ ___ __
|
|
19
19
|
[b|#7075FF] | |/ // / / / / / __ \/ / / | |/ /
|
|
20
20
|
[b|#7075FF] > , </ /_/ / /_/ /_/ / /_/ /> , <
|
|
21
|
-
[b|#7075FF]/_/|_|\____/\__/\____/\____//_/|_| [*|BG:{
|
|
21
|
+
[b|#7075FF]/_/|_|\____/\__/\____/\____//_/|_| [*|BG:{COLOR.gray}|#000] v[b]{__version__} [*]
|
|
22
22
|
|
|
23
|
-
[i|{
|
|
23
|
+
[i|{COLOR.coral}]A TON OF COOL FUNCTIONS, YOU NEED![*]
|
|
24
24
|
|
|
25
25
|
[b|#75A2FF]Usage:[*]
|
|
26
26
|
[{color['punctuators']}]# GENERAL LIBRARY[*]
|
|
@@ -48,6 +48,6 @@ def help_command():
|
|
|
48
48
|
[_]
|
|
49
49
|
[dim](Press any key to exit...)
|
|
50
50
|
""",
|
|
51
|
-
default_color=
|
|
51
|
+
default_color=COLOR.text
|
|
52
52
|
)
|
|
53
53
|
Console.pause_exit(pause=True)
|
xulbux/_consts_.py
CHANGED
|
@@ -1,76 +1,110 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TypeAlias
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
FormattableString: TypeAlias = str
|
|
6
|
+
"""A `str` object that is made to be formatted with the `.format()` method."""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass
|
|
10
|
+
class COLOR:
|
|
11
|
+
"""Color presets used in the `xulbux` library."""
|
|
12
|
+
|
|
13
|
+
text = "#A5D6FF"
|
|
14
|
+
"""The default text color used in the `xulbux` library."""
|
|
15
|
+
|
|
16
|
+
white = "#F1F2FF"
|
|
17
|
+
lightgray = "#B6B7C0"
|
|
18
|
+
gray = "#7B7C8D"
|
|
19
|
+
darkgray = "#67686C"
|
|
20
|
+
black = "#202125"
|
|
21
|
+
red = "#FF606A"
|
|
22
|
+
coral = "#FF7069"
|
|
23
|
+
orange = "#FF876A"
|
|
24
|
+
tangerine = "#FF9962"
|
|
25
|
+
gold = "#FFAF60"
|
|
26
|
+
yellow = "#FFD260"
|
|
27
|
+
lime = "#C9F16E"
|
|
28
|
+
green = "#7EE787"
|
|
29
|
+
teal = "#50EAAF"
|
|
30
|
+
cyan = "#3EDEE6"
|
|
31
|
+
ice = "#77DBEF"
|
|
32
|
+
lightblue = "#60AAFF"
|
|
33
|
+
blue = "#8085FF"
|
|
34
|
+
lavender = "#9B7DFF"
|
|
35
|
+
purple = "#AD68FF"
|
|
36
|
+
magenta = "#C860FF"
|
|
37
|
+
pink = "#F162EF"
|
|
38
|
+
rose = "#FF609F"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class _AllTextCharacters:
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass
|
|
30
46
|
class CHARS:
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
all =
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
digits = "0123456789"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
47
|
+
"""Text character sets."""
|
|
48
|
+
|
|
49
|
+
all = _AllTextCharacters
|
|
50
|
+
"""Code to signal that all characters are allowed."""
|
|
51
|
+
|
|
52
|
+
digits: str = "0123456789"
|
|
53
|
+
"""Digits: `0`-`9`"""
|
|
54
|
+
float_digits: str = digits + "."
|
|
55
|
+
"""Digits: `0`-`9` with decimal point `.`"""
|
|
56
|
+
hex_digits: str = digits + "#abcdefABCDEF"
|
|
57
|
+
"""Digits: `0`-`9` Letters: `a`-`f` `A`-`F` and a hashtag `#`"""
|
|
58
|
+
|
|
59
|
+
lowercase: str = "abcdefghijklmnopqrstuvwxyz"
|
|
60
|
+
"""Lowercase letters `a`-`z`"""
|
|
61
|
+
lowercase_extended: str = lowercase + "äëïöüÿàèìòùáéíóúýâêîôûãñõåæç"
|
|
62
|
+
"""Lowercase letters `a`-`z` with all lowercase diacritic letters."""
|
|
63
|
+
uppercase: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
64
|
+
"""Uppercase letters `A`-`Z`"""
|
|
65
|
+
uppercase_extended: str = uppercase + "ÄËÏÖÜÀÈÌÒÙÁÉÍÓÚÝÂÊÎÔÛÃÑÕÅÆÇß"
|
|
66
|
+
"""Uppercase letters `A`-`Z` with all uppercase diacritic letters."""
|
|
67
|
+
|
|
68
|
+
letters: str = lowercase + uppercase
|
|
69
|
+
"""Lowercase and uppercase letters `a`-`z` and `A`-`Z`"""
|
|
70
|
+
letters_extended: str = lowercase_extended + uppercase_extended
|
|
71
|
+
"""Lowercase and uppercase letters `a`-`z` `A`-`Z` and all diacritic letters."""
|
|
72
|
+
|
|
73
|
+
special_ascii: str = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
|
|
74
|
+
"""All ASCII special characters."""
|
|
75
|
+
special_ascii_extended: str = special_ascii + "ø£Ø×ƒªº¿®¬½¼¡«»░▒▓│┤©╣║╗╝¢¥┐└┴┬├─┼╚╔╩╦╠═╬¤ðÐı┘┌█▄¦▀µþÞ¯´≡±‗¾¶§÷¸°¨·¹³²■ "
|
|
76
|
+
"""All ASCII special characters with the extended ASCII special characters."""
|
|
77
|
+
standard_ascii: str = special_ascii + digits + letters
|
|
78
|
+
"""All standard ASCII characters."""
|
|
79
|
+
full_ascii: str = special_ascii_extended + digits + letters_extended
|
|
80
|
+
"""All characters in the ASCII table."""
|
|
55
81
|
|
|
56
82
|
|
|
57
83
|
class ANSI:
|
|
84
|
+
"""Constants and class-methods for use of ANSI escape codes."""
|
|
58
85
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
escaped_char = "\\x1b"
|
|
86
|
+
escaped_char: str = "\\x1b"
|
|
87
|
+
"""The printable ANSI escape character."""
|
|
62
88
|
CHAR = char = "\x1b"
|
|
89
|
+
"""The ANSI escape character."""
|
|
63
90
|
START = start = "["
|
|
91
|
+
"""The start of an ANSI escape sequence."""
|
|
64
92
|
SEP = sep = ";"
|
|
93
|
+
"""The separator between ANSI escape sequence parts."""
|
|
65
94
|
END = end = "m"
|
|
66
|
-
|
|
95
|
+
"""The end of an ANSI escape sequence."""
|
|
96
|
+
default_color_modifiers: dict[str, str] = {"lighten": "+l", "darken": "-d"}
|
|
97
|
+
"""Characters to modify the lightness of the default color with."""
|
|
67
98
|
|
|
68
|
-
|
|
99
|
+
@classmethod
|
|
100
|
+
def seq(cls, parts: int = 1) -> FormattableString:
|
|
69
101
|
"""Generate an ANSI sequence with `parts` amount of placeholders."""
|
|
70
|
-
return CHAR + START + SEP.join(["{}" for _ in range(parts)]) + END
|
|
102
|
+
return cls.CHAR + cls.START + cls.SEP.join(["{}" for _ in range(parts)]) + cls.END
|
|
71
103
|
|
|
72
|
-
seq_color:
|
|
73
|
-
|
|
104
|
+
seq_color: FormattableString = CHAR + START + "38" + SEP + "2" + SEP + "{}" + SEP + "{}" + SEP + "{}" + END
|
|
105
|
+
"""The ANSI escape sequence for setting the text RGB color."""
|
|
106
|
+
seq_bg_color: FormattableString = CHAR + START + "48" + SEP + "2" + SEP + "{}" + SEP + "{}" + SEP + "{}" + END
|
|
107
|
+
"""The ANSI escape sequence for setting the background RGB color."""
|
|
74
108
|
|
|
75
109
|
color_map: list[str] = [
|
|
76
110
|
########### DEFAULT CONSOLE COLOR NAMES ############
|
|
@@ -83,8 +117,9 @@ class ANSI:
|
|
|
83
117
|
"cyan",
|
|
84
118
|
"white",
|
|
85
119
|
]
|
|
120
|
+
"""The console default color names."""
|
|
86
121
|
|
|
87
|
-
codes_map: dict[str | tuple[str], int] = {
|
|
122
|
+
codes_map: dict[str | tuple[str, ...], int] = {
|
|
88
123
|
################# SPECIFIC RESETS ##################
|
|
89
124
|
"_": 0,
|
|
90
125
|
("_bold", "_b"): 22,
|
|
@@ -143,3 +178,4 @@ class ANSI:
|
|
|
143
178
|
"bg:br:cyan": 106,
|
|
144
179
|
"bg:br:white": 107,
|
|
145
180
|
}
|
|
181
|
+
"""All custom format keys and their corresponding ANSI format number codes."""
|
xulbux/xx_code.py
CHANGED
|
@@ -59,47 +59,42 @@ class Code:
|
|
|
59
59
|
js_pattern = _rx.compile(
|
|
60
60
|
Regex.outside_strings(
|
|
61
61
|
r"""^(?:
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
+
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|(\btypeof\b) # TYPEOF OPERATOR
|
|
100
|
-
|(\bvoid\b) # VOID OPERATOR
|
|
101
|
-
)[\s\S]*$"""
|
|
102
|
-
),
|
|
103
|
-
_rx.VERBOSE | _rx.IGNORECASE,
|
|
62
|
+
(\$[\w_]+)\s* # JQUERY-STYLE VARIABLES
|
|
63
|
+
|(\$[\w_]+\s*\() # JQUERY-STYLE FUNCTION CALLS
|
|
64
|
+
|((""" + funcs + r")" + Regex.brackets("()") + r"""\s*) # PREDEFINED FUNCTION CALLS
|
|
65
|
+
|(\bfunction\s*\() # FUNCTION DECLARATIONS
|
|
66
|
+
|(\b(var|let|const)\s+[\w_]+\s*=) # VARIABLE DECLARATIONS
|
|
67
|
+
|(\b(if|for|while|switch)\s*\() # CONTROL STRUCTURES
|
|
68
|
+
|(\b(return|throw)\s+) # RETURN OR THROW STATEMENTS
|
|
69
|
+
|(\bnew\s+[\w_]+\() # OBJECT INSTANTIATION
|
|
70
|
+
|(\b[\w_]+\s*=>\s*{) # ARROW FUNCTIONS
|
|
71
|
+
|(\b(true|false|null|undefined)\b) # JAVASCRIPT LITERALS
|
|
72
|
+
|(\b(document|window|console)\.) # BROWSER OBJECTS
|
|
73
|
+
|(\b[\w_]+\.(forEach|map|filter|reduce)\() # ARRAY METHODS
|
|
74
|
+
|(/[^/\n\r]*?/[gimsuy]*) # REGULAR EXPRESSIONS
|
|
75
|
+
|(===|!==|\+\+|--|\|\||&&) # JAVASCRIPT-SPECIFIC OPERATORS
|
|
76
|
+
|(\bclass\s+[\w_]+) # CLASS DECLARATIONS
|
|
77
|
+
|(\bimport\s+.*?from\s+) # IMPORT STATEMENTS
|
|
78
|
+
|(\bexport\s+(default\s+)?) # EXPORT STATEMENTS
|
|
79
|
+
|(\basync\s+function) # ASYNC FUNCTIONS
|
|
80
|
+
|(\bawait\s+) # AWAIT KEYWORD
|
|
81
|
+
|(\btry\s*{) # TRY-CATCH BLOCKS
|
|
82
|
+
|(\bcatch\s*\()
|
|
83
|
+
|(\bfinally\s*{)
|
|
84
|
+
|(\byield\s+) # GENERATOR FUNCTIONS
|
|
85
|
+
|(\[.*?\]\s*=) # DESTRUCTURING ASSIGNMENT
|
|
86
|
+
|(\.\.\.) # SPREAD OPERATOR
|
|
87
|
+
|(==|!=|>=|<=|>|<) # COMPARISON OPERATORS
|
|
88
|
+
|(\+=|-=|\*=|/=|%=|\*\*=) # COMPOUND ASSIGNMENT OPERATORS
|
|
89
|
+
|(\+|-|\*|/|%|\*\*) # ARITHMETIC OPERATORS
|
|
90
|
+
|(&|\||\^|~|<<|>>|>>>) # BITWISE OPERATORS
|
|
91
|
+
|(\?|:) # TERNARY OPERATOR
|
|
92
|
+
|(\bin\b) # IN OPERATOR
|
|
93
|
+
|(\binstanceof\b) # INSTANCEOF OPERATOR
|
|
94
|
+
|(\bdelete\b) # DELETE OPERATOR
|
|
95
|
+
|(\btypeof\b) # TYPEOF OPERATOR
|
|
96
|
+
|(\bvoid\b) # VOID OPERATOR
|
|
97
|
+
)[\s\S]*$"""
|
|
98
|
+
), _rx.VERBOSE | _rx.IGNORECASE
|
|
104
99
|
)
|
|
105
100
|
return bool(js_pattern.fullmatch(code))
|
xulbux/xx_color.py
CHANGED
|
@@ -33,6 +33,7 @@ The `Color` class, which contains all sorts of different color-related methods:
|
|
|
33
33
|
|
|
34
34
|
from .xx_regex import Regex
|
|
35
35
|
|
|
36
|
+
from typing import Optional
|
|
36
37
|
import re as _re
|
|
37
38
|
|
|
38
39
|
|
|
@@ -79,13 +80,13 @@ class rgba:
|
|
|
79
80
|
return 3 if self.a is None else 4
|
|
80
81
|
|
|
81
82
|
def __iter__(self) -> iter:
|
|
82
|
-
return iter((self.r, self.g, self.b) + (() if self.a is None else (self.a,)))
|
|
83
|
+
return iter((self.r, self.g, self.b) + (() if self.a is None else (self.a, )))
|
|
83
84
|
|
|
84
85
|
def __dict__(self) -> dict:
|
|
85
86
|
return self.dict()
|
|
86
87
|
|
|
87
88
|
def __getitem__(self, index: int) -> int:
|
|
88
|
-
return ((self.r, self.g, self.b) + (() if self.a is None else (self.a,)))[index]
|
|
89
|
+
return ((self.r, self.g, self.b) + (() if self.a is None else (self.a, )))[index]
|
|
89
90
|
|
|
90
91
|
def __repr__(self) -> str:
|
|
91
92
|
return f'rgba({self.r}, {self.g}, {self.b}{"" if self.a is None else f", {self.a}"})'
|
|
@@ -183,13 +184,7 @@ class rgba:
|
|
|
183
184
|
if additive_alpha:
|
|
184
185
|
self.a = max(0, min(1, (self_a * (2 - ratio)) + (other_a * ratio)))
|
|
185
186
|
else:
|
|
186
|
-
self.a = max(
|
|
187
|
-
0,
|
|
188
|
-
min(
|
|
189
|
-
1,
|
|
190
|
-
(self_a * (1 - (ratio / 2))) + (other_a * (ratio / 2)),
|
|
191
|
-
),
|
|
192
|
-
)
|
|
187
|
+
self.a = max(0, min(1, (self_a * (1 - (ratio / 2))) + (other_a * (ratio / 2))))
|
|
193
188
|
else:
|
|
194
189
|
self.a = None
|
|
195
190
|
return rgba(self.r, self.g, self.b, None if none_alpha else self.a, _validate=False)
|
|
@@ -282,13 +277,13 @@ class hsla:
|
|
|
282
277
|
return 3 if self.a is None else 4
|
|
283
278
|
|
|
284
279
|
def __iter__(self) -> iter:
|
|
285
|
-
return iter((self.h, self.s, self.l) + (() if self.a is None else (self.a,)))
|
|
280
|
+
return iter((self.h, self.s, self.l) + (() if self.a is None else (self.a, )))
|
|
286
281
|
|
|
287
282
|
def __dict__(self) -> dict:
|
|
288
283
|
return self.dict()
|
|
289
284
|
|
|
290
285
|
def __getitem__(self, index: int) -> int:
|
|
291
|
-
return ((self.h, self.s, self.l) + (() if self.a is None else (self.a,)))[index]
|
|
286
|
+
return ((self.h, self.s, self.l) + (() if self.a is None else (self.a, )))[index]
|
|
292
287
|
|
|
293
288
|
def __repr__(self) -> str:
|
|
294
289
|
return f'hsla({self.h}, {self.s}, {self.l}{"" if self.a is None else f", {self.a}"})'
|
|
@@ -508,17 +503,15 @@ class hexa:
|
|
|
508
503
|
return 3 if self.a is None else 4
|
|
509
504
|
|
|
510
505
|
def __iter__(self) -> iter:
|
|
511
|
-
return iter(
|
|
512
|
-
|
|
513
|
-
)
|
|
506
|
+
return iter((f"{self.r:02X}", f"{self.g:02X}", f"{self.b:02X}")
|
|
507
|
+
+ (() if self.a is None else (f"{int(self.a * 255):02X}", )))
|
|
514
508
|
|
|
515
509
|
def __dict__(self) -> dict:
|
|
516
510
|
return self.dict()
|
|
517
511
|
|
|
518
512
|
def __getitem__(self, index: int) -> int:
|
|
519
|
-
return (
|
|
520
|
-
|
|
521
|
-
)[index]
|
|
513
|
+
return ((f"{self.r:02X}", f"{self.g:02X}", f"{self.b:02X}") + (() if self.a is None else
|
|
514
|
+
(f"{int(self.a * 255):02X}", )))[index]
|
|
522
515
|
|
|
523
516
|
def __repr__(self) -> str:
|
|
524
517
|
return f'hexa(#{self.r:02X}{self.g:02X}{self.b:02X}{"" if self.a is None else f"{int(self.a * 255):02X}"})'
|
|
@@ -539,9 +532,7 @@ class hexa:
|
|
|
539
532
|
def dict(self) -> dict:
|
|
540
533
|
"""Returns the color components as a dictionary with hex string values for keys `'r'`, `'g'`, `'b'` and optionally `'a'`"""
|
|
541
534
|
return (
|
|
542
|
-
dict(r=f"{self.r:02X}", g=f"{self.g:02X}", b=f"{self.b:02X}")
|
|
543
|
-
if self.a is None
|
|
544
|
-
else dict(
|
|
535
|
+
dict(r=f"{self.r:02X}", g=f"{self.g:02X}", b=f"{self.b:02X}") if self.a is None else dict(
|
|
545
536
|
r=f"{self.r:02X}",
|
|
546
537
|
g=f"{self.g:02X}",
|
|
547
538
|
b=f"{self.b:02X}",
|
|
@@ -653,18 +644,14 @@ class Color:
|
|
|
653
644
|
elif isinstance(color, (list, tuple)):
|
|
654
645
|
if allow_alpha and Color.has_alpha(color):
|
|
655
646
|
return (
|
|
656
|
-
0 <= color[0] <= 255
|
|
657
|
-
and 0 <= color[1] <= 255
|
|
658
|
-
and 0 <= color[2] <= 255
|
|
647
|
+
0 <= color[0] <= 255 and 0 <= color[1] <= 255 and 0 <= color[2] <= 255
|
|
659
648
|
and (0 <= color[3] <= 1 or color[3] is None)
|
|
660
649
|
)
|
|
661
650
|
return 0 <= color[0] <= 255 and 0 <= color[1] <= 255 and 0 <= color[2] <= 255
|
|
662
651
|
elif isinstance(color, dict):
|
|
663
652
|
if allow_alpha and Color.has_alpha(color):
|
|
664
653
|
return (
|
|
665
|
-
0 <= color["r"] <= 255
|
|
666
|
-
and 0 <= color["g"] <= 255
|
|
667
|
-
and 0 <= color["b"] <= 255
|
|
654
|
+
0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
|
|
668
655
|
and (0 <= color["a"] <= 1 or color["a"] is None)
|
|
669
656
|
)
|
|
670
657
|
return 0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
|
|
@@ -682,9 +669,7 @@ class Color:
|
|
|
682
669
|
elif isinstance(color, (list, tuple)):
|
|
683
670
|
if allow_alpha and Color.has_alpha(color):
|
|
684
671
|
return (
|
|
685
|
-
0 <= color[0] <= 360
|
|
686
|
-
and 0 <= color[1] <= 100
|
|
687
|
-
and 0 <= color[2] <= 100
|
|
672
|
+
0 <= color[0] <= 360 and 0 <= color[1] <= 100 and 0 <= color[2] <= 100
|
|
688
673
|
and (0 <= color[3] <= 1 or color[3] is None)
|
|
689
674
|
)
|
|
690
675
|
else:
|
|
@@ -692,9 +677,7 @@ class Color:
|
|
|
692
677
|
elif isinstance(color, dict):
|
|
693
678
|
if allow_alpha and Color.has_alpha(color):
|
|
694
679
|
return (
|
|
695
|
-
0 <= color["h"] <= 360
|
|
696
|
-
and 0 <= color["s"] <= 100
|
|
697
|
-
and 0 <= color["l"] <= 100
|
|
680
|
+
0 <= color["h"] <= 360 and 0 <= color["s"] <= 100 and 0 <= color["l"] <= 100
|
|
698
681
|
and (0 <= color["a"] <= 1 or color["a"] is None)
|
|
699
682
|
)
|
|
700
683
|
else:
|
|
@@ -713,24 +696,17 @@ class Color:
|
|
|
713
696
|
is_valid = 0 <= color <= (0xFFFFFFFF if allow_alpha else 0xFFFFFF)
|
|
714
697
|
return (is_valid, "0x") if get_prefix else is_valid
|
|
715
698
|
elif isinstance(color, str):
|
|
716
|
-
color, prefix = (
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
)
|
|
721
|
-
return (
|
|
722
|
-
(bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color)), prefix)
|
|
723
|
-
if get_prefix
|
|
724
|
-
else bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color))
|
|
725
|
-
)
|
|
699
|
+
color, prefix = ((color[1:], "#") if color.startswith("#") else
|
|
700
|
+
(color[2:], "0x") if color.startswith("0x") else (color, None))
|
|
701
|
+
return ((bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color)),
|
|
702
|
+
prefix) if get_prefix else bool(_re.fullmatch(Regex.hexa_str(allow_alpha=allow_alpha), color)))
|
|
726
703
|
except Exception:
|
|
727
704
|
return (False, None) if get_prefix else False
|
|
728
705
|
|
|
729
706
|
@staticmethod
|
|
730
707
|
def is_valid(color: str | list | tuple | dict, allow_alpha: bool = True) -> bool:
|
|
731
708
|
return (
|
|
732
|
-
Color.is_valid_rgba(color, allow_alpha)
|
|
733
|
-
or Color.is_valid_hsla(color, allow_alpha)
|
|
709
|
+
Color.is_valid_rgba(color, allow_alpha) or Color.is_valid_hsla(color, allow_alpha)
|
|
734
710
|
or Color.is_valid_hexa(color, allow_alpha)
|
|
735
711
|
)
|
|
736
712
|
|
|
@@ -796,7 +772,7 @@ class Color:
|
|
|
796
772
|
raise ValueError(f"Invalid color format '{color}'")
|
|
797
773
|
|
|
798
774
|
@staticmethod
|
|
799
|
-
def str_to_rgba(string: str, only_first: bool = False) -> rgba | list[rgba]
|
|
775
|
+
def str_to_rgba(string: str, only_first: bool = False) -> Optional[rgba | list[rgba]]:
|
|
800
776
|
"""Will try to recognize RGBA colors inside a string and output the found ones as RGBA objects.\n
|
|
801
777
|
--------------------------------------------------------------------------------------------------
|
|
802
778
|
If `only_first` is `True` only the first found color will be returned (not as a list)."""
|
|
@@ -823,8 +799,7 @@ class Color:
|
|
|
823
799
|
int(m[2]),
|
|
824
800
|
((int(m[3]) if "." not in m[3] else float(m[3])) if m[3] else None),
|
|
825
801
|
_validate=False,
|
|
826
|
-
)
|
|
827
|
-
for m in matches
|
|
802
|
+
) for m in matches
|
|
828
803
|
]
|
|
829
804
|
|
|
830
805
|
@staticmethod
|
|
@@ -901,15 +876,15 @@ class Color:
|
|
|
901
876
|
if r < 0.03928:
|
|
902
877
|
r = r / 12.92
|
|
903
878
|
else:
|
|
904
|
-
r = ((r + 0.055) / 1.055)
|
|
879
|
+
r = ((r + 0.055) / 1.055)**2.4
|
|
905
880
|
if g < 0.03928:
|
|
906
881
|
g = g / 12.92
|
|
907
882
|
else:
|
|
908
|
-
g = ((g + 0.055) / 1.055)
|
|
883
|
+
g = ((g + 0.055) / 1.055)**2.4
|
|
909
884
|
if b < 0.03928:
|
|
910
885
|
b = b / 12.92
|
|
911
886
|
else:
|
|
912
|
-
b = ((b + 0.055) / 1.055)
|
|
887
|
+
b = ((b + 0.055) / 1.055)**2.4
|
|
913
888
|
l = 0.2126 * r + 0.7152 * g + 0.0722 * b
|
|
914
889
|
return round(l * 100) if isinstance(output_type, int) else round(l * 255) if output_type is None else l
|
|
915
890
|
|
|
@@ -918,11 +893,8 @@ class Color:
|
|
|
918
893
|
was_hexa, was_int = Color.is_valid_hexa(text_bg_color), isinstance(text_bg_color, int)
|
|
919
894
|
text_bg_color = Color.to_rgba(text_bg_color)
|
|
920
895
|
brightness = 0.2126 * text_bg_color[0] + 0.7152 * text_bg_color[1] + 0.0722 * text_bg_color[2]
|
|
921
|
-
return (
|
|
922
|
-
|
|
923
|
-
if brightness < 128
|
|
924
|
-
else ((0x000 if was_int else hexa("", 0, 0, 0)) if was_hexa else rgba(0, 0, 0, _validate=False))
|
|
925
|
-
)
|
|
896
|
+
return ((hexa("", 255, 255, 255) if was_hexa else rgba(255, 255, 255, _validate=False)) if brightness < 128 else
|
|
897
|
+
((0x000 if was_int else hexa("", 0, 0, 0)) if was_hexa else rgba(0, 0, 0, _validate=False)))
|
|
926
898
|
|
|
927
899
|
@staticmethod
|
|
928
900
|
def adjust_lightness(color: rgba | hexa, lightness_change: float) -> rgba | hexa:
|