Skip to content

Color Handlers

The pyvesync.utils.colors module provides classes and functions for handling color conversions and representations. It includes the Color class, which serves as a base for color manipulation, and the HSV and RGB classes for specific color models. The module is designed for internal use within the library and is not intended for public use.

Color class

This is the primary class that holds the color data and provides methods for conversion between different color models (RGB, HSV). It also includes methods for validating color values and generating color strings in various formats.

pyvesync.utils.colors.Color dataclass

Dataclass for color values.

This class should be instantiated through the from_rgb or from_hsv classmethods. It will return a Color object with the appropriate color values in RGB and HSV.

Parameters:

Name Type Description Default
color_object HSV | RGB

Named tuple with color values.

required

Attributes:

Name Type Description
hsv namedtuple

hue (0-360), saturation (0-100), value (0-100) see HSV dataclass

rgb namedtuple

red (0-255), green (0-255), blue (0-255) see RGB dataclass

Source code in src\pyvesync\utils\colors.py
@dataclass
class Color:
    """Dataclass for color values.

    This class should be instantiated through the `from_rgb` or `from_hsv`
    classmethods. It will return a `Color` object with the appropriate color
    values in RGB and HSV.

    Args:
        color_object (HSV | RGB): Named tuple with color values.

    Attributes:
        hsv (namedtuple): hue (0-360), saturation (0-100), value (0-100)
            see [`HSV dataclass`][pyvesync.utils.colors.HSV]
        rgb (namedtuple): red (0-255), green (0-255), blue (0-255)
            see [`RGB dataclass`][pyvesync.utils.colors.RGB]
    """
    color_object: InitVar[HSV | RGB]

    def __post_init__(
        self,
        color_object: HSV | RGB,
    ) -> None:
        """Check HSV or RGB Values and create named tuples."""
        if isinstance(color_object, HSV):
            self.hsv = color_object
            self.rgb = self.hsv_to_rgb(*self.hsv.to_tuple())
        elif isinstance(color_object, RGB):
            self.rgb = color_object
            self.hsv = self.rgb_to_hsv(*self.rgb.to_tuple())

    def __str__(self) -> str:
        """Return string representation."""
        return f"Color(hsv={self.hsv}, rgb={self.rgb})"

    def __repr__(self) -> str:
        """Return string representation."""
        return f"Color(hsv={self.hsv}, rgb={self.rgb})"

    def as_dict(self) -> dict[str, dict]:
        """Return color values as dict."""
        return {
            "hsv": {
                "hue": self.hsv.hue,
                "saturation": self.hsv.saturation,
                "value": self.hsv.value,
            },
            "rgb": {
                "red": self.rgb.red,
                "green": self.rgb.green,
                "blue": self.rgb.blue,
            },
        }

    @classmethod
    def from_rgb(cls, red: NUMERIC_STRICT, green: NUMERIC_STRICT,
                 blue: NUMERIC_STRICT) -> Color | None:
        """Create Color instance from RGB values.

        Args:
            red (NUMERIC_STRICT): The red component of the color,
                typically in the range [0, 255].
            green (NUMERIC_STRICT): The green component of the color,
                typically in the range [0, 255].
            blue (NUMERIC_STRICT): The blue component of the color,
                typically in the range [0, 255].

        Returns:
            Color | None: A Color object with the appropriate color values in RGB and HSV,
                or None if the input values are invalid.
        """
        if not Validators.validate_rgb(red, green, blue):
            _LOGGER.debug("Invalid RGB values")
            return None
        return cls(RGB(float(red), float(green), float(blue)))

    @classmethod
    def from_hsv(cls, hue: NUMERIC_STRICT, saturation: NUMERIC_STRICT,
                 value: NUMERIC_STRICT) -> Color | None:
        """Create Color instance from HSV values.

        Args:
            hue (NUMERIC_STRICT): The hue component of the color,
                in the range [0, 360).
            saturation (NUMERIC_STRICT): The saturation component of the color,
                typically in the range [0, 1].
            value (NUMERIC_STRICT): The value (brightness) component of the color,
                typically in the range [0, 1].

        Returns:
            Color | None: A Color object with the appropriate color values in RGB and HSV,
                or None if the input values are invalid.
        """
        if not Validators.validate_hsv(hue, saturation, value):
            _LOGGER.debug("Invalid HSV values")
            return None
        return cls(HSV(float(hue), float(saturation), float(value)))

    @staticmethod
    def hsv_to_rgb(hue: float, saturation: float, value: float) -> RGB:
        """Convert HSV to RGB.

        Args:
            hue (float): The hue component of the color, in the range [0, 360).
            saturation (float): The saturation component of the color,
                in the range [0, 1].
            value (float): The value (brightness) component of the color,
                in the range [0, 1].

        Returns:
            RGB: An RGB dataclass with red, green, and blue components.
        """
        return RGB(
            *tuple(round(i * 255, 0) for i in colorsys.hsv_to_rgb(
                hue / 360,
                saturation / 100,
                value / 100
            ))
        )

    @staticmethod
    def rgb_to_hsv(red: float, green: float, blue: float) -> HSV:
        """Convert RGB to HSV.

        Args:
            red (float): The red component of the color, in the range [0, 255].
            green (float): The green component of the color, in the range [0, 255].
            blue (float): The blue component of the color, in the range [0, 255].

        Returns:
            HSV: An HSV dataclass with hue, saturation, and value components.
        """
        hsv_tuple = colorsys.rgb_to_hsv(
                red / 255,
                green / 255,
                blue / 255
            )
        hsv_factors = [360, 100, 100]

        return HSV(
            float(round(hsv_tuple[0] * hsv_factors[0], 2)),
            float(round(hsv_tuple[1] * hsv_factors[1], 2)),
            float(round(hsv_tuple[2] * hsv_factors[2], 0)),
        )

