xulbux 1.6.8__tar.gz → 1.6.9__tar.gz

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.

Files changed (46) hide show
  1. {xulbux-1.6.8/src/xulbux.egg-info → xulbux-1.6.9}/PKG-INFO +18 -39
  2. {xulbux-1.6.8 → xulbux-1.6.9}/README.md +14 -14
  3. {xulbux-1.6.8 → xulbux-1.6.9}/pyproject.toml +11 -6
  4. xulbux-1.6.9/src/xulbux/__init__.py +25 -0
  5. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/_cli_.py +4 -4
  6. xulbux-1.6.9/src/xulbux/xx_code.py +115 -0
  7. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_color.py +91 -58
  8. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_console.py +98 -39
  9. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_data.py +60 -53
  10. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_env_path.py +0 -4
  11. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_file.py +22 -26
  12. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_format_codes.py +25 -8
  13. xulbux-1.6.9/src/xulbux/xx_json.py +158 -0
  14. xulbux-1.6.9/src/xulbux/xx_path.py +167 -0
  15. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_regex.py +5 -9
  16. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_string.py +4 -1
  17. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/xx_system.py +1 -5
  18. {xulbux-1.6.8 → xulbux-1.6.9/src/xulbux.egg-info}/PKG-INFO +18 -39
  19. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux.egg-info/SOURCES.txt +8 -3
  20. xulbux-1.6.9/tests/test_code.py +78 -0
  21. xulbux-1.6.9/tests/test_color.py +171 -0
  22. xulbux-1.6.9/tests/test_color_types.py +198 -0
  23. xulbux-1.6.9/tests/test_console.py +249 -0
  24. xulbux-1.6.9/tests/test_data.py +210 -0
  25. xulbux-1.6.9/tests/test_file.py +120 -0
  26. xulbux-1.6.9/tests/test_format_codes.py +62 -0
  27. xulbux-1.6.9/tests/test_json.py +202 -0
  28. xulbux-1.6.9/tests/test_path.py +160 -0
  29. xulbux-1.6.9/tests/test_string.py +160 -0
  30. xulbux-1.6.8/src/xulbux/__init__.py +0 -57
  31. xulbux-1.6.8/src/xulbux/xx_code.py +0 -99
  32. xulbux-1.6.8/src/xulbux/xx_json.py +0 -103
  33. xulbux-1.6.8/src/xulbux/xx_path.py +0 -117
  34. xulbux-1.6.8/tests/test_color.py +0 -18
  35. xulbux-1.6.8/tests/test_color_types.py +0 -103
  36. xulbux-1.6.8/tests/test_console_info.py +0 -37
  37. xulbux-1.6.8/tests/test_data.py +0 -51
  38. xulbux-1.6.8/tests/test_format_codes.py +0 -42
  39. {xulbux-1.6.8 → xulbux-1.6.9}/LICENSE +0 -0
  40. {xulbux-1.6.8 → xulbux-1.6.9}/setup.cfg +0 -0
  41. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux/_consts_.py +0 -0
  42. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux.egg-info/dependency_links.txt +0 -0
  43. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux.egg-info/entry_points.txt +0 -0
  44. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux.egg-info/requires.txt +0 -0
  45. {xulbux-1.6.8 → xulbux-1.6.9}/src/xulbux.egg-info/top_level.txt +0 -0
  46. /xulbux-1.6.8/tests/test_env_vars.py → /xulbux-1.6.9/tests/test_env_path.py +0 -0
@@ -1,30 +1,9 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: xulbux
3
- Version: 1.6.8
3
+ Version: 1.6.9
4
4
  Summary: A Python library which includes lots of helpful classes, types and functions aiming to make common programming tasks simpler.
5
5
  Author-email: XulbuX <xulbux.real@gmail.com>
6
- 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
-
6
+ License-Expression: MIT
28
7
  Project-URL: Bug Reports, https://github.com/XulbuX/PythonLibraryXulbuX/issues
29
8
  Project-URL: Changelog, https://github.com/XulbuX/PythonLibraryXulbuX/blob/main/CHANGELOG.md
30
9
  Project-URL: Documentation, https://github.com/XulbuX/PythonLibraryXulbuX/wiki
@@ -37,7 +16,6 @@ Classifier: Programming Language :: Python :: 3
37
16
  Classifier: Programming Language :: Python :: 3.10
38
17
  Classifier: Programming Language :: Python :: 3.11
39
18
  Classifier: Programming Language :: Python :: 3.12
40
- Classifier: License :: OSI Approved :: MIT License
41
19
  Classifier: Operating System :: OS Independent
42
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
43
21
  Requires-Python: >=3.10.0
@@ -54,6 +32,7 @@ Requires-Dist: black>=23.7.0; extra == "dev"
54
32
  Requires-Dist: isort>=5.12.0; extra == "dev"
