"""
term-image
Display images in the terminal
Copyright (c) 2022, Toluwaleke Ogundipe <anonymoux47@gmail.com>
"""
from __future__ import annotations
__all__ = (
"DEFAULT_QUERY_TIMEOUT",
"AutoCellRatio",
"disable_queries",
"disable_win_size_swap",
"enable_queries",
"enable_win_size_swap",
"get_cell_ratio",
"set_cell_ratio",
"set_query_timeout",
)
__author__ = "Toluwaleke Ogundipe"
from enum import Enum, auto
from operator import truediv
from typing_extensions import ClassVar, Final
from . import utils
from .exceptions import TermImageError
from .utils import arg_value_error_range, get_cell_size
version_info = (0, 8, 0, "dev")
# Follows https://semver.org/spec/v2.0.0.html
__version__ = ".".join(map(str, version_info[:3]))
if version_info[3:]:
__version__ += "-" + ".".join(map(str, version_info[3:]))
DEFAULT_QUERY_TIMEOUT: Final[float] = utils._query_timeout
"""Default timeout for :ref:`terminal-queries`
.. seealso:: :py:func:`set_query_timeout`.
"""
[docs]
class AutoCellRatio(Enum):
""":ref:`auto-cell-ratio` enumeration and support status.
.. seealso:: :py:func:`set_cell_ratio`.
"""
FIXED = auto()
"""Fixed cell ratio.
:meta hide-value:
"""
DYNAMIC = auto()
"""Dynamic cell ratio.
:meta hide-value:
"""
is_supported: ClassVar[bool | None]
"""Auto cell ratio support status. Can be
:meta hide-value:
- ``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 :ref:`queried <terminal-queries>`
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.
"""
[docs]
def disable_queries() -> None:
"""Disables :ref:`terminal-queries`.
To re-enable queries, call :py:func:`enable_queries`.
NOTE:
This affects all :ref:`dependent features <queried-features>`.
"""
utils._queries_enabled = False
[docs]
def disable_win_size_swap() -> None:
"""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 :term:`active terminal` are used as-is.
NOTE:
This affects :ref:`auto-cell-ratio` computation and size computations for
:ref:`graphics-based`.
"""
if utils._swap_win_size:
utils._swap_win_size = False
with utils._cell_size_lock:
utils._cell_size_cache[:] = (0,) * 4
[docs]
def enable_queries() -> None:
"""Re-Enables :ref:`terminal-queries`.
Queries are enabled by default. To disable, call :py:func:`disable_queries`.
NOTE:
This affects all :ref:`dependent features <queried-features>`.
"""
if not utils._queries_enabled:
utils._queries_enabled = True
getattr(utils.get_fg_bg_colors, "_invalidate_cache")()
getattr(utils.get_terminal_name_version, "_invalidate_cache")()
with utils._cell_size_lock:
utils._cell_size_cache[:] = (0,) * 4
[docs]
def enable_win_size_swap() -> None:
"""Enables a workaround for terminal emulators that wrongly report window
dimensions swapped.
While enabled, the window dimensions reported by the :term:`active terminal` are
swapped. This workaround is required on some older VTE-based terminal emulators.
NOTE:
This affects :ref:`auto-cell-ratio` computation and size computations for
:ref:`graphics-based`.
"""
if not utils._swap_win_size:
utils._swap_win_size = True
with utils._cell_size_lock:
utils._cell_size_cache[:] = (0,) * 4
[docs]
def get_cell_ratio() -> float:
"""Returns the global :term:`cell ratio`.
.. seealso:: :py:func:`set_cell_ratio`.
"""
# `(1, 2)` is a fallback in case the terminal doesn't respond in time
return _cell_ratio or truediv(*(get_cell_size() or (1, 2)))
[docs]
def set_cell_ratio(ratio: float | AutoCellRatio) -> None:
"""Sets the global :term:`cell ratio`.
Args:
ratio: Can be one of the following values.
* A positive :py:class:`float` value.
* :py:attr:`AutoCellRatio.FIXED`, the ratio is immediately determined from
the :term:`active terminal`.
* :py:attr:`AutoCellRatio.DYNAMIC`, the ratio is determined from the
:term:`active terminal` whenever :py:func:`get_cell_ratio` is called,
though with some caching involved, such that the ratio is re-determined
only if the terminal size changes.
Raises:
ValueError: *ratio* is a non-positive :py:class:`float`.
term_image.exceptions.TermImageError: Auto cell ratio is not supported
in the :term:`active terminal` or on the current platform.
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
:term:`fixed size`. For a change in cell ratio to take effect, the image's
size has to be re-set.
IMPORTANT:
See :ref:`auto-cell-ratio` for details about the auto modes.
"""
global _cell_ratio
if isinstance(ratio, AutoCellRatio):
if AutoCellRatio.is_supported is None:
AutoCellRatio.is_supported = get_cell_size() is not None
if not AutoCellRatio.is_supported:
raise TermImageError(
"Auto cell ratio is not supported in the active terminal or on the "
"current platform"
)
elif ratio is AutoCellRatio.FIXED:
# `(1, 2)` is a fallback in case the terminal doesn't respond in time
_cell_ratio = truediv(*(get_cell_size() or (1, 2)))
else:
_cell_ratio = None
else:
if ratio <= 0.0:
raise arg_value_error_range("ratio", ratio)
_cell_ratio = ratio
[docs]
def set_query_timeout(timeout: float) -> None:
"""Sets the timeout for :ref:`terminal-queries`.
Args:
timeout: Time limit for awaiting a response from the terminal, in seconds.
Raises:
ValueError: *timeout* is less than or equal to zero.
"""
if timeout <= 0.0:
raise arg_value_error_range("timeout", timeout)
utils._query_timeout = timeout
_cell_ratio: float | None = 0.5
AutoCellRatio.is_supported = None