diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..766f6f95 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +test: + pytest --cov=rich tests/ -v diff --git a/rich/color.py b/rich/color.py index 19d2e898..3175ea5c 100644 --- a/rich/color.py +++ b/rich/color.py @@ -100,7 +100,7 @@ class Color(NamedTuple): assert self.number is not None return theme.ansi_colors[self.number] else: # self.type == ColorType.DEFAULT: - assert self.number is not None + assert self.number is None return theme.foreground_color if foreground else theme.background_color @classmethod @@ -159,10 +159,6 @@ class Color(NamedTuple): triplet = ColorTriplet( int(color_24[0:2], 16), int(color_24[2:4], 16), int(color_24[4:6], 16) ) - if not all(component <= 255 for component in triplet): - raise ColorParseError( - f"color components must be <= 0xff (255) in {color!r}" - ) return cls(color, ColorType.TRUECOLOR, triplet=triplet) else: # color_rgb: @@ -262,7 +258,7 @@ def blend_rgb( return new_color -if __name__ == "__main__": +if __name__ == "__main__": # pragma: no cover c = Color.parse("#ff0000") print(c.downgrade(ColorSystem.STANDARD)) diff --git a/tests/test_color.py b/tests/test_color.py new file mode 100644 index 00000000..778179f3 --- /dev/null +++ b/tests/test_color.py @@ -0,0 +1,82 @@ +from rich.color import ( + blend_rgb, + parse_rgb_hex, + Color, + ColorParseError, + ColorSystem, + ColorType, + ColorTriplet, +) + +from rich import themes + +import pytest + + +def test_str() -> None: + print(repr(str(Color.parse("red")))) + assert str(Color.parse("red")) == "\x1b[31m⬤ \x1b[0m" + + +def test_repr() -> None: + assert repr(Color.parse("red")) == "" + + +def test_system() -> None: + assert Color.parse("red").system == ColorSystem.STANDARD + assert Color.parse("#ff0000").system == ColorSystem.TRUECOLOR + + +def test_truecolor() -> None: + assert Color.parse("#ff0000").get_truecolor(themes.DEFAULT) == ColorTriplet( + 255, 0, 0 + ) + assert Color.parse("red").get_truecolor(themes.DEFAULT) == ColorTriplet(128, 0, 0) + assert Color.parse("1").get_truecolor(themes.DEFAULT) == ColorTriplet(128, 0, 0) + assert Color.parse("17").get_truecolor(themes.DEFAULT) == ColorTriplet(0, 0, 95) + assert Color.parse("default").get_truecolor(themes.DEFAULT) == ColorTriplet(0, 0, 0) + assert Color.parse("default").get_truecolor( + themes.DEFAULT, foreground=False + ) == ColorTriplet(255, 255, 255) + + +def test_parse_success() -> None: + assert Color.parse("default") == Color("default", ColorType.DEFAULT, None, None) + assert Color.parse("red") == Color("red", ColorType.STANDARD, 1, None) + assert Color.parse("red+") == Color("red+", ColorType.EIGHT_BIT, 9, None) + assert Color.parse("100") == Color("100", ColorType.EIGHT_BIT, 100, None) + assert Color.parse("#112233") == Color( + "#112233", ColorType.TRUECOLOR, None, ColorTriplet(0x11, 0x22, 0x33) + ) + assert Color.parse("rgb(90,100,110)") == Color( + "rgb(90,100,110)", ColorType.TRUECOLOR, None, ColorTriplet(90, 100, 110) + ) + + +def test_from_triplet() -> None: + assert Color.from_triplet(ColorTriplet(0x10, 0x20, 0x30)) == Color( + "#102030", ColorType.TRUECOLOR, None, ColorTriplet(0x10, 0x20, 0x30) + ) + + +def test_parse_error() -> None: + with pytest.raises(ColorParseError): + Color.parse("rgb(999,0,0)") + with pytest.raises(ColorParseError): + Color.parse("rgb(0,0)") + with pytest.raises(ColorParseError): + Color.parse("rgb(0,0,0,0)") + with pytest.raises(ColorParseError): + Color.parse("nosuchcolor") + with pytest.raises(ColorParseError): + Color.parse("#xxyyzz") + + +def test_parse_rb_hex() -> None: + assert parse_rgb_hex("aabbcc") == ColorTriplet(0xAA, 0xBB, 0xCC) + + +def test_blend_rgb() -> None: + assert blend_rgb( + ColorTriplet(10, 20, 30), ColorTriplet(30, 40, 50) + ) == ColorTriplet(20, 30, 40)