Source code for color50.color

"""The **Color** class and its implementation."""

# Daniel Fletcher
# Harvard CS50P 2024
# Final Project

# color.py
# Color class and related functionality

from .constants import ANSI_PREFIX

[docs]class Color: """A class for representing color in RGB format. Represents any given color by storing its RGB values---that is, its red level (0-255), green level (0-255), and blue level (0-255). Once a **Color** object has its RGB values set, it can be used to add color to strings via concatenation. Also designed to be used in conjunction with other key components of the package, like the **ColorStr** class or the ``colorize`` decorator function. Example:: # Normal print statement (behaves as expected) print(\"Not in Color.\") my_color = rgb(128, 0, 128) # Colorized print statement (prints string contents in purple) print(my_color + \"Now in Color!\" + constants.RESET) Note: Make sure to use the ``RESET`` constant when combining strings with **Color** objects; the color settings of your terminal environment may not revert to defaults unless explicitly specified! """
[docs] def __init__(self): """Initialize a **Color** object with red, green, and blue values all set to ``0``. Note that there are no parameterized ``__init___`` functions for the ``Color`` class; instead, it is recommended to use one of the associated :ref:`core functions <core-functions-module-label>` that come with the package as opposed to calling the initializer explicitly. That said, the default initializer can still be called. Upon initialization, each of the object properties (red, green, blue) can be tweaked individually from their default values of ``0``. Example:: # Normal print statement (behaves as expected) print(\"Not in Color.\") my_color = Color() my_color.red = 128 my_color.green = 0 my_color.blue = 128 # Colorized print statement (prints string contents in purple) print(my_color + \"Now in Color!\" + constants.RESET) """ self.red = 0 self.green = 0 self.blue = 0
[docs] def __str__(self): """Return a string representation of the color. Functionally identical to calling the ``fg`` method. Example:: my_color = rgb(0, 0, 255) print(f\"{my_color}f-strings make me feel blue.{constants.RESET}\") """ return self.fg()
[docs] def __add__(self, string: str) -> str: """Support concatenation of **Color** and **str** objects. Example:: my_color = rgb(0, 255, 0) my_message = \"Hello, Green World!\" print(my_color + my_message + constants.RESET) Note: Concatenation of **Color** and **str** objects only supports operations where the first operand is a **Color**. This means that any operation of the type ``Color + str`` is valid, whereas any operation of the type ``str + Color`` is *not*. """ if isinstance(string, str): return str(self) + string else: return NotImplemented
[docs] def __eq__(self, other) -> bool: """Support equality comparisons of two **Color** objects. Two objects of type **Color** are defined to be equal if and only if: - ``color1.red == color2.red`` is **True**, - ``color1.green == color2.green`` is **True**, - and ``color1.blue == color2.blue`` is **True**. Both equality operators (``==`` and ``!=``) are supported. Example:: color1 = rgb(255, 255, 0) color2 = hexcode(\"#ffff00\") color3 = css(\"blue\") print(color1 == color2) # True print(color2 == color3) # False print(color1 == color3) # False """ return (isinstance(other, Color) and self.red == other.red and self.green == other.green and self.blue == other.blue)
def __ne__(self, other) -> bool: return not (self == other) @property def red(self): """int: A numeric value (0-255) representing the color's red levels. Supports both get and set operations. Raises: TypeError: If the property is set to a non-integer value. ValueError: If the property is set to an out-of-range integer (e.g., not in range 0-255). """ return self._red @red.setter def red(self, red: int): if isinstance(red, int): if 0 <= red <= 255: self._red = red else: raise ValueError(f"Invalid rgb value, {red} not in range [0, 255]") else: raise TypeError(f"Expected rgb value as integer, got object of type {type(red)}") @property def green(self): """int: A numeric value (0-255) representing the color's green levels. Supports both get and set operations. Raises: TypeError: If the property is set to a non-integer value. ValueError: If the property is set to an out-of-range integer (e.g., not in range 0-255). """ return self._green @green.setter def green(self, green: int): if isinstance(green, int): if 0 <= green <= 255: self._green = green else: raise ValueError(f"Invalid rgb value, {green} not in range [0, 255]") else: raise TypeError(f"Expected rgb value as integer, got object of type {type(green)}") @property def blue(self): """int: A numeric value (0-255) representing the color's blue levels. Supports both get and set operations. Raises: TypeError: If the property is set to a non-integer value. ValueError: If the property is set to an out-of-range integer (e.g., not in range 0-255). """ return self._blue @blue.setter def blue(self, blue: int): if isinstance(blue, int): if 0 <= blue <= 255: self._blue = blue else: raise ValueError(f"Invalid rgb value, {blue} not in range [0, 255]") else: raise TypeError(f"Expected rgb value as integer, got object of type {type(blue)}")
[docs] def fg(self) -> str: """Return the stored color as a string representing its corresponding foreground ANSI color code sequence. The return value of this function is the default behavior of converting a **Color** object to a string. The option to call ``fg`` explicitly has been included for completeness, readability, and consistency. Returns: The ANSI color code sequence representation of the object, specifically for use as a foreground color. Example:: my_color = rgb(0, 128, 64) print(my_color.fg() + "This text is so colorful!" + constants.RESET) """ rgb = f"{self.red};{self.green};{self.blue}" return f"{ANSI_PREFIX}[38;2;{rgb}m"
[docs] def bg(self) -> str: """Return the stored color as a string representing its corresponding background ANSI color code sequence. Returns: The ANSI color code sequence representation of the object, specifically to use as a background color. Example:: my_color = rgb(30, 120, 15) print(my_color.bg() + "What a gorgeous background!" + constants.RESET) """ rgb = f"{self.red};{self.green};{self.blue}" return f"{ANSI_PREFIX}[48;2;{rgb}m"