Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
console.py2699 linesDownload Raw Back to rich
1import os2import sys3import threading4from abc import ABC, abstractmethod5from dataclasses import dataclass, field6from datetime import datetime7from functools import wraps8from itertools import islice9from math import ceil10from os import PathLike11from time import monotonic12from types import FrameType, ModuleType, TracebackType13from typing import (14    IO,15    TYPE_CHECKING,16    Any,17    Callable,18    Dict,19    Iterable,20    List,21    Literal,22    Mapping,23    NamedTuple,24    Optional,25    Protocol,26    TextIO,27    Tuple,28    Type,29    Union,30    cast,31    runtime_checkable,32)33 34from rich._null_file import NULL_FILE35 36from . import errors, themes37from ._emoji_replace import _emoji_replace38from ._export_format import CONSOLE_HTML_FORMAT, CONSOLE_SVG_FORMAT39from ._fileno import get_fileno40from ._log_render import FormatTimeCallable, LogRender41from .align import Align, AlignMethod42from .color import ColorSystem, blend_rgb43from .control import Control44from .emoji import EmojiVariant45from .highlighter import NullHighlighter, ReprHighlighter46from .markup import render as render_markup47from .measure import Measurement, measure_renderables48from .pager import Pager, SystemPager49from .protocol import rich_cast50from .region import Region51from .screen import Screen52from .segment import Segment53from .style import Style, StyleType54from .styled import Styled55from .terminal_theme import DEFAULT_TERMINAL_THEME, SVG_EXPORT_THEME, TerminalTheme56from .text import Text, TextType57from .theme import Theme, ThemeStack58 59if TYPE_CHECKING:60    from ._windows import WindowsConsoleFeatures61    from .live import Live62    from .status import Status63 64JUPYTER_DEFAULT_COLUMNS = 11565JUPYTER_DEFAULT_LINES = 10066WINDOWS = sys.platform == "win32"67 68HighlighterType = Callable[[Union[str, "Text"]], "Text"]69JustifyMethod = Literal["default", "left", "center", "right", "full"]70OverflowMethod = Literal["fold", "crop", "ellipsis", "ignore"]71 72 73class NoChange:74    pass75 76 77NO_CHANGE = NoChange()78 79try:80    _STDIN_FILENO = sys.__stdin__.fileno()  # type: ignore[union-attr]81except Exception:82    _STDIN_FILENO = 083try:84    _STDOUT_FILENO = sys.__stdout__.fileno()  # type: ignore[union-attr]85except Exception:86    _STDOUT_FILENO = 187try:88    _STDERR_FILENO = sys.__stderr__.fileno()  # type: ignore[union-attr]89except Exception:90    _STDERR_FILENO = 291 92_STD_STREAMS = (_STDIN_FILENO, _STDOUT_FILENO, _STDERR_FILENO)93_STD_STREAMS_OUTPUT = (_STDOUT_FILENO, _STDERR_FILENO)94 95 96_TERM_COLORS = {97    "kitty": ColorSystem.EIGHT_BIT,98    "256color": ColorSystem.EIGHT_BIT,99    "16color": ColorSystem.STANDARD,100}101 102 103class ConsoleDimensions(NamedTuple):104    """Size of the terminal."""105 106    width: int107    """The width of the console in 'cells'."""108    height: int109    """The height of the console in lines."""110 111 112@dataclass113class ConsoleOptions:114    """Options for __rich_console__ method."""115 116    size: ConsoleDimensions117    """Size of console."""118    legacy_windows: bool119    """legacy_windows: flag for legacy windows."""120    min_width: int121    """Minimum width of renderable."""122    max_width: int123    """Maximum width of renderable."""124    is_terminal: bool125    """True if the target is a terminal, otherwise False."""126    encoding: str127    """Encoding of terminal."""128    max_height: int129    """Height of container (starts as terminal)"""130    justify: Optional[JustifyMethod] = None131    """Justify value override for renderable."""132    overflow: Optional[OverflowMethod] = None133    """Overflow value override for renderable."""134    no_wrap: Optional[bool] = False135    """Disable wrapping for text."""136    highlight: Optional[bool] = None137    """Highlight override for render_str."""138    markup: Optional[bool] = None139    """Enable markup when rendering strings."""140    height: Optional[int] = None141 142    @property143    def ascii_only(self) -> bool:144        """Check if renderables should use ascii only."""145        return not self.encoding.startswith("utf")146 147    def copy(self) -> "ConsoleOptions":148        """Return a copy of the options.149 150        Returns:151            ConsoleOptions: a copy of self.152        """153        options: ConsoleOptions = ConsoleOptions.__new__(ConsoleOptions)154        options.__dict__ = self.__dict__.copy()155        return options156 157    def update(158        self,159        *,160        width: Union[int, NoChange] = NO_CHANGE,161        min_width: Union[int, NoChange] = NO_CHANGE,162        max_width: Union[int, NoChange] = NO_CHANGE,163        justify: Union[Optional[JustifyMethod], NoChange] = NO_CHANGE,164        overflow: Union[Optional[OverflowMethod], NoChange] = NO_CHANGE,165        no_wrap: Union[Optional[bool], NoChange] = NO_CHANGE,166        highlight: Union[Optional[bool], NoChange] = NO_CHANGE,167        markup: Union[Optional[bool], NoChange] = NO_CHANGE,168        height: Union[Optional[int], NoChange] = NO_CHANGE,169    ) -> "ConsoleOptions":170        """Update values, return a copy."""171        options = self.copy()172        if not isinstance(width, NoChange):173            options.min_width = options.max_width = max(0, width)174        if not isinstance(min_width, NoChange):175            options.min_width = min_width176        if not isinstance(max_width, NoChange):177            options.max_width = max_width178        if not isinstance(justify, NoChange):179            options.justify = justify180        if not isinstance(overflow, NoChange):181            options.overflow = overflow182        if not isinstance(no_wrap, NoChange):183            options.no_wrap = no_wrap184        if not isinstance(highlight, NoChange):185            options.highlight = highlight186        if not isinstance(markup, NoChange):187            options.markup = markup188        if not isinstance(height, NoChange):189            if height is not None:190                options.max_height = height191            options.height = None if height is None else max(0, height)192        return options193 194    def update_width(self, width: int) -> "ConsoleOptions":195        """Update just the width, return a copy.196 197        Args:198            width (int): New width (sets both min_width and max_width)199 200        Returns:201            ~ConsoleOptions: New console options instance.202        """203        options = self.copy()204        options.min_width = options.max_width = max(0, width)205        return options206 207    def update_height(self, height: int) -> "ConsoleOptions":208        """Update the height, and return a copy.209 210        Args:211            height (int): New height212 213        Returns:214            ~ConsoleOptions: New Console options instance.215        """216        options = self.copy()217        options.max_height = options.height = height218        return options219 220    def reset_height(self) -> "ConsoleOptions":221        """Return a copy of the options with height set to ``None``.222 223        Returns:224            ~ConsoleOptions: New console options instance.225        """226        options = self.copy()227        options.height = None228        return options229 230    def update_dimensions(self, width: int, height: int) -> "ConsoleOptions":231        """Update the width and height, and return a copy.232 233        Args:234            width (int): New width (sets both min_width and max_width).235            height (int): New height.236 237        Returns:238            ~ConsoleOptions: New console options instance.239        """240        options = self.copy()241        options.min_width = options.max_width = max(0, width)242        options.height = options.max_height = height243        return options244 245 246@runtime_checkable247class RichCast(Protocol):248    """An object that may be 'cast' to a console renderable."""249 250    def __rich__(251        self,252    ) -> Union["ConsoleRenderable", "RichCast", str]:  # pragma: no cover253        ...254 255 256@runtime_checkable257class ConsoleRenderable(Protocol):258    """An object that supports the console protocol."""259 260    def __rich_console__(261        self, console: "Console", options: "ConsoleOptions"262    ) -> "RenderResult":  # pragma: no cover263        ...264 265 266# A type that may be rendered by Console.267RenderableType = Union[ConsoleRenderable, RichCast, str]268"""A string or any object that may be rendered by Rich."""269 270# The result of calling a __rich_console__ method.271RenderResult = Iterable[Union[RenderableType, Segment]]272 273_null_highlighter = NullHighlighter()274 275 276class CaptureError(Exception):277    """An error in the Capture context manager."""278 279 280class NewLine:281    """A renderable to generate new line(s)"""282 283    def __init__(self, count: int = 1) -> None:284        self.count = count285 286    def __rich_console__(287        self, console: "Console", options: "ConsoleOptions"288    ) -> Iterable[Segment]:289        yield Segment("\n" * self.count)290 291 292class ScreenUpdate:293    """Render a list of lines at a given offset."""294 295    def __init__(self, lines: List[List[Segment]], x: int, y: int) -> None:296        self._lines = lines297        self.x = x298        self.y = y299 300    def __rich_console__(301        self, console: "Console", options: ConsoleOptions302    ) -> RenderResult:303        x = self.x304        move_to = Control.move_to305        for offset, line in enumerate(self._lines, self.y):306            yield move_to(x, offset)307            yield from line308 309 310class Capture:311    """Context manager to capture the result of printing to the console.312    See :meth:`~rich.console.Console.capture` for how to use.313 314    Args:315        console (Console): A console instance to capture output.316    """317 318    def __init__(self, console: "Console") -> None:319        self._console = console320        self._result: Optional[str] = None321 322    def __enter__(self) -> "Capture":323        self._console.begin_capture()324        return self325 326    def __exit__(327        self,328        exc_type: Optional[Type[BaseException]],329        exc_val: Optional[BaseException],330        exc_tb: Optional[TracebackType],331    ) -> None:332        self._result = self._console.end_capture()333 334    def get(self) -> str:335        """Get the result of the capture."""336        if self._result is None:337            raise CaptureError(338                "Capture result is not available until context manager exits."339            )340        return self._result341 342 343class ThemeContext:344    """A context manager to use a temporary theme. See :meth:`~rich.console.Console.use_theme` for usage."""345 346    def __init__(self, console: "Console", theme: Theme, inherit: bool = True) -> None:347        self.console = console348        self.theme = theme349        self.inherit = inherit350 351    def __enter__(self) -> "ThemeContext":352        self.console.push_theme(self.theme)353        return self354 355    def __exit__(356        self,357        exc_type: Optional[Type[BaseException]],358        exc_val: Optional[BaseException],359        exc_tb: Optional[TracebackType],360    ) -> None:361        self.console.pop_theme()362 363 364class PagerContext:365    """A context manager that 'pages' content. See :meth:`~rich.console.Console.pager` for usage."""366 367    def __init__(368        self,369        console: "Console",370        pager: Optional[Pager] = None,371        styles: bool = False,372        links: bool = False,373    ) -> None:374        self._console = console375        self.pager = SystemPager() if pager is None else pager376        self.styles = styles377        self.links = links378 379    def __enter__(self) -> "PagerContext":380        self._console._enter_buffer()381        return self382 383    def __exit__(384        self,385        exc_type: Optional[Type[BaseException]],386        exc_val: Optional[BaseException],387        exc_tb: Optional[TracebackType],388    ) -> None:389        if exc_type is None:390            with self._console._lock:391                buffer: List[Segment] = self._console._buffer[:]392                del self._console._buffer[:]393                segments: Iterable[Segment] = buffer394                if not self.styles:395                    segments = Segment.strip_styles(segments)396                elif not self.links:397                    segments = Segment.strip_links(segments)398                content = self._console._render_buffer(segments)399            self.pager.show(content)400        self._console._exit_buffer()401 402 403class ScreenContext:404    """A context manager that enables an alternative screen. See :meth:`~rich.console.Console.screen` for usage."""405 406    def __init__(407        self, console: "Console", hide_cursor: bool, style: StyleType = ""408    ) -> None:409        self.console = console410        self.hide_cursor = hide_cursor411        self.screen = Screen(style=style)412        self._changed = False413 414    def update(415        self, *renderables: RenderableType, style: Optional[StyleType] = None416    ) -> None:417        """Update the screen.418 419        Args:420            renderable (RenderableType, optional): Optional renderable to replace current renderable,421                or None for no change. Defaults to None.422            style: (Style, optional): Replacement style, or None for no change. Defaults to None.423        """424        if renderables:425            self.screen.renderable = (426                Group(*renderables) if len(renderables) > 1 else renderables[0]427            )428        if style is not None:429            self.screen.style = style430        self.console.print(self.screen, end="")431 432    def __enter__(self) -> "ScreenContext":433        self._changed = self.console.set_alt_screen(True)434        if self._changed and self.hide_cursor:435            self.console.show_cursor(False)436        return self437 438    def __exit__(439        self,440        exc_type: Optional[Type[BaseException]],441        exc_val: Optional[BaseException],442        exc_tb: Optional[TracebackType],443    ) -> None:444        if self._changed:445            self.console.set_alt_screen(False)446            if self.hide_cursor:447                self.console.show_cursor(True)448 449 450class Group:451    """Takes a group of renderables and returns a renderable object that renders the group.452 453    Args:454        renderables (Iterable[RenderableType]): An iterable of renderable objects.455        fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True.456    """457 458    def __init__(self, *renderables: "RenderableType", fit: bool = True) -> None:459        self._renderables = renderables460        self.fit = fit461        self._render: Optional[List[RenderableType]] = None462 463    @property464    def renderables(self) -> List["RenderableType"]:465        if self._render is None:466            self._render = list(self._renderables)467        return self._render468 469    def __rich_measure__(470        self, console: "Console", options: "ConsoleOptions"471    ) -> "Measurement":472        if self.fit:473            return measure_renderables(console, options, self.renderables)474        else:475            return Measurement(options.max_width, options.max_width)476 477    def __rich_console__(478        self, console: "Console", options: "ConsoleOptions"479    ) -> RenderResult:480        yield from self.renderables481 482 483def group(fit: bool = True) -> Callable[..., Callable[..., Group]]:484    """A decorator that turns an iterable of renderables in to a group.485 486    Args:487        fit (bool, optional): Fit dimension of group to contents, or fill available space. Defaults to True.488    """489 490    def decorator(491        method: Callable[..., Iterable[RenderableType]],492    ) -> Callable[..., Group]:493        """Convert a method that returns an iterable of renderables in to a Group."""494 495        @wraps(method)496        def _replace(*args: Any, **kwargs: Any) -> Group:497            renderables = method(*args, **kwargs)498            return Group(*renderables, fit=fit)499 500        return _replace501 502    return decorator503 504 505def _is_jupyter() -> bool:  # pragma: no cover506    """Check if we're running in a Jupyter notebook."""507    try:508        get_ipython  # type: ignore[name-defined]509    except NameError:510        return False511    ipython = get_ipython()  # type: ignore[name-defined]512    shell = ipython.__class__.__name__513    if (514        "google.colab" in str(ipython.__class__)515        or os.getenv("DATABRICKS_RUNTIME_VERSION")516        or shell == "ZMQInteractiveShell"517    ):518        return True  # Jupyter notebook or qtconsole519    elif shell == "TerminalInteractiveShell":520        return False  # Terminal running IPython521    else:522        return False  # Other type (?)523 524 525COLOR_SYSTEMS = {526    "standard": ColorSystem.STANDARD,527    "256": ColorSystem.EIGHT_BIT,528    "truecolor": ColorSystem.TRUECOLOR,529    "windows": ColorSystem.WINDOWS,530}531 532_COLOR_SYSTEMS_NAMES = {system: name for name, system in COLOR_SYSTEMS.items()}533 534 535@dataclass536class ConsoleThreadLocals(threading.local):537    """Thread local values for Console context."""538 539    theme_stack: ThemeStack540    buffer: List[Segment] = field(default_factory=list)541    buffer_index: int = 0542 543 544class RenderHook(ABC):545    """Provides hooks in to the render process."""546 547    @abstractmethod548    def process_renderables(549        self, renderables: List[ConsoleRenderable]550    ) -> List[ConsoleRenderable]:551        """Called with a list of objects to render.552 553        This method can return a new list of renderables, or modify and return the same list.554 555        Args:556            renderables (List[ConsoleRenderable]): A number of renderable objects.557 558        Returns:559            List[ConsoleRenderable]: A replacement list of renderables.560        """561 562 563_windows_console_features: Optional["WindowsConsoleFeatures"] = None564 565 566def get_windows_console_features() -> "WindowsConsoleFeatures":  # pragma: no cover567    global _windows_console_features568    if _windows_console_features is not None:569        return _windows_console_features570    from ._windows import get_windows_console_features571 572    _windows_console_features = get_windows_console_features()573    return _windows_console_features574 575 576def detect_legacy_windows() -> bool:577    """Detect legacy Windows."""578    return WINDOWS and not get_windows_console_features().vt579 580 581class Console:582    """A high level console interface.583 584    Args:585        color_system (str, optional): The color system supported by your terminal,586            either ``"standard"``, ``"256"`` or ``"truecolor"``. Leave as ``"auto"`` to autodetect.587        force_terminal (Optional[bool], optional): Enable/disable terminal control codes, or None to auto-detect terminal. Defaults to None.588        force_jupyter (Optional[bool], optional): Enable/disable Jupyter rendering, or None to auto-detect Jupyter. Defaults to None.589        force_interactive (Optional[bool], optional): Enable/disable interactive mode, or None to auto detect. Defaults to None.590        soft_wrap (Optional[bool], optional): Set soft wrap default on print method. Defaults to False.591        theme (Theme, optional): An optional style theme object, or ``None`` for default theme.592        stderr (bool, optional): Use stderr rather than stdout if ``file`` is not specified. Defaults to False.593        file (IO, optional): A file object where the console should write to. Defaults to stdout.594        quiet (bool, Optional): Boolean to suppress all output. Defaults to False.595        width (int, optional): The width of the terminal. Leave as default to auto-detect width.596        height (int, optional): The height of the terminal. Leave as default to auto-detect height.597        style (StyleType, optional): Style to apply to all output, or None for no style. Defaults to None.598        no_color (Optional[bool], optional): Enabled no color mode, or None to auto detect. Defaults to None.599        tab_size (int, optional): Number of spaces used to replace a tab character. Defaults to 8.600        record (bool, optional): Boolean to enable recording of terminal output,601            required to call :meth:`export_html`, :meth:`export_svg`, and :meth:`export_text`. Defaults to False.602        markup (bool, optional): Boolean to enable :ref:`console_markup`. Defaults to True.603        emoji (bool, optional): Enable emoji code. Defaults to True.604        emoji_variant (str, optional): Optional emoji variant, either "text" or "emoji". Defaults to None.605        highlight (bool, optional): Enable automatic highlighting. Defaults to True.606        log_time (bool, optional): Boolean to enable logging of time by :meth:`log` methods. Defaults to True.607        log_path (bool, optional): Boolean to enable the logging of the caller by :meth:`log`. Defaults to True.608        log_time_format (Union[str, TimeFormatterCallable], optional): If ``log_time`` is enabled, either string for strftime or callable that formats the time. Defaults to "[%X] ".609        highlighter (HighlighterType, optional): Default highlighter.610        legacy_windows (bool, optional): Enable legacy Windows mode, or ``None`` to auto detect. Defaults to ``None``.611        safe_box (bool, optional): Restrict box options that don't render on legacy Windows.612        get_datetime (Callable[[], datetime], optional): Callable that gets the current time as a datetime.datetime object (used by Console.log),613            or None for datetime.now.614        get_time (Callable[[], time], optional): Callable that gets the current time in seconds, default uses time.monotonic.615    """616 617    _environ: Mapping[str, str] = os.environ618 619    def __init__(620        self,621        *,622        color_system: Optional[623            Literal["auto", "standard", "256", "truecolor", "windows"]624        ] = "auto",625        force_terminal: Optional[bool] = None,626        force_jupyter: Optional[bool] = None,627        force_interactive: Optional[bool] = None,628        soft_wrap: bool = False,629        theme: Optional[Theme] = None,630        stderr: bool = False,631        file: Optional[IO[str]] = None,632        quiet: bool = False,633        width: Optional[int] = None,634        height: Optional[int] = None,635        style: Optional[StyleType] = None,636        no_color: Optional[bool] = None,637        tab_size: int = 8,638        record: bool = False,639        markup: bool = True,640        emoji: bool = True,641        emoji_variant: Optional[EmojiVariant] = None,642        highlight: bool = True,643        log_time: bool = True,644        log_path: bool = True,645        log_time_format: Union[str, FormatTimeCallable] = "[%X]",646        highlighter: Optional["HighlighterType"] = ReprHighlighter(),647        legacy_windows: Optional[bool] = None,648        safe_box: bool = True,649        get_datetime: Optional[Callable[[], datetime]] = None,650        get_time: Optional[Callable[[], float]] = None,651        _environ: Optional[Mapping[str, str]] = None,652    ):653        # Copy of os.environ allows us to replace it for testing654        if _environ is not None:655            self._environ = _environ656 657        self.is_jupyter = _is_jupyter() if force_jupyter is None else force_jupyter658        if self.is_jupyter:659            if width is None:660                jupyter_columns = self._environ.get("JUPYTER_COLUMNS")661                if jupyter_columns is not None and jupyter_columns.isdigit():662                    width = int(jupyter_columns)663                else:664                    width = JUPYTER_DEFAULT_COLUMNS665            if height is None:666                jupyter_lines = self._environ.get("JUPYTER_LINES")667                if jupyter_lines is not None and jupyter_lines.isdigit():668                    height = int(jupyter_lines)669                else:670                    height = JUPYTER_DEFAULT_LINES671 672        self.tab_size = tab_size673        self.record = record674        self._markup = markup675        self._emoji = emoji676        self._emoji_variant: Optional[EmojiVariant] = emoji_variant677        self._highlight = highlight678        self.legacy_windows: bool = (679            (detect_legacy_windows() and not self.is_jupyter)680            if legacy_windows is None681            else legacy_windows682        )683 684        if width is None:685            columns = self._environ.get("COLUMNS")686            if columns is not None and columns.isdigit():687                width = int(columns) - self.legacy_windows688        if height is None:689            lines = self._environ.get("LINES")690            if lines is not None and lines.isdigit():691                height = int(lines)692 693        self.soft_wrap = soft_wrap694        self._width = width695        self._height = height696 697        self._color_system: Optional[ColorSystem]698 699        self._force_terminal = None700        if force_terminal is not None:701            self._force_terminal = force_terminal702 703        self._file = file704        self.quiet = quiet705        self.stderr = stderr706 707        if color_system is None:708            self._color_system = None709        elif color_system == "auto":710            self._color_system = self._detect_color_system()711        else:712            self._color_system = COLOR_SYSTEMS[color_system]713 714        self._lock = threading.RLock()715        self._log_render = LogRender(716            show_time=log_time,717            show_path=log_path,718            time_format=log_time_format,719        )720        self.highlighter: HighlighterType = highlighter or _null_highlighter721        self.safe_box = safe_box722        self.get_datetime = get_datetime or datetime.now723        self.get_time = get_time or monotonic724        self.style = style725        self.no_color = (726            no_color727            if no_color is not None728            else self._environ.get("NO_COLOR", "") != ""729        )730        if force_interactive is None:731            tty_interactive = self._environ.get("TTY_INTERACTIVE", None)732            if tty_interactive is not None:733                if tty_interactive == "0":734                    force_interactive = False735                elif tty_interactive == "1":736                    force_interactive = True737 738        self.is_interactive = (739            (self.is_terminal and not self.is_dumb_terminal)740            if force_interactive is None741            else force_interactive742        )743 744        self._record_buffer_lock = threading.RLock()745        self._thread_locals = ConsoleThreadLocals(746            theme_stack=ThemeStack(themes.DEFAULT if theme is None else theme)747        )748        self._record_buffer: List[Segment] = []749        self._render_hooks: List[RenderHook] = []750        self._live_stack: List[Live] = []751        self._is_alt_screen = False752 753    def __repr__(self) -> str:754        return f"<console width={self.width} {self._color_system!s}>"755 756    @property757    def file(self) -> IO[str]:758        """Get the file object to write to."""759        file = self._file or (sys.stderr if self.stderr else sys.stdout)760        file = getattr(file, "rich_proxied_file", file)761        if file is None:762            file = NULL_FILE763        return file764 765    @file.setter766    def file(self, new_file: IO[str]) -> None:767        """Set a new file object."""768        self._file = new_file769 770    @property771    def _buffer(self) -> List[Segment]:772        """Get a thread local buffer."""773        return self._thread_locals.buffer774 775    @property776    def _buffer_index(self) -> int:777        """Get a thread local buffer."""778        return self._thread_locals.buffer_index779 780    @_buffer_index.setter781    def _buffer_index(self, value: int) -> None:782        self._thread_locals.buffer_index = value783 784    @property785    def _theme_stack(self) -> ThemeStack:786        """Get the thread local theme stack."""787        return self._thread_locals.theme_stack788 789    def _detect_color_system(self) -> Optional[ColorSystem]:790        """Detect color system from env vars."""791        if self.is_jupyter:792            return ColorSystem.TRUECOLOR793        if not self.is_terminal or self.is_dumb_terminal:794            return None795        if WINDOWS:  # pragma: no cover796            if self.legacy_windows:  # pragma: no cover797                return ColorSystem.WINDOWS798            windows_console_features = get_windows_console_features()799            return (800                ColorSystem.TRUECOLOR801                if windows_console_features.truecolor802                else ColorSystem.EIGHT_BIT803            )804        else:805            color_term = self._environ.get("COLORTERM", "").strip().lower()806            if color_term in ("truecolor", "24bit"):807                return ColorSystem.TRUECOLOR808            term = self._environ.get("TERM", "").strip().lower()809            _term_name, _hyphen, colors = term.rpartition("-")810            color_system = _TERM_COLORS.get(colors, ColorSystem.STANDARD)811            return color_system812 813    def _enter_buffer(self) -> None:814        """Enter in to a buffer context, and buffer all output."""815        self._buffer_index += 1816 817    def _exit_buffer(self) -> None:818        """Leave buffer context, and render content if required."""819        self._buffer_index -= 1820        self._check_buffer()821 822    def set_live(self, live: "Live") -> bool:823        """Set Live instance. Used by Live context manager (no need to call directly).824 825        Args:826            live (Live): Live instance using this Console.827 828        Returns:829            Boolean that indicates if the live is the topmost of the stack.830 831        Raises:832            errors.LiveError: If this Console has a Live context currently active.833        """834        with self._lock:835            self._live_stack.append(live)836            return len(self._live_stack) == 1837 838    def clear_live(self) -> None:839        """Clear the Live instance. Used by the Live context manager (no need to call directly)."""840        with self._lock:841            self._live_stack.pop()842 843    def push_render_hook(self, hook: RenderHook) -> None:844        """Add a new render hook to the stack.845 846        Args:847            hook (RenderHook): Render hook instance.848        """849        with self._lock:850            self._render_hooks.append(hook)851 852    def pop_render_hook(self) -> None:853        """Pop the last renderhook from the stack."""854        with self._lock:855            self._render_hooks.pop()856 857    def __enter__(self) -> "Console":858        """Own context manager to enter buffer context."""859        self._enter_buffer()860        return self861 862    def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:863        """Exit buffer context."""864        self._exit_buffer()865 866    def begin_capture(self) -> None:867        """Begin capturing console output. Call :meth:`end_capture` to exit capture mode and return output."""868        self._enter_buffer()869 870    def end_capture(self) -> str:871        """End capture mode and return captured string.872 873        Returns:874            str: Console output.875        """876        render_result = self._render_buffer(self._buffer)877        del self._buffer[:]878        self._exit_buffer()879        return render_result880 881    def push_theme(self, theme: Theme, *, inherit: bool = True) -> None:882        """Push a new theme on to the top of the stack, replacing the styles from the previous theme.883        Generally speaking, you should call :meth:`~rich.console.Console.use_theme` to get a context manager, rather884        than calling this method directly.885 886        Args:887            theme (Theme): A theme instance.888            inherit (bool, optional): Inherit existing styles. Defaults to True.889        """890        self._theme_stack.push_theme(theme, inherit=inherit)891 892    def pop_theme(self) -> None:893        """Remove theme from top of stack, restoring previous theme."""894        self._theme_stack.pop_theme()895 896    def use_theme(self, theme: Theme, *, inherit: bool = True) -> ThemeContext:897        """Use a different theme for the duration of the context manager.898 899        Args:900            theme (Theme): Theme instance to user.901            inherit (bool, optional): Inherit existing console styles. Defaults to True.902 903        Returns:904            ThemeContext: [description]905        """906        return ThemeContext(self, theme, inherit)907 908    @property909    def color_system(self) -> Optional[str]:910        """Get color system string.911 912        Returns:913            Optional[str]: "standard", "256" or "truecolor".914        """915 916        if self._color_system is not None:917            return _COLOR_SYSTEMS_NAMES[self._color_system]918        else:919            return None920 921    @property922    def encoding(self) -> str:923        """Get the encoding of the console file, e.g. ``"utf-8"``.924 925        Returns:926            str: A standard encoding string.927        """928        return (getattr(self.file, "encoding", "utf-8") or "utf-8").lower()929 930    @property931    def is_terminal(self) -> bool:932        """Check if the console is writing to a terminal.933 934        Returns:935            bool: True if the console writing to a device capable of936                understanding escape sequences, otherwise False.937        """938        # If dev has explicitly set this value, return it939        if self._force_terminal is not None:940            return self._force_terminal941 942        # Fudge for Idle943        if hasattr(sys.stdin, "__module__") and sys.stdin.__module__.startswith(944            "idlelib"945        ):946            # Return False for Idle which claims to be a tty but can't handle ansi codes947            return False948 949        if self.is_jupyter:950            # return False for Jupyter, which may have FORCE_COLOR set951            return False952 953        environ = self._environ954 955        tty_compatible = environ.get("TTY_COMPATIBLE", "")956        # 0 indicates device is not tty compatible957        if tty_compatible == "0":958            return False959        # 1 indicates device is tty compatible960        if tty_compatible == "1":961            return True962 963        # https://force-color.org/964        force_color = environ.get("FORCE_COLOR")965        if force_color is not None:966            return force_color != ""967 968        # Any other value defaults to auto detect969        isatty: Optional[Callable[[], bool]] = getattr(self.file, "isatty", None)970        try:971            return False if isatty is None else isatty()972        except ValueError:973            # in some situation (at the end of a pytest run for example) isatty() can raise974            # ValueError: I/O operation on closed file975            # return False because we aren't in a terminal anymore976            return False977 978    @property979    def is_dumb_terminal(self) -> bool:980        """Detect dumb terminal.981 982        Returns:983            bool: True if writing to a dumb terminal, otherwise False.984 985        """986        _term = self._environ.get("TERM", "")987        is_dumb = _term.lower() in ("dumb", "unknown")988        return self.is_terminal and is_dumb989 990    @property991    def options(self) -> ConsoleOptions:992        """Get default console options."""993        size = self.size994        return ConsoleOptions(995            max_height=size.height,996            size=size,997            legacy_windows=self.legacy_windows,998            min_width=1,999            max_width=size.width,1000            encoding=self.encoding,1001            is_terminal=self.is_terminal,1002        )1003 1004    @property1005    def size(self) -> ConsoleDimensions:1006        """Get the size of the console.1007 1008        Returns:1009            ConsoleDimensions: A named tuple containing the dimensions.1010        """1011 1012        if self._width is not None and self._height is not None:1013            return ConsoleDimensions(self._width - self.legacy_windows, self._height)1014 1015        if self.is_dumb_terminal:1016            return ConsoleDimensions(80, 25)1017 1018        width: Optional[int] = None1019        height: Optional[int] = None1020 1021        streams = _STD_STREAMS_OUTPUT if WINDOWS else _STD_STREAMS1022        for file_descriptor in streams:1023            try:1024                width, height = os.get_terminal_size(file_descriptor)1025            except (AttributeError, ValueError, OSError):  # Probably not a terminal1026                pass1027            else:1028                break1029 1030        columns = self._environ.get("COLUMNS")1031        if columns is not None and columns.isdigit():1032            width = int(columns)1033        lines = self._environ.get("LINES")1034        if lines is not None and lines.isdigit():1035            height = int(lines)1036 1037        # get_terminal_size can report 0, 0 if run from pseudo-terminal1038        width = width or 801039        height = height or 251040        return ConsoleDimensions(1041            width - self.legacy_windows if self._width is None else self._width,1042            height if self._height is None else self._height,1043        )1044 1045    @size.setter1046    def size(self, new_size: Tuple[int, int]) -> None:1047        """Set a new size for the terminal.1048 1049        Args:1050            new_size (Tuple[int, int]): New width and height.1051        """1052        width, height = new_size1053        self._width = width1054        self._height = height1055 1056    @property1057    def width(self) -> int:1058        """Get the width of the console.1059 1060        Returns:1061            int: The width (in characters) of the console.1062        """1063        return self.size.width1064 1065    @width.setter1066    def width(self, width: int) -> None:1067        """Set width.1068 1069        Args:1070            width (int): New width.1071        """1072        self._width = width1073 1074    @property1075    def height(self) -> int:1076        """Get the height of the console.1077 1078        Returns:1079            int: The height (in lines) of the console.1080        """1081        return self.size.height1082 1083    @height.setter1084    def height(self, height: int) -> None:1085        """Set height.1086 1087        Args:1088            height (int): new height.1089        """1090        self._height = height1091 1092    def bell(self) -> None:1093        """Play a 'bell' sound (if supported by the terminal)."""1094        self.control(Control.bell())1095 1096    def capture(self) -> Capture:1097        """A context manager to *capture* the result of print() or log() in a string,1098        rather than writing it to the console.1099 1100        Example:1101            >>> from rich.console import Console1102            >>> console = Console()1103            >>> with console.capture() as capture:1104            ...     console.print("[bold magenta]Hello World[/]")1105            >>> print(capture.get())1106 1107        Returns:1108            Capture: Context manager with disables writing to the terminal.1109        """1110        capture = Capture(self)1111        return capture1112 1113    def pager(1114        self, pager: Optional[Pager] = None, styles: bool = False, links: bool = False1115    ) -> PagerContext:1116        """A context manager to display anything printed within a "pager". The pager application1117        is defined by the system and will typically support at least pressing a key to scroll.1118 1119        Args:1120            pager (Pager, optional): A pager object, or None to use :class:`~rich.pager.SystemPager`. Defaults to None.1121            styles (bool, optional): Show styles in pager. Defaults to False.1122            links (bool, optional): Show links in pager. Defaults to False.1123 1124        Example:1125            >>> from rich.console import Console1126            >>> from rich.__main__ import make_test_card1127            >>> console = Console()1128            >>> with console.pager():1129                    console.print(make_test_card())1130 1131        Returns:1132            PagerContext: A context manager.1133        """1134        return PagerContext(self, pager=pager, styles=styles, links=links)1135 1136    def line(self, count: int = 1) -> None:1137        """Write new line(s).1138 1139        Args:1140            count (int, optional): Number of new lines. Defaults to 1.1141        """1142 1143        assert count >= 0, "count must be >= 0"1144        self.print(NewLine(count))1145 1146    def clear(self, home: bool = True) -> None:1147        """Clear the screen.1148 1149        Args:1150            home (bool, optional): Also move the cursor to 'home' position. Defaults to True.1151        """1152        if home:1153            self.control(Control.clear(), Control.home())1154        else:1155            self.control(Control.clear())1156 1157    def status(1158        self,1159        status: RenderableType,1160        *,1161        spinner: str = "dots",1162        spinner_style: StyleType = "status.spinner",1163        speed: float = 1.0,1164        refresh_per_second: float = 12.5,1165    ) -> "Status":1166        """Display a status and spinner.1167 1168        Args:1169            status (RenderableType): A status renderable (str or Text typically).1170            spinner (str, optional): Name of spinner animation (see python -m rich.spinner). Defaults to "dots".1171            spinner_style (StyleType, optional): Style of spinner. Defaults to "status.spinner".1172            speed (float, optional): Speed factor for spinner animation. Defaults to 1.0.1173            refresh_per_second (float, optional): Number of refreshes per second. Defaults to 12.5.1174 1175        Returns:1176            Status: A Status object that may be used as a context manager.1177        """1178        from .status import Status1179 1180        status_renderable = Status(1181            status,1182            console=self,1183            spinner=spinner,1184            spinner_style=spinner_style,1185            speed=speed,1186            refresh_per_second=refresh_per_second,1187        )1188        return status_renderable1189 1190    def show_cursor(self, show: bool = True) -> bool:1191        """Show or hide the cursor.1192 1193        Args:1194            show (bool, optional): Set visibility of the cursor.1195        """1196        if self.is_terminal:1197            self.control(Control.show_cursor(show))1198            return True1199        return False1200 

Showing the first 1,200 of 2699 lines. Download the file for the rest.

codekingpro/portable-devtools · Team Ai