Source code for progressbar.env

from __future__ import annotations

import contextlib
import enum
import os
import re
import typing

from . import base


@typing.overload
def env_flag(name: str, default: bool) -> bool: ...


@typing.overload
def env_flag(name: str, default: bool | None = None) -> bool | None: ...


[docs] def env_flag(name, default=None): ''' Accepts environt variables formatted as y/n, yes/no, 1/0, true/false, on/off, and returns it as a boolean. If the environment variable is not defined, or has an unknown value, returns `default` ''' v = os.getenv(name) if v and v.lower() in ('y', 'yes', 't', 'true', 'on', '1'): return True if v and v.lower() in ('n', 'no', 'f', 'false', 'off', '0'): return False return default
[docs] class ColorSupport(enum.IntEnum): '''Color support for the terminal.''' NONE = 0 XTERM = 16 XTERM_256 = 256 XTERM_TRUECOLOR = 16777216 WINDOWS = 8
[docs] @classmethod def from_env(cls): '''Get the color support from the environment. If any of the environment variables contain `24bit` or `truecolor`, we will enable true color/24 bit support. If they contain `256`, we will enable 256 color/8 bit support. If they contain `xterm`, we will enable 16 color support. Otherwise, we will assume no color support. If `JUPYTER_COLUMNS` or `JUPYTER_LINES` or `JPY_PARENT_PID` is set, we will assume true color support. Note that the highest available value will be used! Having `COLORTERM=truecolor` will override `TERM=xterm-256color`. ''' variables = ( 'FORCE_COLOR', 'PROGRESSBAR_ENABLE_COLORS', 'COLORTERM', 'TERM', ) if JUPYTER: # Jupyter notebook always supports true color. return cls.XTERM_TRUECOLOR elif os.name == 'nt': # We can't reliably detect true color support on Windows, so we # will assume it is supported if the console is configured to # support it. from .terminal.os_specific import windows if ( windows.get_console_mode() & windows.WindowsConsoleModeFlags.ENABLE_PROCESSED_OUTPUT ): return cls.XTERM_TRUECOLOR else: return cls.WINDOWS # pragma: no cover support = cls.NONE for variable in variables: value = os.environ.get(variable) if value is None: continue elif value in {'truecolor', '24bit'}: # Truecolor support, we don't need to check anything else. support = cls.XTERM_TRUECOLOR break elif '256' in value: support = max(cls.XTERM_256, support) elif value == 'xterm': support = max(cls.XTERM, support) return support
[docs] def is_ansi_terminal( fd: base.IO, is_terminal: bool | None = None, ) -> bool | None: # pragma: no cover if is_terminal is None: # Jupyter Notebooks support progress bars if JUPYTER: is_terminal = True # This works for newer versions of pycharm only. With older versions # there is no way to check. elif os.environ.get('PYCHARM_HOSTED') == '1' and not os.environ.get( 'PYTEST_CURRENT_TEST' ): is_terminal = True if is_terminal is None: # check if we are writing to a terminal or not. typically a file object # is going to return False if the instance has been overridden and # isatty has not been defined we have no way of knowing so we will not # use ansi. ansi terminals will typically define one of the 2 # environment variables. with contextlib.suppress(Exception): is_tty = fd.isatty() # Try and match any of the huge amount of Linux/Unix ANSI consoles if is_tty and ANSI_TERM_RE.match(os.environ.get('TERM', '')): is_terminal = True # ANSICON is a Windows ANSI compatible console elif 'ANSICON' in os.environ: is_terminal = True elif os.name == 'nt': from .terminal.os_specific import windows return bool( windows.get_console_mode() & windows.WindowsConsoleModeFlags.ENABLE_PROCESSED_OUTPUT, ) else: is_terminal = None return is_terminal
[docs] def is_terminal(fd: base.IO, is_terminal: bool | None = None) -> bool | None: if is_terminal is None: # Full ansi support encompasses what we expect from a terminal is_terminal = is_ansi_terminal(fd) or None if is_terminal is None: # Allow a environment variable override is_terminal = env_flag('PROGRESSBAR_IS_TERMINAL', None) if is_terminal is None: # pragma: no cover # Bare except because a lot can go wrong on different systems. If we do # get a TTY we know this is a valid terminal try: is_terminal = fd.isatty() except Exception: is_terminal = False return is_terminal
# Enable Windows full color mode if possible if os.name == 'nt': pass # os_specific.set_console_mode() JUPYTER = bool( os.environ.get('JUPYTER_COLUMNS') or os.environ.get('JUPYTER_LINES') or os.environ.get('JPY_PARENT_PID') ) COLOR_SUPPORT = ColorSupport.from_env() ANSI_TERMS = ( '([xe]|bv)term', '(sco)?ansi', 'cygwin', 'konsole', 'linux', 'rxvt', 'screen', 'tmux', 'vt(10[02]|220|320)', ) ANSI_TERM_RE = re.compile(f"^({'|'.join(ANSI_TERMS)})", re.IGNORECASE)