Skip to content

Commit 00d8c8d

Browse files
[py] convert Color to use @classmethod alternative constructors (#10558)
* move color tests to unit; change to classmethod constructors to permit subclassing * remove unnecessary package in support unit tests; fix licensing * fix violations in Co-authored-by: David Burns <david.burns@theautomatedtester.co.uk>
1 parent d4910a1 commit 00d8c8d

File tree

2 files changed

+27
-17
lines changed

2 files changed

+27
-17
lines changed

‎py/selenium/webdriver/support/color.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# KIND, either express or implied. See the License for the
1515
# specific language governing permissions and limitations
1616
# under the License.
17+
from __future__ import annotations
1718

1819
import sys
1920
from typing import Any, Optional, Sequence, TYPE_CHECKING
@@ -33,7 +34,6 @@
3334
ParseableFloat = Any
3435
ParseableInt = Any
3536

36-
3737
RGB_PATTERN = r"^\s*rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)\s*$"
3838
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*$"
3939
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*$"
@@ -44,7 +44,7 @@
4444
HSLA_PATTERN = r"^\s*hsla\(\s*(\d{1,3})\s*,\s*(\d{1,3})%\s*,\s*(\d{1,3})%\s*,\s*(0|1|0\.\d+)\s*\)\s*$"
4545

4646

47-
class Color(object):
47+
class Color:
4848
"""
4949
Color conversion support class
5050
@@ -59,8 +59,8 @@ class Color(object):
5959
print(Color.from_string('blue').rgba)
6060
"""
6161

62-
@staticmethod
63-
def from_string(str_: str) -> "Color":
62+
@classmethod
63+
def from_string(cls, str_: str) -> Color:
6464
import re
6565

6666
class Matcher(object):
@@ -80,30 +80,32 @@ def groups(self) -> Sequence[str]:
8080
m = Matcher()
8181

8282
if m.match(RGB_PATTERN, str_):
83-
return Color(*m.groups)
83+
return cls(*m.groups)
8484
elif m.match(RGB_PCT_PATTERN, str_):
8585
rgb = tuple([float(each) / 100 * 255 for each in m.groups])
86-
return Color(*rgb)
86+
return cls(*rgb)
8787
elif m.match(RGBA_PATTERN, str_):
88-
return Color(*m.groups)
88+
return cls(*m.groups)
8989
elif m.match(RGBA_PCT_PATTERN, str_):
90-
rgba = tuple([float(each) / 100 * 255 for each in m.groups[:3]] + [m.groups[3]]) # type: ignore
91-
return Color(*rgba)
90+
rgba = tuple(
91+
[float(each) / 100 * 255 for each in m.groups[:3]] + [m.groups[3]]) # type: ignore
92+
return cls(*rgba)
9293
elif m.match(HEX_PATTERN, str_):
9394
rgb = tuple([int(each, 16) for each in m.groups])
94-
return Color(*rgb)
95+
return cls(*rgb)
9596
elif m.match(HEX3_PATTERN, str_):
9697
rgb = tuple([int(each * 2, 16) for each in m.groups])
97-
return Color(*rgb)
98+
return cls(*rgb)
9899
elif m.match(HSL_PATTERN, str_) or m.match(HSLA_PATTERN, str_):
99-
return Color._from_hsl(*m.groups)
100+
return cls._from_hsl(*m.groups)
100101
elif str_.upper() in Colors.keys():
101102
return Colors[str_.upper()]
102103
else:
103104
raise ValueError("Could not convert %s into color" % str_)
104105

105-
@staticmethod
106-
def _from_hsl(h: ParseableFloat, s: ParseableFloat, light: ParseableFloat, a: ParseableFloat = 1) -> "Color":
106+
@classmethod
107+
def _from_hsl(cls, h: ParseableFloat, s: ParseableFloat, light: ParseableFloat,
108+
a: ParseableFloat = 1) -> Color:
107109
h = float(h) / 360
108110
s = float(s) / 100
109111
_l = float(light) / 100
@@ -135,9 +137,10 @@ def hue_to_rgb(lum1: float, lum2: float, hue: float) -> float:
135137
g = hue_to_rgb(luminocity1, luminocity2, h)
136138
b = hue_to_rgb(luminocity1, luminocity2, h - 1.0 / 3.0)
137139

138-
return Color(round(r * 255), round(g * 255), round(b * 255), a)
140+
return cls(round(r * 255), round(g * 255), round(b * 255), a)
139141

140-
def __init__(self, red: ParseableInt, green: ParseableInt, blue: ParseableInt, alpha: ParseableFloat = 1) -> None:
142+
def __init__(self, red: ParseableInt, green: ParseableInt, blue: ParseableInt,
143+
alpha: ParseableFloat = 1) -> None:
141144
self.red = int(red)
142145
self.green = int(green)
143146
self.blue = int(blue)
@@ -170,7 +173,8 @@ def __hash__(self) -> int:
170173
return hash((self.red, self.green, self.blue, self.alpha))
171174

172175
def __repr__(self) -> str:
173-
return "Color(red=%d, green=%d, blue=%d, alpha=%s)" % (self.red, self.green, self.blue, self.alpha)
176+
return "Color(red=%d, green=%d, blue=%d, alpha=%s)" % (
177+
self.red, self.green, self.blue, self.alpha)
174178

175179
def __str__(self) -> str:
176180
return "Color: %s" % self.rgba

‎py/test/selenium/webdriver/support/color_tests.py renamed to ‎py/test/unit/selenium/webdriver/support/color_tests.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@
1818
from selenium.webdriver.support.color import Color
1919

2020

21+
def test_color_can_be_subclassed():
22+
class MyColor(Color):
23+
...
24+
assert type(MyColor.from_string("rgb(1, 2, 3)")) == MyColor
25+
26+
2127
def test_rgb_to_rgb():
2228
rgb = "rgb(1, 2, 3)"
2329
assert Color.from_string(rgb).rgb == rgb

0 commit comments

Comments
 (0)