__repr__

__repr__() -> str

Return string representation.

Source code in src\pyvesync\utils\colors.py
def __repr__(self) -> str:
    """Return string representation."""
    return f"Color(hsv={self.hsv}, rgb={self.rgb})"

as_dict

as_dict() -> dict[str, dict]

Return color values as dict.

Source code in src\pyvesync\utils\colors.py
def as_dict(self) -> dict[str, dict]:
    """Return color values as dict."""
    return {
        "hsv": {
            "hue": self.hsv.hue,
            "saturation": self.hsv.saturation,
            "value": self.hsv.value,
        },
        "rgb": {
            "red": self.rgb.red,
            "green": self.rgb.green,
            "blue": self.rgb.blue,
        },
    }

from_hsv classmethod

from_hsv(
    hue: NUMERIC_STRICT,
    saturation: NUMERIC_STRICT,
    value: NUMERIC_STRICT,
) -> Color | None

Create Color instance from HSV values.

Parameters:

Name Type Description Default
hue NUMERIC_STRICT

The hue component of the color, in the range [0, 360).

required
saturation NUMERIC_STRICT

The saturation component of the color, typically in the range [0, 1].

required
value NUMERIC_STRICT

The value (brightness) component of the color, typically in the range [0, 1].

required

Returns:

Type Description
Color | None

Color | None: A Color object with the appropriate color values in RGB and HSV, or None if the input values are invalid.

Source code in src\pyvesync\utils\colors.py
@classmethod
def from_hsv(cls, hue: NUMERIC_STRICT, saturation: NUMERIC_STRICT,
             value: NUMERIC_STRICT) -> Color | None:
    """Create Color instance from HSV values.

    Args:
        hue (NUMERIC_STRICT): The hue component of the color,
            in the range [0, 360).
        saturation (NUMERIC_STRICT): The saturation component of the color,
            typically in the range [0, 1].
        value (NUMERIC_STRICT): The value (brightness) component of the color,
            typically in the range [0, 1].

    Returns:
        Color | None: A Color object with the appropriate color values in RGB and HSV,
            or None if the input values are invalid.
    """
    if not Validators.validate_hsv(hue, saturation, value):
        _LOGGER.debug("Invalid HSV values")
        return None
    return cls(HSV(float(hue), float(saturation), float(value)))

from_rgb classmethod

from_rgb(
    red: NUMERIC_STRICT,
    green: NUMERIC_STRICT,
    blue: NUMERIC_STRICT,
) -> Color | None

Create Color instance from RGB values.

Parameters:

Name Type Description Default
red NUMERIC_STRICT

The red component of the color, typically in the range [0, 255].

required
green NUMERIC_STRICT

The green component of the color, typically in the range [0, 255].

required
blue NUMERIC_STRICT

The blue component of the color, typically in the range [0, 255].

required

Returns:

Type Description
Color | None

Color | None: A Color object with the appropriate color values in RGB and HSV, or None if the input values are invalid.

