prettypretty.color

This subpackage includes prettypretty’s low-level and high-level color APIs. Much of the functionality of the low-level API is implemented through simple functions and tuples, which are spread out across modules besides prettypretty.color.object and straightforward to reuse and compose. Different modules also are largely independent from each other. The one exception is prettypretty.color.lores, which implements support for low-resolution terminal colors with help of the prettypretty.color.conversion, prettypretty.color.difference, and prettypretty.color.theme modules.

The high-level API is a single class, Color, which is exported by the prettypretty.color.object module and provides access to the same functionality as the low-level API, including the conversion between arbitrary color spaces. The price for both convenience and encapsulation is higher overhead, strictly more code is executed, and the potential for less accurate results, more floating point operations may be executed.

prettypretty.color.contrast

Support for computing color contrast. This module implements a perceptual contrast metric that is surprisingly similar to the accessible perceptual contrast algorithm (APCA), version 0.1.9, dated July 3, 2022, but makes

Note that the perceptual contrast metric is asymmetric, i.e., the order of text and background luminance matters. Furthermore, the metric is designed for text on solidly colored backgrounds only and clamps small contrast values to zero.

prettypretty.color.contrast.srgb_to_luminance(r: float, g: float, b: float) float[source]

Determine the contrast luminance for the given sRGB color.

The color must be in-gamut for sRGB with some error tolerance.

prettypretty.color.contrast.p3_to_luminance(r: float, g: float, b: float) float[source]

Determine the contrast luminance for the given Display P3 color.

The color must be in-gamut for Display P3 with some error tolerance. Also, when colors are in-gamut for sRGB, prefer srgb_to_luminance() instead.

prettypretty.color.contrast.luminance_to_contrast(text_luminance: float, background_luminance: float) float[source]

Determine the contrast between the text and background luminance values.

prettypretty.color.contrast.use_black_text(luminance: float) bool[source]

Determine whether black or white text maximizes contrast against the given background luminance.

prettypretty.color.contrast.use_black_background(luminance: float) bool[source]

Determine whether a black or white background maximizes contrast for the given text luminance.

prettypretty.color.conversion

Conversion between color formats and spaces

prettypretty.color.conversion.rgb256_to_srgb(r: int, g: int, b: int) tuple[float, float, float][source]

Convert the given color from 24-bit RGB to sRGB.

prettypretty.color.conversion.srgb_to_rgb256(r: float, g: float, b: float) tuple[int, int, int][source]

Lossy conversion Convert the given color from sRGB to 24-bit RGB.

prettypretty.color.conversion.srgb_to_linear_srgb(r: float, g: float, b: float) tuple[float, float, float][source]

Convert the given color from sRGB to linear sRGB.

prettypretty.color.conversion.linear_srgb_to_srgb(r: float, g: float, b: float) tuple[float, float, float][source]

Convert the given color from linear sRGB to sRGB.

prettypretty.color.conversion.linear_srgb_to_xyz(r: float, g: float, b: float) tuple[float, float, float][source]

Convert the given color from linear sRGB to XYZ.

prettypretty.color.conversion.p3_to_linear_p3(r: float, g: float, b: float) tuple[float, float, float]

Convert the given color from sRGB to linear sRGB.

prettypretty.color.conversion.linear_p3_to_p3(r: float, g: float, b: float) tuple[float, float, float]

Convert the given color from linear sRGB to sRGB.

prettypretty.color.conversion.linear_p3_to_xyz(r: float, g: float, b: float) tuple[float, float, float][source]

Convert the given color from linear P3 to XYZ.

prettypretty.color.conversion.oklch_to_oklab(L: float, C: float, h: float) tuple[float, float, float][source]

Convert the given color from Oklch to Oklab.

prettypretty.color.conversion.oklab_to_oklch(L: float, a: float, b: float) tuple[float, float, float][source]

Convert the given color from Oklab to Oklch.

prettypretty.color.conversion.oklab_to_xyz(L: float, a: float, b: float) tuple[float, float, float][source]

Convert the given color from Oklab to XYZ.

prettypretty.color.conversion.xyz_to_linear_srgb(X: float, Y: float, Z: float) tuple[float, float, float][source]

Convert the given color from XYZ to linear sRGB.

prettypretty.color.conversion.xyz_to_linear_p3(r: float, g: float, b: float) tuple[float, float, float][source]

Convert the given color from XYZ to linear P3.

