15
15
# specific language governing permissions and limitations
16
16
# under the License.
17
17
18
+ import sys
19
+ from typing import Any , Optional , Sequence , TYPE_CHECKING
20
+
21
+ if sys .version_info >= (3 , 9 ):
22
+ from re import Match
23
+ else :
24
+ from typing import Match
25
+
26
+ if TYPE_CHECKING :
27
+ from typing import SupportsInt , SupportsFloat , Union
28
+ from typing_extensions import SupportsIndex
29
+
30
+ ParseableFloat = Union [SupportsFloat , SupportsIndex , str , bytes , bytearray ]
31
+ ParseableInt = Union [SupportsInt , SupportsIndex , str , bytes ]
32
+ else :
33
+ ParseableFloat = Any
34
+ ParseableInt = Any
35
+
36
+
18
37
RGB_PATTERN = r"^\s*rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)\s*$"
19
38
RGB_PCT_PATTERN = r"^\s*rgb\(\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*,\s*(\d{1,3}|\d{1,2}\.\d+)%\s*\)\s*$"
20
39
RGBA_PATTERN = r"^\s*rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(0|1|0\.\d+)\s*\)\s*$"
@@ -41,19 +60,21 @@ class Color(object):
41
60
"""
42
61
43
62
@staticmethod
44
- def from_string (str_ ) :
63
+ def from_string (str_ : str ) -> "Color" :
45
64
import re
46
65
47
66
class Matcher (object ):
48
- def __init__ (self ):
67
+ match_obj : Optional [Match [str ]]
68
+
69
+ def __init__ (self ) -> None :
49
70
self .match_obj = None
50
71
51
- def match (self , pattern , str_ ) :
72
+ def match (self , pattern : str , str_ : str ) -> Optional [ Match [ str ]] :
52
73
self .match_obj = re .match (pattern , str_ )
53
74
return self .match_obj
54
75
55
76
@property
56
- def groups (self ):
77
+ def groups (self ) -> Sequence [ str ] :
57
78
return () if not self .match_obj else self .match_obj .groups ()
58
79
59
80
m = Matcher ()
@@ -66,7 +87,7 @@ def groups(self):
66
87
elif m .match (RGBA_PATTERN , str_ ):
67
88
return Color (* m .groups )
68
89
elif m .match (RGBA_PCT_PATTERN , str_ ):
69
- rgba = tuple ([float (each ) / 100 * 255 for each in m .groups [:3 ]] + [m .groups [3 ]])
90
+ rgba = tuple ([float (each ) / 100 * 255 for each in m .groups [:3 ]] + [m .groups [3 ]]) # type: ignore
70
91
return Color (* rgba )
71
92
elif m .match (HEX_PATTERN , str_ ):
72
93
rgb = tuple ([int (each , 16 ) for each in m .groups ])
@@ -82,7 +103,7 @@ def groups(self):
82
103
raise ValueError ("Could not convert %s into color" % str_ )
83
104
84
105
@staticmethod
85
- def _from_hsl (h , s , light , a = 1 ) :
106
+ def _from_hsl (h : ParseableFloat , s : ParseableFloat , light : ParseableFloat , a : ParseableFloat = 1 ) -> "Color" :
86
107
h = float (h ) / 360
87
108
s = float (s ) / 100
88
109
_l = float (light ) / 100
@@ -95,7 +116,7 @@ def _from_hsl(h, s, light, a=1):
95
116
luminocity2 = _l * (1 + s ) if _l < 0.5 else _l + s - _l * s
96
117
luminocity1 = 2 * _l - luminocity2
97
118
98
- def hue_to_rgb (lum1 , lum2 , hue ) :
119
+ def hue_to_rgb (lum1 : float , lum2 : float , hue : float ) -> float :
99
120
if hue < 0.0 :
100
121
hue += 1
101
122
if hue > 1.0 :
@@ -116,42 +137,42 @@ def hue_to_rgb(lum1, lum2, hue):
116
137
117
138
return Color (round (r * 255 ), round (g * 255 ), round (b * 255 ), a )
118
139
119
- def __init__ (self , red , green , blue , alpha = 1 ) :
140
+ def __init__ (self , red : ParseableInt , green : ParseableInt , blue : ParseableInt , alpha : ParseableFloat = 1 ) -> None :
120
141
self .red = int (red )
121
142
self .green = int (green )
122
143
self .blue = int (blue )
123
144
self .alpha = "1" if float (alpha ) == 1 else str (float (alpha ) or 0 )
124
145
125
146
@property
126
- def rgb (self ):
147
+ def rgb (self ) -> str :
127
148
return "rgb(%d, %d, %d)" % (self .red , self .green , self .blue )
128
149
129
150
@property
130
- def rgba (self ):
151
+ def rgba (self ) -> str :
131
152
return "rgba(%d, %d, %d, %s)" % (self .red , self .green , self .blue , self .alpha )
132
153
133
154
@property
134
- def hex (self ):
155
+ def hex (self ) -> str :
135
156
return "#%02x%02x%02x" % (self .red , self .green , self .blue )
136
157
137
- def __eq__ (self , other ) :
158
+ def __eq__ (self , other : object ) -> bool :
138
159
if isinstance (other , Color ):
139
160
return self .rgba == other .rgba
140
161
return NotImplemented
141
162
142
- def __ne__ (self , other ) :
163
+ def __ne__ (self , other : Any ) -> bool :
143
164
result = self .__eq__ (other )
144
165
if result is NotImplemented :
145
166
return result
146
167
return not result
147
168
148
- def __hash__ (self ):
169
+ def __hash__ (self ) -> int :
149
170
return hash ((self .red , self .green , self .blue , self .alpha ))
150
171
151
- def __repr__ (self ):
172
+ def __repr__ (self ) -> str :
152
173
return "Color(red=%d, green=%d, blue=%d, alpha=%s)" % (self .red , self .green , self .blue , self .alpha )
153
174
154
- def __str__ (self ):
175
+ def __str__ (self ) -> str :
155
176
return "Color: %s" % self .rgba
156
177
157
178
0 commit comments