1- """
2- Functionality relating to individual colours.
3- """
1+ """Functionality relating to individual colours."""
42from __future__ import annotations
53
64import re
75from dataclasses import dataclass
8- from typing import Any , Tuple
96
107from catppuccin .hsl import rgb_to_hsl
118
9+ HEXLEN_NO_ALPHA = 6
10+ HEXLEN_ALPHA = 8
11+ MAX_ALPHA = 255
12+
1213
1314@dataclass (frozen = True )
1415class Colour :
@@ -17,58 +18,70 @@ class Colour:
1718 red : int
1819 green : int
1920 blue : int
20- alpha : int = 255
21+ alpha : int = MAX_ALPHA
2122
2223 @property
23- def rgb (self ) -> Tuple [int , int , int ]:
24+ def rgb (self ) -> tuple [int , int , int ]:
2425 """Get the colour as a 3-tuple of red, green, and blue."""
2526 return self .red , self .green , self .blue
2627
2728 @property
28- def rgba (self ) -> Tuple [int , int , int , int ]:
29+ def rgba (self ) -> tuple [int , int , int , int ]:
2930 """Get the colour as a 4-tuple of red, green, blue, and alpha."""
3031 return self .red , self .green , self .blue , self .alpha
3132
3233 @property
33- def hsl (self ) -> Tuple [float , float , float ]:
34+ def hsl (self ) -> tuple [float , float , float ]:
3435 """Get the colour as a 3-tuple of hue, saturation, and lightness."""
3536 return rgb_to_hsl (* self .rgb )
3637
3738 @property
38- def hsla (self ) -> Tuple [float , float , float , float ]:
39+ def hsla (self ) -> tuple [float , float , float , float ]:
3940 """Get the colour as a 4-tuple of hue, saturation, lightness, and alpha."""
4041 return (* self .hsl , self .alpha )
4142
4243 @property
4344 def hex (self ) -> str :
4445 """Get the colour as a lowercase hex string."""
45- if self .alpha < 255 :
46+ if self .alpha < MAX_ALPHA :
4647 return f"{ self .red :02x} { self .green :02x} { self .blue :02x} { self .alpha :02x} "
4748 return f"{ self .red :02x} { self .green :02x} { self .blue :02x} "
4849
49- def __eq__ (self , other : Any ) -> bool :
50+ def __eq__ (self , other : object ) -> bool :
51+ """Check equality against another colour."""
5052 if not isinstance (other , Colour ):
51- raise ValueError ("Cannot check equality with non-colour types." )
53+ e = "Cannot check equality with non-colour types."
54+ raise TypeError (e )
5255
5356 return self .hex == other .hex
5457
5558 @classmethod
5659 def from_hex (cls , hex_string : str ) -> Colour :
5760 """Create a colour from hex string."""
58- if len (hex_string ) not in (6 , 8 ):
59- raise ValueError ("Hex string must be 6 or 8 characters long." )
60-
61- num_groups = 3 if len (hex_string ) == 6 else 4
61+ if len (hex_string ) not in (HEXLEN_NO_ALPHA , HEXLEN_ALPHA ):
62+ e = (
63+ f"Hex string must be { HEXLEN_NO_ALPHA } or "
64+ f"{ HEXLEN_ALPHA } characters long."
65+ )
66+ raise ValueError (e )
67+
68+ num_groups = (
69+ HEXLEN_NO_ALPHA // 2
70+ if len (hex_string ) == HEXLEN_NO_ALPHA
71+ else HEXLEN_ALPHA // 2
72+ )
6273 match = re .match (r"([\da-fA-F]{2})" * num_groups , hex_string )
6374 if match is None :
64- raise ValueError ("Hex string has an invalid format." )
75+ e = "Hex string has an invalid format."
76+ raise ValueError (e )
6577
6678 components = (int (col , 16 ) for col in match .groups ())
6779 return Colour (* components )
6880
6981 def opacity (self , opacity : float ) -> Colour :
7082 """Return a new colour with the given opacity."""
7183 if not 0 <= opacity <= 1 :
72- raise ValueError ("Opacity must be between 0 and 1." )
84+ e = "Opacity must be between 0 and 1."
85+ raise ValueError (e )
7386
74- return Colour (self .red , self .green , self .blue , int (opacity * 255 ))
87+ return Colour (self .red , self .green , self .blue , int (opacity * MAX_ALPHA ))
0 commit comments