Welcome to Term-Image’s documentation!#

Attention

🚧 Under Construction - There might be incompatible changes between minor versions of version zero!

If you want to use this library in a project while it’s still on version zero, ensure you pin the dependency to a specific minor version e.g >=0.4,<0.5.

On this note, you probably also want to switch to the specific documentation for the version you’re using (somewhere at the lower left corner of this page).

Contents#

Getting Started#

Installation#

Requirements#
  • Operating System: Unix / Linux / MacOS X / Windows (limited support, see the FAQs)

  • Python >= 3.8

  • A terminal emulator with any of the following:

    Plans to support a wider variety of terminal emulators are in motion.

Steps#

The latest stable version can be installed from PyPI with:

pip install term-image

The development version can be installed with:

pip install git+https://github.com/AnonymouX47/term-image.git
Supported Terminal Emulators#

Some terminals emulators that have been tested to meet the requirements for at least one render style include:

  • libvte-based terminal emulators such as:

    • Gnome Terminal

    • Terminator

    • Tilix

  • Kitty

  • Konsole

  • iTerm2

  • WezTerm

  • Alacritty

  • Windows Terminal

  • MinTTY (on Windows)

  • Termux (on Android)

Note

If you’ve tested term-image on any other terminal emulator that meets all requirements, please mention the name in a new thread under this discussion.

Also, if you’re having an issue with terminal support, you may report or check information about it in the discussion linked above.

Note

Some terminal emulators support direct-color (truecolor) escape sequences but use a 256-color palette. This limits color reproduction.

Tutorial#

This is a basic introduction to using the library. Please refer to the API Reference for detailed description of the features and functionality provided by the library.

For this tutorial we’ll be using the image below:

_images/python.png

The image has a resolution of 288x288 pixels.

Note

All the samples in this tutorial occurred in a terminal window of 255 columns by 70 lines.

Creating an Instance#

Image instances can be created using the convenience functions AutoImage(), from_file() and from_url(), which automatically detect the best style supported by the terminal emulator.

Instances can also be created using the Image Classes directly via their respective constructors or from_file() and from_url() methods.

  1. Initialize with a file path:

    from term_image.image import from_file
    
    image = from_file("path/to/python.png")
    
  2. Initialize with a URL:

    from term_image.image import from_url
    
    image = from_url("https://raw.githubusercontent.com/AnonymouX47/term-image/main/docs/source/resources/tutorial/python.png")
    
  3. Initialize with a PIL (Pillow) image instance:

    from PIL import Image
    from term_image.image import AutoImage
    
    img = Image.open("path/to/python.png")
    image = AutoImage(img)
    
Rendering an Image#

Rendering an image is the process of converting it (per-frame for animated images) into text (a string) which reproduces a representation or approximation of the image when written to the terminal.

Hint

To display the rendered image in the following steps, pass the string as an argument to print().

There are two ways to render an image:

Unformatted Rendering#

This is done using:

str(image)

The image is rendered without padding/alignment and with transparency enabled.

The output (using print()) should look like:

_images/str.png

Formatted Rendering#

Note

To see the effect of alignment in the steps below, set the image size smaller than your terminal size, with e.g:

image.height = 50

This sets the image height to 50 lines (which is less than 70, the height of the terminal window used to prepare this tutorial) and the width proportionally.

We’ll see more about this later.

Below are examples of formatted rendering:

format(image, "|200.^70#ffffff")

Renders the image with:

Note

You might have to reduce the padding width (200) and/or height (70) to something that’ll fit into your terminal window, or increase the size of the terminlal window

The output (using print()) should look like:

_images/white_bg.png

f"{image:>._#.5}"

Renders the image with:

The output (using print()) should look like:

_images/alpha_0_5.png

"{:1.1#}".format(image)

Renders the image with:

  • center horizontal alignment (default)

  • no horizontal padding, since 1 is less than or equal to the image width

  • middle vertical alignment (default)

  • no vertical padding, since 1 is less than or equal to the image height

  • transparency is disabled (alpha channel is ignored)

The output (using print()) should look like:

_images/no_alpha_no_align.png
Drawing/Displaying an Image#

There are two basic ways to draw an image to the terminal screen:

  1. Using the draw() method:

    image.draw()
    

    NOTE: draw() has various parameters for Render Formatting.

  2. Using print() with an image render output (i.e printing the rendered string):

    print(image)  # Uses str()
    # OR
    print(f"{image:>200.^70#ffffff}")  # Uses format()
    

Note

  • For animated images, only the former animates the output, the latter only draws the current frame (see seek() and tell()).

  • Also, the former performs size validation to see if the image will fit into the terminal, while the latter doesn’t.

Important

All the examples above use dynamic and automatic sizing.

Image Size#
The size of an image determines the dimension of its render output.
The image size can be retrieved via the size, width and height properties.

The size of an image can be in either of two states:

  1. Fixed

    In this state,

    • the size property evaluates to a 2-tuple of integers, while the width and height properties evaluate to integers,

    • the image is rendered with the set size.

  2. Dynamic

    In this state,

    • the size, width and height properties evaluate to a Size enum member,

    • the size with which the image is rendered is automatically calculated (based on the current terminal size or the image’s original size) whenever the image is to be rendered.

The size of an image can be set at instantiation by passing an integer or a Size enum member to either the width or the height keyword-only parameter. For whichever axis a dimension is given, the dimension on the other axis is calculated proportionally.

Note

  1. The arguments can only be given by keyword.

  2. If neither is given, the FIT dynamic size applies.

  3. All methods of instantiation accept these arguments.

For example:

>>> from term_image.image import Size, from_file
>>> image = from_file("python.png")  # Dynamic FIT
>>> image.size is Size.FIT
True
>>> image = from_file("python.png", width=60)  # Fixed
>>> image.size
(60, 30)
>>> image.height
30
>>> image = from_file("python.png", height=56)  # Fixed
>>> image.size
(112, 56)
>>> image.width
112
>>> image = from_file("python.png", height=Size.FIT)  # Fixed FIT
>>> image.size
(136, 68)
>>> image = from_file("python.png", width=Size.FIT_TO_WIDTH)  # Fixed FIT_TO_WIDTH
>>> image.size
(255, 128)
>>> image = from_file("python.png", height=Size.ORIGINAL)  # Fixed ORIGINAL
>>> image.size
(288, 144)

No size validation is performed i.e the resulting size might not fit into the terminal window

>>> image = from_file("python.png", height=68)  # Will fit in, OK
>>> image.size
(136, 68)
>>> image = from_file("python.png", height=500)  # Will not fit in, also OK
>>> image.size
(1000, 500)

An exception is raised when both width and height are given.

>>> image = from_file("python.png", width=100, height=100)
Traceback (most recent call last):
  .
  .
  .
ValueError: Cannot specify both width and height

The width and height properties can be used to set the size of an image after instantiation, resulting in fixed size.

>>> image = from_file("python.png")
>>> image.width = 56
>>> image.size
(56, 28)
>>> image.height
28
>>> image.height = 68
>>> image.size
(136, 68)
>>> image.width
136
>>> # Even though the terminal can't contain the resulting height, the size is still set
>>> image.width = 200
>>> image.size
(200, 100)
>>> image.width = Size.FIT
>>> image.size
(136, 69)
>>> image.height = Size.FIT_TO_WIDTH
>>> image.size
(255, 128)
>>> image.height = Size.ORIGINAL
>>> image.size
(288, 144)

The size property can only be set to a Size enum member, resulting in dynamic size.

>>> image = from_file("python.png")
>>> image.size = Size.FIT
>>> image.size is image.width is image.height is Size.FIT
True
>>> image.size = Size.FIT_TO_WIDTH
>>> image.size is image.width is image.height is Size.FIT_TO_WIDTH
True
>>> image.size = Size.ORIGINAL
>>> image.size is image.width is image.height is Size.ORIGINAL
True

Important

  1. The currently set cell ratio is also taken into consideration when calculating sizes for images of Text-based Render Styles.

  2. There is a 2-line difference between the default frame size and the terminal size to allow for shell prompts and the likes.

Tip

See set_size() for extended sizing control.


To explore more of the library’s features and functionality, check out the User Guide and the API Reference.

User Guide#

Concepts#

Render Styles#

See render style.

All render style classes are designed to share a common interface (with some having extensions), making the usage of one class directly compatible with another, except when using style-specific features.

Hence, the factory functions AutoImage, from_file and from_url provide a means of render-style-agnostic usage of the library. These functions automatically detect the best render style supported by the active terminal.

There are two main categories of render styles:

Text-based Render Styles#

Represent images using ASCII or Unicode symbols, and in some cases, with escape sequences to reproduce color.

Render style classes in this category are subclasses of TextImage. These include:

Graphics-based Render Styles#

Represent images with actual pixels, using terminal graphics protocols.

Render style classes in this category are subclasses of GraphicsImage. These include:

Render Methods#

A render style may implement multiple render methods. See the Render Methods section in the description of a render style class (that implements multiple render methods), for the description of its render methods.

Auto Cell Ratio#

Note

This concerns Text-based Render Styles only.

The is a feature which when supported, can be used to determine the cell ratio directly from the terminal emulator itself. With this feature, it is possible to always produce images of text-based render styles with correct aspect ratio.

When using either mode of AutoCellRatio, it’s important to note that some terminal emulators (most non-graphics-capable ones) might have queried. See Terminal Queries.

If the program will never expect any useful input, particularly while an image’s size is being set/calculated, then using DYNAMIC mode is OK. For an image with dynamic size, this includes when it’s being rendered and when its rendered_size, rendered_width or rendered_height property is invoked.

Otherwise i.e if the program will be expecting input, use FIXED mode and use read_tty_all() to read all currently unread input just before calling set_cell_ratio().

The Active Terminal#

See active terminal.

The following streams/files are checked in the following order (along with the rationale behind the ordering):

  • STDOUT: Since it’s where images will most likely be drawn.

  • STDIN: If output is redirected to a file or pipe and the input is a terminal, then using it as the active terminal should give the expected result i.e the same as when output is not redirected.

  • STDERR: If both output and input are redirected, it’s usually unlikely for errors to be.

  • /dev/tty: Finally, if all else fail, fall back to the process’ controlling terminal, if any.

The first one that is ascertained to be a terminal device is used for all Terminal Queries and to retrieve the terminal (and window) size on some terminal emulators.

Note

If none of the streams/files is a TTY device, then a TermImageWarning is issued and dependent functionality is disabled.

Terminal Queries#

Some features of this library require the acquisition of certain information from the active terminal. A single iteration of this acquisition procedure is called a query.

A query involves three major steps:

  1. Clear all unread input from the terminal

  2. Write to the terminal

  3. Read from the terminal

For this procedure to be successful, it must not be interrupted.

About #1

If the program is expecting input, use read_tty_all() to read all currently unread input (without blocking) just before any operation involving a query.

About #2 and #3

After sending a request to the terminal, its response is awaited. The default wait time is DEFAULT_QUERY_TIMEOUT but can be changed using set_query_timeout(). If the terminal emulator responds after the set timeout, this can result in the application program receiving what would seem to be garbage or ghost input (see this FAQ).

If the program includes any other function that could write to the terminal OR especially, read from the terminal or modify it’s attributes, while a query is in progress (as a result of asynchronous execution e.g multithreading or multiprocessing), decorate it with lock_tty() to ensure it doesn’t interfere.

For example, an image viewer based on this project uses urwid which reads from the terminal using urwid.raw_display.Screen.get_available_raw_input(). To prevent this method from interfering with terminal queries, it uses UrwidImageScreen which overrides and wraps the method like:

class UrwidImageScreen(Screen):
    @lock_tty
    def get_available_raw_input(self):
       return super().get_available_raw_input()

Also, if the active terminal is not the controlling terminal of the process using this library (e.g output is redirected to another TTY device), ensure no process that can interfere with a query (e.g a shell or REPL) is currently running in the active terminal. For instance, such a process can be temporarily put to sleep.

Features that require terminal queries#

In parentheses are the outcomes when the terminal doesn’t support queries or when queries are disabled.

  • Auto Cell Ratio (determined to be unsupported)

  • Support checks for Graphics-based Render Styles (determined to be unsupported)

  • Auto background color (black is used)

  • Alpha blend for pixels above the alpha threshold in transparent renders with Text-based Render Styles (black is used)

  • Workaround for background colors in text-based renders on the Kitty terminal (the workaround is disabled)

Note

This list might not always be complete. In case you notice

  • any difference with any unlisted feature when terminal queries are enabled versus when disabled, or

  • a behaviour different from the one specified for the listed features, when terminal queries are disabled,

please open an issue here.

Render Formatting#

Render formatting is simply the modification of a primary render output. This is provided via:

The following constitute render formatting:

Padding#

This adds whitespace around a primary render output. The amount of whitespace added is determined by two values (with respect to the rendered size):

If the padding width or height is less than or equal to the width or height of the primary render output, then the padding has no effect on the corresponding axis.

Alignment#

This determines the position of a primary render output within it’s Padding. The position is determined by two values:

Transparency#

This determines how transparent pixels are rendered. Transparent pixels can be rendered in one of the following ways:

Render Format Specification#
[ <h_align> ]  [ <width> ]  [ . [ <v_align> ] [ <height> ] ]  [ # [ <threshold> | <bgcolor> ] ]  [ + <style> ]

Note

  • spaces are only for clarity and not included in the syntax

  • <...> is a placeholder for a single field

  • | implies mutual exclusivity

  • fields within [ ] are optional

  • fields within { } are required, though subject to any enclosing [ ]

  • if the . is present, then at least one of v_align and height must be present

  • h_alignhorizontal alignment

    • < → left

    • | → center

    • > → right

    • default → center

  • widthpadding width

  • v_alignvertical alignment

    • ^ → top

    • - → middle

    • _ → bottom

    • default → middle

  • heightpadding height

  • # → transparency setting

    • default: transparency is enabled with the default alpha threshold

    • thresholdalpha threshold

      • a float value in the range 0.0 <= threshold < 1.0 (but starting with the . (decimal point))

      • applies to only Text-based Render Styles

      • e.g .0, .325043, .999

    • bgcolor → background underlay color

      • # → the terminal emulator’s default background color (or black, if undetermined), OR

      • a hex color e.g ffffff, 7faa52

    • if neither threshold nor bgcolor is present, but # is present, transparency is disabled i.e alpha channel is ignored

  • style → style-specific format specifier

    See each render style in Image Classes for its own specification, if it defines.

    style can be broken down into [ <parent> ] [ <current> ], where current is the spec defined by a render style and parent is the spec defined by a parent of that render style. parent can in turn be recursively broken down as such.

See also

Formatted rendering tutorial.

API Reference#

Attention

🚧 Under Construction - There might be incompatible interface changes between minor versions of version zero!

If you want to use the library in a project while it’s still on version zero, ensure you pin the dependency to a specific minor version e.g >=0.4,<0.5.

On this note, you probably also want to switch to the specific documentation for the version you’re using (somewhere at the lower left corner of this page).

Attention

Any module or definition not documented here should be considered part of the private interface and can be changed or removed at any time without notice.

Top-Level Definitions#

Constants#
term_image.DEFAULT_QUERY_TIMEOUT: Final[float] = 0.1#

Default timeout for Terminal Queries

Enumerations#
class term_image.AutoCellRatio[source]#

Bases: Enum

Auto Cell Ratio enumeration and support status.

See also

set_cell_ratio().

Attributes:

FIXED

Fixed cell ratio.

DYNAMIC

Dynamic cell ratio.

is_supported

Auto cell ratio support status.

FIXED#

Fixed cell ratio.

DYNAMIC#

Dynamic cell ratio.

is_supported: ClassVar[bool | None]#

Auto cell ratio support status. Can be

  • None -> support status not yet determined

  • True -> supported

  • False -> not supported

Can be explicitly set when using auto cell ratio but want to avoid the support check in a situation where the support status is foreknown. Can help to avoid being wrongly detected as unsupported on a queried terminal that doesn’t respond on time.

For instance, when using multiprocessing, if the support status has been determined in the main process, this value can simply be passed on to and set within the child processes.

Functions#

disable_queries

Disables Terminal Queries.

disable_win_size_swap

Disables a workaround for terminal emulators that wrongly report window dimensions swapped.

enable_queries

Re-Enables Terminal Queries.

enable_win_size_swap

Enables a workaround for terminal emulators that wrongly report window dimensions swapped.

get_cell_ratio

Returns the global cell ratio.

set_cell_ratio

Sets the global cell ratio.

set_query_timeout

Sets the timeout for Terminal Queries.

term_image.disable_queries()[source]#

Disables Terminal Queries.

To re-enable queries, call enable_queries().

Note

This affects all dependent features.

term_image.disable_win_size_swap()[source]#

Disables a workaround for terminal emulators that wrongly report window dimensions swapped.

This workaround is disabled by default. While disabled, the window dimensions reported by the active terminal are used as-is.

Note

This affects Auto Cell Ratio computation and size computations for Graphics-based Render Styles.

term_image.enable_queries()[source]#

Re-Enables Terminal Queries.

Queries are enabled by default. To disable, call disable_queries().

Note

This affects all dependent features.

term_image.enable_win_size_swap()[source]#

Enables a workaround for terminal emulators that wrongly report window dimensions swapped.

While enabled, the window dimensions reported by the active terminal are swapped. This workaround is required on some older VTE-based terminal emulators.

Note

This affects Auto Cell Ratio computation and size computations for Graphics-based Render Styles.

term_image.get_cell_ratio()[source]#

Returns the global cell ratio.

See also

set_cell_ratio().

term_image.set_cell_ratio(ratio)[source]#

Sets the global cell ratio.

Parameters:

ratio (float | AutoCellRatio) –

Can be one of the following values.

Raises:

This value is taken into consideration when setting image sizes for text-based render styles, in order to preserve the aspect ratio of images drawn to the terminal.

Note

Changing the cell ratio does not automatically affect any image that has a fixed size. For a change in cell ratio to take effect, the image’s size has to be re-set.

Important

See Auto Cell Ratio for details about the auto modes.

term_image.set_query_timeout(timeout)[source]#

Sets the timeout for Terminal Queries.

Parameters:

timeout (float) – Time limit for awaiting a response from the terminal, in seconds.

Raises:

ValueErrortimeout is less than or equal to zero.

color Module#

Classes:

Color

A color.

class term_image.color.Color(r, g, b, a=255)[source]#

Bases: _DummyColor

A color.

Parameters:
  • r (int) – The red channel.

  • g (int) – The green channel.

  • b (int) – The blue channel.

  • a (int) – The alpha channel (opacity).

Raises:

ValueError – The value of a channel is not within the valid range.

Note

The valid value range for all channels is 0 to 255, both inclusive.

Tip

This class is a NamedTuple of four fields.

Warning

In the case of multiple inheritance i.e if subclassing this class along with other classes, this class should appear last (i.e to the far right) in the base class list.

Attributes:

r

The red channel

g

The green channel

b

The blue channel

a

The alpha channel (opacity)

Instance Properties:

hex

Converts the color to its RGBA hexadecimal representation.

rgb

Extracts the R, G and B channels of the color.

rgb_hex

Converts the color to its RGB hexadecimal representation.

Class Methods:

from_hex

Creates a new instance from a hexadecimal color string.

r: int#

The red channel

g: int#

The green channel

b: int#

The blue channel

a: int#

The alpha channel (opacity)

property hex: str#

Converts the color to its RGBA hexadecimal representation.

Returns:

The RGBA hex color string, starting with the # character i.e #rrggbbaa.

Each channel is represented by two lowercase hex digits ranging from 00 to ff.

property rgb: tuple[int, int, int]#

Extracts the R, G and B channels of the color.

Returns:

A 3-tuple containing the red, green and blue channel values.

property rgb_hex: str#

Converts the color to its RGB hexadecimal representation.

Returns:

The RGB hex color string, starting with the # character i.e #rrggbb.

Each channel is represented by two lowercase hex digits ranging from 00 to ff.

classmethod from_hex(color)[source]#

Creates a new instance from a hexadecimal color string.

Parameters:

color (str) – A case-insensitive RGB or RGBA hex color string, optionally starting with the # (pound) character i.e [#]rrggbb[aa].

Returns:

A new instance representing the given hex color string.

Raises:

ValueError – Invalid hex color string.

Return type:

Self

Note

For an RGB hex color string, the value of A (the alpha channel) is taken to be 255.

exceptions Module#

Warnings:

TermImageWarning

Package-specific warning base category.

TermImageUserWarning

Package-specific user warning sub-category.

Exceptions:

TermImageError

Exception baseclass.

InvalidSizeError

Raised for invalid sizes.

RenderError

...

StyleError

Raised for errors pertaining to the Style API.

URLNotFoundError

Raised for 404 errors.

UrwidImageError

Raised for errors specific to UrwidImage.

exception term_image.exceptions.TermImageWarning[source]#

Bases: Warning

Package-specific warning base category.

exception term_image.exceptions.TermImageUserWarning[source]#

Bases: TermImageWarning, UserWarning

Package-specific user warning sub-category.

exception term_image.exceptions.TermImageError[source]#

Bases: Exception

Exception baseclass. Raised for generic errors.

exception term_image.exceptions.InvalidSizeError[source]#

Bases: TermImageError

Raised for invalid sizes.

exception term_image.exceptions.RenderError[source]#

Bases: TermImageError

exception term_image.exceptions.StyleError[source]#

Bases: TermImageError

Raised for errors pertaining to the Style API.

exception term_image.exceptions.URLNotFoundError[source]#

Bases: TermImageError, FileNotFoundError

Raised for 404 errors.

exception term_image.exceptions.UrwidImageError[source]#

Bases: TermImageError

Raised for errors specific to UrwidImage.

geometry Module#

Classes:

RawSize

The dimensions of a rectangular region.

Size

The dimensions of a rectangular region.

class term_image.geometry.RawSize(width, height)[source]#

Bases: NamedTuple

The dimensions of a rectangular region.

Parameters:
  • width (int) – The horizontal dimension

  • height (int) – The vertical dimension

Note

  • A dimension may be non-positive but the validity and meaning would be determined by the receiving interface.

  • This is a subclass of tuple. Hence, instances can be used anyway and anywhere tuples can.

Attributes:

width

The horizontal dimension

height

The vertical dimension

width: int#

The horizontal dimension

height: int#

The vertical dimension

class term_image.geometry.Size(width, height)[source]#

Bases: RawSize

The dimensions of a rectangular region.

Raises:

ValueError – Either dimension is non-positive.

Same as RawSize, except that both dimensions must be positive.

Important

In the case of multiple inheritance i.e if subclassing this class along with other classes, this class should appear last (i.e to the far right) in the base class list.

image Module#

Functions#

These functions automatically detect the best supported render style for the current terminal.

Since all classes share a common interface (as defined by BaseImage), any operation supported by one image class can be performed on any other image class, except style-specific operations.

auto_image_class

Selects the image render style that best suits the current terminal emulator.

AutoImage

Creates an image instance from a PIL image instance.

from_file

Creates an image instance from an image file.

from_url

Creates an image instance from an image URL.

term_image.image.auto_image_class()[source]#

Selects the image render style that best suits the current terminal emulator.

Returns:

An image class (a subclass of BaseImage).

Return type:

ImageMeta

term_image.image.AutoImage(image, *, width=None, height=None)[source]#

Creates an image instance from a PIL image instance.

Returns:

An instance of the automatically selected image render style (as returned by auto_image_class()).

Return type:

BaseImage

Same arguments and raised exceptions as the BaseImage class constructor.

term_image.image.from_file(filepath, **kwargs)[source]#

Creates an image instance from an image file.

Returns:

An instance of the automatically selected image render style (as returned by auto_image_class()).

Return type:

BaseImage

Same arguments and raised exceptions as BaseImage.from_file().

term_image.image.from_url(url, **kwargs)[source]#

Creates an image instance from an image URL.

Returns:

An instance of the automatically selected image render style (as returned by auto_image_class()).

Return type:

BaseImage

Same arguments and raised exceptions as BaseImage.from_url().

Enumerations#

ImageSource

Image source type.

Size

Enumeration for automatic sizing.

class term_image.image.ImageSource[source]#

Bases: Enum

Image source type.

FILE_PATH#

The instance was derived from a path to a local image file.

PIL_IMAGE#

The instance was derived from a PIL image instance.

URL#

The instance was derived from an image URL.


class term_image.image.Size[source]#

Bases: Enum

Enumeration for automatic sizing.

AUTO#

Equivalent to ORIGINAL if it will fit into the frame size, else FIT.

FIT#

The image size is set to fit optimally within the frame size.

FIT_TO_WIDTH#

The size is set such that the width is exactly the frame width, regardless of the cell ratio.

ORIGINAL#

The image size is set such that the image is rendered with as many pixels as the the original image consists of.

Image Classes#
Class Hierarchy#
The Classes#

BaseImage

Base of all render styles.

TextImage

Base of all Text-based Render Styles.

BlockImage

A render style using unicode half blocks and direct-color colour escape sequences.

GraphicsImage

Base of all Graphics-based Render Styles.

ITerm2Image

A render style using the iTerm2 inline image protocol.

KittyImage

A render style using the Kitty terminal graphics protocol.

class term_image.image.BaseImage(image, *, width=None, height=None)[source]#

Bases: object

Base of all render styles.

Parameters:
  • image (PIL.Image.Image) – Source image.

  • width (Union[int, Size, None]) –

    Can be

    • a positive integer; horizontal dimension of the image, in columns.

    • a Size enum member.

  • height (Union[int, Size, None]) –

    Can be

    • a positive integer; vertical dimension of the image, in lines.

    • a Size enum member.

Raises:
  • TypeError – An argument is of an inappropriate type.

  • ValueError – An argument is of an appropriate type but has an unexpected/invalid value.

Propagates exceptions raised by set_size(), if width or height is given.

Note

  • If neither width nor height is given (or both are None), FIT applies.

  • If both width and height are not None, they must be positive integers and manual sizing applies i.e the image size is set as given without preserving aspect ratio.

  • For animated images, the seek position is initialized to the current seek position of the given image.

  • It’s allowed to set properties for animated images on non-animated ones, the values are simply ignored.

Attention

This class cannot be directly instantiated. Image instances should be created from its subclasses.

Instance Properties:

closed

Instance finalization status

frame_duration

Duration of a single frame

height

Image height

is_animated

Animatability of the image

original_size

Size of the source (in pixels)

n_frames

Image frame count

rendered_height

The height with which the image is rendered

rendered_size

The size with which the image is rendered

rendered_width

The width with which the image is rendered

size

Image size

source

Image source

source_type

Image source type

width

Image width

Class Properties:

forced_support

Forced render style support

Instance Methods:

close

Finalizes the instance and releases external resources.

draw

Draws the image to standard output.

seek

Changes current image frame.

set_size

Sets the image size (with extended control).

tell

Returns the current image frame number.

Class Methods:

from_file

Creates an instance from an image file.

from_url

Creates an instance from an image URL.

is_supported

Checks if the implemented render style is supported by the active terminal.

Class/Instance Methods:

set_render_method

Sets the render method used by instances of a render style class that implements multiple render methods.

property closed#

Instance finalization status

Type:

bool

GET:

Returns True if the instance has been finalized (close() has been called). Otherwise, False.

property forced_support#

Forced render style support

Type:

bool

GET:

Returns the forced support status of the invoking class or class of the invoking instance.

SET:

Forced support is enabled or disabled for the invoking class.

Can not be set on an instance.

If forced support is:

  • enabled, the render style is treated as if it were supported, regardless of the return value of is_supported().

  • disabled, the return value of is_supported() determines if the render style is supported or not.

By default, forced support is disabled for all render style classes.

Note

  • This property is descendant.

  • This doesn’t affect the return value of is_supported() but may affect operations that require that a render style be supported e.g instantiation of some render style classes.

property frame_duration#

Duration of a single frame

Type:

Optional[float]

GET:

Returns:

  • The duration of a single frame (in seconds), if the image is animated.

  • None, if otherwise.

SET:

If the image is animated, The frame duration is set. Otherwise, nothing is done.

property height#

Image height

Type:

Union[Size, int]

GET:

Returns:

  • The image height (in lines), if the image size is fixed.

  • A Size enum member, if the image size is dynamic.

SET:

If set to:

  • a positive int; the image height is set to the given value and the width is set proportionally.

  • a Size enum member; the image size is set as prescibed by the enum member.

  • None; equivalent to FIT.

This results in a fixed size.

property is_animated#

Animatability of the image

Type:

bool

GET:

Returns True if the image is animated. Otherwise, False.

property original_size#

Size of the source (in pixels)

Type:

Tuple[int, int]

GET:

Returns the source size.

property n_frames: int#

Image frame count

Type:

int

GET:

Returns the number of frames the image has.

property rendered_height#

The height with which the image is rendered

Type:

int

GET:

Returns the number of lines the image will occupy when drawn in a terminal.

property rendered_size#

The size with which the image is rendered

Type:

Tuple[int, int]

GET:

Returns the number of columns and lines (respectively) the image will occupy when drawn in a terminal.

property rendered_width#

The width with which the image is rendered

Type:

int

GET:

Returns the number of columns the image will occupy when drawn in a terminal.

property size#

Image size

Type:

Union[Size, Tuple[int, int]]

GET:

Returns:

  • The image size, (columns, lines), if the image size is fixed.

  • A Size enum member, if the image size is dynamic.

SET:

If set to a:

  • Size enum member, the image size is set as prescibed by the given member.

    This results in a dynamic size i.e the size is computed whenever the image is rendered using the default frame size.

  • 2-tuple of integers, (width, height), the image size set as given.

    This results in a fixed size i.e the size will not change until it is re-set.

property source#

Image source

Type:

Union[PIL.Image.Image, str]

GET:

Returns the source from which the instance was initialized.

property source_type#

Image source type

Type:

ImageSource

GET:

Returns the type of source from which the instance was initialized.

property width#

Image width

Type:

Union[Size, int]

GET:

Returns:

  • The image width (in columns), if the image size is fixed.

  • A Size enum member; if the image size is dynamic.

SET:

If set to:

  • a positive int; the image width is set to the given value and the height is set proportionally.

  • a Size enum member; the image size is set as prescibed by the enum member.

  • None; equivalent to FIT.

This results in a fixed size.

close()[source]#

Finalizes the instance and releases external resources.

  • In most cases, it’s not necessary to explicitly call this method, as it’s automatically called when the instance is garbage-collected.

  • This method can be safely called multiple times.

  • If the instance was initialized with a PIL image, the PIL image is never finalized.

draw(h_align=None, pad_width=0, v_align=None, pad_height=-2, alpha=0.1568627450980392, *, animate=True, repeat=-1, cached=100, scroll=False, check_size=True, **style)[source]#

Draws the image to standard output.

Parameters:
  • h_align (Optional[str]) – Horizontal alignment (“left” / “<”, “center” / “|” or “right” / “>”). Default: center.

  • pad_width (int) –

    Number of columns within which to align the image.

    • Excess columns are filled with spaces.

    • Must not be greater than the terminal width.

  • v_align (Optional[str]) – Vertical alignment (“top”/”^”, “middle”/”-” or “bottom”/”_”). Default: middle.

  • pad_height (int) –

    Number of lines within which to align the image.

    • Excess lines are filled with spaces.

    • Must not be greater than the terminal height, for animations.

  • alpha (Optional[float, str]) –

    Transparency setting.

    • If None, transparency is disabled (alpha channel is removed).

    • If a float (0.0 <= x < 1.0), specifies the alpha ratio above which pixels are taken as opaque. (Applies to only text-based render styles).

    • If a string, specifies a color to replace transparent background with. Can be:

      • ”#” -> The terminal’s default background color (or black, if undetermined) is used.

      • A hex color e.g ffffff, 7faa52.

  • animate (bool) – If False, disable animation i.e draw only the current frame of an animated image.

  • repeat (int) – The number of times to go over all frames of an animated image. A negative value implies infinite repetition.

  • cached (Union[bool, int]) –

    Determines if rendered frames of an animated image will be cached (for speed up of subsequent renders of the same frame) or not.

    • If bool, it directly sets if the frames will be cached or not.

    • If int, caching is enabled only if the framecount of the image is less than or equal to the given number.

  • scroll (bool) – Only applies to non-animations. If True, allows the image’s rendered height to be greater than the terminal height.

  • check_size (bool) – If False, rendered size validation is not performed for non-animations. Does not affect padding size validation.

  • style (Any) – Style-specific render parameters. See each subclass for it’s own usage.

Raises:
  • If pad_width or pad_height is:

    • positive, it is absolute and used as-is.

    • non-positive, it is relative to the corresponding terminal dimension (at the point of calling this method) and equivalent to the absolute dimension max(terminal_dimension + frame_dimension, 1).

  • padding width is always validated.

  • animate, repeat and cached apply to animated images only. They are simply ignored for non-animated images.

  • For animations (i.e animated images with animate set to True):

    • scroll is ignored.

    • Image size is always validated, if set.

    • Padding height is always validated.

  • Animations, by default, are infinitely looped and can be terminated with SIGINT (CTRL + C), without raising KeyboardInterrupt.

classmethod from_file(filepath, **kwargs)[source]#

Creates an instance from an image file.

Parameters:
  • filepath (str | PathLike) – Relative/Absolute path to an image file.

  • kwargs (None | int) – Same keyword arguments as the class constructor.

Returns:

A new instance.

Raises:
Return type:

BaseImage

Propagates exceptions raised (or propagated) by PIL.Image.open() and the class constructor.

classmethod from_url(url, **kwargs)[source]#

Creates an instance from an image URL.

Parameters:
  • url (str) – URL of an image file.

  • kwargs (None | int) – Same keyword arguments as the class constructor.

Returns:

A new instance.

Raises:
Return type:

BaseImage

Also propagates connection-related exceptions from requests.get() and exceptions raised or propagated by the class constructor.

Note

This method creates a temporary file, but only after successful initialization. The file is removed:

  • when close() is called,

  • upon exiting a with statement block that uses the instance as a context manager, or

  • when the instance is garbage collected.

abstract classmethod is_supported()[source]#

Checks if the implemented render style is supported by the active terminal.

Returns:

True if the render style implemented by the invoking class is supported by the active terminal. Otherwise, False.

Return type:

bool

Attention

Support checks for most (if not all) render styles require querying the active terminal the first time they’re executed.

Hence, it’s advisable to perform all necessary support checks (call this method on required style classes) at an early stage of a program, before user input is expected. If using automatic style selection, calling auto_image_class() only should be sufficient.

seek(pos)[source]#

Changes current image frame.

Parameters:

pos (int) – New frame number.

Raises:
  • TypeError – An argument is of an inappropriate type.

  • ValueError – An argument is of an appropriate type but has an unexpected/invalid value.

Frame numbers start from 0 (zero).

classmethod set_render_method(method=None)[source]#

Sets the render method used by instances of a render style class that implements multiple render methods.

Parameters:

method (str | None) – The render method to be set or None for a reset (case-insensitive).

Raises:
  • TypeError – An argument is of an inappropriate type.

  • ValueError – An argument is of an appropriate type but has an unexpected/invalid value.

See the Render Methods section in the description of subclasses that implement such for their specific usage.

If method is not None and this method is called via:

  • a class, the class-wide render method is set.

  • an instance, the instance-specific render method is set.

If method is None and this method is called via:

  • a class, the class-wide render method is unset, so that it uses that of its parent style class (if any) or the default.

  • an instance, the instance-specific render method is unset, so that it uses the class-wide render method thenceforth.

Any instance without a render method set uses the class-wide render method.

Note

method = None is always allowed, even if the render style doesn’t implement multiple render methods.

The class-wide render method is descendant.

set_size(width=None, height=None, frame_size=(0, -2))[source]#

Sets the image size (with extended control).

Parameters:
  • width (int | Size | None) –

    Can be

    • a positive integer; horizontal dimension of the image, in columns.

    • a Size enum member.

  • height (int | Size | None) –

    Can be

    • a positive integer; vertical dimension of the image, in lines.

    • a Size enum member.

  • frame_size (Tuple[int, int]) –

    Frame size, (columns, lines). If columns or lines is

    • positive, it is absolute and used as-is.

    • non-positive, it is relative to the corresponding terminal dimension and equivalent to the absolute dimension max(terminal_dimension + frame_dimension, 1).

    This is used only when neither width nor height is an int.

Raises:
  • TypeError – An argument is of an inappropriate type.

  • ValueError – An argument is of an appropriate type but has an unexpected/invalid value.

  • If both width and height are not None, they must be positive integers and manual sizing applies i.e the image size is set as given without preserving aspect ratio.

  • If width or height is a Size enum member, automatic sizing applies as prescribed by the enum member.

  • If neither width nor height is given (or both are None), FIT applies.

tell()[source]#

Returns the current image frame number.

Return type:

int


class term_image.image.TextImage(image, *, width=None, height=None)[source]#

Bases: BaseImage

Base of all Text-based Render Styles.

See BaseImage for the description of the constructor.

Important

Instantiation of subclasses is always allowed, even if the current terminal does not [fully] support the render style.

To check if the render style is fully supported in the current terminal, use is_supported().

Attention

This class cannot be directly instantiated. Image instances should be created from its subclasses.


class term_image.image.BlockImage(image, *, width=None, height=None)[source]#

Bases: TextImage

A render style using unicode half blocks and direct-color colour escape sequences.

See TextImage for the description of the constructor.


class term_image.image.GraphicsImage(image, *, width=None, height=None)[source]#

Bases: BaseImage

Base of all Graphics-based Render Styles.

Raises:

term_image.exceptions.StyleError – The active terminal doesn’t support the render style.

See BaseImage for the description of the constructor.

Attention

This class cannot be directly instantiated. Image instances should be created from its subclasses.

Tip

To allow instantiation regardless of whether the render style is supported or not, enable forced_support.


class term_image.image.ITerm2Image(image, *, width=None, height=None)[source]#

Bases: GraphicsImage

A render style using the iTerm2 inline image protocol.

See GraphicsImage for the complete description of the constructor.


Render Methods

ITerm2Image provides two methods of rendering images, namely:

LINES (default)

Renders an image line-by-line i.e the image is evenly split across the number of lines it should occupy.

Pros:

  • Good for use cases where it might be required to trim some lines of the image.

Cons:

  • Image drawing is significantly slower on iTerm2 due to the terminal emulator’s performance.

WHOLE

Renders an image all at once i.e the entire image data is encoded into one line of the render output, such that the entire image is drawn once by the terminal and still occupies the correct amount of lines and columns.

Pros:

  • Render results are more compact (i.e less in character count) than with the LINES method since the entire image is encoded at once.

  • Image drawing is faster than with LINES on most terminals.

  • Smoother animations.

Cons:

  • This method currently doesn’t work well on iTerm2 and WezTerm when the image height is greater than the terminal height.

ANIM

Renders an animated image to utilize the protocol’s native animation feature [1].

Similar to the WHOLE render method, except that the terminal emulator animates the image, provided it supports the feature of the protocol. The animation is completely controlled by the terminal emulator.

Note

  • If the image data size (in bytes) is greater than the value of native_anim_max_bytes, a warning is issued.

  • If used with ImageIterator or an animation, the WHOLE render method is used instead.

  • If the image is non-animated, the WHOLE render method is used instead.

Note

The LINES method is the default only because it works properly in all cases, it’s more advisable to use the WHOLE method except when the image height is greater than the terminal height or when trimming the image is required.

The render method can be set with set_render_method() using the names specified above.


Style-Specific Render Parameters

See BaseImage.draw() (particularly the style parameter).

  • method (None | str) → Render method override.

    • None → the current effective render method of the instance is used.

    • defaultNone

  • mix (bool) → Cell content inter-mix policy (Only supported on WezTerm, ignored otherwise).

    • False → existing contents of cells within the region covered by the drawn render output are erased

    • True → existing cell contents show under transparent areas of the drawn render output

    • defaultFalse

  • compress (int) → ZLIB compression level, for renders re-encoded in PNG format.

    • 0 <= compress <= 9

    • 1 → best speed, 9 → best compression, 0 → no compression

    • default4

    • Results in a trade-off between render time and data size/draw speed


Format Specification

See Render Format Specification.

[ <method> ]  [ m <mix> ]  [ c <compress> ]
  • method → render method override

    • LLINES render method (current frame only, for animated images)

    • WWHOLE render method (current frame only, for animated images)

    • AANIM render method [1]

    • default → current effective render method of the instance

  • m → cell content inter-mix policy (Only supported in WezTerm, ignored otherwise)

    • mix → inter-mix policy

      • 0 → existing contents of cells in the region covered by the drawn render output will be erased

      • 1 → existing cell contents show under transparent areas of the drawn render output

    • defaultm0

    • e.g m0, m1

  • c → ZLIB compression level, for renders re-encoded in PNG format

    • compress → compression level

      • An integer in the range 0 <= x <= 9

      • 1 → best speed, 9 → best compression, 0 → no compression

    • defaultc4

    • e.g c0, c9

    • Results in a trade-off between render time and data size/draw speed


Important

Currently supported terminal emulators are:


Class/Instance Properties:

jpeg_quality

JPEG encoding quality

read_from_file

Read-from-file optimization

Class Properties:

native_anim_max_bytes

Maximum size (in bytes) of image data for native animation

Class Methods:

clear

Clears images.

property jpeg_quality#

JPEG encoding quality

Type:

int

GET:

Returns the effective JPEG encoding quality of the invoker (class or instance).

SET:

If invoked via:

  • a class, the class-wide quality is set.

  • an instance, the instance-specific quality is set.

DELETE:

If invoked via:

  • a class, the class-wide quality is unset.

  • an instance, the instance-specific quality is unset.

If:

  • value < 0; JPEG encoding is disabled.

  • 0 <= value <= 95; JPEG encoding is enabled with the given quality.

If unset for:

  • a class, it uses that of its parent iterm2 style class (if any) or the default (disabled), if unset for all parents or the class has no parent iterm2 style class.

  • an instance, it uses that of its class.

By default, the quality is unset (i.e JPEG encoding is disabled) and images are encoded in the PNG format (when not reading directly from file) but in some cases, higher and/or faster compression may be desired. JPEG encoding is significantly faster than PNG encoding and produces smaller (in data size) output but at the cost of image quality.

Note

  • This property is descendant.

  • This optimization applies to only re-encoded (i.e not read directly from file) non-transparent renders.

Tip

The transparency status of some images can not be correctly determined in an efficient way at render time. To ensure JPEG encoding is always used for a re-encoded render, disable transparency or set a background color.

Furthermore, to ensure that renders with the WHOLE render method are always re-encoded, disable read_from_file.

This optimization is useful in improving non-native animation performance.

See also

property native_anim_max_bytes#

Maximum size (in bytes) of image data for native animation

Type:

int

GET:

Returns the set value.

SET:

A positive integer; the value is set.

Can not be set via an instance.

DELETE:

The value is reset to the default.

Can not be reset via an instance.

TermImageUserWarning is issued (and shown only the first time, except the warning filters are modified to do otherwise) if the image data size for a native animation is above this value.

Note

This property is a global setting. Hence, setting/resetting it on this class or any subclass affects all classes and their instances.

Warning

This property should be altered with caution to avoid excessive memory usage, particularly on the terminal emulator’s end.

property read_from_file#

Read-from-file optimization

Type:

bool

GET:

Returns the effective read-from-file policy of the invoker (class or instance).

SET:

If invoked via:

  • a class, the class-wide policy is set.

  • an instance, the instance-specific policy is set.

DELETE:

If invoked via:

  • a class, the class-wide policy is unset.

  • an instance, the instance-specific policy is unset.

If the value is:

  • True, image data is read directly from file when possible and no image manipulation is required.

  • False, images are always re-encoded (in the PNG format by default).

If unset for:

  • a class, it uses that of its parent iterm2 style class (if any) or the default (True), if unset for all parents or the class has no parent iterm2 style class.

  • an instance, it uses that of its class.

By default, the policy is unset, which is equivalent to True i.e the optimization is enabled.

Note

  • This property is descendant.

  • This is an optimization to reduce render times and is only applicable to the WHOLE render method, since the the LINES method inherently requires image manipulation.

  • This property does not affect animations. Native animations are always read from file when possible and frames of non-native animations have to be re-encoded.

See also

jpeg_quality

classmethod clear(cursor=False, now=False)[source]#

Clears images.

Parameters:
  • cursor (bool) – If True, all images intersecting with the current cursor position are cleared. Otherwise, all visible images are cleared.

  • now (bool) – If True the images are cleared immediately, without affecting any standard I/O stream. Otherwise they’re cleared when next sys.stdout is flushed.

Note

Required and works only on Konsole, as text doesn’t overwrite images.


class term_image.image.KittyImage(image, *, width=None, height=None)[source]#

Bases: GraphicsImage

A render style using the Kitty terminal graphics protocol.

See GraphicsImage for the complete description of the constructor.


Render Methods

KittyImage provides two methods of rendering images, namely:

LINES (default)

Renders an image line-by-line i.e the image is evenly split across the number of lines it should occupy.

Pros:

  • Good for use cases where it might be required to trim some lines of the image.

WHOLE

Renders an image all at once i.e the entire image data is encoded into one line of the rendered output, such that the entire image is drawn once by the terminal and still occupies the correct amount of lines and columns.

Pros:

  • Render results are more compact (i.e less in character count) than with the LINES method since the entire image is encoded at once.

The render method can be set with set_render_method() using the names specified above.


Style-Specific Render Parameters

See BaseImage.draw() (particularly the style parameter).

  • method (None | str) → Render method override.

    • None → the current effective render method of the instance is used.

    • defaultNone

  • z_index (int) → The stacking order of graphics and text for non-animations.

    • An integer in the signed 32-bit range (excluding -(2**31))

    • >= 0 → the image will be drawn above text

    • < 0 → the image will be drawn below text

    • < -(2**31)/2 → the image will be drawn below cells with non-default background color

    • default0

    • Overlapping graphics on different z-indexes will be blended (by the terminal emulator) if they are semi-transparent.

    • To inter-mix text with graphics, see the mix parameter.

  • mix (bool) → Graphics/Text inter-mix policy.

    • False → text within the region covered by the drawn render output will be erased, though text can be inter-mixed with graphics after drawing

    • True → text within the region covered by the drawn render output will NOT be erased

    • defaultFalse

  • compress (int) → ZLIB compression level.

    • 0 <= compress <= 9

    • 1 → best speed, 9 → best compression, 0 → no compression

    • default4

    • Results in a trade-off between render time and data size/draw speed


Format Specification

See Render Format Specification.

[ <method> ]  [ z <z-index> ]  [ m <mix> ]  [ c <compress> ]
  • method → render method override

    • LLINES render method (current frame only, for animated images)

    • WWHOLE render method (current frame only, for animated images)

    • default → Current effective render method of the image

  • z → graphics/text stacking order

    • z-index → z-index

      • An integer in the signed 32-bit range (excluding -(2**31))

      • >= 0 → the render output will be drawn above text

      • < 0 → the render output will be drawn below text

      • < -(2**31)/2 → the render output will be drawn below cells with non-default background color

    • defaultz0 (z-index zero)

    • e.g z0, z1, z-1, z2147483647, z-2147483648

    • overlapping graphics on different z-indexes will be blended (by the terminal emulator) if they are semi-transparent

  • m → graphics/text inter-mix policy

    • mix → inter-mix policy

      • 0 → text within the region covered by the drawn render output will be erased, though text can be inter-mixed with graphics after drawing

      • 1 → text within the region covered by the drawn render output will NOT be erased

    • defaultm0

    • e.g m0, m1

  • c → ZLIB compression level

    • compress → compression level

      • An integer in the range 0 <= compress <= 9

      • 1 → best speed, 9 → best compression, 0 → no compression

    • defaultc4

    • e.g c0, c9

    • results in a trade-off between render time and data size/draw speed


Important

Currently supported terminal emulators are:

Class Methods:

clear

Clears images.

classmethod clear(*, cursor=False, z_index=None, now=False)[source]#

Clears images.

Parameters:
  • cursor (bool) – If True, all images intersecting with the current cursor position are cleared.

  • z_index (int | None) – An integer in the signed 32-bit range. If given, all images on the given z-index are cleared.

  • now (bool) – If True the images are cleared immediately, without affecting any standard I/O stream. Otherwise they’re cleared when next sys.stdout is flushed.

Aside now, only one other argument may be given. If no argument is given (aside now) or default values are given, all images visible on the screen are cleared.

Note

This method does nothing if the render style is not supported.


Context Management Protocol Support#

BaseImage instances are context managers i.e they can be used with the with statement as in:

with from_url(url) as image:
    ...

Using an instance as a context manager guarantees instant object finalization (i.e clean-up/release of resources), especially for instances with URL sources (see BaseImage.from_url()).


Iteration Support#

Animated images are iterable i.e they can be used with the for statement (and other means of iteration such as unpacking) as in:

for frame in from_file("animated.gif"):
    ...

Subsequent frames of the image are yielded on subsequent iterations.

Note

  • iter(anim_image) returns an ImageIterator instance with a repeat count of 1, hence caching is disabled.

  • The frames are unformatted and transparency is enabled i.e as returned by str(image).

For extensive or custom iteration, use ImageIterator directly.

Other Classes#
class term_image.image.ImageIterator(image, repeat=-1, format_spec='', cached=100)[source]#

Bases: object

Efficiently iterate over rendered frames of an animated image

Parameters:
  • image (BaseImage) – Animated image.

  • repeat (int) – The number of times to go over the entire image. A negative value implies infinite repetition.

  • format_spec (str) – The format specifier for the rendered frames (default: auto).

  • cached (Union[bool, int]) –

    Determines if the rendered frames will be cached (for speed up of subsequent renders) or not. If it is

    • a boolean, caching is enabled if True. Otherwise, caching is disabled.

    • a positive integer, caching is enabled only if the framecount of the image is less than or equal to the given number.

Raises:
  • If repeat equals 1, caching is disabled.

  • The iterator has immediate response to changes in the image size.

  • If the image size is dynamic, it’s computed per frame.

  • The number of the last yielded frame is set as the image’s seek position.

  • Directly adjusting the seek position of the image doesn’t affect iteration. Use ImageIterator.seek() instead.

  • After the iterator is exhausted, the underlying image is set to frame 0.

Instance Properties:

loop_no

Iteration repeat countdown

Instance Methods:

close

Closes the iterator and releases resources used.

seek

Sets the frame number to be yielded on the next iteration without affecting the repeat count.

property loop_no#

Iteration repeat countdown

Type:

Optional[int]

GET:

Returns:

  • None, if iteration hasn’t started.

  • Otherwise, the current iteration repeat countdown value.

Changes on the first iteration of each loop, except for infinite iteration where it’s always -1. When iteration has ended, the value is zero.

close()[source]#

Closes the iterator and releases resources used.

Does not reset the frame number of the underlying image.

Note

This method is automatically called when the iterator is exhausted or garbage-collected.

seek(pos)[source]#

Sets the frame number to be yielded on the next iteration without affecting the repeat count.

Parameters:

pos (int) – Next frame number.

Raises:

Frame numbers start from 0 (zero).

padding Module#

Classes#

Padding

Render output padding.

AlignedPadding

Aligned render output padding.

ExactPadding

Exact render output padding.

class term_image.padding.Padding(fill=' ')[source]#

Bases: object

Render output padding.

Parameters:

fill (str) –

Determines the string with which render outputs will be padded.

May be any string that occupies exactly one column on a terminal screen, or an empty string. If empty, the padding simply advances the cursor without overwriting existing content on the terminal screen.

Attention

This is an abstract base class. Hence, only concrete subclasses can be instantiated.

See also

Padding

Padding‘s Extension API

Attributes:

fill

Fill string

Instance Methods:

get_padded_size

Computes an expected padded render size.

pad

Pads a render output.

to_exact

Converts the padding to an exact padding for the given render size.

fill: str#

Fill string

get_padded_size(render_size)[source]#

Computes an expected padded render size.

Parameters:

render_size (Size) – Render size.

Returns:

The size of the render output that would be produced by using this instance to pad a render output with the given size.

Return type:

Size

pad(render, render_size)[source]#

Pads a render output.

Parameters:
Returns:

The padded render output.

This is also in the form specified to be returned by Renderable._render_(), provided render is.

Return type:

str

to_exact(render_size)[source]#

Converts the padding to an exact padding for the given render size.

Parameters:

render_size (Size) – Render size.

Returns:

An equivalent exact padding, with respect to the given render size i.e one that would produce the same result as the padding being converted, for the given render size.

Return type:

ExactPadding

This is useful to avoid recomputing the exact padding dimensions for the same render size.


class term_image.padding.AlignedPadding(width, height, h_align=HAlign.CENTER, v_align=VAlign.MIDDLE, fill=' ')[source]#

Bases: Padding

Aligned render output padding.

Parameters:

If width or height is:

  • positive, it is absolute and used as-is.

  • non-positive, it is relative to the corresponding terminal dimension (at the point of resolution) and equivalent to the absolute dimension max(terminal_dimension + relative_dimension, 1).

The padded render dimension (i.e the dimension of a render output after it’s padded) on each axis is given by:

padded_dimension = max(render_dimension, absolute_minimum_dimension)

In words… If the absolute minimum render dimension on an axis is less than or equal to the corresponding render dimension, there is no padding on that axis and the padded render dimension on that axis is equal to the render dimension. Otherwise, the render output will be padded along that axis and the padded render dimension on that axis is equal to the minimum render dimension.

The amount of padding to each side depends on the alignment, defined by h_align and v_align.

Important

RelativePaddingDimensionError is raised if any padding-related computation/operation (basically, calling any method other than resolve()) is performed on an instance with relative minimum render dimension(s) i.e if relative is True.

Note

Any interface receiving an instance with relative dimension(s) should typically resolve it/them upon reception.

Tip

  • Instances are immutable and hashable.

  • Instances with equal fields compare equal.

Attributes:

width

Minimum render width

height

Minimum render height

h_align

Horizontal alignment

v_align

Vertical alignment

relative

True if either or both minimum render dimension(s) is/are relative i.e non-positive.

Instance Properties:

size

Minimum render size

Instance Methods:

get_padded_size

Computes an expected padded render size.

resolve

Resolves relative minimum render dimensions.

width: int#

Minimum render width

height: int#

Minimum render height

h_align: HAlign#

Horizontal alignment

v_align: VAlign#

Vertical alignment

relative: bool#

True if either or both minimum render dimension(s) is/are relative i.e non-positive. Otherwise, False.

property size: RawSize#

Minimum render size

GET:

Returns the minimum render dimensions.

get_padded_size(render_size)[source]#

Computes an expected padded render size.

See Padding.get_padded_size().

Raises:

RelativePaddingDimensionError – Relative minimum render dimension(s).

resolve(terminal_size)[source]#

Resolves relative minimum render dimensions.

Parameters:

terminal_size (terminal_size) – The terminal size against which to resolve relative dimensions.

Returns:

An instance with equivalent absolute dimensions.

Return type:

AlignedPadding


class term_image.padding.ExactPadding(left=0, top=0, right=0, bottom=0, fill=' ')[source]#

Bases: Padding

Exact render output padding.

Parameters:
  • left (int) – Left padding dimension

  • top (int) – Top padding dimension.

  • right (int) – Right padding dimension

  • bottom (int) – Bottom padding dimension

Raises:

ValueError – A dimension is negative.

Pads a render output on each side by the specified amount of lines or columns.

Tip

  • Instances are immutable and hashable.

  • Instances with equal fields compare equal.

Attributes:

left

Left padding dimension

top

Top padding dimension

right

Right padding dimension

bottom

Bottom padding dimension

Instance Properties:

dimensions

Padding dimensions

left: int#

Left padding dimension

top: int#

Top padding dimension

right: int#

Right padding dimension

bottom: int#

Bottom padding dimension

property dimensions: tuple[int, int, int, int]#

Padding dimensions

GET:

Returns the padding dimensions, (left, top, right, bottom).


Enumerations#

HAlign

Horizontal alignment enumeration

VAlign

Vertical alignment enumeration

class term_image.padding.HAlign[source]#

Bases: IntEnum

Horizontal alignment enumeration

LEFT#

Left horizontal alignment

CENTER#

Center horizontal alignment

RIGHT#

Right horizontal alignment


class term_image.padding.VAlign[source]#

Bases: IntEnum

Vertical alignment enumeration

TOP#

Top vertical alignment

MIDDLE#

Middle vertical alignment

BOTTOM#

Bottom vertical alignment


Exceptions#

PaddingError

Base exception class for padding errors.

RelativePaddingDimensionError

Raised when a padding operation is performed on an AlignedPadding instance with relative minimum render dimension(s).

exception term_image.padding.PaddingError[source]#

Bases: TermImageError

Base exception class for padding errors.

exception term_image.padding.RelativePaddingDimensionError[source]#

Bases: PaddingError

Raised when a padding operation is performed on an AlignedPadding instance with relative minimum render dimension(s).


Extension API#

Note

The following definitions are provided and required only for extended use of the interfaces defined above.

Everything required for normal usage should typically be exposed in the public API.

Padding#
class term_image.padding.Padding[source]

See Padding for the public API.

Note

Instances of subclasses should be immutable to avoid inconsistent results in asynchronous render operations that perform padding.

Instance Methods:

_get_exact_dimensions_

Returns the exact padding dimensions for the given render size.

abstract _get_exact_dimensions_(render_size)[source]#

Returns the exact padding dimensions for the given render size.

Parameters:

render_size (Size) – Render size.

Returns:

Returns the exact padding dimensions, (left, top, right, bottom).

Return type:

tuple[int, int, int, int]

This is called to implement operations in the public API.

renderable Module#

Classes#

Renderable

A renderable.

RenderArgs

Render arguments.

ArgsNamespace

Render class-specific render argument namespace.

Frame

A rendered frame.

class term_image.renderable.Renderable(frame_count, frame_duration)[source]#

Bases: object

A renderable.

Parameters:
  • frame_count (int | FrameCount) –

    Number of frames. If it’s a

    • positive integer, the number of frames is as given.

    • FrameCount enum member, see the member’s description.

    If equal to 1 (one), the renderable is non-animated. Otherwise, it is animated.

  • frame_duration (int | FrameDuration) –

    The duration of a frame. If it’s a

    • positive integer, it implies a static duration (in milliseconds) i.e the same duration applies to every frame.

    • FrameDuration enum member, see the member’s description.

    This argument is ignored if frame_count equals 1 (one) i.e the renderable is non-animated.

Raises:

ValueError – An argument has an invalid value.

Attention

This is an abstract base class. Hence, only concrete subclasses can be instantiated.

See also

Renderable

Renderable‘s Extension API

Attributes:

Args

Render class-specific render arguments.

animated

True if the renderable is animated.

Special Methods:

__iter__

Returns a render iterator.

__str__

Renders the current frame with default arguments and no padding.

Instance Properties:

frame_count

Frame count

frame_duration

Frame duration

render_size

Render size

Instance Methods:

draw

Draws the current frame or an animation to standard output.

render

Renders the current frame.

seek

Sets the current frame number.

tell

Returns the current frame number.

Args: ClassVar[type[ArgsNamespace] | None]#

Render class-specific render arguments.

This is either:

  • a render argument namespace class (subclass of ArgsNamespace) associated [3] with the render class, or

  • None, if the render class has no render arguments.

If this is a class, an instance of it (or a subclass thereof) is contained within any RenderArgs instance associated [1] with the render class or any of its subclasses. Also, an instance of this class (or a subclass of it) is returned by render_args[render_cls]; where render_args is an instance of RenderArgs as previously described and render_cls is the render class with which this namespace class is associated [3].

None
>>> class Foo(Renderable):
...     pass
...
... class FooArgs(ArgsNamespace, render_cls=Foo):
...     foo: str | None = None
...
>>> Foo.Args is FooArgs
True
>>>
>>> # default
>>> foo_args = Foo.Args()
>>> foo_args
FooArgs(foo=None)
>>> foo_args.foo is None
True
>>>
>>> render_args = RenderArgs(Foo)
>>> render_args[Foo]
FooArgs(foo=None)
>>>
>>> # non-default
>>> foo_args = Foo.Args("FOO")
>>> foo_args
FooArgs(foo='FOO')
>>> foo_args.foo
'FOO'
>>>
>>> render_args = RenderArgs(Foo, foo_args.update(foo="bar"))
>>> render_args[Foo]
FooArgs(foo='bar')

On the other hand, if this is None, it implies the render class has no render arguments.

None
>>> class Bar(Renderable):
...     pass
...
>>> Bar.Args is None
True
>>> render_args = RenderArgs(Bar)
>>> render_args[Bar]
Traceback (most recent call last):
  ...
NoArgsNamespaceError: 'Bar' has no render arguments
animated: bool#

True if the renderable is animated. Otherwise, False.

iter(self)[source]#

Returns a render iterator.

Returns:

A render iterator (with frame caching disabled and all other optional arguments to RenderIterator being the default values).

Raises:

NonAnimatedRenderableError – The renderable is non-animated.

Return type:

RenderIterator

Animated renderables are iterable i.e they can be used with various means of iteration such as the for statement and iterable unpacking.

str(self)[source]#

Renders the current frame with default arguments and no padding.

Returns:

The frame render output.

Raises:

RenderError – An error occurred during rendering.

Return type:

str

property frame_count: int | Literal[FrameCount.INDEFINITE]#

Frame count

GET:

Returns either

  • the number of frames the renderable has, or

  • INDEFINITE.

property frame_duration: int | FrameDuration#

Frame duration

GET:

Returns

  • a positive integer, a static duration (in milliseconds) i.e the same duration applies to every frame; or

  • DYNAMIC.

SET:

If the value is

  • a positive integer, it implies a static duration (in milliseconds) i.e the same duration applies to every frame.

  • DYNAMIC, see the enum member’s description.

Raises:

NonAnimatedRenderableError – The renderable is non-animated.

property render_size: Size#

Render size

GET:

Returns the size of the renderable’s render output.

draw(render_args=None, padding=AlignedPadding(width=0, height=-2, h_align=CENTER, v_align=MIDDLE, fill=' '), *, animate=True, loops=-1, cache=100, check_size=True, allow_scroll=False, hide_cursor=True, echo_input=False)[source]#

Draws the current frame or an animation to standard output.

Parameters:
  • render_args (RenderArgs | None) – Render arguments.

  • padding (Padding) – Render output padding.

  • animate (bool) – Whether to enable animation for animated renderables. If disabled, only the current frame is drawn.

  • loops (int) – See RenderIterator (applies to animations only).

  • cache (bool | int) – See RenderIterator. (applies to animations only).

  • check_size (bool) – Whether to validate the padded render size of non-animations.

  • allow_scroll (bool) – Whether to validate the padded render height of non-animations. Ignored if check_size is False.

  • hide_cursor (bool) – Whether to hide the cursor while drawing.

  • echo_input (bool) –

    Whether to display input while drawing (applies on Unix only).

    Note

    • If disabled (default), input is not read/consumed, it’s just not displayed.

    • If enabled, echoed input may affect cursor positioning and therefore, the output (especially for animations).

Raises:

If check_size is True (or it’s an animation),

Note

  • hide_cursor and echo_input apply if and only if the output stream is connected to a terminal.

  • For animations (i.e animated renderables with animate = True), the padded render size is always validated.

  • Animations with definite frame count, by default, are infinitely looped but can be terminated with SIGINT (CTRL + C), without raising KeyboardInterrupt.

render(render_args=None, padding=ExactPadding(left=0, top=0, right=0, bottom=0, fill=' '))[source]#

Renders the current frame.

Parameters:
Returns:

The rendered frame.

Raises:
Return type:

Frame

seek(offset, whence=Seek.START)[source]#

Sets the current frame number.

Parameters:
  • offset (int) – Frame offset (relative to whence).

  • whence (Seek) – Reference position for offset.

Returns:

The new current frame number.

Raises:
Return type:

int

The value range for offset depends on whence:

whence

Valid value range for offset

START

0 <= offset < frame_count

CURRENT

-tell() <= offset < frame_count - tell()

END

-frame_count < offset <= 0

tell()[source]#

Returns the current frame number.

Returns:

Zero, if the renderable is non-animated or has INDEFINITE frame count. Otherwise, the current frame number.

Return type:

int


class term_image.renderable.RenderArgs(render_cls, /, *namespaces)[source]#
class term_image.renderable.RenderArgs(render_cls, init_render_args, /, *namespaces)

Bases: RenderArgsData

Render arguments.

Parameters:
  • render_cls (type[Renderable]) – A render class.

  • init_render_args (RenderArgs | None) –

    A set of render arguments. If not None,

    • it must be compatible [2] with render_cls,

    • it’ll be used to initialize the render arguments.

  • namespaces (ArgsNamespace) –

    Render argument namespaces compatible [4] with render_cls.

    Note

    If multiple namespaces associated with the same render class are given, the last of them takes precedence.

Raises:

A set of render arguments (an instance of this class) is basically a container of render argument namespaces (instances of ArgsNamespace); one for each render class, which has render arguments, in the Method Resolution Order of its associated [1] render class.

The namespace for each render class is derived from the following sources, in [descending] order of precedence:

  • namespaces

  • init_render_args

  • default render argument namespaces

Note

Instances are immutable but updated copies can be created via update().

See also

Args

Render class-specific render arguments.

Footnotes

Attributes:

render_cls

The associated render class

Special Methods:

__contains__

Checks if a render argument namespace is contained in this set of render arguments.

__eq__

Compares this set of render arguments with another.

__getitem__

Returns a constituent namespace.

__hash__

Computes the hash of the render arguments.

__iter__

Returns an iterator that yields the constituent namespaces.

Instance Methods:

convert

Converts the set of render arguments to one for a related render class.

update

Replaces or updates render argument namespaces.

render_cls: type[Renderable]#

The associated render class

namespace in self[source]#

Checks if a render argument namespace is contained in this set of render arguments.

Parameters:

namespace (ArgsNamespace) – A render argument namespace.

Returns:

True if the given namespace is equal to any of the namespaces contained in this set of render arguments. Otherwise, False.

Return type:

bool

self == other[source]#

Compares this set of render arguments with another.

Parameters:

other (object) – Another set of render arguments.

Returns:

True if both are associated with the same render class and have equal argument values. Otherwise, False.

Return type:

bool

self[render_cls][source]#

Returns a constituent namespace.

Parameters:

render_cls (type[Renderable]) – A render class of which render_cls is a subclass (which may be render_cls itself) and which has render arguments.

Returns:

The constituent namespace associated with render_cls.

Raises:
Return type:

Any

Note

The return type hint is Any only for compatibility with static type checking, as this aspect of the interface seems too dynamic to be correctly expressed with the exisiting type system.

Regardless, the return value is guaranteed to always be an instance of a render argument namespace class associated with render_cls. For instance, the following would always be valid for Renderable:

renderable_args: RenderableArgs = render_args[Renderable]

and similar idioms are encouraged to be used for other render classes.

hash(self)[source]#

Computes the hash of the render arguments.

Returns:

The computed hash.

Return type:

int

Important

Like tuples, an instance is hashable if and only if the constituent namespaces are hashable.

iter(self)[source]#

Returns an iterator that yields the constituent namespaces.

Returns:

An iterator that yields the constituent namespaces.

Return type:

Iterator[ArgsNamespace]

Warning

The number and order of namespaces is guaranteed to be the same across all instances associated [1] with the same render class but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Renderable API and the number should be considered alike with respect to the associated render class.

convert(render_cls)[source]#

Converts the set of render arguments to one for a related render class.

Parameters:

render_cls (type[Renderable]) – A render class of which render_cls is a parent or child (which may be render_cls itself).

Returns:

A set of render arguments associated [1] with render_cls and initialized with all constituent namespaces (of this set of render arguments, self) that are compatible [4] with render_cls.

Raises:

ValueErrorrender_cls is not a parent or child of render_cls.

Return type:

RenderArgs

update(namespace, /, *namespaces) RenderArgs[source]#
update(render_cls, /, **fields) RenderArgs

Replaces or updates render argument namespaces.

Parameters:
  • namespace (ArgsNamespace) – Prepended to namespaces.

  • namespaces (ArgsNamespace) –

    Render argument namespaces compatible [4] with render_cls.

    Note

    If multiple namespaces associated with the same render class are given, the last of them takes precedence.

  • render_cls (type[Renderable]) – A render class of which render_cls is a subclass (which may be render_cls itself) and which has render arguments.

  • fields (Any) –

    Render argument fields.

    The keywords must be names of render argument fields for render_cls.

Returns:

For the first form, an instance with the namespaces for the respective associated render classes of the given namespaces replaced.

For the second form, an instance with the given render argument fields for render_cls updated, if any.

Raises:

TypeError – The arguments given do not conform to any of the expected forms.

Return type:

RenderArgs

Propagates exceptions raised by:


class term_image.renderable.ArgsNamespace(*values, **fields)[source]#

Bases: ArgsDataNamespace

Render class-specific render argument namespace.

Parameters:
  • values (Any) –

    Render argument field values.

    The values are mapped to fields in the order in which the fields were defined.

  • fields (Any) –

    Render argument fields.

    The keywords must be names of render argument fields for the associated [3] render class.

Raises:

If no value is given for a field, its default value is used.

Note

  • Fields are exposed as instance attributes.

  • Instances are immutable but updated copies can be created via update().

See also

ArgsNamespace.

Footnotes

Special Methods:

__eq__

Compares the namespace with another.

__hash__

Computes the hash of the namespace.

__or__

Derives a set of render arguments from the combination of both operands.

__pos__

Creates a set of render arguments from the namespace.

__ror__

Same as __or__() but with reflected operands.

Instance Methods:

as_dict

Copies the namespace as a dictionary.

to_render_args

Creates a set of render arguments from the namespace.

update

Updates render argument fields.

Class Methods:

get_fields

Returns the field definitions.

get_render_cls

Returns the associated render class.

self == other[source]#

Compares the namespace with another.

Parameters:

other (object) – Another render argument namespace.

Returns:

True if both operands are associated with the same render class and have equal field values. Otherwise, False.

Return type:

bool

hash(self)[source]#

Computes the hash of the namespace.

Returns:

The computed hash.

Return type:

int

Important

Like tuples, an instance is hashable if and only if the field values are hashable.

self | other[source]#

Derives a set of render arguments from the combination of both operands.

Parameters:

other (ArgsNamespace | RenderArgs) – Another render argument namespace or a set of render arguments.

Returns:

A set of render arguments associated with the most derived one of the associated render classes of both operands.

Raises:
Return type:

RenderArgs

Note

  • If other is a render argument namespace associated with the same render class as self, other takes precedence.

  • If other is a set of render arguments that contains a namespace associated with the same render class as self, self takes precedence.

+self[source]#

Creates a set of render arguments from the namespace.

Returns:

A set of render arguments associated with the same render class as the namespace and initialized with the namespace.

Return type:

RenderArgs

Tip

+namespace is shorthand for namespace.to_render_args().

other | self[source]#

Same as __or__() but with reflected operands.

Note

Unlike __or__(), if other is a render argument namespace associated with the same render class as self, self takes precedence.

as_dict()[source]#

Copies the namespace as a dictionary.

Returns:

A dictionary mapping field names to their values.

Return type:

dict[str, Any]

Warning

The number and order of fields are guaranteed to be the same for a namespace class that defines fields, its subclasses, and all their instances; but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Render Arguments/Data API and the number should be considered an implementation detail of the specific namespace subclass.

classmethod get_fields()[source]#

Returns the field definitions.

Returns:

A mapping of field names to their default values.

Return type:

Mapping[str, Any]

Warning

The number and order of fields are guaranteed to be the same for a namespace class that defines fields, its subclasses, and all their instances; but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Render Arguments/Data API and the number should be considered an implementation detail of the specific namespace subclass.

to_render_args(render_cls=None)[source]#

Creates a set of render arguments from the namespace.

Parameters:

render_cls (type[Renderable] | None) – A render class, with which the namespace is compatible [4].

Returns:

A set of render arguments associated with render_cls (or the associated [3] render class of the namespace, if None) and initialized with the namespace.

Return type:

RenderArgs

Propagates exceptions raised by the RenderArgs constructor, as applicable.

See also

__pos__().

update(**fields)[source]#

Updates render argument fields.

Parameters:

fields (Any) – Render argument fields.

Returns:

A namespace with the given fields updated.

Raises:

UnknownArgsFieldError – Unknown field name(s).

Return type:

Self

classmethod get_render_cls()#

Returns the associated render class.

Returns:

The associated render class, if the namespace class has been associated.

Raises:

UnassociatedNamespaceError – The namespace class hasn’t been associated with a render class.

Return type:

type[Renderable]


class term_image.renderable.Frame(number, duration, render_size, render_output)[source]#

Bases: NamedTuple

A rendered frame.

Tip

  • Instances are immutable and hashable.

  • Instances with equal fields compare equal.

Warning

Even though this class inherits from tuple, the class and its instances should not be used as such, because:

  • this is an implementation detail,

  • the number or order of fields may change.

Any change to this aspect of the interface may happen without notice and will not be considered a breaking change.

Attributes:

number

Frame number

duration

Frame duration (in milliseconds)

render_size

Frame render size

render_output

Frame render output

Special Methods:

__str__

Returns the frame render output.

number: int#

Frame number

The number of the rendered frame (a non-negative integer), if the frame was rendered by a renderable with definite frame count. Otherwise, the value range and meaning of this field is unspecified.

duration: int#

Frame duration (in milliseconds)

The duration of the rendered frame (a non-negative integer), if the frame was rendered by an animated renderable. Otherwise, the value range and meaning of this field is unspecified.

Hint

For animated renderables, a zero value indicates that the next frame should be displayed immediately after (without any delay), except stated otherwise.

render_size: Size#

Frame render size

render_output: str#

Frame render output

str(self)[source]#

Returns the frame render output.

Returns:

The frame render output, render_output.

Return type:

str


Enumerations#

FrameCount

Frame count enumeration

FrameDuration

Frame duration enumeration

Seek

Relative seek enumeration

class term_image.renderable.FrameCount[source]#

Bases: Enum

Frame count enumeration

See also

frame_count, seek(), tell().

INDEFINITE#

Indicates a renderable has a streaming source.

In other words, it’s either the renderable has an infinite amount of frames or the exact amount cannot be predetermined.

POSTPONED#

Indicates lazy evaluation of frame count.

Evaluation of frame count is postponed until frame_count is invoked.


class term_image.renderable.FrameDuration[source]#

Bases: Enum

Frame duration enumeration

See also

frame_duration.

DYNAMIC#

Dynamic frame duration

The duration of each frame is determined at render-time.


class term_image.renderable.Seek[source]#

Bases: IntEnum

Relative seek enumeration

Tip

  • Each member’s value is that of the corresponding os.SEEK_* constant.

  • Every member can be used directly as an integer since enum.IntEnum is a base class.

SET = 0#
START = 0#

Start position

CUR = 1#
CURRENT = 1#

Current position

END = 2#

End position


Exceptions#

RenderableError

Base exception class for errors specific to the Renderable API and other APIs extending it.

IndefiniteSeekError

Raised when a seek is attempted on a renderable with INDEFINITE frame count.

RenderError

Base exception class for errors that occur during rendering.

RenderSizeOutofRangeError

Raised when the render size of a renderable is beyond an expected range.

RenderArgsDataError

Base exception class for errors specific to RenderArgs and RenderData.

RenderArgsError

Base exception class for errors specific to RenderArgs.

RenderDataError

Base exception class for errors specific to RenderData.

IncompatibleArgsNamespaceError

Raised when a given render argument namespace is incompatible [4] with a certain render class.

IncompatibleRenderArgsError

Raised when a given set of render arguments is incompatible [2] with a certain render class.

NoArgsNamespaceError

Raised when an attempt is made to get a render argument namespace for a render class that has no render arguments.

NoDataNamespaceError

Raised when an attempt is made to get a render data namespace for a render class that has no render data.

NonAnimatedRenderableError

Raised when attempting to perform certain operations meant for animated renderables on a non-animated renderable.

UnassociatedNamespaceError

Raised when certain operations are attempted on a render argument/data namespace class that hasn't been associated [3] [6] with a render class.

UninitializedDataFieldError

Raised when an attempt is made to access a render data field that hasn't been initialized i.e for which a value hasn't been set.

UnknownArgsFieldError

Raised when an attempt is made to access or modify an unknown render argument field.

UnknownDataFieldError

Raised when an attempt is made to access or modify an unknown render data field.

exception term_image.renderable.RenderableError[source]#

Bases: TermImageError

Base exception class for errors specific to the Renderable API and other APIs extending it.

Raised for errors that occur during the creation of render classes.

exception term_image.renderable.IndefiniteSeekError[source]#

Bases: RenderableError

Raised when a seek is attempted on a renderable with INDEFINITE frame count.

exception term_image.renderable.RenderError[source]#

Bases: RenderableError

Base exception class for errors that occur during rendering.

If the direct cause of the error is an exception, it should typically be attached as the context of this exception, as in:

raise SubclassOfRenderError("...") from exception
exception term_image.renderable.RenderSizeOutofRangeError[source]#

Bases: RenderableError

Raised when the render size of a renderable is beyond an expected range.

exception term_image.renderable.RenderArgsDataError[source]#

Bases: RenderableError

Base exception class for errors specific to RenderArgs and RenderData.

Raised for errors that occur during the creation of render argument/data namespace classes.

exception term_image.renderable.RenderArgsError[source]#

Bases: RenderArgsDataError

Base exception class for errors specific to RenderArgs.

Raised for errors that occur during the creation of render argument namespace classes.

exception term_image.renderable.RenderDataError[source]#

Bases: RenderArgsDataError

Base exception class for errors specific to RenderData.

exception term_image.renderable.IncompatibleArgsNamespaceError[source]#

Bases: RenderArgsError

Raised when a given render argument namespace is incompatible [4] with a certain render class.

exception term_image.renderable.IncompatibleRenderArgsError[source]#

Bases: RenderArgsError

Raised when a given set of render arguments is incompatible [2] with a certain render class.

exception term_image.renderable.NoArgsNamespaceError[source]#

Bases: RenderArgsError

Raised when an attempt is made to get a render argument namespace for a render class that has no render arguments.

exception term_image.renderable.NoDataNamespaceError[source]#

Bases: RenderDataError

Raised when an attempt is made to get a render data namespace for a render class that has no render data.

exception term_image.renderable.NonAnimatedRenderableError[source]#

Bases: RenderableError

Raised when attempting to perform certain operations meant for animated renderables on a non-animated renderable.

exception term_image.renderable.UnassociatedNamespaceError[source]#

Bases: RenderArgsDataError

Raised when certain operations are attempted on a render argument/data namespace class that hasn’t been associated [3] [6] with a render class.

exception term_image.renderable.UninitializedDataFieldError[source]#

Bases: RenderDataError, AttributeError

Raised when an attempt is made to access a render data field that hasn’t been initialized i.e for which a value hasn’t been set.

exception term_image.renderable.UnknownArgsFieldError[source]#

Bases: RenderArgsError, AttributeError

Raised when an attempt is made to access or modify an unknown render argument field.

exception term_image.renderable.UnknownDataFieldError[source]#

Bases: RenderDataError, AttributeError

Raised when an attempt is made to access or modify an unknown render data field.


Type Variables and Aliases#
term_image.renderable.OptionalPaddingT = TypeVar(OptionalPaddingT, bound=term_image.padding.Padding | None)#

Invariant TypeVar bound to typing.Optional[term_image.padding.Padding].


Extension API#

Note

The following interfaces are provided and required only to extend the Renderable API i.e to create custom renderables or extend any of those provided by this library.

Everything required for normal usage should typically be exposed in the public API.

For performance reasons, all implementations of these interfaces within this library perform no form of argument validation, except stated otherwise. The same should apply to any extension or override of these interfaces. All arguments are and should be expected to be valid. Hence, arguments should be validated beforehand if necessary.

In the same vein, return values of any of these interfaces will not be validated by the callers before use.

Renderable#
class term_image.renderable.Renderable[source]

See Renderable for the public API.

Classes:

Attributes:

_EXPORTED_ATTRS_

Exported attributes.

_EXPORTED_DESCENDANT_ATTRS_

Exported descendant attributes.

Instance Methods:

_animate_

Animates frames of a renderable.

_clear_frame_

Clears the previous frame of an animation, if necessary.

_get_frame_count_

Implements POSTPONED frame count evaluation.

_get_render_data_

Generates data required for rendering that's based on internal or external state.

_handle_interrupted_draw_

Performs any special handling necessary when an interruption occurs while writing a render output to a stream.

_init_render_

Initiates a render operation.

_render_

Renders a frame.

Class Methods:

_finalize_render_data_

Finalizes render data.

_Data_: ClassVar[type[DataNamespace] | None]#

Render class-specific render data.

This is either:

  • a render data namespace class (subclass of DataNamespace) associated [6] with the render class, or

  • None, if the render class has no render data.

If this is a class, an instance of it (or a subclass thereof) is contained within any RenderData instance associated [5] with the render class or any of its subclasses. Also, an instance of this class (or a subclass of it) is returned by render_data[render_cls]; where render_data is an instance of RenderData as previously described and render_cls is the render class with which this namespace class is associated [6].

None
>>> class Foo(Renderable):
...     pass
...
... class _Data_(DataNamespace, render_cls=Foo):
...     foo: str | None
...
>>> Foo._Data_ is FooData
True
>>>
>>> foo_data = Foo._Data_()
>>> foo_data
<FooData: foo=<uninitialized>>
>>> foo_data.foo
Traceback (most recent call last):
  ...
UninitializedDataFieldError: The render data field 'foo' of 'Foo' has not been initialized
>>>
>>> foo_data.foo = "FOO"
>>> foo_data
<FooData: foo='FOO'>
>>> foo_data.foo
'FOO'
>>>
>>> render_data = RenderData(Foo)
>>> render_data[Foo]
<FooData: foo=<uninitialized>>
>>>
>>> render_data[Foo].foo = "bar"
>>> render_data[Foo]
<FooData: foo='bar'>

On the other hand, if this is None, it implies the render class has no render data.

None
>>> class Bar(Renderable):
...     pass
...
>>> Bar._Data_ is None
True
>>>
>>> render_data = RenderData(Bar)
>>> render_data[Bar]
Traceback (most recent call last):
  ...
NoDataNamespaceError: 'Bar' has no render data

See also

RenderableData

Render data for Renderable.

_EXPORTED_ATTRS_: ClassVar[tuple[str, ...]]#

Exported attributes.

This specifies class attributes defined by the class (not a parent) on itself but not its subclasses which should be exported to definitions of the class in subprocesses.

These attributes are typically assigned using __class__.* within methods.

Note

  • Defining this is optional.

  • The attributes are exported for a class if and only if they are defined on that class when starting a subprocess.

  • The attributes are exported only for subprocesses started via multiprocessing.Process.

Tip

This can be used to export “private” attributes of the class across subprocesses.

_EXPORTED_DESCENDANT_ATTRS_: ClassVar[tuple[str, ...]]#

Exported descendant attributes.

This specifies class attributes defined by the class (not a parent) on itself and its subclasses (i.e descendant attributes) which should be exported to definitions of the class and its subclasses in subprocesses.

These attributes are typically assigned using cls.* within class methods.

This extends the exported descendant attributes of parent classes i.e all exported descendant attributes of a class are also exported for its subclasses.

Note

  • Defining this is optional.

  • The attributes are exported for a class if and only if they are defined on that class when starting a subprocess.

  • The attributes are exported only for subprocesses started via multiprocessing.Process.

Tip

This can be used to export “private” descendant attributes of the class across subprocesses.

_animate_(render_data, render_args, padding, loops, cache, output)[source]#

Animates frames of a renderable.

Parameters:
  • render_data (RenderData) – Render data.

  • render_args (RenderArgs) – Render arguments associated with the renderable’s class.

  • output (TextIO) – The text I/O stream to which rendered frames will be written.

All other parameters are the same as for draw(), except that padding must have absolute dimensions if it’s an instance of AlignedPadding.

This is called by draw() for animations.

Note

  • The base implementation does not finalize render_data.

  • Render size validation is expected to have been performed by the caller.

  • When called by draw() (at least, the base implementation), loops and cache wouldn’t have been validated.

_clear_frame_(render_data, render_args, cursor_x, output)[source]#

Clears the previous frame of an animation, if necessary.

Parameters:
  • render_data (RenderData) – Render data.

  • render_args (RenderArgs) – Render arguments.

  • cursor_x (int) –

    Column/horizontal position of the cursor at the point of calling this method.

    Note

    The position is 1-based i.e the leftmost column on the screen is at position 1 (one).

  • output (TextIO) – The text I/O stream to which frames of the animation are being written.

Called by the base implementation of _animate_() just before drawing the next frame of an animation.

Upon calling this method, the cursor should be positioned at the top-left-most cell of the region occupied by the frame render output on the terminal screen.

Upon return, ensure the cursor is at the same position it was at the point of calling this method (at least logically, since output shouldn’t be flushed yet).

The base implementation does nothing.

Note

  • This is required only if drawing the next frame doesn’t inherently overwrite the previous frame.

  • This is only meant (and should only be used) as a last resort since clearing the previous frame before drawing the next may result in visible flicker.

  • Ensure whatever this method does doesn’t result in the screen being scrolled.

Tip

To reduce flicker, it’s advisable to not flush output. It will be flushed after writing the next frame.

classmethod _finalize_render_data_(render_data)[source]#

Finalizes render data.

Parameters:

render_data (RenderData) – Render data.

Typically, an overriding method should

  • finalize the data generated by _get_render_data_() of the same class, if necessary,

  • call the overridden method, passing on render_data.

Note

  • It’s recommended to call RenderData.finalize() instead as that assures a single invocation of this method.

  • Any definition of this method should be safe for multiple invocations on the same RenderData instance, just in case.

See also

_get_render_data_(), RenderData.finalize(), the finalize parameter of _init_render_().

_get_frame_count_()[source]#

Implements POSTPONED frame count evaluation.

Returns:

The frame count of the renderable. See frame_count.

Note

Returning POSTPONED or 1 (one) is invalid and may result in unexpected/undefined behaviour across various interfaces defined by this library (and those derived from them), since re-postponing evaluation is unsupported and the renderable would have been taken to be animated.

Return type:

int | Literal[FrameCount.INDEFINITE]

The base implementation raises NotImplementedError.

_get_render_data_(*, iteration)[source]#

Generates data required for rendering that’s based on internal or external state.

Parameters:

iteration (bool) – Whether the render operation requiring the data involves a sequence of renders (most likely of different frames), or it’s a one-off render.

Returns:

The generated render data.

Return type:

RenderData

The render data should include copies of any variable/mutable internal/external state required for rendering and other data generated from constant state but which should persist throughout a render operation (which may involve consecutive/repeated renders of one or more frames).

May also be used to “allocate” and initialize storage for mutable/variable data specific to a render operation.

Typically, an overriding method should

Important

The RenderData instance returned must be associated [5] with the type of the renderable on which this method is called i.e type(self). This is always the case for the base implementation of this method.

Note

This method being called doesn’t mean the data generated will be used immediately.

abstract _get_render_size_()[source]#

Returns the renderable’s render size.

Returns:

The size of the renderable’s render output.

Return type:

Size

The base implementation raises NotImplementedError.

Note

Both dimensions are expected to be positive.

See also

render_size

_handle_interrupted_draw_(render_data, render_args, output)[source]#

Performs any special handling necessary when an interruption occurs while writing a render output to a stream.

Parameters:
  • render_data (RenderData) – Render data.

  • render_args (RenderArgs) – Render arguments.

  • output (TextIO) – The text I/O stream to which the render output was being written.

Called by the base implementations of draw() (for non-animations) and _animate_() when KeyboardInterrupt is raised while writing a render output.

The base implementation does nothing.

Note

output should be flushed by this method.

Hint

For a renderable that uses SGR sequences in its render output, this method may write CSI 0 m to output.

_init_render_(renderer, render_args=None, padding=None, *, iteration=False, finalize=True, check_size=False, allow_scroll=False)[source]#

Initiates a render operation.

Parameters:
  • renderer (Callable[[RenderData, RenderArgs], T]) – Performs a render operation or extracts render data and arguments for a render operation to be performed later on.

  • render_args (RenderArgs | None) – Render arguments.

  • padding (OptionalPaddingT) – Render output padding.

  • iteration (bool) – Whether the render operation involves a sequence of renders (most likely of different frames), or it’s a one-off render.

  • finalize (bool) – Whether to finalize the render data passed to renderer immediately renderer returns.

  • check_size (bool) – Whether to validate the [padded] render size of non-animations.

  • allow_scroll (bool) – Whether to validate the [padded] render height of non-animations. Ignored if check_size is False.

Returns:

A tuple containing

  • The return value of renderer.

  • padding (with equivalent absolute dimensions if it’s an instance of AlignedPadding).

Raises:
Return type:

tuple[T, OptionalPaddingT]

After preparing render data and processing arguments, renderer is called with the following positional arguments:

  1. Render data associated with the renderable’s class

  2. Render arguments associated with the renderable’s class and initialized with render_args

Any exception raised by renderer is propagated.

Important

Beyond this method (i.e any context from renderer onwards), use of any variable state (internal or external) should be avoided if possible. Any variable state (internal or external) required for rendering should be provided via _get_render_data_().

If at all any variable state has to be used and is not reasonable/practicable to be provided via _get_render_data_(), it should be read only once during a single render and passed to any nested/subsequent calls that require the value of that state during the same render.

This is to prevent inconsistency in data used for the same render which may result in unexpected output.

abstract _render_(render_data, render_args)[source]#

Renders a frame.

Parameters:
Returns:

The rendered frame.

  • The render_size field = render_data[Renderable].size.

  • The render_output field holds the render output. This string should:

    • contain as many lines as render_size.height i.e exactly render_size.height - 1 occurrences of \n (the newline sequence).

    • occupy exactly render_size.height lines and render_size.width columns on each line when drawn onto a terminal screen, at least when the render size it not greater than the terminal size on either axis.

      Tip

      If for any reason, the output behaves differently when the render height is greater than the terminal height, the behaviour, along with any possible alternatives or workarounds, should be duely noted. This doesn’t apply to the width.

    • not end with \n (the newline sequence).

  • As for the duration field, if the renderable is:

Raises:
Return type:

Frame

Note

StopIteration may be raised if and only if render_data[Renderable].iteration is True. Otherwise, it would be out of place.

See also

RenderableData.


ArgsNamespace#
class term_image.renderable.ArgsNamespace[source]

See ArgsNamespace for the public API.

Defining Fields#

Fields are defined as annotated class attributes. All annotated attributes of a subclass are taken to be fields. Every such attribute must be assigned a value which is taken to be the default value of the field.

None
>>> class Foo(Renderable):
...     pass
...
>>> class FooArgs(ArgsNamespace, render_cls=Foo):
...     foo: str = "FOO"
...     bar: str = "BAR"
...
>>> FooArgs.get_fields()
mappingproxy({'foo': 'FOO', 'bar': 'BAR'})

The attribute annotations are only used to identify the fields, they’re never evaluated or used otherwise by any part of the Renderable API. The field names will be unbound from their assigned values (the default field values) during the creation of the class.

Note

A subclass that inherits fields must not define fields.

Associating With a Render Class#

To associate a namespace class with a render class, the render class should be specified via the render_cls keyword argument in the class definition header.

None
>>> class Foo(Renderable):
...     pass
...
>>> class FooArgs(ArgsNamespace, render_cls=Foo):
...     foo: str = "FOO"
...
>>> FooArgs.get_render_cls() is Foo
True

Note

  • A subclass that has fields must be associated [3] with a render class.

  • A subclass that has NO fields cannot be associated with a render class.

  • A subclass that inherits fields cannot be reassociated with another render class.

Attention

Due to the design of the Renderable API, if a render class is intended to have a namespace class asssociated, the namespace class should be associated with it before it is subclassed or any RenderArgs instance associated with it is created.

Inheriting Fields#

Fields are inherited from any associated [3] render argument namespace class (i.e anyone that has fields) by subclassing it. The new subclass inherits both the fields and associated render class of its parent.

None
>>> class Foo(Renderable):
...     pass
...
>>> class FooArgs(ArgsNamespace, render_cls=Foo):
...     foo: str = "FOO"
...
>>> FooArgs.get_render_cls() is Foo
True
>>> FooArgs.get_fields()
mappingproxy({'foo': 'FOO'})
>>>
>>> class SubFooArgs(FooArgs):
...     pass
...
>>> SubFooArgs.get_render_cls() is Foo
True
>>> SubFooArgs.get_fields()
mappingproxy({'foo': 'FOO'})

Note

A subclass that inherits fields:

  • must not define fields.

  • cannot be reassociated with another render class.

Other Notes#

Note

  • A subclass cannot have multiple base classes.

  • The constructor of any subclass that has fields must not have required parameters.

Tip

A subclass may neither define nor inherit fields. Such can be used as a base class for other namespace classes.

Important

Due to the design and implementation of the API, field values (including defaults) should:

  • (and are expected to) be immutable.

    Otherwise, such may yield unexpected behaviour during render operations or unexpected render outputs, if an object used as a field value is modified, as:

    • a namespace containing a mutable field value (or a set of render arguments containing such a namespace) may be in use in an asynchronous render operation,

    • different sets of render arguments may contain the same namespace, and

    • different namespaces may contain the same object as field values.

  • be hashable.

    Otherwise, the namespace and any containing set of render arguments will also not be hashable.


Other Classes#

RenderData

Render data.

DataNamespace

Render class-specific render data namespace.

RenderableData

Render data namespace for Renderable.

class term_image.renderable.RenderData(render_cls)[source]#

Bases: RenderArgsData

Render data.

Parameters:

render_cls (type[Renderable]) – A render class.

An instance of this class is basically a container of render data namespaces (instances of DataNamespace); one for each render class, which has render data, in the Method Resolution Order of its associated [5] render class.

Note

  • Instances are immutable but the constituent namespaces are mutable.

  • Instances and their contents shouldn’t be copied by any means because finalizing an instance may invalidate all other copies.

  • Instances should always be explicitly finalized as soon as they’re no longer needed.

See also

_Data_

Render class-specific render data.

Footnotes

Attributes:

render_cls

The associated render class

finalized

Finalization status

Special Methods:

__getitem__

Returns a constituent namespace.

__iter__

Returns an iterator that yields the constituent namespaces.

Instance Methods:

finalize

Finalizes the render data.

render_cls: type[Renderable]#

The associated render class

finalized: bool#

Finalization status

self[render_cls][source]#

Returns a constituent namespace.

Parameters:

render_cls (type[Renderable]) – A render class of which render_cls is a subclass (which may be render_cls itself) and which has render data.

Returns:

The constituent namespace associated with render_cls.

Raises:
Return type:

Any

Note

The return type hint is Any only for compatibility with static type checking, as this aspect of the interface seems too dynamic to be correctly expressed with the exisiting type system.

Regardless, the return value is guaranteed to always be an instance of a render data namespace class associated with render_cls. For instance, the following would always be valid for Renderable:

renderable_data: RenderableData = render_data[Renderable]

and similar idioms are encouraged to be used for other render classes.

iter(self)[source]#

Returns an iterator that yields the constituent namespaces.

Returns:

An iterator that yields the constituent namespaces.

Return type:

Iterator[DataNamespace]

Warning

The number and order of namespaces is guaranteed to be the same across all instances associated [5] with the same render class but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Renderable API and the number should be considered alike with respect to the associated render class.

finalize()[source]#

Finalizes the render data.

Calls _finalize_render_data_() of render_cls.

Note

This method is safe for multiple invocations on the same instance.


class term_image.renderable.DataNamespace[source]#

Bases: ArgsDataNamespace

Render class-specific render data namespace.

Raises:

UnassociatedNamespaceError – The namespace class hasn’t been associated [6] with a render class.

Subclassing, defining (and inheriting) fields and associating with a render class are just as they are for ArgsNamespace, except that values assigned to class attributes are neither required nor used.

Every field of a namespace is uninitialized immediately after instantiation. The fields are expected to be initialized within the _get_render_data_() method of the render class with which the namespace is associated [6] or at some other point during a render operation, if necessary.

Note

  • Fields are exposed as instance attributes.

  • Instances are mutable and fields can be updated in-place, either individually by assignment to an attribute reference or in batch via update().

  • An instance shouldn’t be copied by any means because finalizing its containing RenderData instance may invalidate all copies of the namespace.

Footnotes

Instance Methods:

as_dict

Copies the namespace as a dictionary.

update

Updates render data fields.

Class Methods:

get_fields

Returns the field names.

get_render_cls

Returns the associated render class.

as_dict()[source]#

Copies the namespace as a dictionary.

Returns:

A dictionary mapping field names to their current values.

Raises:

UninitializedDataFieldError – A field has not been initialized.

Return type:

dict[str, Any]

Warning

The number and order of fields are guaranteed to be the same for a namespace class that defines fields, its subclasses, and all their instances; but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Render Arguments/Data API and the number should be considered an implementation detail of the specific namespace subclass.

classmethod get_fields()[source]#

Returns the field names.

Returns:

A tuple of field names.

Return type:

tuple[str, …]

Warning

The number and order of fields are guaranteed to be the same for a namespace class that defines fields, its subclasses, and all their instances; but beyond this, should not be relied upon as the details (such as the specific number or order) may change without notice.

The order is an implementation detail of the Render Arguments/Data API and the number should be considered an implementation detail of the specific namespace subclass.

update(**fields)[source]#

Updates render data fields.

Parameters:

fields (Any) – Render data fields.

Raises:

UnknownDataFieldError – Unknown field name(s).

classmethod get_render_cls()#

Returns the associated render class.

Returns:

The associated render class, if the namespace class has been associated.

Raises:

UnassociatedNamespaceError – The namespace class hasn’t been associated with a render class.

Return type:

type[Renderable]


class term_image.renderable.RenderableData[source]#

Bases: DataNamespace

Render data namespace for Renderable.

See also

_Data_

Render class-specific render data.

_render_()

Renders a frame of a renderable.

Attributes:

size

Render size

frame_offset

Frame number/offset

seek_whence

Reference position for frame_offset

duration

Frame duration

iteration

Render operation kind

size: geometry.Size#

Render size

See _render_().

frame_offset: int#

Frame number/offset

If the frame_count of the renderable (that generated the data) is:

  • definite (i.e an integer); the value of this field is a non-negative integer less than the frame count, the number of the frame to be rendered.

  • INDEFINITE, the value range and interpretation of this field depends on the value of iteration and seek_whence.

    If iteration is False, the value is always zero and anything (such as a placeholder frame) may be rendered, as renderables with INDEFINITE frame count are typically meant for iteration/animation.

    If iteration is True and seek_whence is:

    • CURRENT, the value of this field may be:

      • zero, denoting that the next frame on the stream should be rendered.

      • positive, denoting that the stream should be seeked forward by frame_offset frames and then the new next frame should be rendered.

      • negative, denoting that the stream should be seeked backward by -frame_offset frames and then the new next frame should be rendered.

    • START, the value of this field may be:

      • zero, denoting that the stream should be seeked to its beginning and then the first frame should be rendered.

      • positive, denoting that the stream should be seeked to the (frame_offset)th frame after the first and then the new next frame should be rendered.

    • END, the value of this field may be:

      • zero, denoting that the stream should be seeked to its end and then the last frame should be rendered.

      • negative, denoting that the stream should be seeked to the (-frame_offset)th frame before the last and then the new next frame should be rendered.

      If the end of the stream cannot be determined (yet), such as with a live source, the furthest available frame in the forward direction should be taken to be the end.

    Note

    • If any seek operation is not supported by the underlying source, it should be ignored and the next frame on the stream should be rendered.

    • If forward seek is supported but the offset is out of the range of available frames, the stream should be seeked to the furthest available frame in the forward direction if its end cannot be determined (yet), such as with a live source. Otherwise i.e if the offset is determined to be beyond the end of the stream, StopIteration should be raised (see _render_()).

    • If backward seek is supported but the offset is out of the range of available frames, the stream should be seeked to its beginning or the furthest available frame in the backward direction.

    Tip

    A render class that implements INDEFINITE frame count should specify which seek operations it supports and any necessary details.

seek_whence: Seek#

Reference position for frame_offset

If the frame_count of the renderable (that generated the data) is definite, or INDEFINITE but iteration is False; the value of this field is always START. Otherwise i.e if frame_count is INDEFINITE and iteration is True, it may be any member of Seek.

duration: int | FrameDuration#

Frame duration

The possible values and their respective interpretations are the same as for frame_duration. See _render_() for usage details.

Attention

This field is left uninitialized for render data generated by/for non-animated renderables.

iteration: bool#

Render operation kind

True if the render is part of a render operation involving a sequence of renders (most likely of different frames). Otherwise i.e if it’s a one-off render, False.

render Module#

Classes#

RenderIterator

An iterator for efficient iteration over rendered frames of an animated renderable.

class term_image.render.RenderIterator(renderable, render_args=None, padding=ExactPadding(left=0, top=0, right=0, bottom=0, fill=' '), loops=1, cache=100)[source]#

Bases: object

An iterator for efficient iteration over rendered frames of an animated renderable.

Parameters:
  • renderable (Renderable) – An animated renderable.

  • render_args (RenderArgs | None) – Render arguments.

  • padding (Padding) – Render output padding.

  • loops (int) –

    The number of times to go over all frames.

    • < 0 -> loop infinitely.

    • 0 -> invalid.

    • > 0 -> loop the given number of times.

    Note

    The value is ignored and taken to be 1 (one), if renderable has INDEFINITE frame count.

  • cache (bool | int) –

    Determines if rendered frames are cached.

    If the value is True or a positive integer greater than or equal to the frame count of renderable, caching is enabled. Otherwise i.e False or a positive integer less than the frame count, caching is disabled.

    Note

    The value is ignored and taken to be False, if renderable has INDEFINITE frame count.

Raises:

The iterator yields a Frame instance on every iteration.

Note

  • Seeking the underlying renderable (via Renderable.seek()) does not affect an iterator, use RenderIterator.seek() instead. Likewise, the iterator does not modify the underlying renderable’s current frame number.

  • Changes to the underlying renderable’s render size does not affect an iterator’s render outputs, use set_render_size() instead.

  • Changes to the underlying renderable’s frame_duration does not affect the value yiedled by an iterator, the value when initializing the iterator is what it will use.

See also

Renderable.__iter__()

Renderables are iterable

RenderIterator

RenderIterator‘s Extension API

Attributes:

loop

Iteration loop countdown

Instance Methods:

close

Finalizes the iterator and releases resources used.

seek

Sets the frame to be rendered on the next iteration, without affecting the loop count.

set_frame_duration

Sets the frame duration.

set_padding

Sets the render output padding.

set_render_args

Sets the render arguments.

set_render_size

Sets the render size.

loop: int#

Iteration loop countdown

  • A negative integer, if iteration is infinite.

  • Otherwise, the current iteration loop countdown value.

    • Starts from the value of the loops constructor argument,

    • decreases by one upon rendering the first frame of every loop after the first,

    • and ends at zero after the iterator is exhausted.

Note

Modifying this doesn’t affect the iterator.

close()[source]#

Finalizes the iterator and releases resources used.

Note

This method is automatically called when the iterator is exhausted or garbage-collected but it’s recommended to call it manually if iteration is ended prematurely (i.e before the iterator itself is exhausted), especially if frames are cached.

This method is safe for multiple invocations.

seek(offset, whence=Seek.START)[source]#

Sets the frame to be rendered on the next iteration, without affecting the loop count.

Parameters:
  • offset (int) – Frame offset (relative to whence).

  • whence (Seek) – Reference position for offset.

Raises:

The value range for offset depends on the frame_count of the underlying renderable and whence:

definite frame count#

whence

Valid value range for offset

START

0 <= offset < frame_count

CURRENT

-next_frame_number [1] <= offset < frame_count - next_frame_number

END

-frame_count < offset <= 0

INDEFINITE frame count#

whence

Valid value range for offset

START

0 <= offset

CURRENT

any value

END

offset <= 0

Note

If the underlying renderable has definite frame count, seek operations have immeditate effect. Hence, multiple consecutive seek operations, starting with any kind and followed by one or more with whence = CURRENT, between any two consecutive renders have a cumulative effect. In particular, any seek operation with whence = CURRENT is relative to the frame to be rendered next [1].

None
>>> animated_renderable.frame_count
10
>>> render_iter = RenderIterator(animated_renderable)  # next = 0
>>> render_iter.seek(5)  # next = 5
>>> next(render_iter).number  # next = 5 + 1 = 6
5
>>> # cumulative
>>> render_iter.seek(2, Seek.CURRENT)  # next = 6 + 2 = 8
>>> render_iter.seek(-4, Seek.CURRENT)  # next = 8 - 4 = 4
>>> next(render_iter).number  # next = 4 + 1 = 5
4
>>> # cumulative
>>> render_iter.seek(7)  # next = 7
>>> render_iter.seek(1, Seek.CURRENT)  # next = 7 + 1 = 8
>>> render_iter.seek(-5, Seek.CURRENT)  # next = 8 - 5 = 3
>>> next(render_iter).number  # next = 3 + 1 = 4
3
>>> # NOT cumulative
>>> render_iter.seek(3, Seek.CURRENT)  # next = 4 + 3 = 7
>>> render_iter.seek(2)  # next = 2
>>> next(render_iter).number  # next = 2 + 1 = 3
2

On the other hand, if the underlying renderable has INDEFINITE frame count, seek operations don’t take effect until the next render. Hence, multiple consecutive seek operations between any two consecutive renders do not have a cumulative effect; rather, only the last one takes effect. In particular, any seek operation with whence = CURRENT is relative to the frame after that which was rendered last.

None
>>> animated_renderable.frame_count is FrameCount.INDEFINITE
True
>>> # iterating normally without seeking
>>> [frame.render_output for frame in animated_renderable]
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', ...]
>>>
>>> # Assuming the renderable implements all kinds of seek operations
>>> render_iter = RenderIterator(animated_renderable)  # next = 0
>>> render_iter.seek(5)  # next = 5
>>> next(render_iter).render_output  # next = 5 + 1 = 6
'5'
>>> render_iter.seek(2, Seek.CURRENT)  # next = 6 + 2 = 8
>>> render_iter.seek(-4, Seek.CURRENT)  # next = 6 - 4 = 2
>>> next(render_iter).render_output  # next = 2 + 1 = 3
'2'
>>> render_iter.seek(7)  # next = 7
>>> render_iter.seek(3, Seek.CURRENT)  # next = 3 + 3 = 6
>>> next(render_iter).render_output  # next = 6 + 1 = 7
'6'

A renderable with INDEFINITE frame count may not support/implement all kinds of seek operations or any at all. If the underlying renderable doesn’t support/implement a given seek operation, the seek operation should simply have no effect on iteration i.e the next frame should be the one after that which was rendered last. See each render class that implements INDEFINITE frame count for the seek operations it supports and any other specific related details.

set_frame_duration(duration)[source]#

Sets the frame duration.

Parameters:

duration (int | FrameDuration) – Frame duration (see frame_duration).

Raises:

Note

Takes effect from the next [1] rendered frame.

set_padding(padding)[source]#

Sets the render output padding.

Parameters:

padding (Padding) – Render output padding.

Raises:

FinalizedIteratorError – The iterator has been finalized.

Note

Takes effect from the next [1] rendered frame.

set_render_args(render_args)[source]#

Sets the render arguments.

Parameters:

render_args (RenderArgs) – Render arguments.

Raises:

Note

Takes effect from the next [1] rendered frame.

set_render_size(render_size)[source]#

Sets the render size.

Parameters:

render_size (Size) – Render size.

Raises:

FinalizedIteratorError – The iterator has been finalized.

Note

Takes effect from the next [1] rendered frame.


Exceptions#

RenderIteratorError

Base exception class for errors specific to RenderIterator.

FinalizedIteratorError

Raised if certain operations are attempted on a finalized iterator.

exception term_image.render.RenderIteratorError[source]#

Bases: TermImageError

Base exception class for errors specific to RenderIterator.

exception term_image.render.FinalizedIteratorError[source]#

Bases: RenderIteratorError

Raised if certain operations are attempted on a finalized iterator.


Extension API#

Note

The following definitions are provided and required only for extended use of the interfaces defined above.

Everything required for normal usage should typically be exposed in the public API.

RenderIterator#
class term_image.render.RenderIterator[source]

See RenderIterator for the public API.

Class Methods:

_from_render_data_

Constructs an iterator with pre-generated render data.

classmethod _from_render_data_(renderable, render_data, render_args=None, padding=ExactPadding(left=0, top=0, right=0, bottom=0, fill=' '), *args, finalize=True, **kwargs)[source]#

Constructs an iterator with pre-generated render data.

Parameters:
  • renderable (Renderable) – An animated renderable.

  • render_data (RenderData) – Render data.

  • render_args (RenderArgs | None) – Render arguments.

  • args (Any) – Other positional arguments accepted by the class constructor.

  • finalize (bool) – Whether render_data is finalized along with the iterator.

  • kwargs (Any) – Other keyword arguments accepted by the class constructor.

Returns:

A new iterator instance.

Return type:

Self

Raises the same exceptions as the class constructor.

Note

render_data may be modified by the iterator or the underlying renderable.


Footnotes

utils Module#

Functions:

get_cell_size

Returns the current size of a character cell in the active terminal.

get_terminal_name_version

Returns the name and version of the active terminal, if available.

get_terminal_size

Returns the current size of the active terminal.

lock_tty

Synchronizes access to the active terminal.

read_tty_all

Reads all available input directly from the active terminal without blocking.

write_tty

Writes to the active terminal and waits until complete transmission.

term_image.utils.get_cell_size()[source]#

Returns the current size of a character cell in the active terminal.

Returns:

The cell size in pixels or None if undetermined.

Return type:

Size | None

The speed of this implementation is almost entirely dependent on the terminal; the method it supports and its response time if it has to be queried.

Note

Currently works on UNIX only, returns None on any other platform or when there is no active terminal.

term_image.utils.get_terminal_name_version()[source]#

Returns the name and version of the active terminal, if available.

Returns:

A 2-tuple, (name, version). If either is not available, returns None in its place.

Return type:

tuple[str | None, str | None]

term_image.utils.get_terminal_size()[source]#

Returns the current size of the active terminal.

Returns:

The terminal size in columns and lines.

Return type:

terminal_size

Note

This implementation is quite different from shutil.get_terminal_size() and os.get_terminal_size() in that it:

  • gives the correct size of the active terminal even when output is redirected, in most cases

  • gives different results in certain situations

  • is what this library works with

term_image.utils.lock_tty(func)[source]#

Synchronizes access to the active terminal.

Parameters:

func (Callable[[~P], T]) – The function to be wrapped.

When a decorated function is called, a re-entrant lock is acquired by the current process or thread and released after the call, such that any other decorated function called within another thread or subprocess waits until the lock is fully released (i.e has been released as many times as acquired) by the current process or thread.

Note

It works across parent-/sub-processes, started directly or indirectly via multiprocessing.Process (or a subclass of it), and their threads, provided multiprocessing.synchronize is supported on the host platform. Otherwise, a warning is issued when starting a subprocess.

Warning

If multiprocessing.synchronize is supported and a subprocess is started within a call (possibly recursive) to a decorated function, the thread in which that occurs will be out of sync until that call returns. Hence, avoid starting a subprocess within a decorated function.

term_image.utils.read_tty_all()[source]#

Reads all available input directly from the active terminal without blocking.

Returns:

The input read or None if not supported.

Return type:

bytes | None

Important

Synchronized with lock_tty().

Note

Currently works on UNIX only, returns None on any other platform or when there is no active terminal.

term_image.utils.write_tty(data)[source]#

Writes to the active terminal and waits until complete transmission.

Parameters:

data (bytes) – Data to be written.

Important

Synchronized with lock_tty().

Note

Currently works on UNIX only, returns None on any other platform or when there is no active terminal.

widget Module#

Classes:

UrwidImage

Image widget (box/flow) for the urwid TUI framework.

UrwidImageCanvas

Image canvas for the urwid TUI framework.

UrwidImageScreen

A screen that supports drawing images.

class term_image.widget.UrwidImage(image, format_spec='', *, upscale=False)[source]#

Bases: Widget

Image widget (box/flow) for the urwid TUI framework.

Parameters:
  • image (BaseImage) – The image to be rendered by the widget.

  • format_spec (str) – Render format specifier. Padding width and height are ignored.

  • upscale (bool) – If True, the image will be upscaled to fit maximally within the available size, if necessary, while still preserving the aspect ratio. Otherwise, the image is never upscaled.

Raises:
Any ample space in the widget’s render size is filled with spaces.
For animated images, the current frame (at render-time) is rendered.

Tip

If image is of a graphics-based render style and the widget is being used as or within a flow widget, with overlays or in any other case where the canvas will require vertical trimming, make sure to use a render method that splits images across lines such as the LINES render method for kitty and iterm2 render styles.

Note

  • The z-index style-specific format spec field for KittyImage is ignored as this is used internally.

  • A maximum of 2**32 - 2 instances initialized with KittyImage instances may exist at the same time.

Important

This is defined if and only if the urwid package is available.

Instance Properties:

image

The image rendered by the widget

Class Methods:

set_error_placeholder

Sets the widget to be rendered in place of an image when rendering fails.

property image#

The image rendered by the widget

Type:

BaseImage

GET:

Returns the image instance rendered by the widget.

classmethod set_error_placeholder(widget)[source]#

Sets the widget to be rendered in place of an image when rendering fails.

Parameters:

widget (Widget | None) – The placeholder widget or None to remove the placeholder.

Raises:

TypeErrorwidget is not an urwid widget.

If set, any exception raised during rendering is suppressed and the placeholder is rendered in place of the image.

class term_image.widget.UrwidImageCanvas(render, size, image_size)[source]#

Bases: Canvas

Image canvas for the urwid TUI framework.

Parameters:
  • render (str) – The rendered image.

  • size (Tuple[int, int]) – The canvas size. Also, the size of the rendered (and formatted) image.

  • image_size (Tuple[int, int]) – The size with which the image was rendered (excluding padding).

Note

The canvas outputs blanks (spaces) for graphics-based images when horizontal trimming is required (e.g when a widget is laid over an image). This is temporary as horizontal trimming will be implemented in the future.

This canvas is intended to be rendered by UrwidImage (or a subclass of it) only. Otherwise, the output isn’t guaranteed to be as expected.

Warning

The constructor of this class performs NO argument validation at all for the sake of performance. If instantiating this class directly, make sure to pass appropriate arguments or create subclass, override the constructor and perform the validation.

Important

This is defined if and only if the urwid package is available.

class term_image.widget.UrwidImageScreen(*args, **kwargs)[source]#

Bases: Screen

A screen that supports drawing images.

It monitors images of some graphics-based render styles and clears them off the screen when necessary (e.g at startup, when scrolling, upon terminal resize and at exit).

See the baseclass for further description.

Important

This is defined if and only if the urwid package is available.

Instance Methods:

clear_images

Clears on-screen images of graphics-based styles that support/require such an operation.

draw_screen

See the description of the baseclass' method.

flush

See the baseclass' method for the description.

get_available_raw_input

See the baseclass' method for the description.

write

See the baseclass' method for the description.

clear_images(*widgets, now=False)[source]#

Clears on-screen images of graphics-based styles that support/require such an operation.

Parameters:
  • widgets (UrwidImage) –

    Image widgets to clear.

    All on-screen images rendered by each of the widgets are cleared, provided the widget was initialized with a term_image.image.KittyImage instance.

    If none is given, all images (of styles that support/require such an operation) on-screen are cleared.

  • now (bool) – If True the images are cleared immediately. Otherwise, they’re cleared when next the output buffer is flushed, such as at the next screen redraw.

draw_screen(maxres, canvas)[source]#

See the description of the baseclass’ method.

Synchronizes output on terminal emulators that support the feature to reduce/eliminate image flickering and screen tearing.

Important

Synchronized with lock_tty().

flush()[source]#

See the baseclass’ method for the description.

Important

Synchronized with lock_tty().

get_available_raw_input()[source]#

See the baseclass’ method for the description.

Important

Synchronized with lock_tty().

write(data)[source]#

See the baseclass’ method for the description.

Important

Synchronized with lock_tty().

Known Issues#

  1. Drawing of images and animations doesn’t work completely well with Python for Windows (tested in Windows Terminal and MinTTY).

    • Description: Some lines of the image seem to extend beyond the number of columns that they should normally occupy by one or two columns.

      This behaviour causes animations to go bizarre when lines extend beyond the width of the terminal emulator.

    • Comment: First of all, the issue seems to be caused by the layer(s) between Python and the terminal emulators i.e the Windows Console APIs.

      It is neither a fault of this library nor of the terminal emulators, as drawing of images and animations works properly with WSL within Windows Terminal.

    • Solution: A workaround is to leave some columns between the right edge of the image and the right edge of the terminal.

  2. Animations with the kitty render style on the Kitty terminal emulator might be glitchy for some images with high resolution and size and/or sparse color distribution.

    • Description: When the LINES render method is used, lines of the image might intermittently disappear. When the WHOLE render method is used, the entire image might intermitently disappear.

    • Comment: This is due to the fact that drawing each frame requires clearing the previous frame off the screen, since the terminal would otherwise blend subsequent frames. Not clearing previous frames would break transparent animations and result in a performance lag that gets worse over time.

    • Solution: Plans are in motion to implement support for native animations i.e utilizing the animation features provided by the protocol (See #40).

FAQs#

Why?
  • Why not?

  • To improve and extend the capabilities of CLI and TUI applications.

  • Terminals emulators have always been and always will be!

What about Windows support?
  • Windows Terminal and Mintty (at least) have modern terminal emulator features including full Unicode and Truecolor support.

  • Drawing images and animations doesn’t work completely well with Python for Windows. See Known Issues.

  • Note that the graphics protocols supported by Mintty would only work for Cygwin, MSYS and Msys2 programs, or via WSL; not for native Windows programs.

Why are colours not properly reproduced?
  • Some terminal emulators support direct-color (truecolor) sequences but use a 256-color palette. This limits color reproduction.

Why are images out of scale?
Why does my program get garbage input (possibly also written to the screen) or phantom keystrokes?

Glossary#

Below are definitions of terms used across the API, exception messages and the documentation.

Note

For contributors, some of these terms are also used in the source code, as variable names, in comments, docstrings, etc.

active terminal#

The terminal emulator connected to the first TTY device discovered upon loading the term_image package.

At times, this may also be used to refer to the TTY device itself.

alignment#
horizontal alignment#
vertical alignment#

alpha threshold#

Alpha ratio/value above which a pixel is taken as opaque (applies only to Text-based Render Styles).

See also

Transparency

animated#

Having multiple frames.

The frames of an animated image are generally meant to be displayed in rapid succession, to give the effect of animation.

automatic size#
automatic sizing#

A form of sizing wherein an image’s size is computed based on a combination of a frame size, the image’s original size and a given width or height.

This form of sizing tries to preserve image aspect ratio and can be used with both fixed sizing and dynamic sizing.

cell ratio#

The aspect ratio (i.e the ratio of width to height) of a character cell on a terminal screen.

descendant#

Refers to an attribute, property or setting set on a class which applies to that class and all its subclasses on which the attribute, property or setting is unset.

dynamic size#
dynamic sizing#

A form of sizing wherein the image size is automatically computed at render-time.

This only works with automatic sizing.

See also

fixed sizing and size

fixed size#
fixed sizing#

A form of sizing wherein the image size is set to a specific value which won’t change until it is re-set.

This works with both manual sizing and automatic sizing.

frame height#

The height of the area used in automatic sizing.

frame size#

The dimensions of the area used in automatic sizing.

frame width#

The width of the area used in automatic sizing.

manual size#
manual sizing#

A form of sizing wherein both the width and the height are specified to set the image size.

This form of sizing does not preserve image aspect ratio and can only be used with fixed sizing.

padding#
padding size#
padding width#
padding height#

pixel ratio#

The aspect ratio with which one rendered pixel is drawn/displayed on the terminal screen.

For Graphics-based Render Styles, this is ideally 1.0.

For Text-based Render Styles, this is equivalent to the cell ratio multiplied by 2, since there are technically two times more pixels along the vertical axis than along the horizontal axis in one character cell.

render#
renders#
rendered#
rendering#

The process of encoding visual/textual data into a byte/character string (possibly including terminal control sequences), the result of which is called a render output.

See also

_render_()

render class#
render classes#

Renderable or a subclass of it.

render height#
rendered height#

The amount of lines that’ll be occupied by a render output when drawn (written) onto a terminal screen. Also the vertical component of a render size.

render method#
render methods#

A unique implementation of a render style.

See also

Render Methods

render output#
render outputs#

A string produced by rendering or by padding another render output.

render size#
rendered size#

The amount of space (columns and lines) that’ll be occupied by a render output when drawn (written) onto a terminal screen.

render style#
render styles#
style#
styles#

A specific technique for rendering or displaying pixel data (including images) in a terminal emulator.

A render style (or simply style) is implemented by a class, often referred to as a render style class (or simply style class).

See also

Render Styles

render width#
rendered width#

The amount of columns that’ll be occupied by a render output when drawn (written) onto a terminal screen. Also the horizontal component of a render size.

source#

The resource from which an image instance is initialized.

See also

source and source_type

terminal height#

The amount of lines on a terminal screen at a time i.e without scrolling.

terminal size#

The amount of columns and lines on a terminal screen at a time i.e without scrolling.

terminal width#

The amount of columns on a terminal screen at a time.

Indices and Tables#