progressbar.env module

Environment-driven terminal capability detection.

Resolves two independent questions about an output stream: whether it is a terminal at all (is_terminal, via is_ansi_terminal) and how many colors it can display (ColorSupport, computed once at import time as COLOR_SUPPORT). See docs/explanation/terminal-detection.rst for the full precedence rules and worked examples.

progressbar.env.ANSI_TERMS: tuple[str, ...] = ('([xe]|bv)term', '(sco)?ansi', 'cygwin', 'konsole', 'linux', 'rxvt', 'screen', 'tmux', 'vt(10[02]|220|320)')

Regex fragments (unanchored) recognized as ANSI-capable TERM values.

progressbar.env.ANSI_TERM_RE: Pattern[str] = re.compile('^(([xe]|bv)term|(sco)?ansi|cygwin|konsole|linux|rxvt|screen|tmux|vt(10[02]|220|320))', re.IGNORECASE)

Compiled prefix match against ANSI_TERMS, case-insensitive.

class progressbar.env.ColorSupport(*values)[source]

Bases: IntEnum

Color support for the terminal.

NONE = 0
WINDOWS = 8
XTERM = 16
XTERM_256 = 256
XTERM_TRUECOLOR = 16777216
classmethod from_env() ColorSupport[source]

Get the color support from the environment.

A variable containing 24bit or truecolor, a TERM naming a truecolor terminal (see TRUECOLOR_TERMS), or a Jupyter kernel (JUPYTER_COLUMNS/JUPYTER_LINES/JPY_PARENT_PID set) enables true color. A value containing 256 enables 256-color support, and a match against a known ANSI terminal (see ANSI_TERM_RE, e.g. xterm-color, screen, tmux) enables 16-color support. Otherwise no color support is assumed. The highest depth seen wins: COLORTERM=truecolor overrides TERM=xterm-256color.

progressbar.env.JUPYTER: bool = False

Whether this process looks like it’s running inside a Jupyter kernel, computed once at import time from JUPYTER_COLUMNS/JUPYTER_LINES/ JPY_PARENT_PID. Jupyter and Windows short-circuit color/terminal detection ahead of everything else – see ColorSupport.from_env and is_ansi_terminal.

progressbar.env.TRUECOLOR_TERMS: frozenset[str] = frozenset({'xterm-ghostty', 'xterm-kitty'})

TERM values that on their own guarantee a truecolor-capable terminal, so 24-bit color still engages when COLORTERM is stripped (e.g. over ssh or sudo). Limited to names that are the terminal, since generic values such as xterm-256color are used by plenty of 256-only emulators.

progressbar.env.env_flag(name: str, default: bool) bool[source]
progressbar.env.env_flag(name: str, default: bool | None = None) bool | None

Read a boolean-ish environment variable.

Parameters:
  • name – Environment variable to read.

  • default – Returned when name is unset or its value isn’t recognized.

Returns:

True for y/yes/t/true/on/1, False for n/no/f/false/off/0 (case-insensitive), otherwise default.

progressbar.env.is_ansi_terminal(fd: IO[Any], is_terminal: bool | None = None) bool | None[source]

Detect whether fd looks like an ANSI-capable terminal.

Tri-state, not boolean: True is a confirmed ANSI terminal, and None means detection was inconclusive rather than negative. Outside the Windows branch this function never returns False on its own: an unmatched TERM, no ANSICON, or a stream that can’t answer isatty() is left as None, so callers such as is_terminal keep falling back instead of concluding “not a terminal” from missing information. The Windows console-mode probe is the one exception: it is authoritative there and can return a definite False.

Detection order: an interactive Jupyter kernel or a modern-enough PyCharm terminal (not under pytest) short-circuits straight to True, since both render ANSI without being a tty. Otherwise, fd.isatty() plus a TERM match against ANSI_TERM_RE, or ANSICON being set, or (on Windows) the console-mode probe (see os_specific.windows.get_console_mode for what that probe actually tests, which is not what its flag name suggests). Only the errors a stream can legitimately raise while being probed are swallowed: OSError (real I/O), ValueError (closed/detached file) and AttributeError (no isatty at all). Anything else is a bug and propagates.

Parameters:
  • fd – Stream to probe.

  • is_terminal – Already-known answer, if any, passed straight through unchanged. Only None triggers detection.

Returns:

True, False, or None (undetermined) – see above.

progressbar.env.is_terminal(fd: IO[Any], is_terminal: bool | None = None) bool | None[source]

Resolve whether fd should be treated as an interactive terminal.

Falls back through the following, stopping at the first non-None result: the is_terminal argument if the caller already knows. Then is_ansi_terminal(fd), with any falsy result normalized back to None (including the definite False the Windows branch can return, because “no ANSI support” is not the same answer as “not a terminal”). Then the PROGRESSBAR_IS_TERMINAL environment variable, an explicit override for cases auto-detection can’t cover. Finally a bare fd.isatty(), defaulting to False if the stream can’t answer at all (closed, detached, or missing isatty).

Parameters:
  • fd – Stream to probe.

  • is_terminal – Known answer, if already determined by the caller.

Returns:

True or False once resolved – the final fallback always settles on a boolean, so a caller never sees None back.