prettypretty.color.conversion.xyz_to_oklab(X: float, Y: float, Z: float) tuple[float, float, float][source]

Convert the given color from XYZ to Oklab.

prettypretty.color.conversion.get_converter(source: str, target: str) ConverterSpec[source]

Instantiate a function that converts coordinates from the source color format or space to the target color format or space.

This function factory caches converters to avoid re-instantiating the same converter over and over again. Each converter’s name is computed as f"{source}_to_{target}".

prettypretty.color.difference

Support for computing the difference between two or more colors

prettypretty.color.difference.deltaE_oklab(L1: float, a1: float, b1: float, L2: float, a2: float, b2: float, *, version: Literal[1, 2] = 1) float[source]

Determine the difference between two Oklab colors.

For the first version, that difference is just the Euclidian distance between the coordinates.

For the second version, the difference between the a and b coordinates is scaled by a constant factor before computing the Euclidian distance. For now that factor is 2, even though it probably is closer to 2.1.

prettypretty.color.difference.closest_oklab(origin: tuple[float, float, float], candidates: Iterable[tuple[float, float, float]]) tuple[int, tuple[float, float, float]][source]

Find the color closest to the origin amongst candidate colors.

Parameters:
  • origin – is the reference color in Oklab coordinates

  • candidates – are the colors to compare to, also in Oklab coordinates

Returns:

the index and coordinates of the candidate color closest to the origin, which are -1 and origin if the iterable is empty.

This function iterates over the candidates only once and hence the iterable may also be an iterator.

prettypretty.color.equality

Equality of colors.

Equality comparison for colors is complicated by four orthogonal problems:

  1. Coordinate values may be not-a-numbers, which do not equal themselves.

  2. Angular coordinates may have values outside the range of 0 to 360 but still denote the same angle, albeit with additional rotations.

  3. Conversion between color spaces may accrue some amount of floating point error. That amount may further differ between processors and operating systems.

  4. Python requires that, if a class redefines __eq__() it must also redefine __hash__(), so that two equal instances also have the same hash codes.

Addressing the first two problems fundamentally requires customizing equality comparison to correctly handle not-a-numbers and angles. The third problem could be addressed by testing whether the difference between two coordinates is smaller than some epsilon. But that defines color equality in terms of the difference between two instances and hence makes computing the hash even harder, if not impossible. A more productive strategy is to normalize a color’s coordinates to some canonical representation that is then used for both hash computation and equality comparison.

This module implements just that normalization. Correct normalization requires knowing which coordinates are angles. But I am not aware of any color space that has more than one angle—for the hue.

prettypretty.color.equality.PRECISION = 14

The default precision for rounding coordinates during normalization.

prettypretty.color.equality.normalize(coordinates: tuple[float, ...], *, angular_index: int = -1, integral: bool = False, precision: int = 14) tuple[None | float, ...][source]

Normalize the coordinates.

Parameters:
  • coordinates – are the color’s components.

  • angle_index – is the index of the angular coordinate, if there is one.

  • integral – indicates that the color has integral components.

  • precision – is the number of decimals to round to.

Returns:

The normalized coordinates.

This function normalizes the coordinates as follows:

  • It replaces not-a-numbers with None, which equals itself;

  • It coerces integral coordinates to integers;

  • It maps angles to 0–360, coerces them to floating point numbers, and rounds them to two decimal digits less than precision;

  • It coerces all other coordinates to floating point numbers and rounds them to as many decimal digits as precision.

The default precision of 14 digits for arbitrary coordinates and 12 digits for angles was experimentally determined by running tests on macOS and Linux.

The resulting tuple accounts for all of the problems identified above and hence is trivially suitable for hashing and equality testing.

It may be possible to speed up equality testing in case of coordinates already being equal. But it is doubtful that this will lead to noticeable speed gains in applications because equality testing for colors really only matters when testing color manipulation. In general, color distance is the far more relevant comparison.

prettypretty.color.gamut

Support for gamut mapping.

Gamut mapping makes extensive use of other color algorithms, constantly converting betwee color spaces, computing the distance between colors, checking whether colors are in gamut, and clipping colors. As a result, this module has more dependencies than most of the color modules, importing symbols from conversion, difference, space, and spec.

prettypretty.color.gamut.map_into_gamut(target: str, coordinates: tuple[int] | tuple[int, int, int] | tuple[float, float, float]) tuple[float, float, float][source]

Map the coordinates into gamut by using the CSS Color 4 algorithm.

The algorithm performs a binary search across the chroma range between zero and the chroma of the original, out-of-gamut color in Oklch. It stops the search once the chroma-adjusted color is within the just noticeable difference (JND) of its clipped version as measured by deltaEOK and uses that clipped version as result. As such, the algorithm manipulates colors across three color spaces: It uses the coordinates’ color space for gamut testing and clipping, Oklch for producing candidate colors, and Oklab for measuring distance.

prettypretty.color.lores

Support for low-resolution terminal colors

prettypretty.color.lores.ansi_to_eight_bit(color: int) tuple[int][source]

Convert the given ANSI color to 8-bit format. This function implements the identity transform for the color value.

prettypretty.color.lores.rgb6_to_eight_bit(r: int, g: int, b: int) tuple[int][source]

Convert the given color from the 6x6x6 RGB cube of 8-bit terminal colors to an actual 8-bit terminal color.

prettypretty.color.lores.eight_bit_to_rgb6(color: int) tuple[int, int, int][source]

Convert the given 8-bit color to the three components of the 6x6x6 RGB cube. The color value must be between 16 and 231, inclusive.

prettypretty.color.lores.rgb6_to_rgb256(r: int, g: int, b: int) tuple[int, int, int][source]

Convert the given color in RGB6 format to RGB256 format.

prettypretty.color.lores.approximate_rgb256_with_rgb6(r: int, g: int, b: int) tuple[int, int, int][source]

Lossy conversion Convert the given color from RGB256 to RGB6.

This function effectively reverses the conversion from RGB6 to RGB256: It compares each RGB256 coordinate with the RGB256 values used for the inverse and picks the RGB6 with the closest RGB256 value for the inverse.

The correctness of this particular implementation depends on the inverse mapping the extrema of the domain to the extrema of the codomain, i.e., 0 to 0 and 5 to 255.

prettypretty.color.lores.ansi_to_rgb256(color: int) tuple[int, int, int][source]

Lossy conversion Convert the given ANSI color to RGB256 format.

Warning

The result of this function critically depends on the current color theme. After all, the current theme determines the RGB256 values for all extended ANSI colors.

prettypretty.color.lores.eight_bit_to_rgb256(color: int) tuple[int, int, int][source]

Lossy conversion Convert the given 8-bit terminal color to 24-bit RGB.

Warning

The result of this function may depend on the current color theme. It provides RGB256 color values for 8-bit colors 0–15, i.e., the extended ANSI colors.

prettypretty.color.lores.ansi_to_srgb(color: int) tuple[float, float, float][source]

Convert the ANSI color to sRGB. Directly converting to sRGB and avoiding RGB256 is the more conservative conversion because most terminals, when queried with OSC-4, report color values with four hexadecimal digits per coordinate. RGB256 obviously cannot preserve that resolution, though sRGB can.

Warning

The result of this function critically depends on the current color theme. After all, the current theme determines the RGB256 values for all extended ANSI colors.

prettypretty.color.lores.rgb6_to_srgb(r: int, g: int, b: int) tuple[float, float, float][source]

Convert the given color in RGB6 format to sRGB format.

prettypretty.color.lores.eight_bit_to_srgb(color: int) tuple[float, float, float][source]

Convert the given 8-bit terminal color to sRGB.

Warning

The result of this function may depend on the current color theme. It provides RGB256 color values for 8-bit colors 0–15, i.e., the extended ANSI colors.

prettypretty.color.lores.oklab_to_eight_bit(L: float, a: float, b: float) tuple[int][source]

Lossy conversion Convert the given color from Oklab to an 8-bit terminal color.

prettypretty.color.lores.oklab_to_rgb6(L: float, a: float, b: float) tuple[int, int, int][source]

Lossy conversion Convert the given color from Oklab to RGB6.

prettypretty.color.lores.oklab_to_ansi(L: float, a: float, b: float) tuple[int][source]

Lossy conversion Convert the given color from Oklab to the extended sixteen ANSI colors.

Warning

The result of this function critically depends on the current color theme. It provides an implicit input in addition to the arguments.

prettypretty.color.lores.naive_eight_bit_to_ansi(color: int) tuple[int][source]

Perform the naive RGB component conversion from 8-bit to ANSI colors.

This function maps 6x6x6 RGB colors and the 24-step gray gradient to the 16 extended ANSI colors:

  1. It converts the input color to a 3-bit RGB color.

  2. If the sum of the components exceeds some threshold, it makes the 3-bit color a bright color.

Alas, if the sum of the components uses the 3-bit RGB color, possible thresholds 0—3 simply are too coarse. Instead the implementation uses performs downsampling in floating point and retains the resulting normal values for summation during the second step. A threshold of 1.8 has been experimentally validated as reasonable.

Arguably, this isn’t the naive conversion any more. For example, the chalk library implements an even more naive version.

prettypretty.color.object

Prettypretty’s high-level color API.

class prettypretty.color.object.Color(color: int | str | ColorSpec | Self, /)[source]
class prettypretty.color.object.Color(c1: int, c2: int, c3: int, /)
class prettypretty.color.object.Color(tag: str, coordinates: CoordinateSpec, /)
class prettypretty.color.object.Color(tag: str, c1: float, c2: float, c3: float, /)

A color object.

This class implements the high-level, object-oriented API for colors.

tag

identifies the color format or space

Type:

str

coordinates

are the numerical components of the color

Type:

tuple[int] | tuple[int, int, int] | tuple[float, float, float]

Color’s constructor supports a number of options for specifying the color and its coordinates:

  • From an existing ColorSpec or Color object

  • From the textual representation of a color, using #, rgb:, rgbi:, or one of the tags as prefix

  • From a tag and tuple with coordinates

  • From a tag and one or three coordinates

When invoked on an existing color specification or color object, the constructor returns a new color object with the same tag and coordinates. Hence, it effectively upgrades color specifications to full featured color objects.

As for the parent class ColorSpec, instances of this class are immutable.

This class implements __hash__() and __eq__() so that colors in the same color format or space with sufficiently close coordinates are treated as equal. For color formats with integral coordinates, “sufficiently close” means equal coordinates. For color spaces, it means equality after rounding to 14 significant digits. Since equal colors must have equal hashes, the magnitude of the difference cannot be used for equality.

property space: Space

Get the color space for this color.

update(c1: None | float, c2: None | float = None, c3: None | float = None) Self[source]

Update this color.

Since color objects are immutable, this method returns a new color. That color has the same color format or space as this color. Its coordinates are the arguments to this method, except that this color’s coordinates fill null arguments.

in_gamut(epsilon: float = 7.5e-05) bool[source]

Determine whether this color is within gamut for its color space.

clip(epsilon: float = 0) Self[source]

Clip this color to its color space’s gamut.

to_gamut() Self[source]

Map this color into the gamut of its color space using the CSS Color 4 algorithm.

That algorithm performs a binary search across the chroma range between zero and the chroma of the original, out-of-gamut color in Oklch. It stops the search once the chroma-adjusted color is within the just noticeable difference (JND) of its clipped version as measured by deltaEOK and uses that clipped version as result. As such, the algorithm simultaneously manipulates colors across three color spaces: It relies on the coordinates’ color space for gamut testing and clipping, Oklch for producing candidate colors, and Oklab for measuring distance.

Note that only XYZ is unbounded, even if the CSS Color 4 specification claims that Oklab and Oklch also are unbounded. otherwise.

to(target: str) Self[source]

Convert this color to the specified color format or space.

distance(other: ColorSpec, *, version: Literal[1, 2] = 1) float[source]

Determine the symmetric distance ΔE between this color and the given color.

closest(colors: Iterable[ColorSpec]) int[source]

Find the color with the smallest symmetric distance from this color and return its index.

contrast_against(background: ColorSpec) float[source]

Determine the perceptual contrast of text with this color against the given background.

use_black_text() bool[source]

Determine whether to use black or white text against a background of this color for maximum perceptual contrast.

use_black_background() bool[source]

Determine whether to use a black or white background for text of this color for maximum perceptual contrast.

prettypretty.color.serde

Support for serializing and deserializing color values

prettypretty.color.serde.parse_hex(color: str) tuple[str, tuple[int, int, int]][source]

Parse the string specifying a color in hashed hexadecimal format.

prettypretty.color.serde.parse_x_rgb(color: str) tuple[str, tuple[float, float, float]][source]

Parse the string specifying a color in X’s rgb: format.

prettypretty.color.serde.parse_x_rgbi(color: str) tuple[str, tuple[float, float, float]][source]

Parse the string specifying a color in X’s rgbi: format.

class prettypretty.color.serde.Format(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)[source]

A selector for a color output format.

FUNCTION

for <tag>(<coordinates>) notation

HEX

for #<hex> notation

CSS

for color(), oklab(), oklch(), and rgb() notation

X

for rgb:<hex>/<hex>/<hex> and rgbi:<float>/<float>/<float> notation

prettypretty.color.serde.parse_format_spec(spec: str) tuple[Format, int][source]

Parse a color format specifier.

Format specifiers for colors consist of two optional components matching the regular expression (\.\d\d?)?[cfhx]?. Consistent with the conventions of the Python format mini-language, the precision for color coordinates comes before the format selector. Valid selectors are

  • c for CSS notation,

  • f for <tag>(<coordinates>) function notation,

  • h for #<hex> hexadecimal notation,

  • x for rgb:<hex>/<hex>/<hex> or rgbi:<float>/<float>/<float> notation.

All but h for hexadecimal notation may be prefixed with a precision. The default format is f for function notation and the default precision is 5.

prettypretty.color.serde.stringify(tag: str, coordinates: tuple[int] | tuple[float, float, float], format: Format = Format.FUNCTION, precision: int = 5) str[source]

Format the tagged coordinates in the specified format and with the specified precision.

prettypretty.color.space

Metadata about color spaces.

Note that the conversion module has local copies of some of the same data. If you update this module, be sure to update that module, too.

class prettypretty.color.space.Coordinate(name: str, min: None | float = None, max: None | float = None, type: None | Literal['angle', 'int', 'normal'] = None)[source]

A color space coordinate.

name

the single-letter name of the coordinate or an empty string for nameless coordinates

Type:

str

min

the optional minimum value for the coordinate

Type:

None | float

max

the optional maximum value for the coordinate

Type:

None | float

type

the optional type for common coordinate semantics

Type:

None | Literal[‘angle’, ‘int’, ‘normal’]

The following three coordinate type annotations are recognized:

  • An angle is a floating point number representing a rotation between 0 and 360 degrees, inclusive; used for the hue in polar color spaces.

  • A normal is a floating point number between 0 and 1, inclusive.

  • An int may have arbitrary range but all its values must be integral.

Instances of this class are immutable.

property angular: bool

Flag for this coordinate representing an angle.

property integral: bool

Flag for this coordinate having integer values only.

property normal: bool

Flag for this coordinate being normal, i.e., between 0 and 1.

property unbounded: bool

Flag for this coordinate having no bounds. That is the case if the coordinate represents an angle or has no limits.

in_range(value: int | float, *, epsilon: float = 7.5e-05) bool[source]

Determine whether the given value is within the range set by this coordinate’s min and max attributes with an epsilon tolerance. For angles, null limits, and not-a-numbers, that is always the case.

clip(value: float, *, epsilon: float = 0) float[source]

Clip the value to the range set by this coordinate’s min and max attributes with an epsilon tolerance. The result is the input for angles, null limits, and not-a-numbers.

class prettypretty.color.space.Space(tag: str, label: str, base: None | Self, coordinates: tuple[Coordinate, ...], css_format: None | str = None, lores: bool = False)[source]

A color format or space.

tag

is a lower-case Python identifier

Type:

str

name

is a human-readable, descriptive label

base

is the optional base color space

Type:

None | Self

coordinates

are the coordinates

Type:

tuple[Coordinate, …]

css_format

is the optional CSS format

Type:

None | str

lores

is the flag for a low-resolution format

Type:

bool

All coordinates of a color format or space must have the same numeric representation, i.e., be either int or float. In practice, the difference between integral and non-integral coordinates also is the difference between color formats and color spaces.

Instances of this class are immutable.

property polar: bool

Flag for this color format or space having polar coordinates.

property angular_index: int

Determine the index of the angular coordinate. If the color format or space is polar, this property provides the angular coordinate’s index. Otherwise, it is -1.

property integral: bool

Flag for this color format or space having only integral coordinates.

property unbounded: bool

Flag for the color format or space having only unbounded coordinates.

in_gamut(*coordinates: float, epsilon: float = 7.5e-05) bool[source]

Determine whether the given coordinates are in gamut for this color format or space within an epsilon tolerance.¯

clip(*coordinates: float, epsilon: float = 0) tuple[int] | tuple[int, int, int] | tuple[float, float, float][source]

Clip the coordinates to this color space’s gamut with an epsilon tolerance.

normalize(*coordinates: float) tuple[None | float, ...][source]

Normalize coordinates for this color format or space. See normalize().

static is_tag(tag: str) bool[source]

Check whether the tag is a valid for a color format or space.

static resolve(tag: str) Space[source]

Resolve the tag to the corresponding color format or space.