55
33
  Requires-Dist: flake8>=6.1.0; extra == "dev"
56
34
  Requires-Dist: flake8-pyproject>=1.2.3; extra == "dev"
35
+ Dynamic: license-file
57
36
 
58
37
  # **$\color{#8085FF}\Huge\textsf{XulbuX}$**
59
38
 
@@ -102,20 +81,20 @@ from xulbux import rgba, hsla, hexa
102
81
 
103
82
  ## Modules
104
83
 
105
- | Module | Short Description |
106
- | :----------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------- |
107
- | <h3>[`xx_code`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code)</h3> | advanced code-string operations (*changing the indent, finding function calls, ...*) |
108
- | <h3>[`xx_color`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color)</h3> | everything around colors (*converting, blending, searching colors in strings, ...*) |
109
- | <h3>[`xx_console`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console)</h3> | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
110
- | <h3>[`xx_data`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data)</h3> | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
111
- | <h3>[`xx_env_path`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_env_path)</h3> | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
112
- | <h3>[`xx_file`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file)</h3> | advanced working with files (*create files, rename file-extensions, ...*) |
113
- | <h3>[`xx_format_codes`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_format_codes)</h3> | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
114
- | <h3>`xx_json`</h3> | advanced working with json files (*read, create, update, ...*) |
115
- | <h3>`xx_path`</h3> | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
116
- | <h3>`xx_regex`</h3> | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
117
- | <h3>[`xx_string`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string)</h3> | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
118
- | <h3>`xx_system`</h3> | advanced system actions (*restart with message, check installed Python libs, ...*) |
84
+ | Module | Short Description |
85
+ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |
86
+ | [![xx_code](https://img.shields.io/badge/xx__code-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code) | advanced code-string operations (*changing the indent, finding function calls, ...*) |
87
+ | [![xx_color](https://img.shields.io/badge/xx__color-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color) | everything around colors (*converting, blending, searching colors in strings, ...*) |
88
+ | [![xx_console](https://img.shields.io/badge/xx__console-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console) | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
89
+ | [![xx_data](https://img.shields.io/badge/xx__data-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data) | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
90
+ | [![xx_env_path](https://img.shields.io/badge/xx__env__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_env_path) | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
91
+ | [![xx_file](https://img.shields.io/badge/xx__file-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file) | advanced working with files (*create files, rename file-extensions, ...*) |
92
+ | [![xx_format_codes](https://img.shields.io/badge/xx__format__codes-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_format_codes) | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
93
+ | [![xx_json](https://img.shields.io/badge/xx__json-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_json) | advanced working with json files (*read, create, update, ...*) |
94
+ | [![xx_path](https://img.shields.io/badge/xx__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_path) | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
95
+ | ![xx_regex](https://img.shields.io/badge/xx__regex-6065FF?style=flat) | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
96
+ | [![xx_string](https://img.shields.io/badge/xx__string-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string) | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
97
+ | ![xx_system](https://img.shields.io/badge/xx__system-6065FF?style=flat) | advanced system actions (*restart with message, check installed Python libs, ...*) |
119
98
 
120
99
  <br>
121
100
 
@@ -45,20 +45,20 @@ from xulbux import rgba, hsla, hexa
45
45
 
46
46
  ## Modules
47
47
 
48
- | Module | Short Description |
49
- | :----------------------------------------------------------------------------------------------: | :------------------------------------------------------------------------------------------------- |
50
- | <h3>[`xx_code`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code)</h3> | advanced code-string operations (*changing the indent, finding function calls, ...*) |
51
- | <h3>[`xx_color`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color)</h3> | everything around colors (*converting, blending, searching colors in strings, ...*) |
52
- | <h3>[`xx_console`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console)</h3> | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
53
- | <h3>[`xx_data`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data)</h3> | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
54
- | <h3>[`xx_env_path`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_env_path)</h3> | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
55
- | <h3>[`xx_file`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file)</h3> | advanced working with files (*create files, rename file-extensions, ...*) |
56
- | <h3>[`xx_format_codes`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_format_codes)</h3> | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
57
- | <h3>`xx_json`</h3> | advanced working with json files (*read, create, update, ...*) |
58
- | <h3>`xx_path`</h3> | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
59
- | <h3>`xx_regex`</h3> | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
60
- | <h3>[`xx_string`](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string)</h3> | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
61
- | <h3>`xx_system`</h3> | advanced system actions (*restart with message, check installed Python libs, ...*) |
48
+ | Module | Short Description |
49
+ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------- |
50
+ | [![xx_code](https://img.shields.io/badge/xx__code-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_code) | advanced code-string operations (*changing the indent, finding function calls, ...*) |
51
+ | [![xx_color](https://img.shields.io/badge/xx__color-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_color) | everything around colors (*converting, blending, searching colors in strings, ...*) |
52
+ | [![xx_console](https://img.shields.io/badge/xx__console-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_console) | advanced actions related to the console (*pretty logging, advanced inputs, ...*) |
53
+ | [![xx_data](https://img.shields.io/badge/xx__data-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_data) | advanced operations with data structures (*compare, generate path ID's, pretty print/format, ...*) |
54
+ | [![xx_env_path](https://img.shields.io/badge/xx__env__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_env_path) | getting and editing the PATH variable (*get paths, check for paths, add paths, ...*) |
55
+ | [![xx_file](https://img.shields.io/badge/xx__file-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_file) | advanced working with files (*create files, rename file-extensions, ...*) |
56
+ | [![xx_format_codes](https://img.shields.io/badge/xx__format__codes-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_format_codes) | easy pretty printing with custom format codes (*print, inputs, custom format codes to ANSI, ...*) |
57
+ | [![xx_json](https://img.shields.io/badge/xx__json-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_json) | advanced working with json files (*read, create, update, ...*) |
58
+ | [![xx_path](https://img.shields.io/badge/xx__path-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_path) | advanced path operations (*get paths, smart-extend relative paths, delete paths, ...*) |
59
+ | ![xx_regex](https://img.shields.io/badge/xx__regex-6065FF?style=flat) | generated regex pattern-templates (*match bracket- and quote pairs, match colors, ...*) |
60
+ | [![xx_string](https://img.shields.io/badge/xx__string-6065FF?style=flat)](https://github.com/XulbuX/PythonLibraryXulbuX/wiki/xx_string) | helpful actions when working with strings. (*normalize, escape, decompose, ...*) |
61
+ | ![xx_system](https://img.shields.io/badge/xx__system-6065FF?style=flat) | advanced system actions (*restart with message, check installed Python libs, ...*) |
62
62
 
63
63
  <br>
64
64
 
@@ -4,11 +4,12 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "xulbux"
7
- version = "1.6.8"
7
+ version = "1.6.9"
8
8
  authors = [{ name = "XulbuX", email = "xulbux.real@gmail.com" }]
9
9
  description = "A Python library which includes lots of helpful classes, types and functions aiming to make common programming tasks simpler."
10
10
  readme = "README.md"
11
- license = { file = "LICENSE" }
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
12
13
  requires-python = ">=3.10.0"
13
14
  dependencies = [
14
15
  "keyboard>=0.13.5",
@@ -30,7 +31,6 @@ classifiers = [
30
31
  "Programming Language :: Python :: 3.10",
31
32
  "Programming Language :: Python :: 3.11",
32
33
  "Programming Language :: Python :: 3.12",
33
- "License :: OSI Approved :: MIT License",
34
34
  "Operating System :: OS Independent",
35
35
  "Topic :: Software Development :: Libraries :: Python Modules",
36
36
  ]
@@ -151,10 +151,15 @@ minversion = "7.0"
151
151
  addopts = "-ra -q"
152
152
  pythonpath = ["src"]
153
153
  testpaths = [
154
- "tests/test_console_info.py",
155
- "tests/test_color_types.py",
154
+ "tests/test_code.py",
156
155
  "tests/test_color.py",
156
+ "tests/test_color_types.py",
157
+ "tests/test_console.py",
157
158
  "tests/test_data.py",
158
- "tests/test_env_vars.py",
159
+ "tests/test_env_path.py",
160
+ "tests/test_file.py",
159
161
  "tests/test_format_codes.py",
162
+ "tests/test_json.py",
163
+ "tests/test_path.py",
164
+ "tests/test_string.py",
160
165
  ]
@@ -0,0 +1,25 @@
1
+ __version__ = "1.6.9"
2
+ __author__ = "XulbuX"
3
+ __email__ = "xulbux.real@gmail.com"
4
+ __license__ = "MIT"
5
+ __copyright__ = "Copyright (c) 2025 XulbuX"
6
+ __url__ = "https://github.com/XulbuX/PythonLibraryXulbuX"
7
+ __description__ = "A library which includes a lot of really helpful functions."
8
+ __all__ = [
9
+ "_consts_", "xx_code", "xx_color", "xx_console", "xx_data", "xx_env_path", "xx_file", "xx_format_codes", "xx_json",
10
+ "xx_path", "xx_regex", "xx_string", "xx_system"
11
+ ]
12
+
13
+ from ._consts_ import *
14
+ from .xx_code import *
15
+ from .xx_color import *
16
+ from .xx_console import *
17
+ from .xx_data import *
18
+ from .xx_env_path import *
19
+ from .xx_file import *
20
+ from .xx_format_codes import *
21
+ from .xx_json import *
22
+ from .xx_path import *
23
+ from .xx_regex import *
24
+ from .xx_string import *
25
+ from .xx_system import *
@@ -1,5 +1,5 @@
1
- from . import __version__
2
1
  from ._consts_ import COLOR
2
+ from . import __version__
3
3
  from .xx_format_codes import FormatCodes
4
4
  from .xx_console import Console
5
5
 
@@ -33,17 +33,17 @@ def help_command():
33
33
  [dim](•) [{color['class']}]rgba[{color['punctuators']}]/([i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]float[_|{color['punctuators']}])[*]
34
34
  [dim](•) [{color['class']}]hsla[{color['punctuators']}]/([i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]int[_|{color['punctuators']}],[i|{color['types']}]float[_|{color['punctuators']}])[*]
35
35
  [dim](•) [{color['class']}]hexa[{color['punctuators']}]/([i|{color['types']}]str[_|{color['punctuators']}]|[i|{color['types']}]int[_|{color['punctuators']}])[*]
36
+ [dim](•) CODE STRING OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Code[*]
37
+ [dim](•) WORKING WITH COLORS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Color[*]
38
+ [dim](•) CONSOLE LOG AND ACTIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Console[*]
36
39
  [dim](•) PATH OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Path[*]
37
40
  [dim](•) FILE OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]File[*]
38
41
  [dim](•) JSON FILE OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Json[*]
39
42
  [dim](•) SYSTEM ACTIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]System[*]
40
43
  [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
44
  [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
45
  [dim](•) DATA OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]Data[*]
45
46
  [dim](•) STRING OPERATIONS [{color['lib']}]xx[{color['punctuators']}].[{color['class']}]String[*]
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...)
@@ -0,0 +1,115 @@
1
+ from .xx_string import String
2
+ from .xx_regex import Regex
3
+ from .xx_data import Data
4
+
5
+ import regex as _rx
6
+
7
+
8
+ class Code:
9
+
10
+ @staticmethod
11
+ def add_indent(code: str, indent: int) -> str:
12
+ """Adds `indent` spaces at the beginning of each line."""
13
+ indented_lines = [" " * indent + line for line in code.splitlines()]
14
+ return "\n".join(indented_lines)
15
+
16
+ @staticmethod
17
+ def get_tab_spaces(code: str) -> int:
18
+ """Will try to get the amount of spaces used for indentation."""
19
+ code_lines = String.get_lines(code, remove_empty_lines=True)
20
+ indents = [len(line) - len(line.lstrip()) for line in code_lines]
21
+ non_zero_indents = [i for i in indents if i > 0]
22
+ return min(non_zero_indents) if non_zero_indents else 0
23
+
24
+ @staticmethod
25
+ def change_tab_size(code: str, new_tab_size: int, remove_empty_lines: bool = False) -> str:
26
+ """Replaces all tabs with `new_tab_size` spaces.\n
27
+ ----------------------------------------------------------------------------------
28
+ If `remove_empty_lines` is `True`, empty lines will be removed in the process."""
29
+ code_lines = String.get_lines(code, remove_empty_lines=True)
30
+ lines = code_lines if remove_empty_lines else String.get_lines(code)
31
+ tab_spaces = Code.get_tab_spaces(code)
32
+ if (tab_spaces == new_tab_size) or tab_spaces == 0:
33
+ if remove_empty_lines:
34
+ return "\n".join(code_lines)
35
+ return code
36
+ result = []
37
+ for line in lines:
38
+ stripped = line.lstrip()
39
+ indent_level = (len(line) - len(stripped)) // tab_spaces
40
+ new_indent = " " * (indent_level * new_tab_size)
41
+ result.append(new_indent + stripped)
42
+ return "\n".join(result)
43
+
44
+ @staticmethod
45
+ def get_func_calls(code: str) -> list:
46
+ """Will try to get all function calls and return them as a list."""
47
+ funcs = _rx.findall(r"(?i)" + Regex.func_call(), code)
48
+ nested_func_calls = []
49
+ for _, func_attrs in funcs:
50
+ nested_calls = _rx.findall(r"(?i)" + Regex.func_call(), func_attrs)
51
+ if nested_calls:
52
+ nested_func_calls.extend(nested_calls)
53
+ return Data.remove_duplicates(funcs + nested_func_calls)
54
+
55
+ @staticmethod
56
+ def is_js(code: str, funcs: list = ["__", "$t", "$lang"]) -> bool:
57
+ """Will check if the code is very likely to be JavaScript."""
58
+ if not code or len(code.strip()) < 3:
59
+ return False
60
+ for func in funcs:
61
+ if _rx.match(r"^[\s\n]*" + _rx.escape(func) + r"\([^\)]*\)[\s\n]*$", code):
62
+ return True
63
+ direct_js_patterns = [
64
+ r"^[\s\n]*\$\(['\"][^'\"]+['\"]\)\.[\w]+\([^\)]*\);?[\s\n]*$", # jQuery calls
65
+ r"^[\s\n]*\$\.[a-zA-Z]\w*\([^\)]*\);?[\s\n]*$", # $.ajax(), etc.
66
+ r"^[\s\n]*\(\s*function\s*\(\)\s*\{.*\}\s*\)\(\);?[\s\n]*$", # IIFE
67
+ r"^[\s\n]*document\.[a-zA-Z]\w*\([^\)]*\);?[\s\n]*$", # document.getElementById()
68
+ r"^[\s\n]*window\.[a-zA-Z]\w*\([^\)]*\);?[\s\n]*$", # window.alert()
69
+ r"^[\s\n]*console\.[a-zA-Z]\w*\([^\)]*\);?[\s\n]*$", # console.log()
70
+ ]
71
+ for pattern in direct_js_patterns:
72
+ if _rx.match(pattern, code):
73
+ return True
74
+ arrow_function_patterns = [
75
+ r"^[\s\n]*\b[\w_]+\s*=\s*\([^\)]*\)\s*=>\s*[^;{]*[;]?[\s\n]*$", # const x = (y) => y*2;
76
+ r"^[\s\n]*\b[\w_]+\s*=\s*[\w_]+\s*=>\s*[^;{]*[;]?[\s\n]*$", # const x = y => y*2;
77
+ r"^[\s\n]*\(\s*[\w_,\s]+\s*\)\s*=>\s*[^;{]*[;]?[\s\n]*$", # (x) => x*2
78
+ r"^[\s\n]*[\w_]+\s*=>\s*[^;{]*[;]?[\s\n]*$", # x => x*2
79
+ ]
80
+ for pattern in arrow_function_patterns:
81
+ if _rx.match(pattern, code):
82
+ return True
83
+ funcs_pattern = r"(" + "|".join(_rx.escape(f) for f in funcs) + r")" + Regex.brackets("()")
84
+ js_indicators = [(r"\b(var|let|const)\s+[\w_$]+", 2), # JS variable declarations
85
+ (r"\$[\w_$]+\s*=", 2), # jQuery-style variables
86
+ (r"\$[\w_$]+\s*\(", 2), # jQuery function calls
87
+ (r"\bfunction\s*[\w_$]*\s*\(", 2), # Function declarations
88
+ (r"[\w_$]+\s*=\s*function\s*\(", 2), # Function assignments
89
+ (r"\b[\w_$]+\s*=>\s*[\{\(]", 2), # Arrow functions
90
+ (r"\(function\s*\(\)\s*\{", 2), # IIFE pattern
91
+ (funcs_pattern, 2), # Custom predefined functions
92
+ (r"\b(true|false|null|undefined)\b", 1), # JS literals
93
+ (r"===|!==|\+\+|--|\|\||&&", 1.5), # JS-specific operators
94
+ (r"\bnew\s+[\w_$]+\s*\(", 1.5), # Object instantiation with new
95
+ (r"\b(document|window|console|Math|Array|Object|String|Number)\.", 2), # JS objects
96
+ (r"\basync\s+function|\bawait\b", 2), # Async/await
97
+ (r"\b(if|for|while|switch)\s*\([^)]*\)\s*\{", 1), # Control structures with braces
98
+ (r"\btry\s*\{[^}]*\}\s*catch\s*\(", 1.5), # Try-catch
99
+ (r";[\s\n]*$", 0.5), # Semicolon line endings
100
+ ]
101
+ js_score = 0
102
+ line_endings = [line.strip() for line in code.splitlines() if line.strip()]
103
+ semicolon_endings = sum(1 for line in line_endings if line.endswith(';'))
104
+ if semicolon_endings >= 1:
105
+ js_score += min(semicolon_endings, 2)
106
+ opening_braces = code.count('{')
107
+ closing_braces = code.count('}')
108
+ if opening_braces > 0 and opening_braces == closing_braces:
109
+ js_score += 1
110
+ for pattern, score in js_indicators:
111
+ regex = _rx.compile(pattern, _rx.IGNORECASE)
112
+ matches = regex.findall(code)
113
+ if matches:
114
+ js_score += len(matches) * score
115
+ return js_score >= 2
@@ -97,12 +97,7 @@ class rgba:
97
97
  def __eq__(self, other: "rgba") -> bool:
98
98
  if not isinstance(other, rgba):
99
99
  return False
100
- return (self.r, self.g, self.b, self.a) == (
101
- other[0],
102
- other[1],
103
- other[2],
104
- other[3],
105
- )
100
+ return (self.r, self.g, self.b, self.a) == (other.r, other.g, other.b, other.a)
106
101
 
107
102
  def dict(self) -> dict:
108
103
  """Returns the color components as a dictionary with keys `'r'`, `'g'`, `'b'` and optionally `'a'`"""
@@ -156,9 +151,15 @@ class rgba:
156
151
  self.a = 1 - self.a
157
152
  return rgba(self.r, self.g, self.b, self.a, _validate=False)
158
153
 
159
- def grayscale(self) -> "rgba":
160
- """Converts the color to grayscale using the luminance formula"""
161
- self.r = self.g = self.b = Color.luminance(self.r, self.g, self.b)
154
+ def grayscale(self, method: str = "wcag2") -> "rgba":
155
+ """Converts the color to grayscale using the luminance formula.\n
156
+ ------------------------------------------------------------------
157
+ The `method` is the luminance calculation method to use:
158
+ - `"wcag2"` WCAG 2.0 standard (default and most accurate for perception)
159
+ - `"wcag3"` Draft WCAG 3.0 standard with improved coefficients
160
+ - `"simple"` Simple arithmetic mean (less accurate)
161
+ - `"bt601"` ITU-R BT.601 standard (older TV standard)"""
162
+ self.r = self.g = self.b = Color.luminance(self.r, self.g, self.b, method=method)
162
163
  return rgba(self.r, self.g, self.b, self.a, _validate=False)
163
164
 
164
165
  def blend(self, other: "rgba", ratio: float = 0.5, additive_alpha: bool = False) -> "rgba":
@@ -286,20 +287,15 @@ class hsla:
286
287
  return ((self.h, self.s, self.l) + (() if self.a is None else (self.a, )))[index]
287
288
 
288
289
  def __repr__(self) -> str:
289
- return f'hsla({self.h}, {self.s}, {self.l}{"" if self.a is None else f", {self.a}"})'
290
+ return f'hsla({self.h}°, {self.s}%, {self.l}%{"" if self.a is None else f", {self.a}"})'
290
291
 
291
292
  def __str__(self) -> str:
292
- return f'({self.h}, {self.s}, {self.l}{"" if self.a is None else f", {self.a}"})'
293
+ return f'({self.h}°, {self.s}%, {self.l}%{"" if self.a is None else f", {self.a}"})'
293
294
 
294
295
  def __eq__(self, other: "hsla") -> bool:
295
296
  if not isinstance(other, hsla):
296
297
  return False
297
- return (self.h, self.s, self.l, self.a) == (
298
- other[0],
299
- other[1],
300
- other[2],
301
- other[3],
302
- )
298
+ return (self.h, self.s, self.l, self.a) == (other.h, other.s, other.l, other.a)
303
299
 
304
300
  def dict(self) -> dict:
305
301
  """Returns the color components as a dictionary with keys `'h'`, `'s'`, `'l'` and optionally `'a'`"""
@@ -363,9 +359,15 @@ class hsla:
363
359
  self.a = 1 - self.a
364
360
  return hsla(self.h, self.s, self.l, self.a, _validate=False)
365
361
 
366
- def grayscale(self) -> "hsla":
367
- """Converts the color to grayscale using the luminance formula"""
368
- l = Color.luminance(*self._hsl_to_rgb(self.h, self.s, self.l))
362
+ def grayscale(self, method: str = "wcag2") -> "hsla":
363
+ """Converts the color to grayscale using the luminance formula.\n
364
+ ------------------------------------------------------------------
365
+ The `method` is the luminance calculation method to use:
366
+ - `"wcag2"` WCAG 2.0 standard (default and most accurate for perception)
367
+ - `"wcag3"` Draft WCAG 3.0 standard with improved coefficients
368
+ - `"simple"` Simple arithmetic mean (less accurate)
369
+ - `"bt601"` ITU-R BT.601 standard (older TV standard)"""
370
+ l = Color.luminance(*self._hsl_to_rgb(self.h, self.s, self.l), method=method)
369
371
  self.h, self.s, self.l, _ = rgba(l, l, l, _validate=False).to_hsla().values()
370
372
  return hsla(self.h, self.s, self.l, self.a, _validate=False)
371
373
 
@@ -520,14 +522,10 @@ class hexa:
520
522
  return f'#{self.r:02X}{self.g:02X}{self.b:02X}{"" if self.a is None else f"{int(self.a * 255):02X}"}'
521
523
 
522
524
  def __eq__(self, other: "hexa") -> bool:
525
+ """Returns whether the other color is equal to this one."""
523
526
  if not isinstance(other, hexa):
524
527
  return False
525
- return (self.r, self.g, self.b, self.a) == (
526
- other[0],
527
- other[1],
528
- other[2],
529
- other[3],
530
- )
528
+ return (self.r, self.g, self.b, self.a) == (other.r, other.g, other.b, other.a)
531
529
 
532
530
  def dict(self) -> dict:
533
531
  """Returns the color components as a dictionary with hex string values for keys `'r'`, `'g'`, `'b'` and optionally `'a'`"""
@@ -540,9 +538,9 @@ class hexa:
540
538
  )
541
539
  )
542
540
 
543
- def values(self) -> tuple:
541
+ def values(self, round_alpha: bool = True) -> tuple:
544
542
  """Returns the color components as separate values `r, g, b, a`"""
545
- return self.r, self.g, self.b, self.a
543
+ return self.r, self.g, self.b, None if self.a is None else (round(self.a, 2) if round_alpha else self.a)
546
544
 
547
545
  def to_rgba(self, round_alpha: bool = True) -> "rgba":
548
546
  """Returns the color as a `rgba()` color"""
@@ -594,9 +592,15 @@ class hexa:
594
592
  self.a = 1 - self.a
595
593
  return hexa("", self.r, self.g, self.b, self.a)
596
594
 
597
- def grayscale(self) -> "hexa":
598
- """Converts the color to grayscale using the luminance formula"""
599
- self.r = self.g = self.b = Color.luminance(self.r, self.g, self.b)
595
+ def grayscale(self, method: str = "wcag2") -> "hexa":
596
+ """Converts the color to grayscale using the luminance formula.\n
597
+ ------------------------------------------------------------------
598
+ The `method` is the luminance calculation method to use:
599
+ - `"wcag2"` WCAG 2.0 standard (default and most accurate for perception)
600
+ - `"wcag3"` Draft WCAG 3.0 standard with improved coefficients
601
+ - `"simple"` Simple arithmetic mean (less accurate)
602
+ - `"bt601"` ITU-R BT.601 standard (older TV standard)"""
603
+ self.r = self.g = self.b = Color.luminance(self.r, self.g, self.b, method=method)
600
604
  return hexa("", self.r, self.g, self.b, self.a)
601
605
 
602
606
  def blend(self, other: "hexa", ratio: float = 0.5, additive_alpha: bool = False) -> "rgba":
@@ -647,14 +651,20 @@ class Color:
647
651
  0 <= color[0] <= 255 and 0 <= color[1] <= 255 and 0 <= color[2] <= 255
648
652
  and (0 <= color[3] <= 1 or color[3] is None)
649
653
  )
650
- return 0 <= color[0] <= 255 and 0 <= color[1] <= 255 and 0 <= color[2] <= 255
654
+ elif len(color) == 3:
655
+ return 0 <= color[0] <= 255 and 0 <= color[1] <= 255 and 0 <= color[2] <= 255
656
+ else:
657
+ return False
651
658
  elif isinstance(color, dict):
652
659
  if allow_alpha and Color.has_alpha(color):
653
660
  return (
654
661
  0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
655
662
  and (0 <= color["a"] <= 1 or color["a"] is None)
656
663
  )
657
- return 0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
664
+ elif len(color) == 3:
665
+ return 0 <= color["r"] <= 255 and 0 <= color["g"] <= 255 and 0 <= color["b"] <= 255
666
+ else:
667
+ return False
658
668
  elif isinstance(color, str):
659
669
  return bool(_re.fullmatch(Regex.rgba_str(allow_alpha=allow_alpha), color))
660
670
  return False
@@ -672,16 +682,20 @@ class Color:
672
682
  0 <= color[0] <= 360 and 0 <= color[1] <= 100 and 0 <= color[2] <= 100
673
683
  and (0 <= color[3] <= 1 or color[3] is None)
674
684
  )
675
- else:
685
+ elif len(color) == 3:
676
686
  return 0 <= color[0] <= 360 and 0 <= color[1] <= 100 and 0 <= color[2] <= 100
687
+ else:
688
+ return False
677
689
  elif isinstance(color, dict):
678
690
  if allow_alpha and Color.has_alpha(color):
679
691
  return (
680
692
  0 <= color["h"] <= 360 and 0 <= color["s"] <= 100 and 0 <= color["l"] <= 100
681
693
  and (0 <= color["a"] <= 1 or color["a"] is None)
682
694
  )
683
- else:
695
+ elif len(color) == 3:
684
696
  return 0 <= color["h"] <= 360 and 0 <= color["s"] <= 100 and 0 <= color["l"] <= 100
697
+ else:
698
+ return False
685
699
  elif isinstance(color, str):
686
700
  return bool(_re.fullmatch(Regex.hsla_str(allow_alpha=allow_alpha), color))
687
701
  except Exception:
@@ -691,9 +705,9 @@ class Color:
691
705
  def is_valid_hexa(color: str | int, allow_alpha: bool = True, get_prefix: bool = False) -> bool | tuple[bool, str]:
692
706
  try:
693
707
  if isinstance(color, hexa):
694
- return (True, "#")
708
+ return (True, "#") if get_prefix else True
695
709
  elif isinstance(color, int):
696
- is_valid = 0 <= color <= (0xFFFFFFFF if allow_alpha else 0xFFFFFF)
710
+ is_valid = 0x000000 <= color <= (0xFFFFFFFF if allow_alpha else 0xFFFFFF)
697
711
  return (is_valid, "0x") if get_prefix else is_valid
698
712
  elif isinstance(color, str):
699
713
  color, prefix = ((color[1:], "#") if color.startswith("#") else
@@ -705,7 +719,7 @@ class Color:
705
719
 
706
720
  @staticmethod
707
721
  def is_valid(color: str | list | tuple | dict, allow_alpha: bool = True) -> bool:
708
- return (
722
+ return bool(
709
723
  Color.is_valid_rgba(color, allow_alpha) or Color.is_valid_hsla(color, allow_alpha)
710
724
  or Color.is_valid_hexa(color, allow_alpha)
711
725
  )
@@ -777,7 +791,7 @@ class Color:
777
791
  --------------------------------------------------------------------------------------------------
778
792
  If `only_first` is `True` only the first found color will be returned (not as a list)."""
779
793
  if only_first:
780
- match = _re.search(Regex.rgb_str(allow_alpha=True), string)
794
+ match = _re.search(Regex.rgba_str(allow_alpha=True), string)
781
795
  if not match:
782
796
  return None
783
797
  m = match.groups()
@@ -789,7 +803,7 @@ class Color:
789
803
  _validate=False,
790
804
  )
791
805
  else:
792
- matches = _re.findall(Regex.rgb_str(allow_alpha=True), string)
806
+ matches = _re.findall(Regex.rgba_str(allow_alpha=True), string)
793
807
  if not matches:
794
808
  return None
795
809
  return [
@@ -865,28 +879,47 @@ class Color:
865
879
  raise ValueError(f"Invalid HEX integer '0x{hex_str}': expected in range [0x000000, 0xFFFFFF]")
866
880
 
867
881
  @staticmethod
868
- def luminance(r: int, g: int, b: int, output_type: type = None) -> int | float:
869
- """Gets the colors luminance using the luminance formula.\n
870
- ------------------------------------------------------------
871
- The param `output_type` can be set to:
872
- - `int` =⠀integer in [0, 100]
873
- - `float` =⠀float in [0.0, 1.0]
874
- - `None` =⠀integer in [0, 255]"""
882
+ def luminance(r: int, g: int, b: int, output_type: type = None, method: str = "wcag2") -> int | float:
883
+ """Calculates the relative luminance of a color according to various standards.\n
884
+ ----------------------------------------------------------------------------------
885
+ The `output_type` controls the range of the returned luminance value:
886
+ - `int` returns integer in [0, 100]
887
+ - `float` returns float in [0.0, 1.0]
888
+ - `None` returns integer in [0, 255]\n
889
+ The `method` is the luminance calculation method to use:
890
+ - `"wcag2"` WCAG 2.0 standard (default and most accurate for perception)
891
+ - `"wcag3"` Draft WCAG 3.0 standard with improved coefficients
892
+ - `"simple"` Simple arithmetic mean (less accurate)
893
+ - `"bt601"` ITU-R BT.601 standard (older TV standard)"""
875
894
  r, g, b = r / 255.0, g / 255.0, b / 255.0
876
- if r < 0.03928:
877
- r = r / 12.92
895
+ if method == "simple":
896
+ luminance = (r + g + b) / 3
897
+ elif method == "bt601":
898
+ luminance = 0.299 * r + 0.587 * g + 0.114 * b
899
+ elif method == "wcag3":
900
+ r = Color._linearize_srgb(r)
901
+ g = Color._linearize_srgb(g)
902
+ b = Color._linearize_srgb(b)
903
+ luminance = 0.2126729 * r + 0.7151522 * g + 0.0721750 * b
878
904
  else:
879
- r = ((r + 0.055) / 1.055)**2.4
880
- if g < 0.03928:
881
- g = g / 12.92
905
+ r = Color._linearize_srgb(r)
906
+ g = Color._linearize_srgb(g)
907
+ b = Color._linearize_srgb(b)
908
+ luminance = 0.2126 * r + 0.7152 * g + 0.0722 * b
909
+ if output_type == int:
910
+ return round(luminance * 100)
911
+ elif output_type == float:
912
+ return luminance
882
913
  else:
883
- g = ((g + 0.055) / 1.055)**2.4
884
- if b < 0.03928:
885
- b = b / 12.92
914
+ return round(luminance * 255)
915
+
916
+ @staticmethod
917
+ def _linearize_srgb(c: float) -> float:
918
+ """Helper method to linearize sRGB component following the WCAG standard."""
919
+ if c <= 0.03928:
920
+ return c / 12.92
886
921
  else:
887
- b = ((b + 0.055) / 1.055)**2.4
888
- l = 0.2126 * r + 0.7152 * g + 0.0722 * b
889
- return round(l * 100) if isinstance(output_type, int) else round(l * 255) if output_type is None else l
922
+ return ((c + 0.055) / 1.055)**2.4
890
923
 
891
924
  @staticmethod
892
925
  def text_color_for_on_bg(text_bg_color: rgba | hexa) -> rgba | hexa: