Source code for graphinglib.tools

from copy import deepcopy
from difflib import get_close_matches
from typing import Any, Protocol, TypeVar

try:
    from typing import Self
except ImportError:
    from typing_extensions import Self

from matplotlib.colors import to_rgba_array

T = TypeVar("T")


def _copy_with_overrides(instance: T, **kwargs: Any) -> T:
    """
    Returns a deep copy of an instance with selected public writable properties overridden.
    """
    class_name = instance.__class__.__name__
    properties: dict[str, property] = {}
    for attr in dir(instance.__class__):
        if attr.startswith("_"):
            continue
        property_ = getattr(instance.__class__, attr, None)
        if isinstance(property_, property):
            properties[attr] = property_
    writable_properties = {
        attr: property_
        for attr, property_ in properties.items()
        if property_.fset is not None
    }
    property_names = list(properties)
    for key in kwargs:
        if key.startswith("_"):
            raise AttributeError(
                f"{class_name} has no public writable property '{key}'."
            )
        if key in writable_properties:
            continue
        if key in properties:
            raise AttributeError(
                f"{class_name}.{key} is a read-only property and cannot be set."
            )
        close_match = get_close_matches(key, property_names, n=1, cutoff=0.6)
        if close_match:
            raise AttributeError(
                f"{class_name} has no public writable property '{key}'. "
                f"Did you mean '{close_match[0]}'?"
            )
        raise AttributeError(f"{class_name} has no public writable property '{key}'.")

    new_copy = deepcopy(instance)
    for key, value in kwargs.items():
        setattr(new_copy, key, value)
    return new_copy


[docs] class MathematicalObject(Protocol): """ This class implements the __r* (reverse) and __i* (inplace) methods for adding, subtracting, multiplying, dividing and raising to a power an object that implements the direct methods. .. warning:: This class works only if the children class implements the `__add__`, `__sub__`, `__mul__`, `__truediv__` and `__pow__` methods. Note also that the `__rpow__` method is not implemented by this class. """ def __add__(self, other: Any) -> Self: raise NotImplementedError def __radd__(self, other: Any) -> Self: return self.__add__(other) def __iadd__(self, other: Any) -> Self: self = self.__add__(other) return self def __sub__(self, other: Any) -> Self: raise NotImplementedError def __rsub__(self, other: Any) -> Self: return self.__sub__(other) * (-1) def __isub__(self, other: Any) -> Self: self = self.__sub__(other) return self def __mul__(self, other: Any) -> Self: raise NotImplementedError def __rmul__(self, other: Any) -> Self: return self.__mul__(other) def __imul__(self, other: Any) -> Self: self = self.__mul__(other) return self def __truediv__(self, other: Any) -> Self: raise NotImplementedError def __rtruediv__(self, other: Any) -> Self: return self.__truediv__(other) ** (-1) def __itruediv__(self, other: Any) -> Self: self = self.__truediv__(other) return self def __pow__(self, other: Any) -> Self: raise NotImplementedError def __rpow__(self, other: Any) -> Self: raise NotImplementedError def __ipow__(self, other: Any) -> Self: self = self.__pow__(other) return self
def get_contrasting_shade(color: str | tuple[int, int, int]) -> str: """ Gives the most contrasting shade (black/white) for a given color. The algorithm used comes from this Stack Exchange answer : https://ux.stackexchange.com/a/82068. Parameters ---------- color : str or tuple[int, int, int] Color that needs to be contrasted. This can either be a known matplotlib color string or a RGB code, given as a tuple of integers between ``0`` and ``255``. Accepted string formats include named colors (``"blue"``), short color strings (``"b"``), hex strings (``"#0000ff"``), and grayscale strings (``"0.5"``). RGB tuples use values between ``0`` and ``255`` (``(0, 0, 255)``). Returns ------- shade : str Shade (black/white) that contrasts the most with the given color. """ if isinstance(color, str): color = to_rgba_array(color)[0, :3] * 255 R, G, B = color if R <= 10: Rg = R / 3294 else: Rg = (R / 269 + 0.0513) ** 2.4 if G <= 10: Gg = G / 3294 else: Gg = (G / 269 + 0.0513) ** 2.4 if B <= 10: Bg = B / 3294 else: Bg = (B / 269 + 0.0513) ** 2.4 L = 0.2126 * Rg + 0.7152 * Gg + 0.0722 * Bg if L < 0.5: return "white" else: return "black"