summaryrefslogtreecommitdiff
path: root/venv/lib/python3.11/site-packages/rich/style.py
diff options
context:
space:
mode:
Diffstat (limited to 'venv/lib/python3.11/site-packages/rich/style.py')
-rw-r--r--venv/lib/python3.11/site-packages/rich/style.py796
1 files changed, 0 insertions, 796 deletions
diff --git a/venv/lib/python3.11/site-packages/rich/style.py b/venv/lib/python3.11/site-packages/rich/style.py
deleted file mode 100644
index 313c889..0000000
--- a/venv/lib/python3.11/site-packages/rich/style.py
+++ /dev/null
@@ -1,796 +0,0 @@
-import sys
-from functools import lru_cache
-from marshal import dumps, loads
-from random import randint
-from typing import Any, Dict, Iterable, List, Optional, Type, Union, cast
-
-from . import errors
-from .color import Color, ColorParseError, ColorSystem, blend_rgb
-from .repr import Result, rich_repr
-from .terminal_theme import DEFAULT_TERMINAL_THEME, TerminalTheme
-
-# Style instances and style definitions are often interchangeable
-StyleType = Union[str, "Style"]
-
-
-class _Bit:
- """A descriptor to get/set a style attribute bit."""
-
- __slots__ = ["bit"]
-
- def __init__(self, bit_no: int) -> None:
- self.bit = 1 << bit_no
-
- def __get__(self, obj: "Style", objtype: Type["Style"]) -> Optional[bool]:
- if obj._set_attributes & self.bit:
- return obj._attributes & self.bit != 0
- return None
-
-
-@rich_repr
-class Style:
- """A terminal style.
-
- A terminal style consists of a color (`color`), a background color (`bgcolor`), and a number of attributes, such
- as bold, italic etc. The attributes have 3 states: they can either be on
- (``True``), off (``False``), or not set (``None``).
-
- Args:
- color (Union[Color, str], optional): Color of terminal text. Defaults to None.
- bgcolor (Union[Color, str], optional): Color of terminal background. Defaults to None.
- bold (bool, optional): Enable bold text. Defaults to None.
- dim (bool, optional): Enable dim text. Defaults to None.
- italic (bool, optional): Enable italic text. Defaults to None.
- underline (bool, optional): Enable underlined text. Defaults to None.
- blink (bool, optional): Enabled blinking text. Defaults to None.
- blink2 (bool, optional): Enable fast blinking text. Defaults to None.
- reverse (bool, optional): Enabled reverse text. Defaults to None.
- conceal (bool, optional): Enable concealed text. Defaults to None.
- strike (bool, optional): Enable strikethrough text. Defaults to None.
- underline2 (bool, optional): Enable doubly underlined text. Defaults to None.
- frame (bool, optional): Enable framed text. Defaults to None.
- encircle (bool, optional): Enable encircled text. Defaults to None.
- overline (bool, optional): Enable overlined text. Defaults to None.
- link (str, link): Link URL. Defaults to None.
-
- """
-
- _color: Optional[Color]
- _bgcolor: Optional[Color]
- _attributes: int
- _set_attributes: int
- _hash: Optional[int]
- _null: bool
- _meta: Optional[bytes]
-
- __slots__ = [
- "_color",
- "_bgcolor",
- "_attributes",
- "_set_attributes",
- "_link",
- "_link_id",
- "_ansi",
- "_style_definition",
- "_hash",
- "_null",
- "_meta",
- ]
-
- # maps bits on to SGR parameter
- _style_map = {
- 0: "1",
- 1: "2",
- 2: "3",
- 3: "4",
- 4: "5",
- 5: "6",
- 6: "7",
- 7: "8",
- 8: "9",
- 9: "21",
- 10: "51",
- 11: "52",
- 12: "53",
- }
-
- STYLE_ATTRIBUTES = {
- "dim": "dim",
- "d": "dim",
- "bold": "bold",
- "b": "bold",
- "italic": "italic",
- "i": "italic",
- "underline": "underline",
- "u": "underline",
- "blink": "blink",
- "blink2": "blink2",
- "reverse": "reverse",
- "r": "reverse",
- "conceal": "conceal",
- "c": "conceal",
- "strike": "strike",
- "s": "strike",
- "underline2": "underline2",
- "uu": "underline2",
- "frame": "frame",
- "encircle": "encircle",
- "overline": "overline",
- "o": "overline",
- }
-
- def __init__(
- self,
- *,
- color: Optional[Union[Color, str]] = None,
- bgcolor: Optional[Union[Color, str]] = None,
- bold: Optional[bool] = None,
- dim: Optional[bool] = None,
- italic: Optional[bool] = None,
- underline: Optional[bool] = None,
- blink: Optional[bool] = None,
- blink2: Optional[bool] = None,
- reverse: Optional[bool] = None,
- conceal: Optional[bool] = None,
- strike: Optional[bool] = None,
- underline2: Optional[bool] = None,
- frame: Optional[bool] = None,
- encircle: Optional[bool] = None,
- overline: Optional[bool] = None,
- link: Optional[str] = None,
- meta: Optional[Dict[str, Any]] = None,
- ):
- self._ansi: Optional[str] = None
- self._style_definition: Optional[str] = None
-
- def _make_color(color: Union[Color, str]) -> Color:
- return color if isinstance(color, Color) else Color.parse(color)
-
- self._color = None if color is None else _make_color(color)
- self._bgcolor = None if bgcolor is None else _make_color(bgcolor)
- self._set_attributes = sum(
- (
- bold is not None,
- dim is not None and 2,
- italic is not None and 4,
- underline is not None and 8,
- blink is not None and 16,
- blink2 is not None and 32,
- reverse is not None and 64,
- conceal is not None and 128,
- strike is not None and 256,
- underline2 is not None and 512,
- frame is not None and 1024,
- encircle is not None and 2048,
- overline is not None and 4096,
- )
- )
- self._attributes = (
- sum(
- (
- bold and 1 or 0,
- dim and 2 or 0,
- italic and 4 or 0,
- underline and 8 or 0,
- blink and 16 or 0,
- blink2 and 32 or 0,
- reverse and 64 or 0,
- conceal and 128 or 0,
- strike and 256 or 0,
- underline2 and 512 or 0,
- frame and 1024 or 0,
- encircle and 2048 or 0,
- overline and 4096 or 0,
- )
- )
- if self._set_attributes
- else 0
- )
-
- self._link = link
- self._meta = None if meta is None else dumps(meta)
- self._link_id = (
- f"{randint(0, 999999)}{hash(self._meta)}" if (link or meta) else ""
- )
- self._hash: Optional[int] = None
- self._null = not (self._set_attributes or color or bgcolor or link or meta)
-
- @classmethod
- def null(cls) -> "Style":
- """Create an 'null' style, equivalent to Style(), but more performant."""
- return NULL_STYLE
-
- @classmethod
- def from_color(
- cls, color: Optional[Color] = None, bgcolor: Optional[Color] = None
- ) -> "Style":
- """Create a new style with colors and no attributes.
-
- Returns:
- color (Optional[Color]): A (foreground) color, or None for no color. Defaults to None.
- bgcolor (Optional[Color]): A (background) color, or None for no color. Defaults to None.
- """
- style: Style = cls.__new__(Style)
- style._ansi = None
- style._style_definition = None
- style._color = color
- style._bgcolor = bgcolor
- style._set_attributes = 0
- style._attributes = 0
- style._link = None
- style._link_id = ""
- style._meta = None
- style._null = not (color or bgcolor)
- style._hash = None
- return style
-
- @classmethod
- def from_meta(cls, meta: Optional[Dict[str, Any]]) -> "Style":
- """Create a new style with meta data.
-
- Returns:
- meta (Optional[Dict[str, Any]]): A dictionary of meta data. Defaults to None.
- """
- style: Style = cls.__new__(Style)
- style._ansi = None
- style._style_definition = None
- style._color = None
- style._bgcolor = None
- style._set_attributes = 0
- style._attributes = 0
- style._link = None
- style._meta = dumps(meta)
- style._link_id = f"{randint(0, 999999)}{hash(style._meta)}"
- style._hash = None
- style._null = not (meta)
- return style
-
- @classmethod
- def on(cls, meta: Optional[Dict[str, Any]] = None, **handlers: Any) -> "Style":
- """Create a blank style with meta information.
-
- Example:
- style = Style.on(click=self.on_click)
-
- Args:
- meta (Optional[Dict[str, Any]], optional): An optional dict of meta information.
- **handlers (Any): Keyword arguments are translated in to handlers.
-
- Returns:
- Style: A Style with meta information attached.
- """
- meta = {} if meta is None else meta
- meta.update({f"@{key}": value for key, value in handlers.items()})
- return cls.from_meta(meta)
-
- bold = _Bit(0)
- dim = _Bit(1)
- italic = _Bit(2)
- underline = _Bit(3)
- blink = _Bit(4)
- blink2 = _Bit(5)
- reverse = _Bit(6)
- conceal = _Bit(7)
- strike = _Bit(8)
- underline2 = _Bit(9)
- frame = _Bit(10)
- encircle = _Bit(11)
- overline = _Bit(12)
-
- @property
- def link_id(self) -> str:
- """Get a link id, used in ansi code for links."""
- return self._link_id
-
- def __str__(self) -> str:
- """Re-generate style definition from attributes."""
- if self._style_definition is None:
- attributes: List[str] = []
- append = attributes.append
- bits = self._set_attributes
- if bits & 0b0000000001111:
- if bits & 1:
- append("bold" if self.bold else "not bold")
- if bits & (1 << 1):
- append("dim" if self.dim else "not dim")
- if bits & (1 << 2):
- append("italic" if self.italic else "not italic")
- if bits & (1 << 3):
- append("underline" if self.underline else "not underline")
- if bits & 0b0000111110000:
- if bits & (1 << 4):
- append("blink" if self.blink else "not blink")
- if bits & (1 << 5):
- append("blink2" if self.blink2 else "not blink2")
- if bits & (1 << 6):
- append("reverse" if self.reverse else "not reverse")
- if bits & (1 << 7):
- append("conceal" if self.conceal else "not conceal")
- if bits & (1 << 8):
- append("strike" if self.strike else "not strike")
- if bits & 0b1111000000000:
- if bits & (1 << 9):
- append("underline2" if self.underline2 else "not underline2")
- if bits & (1 << 10):
- append("frame" if self.frame else "not frame")
- if bits & (1 << 11):
- append("encircle" if self.encircle else "not encircle")
- if bits & (1 << 12):
- append("overline" if self.overline else "not overline")
- if self._color is not None:
- append(self._color.name)
- if self._bgcolor is not None:
- append("on")
- append(self._bgcolor.name)
- if self._link:
- append("link")
- append(self._link)
- self._style_definition = " ".join(attributes) or "none"
- return self._style_definition
-
- def __bool__(self) -> bool:
- """A Style is false if it has no attributes, colors, or links."""
- return not self._null
-
- def _make_ansi_codes(self, color_system: ColorSystem) -> str:
- """Generate ANSI codes for this style.
-
- Args:
- color_system (ColorSystem): Color system.
-
- Returns:
- str: String containing codes.
- """
-
- if self._ansi is None:
- sgr: List[str] = []
- append = sgr.append
- _style_map = self._style_map
- attributes = self._attributes & self._set_attributes
- if attributes:
- if attributes & 1:
- append(_style_map[0])
- if attributes & 2:
- append(_style_map[1])
- if attributes & 4:
- append(_style_map[2])
- if attributes & 8:
- append(_style_map[3])
- if attributes & 0b0000111110000:
- for bit in range(4, 9):
- if attributes & (1 << bit):
- append(_style_map[bit])
- if attributes & 0b1111000000000:
- for bit in range(9, 13):
- if attributes & (1 << bit):
- append(_style_map[bit])
- if self._color is not None:
- sgr.extend(self._color.downgrade(color_system).get_ansi_codes())
- if self._bgcolor is not None:
- sgr.extend(
- self._bgcolor.downgrade(color_system).get_ansi_codes(
- foreground=False
- )
- )
- self._ansi = ";".join(sgr)
- return self._ansi
-
- @classmethod
- @lru_cache(maxsize=1024)
- def normalize(cls, style: str) -> str:
- """Normalize a style definition so that styles with the same effect have the same string
- representation.
-
- Args:
- style (str): A style definition.
-
- Returns:
- str: Normal form of style definition.
- """
- try:
- return str(cls.parse(style))
- except errors.StyleSyntaxError:
- return style.strip().lower()
-
- @classmethod
- def pick_first(cls, *values: Optional[StyleType]) -> StyleType:
- """Pick first non-None style."""
- for value in values:
- if value is not None:
- return value
- raise ValueError("expected at least one non-None style")
-
- def __rich_repr__(self) -> Result:
- yield "color", self.color, None
- yield "bgcolor", self.bgcolor, None
- yield "bold", self.bold, None,
- yield "dim", self.dim, None,
- yield "italic", self.italic, None
- yield "underline", self.underline, None,
- yield "blink", self.blink, None
- yield "blink2", self.blink2, None
- yield "reverse", self.reverse, None
- yield "conceal", self.conceal, None
- yield "strike", self.strike, None
- yield "underline2", self.underline2, None
- yield "frame", self.frame, None
- yield "encircle", self.encircle, None
- yield "link", self.link, None
- if self._meta:
- yield "meta", self.meta
-
- def __eq__(self, other: Any) -> bool:
- if not isinstance(other, Style):
- return NotImplemented
- return self.__hash__() == other.__hash__()
-
- def __ne__(self, other: Any) -> bool:
- if not isinstance(other, Style):
- return NotImplemented
- return self.__hash__() != other.__hash__()
-
- def __hash__(self) -> int:
- if self._hash is not None:
- return self._hash
- self._hash = hash(
- (
- self._color,
- self._bgcolor,
- self._attributes,
- self._set_attributes,
- self._link,
- self._meta,
- )
- )
- return self._hash
-
- @property
- def color(self) -> Optional[Color]:
- """The foreground color or None if it is not set."""
- return self._color
-
- @property
- def bgcolor(self) -> Optional[Color]:
- """The background color or None if it is not set."""
- return self._bgcolor
-
- @property
- def link(self) -> Optional[str]:
- """Link text, if set."""
- return self._link
-
- @property
- def transparent_background(self) -> bool:
- """Check if the style specified a transparent background."""
- return self.bgcolor is None or self.bgcolor.is_default
-
- @property
- def background_style(self) -> "Style":
- """A Style with background only."""
- return Style(bgcolor=self.bgcolor)
-
- @property
- def meta(self) -> Dict[str, Any]:
- """Get meta information (can not be changed after construction)."""
- return {} if self._meta is None else cast(Dict[str, Any], loads(self._meta))
-
- @property
- def without_color(self) -> "Style":
- """Get a copy of the style with color removed."""
- if self._null:
- return NULL_STYLE
- style: Style = self.__new__(Style)
- style._ansi = None
- style._style_definition = None
- style._color = None
- style._bgcolor = None
- style._attributes = self._attributes
- style._set_attributes = self._set_attributes
- style._link = self._link
- style._link_id = f"{randint(0, 999999)}" if self._link else ""
- style._null = False
- style._meta = None
- style._hash = None
- return style
-
- @classmethod
- @lru_cache(maxsize=4096)
- def parse(cls, style_definition: str) -> "Style":
- """Parse a style definition.
-
- Args:
- style_definition (str): A string containing a style.
-
- Raises:
- errors.StyleSyntaxError: If the style definition syntax is invalid.
-
- Returns:
- `Style`: A Style instance.
- """
- if style_definition.strip() == "none" or not style_definition:
- return cls.null()
-
- STYLE_ATTRIBUTES = cls.STYLE_ATTRIBUTES
- color: Optional[str] = None
- bgcolor: Optional[str] = None
- attributes: Dict[str, Optional[Any]] = {}
- link: Optional[str] = None
-
- words = iter(style_definition.split())
- for original_word in words:
- word = original_word.lower()
- if word == "on":
- word = next(words, "")
- if not word:
- raise errors.StyleSyntaxError("color expected after 'on'")
- try:
- Color.parse(word) is None
- except ColorParseError as error:
- raise errors.StyleSyntaxError(
- f"unable to parse {word!r} as background color; {error}"
- ) from None
- bgcolor = word
-
- elif word == "not":
- word = next(words, "")
- attribute = STYLE_ATTRIBUTES.get(word)
- if attribute is None:
- raise errors.StyleSyntaxError(
- f"expected style attribute after 'not', found {word!r}"
- )
- attributes[attribute] = False
-
- elif word == "link":
- word = next(words, "")
- if not word:
- raise errors.StyleSyntaxError("URL expected after 'link'")
- link = word
-
- elif word in STYLE_ATTRIBUTES:
- attributes[STYLE_ATTRIBUTES[word]] = True
-
- else:
- try:
- Color.parse(word)
- except ColorParseError as error:
- raise errors.StyleSyntaxError(
- f"unable to parse {word!r} as color; {error}"
- ) from None
- color = word
- style = Style(color=color, bgcolor=bgcolor, link=link, **attributes)
- return style
-
- @lru_cache(maxsize=1024)
- def get_html_style(self, theme: Optional[TerminalTheme] = None) -> str:
- """Get a CSS style rule."""
- theme = theme or DEFAULT_TERMINAL_THEME
- css: List[str] = []
- append = css.append
-
- color = self.color
- bgcolor = self.bgcolor
- if self.reverse:
- color, bgcolor = bgcolor, color
- if self.dim:
- foreground_color = (
- theme.foreground_color if color is None else color.get_truecolor(theme)
- )
- color = Color.from_triplet(
- blend_rgb(foreground_color, theme.background_color, 0.5)
- )
- if color is not None:
- theme_color = color.get_truecolor(theme)
- append(f"color: {theme_color.hex}")
- append(f"text-decoration-color: {theme_color.hex}")
- if bgcolor is not None:
- theme_color = bgcolor.get_truecolor(theme, foreground=False)
- append(f"background-color: {theme_color.hex}")
- if self.bold:
- append("font-weight: bold")
- if self.italic:
- append("font-style: italic")
- if self.underline:
- append("text-decoration: underline")
- if self.strike:
- append("text-decoration: line-through")
- if self.overline:
- append("text-decoration: overline")
- return "; ".join(css)
-
- @classmethod
- def combine(cls, styles: Iterable["Style"]) -> "Style":
- """Combine styles and get result.
-
- Args:
- styles (Iterable[Style]): Styles to combine.
-
- Returns:
- Style: A new style instance.
- """
- iter_styles = iter(styles)
- return sum(iter_styles, next(iter_styles))
-
- @classmethod
- def chain(cls, *styles: "Style") -> "Style":
- """Combine styles from positional argument in to a single style.
-
- Args:
- *styles (Iterable[Style]): Styles to combine.
-
- Returns:
- Style: A new style instance.
- """
- iter_styles = iter(styles)
- return sum(iter_styles, next(iter_styles))
-
- def copy(self) -> "Style":
- """Get a copy of this style.
-
- Returns:
- Style: A new Style instance with identical attributes.
- """
- if self._null:
- return NULL_STYLE
- style: Style = self.__new__(Style)
- style._ansi = self._ansi
- style._style_definition = self._style_definition
- style._color = self._color
- style._bgcolor = self._bgcolor
- style._attributes = self._attributes
- style._set_attributes = self._set_attributes
- style._link = self._link
- style._link_id = f"{randint(0, 999999)}" if self._link else ""
- style._hash = self._hash
- style._null = False
- style._meta = self._meta
- return style
-
- @lru_cache(maxsize=128)
- def clear_meta_and_links(self) -> "Style":
- """Get a copy of this style with link and meta information removed.
-
- Returns:
- Style: New style object.
- """
- if self._null:
- return NULL_STYLE
- style: Style = self.__new__(Style)
- style._ansi = self._ansi
- style._style_definition = self._style_definition
- style._color = self._color
- style._bgcolor = self._bgcolor
- style._attributes = self._attributes
- style._set_attributes = self._set_attributes
- style._link = None
- style._link_id = ""
- style._hash = self._hash
- style._null = False
- style._meta = None
- return style
-
- def update_link(self, link: Optional[str] = None) -> "Style":
- """Get a copy with a different value for link.
-
- Args:
- link (str, optional): New value for link. Defaults to None.
-
- Returns:
- Style: A new Style instance.
- """
- style: Style = self.__new__(Style)
- style._ansi = self._ansi
- style._style_definition = self._style_definition
- style._color = self._color
- style._bgcolor = self._bgcolor
- style._attributes = self._attributes
- style._set_attributes = self._set_attributes
- style._link = link
- style._link_id = f"{randint(0, 999999)}" if link else ""
- style._hash = None
- style._null = False
- style._meta = self._meta
- return style
-
- def render(
- self,
- text: str = "",
- *,
- color_system: Optional[ColorSystem] = ColorSystem.TRUECOLOR,
- legacy_windows: bool = False,
- ) -> str:
- """Render the ANSI codes for the style.
-
- Args:
- text (str, optional): A string to style. Defaults to "".
- color_system (Optional[ColorSystem], optional): Color system to render to. Defaults to ColorSystem.TRUECOLOR.
-
- Returns:
- str: A string containing ANSI style codes.
- """
- if not text or color_system is None:
- return text
- attrs = self._ansi or self._make_ansi_codes(color_system)
- rendered = f"\x1b[{attrs}m{text}\x1b[0m" if attrs else text
- if self._link and not legacy_windows:
- rendered = (
- f"\x1b]8;id={self._link_id};{self._link}\x1b\\{rendered}\x1b]8;;\x1b\\"
- )
- return rendered
-
- def test(self, text: Optional[str] = None) -> None:
- """Write text with style directly to terminal.
-
- This method is for testing purposes only.
-
- Args:
- text (Optional[str], optional): Text to style or None for style name.
-
- """
- text = text or str(self)
- sys.stdout.write(f"{self.render(text)}\n")
-
- @lru_cache(maxsize=1024)
- def _add(self, style: Optional["Style"]) -> "Style":
- if style is None or style._null:
- return self
- if self._null:
- return style
- new_style: Style = self.__new__(Style)
- new_style._ansi = None
- new_style._style_definition = None
- new_style._color = style._color or self._color
- new_style._bgcolor = style._bgcolor or self._bgcolor
- new_style._attributes = (self._attributes & ~style._set_attributes) | (
- style._attributes & style._set_attributes
- )
- new_style._set_attributes = self._set_attributes | style._set_attributes
- new_style._link = style._link or self._link
- new_style._link_id = style._link_id or self._link_id
- new_style._null = style._null
- if self._meta and style._meta:
- new_style._meta = dumps({**self.meta, **style.meta})
- else:
- new_style._meta = self._meta or style._meta
- new_style._hash = None
- return new_style
-
- def __add__(self, style: Optional["Style"]) -> "Style":
- combined_style = self._add(style)
- return combined_style.copy() if combined_style.link else combined_style
-
-
-NULL_STYLE = Style()
-
-
-class StyleStack:
- """A stack of styles."""
-
- __slots__ = ["_stack"]
-
- def __init__(self, default_style: "Style") -> None:
- self._stack: List[Style] = [default_style]
-
- def __repr__(self) -> str:
- return f"<stylestack {self._stack!r}>"
-
- @property
- def current(self) -> Style:
- """Get the Style at the top of the stack."""
- return self._stack[-1]
-
- def push(self, style: Style) -> None:
- """Push a new style on to the stack.
-
- Args:
- style (Style): New style to combine with current style.
- """
- self._stack.append(self._stack[-1] + style)
-
- def pop(self) -> Style:
- """Pop last style and discard.
-
- Returns:
- Style: New current style (also available as stack.current)
- """
- self._stack.pop()
- return self._stack[-1]