xulbux 1.6.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/__init__.py +57 -0
- xulbux/_cli_.py +53 -0
- xulbux/_consts_.py +145 -0
- xulbux/xx_code.py +105 -0
- xulbux/xx_color.py +955 -0
- xulbux/xx_console.py +378 -0
- xulbux/xx_data.py +531 -0
- xulbux/xx_env_path.py +113 -0
- xulbux/xx_file.py +65 -0
- xulbux/xx_format_codes.py +305 -0
- xulbux/xx_json.py +106 -0
- xulbux/xx_path.py +107 -0
- xulbux/xx_regex.py +156 -0
- xulbux/xx_string.py +159 -0
- xulbux/xx_system.py +85 -0
- xulbux-1.6.1.dist-info/LICENSE +21 -0
- xulbux-1.6.1.dist-info/METADATA +110 -0
- xulbux-1.6.1.dist-info/RECORD +21 -0
- xulbux-1.6.1.dist-info/WHEEL +5 -0
- xulbux-1.6.1.dist-info/entry_points.txt +3 -0
- xulbux-1.6.1.dist-info/top_level.txt +1 -0
xulbux/xx_regex.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Really long regex code presets:
|
|
3
|
+
`quotes` match everything inside quotes
|
|
4
|
+
`brackets` match everything inside brackets
|
|
5
|
+
`outside_strings` match the pattern but not inside strings
|
|
6
|
+
`all_except` match everything except a certain pattern
|
|
7
|
+
`func_call` match a function call
|
|
8
|
+
`rgba_str` match an RGBA color
|
|
9
|
+
`hsla_str` match a HSLA color
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import re as _re
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class Regex:
|
|
16
|
+
|
|
17
|
+
@staticmethod
|
|
18
|
+
def quotes() -> str:
|
|
19
|
+
"""Matches everything inside quotes. (strings)\n
|
|
20
|
+
------------------------------------------------------------------------------------
|
|
21
|
+
Will create two named groups:
|
|
22
|
+
- `quote` the quote type (single or double)
|
|
23
|
+
- `string` everything inside the found quote pair\n
|
|
24
|
+
------------------------------------------------------------------------------------
|
|
25
|
+
Attention: Requires non standard library `regex` not standard library `re`!"""
|
|
26
|
+
return r'(?P<quote>[\'"])(?P<string>(?:\\.|(?!\g<quote>).)*?)\g<quote>'
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def brackets(bracket1: str = "(", bracket2: str = ")", is_group: bool = False) -> str:
|
|
30
|
+
"""Matches everything inside brackets, including other nested brackets.\n
|
|
31
|
+
------------------------------------------------------------------------------------
|
|
32
|
+
Attention: Requires non standard library `regex` not standard library `re`!"""
|
|
33
|
+
g, b1, b2 = (
|
|
34
|
+
"" if is_group else "?:",
|
|
35
|
+
_re.escape(bracket1) if len(bracket1) == 1 else bracket1,
|
|
36
|
+
_re.escape(bracket2) if len(bracket2) == 1 else bracket2,
|
|
37
|
+
)
|
|
38
|
+
return rf'{b1}\s*({g}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|{b1}(?:[^{b1}{b2}"\']|"(?:\\.|[^"\\])*"|\'(?:\\.|[^\'\\])*\'|(?R))*{b2})*)\s*{b2}'
|
|
39
|
+
|
|
40
|
+
@staticmethod
|
|
41
|
+
def outside_strings(pattern: str = r".*") -> str:
|
|
42
|
+
"""Matches the `pattern` only when it is not found inside a string (`'...'` or `"..."`)."""
|
|
43
|
+
return rf'(?<!["\'])(?:{pattern})(?!["\'])'
|
|
44
|
+
|
|
45
|
+
@staticmethod
|
|
46
|
+
def all_except(
|
|
47
|
+
disallowed_pattern: str,
|
|
48
|
+
ignore_pattern: str = "",
|
|
49
|
+
is_group: bool = False,
|
|
50
|
+
) -> 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'`)."""
|
|
56
|
+
return rf'({"" if is_group else "?:"}(?:(?!{ignore_pattern}).)*(?:(?!{Regex.outside_strings(disallowed_pattern)}).)*)'
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def func_call(func_name: str = None) -> str:
|
|
60
|
+
"""Match a function call
|
|
61
|
+
- `1` function name
|
|
62
|
+
- `2` the function's arguments\n
|
|
63
|
+
If no `func_name` is given, it will match any function call.\n
|
|
64
|
+
------------------------------------------------------------------------------------
|
|
65
|
+
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)
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def rgba_str(fix_sep: str = ",", allow_alpha: bool = True) -> str:
|
|
70
|
+
"""Matches an RGBA color inside a string.\n
|
|
71
|
+
----------------------------------------------------------------------------
|
|
72
|
+
The RGBA color can be in the formats (for `fix_sep = ','`):
|
|
73
|
+
- `rgba(r, g, b)`
|
|
74
|
+
- `rgba(r, g, b, a)` (if `allow_alpha=True`)
|
|
75
|
+
- `(r, g, b)`
|
|
76
|
+
- `(r, g, b, a)` (if `allow_alpha=True`)
|
|
77
|
+
- `r, g, b`
|
|
78
|
+
- `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)
|
|
84
|
+
- `a` 0-1 (float: opacity)\n
|
|
85
|
+
----------------------------------------------------------------------------
|
|
86
|
+
If the `fix_sep` is set to nothing, any char that is not a letter or number
|
|
87
|
+
can be used to separate the RGBA values, including just a space."""
|
|
88
|
+
if fix_sep in (None, ""):
|
|
89
|
+
fix_sep = r"[^0-9A-Z]"
|
|
90
|
+
else:
|
|
91
|
+
fix_sep = _re.escape(fix_sep)
|
|
92
|
+
rgb_part = rf"""((?:0*(?:25[0-5]|2[0-4][0-9]|1?[0-9]{{1,2}})))
|
|
93
|
+
(?:\s*{fix_sep}\s*)((?:0*(?:25[0-5]|2[0-4][0-9]|1?[0-9]{{1,2}})))
|
|
94
|
+
(?:\s*{fix_sep}\s*)((?:0*(?:25[0-5]|2[0-4][0-9]|1?[0-9]{{1,2}})))"""
|
|
95
|
+
return (
|
|
96
|
+
rf"""(?ix)
|
|
97
|
+
(?:rgb|rgba)?\s*(?:\(?\s*{rgb_part}
|
|
98
|
+
(?:(?:\s*{fix_sep}\s*)((?:0*(?:0?\.[0-9]+|1\.0+|[0-9]+\.[0-9]+|[0-9]+))))?
|
|
99
|
+
\s*\)?)"""
|
|
100
|
+
if allow_alpha
|
|
101
|
+
else rf"(?ix)(?:rgb|rgba)?\s*(?:\(?\s*{rgb_part}\s*\)?)"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def hsla_str(fix_sep: str = ",", allow_alpha: bool = True) -> str:
|
|
106
|
+
"""Matches a HSLA color inside a string.\n
|
|
107
|
+
----------------------------------------------------------------------------
|
|
108
|
+
The HSLA color can be in the formats (for `fix_sep = ','`):
|
|
109
|
+
- `hsla(h, s, l)`
|
|
110
|
+
- `hsla(h, s, l, a)` (if `allow_alpha=True`)
|
|
111
|
+
- `(h, s, l)`
|
|
112
|
+
- `(h, s, l, a)` (if `allow_alpha=True`)
|
|
113
|
+
- `h, s, l`
|
|
114
|
+
- `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)
|
|
120
|
+
- `a` 0-1 (float: opacity)\n
|
|
121
|
+
----------------------------------------------------------------------------
|
|
122
|
+
If the `fix_sep` is set to nothing, any char that is not a letter or number
|
|
123
|
+
can be used to separate the HSLA values, including just a space."""
|
|
124
|
+
if fix_sep in (None, ""):
|
|
125
|
+
fix_sep = r"[^0-9A-Z]"
|
|
126
|
+
else:
|
|
127
|
+
fix_sep = _re.escape(fix_sep)
|
|
128
|
+
hsl_part = rf"""((?:0*(?:360|3[0-5][0-9]|[12][0-9][0-9]|[1-9]?[0-9])))
|
|
129
|
+
(?:\s*{fix_sep}\s*)((?:0*(?:100|[1-9][0-9]|[0-9])))
|
|
130
|
+
(?:\s*{fix_sep}\s*)((?:0*(?:100|[1-9][0-9]|[0-9])))"""
|
|
131
|
+
return (
|
|
132
|
+
rf"""(?ix)
|
|
133
|
+
(?:hsl|hsla)?\s*(?:\(?\s*{hsl_part}
|
|
134
|
+
(?:(?:\s*{fix_sep}\s*)((?:0*(?:0?\.[0-9]+|1\.0+|[0-9]+\.[0-9]+|[0-9]+))))?
|
|
135
|
+
\s*\)?)"""
|
|
136
|
+
if allow_alpha
|
|
137
|
+
else rf"(?ix)(?:hsl|hsla)?\s*(?:\(?\s*{hsl_part}\s*\)?)"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
@staticmethod
|
|
141
|
+
def hexa_str(allow_alpha: bool = True) -> str:
|
|
142
|
+
"""Matches a HEXA color inside a string.\n
|
|
143
|
+
----------------------------------------------------------------------
|
|
144
|
+
The HEXA color can be in the formats (prefix `#`, `0x` or no prefix):
|
|
145
|
+
- `RGB`
|
|
146
|
+
- `RGBA` (if `allow_alpha=True`)
|
|
147
|
+
- `RRGGBB`
|
|
148
|
+
- `RRGGBBAA` (if `allow_alpha=True`)\n
|
|
149
|
+
----------------------------------------------------------------------
|
|
150
|
+
### Valid ranges:
|
|
151
|
+
each channel from 0-9 and A-F (case insensitive)"""
|
|
152
|
+
return (
|
|
153
|
+
r"(?i)^(?:#|0x)?[0-9A-F]{8}|[0-9A-F]{6}|[0-9A-F]{4}|[0-9A-F]{3}$"
|
|
154
|
+
if allow_alpha
|
|
155
|
+
else r"(?i)^(?:#|0x)?[0-9A-F]{6}|[0-9A-F]{3}$"
|
|
156
|
+
)
|
xulbux/xx_string.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import re as _re
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class String:
|
|
5
|
+
|
|
6
|
+
@staticmethod
|
|
7
|
+
def to_type(string: str) -> any:
|
|
8
|
+
"""Will convert a string to the found type."""
|
|
9
|
+
string = string.strip() # Clean up whitespace
|
|
10
|
+
# BOOLEAN
|
|
11
|
+
if _re.match(r"(?i)^(true|false)$", string):
|
|
12
|
+
return string.lower() == "true"
|
|
13
|
+
# NONE
|
|
14
|
+
elif _re.match(r"(?i)^(none|null|undefined)$", string):
|
|
15
|
+
return None
|
|
16
|
+
# INTEGER
|
|
17
|
+
elif _re.match(r"^-?\d+$", string):
|
|
18
|
+
return int(string)
|
|
19
|
+
# FLOAT
|
|
20
|
+
elif _re.match(r"^-?\d+\.\d+$", string):
|
|
21
|
+
return float(string)
|
|
22
|
+
# COMPLEX
|
|
23
|
+
elif _re.match(r"^(-?\d+(\.\d+)?[+-]\d+(\.\d+)?j)$", string):
|
|
24
|
+
return complex(string)
|
|
25
|
+
# QUOTED STRING
|
|
26
|
+
elif _re.match(r'^["\'](.*)["\']$', string):
|
|
27
|
+
return string[1:-1]
|
|
28
|
+
# BYTES
|
|
29
|
+
elif _re.match(r"^b['\"](.*)['\"]$", string):
|
|
30
|
+
return bytes(string[2:-1], "utf-8")
|
|
31
|
+
# LIST
|
|
32
|
+
elif _re.match(r"^\[(.*)\]$", string):
|
|
33
|
+
return [
|
|
34
|
+
String.to_type(item.strip()) for item in _re.findall(r"(?:[^,\[\]]+|\[.*?\]|\(.*?\)|\{.*?\})+", string[1:-1])
|
|
35
|
+
]
|
|
36
|
+
# TUPLE
|
|
37
|
+
elif _re.match(r"^\((.*)\)$", string):
|
|
38
|
+
return tuple(
|
|
39
|
+
String.to_type(item.strip()) for item in _re.findall(r"(?:[^,\(\)]+|\[.*?\]|\(.*?\)|\{.*?\})+", string[1:-1])
|
|
40
|
+
)
|
|
41
|
+
# DICTIONARY
|
|
42
|
+
elif _re.match(r"^\{(.*)\}$", string) and ":" in string:
|
|
43
|
+
return {
|
|
44
|
+
String.to_type(k.strip()): String.to_type(v.strip())
|
|
45
|
+
for k, v in _re.findall(
|
|
46
|
+
r"((?:[^:,{}]+|\[.*?\]|\(.*?\)|\{.*?\})+)\s*:\s*((?:[^:,{}]+|\[.*?\]|\(.*?\)|\{.*?\})+)", string[1:-1]
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
# SET
|
|
50
|
+
elif _re.match(r"^\{(.*?)\}$", string):
|
|
51
|
+
return {
|
|
52
|
+
String.to_type(item.strip()) for item in _re.findall(r"(?:[^,{}]+|\[.*?\]|\(.*?\)|\{.*?\})+", string[1:-1])
|
|
53
|
+
}
|
|
54
|
+
# RETURN AS IS (str)
|
|
55
|
+
return string
|
|
56
|
+
|
|
57
|
+
@staticmethod
|
|
58
|
+
def normalize_spaces(string: str, tab_spaces: int = 4) -> str:
|
|
59
|
+
"""Replaces all special space characters with normal spaces.
|
|
60
|
+
Also replaces tab characters with `tab_spaces` spaces."""
|
|
61
|
+
return (
|
|
62
|
+
string.replace("\t", " " * tab_spaces)
|
|
63
|
+
.replace("\u2000", " ")
|
|
64
|
+
.replace("\u2001", " ")
|
|
65
|
+
.replace("\u2002", " ")
|
|
66
|
+
.replace("\u2003", " ")
|
|
67
|
+
.replace("\u2004", " ")
|
|
68
|
+
.replace("\u2005", " ")
|
|
69
|
+
.replace("\u2006", " ")
|
|
70
|
+
.replace("\u2007", " ")
|
|
71
|
+
.replace("\u2008", " ")
|
|
72
|
+
.replace("\u2009", " ")
|
|
73
|
+
.replace("\u200A", " ")
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
@staticmethod
|
|
77
|
+
def escape(string: str, str_quotes: str = '"') -> str:
|
|
78
|
+
"""Escapes the special characters and quotes inside a string.\n
|
|
79
|
+
---------------------------------------------------------------------------
|
|
80
|
+
`str_quotes` can be either `"` or `'` and should match the quotes,
|
|
81
|
+
the string will be put inside of. So if your string will be `"string"`,
|
|
82
|
+
you should pass `"` to the parameter `str_quotes`.
|
|
83
|
+
That way, if the string includes the same quotes, they will be escaped."""
|
|
84
|
+
string = (
|
|
85
|
+
string.replace("\\", r"\\")
|
|
86
|
+
.replace("\n", r"\n")
|
|
87
|
+
.replace("\r", r"\r")
|
|
88
|
+
.replace("\t", r"\t")
|
|
89
|
+
.replace("\b", r"\b")
|
|
90
|
+
.replace("\f", r"\f")
|
|
91
|
+
.replace("\a", r"\a")
|
|
92
|
+
)
|
|
93
|
+
if str_quotes == '"':
|
|
94
|
+
string = string.replace(r"\\'", "'").replace(r'"', r"\"")
|
|
95
|
+
elif str_quotes == "'":
|
|
96
|
+
string = string.replace(r'\\"', '"').replace(r"'", r"\'")
|
|
97
|
+
return string
|
|
98
|
+
|
|
99
|
+
@staticmethod
|
|
100
|
+
def is_empty(string: str, spaces_are_empty: bool = False):
|
|
101
|
+
"""Returns `True` if the string is empty and `False` otherwise.\n
|
|
102
|
+
-------------------------------------------------------------------------------------------
|
|
103
|
+
If `spaces_are_empty` is true, it will also return `True` if the string is only spaces."""
|
|
104
|
+
return (string in (None, "")) or (spaces_are_empty and isinstance(string, str) and not string.strip())
|
|
105
|
+
|
|
106
|
+
@staticmethod
|
|
107
|
+
def single_char_repeats(string: str, char: str) -> int | bool:
|
|
108
|
+
"""- If the string consists of only the same `char`, it returns the number of times it is present.
|
|
109
|
+
- If the string doesn't consist of only the same character, it returns `False`."""
|
|
110
|
+
if len(string) == len(char) * string.count(char):
|
|
111
|
+
return string.count(char)
|
|
112
|
+
else:
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def decompose(case_string: str, seps: str = "-_", lower_all: bool = True) -> list[str]:
|
|
117
|
+
"""Will decompose the string (any type of casing, also mixed) into parts."""
|
|
118
|
+
return [
|
|
119
|
+
(part.lower() if lower_all else part)
|
|
120
|
+
for part in _re.split(rf"(?<=[a-z])(?=[A-Z])|[{_re.escape(seps)}]", case_string)
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
@staticmethod
|
|
124
|
+
def to_camel_case(string: str, upper: bool = True) -> str:
|
|
125
|
+
"""Will convert the string of any type of casing to `UpperCamelCase` or `lowerCamelCase` if `upper` is false."""
|
|
126
|
+
parts = String.decompose(string)
|
|
127
|
+
return ("" if upper else parts[0].lower()) + "".join(part.capitalize() for part in (parts if upper else parts[1:]))
|
|
128
|
+
|
|
129
|
+
@staticmethod
|
|
130
|
+
def to_delimited_case(string: str, delimiter: str = "_", screaming: bool = False) -> str:
|
|
131
|
+
"""Will convert the string of any type of casing to casing delimited by `delimiter`."""
|
|
132
|
+
return delimiter.join(part.upper() if screaming else part for part in String.decompose(string))
|
|
133
|
+
|
|
134
|
+
@staticmethod
|
|
135
|
+
def get_lines(string: str, remove_empty_lines: bool = False) -> list[str]:
|
|
136
|
+
"""Will split the string into lines."""
|
|
137
|
+
if not remove_empty_lines:
|
|
138
|
+
return string.splitlines()
|
|
139
|
+
lines = string.splitlines()
|
|
140
|
+
if not lines:
|
|
141
|
+
return []
|
|
142
|
+
non_empty_lines = [line for line in lines if line.strip()]
|
|
143
|
+
if not non_empty_lines:
|
|
144
|
+
return []
|
|
145
|
+
return non_empty_lines
|
|
146
|
+
|
|
147
|
+
@staticmethod
|
|
148
|
+
def remove_consecutive_empty_lines(string: str, max_consecutive: int = 0) -> str:
|
|
149
|
+
"""Will remove consecutive empty lines from the string.\n
|
|
150
|
+
--------------------------------------------------------------------------------------------
|
|
151
|
+
- If `max_consecutive` is `0`, it will remove all consecutive empty lines.
|
|
152
|
+
- If `max_consecutive` is bigger than `0`, it will only allow `max_consecutive` consecutive
|
|
153
|
+
empty lines and everything above it will be cut down to `max_consecutive` empty lines."""
|
|
154
|
+
return _re.sub(r"(\n\s*){2,}", r"\1" * (max_consecutive + 1), string)
|
|
155
|
+
|
|
156
|
+
@staticmethod
|
|
157
|
+
def split_count(string: str, count: int) -> list[str]:
|
|
158
|
+
"""Will split the string every `count` characters."""
|
|
159
|
+
return [string[i : i + count] for i in range(0, len(string), count)]
|
xulbux/xx_system.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import subprocess as _subprocess
|
|
2
|
+
import platform as _platform
|
|
3
|
+
import time as _time
|
|
4
|
+
import sys as _sys
|
|
5
|
+
import os as _os
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class System:
|
|
9
|
+
|
|
10
|
+
@staticmethod
|
|
11
|
+
def restart(
|
|
12
|
+
prompt: object = None,
|
|
13
|
+
wait: int = 0,
|
|
14
|
+
continue_program: bool = False,
|
|
15
|
+
force: bool = False,
|
|
16
|
+
) -> None:
|
|
17
|
+
"""Starts a system restart:
|
|
18
|
+
- `prompt` is the message to be displayed in the systems restart notification.
|
|
19
|
+
- `wait` is the time to wait until restarting in seconds.
|
|
20
|
+
- `continue_program` is whether to continue the current Python program after calling this function.
|
|
21
|
+
- `force` is whether to force a restart even if other processes are still running."""
|
|
22
|
+
system = _platform.system().lower()
|
|
23
|
+
if system == "windows":
|
|
24
|
+
if not force:
|
|
25
|
+
output = _subprocess.check_output("tasklist", shell=True).decode()
|
|
26
|
+
processes = [line.split()[0] for line in output.splitlines()[3:] if line.strip()]
|
|
27
|
+
if len(processes) > 2: # EXCLUDING THE PYTHON PROCESS AND CMD
|
|
28
|
+
raise RuntimeError("Processes are still running. Use the parameter `force=True` to restart anyway.")
|
|
29
|
+
if prompt:
|
|
30
|
+
_os.system(f'shutdown /r /t {wait} /c "{prompt}"')
|
|
31
|
+
else:
|
|
32
|
+
_os.system("shutdown /r /t 0")
|
|
33
|
+
if continue_program:
|
|
34
|
+
print(f"Restarting in {wait} seconds...")
|
|
35
|
+
_time.sleep(wait)
|
|
36
|
+
elif system in ("linux", "darwin"):
|
|
37
|
+
if not force:
|
|
38
|
+
output = _subprocess.check_output(["ps", "-A"]).decode()
|
|
39
|
+
processes = output.splitlines()[1:] # EXCLUDE HEADER
|
|
40
|
+
if len(processes) > 2: # EXCLUDING THE PYTHON PROCESS AND PS
|
|
41
|
+
raise RuntimeError("Processes are still running. Use the parameter `force=True` to restart anyway.")
|
|
42
|
+
if prompt:
|
|
43
|
+
_subprocess.Popen(["notify-send", "System Restart", prompt])
|
|
44
|
+
_time.sleep(wait)
|
|
45
|
+
try:
|
|
46
|
+
_subprocess.run(["sudo", "shutdown", "-r", "now"])
|
|
47
|
+
except _subprocess.CalledProcessError:
|
|
48
|
+
raise PermissionError("Failed to restart: insufficient privileges. Ensure sudo permissions are granted.")
|
|
49
|
+
if continue_program:
|
|
50
|
+
print(f"Restarting in {wait} seconds...")
|
|
51
|
+
_time.sleep(wait)
|
|
52
|
+
else:
|
|
53
|
+
raise NotImplementedError(f"Restart not implemented for `{system}`")
|
|
54
|
+
|
|
55
|
+
@staticmethod
|
|
56
|
+
def check_libs(
|
|
57
|
+
lib_names: list[str],
|
|
58
|
+
install_missing: bool = False,
|
|
59
|
+
confirm_install: bool = True,
|
|
60
|
+
) -> None | list[str]:
|
|
61
|
+
"""Checks if the given list of libraries are installed. If not:
|
|
62
|
+
- If `install_missing` is `False` the missing libraries will be returned as a list.
|
|
63
|
+
- If `install_missing` is `True` the missing libraries will be installed.
|
|
64
|
+
- If `confirm_install` is `True` the user will first be asked if they want to install the missing libraries."""
|
|
65
|
+
missing = []
|
|
66
|
+
for lib in lib_names:
|
|
67
|
+
try:
|
|
68
|
+
__import__(lib)
|
|
69
|
+
except ImportError:
|
|
70
|
+
missing.append(lib)
|
|
71
|
+
if not missing:
|
|
72
|
+
return None
|
|
73
|
+
elif not install_missing:
|
|
74
|
+
return missing
|
|
75
|
+
if confirm_install:
|
|
76
|
+
print("The following required libraries are missing:")
|
|
77
|
+
for lib in missing:
|
|
78
|
+
print(f"- {lib}")
|
|
79
|
+
if input("Do you want to install them now (Y/n): ").strip().lower() not in ("", "y", "yes"):
|
|
80
|
+
raise ImportError("Missing required libraries.")
|
|
81
|
+
try:
|
|
82
|
+
_subprocess.check_call([_sys.executable, "-m", "pip", "install"] + missing)
|
|
83
|
+
return None
|
|
84
|
+
except _subprocess.CalledProcessError:
|
|
85
|
+
return missing
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 XulbuX
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: xulbux
|
|
3
|
+
Version: 1.6.1
|
|
4
|
+
Summary: A library which includes a lot of really helpful functions.
|
|
5
|
+
Author-email: XulbuX <xulbux.real@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2024 XulbuX
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Bug Reports, https://github.com/XulbuX-dev/PythonLibraryXulbuX/issues
|
|
29
|
+
Project-URL: Changelog, https://github.com/XulbuX-dev/PythonLibraryXulbuX/blob/main/CHANGELOG.md
|
|
30
|
+
Project-URL: Documentation, https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki
|
|
31
|
+
Project-URL: Homepage, https://github.com/XulbuX-dev/PythonLibraryXulbuX
|
|
32
|
+
Project-URL: License, https://github.com/XulbuX-dev/PythonLibraryXulbuX/blob/main/LICENSE
|
|
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
|
|
35
|
+
Classifier: Intended Audience :: Developers
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
41
|
+
Classifier: Operating System :: OS Independent
|
|
42
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
43
|
+
Requires-Python: >=3.10.0
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
License-File: LICENSE
|
|
46
|
+
Requires-Dist: keyboard>=0.13.5
|
|
47
|
+
Requires-Dist: mouse>=0.7.1
|
|
48
|
+
Requires-Dist: pyperclip>=1.9.0
|
|
49
|
+
Requires-Dist: regex>=2023.10.3
|
|
50
|
+
Provides-Extra: dev
|
|
51
|
+
Requires-Dist: pytest>=7.4.2; extra == "dev"
|
|
52
|
+
Requires-Dist: black>=23.7.0; extra == "dev"
|
|
53
|
+
Requires-Dist: isort>=5.12.0; extra == "dev"
|
|
54
|
+
Requires-Dist: flake8>=6.1.0; extra == "dev"
|
|
55
|
+
|
|
56
|
+
# **$\color{#8085FF}\Huge\textsf{XulbuX}$**
|
|
57
|
+
|
|
58
|
+
**$\color{#8085FF}\textsf{XulbuX}$** is a library which includes a lot of really helpful classes, types and functions.
|
|
59
|
+
|
|
60
|
+
For precise information about the library, see the library's [Wiki page](https://github.com/XulbuX-dev/PythonLibraryXulbuX/wiki).<br>
|
|
61
|
+
For the libraries latest changes, see the [change log](https://github.com/XulbuX-dev/PythonLibraryXulbuX/blob/main/CHANGELOG.md).
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Installation
|
|
65
|
+
|
|
66
|
+
To install the library and all its dependencies, open a console and run the command:
|
|
67
|
+
```prolog
|
|
68
|
+
pip install xulbux
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
To upgrade the library to the latest available version, run the following command in your console:
|
|
72
|
+
```prolog
|
|
73
|
+
pip install --upgrade xulbux
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
Import the full library under the alias `xx`, so it's classes, types and functions are accessible with `xx.Class.method()`, `xx.type()` and `xx.function()`:
|
|
80
|
+
```python
|
|
81
|
+
import xulbux as xx
|
|
82
|
+
```
|
|
83
|
+
So you don't have to write `xx` in front of the library's types, you can import them directly:
|
|
84
|
+
```python
|
|
85
|
+
from xulbux import rgba, hsla, hexa
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# Modules
|
|
90
|
+
|
|
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`</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, ...*) |
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
<br>
|
|
108
|
+
|
|
109
|
+
--------------------------------------------------------------
|
|
110
|
+
[View this library on PyPI](https://pypi.org/project/XulbuX/)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
xulbux/__init__.py,sha256=ayM2Gomwlns0lEDdbUZ6uxtrDIQRb0ldSOyqguQ_ON8,1658
|
|
2
|
+
xulbux/_cli_.py,sha256=U25ZrtpQgpKXtvOSTBBbh7-AJ_WTeZ95A66DQARAqzo,3558
|
|
3
|
+
xulbux/_consts_.py,sha256=2-swueg8B5retfsAQqmR8nFNc06tqAwpL__TOv3V4kw,4882
|
|
4
|
+
xulbux/xx_code.py,sha256=yBP5WxCxNxjBiS6nVAmUBJpD0hX6fgnh5RWq-NmrnaY,5222
|
|
5
|
+
xulbux/xx_color.py,sha256=sRW0Fr8CFfM2EsUubEO74aLRTseCu5VulXyjqDcahEw,44895
|
|
6
|
+
xulbux/xx_console.py,sha256=ydDPYyGZ5OVHIkCiJO_eaAJI-8k97L5vQ7v1SoUUmWI,15436
|
|
7
|
+
xulbux/xx_data.py,sha256=OEKLbI1XeNTrittdz3s3mvQk8YrBoSovj9O1H-b7ArY,25844
|
|
8
|
+
xulbux/xx_env_path.py,sha256=5CvKpItzA4n8nvF7RwOmZwgs4erGltZqRJ3VD-9dFzo,4388
|
|
9
|
+
xulbux/xx_file.py,sha256=-58YnqKvrs5idIF91UzEki7o7qnskFvnQYkBaRrp7Vw,3122
|
|
10
|
+
xulbux/xx_format_codes.py,sha256=TkdHaiKXpZxVoUN6oEcsGXITgxrxzkghMCde2Kw-kQg,14806
|
|
11
|
+
xulbux/xx_json.py,sha256=q60lOj8Xg8c4L9cBu6SBZdJzFC7QbjDfFwcKKzBKj5w,5173
|
|
12
|
+
xulbux/xx_path.py,sha256=_xkH9cowPdi3nHw2q_TvN_i_5oG6GJut-QwPBLxnrAQ,4519
|
|
13
|
+
xulbux/xx_regex.py,sha256=zyxkS1bLlrSq26ErhO4UtrimIhW71_a7kox6ArCoK58,7670
|
|
14
|
+
xulbux/xx_string.py,sha256=Wa3qHxnk7AIpAVAn1vI_GBtkfYFwy4F_Xtj83ojEPKc,7168
|
|
15
|
+
xulbux/xx_system.py,sha256=Eyf4MbZpaHHKv71SOcM_EK0bvT4PGG0KLwAXx4m60vo,3918
|
|
16
|
+
xulbux-1.6.1.dist-info/LICENSE,sha256=6NflEcvzFEe8_JFVNCPVwZBwBhlLLd4vqQi8WiX_Xk4,1084
|
|
17
|
+
xulbux-1.6.1.dist-info/METADATA,sha256=NLrtou5gw1j1FQ3PLIsI09UCoowzZg7xtJzVl5l9mi0,6836
|
|
18
|
+
xulbux-1.6.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
19
|
+
xulbux-1.6.1.dist-info/entry_points.txt,sha256=a3womfLIMZKnOFiyy-xnVb4g2qkZsHR5FbKKkljcGns,94
|
|
20
|
+
xulbux-1.6.1.dist-info/top_level.txt,sha256=FkK4EZajwfP36fnlrPaR98OrEvZpvdEOdW1T5zTj6og,7
|
|
21
|
+
xulbux-1.6.1.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
xulbux
|