🚧 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).
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:
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.
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.
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().
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.
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 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:
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.
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 widthor the
heightkeyword-only parameter.
For whichever axis a dimension is given, the dimension on the other axis is calculated
proportionally.
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.height28>>> image.height=68>>> image.size(136, 68)>>> image.width136>>> # 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.
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.
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.
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 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.
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:
Clear all unread input from the terminal
Write to the terminal
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:
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.
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.
# → 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.
🚧 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.
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.
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.
AutoCellRatio.DYNAMIC, the ratio is determined from the
active terminal whenever get_cell_ratio() is called,
though with some caching involved, such that the ratio is re-determined
only if the terminal size changes.
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.
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.
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.
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.
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.
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.
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).
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.
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.
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.
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.
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 WHOLErender method
are always re-encoded, disable read_from_file.
This optimization is useful in improving non-native animation performance.
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.
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.
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.
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.
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.
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.
BaseImage instances are context managers i.e they can be used with the with statement as in:
withfrom_url(url)asimage:...
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()).
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.
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.
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:
In words… If the absoluteminimum 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 relativeminimum
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.
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].
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().
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:
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.
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.
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.
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.
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.
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.
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.
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.
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
>>> classFoo(Renderable):... pass...... class_Data_(DataNamespace,render_cls=Foo):... foo:str|None...>>> Foo._Data_isFooDataTrue>>>>>> foo_data=Foo._Data_()>>> foo_data<FooData: foo=<uninitialized>>>>> foo_data.fooTraceback (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
>>> classBar(Renderable):... pass...>>> Bar._Data_isNoneTrue>>>>>> render_data=RenderData(Bar)>>> render_data[Bar]Traceback (most recent call last):...NoDataNamespaceError: 'Bar' has no render data
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.
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.
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.
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.
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.
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
call the overridden method,
update the namespace for its defining class (i.e
render_data[__class__]) within the
RenderData instance returned by the
overridden method,
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.
renderer (Callable[[RenderData, RenderArgs], T]) – Performs a render operation or extracts render data and arguments
for a render operation to be performed later on.
After preparing render data and processing arguments, renderer is called with
the following positional arguments:
Render data associated with the renderable’s class
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.
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.
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.
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.
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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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
frame_duration does not affect
the value yiedled by an iterator, the value when initializing the iterator
is what it will use.
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.
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_count10>>> render_iter=RenderIterator(animated_renderable)# next = 0>>> render_iter.seek(5)# next = 5>>> next(render_iter).number# next = 5 + 1 = 65>>> # 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 = 54>>> # 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 = 43>>> # 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 = 32
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_countisFrameCount.INDEFINITETrue>>> # iterating normally without seeking>>> [frame.render_outputforframeinanimated_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.
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.
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:
TypeError – An argument is of an inappropriate type.
ValueError – An argument is of an appropriate type but has an
unexpected/invalid value.
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.
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.
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.
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.
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.
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).
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.
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.
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.
The amount of columns that’ll be occupied by a render outputwhen drawn (written) onto a terminal screen. Also the horizontal component of a render size.