about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py241
1 files changed, 241 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
new file mode 100644
index 00000000..7de86ce5
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_vendor/rich/ansi.py
@@ -0,0 +1,241 @@
+import re
+import sys
+from contextlib import suppress
+from typing import Iterable, NamedTuple, Optional
+
+from .color import Color
+from .style import Style
+from .text import Text
+
+re_ansi = re.compile(
+    r"""
+(?:\x1b[0-?])|
+(?:\x1b\](.*?)\x1b\\)|
+(?:\x1b([(@-Z\\-_]|\[[0-?]*[ -/]*[@-~]))
+""",
+    re.VERBOSE,
+)
+
+
+class _AnsiToken(NamedTuple):
+    """Result of ansi tokenized string."""
+
+    plain: str = ""
+    sgr: Optional[str] = ""
+    osc: Optional[str] = ""
+
+
+def _ansi_tokenize(ansi_text: str) -> Iterable[_AnsiToken]:
+    """Tokenize a string in to plain text and ANSI codes.
+
+    Args:
+        ansi_text (str): A String containing ANSI codes.
+
+    Yields:
+        AnsiToken: A named tuple of (plain, sgr, osc)
+    """
+
+    position = 0
+    sgr: Optional[str]
+    osc: Optional[str]
+    for match in re_ansi.finditer(ansi_text):
+        start, end = match.span(0)
+        osc, sgr = match.groups()
+        if start > position:
+            yield _AnsiToken(ansi_text[position:start])
+        if sgr:
+            if sgr == "(":
+                position = end + 1
+                continue
+            if sgr.endswith("m"):
+                yield _AnsiToken("", sgr[1:-1], osc)
+        else:
+            yield _AnsiToken("", sgr, osc)
+        position = end
+    if position < len(ansi_text):
+        yield _AnsiToken(ansi_text[position:])
+
+
+SGR_STYLE_MAP = {
+    1: "bold",
+    2: "dim",
+    3: "italic",
+    4: "underline",
+    5: "blink",
+    6: "blink2",
+    7: "reverse",
+    8: "conceal",
+    9: "strike",
+    21: "underline2",
+    22: "not dim not bold",
+    23: "not italic",
+    24: "not underline",
+    25: "not blink",
+    26: "not blink2",
+    27: "not reverse",
+    28: "not conceal",
+    29: "not strike",
+    30: "color(0)",
+    31: "color(1)",
+    32: "color(2)",
+    33: "color(3)",
+    34: "color(4)",
+    35: "color(5)",
+    36: "color(6)",
+    37: "color(7)",
+    39: "default",
+    40: "on color(0)",
+    41: "on color(1)",
+    42: "on color(2)",
+    43: "on color(3)",
+    44: "on color(4)",
+    45: "on color(5)",
+    46: "on color(6)",
+    47: "on color(7)",
+    49: "on default",
+    51: "frame",
+    52: "encircle",
+    53: "overline",
+    54: "not frame not encircle",
+    55: "not overline",
+    90: "color(8)",
+    91: "color(9)",
+    92: "color(10)",
+    93: "color(11)",
+    94: "color(12)",
+    95: "color(13)",
+    96: "color(14)",
+    97: "color(15)",
+    100: "on color(8)",
+    101: "on color(9)",
+    102: "on color(10)",
+    103: "on color(11)",
+    104: "on color(12)",
+    105: "on color(13)",
+    106: "on color(14)",
+    107: "on color(15)",
+}
+
+
+class AnsiDecoder:
+    """Translate ANSI code in to styled Text."""
+
+    def __init__(self) -> None:
+        self.style = Style.null()
+
+    def decode(self, terminal_text: str) -> Iterable[Text]:
+        """Decode ANSI codes in an iterable of lines.
+
+        Args:
+            lines (Iterable[str]): An iterable of lines of terminal output.
+
+        Yields:
+            Text: Marked up Text.
+        """
+        for line in terminal_text.splitlines():
+            yield self.decode_line(line)
+
+    def decode_line(self, line: str) -> Text:
+        """Decode a line containing ansi codes.
+
+        Args:
+            line (str): A line of terminal output.
+
+        Returns:
+            Text: A Text instance marked up according to ansi codes.
+        """
+        from_ansi = Color.from_ansi
+        from_rgb = Color.from_rgb
+        _Style = Style
+        text = Text()
+        append = text.append
+        line = line.rsplit("\r", 1)[-1]
+        for plain_text, sgr, osc in _ansi_tokenize(line):
+            if plain_text:
+                append(plain_text, self.style or None)
+            elif osc is not None:
+                if osc.startswith("8;"):
+                    _params, semicolon, link = osc[2:].partition(";")
+                    if semicolon:
+                        self.style = self.style.update_link(link or None)
+            elif sgr is not None:
+                # Translate in to semi-colon separated codes
+                # Ignore invalid codes, because we want to be lenient
+                codes = [
+                    min(255, int(_code) if _code else 0)
+                    for _code in sgr.split(";")
+                    if _code.isdigit() or _code == ""
+                ]
+                iter_codes = iter(codes)
+                for code in iter_codes:
+                    if code == 0:
+                        # reset
+                        self.style = _Style.null()
+                    elif code in SGR_STYLE_MAP:
+                        # styles
+                        self.style += _Style.parse(SGR_STYLE_MAP[code])
+                    elif code == 38:
+                        #  Foreground
+                        with suppress(StopIteration):
+                            color_type = next(iter_codes)
+                            if color_type == 5:
+                                self.style += _Style.from_color(
+                                    from_ansi(next(iter_codes))
+                                )
+                            elif color_type == 2:
+                                self.style += _Style.from_color(
+                                    from_rgb(
+                                        next(iter_codes),
+                                        next(iter_codes),
+                                        next(iter_codes),
+                                    )
+                                )
+                    elif code == 48:
+                        # Background
+                        with suppress(StopIteration):
+                            color_type = next(iter_codes)
+                            if color_type == 5:
+                                self.style += _Style.from_color(
+                                    None, from_ansi(next(iter_codes))
+                                )
+                            elif color_type == 2:
+                                self.style += _Style.from_color(
+                                    None,
+                                    from_rgb(
+                                        next(iter_codes),
+                                        next(iter_codes),
+                                        next(iter_codes),
+                                    ),
+                                )
+
+        return text
+
+
+if sys.platform != "win32" and __name__ == "__main__":  # pragma: no cover
+    import io
+    import os
+    import pty
+    import sys
+
+    decoder = AnsiDecoder()
+
+    stdout = io.BytesIO()
+
+    def read(fd: int) -> bytes:
+        data = os.read(fd, 1024)
+        stdout.write(data)
+        return data
+
+    pty.spawn(sys.argv[1:], read)
+
+    from .console import Console
+
+    console = Console(record=True)
+
+    stdout_result = stdout.getvalue().decode("utf-8")
+    print(stdout_result)
+
+    for line in decoder.decode(stdout_result):
+        console.print(line)
+
+    console.save_html("stdout.html")