Source code in src\pyvesync\utils\colors.py
@classmethod
def from_rgb(cls, red: NUMERIC_STRICT, green: NUMERIC_STRICT,
             blue: NUMERIC_STRICT) -> Color | None:
    """Create Color instance from RGB values.

    Args:
        red (NUMERIC_STRICT): The red component of the color,
            typically in the range [0, 255].
        green (NUMERIC_STRICT): The green component of the color,
            typically in the range [0, 255].
        blue (NUMERIC_STRICT): The blue component of the color,
            typically in the range [0, 255].

    Returns:
        Color | None: A Color object with the appropriate color values in RGB and HSV,
            or None if the input values are invalid.
    """
    if not Validators.validate_rgb(red, green, blue):
        _LOGGER.debug("Invalid RGB values")
        return None
    return cls(RGB(float(red), float(green), float(blue)))

hsv_to_rgb staticmethod

hsv_to_rgb(
    hue: float, saturation: float, value: float
) -> RGB

Convert HSV to RGB.

Parameters:

Name Type Description Default
hue float

The hue component of the color, in the range [0, 360).

required
saturation float

The saturation component of the color, in the range [0, 1].

required
value float

The value (brightness) component of the color, in the range [0, 1].

required

Returns:

Name Type Description
RGB RGB

An RGB dataclass with red, green, and blue components.

Source code in src\pyvesync\utils\colors.py
@staticmethod
def hsv_to_rgb(hue: float, saturation: float, value: float) -> RGB:
    """Convert HSV to RGB.

    Args:
        hue (float): The hue component of the color, in the range [0, 360).
        saturation (float): The saturation component of the color,
            in the range [0, 1].
        value (float): The value (brightness) component of the color,
            in the range [0, 1].

    Returns:
        RGB: An RGB dataclass with red, green, and blue components.
    """
    return RGB(
        *tuple(round(i * 255, 0) for i in colorsys.hsv_to_rgb(
            hue / 360,
            saturation / 100,
            value / 100
        ))
    )

rgb_to_hsv staticmethod

rgb_to_hsv(red: float, green: float, blue: float) -> HSV

Convert RGB to HSV.

Parameters:

Name Type Description Default
red float

The red component of the color, in the range [0, 255].

required
green float

The green component of the color, in the range [0, 255].

required
blue float

The blue component of the color, in the range [0, 255].

required

Returns:

Name Type Description
HSV HSV

An HSV dataclass with hue, saturation, and value components.

Source code in src\pyvesync\utils\colors.py
@staticmethod
def rgb_to_hsv(red: float, green: float, blue: float) -> HSV:
    """Convert RGB to HSV.

    Args:
        red (float): The red component of the color, in the range [0, 255].
        green (float): The green component of the color, in the range [0, 255].
        blue (float): The blue component of the color, in the range [0, 255].

    Returns:
        HSV: An HSV dataclass with hue, saturation, and value components.
    """
    hsv_tuple = colorsys.rgb_to_hsv(
            red / 255,
            green / 255,
            blue / 255
        )
    hsv_factors = [360, 100, 100]

    return HSV(
        float(round(hsv_tuple[0] * hsv_factors[0], 2)),
        float(round(hsv_tuple[1] * hsv_factors[1], 2)),
        float(round(hsv_tuple[2] * hsv_factors[2], 0)),
    )

pyvesync.utils.colors.HSV dataclass

HSV color space dataclass, for internal use in utils.colors.Color dataclass.

Does not perform any validation and should not be used directly, only by the Color dataclass through the Color.from_hsv(hue, saturation, value) classmethod or Color.rgb_to_hsv(red, green, blue) method.

Attributes:

Name Type Description
hue float

The hue component of the color, typically in the range [0, 360).

saturation float

The saturation component of the color, typically in the range [0, 1].

value float

The value (brightness) component of the color, typically in the range [0, 1].