prettypretty.color.spec

Basic type declarations for coordinates, colors, and conversions:

  • IntCoordinateSpec and FloatCoordinateSpec are triples of integers and floating point values, respectively

  • CoordinateSpec combines the two types with a tuple of a single integer

  • ConverterSpec describes a function that converts from one color format or space into another

  • ColorSpec is a dataclass that associates a color’s components with the tag identifying the color format or space.

All container types are immutable.

class prettypretty.color.spec.ConverterSpec(*args, **kwargs)[source]
class prettypretty.color.spec.ColorSpec(tag: str, coordinates: tuple[int] | tuple[int, int, int] | tuple[float, float, float])[source]

A color specification.

tag

identifies the coordinates’ color format or space

Type:

str

coordinates

are the numeric components of the color

Type:

tuple[int] | tuple[int, int, int] | tuple[float, float, float]

With exception of the ansi and eight_bit terminal color formats, which have one components, all other color formats and spaces have three components. In particular, the rgb6 and rgb256 formats have three integer components, whereas the color spaces all have three floating point components.

This class does validate the tag and number of coordinates upon creation.

Instance of this class are immutable.

classmethod of(tag: int | str | Self, c1: None | float | tuple[int] | tuple[int, int, int] | tuple[float, float, float] = None, c2: None | float = None, c3: None | float = None) Self[source]

Coerce the arguments into a color specification. While this method has six distinct overloads, they remain intentionally undeclared. That way, this method can be used to implement other methods with the same signature and explicitly declared overloads. The six overloads are:

  1. Invoking this method with a color specification results in the same color specification.

  2. Invoking this method with an integer results in a color specification tagged ansi or eight_bit, depending on whether the value is below 16 or not, and the value as coordinates.

  3. Invoking this method with three integers results in a color specification tagged rgb256 and the values as coordinates.

  4. Invoking this method with a string tag and integer coordinate results in a new color specification with the same tag and coordinate (as a tuple).

  5. Invoking this method with a string tag and a tuple of one integer or three integers or three floating point numbers results in a new color specification with the same tag and tuple coordinates.

  6. Invoking this method with a string and three integer or floating point coordinates results in a new color specification with the same tag and coordinates (as a tuple).

prettypretty.color.theme

Support for representing the sixteen extended ANSI colors and for mapping them to meaningful color values.

class prettypretty.color.theme.Theme(*, text: ColorSpec, background: ColorSpec, black: ColorSpec, red: ColorSpec, green: ColorSpec, yellow: ColorSpec, blue: ColorSpec, magenta: ColorSpec, cyan: ColorSpec, white: ColorSpec, bright_black: ColorSpec, bright_red: ColorSpec, bright_green: ColorSpec, bright_yellow: ColorSpec, bright_blue: ColorSpec, bright_magenta: ColorSpec, bright_cyan: ColorSpec, bright_white: ColorSpec)[source]

A terminal color theme.

This class collects color values for the default text (foreground) and background colors as well as the 16 extended ANSI colors. While many terminal themes affect additional user interface elements, such as cursor color, ANSI escape codes cannot modify the appearance of these additional UI elements and hence they can be safely ignored.

Since circular definition of extended ANSI colors in terms of extended ANSI colors defeats the purpose of color themes, this class rejects values tagged as ansi or as eight_bit if the value is between -1 and 15, inclusive. While technically acceptable, the remaining 8-bit colors as well as the RGB6 colors are not recommended for theme colors either.

Instances of this class are immutable.

colors() Iterator[tuple[str, ColorSpec]][source]

Get an iterator over the name, color pairs of this theme.

ansi(color: int) ColorSpec[source]

Look up the RGB256 coordinates for the extended ANSI color.

prettypretty.color.theme.hex(color: str) ColorSpec[source]

Convert a string with exactly six hexadecimal digits into an RGB256 color.

prettypretty.color.theme.builtin_theme_name(theme: Theme) None | str[source]

Determine the name of the given theme. If the theme is one of the built-in themes, this function returns a descriptive name. Otherwise, it returns None.

prettypretty.color.theme.current_theme() Theme[source]
prettypretty.color.theme.current_theme(theme: Theme) ContextManager[Theme]

Manage the current theme.

This function does the work of two:

  1. When invoked without arguments, this function simply returns the current theme.

  2. When invoked with a theme as argument, this function returns a context manager that switches to the provided theme on entry and restores the current theme again on exit.

The default theme uses the same colors as good ol’ VGA text mode.