1from __future__ import annotations 
    2 
    3import sys 
    4from typing import TYPE_CHECKING, TextIO, cast 
    5 
    6from prompt_toolkit.utils import ( 
    7    get_bell_environment_variable, 
    8    get_term_environment_variable, 
    9    is_conemu_ansi, 
    10) 
    11 
    12from .base import DummyOutput, Output 
    13from .color_depth import ColorDepth 
    14from .plain_text import PlainTextOutput 
    15 
    16if TYPE_CHECKING: 
    17    from prompt_toolkit.patch_stdout import StdoutProxy 
    18 
    19 
    20__all__ = [ 
    21    "create_output", 
    22] 
    23 
    24 
    25def create_output( 
    26    stdout: TextIO | StdoutProxy | None = None, always_prefer_tty: bool = False 
    27) -> Output: 
    28    """ 
    29    Return an :class:`~prompt_toolkit.output.Output` instance for the command 
    30    line. 
    31 
    32    :param stdout: The stdout object 
    33    :param always_prefer_tty: When set, look for `sys.stderr` if `sys.stdout` 
    34        is not a TTY. Useful if `sys.stdout` is redirected to a file, but we 
    35        still want user input and output on the terminal. 
    36 
    37        By default, this is `False`. If `sys.stdout` is not a terminal (maybe 
    38        it's redirected to a file), then a `PlainTextOutput` will be returned. 
    39        That way, tools like `print_formatted_text` will write plain text into 
    40        that file. 
    41    """ 
    42    # Consider TERM, PROMPT_TOOLKIT_BELL, and PROMPT_TOOLKIT_COLOR_DEPTH 
    43    # environment variables. Notice that PROMPT_TOOLKIT_COLOR_DEPTH value is 
    44    # the default that's used if the Application doesn't override it. 
    45    term_from_env = get_term_environment_variable() 
    46    bell_from_env = get_bell_environment_variable() 
    47    color_depth_from_env = ColorDepth.from_env() 
    48 
    49    if stdout is None: 
    50        # By default, render to stdout. If the output is piped somewhere else, 
    51        # render to stderr. 
    52        stdout = sys.stdout 
    53 
    54        if always_prefer_tty: 
    55            for io in [sys.stdout, sys.stderr]: 
    56                if io is not None and io.isatty(): 
    57                    # (This is `None` when using `pythonw.exe` on Windows.) 
    58                    stdout = io 
    59                    break 
    60 
    61    # If the patch_stdout context manager has been used, then sys.stdout is 
    62    # replaced by this proxy. For prompt_toolkit applications, we want to use 
    63    # the real stdout. 
    64    from prompt_toolkit.patch_stdout import StdoutProxy 
    65 
    66    while isinstance(stdout, StdoutProxy): 
    67        stdout = stdout.original_stdout 
    68 
    69    # If the output is still `None`, use a DummyOutput. 
    70    # This happens for instance on Windows, when running the application under 
    71    # `pythonw.exe`. In that case, there won't be a terminal Window, and 
    72    # stdin/stdout/stderr are `None`. 
    73    if stdout is None: 
    74        return DummyOutput() 
    75 
    76    if sys.platform == "win32": 
    77        from .conemu import ConEmuOutput 
    78        from .win32 import Win32Output 
    79        from .windows10 import Windows10_Output, is_win_vt100_enabled 
    80 
    81        if is_win_vt100_enabled(): 
    82            return cast( 
    83                Output, 
    84                Windows10_Output(stdout, default_color_depth=color_depth_from_env), 
    85            ) 
    86        if is_conemu_ansi(): 
    87            return cast( 
    88                Output, ConEmuOutput(stdout, default_color_depth=color_depth_from_env) 
    89            ) 
    90        else: 
    91            return Win32Output(stdout, default_color_depth=color_depth_from_env) 
    92    else: 
    93        from .vt100 import Vt100_Output 
    94 
    95        # Stdout is not a TTY? Render as plain text. 
    96        # This is mostly useful if stdout is redirected to a file, and 
    97        # `print_formatted_text` is used. 
    98        if not stdout.isatty(): 
    99            return PlainTextOutput(stdout) 
    100 
    101        return Vt100_Output.from_pty( 
    102            stdout, 
    103            term=term_from_env, 
    104            default_color_depth=color_depth_from_env, 
    105            enable_bell=bell_from_env, 
    106        )