Source code in src\pyvesync\utils\colors.py
@dataclass
class HSV:
    """HSV color space dataclass, for internal use in `utils.colors.Color` dataclass.

    Does not perform any validation and should not be used directly, only
    by the `Color` dataclass through the Color.from_hsv(hue, saturation, value)
    classmethod or Color.rgb_to_hsv(red, green, blue) method.

    Attributes:
        hue (float): The hue component of the color, typically in the range [0, 360).
        saturation (float): The saturation component of the color,
            typically in the range [0, 1].
        value (float): The value (brightness) component of the color,
            typically in the range [0, 1].
    """
    hue: float
    saturation: float
    value: float

    def __post_init__(self) -> None:
        """Convert to int."""
        self.hue = int(self.hue)
        self.saturation = int(self.saturation)
        self.value = int(self.value)

    def __str__(self) -> str:
        """Return string representation."""
        return f"HSV({self.hue}, {self.saturation}, {self.value})"

    def __repr__(self) -> str:
        """Return string representation."""
        return f"HSV(hue={self.hue}, saturation={self.saturation}, value={self.value})"

    def to_tuple(self) -> tuple[float, float, float]:
        """Return HSV values as tuple."""
        return self.hue, self.saturation, self.value

    def to_dict(self) -> dict[str, float]:
        """Return HSV values as dict."""
        return {
            "hue": self.hue,
            "saturation": self.saturation,
            "value": self.value,
        }

__repr__

__repr__() -> str

Return string representation.

Source code in src\pyvesync\utils\colors.py
def __repr__(self) -> str:
    """Return string representation."""
    return f"HSV(hue={self.hue}, saturation={self.saturation}, value={self.value})"

to_dict

to_dict() -> dict[str, float]

Return HSV values as dict.

Source code in src\pyvesync\utils\colors.py
def to_dict(self) -> dict[str, float]:
    """Return HSV values as dict."""
    return {
        "hue": self.hue,
        "saturation": self.saturation,
        "value": self.value,
    }

to_tuple

to_tuple() -> tuple[float, float, float]

Return HSV values as tuple.

Source code in src\pyvesync\utils\colors.py
def to_tuple(self) -> tuple[float, float, float]:
    """Return HSV values as tuple."""
    return self.hue, self.saturation, self.value

pyvesync.utils.colors.RGB dataclass

RGB color space dataclass, for internal use in utils.colors.Color dataclass.

Does not perform any validation, it should not be used directly. Used as an attribute in the :obj:pyvesync.helpers.Color dataclass. This should only be used through the :obj:Color dataclass with the Color.from_rgb(red, green, blue) classmethod.

Attributes:

Name Type Description
red float

The red component of the RGB color.

green float

The green component of the RGB color.

blue float

The blue component of the RGB color.

Source code in src\pyvesync\utils\colors.py
@dataclass
class RGB:
    """RGB color space dataclass, for internal use in `utils.colors.Color` dataclass.

    Does not perform any validation, it should not be used directly. Used as an
    attribute in the :obj:`pyvesync.helpers.Color` dataclass. This should only be
    used through the :obj:`Color` dataclass with the Color.from_rgb(red, green, blue)
    classmethod.

    Attributes:
        red (float): The red component of the RGB color.
        green (float): The green component of the RGB color.
        blue (float): The blue component of the RGB color.
    """

    red: float
    green: float
    blue: float

    def __post_init__(self) -> None:
        """Convert to int."""
        self.red = int(self.red)
        self.green = int(self.green)
        self.blue = int(self.blue)

    def __str__(self) -> str:
        """Return string representation."""
        return f"RGB({self.red}, {self.green}, {self.blue})"

    def __repr__(self) -> str:
        """Return string representation."""
        return f"RGB(red={self.red}, green={self.green}, blue={self.blue})"

    def to_tuple(self) -> tuple[float, float, float]:
        """Return RGB values as tuple."""
        return self.red, self.green, self.blue

    def to_dict(self) -> dict[str, float]:
        """Return RGB values as dict."""
        return {
            "red": self.red,
            "green": self.green,
            "blue": self.blue,
        }

__repr__

__repr__() -> str

Return string representation.

Source code in src\pyvesync\utils\colors.py
def __repr__(self) -> str:
    """Return string representation."""
    return f"RGB(red={self.red}, green={self.green}, blue={self.blue})"

to_dict

to_dict() -> dict[str, float]

Return RGB values as dict.

Source code in src\pyvesync\utils\colors.py
def to_dict(self) -> dict[str, float]:
    """Return RGB values as dict."""
    return {
        "red": self.red,
        "green": self.green,
        "blue": self.blue,
    }

to_tuple

to_tuple() -> tuple[float, float, float]

Return RGB values as tuple.

Source code in src\pyvesync\utils\colors.py
def to_tuple(self) -> tuple[float, float, float]:
    """Return RGB values as tuple."""
    return self.red, self.green, self.blue