Io

This module implements user-friendly console input and output.

Configuration

Yuio configures itself upon import using environment variables:

The only thing it doesn’t do automatically is wrapping sys.stdout and sys.stderr into safe proxies. The yuio.app CLI builder will do it for you, though, so you don’t need to worry about it.

yuio.io.setup(
*,
term: Term | None = None,
theme: Theme | Callable[[Term], Theme] | None = None,
wrap_stdio: bool = True,
)

Initial setup of the logging facilities.

Parameters:
  • term

    terminal that will be used for output.

    If not passed, the global terminal is not re-configured; the default is to use a term attached to sys.stderr.

  • theme

    either a theme that will be used for output, or a theme constructor that takes a Term and returns a theme.

    If not passed, the global theme is not re-configured; the default is to use yuio.theme.DefaultTheme then.

  • wrap_stdio

    if set to True, wraps sys.stdout and sys.stderr in a special wrapper that ensures better interaction with Yuio’s progress bars and widgets.

    Note

    If you’re working with some other library that wraps sys.stdout and sys.stderr, such as colorama, initialize it before Yuio.

Warning

This operation is not atomic. Call this function before creating new threads that use yuio.io or output streams to avoid race conditions.

To introspect the current state of Yuio’s initialization, use the following functions:

yuio.io.get_term() Term

Get the global instance of Term that is used with yuio.io.

If global setup wasn’t performed, this function implicitly performs it.

Returns:

Instance of Term that’s used to print messages and tasks.

yuio.io.get_theme() Theme

Get the global instance of Theme that is used with yuio.io.

If global setup wasn’t performed, this function implicitly performs it.

Returns:

Instance of Theme that’s used to format messages and tasks.

yuio.io.wrap_streams()

Wrap sys.stdout and sys.stderr so that they honor Yuio tasks and widgets. If strings are already wrapped, this function has no effect.

Note

If you’re working with some other library that wraps sys.stdout and sys.stderr, such as colorama, initialize it before Yuio.

See also

setup().

yuio.io.restore_streams()

Restore wrapped streams. If streams weren’t wrapped, this function has no effect.

yuio.io.streams_wrapped() bool

Check if sys.stdout and sys.stderr are wrapped. See setup().

Returns:

True is streams are currently wrapped, False otherwise.

yuio.io.orig_stderr() TextIO

Return the original sys.stderr before wrapping.

yuio.io.orig_stdout() TextIO

Return the original sys.stdout before wrapping.

Printing messages

To print messages for the user, there are functions with an interface similar to the one from logging. Messages are highlighted using color tags and formatted using either %-formatting or template strings.

yuio.io.info(msg: LiteralString, /, *args, **kwargs)
yuio.io.info(msg: Template, /, **kwargs)
yuio.io.info(msg: ToColorable, /, **kwargs)

Print an info message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.warning(msg: LiteralString, /, *args, **kwargs)
yuio.io.warning(msg: Template, /, **kwargs)
yuio.io.warning(msg: ToColorable, /, **kwargs)

Print a warning message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.success(msg: LiteralString, /, *args, **kwargs)
yuio.io.success(msg: Template, /, **kwargs)
yuio.io.success(msg: ToColorable, /, **kwargs)

Print a success message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.failure(msg: LiteralString, /, *args, **kwargs)
yuio.io.failure(msg: Template, /, **kwargs)
yuio.io.failure(msg: ToColorable, /, **kwargs)

Print a failure message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.failure_with_tb(msg: LiteralString, /, *args, **kwargs)
yuio.io.failure_with_tb(msg: Template, /, **kwargs)
yuio.io.failure_with_tb(msg: ToColorable, /, **kwargs)

Print a failure message and capture the current exception.

Call this function in the except clause of a try block or in an __exit__ function of a context manager to attach current exception details to the log message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.error(msg: LiteralString, /, *args, **kwargs)
yuio.io.error(msg: Template, /, **kwargs)
yuio.io.error(msg: ToColorable, /, **kwargs)

Print an error message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.error_with_tb(msg: LiteralString, /, *args, **kwargs)
yuio.io.error_with_tb(msg: Template, /, **kwargs)
yuio.io.error_with_tb(msg: ToColorable, /, **kwargs)

Print an error message and capture the current exception.

