stouputils.print.output_stream module#
- LINE_TOKENS_RE: Pattern[str] = re.compile('(\\n|\\r|\\x1b\\[\\d*[AB])')[source]#
newlines, carriage returns and line moves.
- Type:
Splits a text around what moves a terminal cursor
- REDRAW_CHECKPOINT_SECONDS: float = 60.0[source]#
Interval at which a file receives the current state of a line still being redrawn, such as a long progress bar.
- class LineState(
- checkpoint_seconds: float = 60.0,
- mode: Literal['start', 'text', 'redraw', 'repeat'] = 'start',
- buffer: str = '',
- shown: bool = False,
- carriage: bool = False,
- held_repeat: str = '',
- since: float = 0.0,
Bases:
objectWhere a non-terminal output stands in the line one thread is writing, so it receives what a terminal ends up showing.
Text is held until its line ends or the stream is flushed, like a terminal’s line-buffered stdout. Lines from several threads therefore never cut into each other. A line drawn again after a carriage return, such as a progress bar, is written once in its final state, plus every
checkpoint_secondswhile it lasts. A line starting with a cursor move rewrites the previous one, as stouputils does for a repeated message, and the last of such a series is written when the series ends.>>> state = LineState() >>> state.feed("\r 10%") + state.feed("\r100%\n") + state.feed("done\n") '100%\ndone\n' >>> state.feed("same\n") + state.feed("\x1b[1Asame (x2)\n") + state.feed("\x1b[1Asame (x3)\n") + state.feed("other\n") 'same\nsame (x3)\nother\n' >>> state.feed("Processing..."), state.flush(), state.feed(" done\n") ('', 'Processing...', ' done\n')
- mode: Literal['start', 'text', 'redraw', 'repeat'] = 'start'[source]#
not started, plain text, drawn again after a carriage return, or rewriting the previous line.
- Type:
What the current line is
- buffer: str = ''[source]#
Text of the current line not written yet, its last drawing for a redrawn line.
- carriage: bool = False[source]#
Whether a carriage return came since the last text, so the next text draws the line again.
- take(token: str) str[source]#
What the output receives of one token: a newline, a carriage return, a line move or plain text.
- draw(token: str) str[source]#
Add text to the current line, a carriage return before it starting the drawing over.
- flush() str[source]#
The unwritten text of a plain line, which a terminal shows on flush, so a step announced without newline shows.
- class TeeTarget(file: ~typing.IO[~typing.Any], thread: int | None = None, strip_colors: bool = True, ascii_only: bool = True, ignore_lineup: bool = True, lines: dict[int, ~stouputils.print.output_stream.LineState] = <factory>, lock: ~_thread.allocate_lock = <factory>)[source]#
Bases:
objectOne output of a
TeeMultiOutput, with how it is written to and which thread it listens to.- ascii_only: bool = True[source]#
Whether non-ASCII characters are replaced, when the output is not a terminal.
- ignore_lineup: bool = True[source]#
Whether the output receives what a terminal ends up showing, when it is not a terminal itself.
- terminal: bool[source]#
Whether the output is a terminal, read once since asking costs a system call.
- write(obj: str) int | None[source]#
Write the text as this output receives it.
- Returns:
Characters written, or None when the output is closed and has to be dropped.
- finish() None[source]#
Write what every thread’s current line still holds back, as when the stream ends.
- class TeeMultiOutput(
- *files: IO[Any],
- strip_colors: bool = True,
- ascii_only: bool = True,
- ignore_lineup: bool = True,
Bases:
objectFile-like object that duplicates output to multiple file-like objects.
Outputs can be added and removed while it is in place, each one listening to every thread or to a single one.
- Parameters:
*files – One or more file-like objects that have write and flush methods
strip_colors – Strip ANSI color codes from output sent to these files
ascii_only – Replace non-ASCII characters with their ASCII equivalents for non-stdout/stderr files
ignore_lineup – Write to non-terminal outputs what a terminal ends up showing, see
LineState
>>> import sys >>> f = open("logfile.txt", "w") >>> sys.stdout = TeeMultiOutput(sys.stdout, f) >>> print("Hello World") # Output goes to both console and file Hello World >>> f.close() # TeeMultiOutput will handle any future writes to closed files gracefully
- targets: tuple[TeeTarget, ...][source]#
Outputs written to, the first one standing for the stream this object replaces
- removable: bool[source]#
Whether
LogToFileput it in place, and takes it away with the last file it holds
- property encoding: str[source]#
Get the encoding of the first file, or “utf-8” as fallback. :returns: “utf-8”, “ascii”, “latin1”, etc. :rtype: The encoding, ex
- write(obj: str) int[source]#
Write the object to every output listening to the current thread.
- Parameters:
obj – String to write
- Returns:
Number of characters written to the first file
- add_file(
- file: IO[Any],
- thread: int | None = None,
- strip_colors: bool = True,
- ascii_only: bool = True,
- ignore_lineup: bool = True,
Start writing to one more output.
- Parameters:
thread – Thread identifier whose writes alone it receives, None for every thread.