yta-colors 0.0.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.
yta_colors/__init__.py ADDED
@@ -0,0 +1,198 @@
1
+ from yta_colors.converter import ColorConverter
2
+ from yta_colors.utils import parse_color
3
+ from yta_validation import PythonValidator
4
+ from typing import Union
5
+
6
+
7
+ class Color:
8
+ """
9
+ Class that represents a color, stored as RGBA, makes
10
+ easy the way we interact with color and provide them as
11
+ parameters and simplify the color conversion. The color
12
+ is stored as a not-normalized color, but values can be
13
+ normalized through the methods that allow it (those
14
+ including the 'normalized' bool parameter).
15
+
16
+ Any attribute has to be initialized with a value between
17
+ 0 and 255. Alpha as 255 means full opaque.
18
+
19
+ TODO: Please confirm alpha 255 is opaque.
20
+ """
21
+
22
+ r: int
23
+ """
24
+ Red color, from 0 to 255, where 0 is no value and 255
25
+ is everything.
26
+ """
27
+ g: int
28
+ """
29
+ Green color, from 0 to 255, where 0 is no value and 255
30
+ is everything.
31
+ """
32
+ b: int
33
+ """
34
+ Blue color, from 0 to 255, where 0 is no value and 255
35
+ is everything.
36
+ """
37
+ a: int
38
+ """
39
+ Alpha (transparency), from 0 to 255, where 0 is no
40
+ value and 255 is everything.
41
+ """
42
+
43
+ def __init__(self, r, g, b, a):
44
+ self.r, self.g, self.b, self.a = r, g, b, a
45
+ # TODO: Precalculate and store all the values
46
+ # internally so we don't need to calculate them
47
+ # later (?)
48
+
49
+ @property
50
+ def rgb_not_normalized(self):
51
+ """
52
+ Get the color as a tuple of the 3 RGB values that
53
+ are, in order: red, green, blue. These values are
54
+ not normalized, so each value is in the interval
55
+ [0, 255].
56
+ """
57
+ return self.r, self.g, self.b
58
+
59
+ @property
60
+ def rgb_normalized(self):
61
+ """
62
+ Get the color as a tuple of the 3 RGB values that
63
+ are, in order: red, green, blue. These values are
64
+ normalized, so each value is in the interval [0, 1].
65
+ """
66
+ return self.r / 255.0, self.g / 255.0, self.b / 255.0
67
+
68
+ @property
69
+ def rgba_not_normalized(self):
70
+ """
71
+ Get the color as a tuple of the 3 RGB values and
72
+ a 4th value representing the transparency, that
73
+ are, in order: red, green, blue, alpha. These
74
+ values are not normalized, so each value is in
75
+ the interval [0, 255].
76
+ """
77
+ self.r, self.g, self.b, self.a
78
+
79
+ @property
80
+ def rgba_normalized(self):
81
+ """
82
+ Get the color as a tuple of the 3 RGB values and
83
+ a 4th value representing the transparency, that
84
+ are, in order: red, green, blue, alpha. These
85
+ values are normalized, so each value is in the
86
+ interval [0, 1].
87
+ """
88
+ return self.r / 255.0, self.g / 255.0, self.b / 255.0, self.a / 255.0
89
+
90
+ @property
91
+ def rgb_array_not_normalized(self):
92
+ """
93
+ Get the color as an array of the 3 RGB values that
94
+ are, in order: red, green, blue. These values are
95
+ not normalized, so each value is in the interval
96
+ [0, 255].
97
+ """
98
+ return [*self.rgba_not_normalized]
99
+
100
+ @property
101
+ def rgb_array_normalized(self):
102
+ """
103
+ Get the color as an array of the 3 RGB values that
104
+ are, in order: red, green, blue. These values are
105
+ normalized, so each value is in the interval [0, 1].
106
+ """
107
+ return [*self.rgba_normalized]
108
+
109
+ @property
110
+ def rgba_array_not_normalized(self):
111
+ """
112
+ Get the color as an array of the 3 RGB values and
113
+ a 4th value representing the transparency, that
114
+ are, in order: red, green, blue, alpha. These
115
+ values are not normalized, so each value is in
116
+ the interval [0, 255].
117
+ """
118
+ return [*self.rgba_not_normalized]
119
+
120
+ @property
121
+ def rgba_array_normalized(self):
122
+ """
123
+ Get the color as an array of the 3 RGB values and
124
+ a 4th value representing the transparency, that
125
+ are, in order: red, green, blue, alpha. These
126
+ values are normalized, so each value is in the
127
+ interval [0, 1].
128
+ """
129
+ return [*self.rgba_normalized]
130
+
131
+ @property
132
+ def hex_with_alpha(self):
133
+ """
134
+ Get the color as a string representing it in
135
+ hexadecimal value. The result will be #RRGGBBAA
136
+ because it includes the alpha value in the last
137
+ position.
138
+ """
139
+ return ColorConverter.rgba_to_hex(self.rgba_not_normalized, True)
140
+
141
+ @property
142
+ def hex_without_alpha(self):
143
+ """
144
+ Get the color as a string representing it in
145
+ hexadecimal value. The result will be #RRGGBB
146
+ because it doesn't include the alpha value.
147
+ """
148
+ return ColorConverter.rgba_to_hex(self.rgba_not_normalized, False)
149
+
150
+ @property
151
+ def hsl(self):
152
+ """
153
+ Get the color as an HSL color.
154
+ """
155
+ return ColorConverter.rgba_to_hsl(self.rgba_not_normalized)
156
+
157
+ @property
158
+ def cymk(self):
159
+ """
160
+ Get the color as an CYMK color.
161
+ """
162
+ return ColorConverter.rgba_to_cymk(self.rgba_not_normalized)
163
+
164
+ @property
165
+ def hsv(self):
166
+ """
167
+ Get the color as a HSV color.
168
+ """
169
+ return ColorConverter.rgba_to_hsv(self.rgba_not_normalized)
170
+
171
+ # TODO: Use the cv2 library to make other changes
172
+ @staticmethod
173
+ def parse(color: Union[list, tuple, str, 'ColorString', 'Color']):
174
+ """
175
+ Parse the provided 'color' parameter and return the
176
+ color as r,g,b,a values or raises an Exception if it
177
+ is not a valid and parseable color.
178
+
179
+ This method accepts string colors (if names are
180
+ registered in our system), hexadecimal colors (than
181
+ can also include alpha value), RGB array or tuples
182
+ (that can be normalized, with float values between
183
+ 0.0 and 1.0, or not normalized, with int values
184
+ between 0 and 255), or RGBA array or tuples, similar
185
+ to RGB but including a 4h alpha value.
186
+ """
187
+ # TODO: Work on this method to accept other arguments as
188
+ # I've been working on the 'parse_hexadecimal_color'
189
+ # method which is in the 'utils.py' file.
190
+ if PythonValidator.is_instance(color, Color):
191
+ return color
192
+
193
+ color = parse_color(color)
194
+
195
+ if color is None:
196
+ raise Exception(f'The provided "color" parameter is not parseable.')
197
+
198
+ return Color(*color)
@@ -0,0 +1,152 @@
1
+ from yta_colors.utils import is_hexadecimal_color, parse_rgba_color, rgba_to_hex, hex_to_rgba, rgb_to_hex, rgba_to_hex, rgb_to_hsl, rgb_to_cymk, rgb_to_hsv, hsv_to_rgb, rgba_to_hsv, parse_color, hsv_to_rgba
2
+ from yta_validation import PythonValidator
3
+ from typing import Union
4
+
5
+
6
+ class ColorConverter:
7
+ """
8
+ Class to simplify and encapsulate the functionality
9
+ related to color conversion.
10
+ """
11
+
12
+ @staticmethod
13
+ def rgb_to_hex(red, green, blue):
14
+ """
15
+ Returns the provided RGB color as a hex color. The 'red', 'green' and
16
+ 'blue' parameters must be between 0 and 255.
17
+ """
18
+ return rgba_to_hex(red, green, blue)
19
+
20
+ @staticmethod
21
+ def hex_to_rgb(color: str):
22
+ """
23
+ Parse the provided hexadecimal 'color' parameter and
24
+ turn it into an RGB color (returned as r,g,b) or
25
+ raises an Exception if not.
26
+ """
27
+ r, g, b, _ = ColorConverter.hex_to_rgba(color)
28
+
29
+ return r, g, b
30
+
31
+ @staticmethod
32
+ def hex_to_rgba(color: str):
33
+ if not is_hexadecimal_color(color):
34
+ raise Exception(f'The provided "color" parameter "{str(color)}" is not an hexadecimal color.')
35
+
36
+ return hex_to_rgba(color)
37
+
38
+ @staticmethod
39
+ def rgb_to_hex(color: Union[tuple, list], do_include_alpha: bool = False):
40
+ """
41
+ Parse the provided RGB 'color' parameter and turn it to
42
+ a hexadecimal color if valid or raises an Exception if
43
+ not. The result will be #RRGGBB if 'do_include_alpha' is
44
+ False, or #RRGGBBAA if 'do_include_alpha' is True.
45
+ """
46
+ validate_color(color)
47
+
48
+ return rgb_to_hex(color, do_include_alpha)
49
+
50
+ @staticmethod
51
+ def rgba_to_hex(color: Union[tuple, list], do_include_alpha: bool = False):
52
+ """
53
+ Parse the provided RGBA 'color' parameter and turn it to
54
+ a hexadecimal color if valid or raises an Exception if
55
+ not. The result will be #RRGGBB if 'do_include_alpha' is
56
+ False, or #RRGGBBAA if 'do_include_alpha' is True.
57
+ """
58
+ validate_color(color)
59
+
60
+ return rgba_to_hex(color, do_include_alpha)
61
+
62
+ @staticmethod
63
+ def rgba_to_hsl(color: Union[tuple, list]):
64
+ # TODO: Explain
65
+ validate_color(color)
66
+
67
+ _, _, _, a = parse_rgba_color(color)
68
+
69
+ return *ColorConverter.rgb_to_hsl(color), a
70
+
71
+ @staticmethod
72
+ def rgb_to_hsl(color: Union[tuple, list]):
73
+ # TODO: Explain
74
+ validate_color(color)
75
+
76
+ return rgb_to_hsl(color)
77
+
78
+ @staticmethod
79
+ def rgba_to_cymk(color: Union[tuple, list]):
80
+ # TODO: Explain
81
+ validate_color(color)
82
+
83
+ color = color[:3]
84
+
85
+ # TODO: Is there a way to handle alpha transparency
86
+ # with a cymk (?)
87
+ return ColorConverter.rgb_to_cymk(color)
88
+
89
+ @staticmethod
90
+ def rgb_to_cymk(color: Union[tuple, list]):
91
+ # TODO: Explain
92
+ # It looks like you need to know the color profile before
93
+ # any conversion from RGB or RGBA
94
+ # https://www.reddit.com/r/AdobeIllustrator/comments/17vpbod/different_cmyk_values_for_same_hex_code_which/?rdt=55781#:~:text=A%20hex%20code%20is%20an,information%2C%20like%20a%20colour%20profile.
95
+ validate_color(color)
96
+
97
+ return rgb_to_cymk(color)
98
+
99
+ @staticmethod
100
+ def rgb_to_hsv(color: Union[tuple, list]):
101
+ """
102
+ Turn the provided RGB 'color' into a HSV color.
103
+ """
104
+ validate_color(color)
105
+
106
+ return rgb_to_hsv(color)
107
+
108
+ @staticmethod
109
+ def rgba_to_hsv(color: Union[tuple, list]):
110
+ """
111
+ Turn the provided RGBA 'color' into a HSV color.
112
+ The HSV color doesn't pay attention to the alpha
113
+ layer so this method is the same as using the
114
+ 'rgb_to_hsv' method for this 'color'.
115
+ """
116
+ validate_color(color)
117
+
118
+ return rgba_to_hsv(color)
119
+
120
+ @staticmethod
121
+ def hsv_to_rgb(color: Union[tuple, list]):
122
+ """
123
+ Turn the provided HSV 'color' into a RGB color.
124
+ """
125
+ validate_color(color)
126
+
127
+ h, s, v = color
128
+
129
+ return hsv_to_rgb(h, s, v)
130
+
131
+ @staticmethod
132
+ def hsv_to_rgba(color: Union[tuple, list]):
133
+ """
134
+ Turn the provided HSV 'color' into a RGBA color.
135
+ The HSV color doesn't pay attention to the alpha
136
+ layer so it will be always one.
137
+ """
138
+ validate_color(color)
139
+
140
+ h, s, v = color
141
+
142
+ return hsv_to_rgba(h, s, v)
143
+
144
+ def validate_color(color: Union[tuple, list]):
145
+ """
146
+ Validate the provided 'color' as a tuple or list of 3
147
+ or 4 elements.
148
+ """
149
+ if not PythonValidator.is_instance(color, 'Color') and parse_color(color) is None:
150
+ raise Exception('The provided "color" is not a parsable color.')
151
+
152
+ return True
yta_colors/utils.py ADDED
@@ -0,0 +1,493 @@
1
+ from yta_constants.color import ColorString
2
+ from yta_constants.regex import ColorRegularExpression
3
+ from yta_validation import PythonValidator
4
+ from colorsys import rgb_to_hsv as _rgb_to_hsv, hsv_to_rgb as _hsv_to_rgb
5
+ from typing import Union
6
+
7
+
8
+ def is_hexadecimal_color(
9
+ color: str
10
+ ) -> bool:
11
+ """
12
+ Check that the 'color' parameter is an hexadecimal
13
+ color.
14
+ """
15
+ return ColorRegularExpression.HEX.parse(color)
16
+
17
+ def is_string_color(
18
+ color: str
19
+ ) -> bool:
20
+ """
21
+ Check that the 'color' parameter is an string
22
+ color accepted by our system, whose value is an
23
+ hexadecimal value.
24
+ """
25
+ return ColorString.is_valid(color)
26
+
27
+ def is_array_or_tuple_without_alpha_normalized(
28
+ color: str
29
+ ):
30
+ """
31
+ Check that the 'color' parameter is an array or a
32
+ tuple of 3 elements that are float values between
33
+ 0 and 1 (normalized value).
34
+ """
35
+ return (
36
+ is_array_or_tuple_without_alpha and
37
+ all(
38
+ PythonValidator.is_instance(c, float) and
39
+ 0 <= c <= 1
40
+ for c in color
41
+ )
42
+ )
43
+
44
+ def is_array_or_tuple_with_alpha_normalized(
45
+ color: str
46
+ ):
47
+ """
48
+ Check that the 'color' parameter is an array or a
49
+ tuple of 4 elements that are float values between
50
+ 0 and 1 (normalized value).
51
+ """
52
+ return (
53
+ is_array_or_tuple_with_alpha and
54
+ all(
55
+ PythonValidator.is_instance(c, float) and
56
+ 0 <= c <= 1
57
+ for c in color
58
+ )
59
+ )
60
+
61
+ def is_array_or_tuple_without_alpha(
62
+ color: str
63
+ ):
64
+ """
65
+ Check that the 'color' parameter is an array or a
66
+ tuple of 3 elements that are int values between 0
67
+ and 255.
68
+ """
69
+ return (
70
+ PythonValidator.is_instance(color, [tuple, list]) and
71
+ len(color) == 3 and
72
+ all(
73
+ PythonValidator.is_instance(c, int) and
74
+ 0 <= c <= 255
75
+ for c in color
76
+ )
77
+ )
78
+
79
+ def is_array_or_tuple_with_alpha(
80
+ color: Union[list, tuple]
81
+ ) -> bool:
82
+ """
83
+ Check that the 'color' parameter is an array or a
84
+ tuple of 4 elements that are int values between 0
85
+ and 255.
86
+ """
87
+ return (
88
+ PythonValidator.is_instance(color, [tuple, list]) and
89
+ len(color) == 4 and
90
+ all(
91
+ PythonValidator.is_instance(c, int) and
92
+ 0 <= c <= 255
93
+ for c in color
94
+ )
95
+ )
96
+
97
+ def parse_rgb_color(
98
+ color: str
99
+ ) -> list:
100
+ """
101
+ Parse the provided 'color' as RGB and returns it as
102
+ r,g,b values.
103
+ """
104
+ if is_array_or_tuple_without_alpha_normalized(color):
105
+ return color[0] * 255, color[1] * 255, color[2] * 255
106
+ elif is_array_or_tuple_without_alpha(color):
107
+ return color[0], color[1], color[2]
108
+ else:
109
+ raise Exception(f'The provided "color" parameter is not an RGB color.')
110
+
111
+ def parse_rgba_color(
112
+ color: str
113
+ ) -> list:
114
+ """
115
+ Parse the provided 'color' as RGBA and returns it as
116
+ r,g,b,a values.
117
+ """
118
+ if is_array_or_tuple_with_alpha_normalized(color):
119
+ return color[0] * 255, color[1] * 255, color[2] * 255, color[3] * 255
120
+ elif is_array_or_tuple_with_alpha(color):
121
+ return color[0], color[1], color[2], color[3]
122
+ else:
123
+ raise Exception(f'The provided "color" parameter is not an RGBA color.')
124
+
125
+ def parse_color(
126
+ color: Union[str, list, tuple]
127
+ ) -> Union[list, None]:
128
+ """
129
+ Tries to parse the provided 'color' and returns it
130
+ as an RGBA if parseable, or None if not.
131
+ """
132
+ # As string color
133
+ string_color = None
134
+ try:
135
+ string_color = ColorString.to_enum(color)
136
+ except:
137
+ pass
138
+
139
+ color_array = None
140
+ if string_color is not None:
141
+ color_array = hex_to_rgba(string_color.value)
142
+ # A hexadecimal string
143
+ elif PythonValidator.is_string(color) and is_hexadecimal_color(color):
144
+ color_array = hex_to_rgba(color)
145
+ else:
146
+ # RGBA color
147
+ try:
148
+ color_array = parse_rgba_color(color)
149
+ except:
150
+ pass
151
+
152
+ # RGB color
153
+ try:
154
+ color_array = *parse_rgb_color(color), 0
155
+ except:
156
+ pass
157
+
158
+ # TODO: What about HSL, CYMK, etc. (?)
159
+
160
+ return color_array
161
+
162
+ # These methods below are just actioners, they don't
163
+ # check anything as they will be used by a class that
164
+ # validates everything before using these methods.
165
+ def hex_to_rgba(
166
+ hex_color: str
167
+ ) -> list:
168
+ """
169
+ Return a tuple containing the color in RGBA order.
170
+ """
171
+ # Hex can start with '0x', '0X' or '#'
172
+ hex = hex_color.lstrip('#').lstrip('0x').lstrip('0X')
173
+ if len(hex) == 8:
174
+ # hex with alpha
175
+ r, g, b, a = (int(hex[i:i+2], 16) for i in (0, 2, 4, 6))
176
+ elif len(hex) == 6:
177
+ # hex without alpha
178
+ r, g, b, a = *(int(hex[i:i+2], 16) for i in (0, 2, 4)), 0
179
+
180
+ return r, g, b, a
181
+
182
+ def hex_to_rgb(
183
+ hex_color: str
184
+ ) -> list:
185
+ """
186
+ Return a tuple containing the color in RGB order.
187
+ """
188
+ r, g, b, _ = hex_to_rgba(hex_color)
189
+
190
+ return r, g, b
191
+
192
+ def rgb_to_hex(
193
+ rgb_color: list,
194
+ do_include_alpha: bool = False
195
+ ) -> list:
196
+ """
197
+ Return a tuple containing the color in RGB or RGBA
198
+ order (according to the given 'do_include_alpha'
199
+ parameter value).
200
+ """
201
+ r, g, b = parse_rgb_color(rgb_color)
202
+
203
+ return rgba_to_hex([r, g, b, 255], do_include_alpha)
204
+
205
+ def rgba_to_hex(
206
+ rgba_color: list,
207
+ do_include_alpha: bool = False
208
+ ) -> list:
209
+ """
210
+ Return a tuple containing the color in HEX mode
211
+ (including the alpha value if the given
212
+ 'do_include_alpha' parameter is True).
213
+ """
214
+ r, g, b, a = parse_rgba_color(rgba_color)
215
+
216
+ return (
217
+ "#{:02x}{:02x}{:02x}{:02x}".format(r, g, b, a)
218
+ if do_include_alpha else
219
+ "#{:02x}{:02x}{:02x}".format(r, g, b)
220
+ )
221
+
222
+ def rgba_to_hsl(
223
+ rgba_color: list
224
+ ) -> list:
225
+ r, g, b, _ = parse_rgba_color(rgba_color)
226
+
227
+ return rgb_to_hsl([r, g, b])
228
+
229
+ def rgb_to_hsl(
230
+ rgb_color: list
231
+ ) -> list:
232
+ r, g, b = parse_rgb_color(rgb_color)
233
+
234
+ # Values normalization
235
+ r /= 255.0
236
+ g /= 255.0
237
+ b /= 255.0
238
+
239
+ # Max and minimum values for RGB
240
+ cmax = max(r, g, b)
241
+ cmin = min(r, g, b)
242
+ delta = cmax - cmin
243
+
244
+ # Tone (H)
245
+ h = (
246
+ 0 # No difference => undefined (gray) tone
247
+ if delta == 0 else
248
+ (60 * ((g - b) / delta) + 360) % 360
249
+ if cmax == r else
250
+ (60 * ((b - r) / delta) + 120) % 360
251
+ if cmax == g else
252
+ (60 * ((r - g) / delta) + 240) % 360 # cmax == b
253
+ )
254
+
255
+ # Luminosity (L)
256
+ l = (cmax + cmin) / 2
257
+
258
+ # Saturation (S)
259
+ s = (
260
+ 0 # No difference => saturation is 0
261
+ if delta == 0 else
262
+ delta / (1 - abs(2 * l - 1)) if l != 0 and l != 1 else delta / (2 - (cmax + cmin))
263
+ )
264
+
265
+ # TODO: I saw in some online solutions that they offer
266
+ # the results without decimal figures
267
+ return round(h, 2), round(s * 100, 2), round(l * 100, 2)
268
+
269
+ # TODO: Add 'hsl_to_rgb'
270
+ # TODO: Add 'hsl_to_rgba'
271
+
272
+ def rgb_to_cymk(
273
+ rgb_color: list
274
+ ) -> list:
275
+ r, g, b = parse_rgb_color(rgb_color)
276
+
277
+ r, g, b = r / 255.0, g / 255.0, b / 255.0
278
+
279
+ k = 1 - max(r, g, b)
280
+
281
+ if k == 1:
282
+ c = m = y = 0
283
+ else:
284
+ c = (1 - r - k) / (1 - k)
285
+ m = (1 - g - k) / (1 - k)
286
+ y = (1 - b - k) / (1 - k)
287
+
288
+ # TODO: I saw in some online solutions that they offer
289
+ # the results without decimal figures
290
+ return round(c * 100, 2), round(m * 100, 2), round(y * 100, 2), round(k * 100, 2)
291
+
292
+ def rgb_to_hsv(
293
+ rgb_color
294
+ ) -> list:
295
+ r, g, b = parse_rgb_color(rgb_color)
296
+
297
+ # TODO: Assume this is not normalized
298
+ return _rgb_to_hsv(r, g, b)
299
+
300
+ def rgba_to_hsv(
301
+ rgba_color
302
+ ) -> list:
303
+ r, g, b, _ = parse_rgba_color(rgba_color)
304
+
305
+ # TODO: Assume this is not normalized
306
+ return _rgb_to_hsv(r, g, b)
307
+
308
+ def hsv_to_rgb(
309
+ h,
310
+ s,
311
+ v
312
+ ):
313
+ # TODO: Assume this is not normalized
314
+ return _hsv_to_rgb(h, s, v)
315
+
316
+ def hsv_to_rgba(
317
+ h,
318
+ s,
319
+ v
320
+ ):
321
+ # TODO: Assume this is not normalized
322
+ return *hsv_to_rgb(h, s, v), 255
323
+
324
+
325
+
326
+ # TODO: We need to accept colors in different formats
327
+ # 1. string representing the color ('red', 'blue')
328
+ # 2. string representing hexa color ('#334455', '0x334455', '0X334455')
329
+ # 3. array, list or tuple containing 3 or 4 colors, each color can be only 1 number/letter (f means ff)
330
+ def parse_hexadecimal_color(
331
+ color: Union[str, list, tuple]
332
+ ) -> Union[list, None]:
333
+ """
334
+ Parse a hexadecimal color. It returns None if unparseable
335
+ or an array containing [r, g, b, a].
336
+
337
+ This method accepts a string color (such as 'black' or
338
+ 'white'), an hexadecimal value (such as '#ffffff' or
339
+ '0x000000') and an array containing the RGB(A) values.
340
+
341
+ TODO: Please, refactor this code.
342
+ """
343
+ if (
344
+ not is_array_or_tuple_with_alpha(color) and
345
+ not is_array_or_tuple_without_alpha(color) and
346
+ not PythonValidator.is_string(color)
347
+ ):
348
+ # TODO: Raise an Exception or return None here?
349
+ return None
350
+
351
+ alpha = None
352
+ if is_array_or_tuple_with_alpha(color):
353
+ color = ''.join(f"{c:02X}" for c in color)
354
+ alpha = color[-2:]
355
+ color = color[:-2]
356
+ #return color
357
+ if is_array_or_tuple_without_alpha(color):
358
+ color = f'{"".join(f"{c:02X}" for c in color)}'
359
+ #return color.append(0)
360
+
361
+ color = color.lower()
362
+
363
+ # 1. Parse a string color name and turn into its hexadecimal value
364
+ tmp_color = ColorString.from_color_string(color)
365
+ if tmp_color is not None:
366
+ color = tmp_color.value
367
+ #return tmp_color.as_hex_array.append(0)
368
+
369
+ from yta_constants.regex import ColorRegularExpression
370
+
371
+ try:
372
+ # Transform the string to its hexadecimal value '#xxxxxx'
373
+ color = f'#{ColorString.to_enum(color.replace("#", "").replace("0x", "")).value}'
374
+ except:
375
+ pass
376
+
377
+ if not ColorRegularExpression.HEXADECIMAL.is_valid(color):
378
+ # TODO: Raise an Exception or return None here?
379
+ return None
380
+
381
+ # It is a valid hexadecimal string
382
+ if (
383
+ ColorRegularExpression.HEXADECIMAL_3_CHARACTERS_NO_ALPHA.is_valid(color) or
384
+ ColorRegularExpression.HEXADECIMAL_4_CHARACTERS_ALPHA.is_valid(color)
385
+ ):
386
+ # We duplicate it to make it have 6 or 8 characters
387
+ # duplicating not the '#' or '0x' flag.
388
+ color = (
389
+ f'#{"".join(c * 2 for c in color[1:])}'
390
+ if color.startswith('#') else
391
+ f'0x{"".join(c * 2 for c in color[2:])}'
392
+ if color.startswith('0x') else
393
+ ''.join(c * 2 for c in color)
394
+ )
395
+
396
+ if ColorRegularExpression.HEXADECIMAL_8_CHARACTERS_ALPHA.is_valid(color):
397
+ #alpha = int(color[-2:], 16)
398
+ alpha = color[-2:]
399
+ color = color[:-2]
400
+
401
+ alpha = (
402
+ alpha.lower()
403
+ if PythonValidator.is_string(alpha) else
404
+ alpha
405
+ )
406
+
407
+ # String is like '#ffffff' or '0xffffff' here
408
+ return [
409
+ color[-6:-4],
410
+ color[-4:-2],
411
+ color[-2:],
412
+ alpha
413
+ ]
414
+
415
+
416
+
417
+ # TODO: This class has to be different, having '#FFFFFF' is not a good choice
418
+ from yta_constants.enum import YTAEnum as Enum
419
+ class ColorString(Enum):
420
+ """
421
+ The hexadecimal string that corresponds to the color.
422
+ """
423
+
424
+ BLACK = 'ffffff'
425
+ WHITE = '000000'
426
+
427
+ @property
428
+ def as_color_string(
429
+ self
430
+ ) -> str:
431
+ return self.name.lower()
432
+
433
+ @property
434
+ def as_hex_str(
435
+ self
436
+ ) -> str:
437
+ """
438
+ Get the color as a string in the '#ffffff' format.
439
+ """
440
+ return f'#{self.value.lower()}'
441
+
442
+ @property
443
+ def as_hex_0x_str(
444
+ self
445
+ ) -> str:
446
+ """
447
+ Get the color as a string in the '0xffffff' format.
448
+ """
449
+ return f'0x{self.value.lower()}'
450
+
451
+ @property
452
+ def as_hex_array(
453
+ self
454
+ ) -> list:
455
+ """
456
+ Get the color as an array in the [red, green, blue] format
457
+ """
458
+ return [
459
+ self.value[-6:-4],
460
+ self.value[-4:-2],
461
+ self.value[-2:]
462
+ ]
463
+
464
+ @property
465
+ def as_hex_int_array(
466
+ self
467
+ ) -> list:
468
+ """
469
+ Get the color as an array in the [red, green, blue] format
470
+ but with integer values.
471
+ """
472
+ return [
473
+ int(self.value[-6:-4], 16),
474
+ int(self.value[-4:-2], 16),
475
+ int(self.value[-2:], 16)
476
+ ]
477
+
478
+ @staticmethod
479
+ def from_color_string(
480
+ color: str
481
+ ) -> Union[ColorString, None]:
482
+ """
483
+ Parse the provided 'color' string as an Enum instance or
484
+ get None if not.
485
+ """
486
+ try:
487
+ return ColorString[color.upper()]
488
+ except KeyError:
489
+ return None
490
+ # TODO: Maybe better an Exception?
491
+ raise Exception('The given "color" is not valid.')
492
+
493
+
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2018 The Python Packaging Authority
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.3
2
+ Name: yta-colors
3
+ Version: 0.0.1
4
+ Summary:
5
+ Author: danialcala94
6
+ Author-email: danielalcalavalera@gmail.com
7
+ Requires-Python: ==3.9
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.9
10
+ Requires-Dist: yta_constants (>=0.0.1,<1.0.0)
11
+ Requires-Dist: yta_validation (>=0.0.1,<1.0.0)
12
+ Description-Content-Type: text/markdown
13
+
14
+ # Youtube Autonomous Colors add-on
15
+
16
+ The way to handle and validate colors.
@@ -0,0 +1,7 @@
1
+ yta_colors/__init__.py,sha256=Gk5tQF7zwqJy_DjtOQIysUG-ZQPu8AhK7krGhVLGI4A,6590
2
+ yta_colors/converter.py,sha256=mGOopt8VoRTPyYrcnZ19RErxg69kYJYrxzkKG2zuitY,4934
3
+ yta_colors/utils.py,sha256=2fAPZaQrBs7617sW3WmcUAi6YOjnCrO3kXpOkCH4zxo,13252
4
+ yta_colors-0.0.1.dist-info/LICENSE,sha256=6kbiFSfobTZ7beWiKnHpN902HgBx-Jzgcme0SvKqhKY,1091
5
+ yta_colors-0.0.1.dist-info/METADATA,sha256=YBzkS_uwC7nFS92g9Rd9ml_BTkK0OmYBR_RXnmAlgVM,458
6
+ yta_colors-0.0.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
7
+ yta_colors-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any