Call this function in the except clause of a try block or in an __exit__ function of a context manager to attach current exception details to the log message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.heading(msg: LiteralString, /, *args, level: int = 1, **kwargs)
yuio.io.heading(msg: Template, /, *, level: int = 1, **kwargs)
yuio.io.heading(msg: ToColorable, /, *, level: int = 1, **kwargs)

Print a heading message.

Parameters:
  • msg – message to print.

  • args – arguments for %-formatting the message.

  • level – level of the heading.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.md(msg: str, /, *, dedent: bool = True, allow_headings: bool = True, **kwargs)

Print a markdown-formatted text.

Yuio supports all CommonMark block markup except tables. See yuio.md for more info.

Parameters:
  • msg – message to print.

  • dedent – whether to remove leading indent from msg.

  • allow_headings – whether to render headings as actual headings or as paragraphs.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.rst(msg: str, /, *, dedent: bool = True, allow_headings: bool = True, **kwargs)

Print a RST-formatted text.

Yuio supports all RST block markup except tables and field lists. See yuio.rst for more info.

Parameters:
  • msg – message to print.

  • dedent – whether to remove leading indent from msg.

  • allow_headings – whether to render headings as actual headings or as paragraphs.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.hl(
msg: LiteralString,
/,
*args,
syntax: str,
dedent: bool = True,
**kwargs,
)
yuio.io.hl(msg: str, /, *, syntax: str, dedent: bool = True, **kwargs)

Print highlighted code. See yuio.hl for more info.

Parameters:
  • msg – code to highlight.

  • args – arguments for %-formatting the highlighted code.

  • syntax – name of syntax or a SyntaxHighlighter instance.

  • dedent – whether to remove leading indent from msg.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.br(**kwargs)

Print an empty string.

Parameters:

kwargs – any additional keyword arguments will be passed to raw().

yuio.io.hr(msg: LiteralString = '', /, *args, weight: int | str = 1, **kwargs)
yuio.io.hr(msg: Template, /, *, weight: int | str = 1, **kwargs)
yuio.io.hr(msg: ToColorable, /, *, weight: int | str = 1, **kwargs)

Print a horizontal ruler.

Parameters:
  • msg – message to print in the middle of the ruler.

  • args – arguments for %-formatting the message.

  • weight

    weight or style of the ruler:

    • 0 prints no ruler (but still prints centered text),

    • 1 prints normal ruler,

    • 2 prints bold ruler.

    Additional styles can be added through Theme.msg_decorations.

  • kwargs – any additional keyword arguments will be passed to raw().

yuio.io.raw(
msg: Colorable,
/,
*,
ignore_suspended: bool = False,
tag: str | None = None,
exc_info: ExcInfo | bool | None = None,
add_newline: bool = False,
heading: bool = False,
wrap: bool = False,
ctx: ReprContext | None = None,
term: Term | None = None,
to_stdout: bool = False,
to_stderr: bool = False,
theme: Theme | None = None,
multiline: bool | None = None,
highlighted: bool | None = None,
max_depth: int | None = None,
width: int | None = None,
)

Print any ToColorable.

This is a bridge between yuio.io and lower-level modules like yuio.string.

Parameters:
  • msg – message to print.

  • ignore_suspended – whether to ignore SuspendOutput context.

  • tag

    tag that will be used to add color and decoration to the message.

    Decoration is looked up by path tag (see Theme.msg_decorations), and color is looked up by path msg/text:tag (see Theme.colors).

  • exc_info – either a boolean indicating that the current exception should be captured, or a tuple of three elements, as returned by sys.exc_info().

  • add_newline – adds newline after the message.

  • heading

    whether to separate message by extra newlines.

    If True, adds extra newline after the message; if this is not the first message printed so far, adds another newline before the message.

  • wrap – whether to wrap message before printing it.

  • ctxReprContext that should be used for formatting and printing the message.

  • term – if ctx is not given, sets terminal where to print this message. Default is to use get_term().

  • to_stdout – shortcut for setting term to stdout.

  • to_stderr – shortcut for setting term to stderr.

  • theme – if ctx is not given, sets theme used to format the message. Default is to use get_theme().

  • multiline – if ctx is not given, sets initial value for ReprContext.multiline. Default is False.

  • highlighted – if ctx is not given, sets initial value for ReprContext.highlighted. Default is False.

  • max_depth – if ctx is not given, sets initial value for ReprContext.max_depth. Default is False.

  • width – if ctx is not given, sets initial value for ReprContext.width. If not given, uses current terminal width or Theme.fallback_width if terminal width can’t be established.

Formatting the output

Yuio supports printf-style formatting, similar to logging. If you’re using Python 3.14 or later, you can also use template strings.

%s and %r specifiers are handled to respect colors and rich repr protocol. Additionally, they allow specifying flags to control whether rendered values should be highlighted, and should they be rendered in multiple lines:

  • # enables colors in repr (i.e. %#r);

  • + splits repr into multiple lines (i.e. %+r, %#+r).

yuio.io.info("Loaded config: %#+r", config)

When formatting template strings, default format specification is extended to respect colors and rich repr protocol. Additionally, it allows specifying flags to control whether rendered values should be highlighted, and should they be rendered in multiple lines:

  • # enables colors in repr (i.e. {var:#});

  • + splits repr into multiple lines (i.e. {var:+}, {var:#+});

  • unless explicit conversion is given (i.e. !s, !r, or !a), this format specification applies to objects that don’t define custom __format__ method;

  • full format specification is available here.

yuio.io.info(t"Loaded config: {config!r:#+}")

Note

The formatting algorithm is as follows:

  1. if formatting conversion is specified (i.e. !s, !r, or !a), the object is passed to ReprContext.convert();

  2. otherwise, if object defines custom __format__ method, this method is used;

  3. otherwise, we fall back to ReprContext.convert() with assumed conversion flag "s".

To support highlighted formatting, define __colorized_str__ or __colorized_repr__ on your class. See Pretty printing protocol for implementation details.

To support rich repr protocol, define function __rich_repr__ on your class. This method should return an iterable of tuples, as described in Rich documentation.

Coloring the output

By default, all messages are colored according to their level (i.e. which function you use to print them).

If you need inline colors, you can use special tags in your log messages:

yuio.io.info("Using the <c code>code</c> tag.")

You can combine multiple colors in the same tag:

yuio.io.info("<c bold green>Success!</c>")

Only tags that appear in the message itself are processed:

yuio.io.info("Tags in this message --> %s are printed as-is", "<c color>")
value = "<c color>"
yuio.io.info(t"Tags in this message --> {value} are printed as-is")

For highlighting inline code, Yuio supports parsing CommonMark’s backticks:

yuio.io.info("Using the `backticks`.")
yuio.io.info("Using the `` nested `backticks` ``")

Any punctuation symbol can be escaped with backslash:

yuio.io.info(r"\`\<c red> this is normal text \</c>\`.")

See full list of tags in yuio.theme.

Message channels

class yuio.io.MessageChannel(**kwargs)

Message channels are similar to logging adapters: they allow adding additional arguments for calls to raw() and other message functions.

This is useful when you need to control destination for messages, but don’t want to override global settings via setup(). One example for them is described in Print formatted text to file.

Protected members
_msg_kwargs: dict[str, Any]

Keyword arguments that will be added to every message.

_update_kwargs(kwargs: dict[str, Any])

A hook that updates method’s kwargs before calling its implementation.

_is_enabled()

A hook that check if the message should be printed. By default, returns value of enabled.

enabled: bool

Message channel can be disabled, in which case messages are not printed.

info(msg: LiteralString, /, *args, **kwargs)
info(msg: Template, /, **kwargs)
info(msg: ToColorable, /, **kwargs)

Print an info() message.

warning(msg: LiteralString, /, *args, **kwargs)
warning(msg: Template, /, **kwargs)
warning(msg: ToColorable, /, **kwargs)

Print a warning() message.

success(msg: LiteralString, /, *args, **kwargs)
success(msg: Template, /, **kwargs)
success(msg: ToColorable, /, **kwargs)

Print a success() message.

error(msg: LiteralString, /, *args, **kwargs)
error(msg: Template, /, **kwargs)
error(msg: ToColorable, /, **kwargs)

Print an error() message.

error_with_tb(msg: LiteralString, /, *args, **kwargs)
error_with_tb(msg: Template, /, **kwargs)
error_with_tb(msg: ToColorable, /, **kwargs)

Print an error_with_tb() message.

failure(msg: LiteralString, /, *args, **kwargs)
failure(msg: Template, /, **kwargs)
failure(msg: ToColorable, /, **kwargs)

Print a failure() message.

failure_with_tb(msg: LiteralString, /, *args, **kwargs)
failure_with_tb(msg: Template, /, **kwargs)
failure_with_tb(msg: ToColorable, /, **kwargs)

Print a failure_with_tb() message.

heading(msg: LiteralString, /, *args, **kwargs)
heading(msg: Template, /, **kwargs)
heading(msg: ToColorable, /, **kwargs)

Print a heading() message.

md(msg: str, /, **kwargs)

Print an md() message.

rst(msg: str, /, **kwargs)

Print an rst() message.

br()

Print a br() message.

hl(
msg: LiteralString,
/,
*args,
syntax: str,
dedent: bool = True,
**kwargs,
)
hl(msg: str, /, *, syntax: str, dedent: bool = True, **kwargs)

Print an hl() message.

hr(
msg: LiteralString = '',
/,
*args,
weight: int | str = 1,
**kwargs,
)
hr(
msg: Template,
/,
*,
weight: int | str = 1,
**kwargs,
)
hr(
msg: ToColorable,
/,
*,
weight: int | str = 1,
**kwargs,
)

Print an hr() message.

raw(msg: Colorable, /, **kwargs)

Print a raw() message.

make_repr_context() ReprContext

Make a ReprContext using settings from _msg_kwargs.

Formatting utilities

There are several formatting utilities defined in yuio.string and re-exported in yuio.io. These utilities perform various formatting tasks when converted to strings, allowing you to lazily build more complex messages.

Indicating progress

You can use the Task class to indicate status and progress of some task.

class yuio.io.TaskBase

Base class for tasks and other objects that you might show to the user.

Example of a custom task can be found in cookbook.

Protected members
property _lock

Global IO lock.

All protected methods, as well as state mutations, should happen under this lock.

abstractmethod _get_widget() Widget[Never]

This method should return widget that renders the task.

Warning

This method should be called under _lock.

abstractmethod _get_priority() int

This method should return priority that will be used to hide non-important tasks when there is not enough space to show all of them.

Default priority is 1, priority for finished tasks is 0.

Warning

This method should be called under _lock.

_request_update(*, immediate_render: bool = False)

Indicate that task’s state has changed, and update is necessary.

Warning

This method should be called under _lock.

Parameters:

immediate_render – by default, tasks are updated lazily from a background thread; set this parameter to True to redraw them immediately from this thread.

_widgets_are_displayed() bool

Return True if we’re in an interactive foreground process which renders tasks.

If this function returns False, you should print log messages about task status instead of relying on task’s widget being presented to the user.

Warning

This method should be called under _lock.

_get_parent() TaskBase | None

Get parent task.

Warning

This method should be called under _lock.

_is_toplevel() bool

Check if this task is attached to the first level of the tree.

Warning

This method should be called under _lock.

_get_children() Sequence[TaskBase]

Get child tasks.

Warning

This method should be called under _lock.

attach(parent: TaskBase | None)

Attach this task and all of its children to the task tree.

Parameters:

parent – parent task in the tree. Pass None to attach to root.

detach()

Remove this task and all of its children from the task tree.

class yuio.io.Task(
msg: LiteralString,
/,
*args,
comment: str | None = None,
parent: Task | None = None,
)
class yuio.io.Task(msg: str, /, *, comment: str | None = None, parent: Task | None = None)

A class for indicating progress of some task.

Parameters:
  • msg – task heading.

  • args – arguments for %-formatting the task heading.

  • comment – comment for the task. Can be specified after creation via the comment() method.

  • persistent

    whether to keep showing this task after it finishes. Default is False.

    To manually hide the task, call detach().

  • initial_status – initial status of the task.

  • parent – parent task.

You can have multiple tasks at the same time, create subtasks, set task’s progress or add a comment about what’s currently being done within a task.

This class can be used as a context manager:

with yuio.io.Task("Processing input") as t:
    ...
    t.progress(0.3)
    ...
Protected members
_widget_class: ClassVar[type[Task]] = <class 'yuio.widget.Task'>

Class of the widget that will be used to draw this task, can be overridden in subclasses.

class Status(*values)

Task status.

DONE = 'done'

Task has finished successfully.

ERROR = 'error'

Task has finished with an error.

RUNNING = 'running'

Task is running.

PENDING = 'pending'

Task is waiting to start.

progress(progress: float | None, /, *, ndigits: int = 2)
progress(
done: float | int,
total: float | int,
/,
*,
unit: str = '',
ndigits: int = 0,
)

Indicate progress of this task.

If given one argument, it is treated as percentage between 0 and 1.

If given two arguments, they are treated as amount of finished work, and a total amount of work. In this case, optional argument unit can be used to indicate units for the progress.

If given a single None, reset task progress.

Note

Tasks are updated asynchronously once every ~100ms, so calling this method is relatively cheap. It still requires acquiring a global lock, though: contention could be an issue in multi-threaded applications.

Parameters:
  • progress – a percentage between 0 and 1, or None to reset task progress.

  • done – amount of finished work, should be less than or equal to total.

  • total – total amount of work.

  • unit – unit for measuring progress. Only displayed when progress is given as done and total.

  • ndigits – number of digits to display after a decimal point.

Example:
with yuio.io.Task("Loading cargo") as task:
    task.progress(110, 150, unit="Kg")

This will print the following:

■■■■■■■■■■■□□□□ Loading cargo - 110/150Kg
progress_size(
done: float | int,
total: float | int,
/,
*,
ndigits: int = 2,
)

Indicate progress of this task using human-readable 1024-based size units.

Parameters:
  • done – amount of processed data.

  • total – total amount of data.

  • ndigits – number of digits to display after a decimal point.

Example:
with yuio.io.Task("Downloading a file") as task:
    task.progress_size(31.05 * 2**20, 150 * 2**20)

This will print:

■■■□□□□□□□□□□□□ Downloading a file - 31.05/150.00M
progress_scale(
done: float | int,
total: float | int,
/,
*,
unit: str = '',
ndigits: int = 2,
)

Indicate progress of this task while scaling numbers in accordance with SI system.

Parameters:
  • done – amount of finished work, should be less than or equal to total.

  • total – total amount of work.

  • unit – unit for measuring progress.

  • ndigits – number of digits to display after a decimal point.

Example:
with yuio.io.Task("Charging a capacitor") as task:
    task.progress_scale(889.25e-3, 1, unit="V")

This will print:

■■■■■■■■■■■■■□□ Charging a capacitor - 889.25mV/1.00V
iter(
collection: Collection[T],
/,
*,
unit: str = '',
ndigits: int = 0,
) Iterable[T]

Helper for updating progress automatically while iterating over a collection.

Parameters:
  • collection – an iterable collection. Should support returning its length.

  • unit – unit for measuring progress.

  • ndigits – number of digits to display after a decimal point.

Example:
with yuio.io.Task("Fetching data") as t:
    for url in t.iter(urls):
        ...

This will output the following:

■■■■■□□□□□□□□□□ Fetching data - 1/3
comment(comment: str | None, /, *args)

Set a comment for a task.

Comment is displayed after the progress.

Parameters:
  • comment – comment to display beside task progress.

  • args – arguments for %-formatting comment.

Example:
with yuio.io.Task("Fetching data") as t:
    for url in urls:
        t.comment("%s", url)
        ...

This will output the following:

⣿ Fetching data - https://google.com
set_status(status: Status)

Set task status.

Parameters:

status – New status.

running()

Indicate that this task is running.

pending()

Indicate that this task is pending.

done()

Indicate that this task has finished successfully.

error()

Indicate that this task has finished with an error.

subtask(
msg: str,
/,
*args,
comment: str | None = None,
persistent: bool = True,
initial_status: Status = Status.RUNNING,
) Task

Create a subtask within this task.

Parameters:
  • msg – subtask heading.

  • args – arguments for %-formatting the subtask heading.

  • comment – comment for the task. Can be specified after creation via the comment() method.

  • persistent – whether to keep showing this subtask after it finishes. Default is True.

  • initial_status – initial status of the task.

Returns:

a new Task that will be displayed as a sub-task of this task.

Querying user input

If you need to get something from the user, ask() is the way to do it.

yuio.io.ask(
msg: LiteralString,
/,
*args,
parser: Parser[T] | None = None,
default: U,
default_non_interactive: U,
input_description: str | None = None,
default_description: str | None = None,
) T | U
yuio.io.ask(
msg: str,
/,
*,
parser: Parser[T] | None = None,
default: U,
default_non_interactive: U,
input_description: str | None = None,
default_description: str | None = None,
) T | U

Ask user to provide an input, parse it and return a value.

If current terminal is not interactive, return default if one is present, or raise a UserIoError.

ask() accepts generic parameters, which determine how input is parsed. For example, if you’re asking for an enum element, Yuio will show user a choice widget.

You can also supply a custom Parser, which will determine the widget that is displayed to the user, the way autocompletion works, etc.

Note

ask() is designed to interact with users, not to read data. It uses /dev/tty on Unix, and console API on Windows, so it will read from an actual TTY even if stdin is redirected.

When designing your program, make sure that users have alternative means to provide values: use configs or CLI arguments, allow passing passwords via environment variables, etc.

Parameters:
  • msg – prompt to display to user.

  • args – arguments for %- formatting the prompt.

  • parser – parser to use to parse user input. See yuio.parse for more info.

  • default – default value to return if user input is empty.

  • default_non_interactive – default value returned if input stream is not readable. If not given, default is used instead. This is handy when you want to ask user if they want to continue with default set to False, but default_non_interactive set to True.

  • input_description – description of the expected input, like "yes/no" for boolean inputs.

  • default_description – description of the default value.

Returns:

parsed user input.

Raises:

raises UserIoError if we’re not in interactive environment, and there is no default to return.

Example:
class Level(enum.Enum):
    WARNING = "Warning"
    INFO = "Info"
    DEBUG = "Debug"


answer = yuio.io.ask[Level]("Choose a logging level", default=Level.INFO)
yuio.io.wait_for_user(
msg: LiteralString = 'Press <c note>enter</c> to continue',
/,
*args,
)

A simple function to wait for user to press enter.

If current terminal is not interactive, this functions has no effect.

Parameters:
  • msg – prompt to display to user.

  • args – arguments for %- formatting the prompt.

You can also prompt the user to edit something with the edit() function:

yuio.io.edit(
text: str,
/,
*,
comment_marker: str | None = None,
editor: str | None = None,
file_ext: str = '.txt',
fallbacks: list[str] | None = None,
dedent: bool = False,
) str

Ask user to edit some text.

This function creates a temporary file with the given text and opens it in an editor. After editing is done, it strips away all lines that start with comment_marker, if one is given.

Parameters:
  • text – text to edit.

  • comment_marker – lines starting with this marker will be removed from the output after edit.

  • editor

    overrides editor.

    On Unix, this should be a shell command, file path will be appended to it; on Windows, this should be an executable path.

  • file_ext – extension for the temporary file, can be used to enable syntax highlighting in editors that support it.

  • fallbacks – list of fallback editors to try, see detect_editor() for details.

  • dedent – remove leading indentation from text before opening an editor.

Returns:

an edited string with comments removed.

Raises:

If editor is not available, returns a non-zero exit code, or launched in a non-interactive environment, a UserIoError is raised.

Also raises UserIoError if stdin or stderr is piped or redirected to a file (virtually no editors can work when this happens).

Example:
message = yuio.io.edit(
    """
        # Please enter the commit message for your changes. Lines starting
        # with '#' will be ignored, and an empty message aborts the commit.
    """,
    comment_marker="#",
    dedent=True,
)
yuio.io.detect_editor(fallbacks: list[str] | None = None) str | None

Detect the user’s preferred editor.

This function checks the VISUAL and EDITOR environment variables. If they’re not set, it checks if any of the fallback editors are available. If none can be found, it returns None.

Parameters:

fallbacks – list of fallback editors to try. By default, we try “nano”, “vim”, “vi”, “msedit”, “edit”, “notepad”, “gedit”.

Returns:

on Windows, returns an executable name; on Unix, may return a shell command or an executable name.

If you need to spawn a sub-shell for user to interact with, you can use shell():

yuio.io.shell(
*,
shell: str | None = None,
fallbacks: list[str] | None = None,
prompt_marker: str = '',
)

Launch an interactive shell and give user control over it.

This function is useful in interactive scripts. For example, if the script is creating a release commit, it might be desired to give user a chance to inspect repository status before proceeding.

Parameters:
  • shell – overrides shell executable.

  • fallbacks – list of fallback shells to try, see detect_shell() for details.

  • prompt_marker

    if given, Yuio will try to add this marker to the shell’s prompt to remind users that this shell is a sub-process of some script.

    This only works with Bash, Zsh, Fish, and PowerShell.

yuio.io.detect_shell(fallbacks: list[str] | None = None) str | None

Detect the user’s preferred shell.

This function checks the SHELL environment variable. If it’s not set, it checks if any of the fallback shells are available. If none can be found, it returns None.

Parameters:

fallbacks – list of fallback shells to try. By default, we try “pwsh” and “powershell” on Windows, and “bash”, “sh”, “/bin/sh” on Linux/MacOS.

Returns:

returns an executable name.

All of these functions throw an error if something goes wrong:

class yuio.io.UserIoError(*args)

Raised when interaction with user fails.

Suspending the output

You can temporarily disable printing of tasks and messages using the SuspendOutput context manager.

class yuio.io.SuspendOutput(initial_channel: MessageChannel | None = None, /)

A context manager for pausing output.

This is handy for when you need to take control over the output stream. For example, the ask() function uses this class internally.

This context manager also suspends all prints that go to sys.stdout and sys.stderr if they were wrapped (see setup()). To print through them, use orig_stderr() and orig_stdout().

Each instance of this class is a MessageChannel; calls to its printing methods bypass output suppression:

with SuspendOutput() as out:
    print("Suspended")  # [1]_
    out.info("Not suspended")  # [2]_
  1. This message is suspended; it will be printed when output is resumed.

  2. This message bypasses suspension; it will be printed immediately.

resume()

Manually resume the logging process.

Python’s logging and yuio

If you want to direct messages from the logging to Yuio, you can add a Handler:

class yuio.io.Handler(level: int | str = 0)

A handler that redirects all log messages to Yuio.

class yuio.io.Formatter(
fmt: str | None = None,
datefmt: str | None = None,
validate: bool = True,
*,
defaults: Mapping[str, Any] | None = None,
)

Log formatter that uses % style with colorized string formatting and returns a string with ANSI escape characters generated for current output terminal.

Every part of log message is colored with path log/name:level. For example, asctime in info log line is colored with path log/asctime:info.

In addition to the usual log record attributes, this formatter also adds %(colMessage)s, which is similar to %(message)s, but colorized.

Helpers

yuio.io.make_repr_context(
*,
term: Term | None = None,
to_stdout: bool = False,
to_stderr: bool = False,
theme: Theme | None = None,
multiline: bool | None = None,
highlighted: bool | None = None,
max_depth: int | None = None,
width: int | None = None,
) ReprContext

Create new ReprContext for the given term and theme.

Warning

ReprContexts are not thread safe. As such, you shouldn’t create them for long term use.

Parameters:
  • term – terminal where to print this message. If not given, terminal from get_term() is used.

  • to_stdout – shortcut for setting term to stdout.

  • to_stderr – shortcut for setting term to stderr.

  • theme – theme used to format the message. If not given, theme from get_theme() is used.

  • multiline – sets initial value for ReprContext.multiline. Default is False.

  • highlighted – sets initial value for ReprContext.highlighted. Default is False.

  • max_depth – sets initial value for ReprContext.max_depth. Default is False.

  • width – sets initial value for ReprContext.width. If not given, uses current terminal width or Theme.fallback_width depending on whether term is attached to a TTY device and whether colors are supported by the target terminal.

type yuio.io.ExcInfo = tuple[type[BaseException] | None, BaseException | None, types.TracebackType | None]

Exception information as returned by sys.exc_info().

Re-imports

type yuio.io.And

Alias of yuio.string.And.

type yuio.io.Ordinal

Alias of yuio.string.Ordinal.

type yuio.io.ColorizedString

Alias of yuio.string.ColorizedString.

type yuio.io.Format

Alias of yuio.string.Format.

type yuio.io.Hl

Alias of yuio.string.Hl.

type yuio.io.Hr

Alias of yuio.string.Hr.

type yuio.io.Indent

Alias of yuio.string.Indent.

type yuio.io.JoinRepr

Alias of yuio.string.JoinRepr.

type yuio.io.JoinStr

Alias of yuio.string.JoinStr.

type yuio.io.Link

Alias of yuio.string.Link.

type yuio.io.Md

Alias of yuio.string.Md.

type yuio.io.Rst

Alias of yuio.string.Rst.

type yuio.io.Or

Alias of yuio.string.Or.

type yuio.io.Plural

Alias of yuio.string.Plural.

type yuio.io.Repr

Alias of yuio.string.Repr.

type yuio.io.Stack

Alias of yuio.string.Stack.

type yuio.io.TypeRepr

Alias of yuio.string.TypeRepr.

type yuio.io.WithBaseColor

Alias of yuio.string.WithBaseColor.

type yuio.io.Wrap

Alias of yuio.string.Wrap.