Skip to content

BaseEffect

Module: terminaltexteffects.engine.base_effect

Base classes for all effects.

Base classes from which all effects should inherit. These classes define the basic structure for an effect and establish the effect iterator interface as well as the effect configuration and terminal configuration.

Classes:

Name Description
BaseEffectIterator

An abstract base class that defines the basic structure for an iterator that applies a certain effect to the input data. Provides initialization for the effect configuration and terminal as well as the __iter__ method.

BaseEffect

An abstract base class that defines the basic structure for an effect. Provides the __iter__ method and a context manager for terminal output.

BaseEffect

Bases: ABC, Generic[T]

Base iterable class for all effects.

Base class for all effects. Provides the __iter__ method and a context manager for terminal output.

Attributes:

Name Type Description
input_data str

Text to which the effect will be applied.

effect_config T

Configuration for the effect.

terminal_config TerminalConfig

Configuration for the terminal.

Source code in terminaltexteffects/engine/base_effect.py
class BaseEffect(ABC, Generic[T]):
    """Base iterable class for all effects.

    Base class for all effects. Provides the `__iter__` method and a context manager for terminal output.

    Attributes:
        input_data (str): Text to which the effect will be applied.
        effect_config (T): Configuration for the effect.
        terminal_config (TerminalConfig): Configuration for the terminal.

    """

    @property
    @abstractmethod
    def _config_cls(self) -> type[T]:
        """Effect configuration class as a subclass of ArgsDataClass."""

    @property
    @abstractmethod
    def _iterator_cls(self) -> type[BaseEffectIterator]:
        """Effect iterator class as a subclass of BaseEffectIterator."""

    def __init__(
        self,
        input_data: str,
        effect_config: T | None = None,
        terminal_config: TerminalConfig | None = None,
    ) -> None:
        """Initialize the effect with the input data.

        Args:
            input_data (str): Text to which the effect will be applied.
            effect_config (BaseConfig | None, optional): Effect configuration. If not
                provided, a new configuration will be built with default values.
                Defaults to None.
            terminal_config (TerminalConfig | None, optional): Terminal configuration. If not
                provided, a new configuration will be built with default values.
                Defaults to None.

        """
        self.input_data = input_data
        self.effect_config: T = effect_config or self._config_cls._build_config()
        self.terminal_config: TerminalConfig = terminal_config or TerminalConfig._build_config()

    def __iter__(self) -> BaseEffectIterator:
        """Create and return a new iterator for the effect.

        Returns:
            BaseEffectIterator: A new iterator instance for this effect.

        """
        return self._iterator_cls(self)

    @contextmanager
    def terminal_output(self, end_symbol: str = "\n") -> Generator[Terminal, None, None]:
        """Context manager for terminal output. Prepares the terminal for output and restores it after.

        Args:
            end_symbol (str, optional): Symbol to print after the effect has completed. Defaults to newline.

        Yields:
            Terminal: Terminal object for handling output.

        Raises:
            Exception: Any exception that occurs within the context manager is re-raised
                after the terminal state is restored.

        """
        terminal = Terminal(self.input_data, self.terminal_config)
        try:
            terminal.prep_canvas()
            yield terminal

        finally:
            terminal.restore_cursor(end_symbol)

__init__(input_data, effect_config=None, terminal_config=None)

Initialize the effect with the input data.

Parameters:

Name Type Description Default
input_data str

Text to which the effect will be applied.

required
effect_config BaseConfig | None

Effect configuration. If not provided, a new configuration will be built with default values. Defaults to None.

None
terminal_config TerminalConfig | None

Terminal configuration. If not provided, a new configuration will be built with default values. Defaults to None.

None
Source code in terminaltexteffects/engine/base_effect.py
def __init__(
    self,
    input_data: str,
    effect_config: T | None = None,
    terminal_config: TerminalConfig | None = None,
) -> None:
    """Initialize the effect with the input data.

    Args:
        input_data (str): Text to which the effect will be applied.
        effect_config (BaseConfig | None, optional): Effect configuration. If not
            provided, a new configuration will be built with default values.
            Defaults to None.
        terminal_config (TerminalConfig | None, optional): Terminal configuration. If not
            provided, a new configuration will be built with default values.
            Defaults to None.

    """
    self.input_data = input_data
    self.effect_config: T = effect_config or self._config_cls._build_config()
    self.terminal_config: TerminalConfig = terminal_config or TerminalConfig._build_config()

__iter__()

Create and return a new iterator for the effect.

Returns:

Name Type Description
BaseEffectIterator BaseEffectIterator

A new iterator instance for this effect.

Source code in terminaltexteffects/engine/base_effect.py
def __iter__(self) -> BaseEffectIterator:
    """Create and return a new iterator for the effect.

    Returns:
        BaseEffectIterator: A new iterator instance for this effect.

    """
    return self._iterator_cls(self)

terminal_output(end_symbol='\n')

Context manager for terminal output. Prepares the terminal for output and restores it after.

Parameters:

Name Type Description Default
end_symbol str

Symbol to print after the effect has completed. Defaults to newline.

'\n'

Yields:

Name Type Description
Terminal Terminal

Terminal object for handling output.

Raises:

Type Description
Exception

Any exception that occurs within the context manager is re-raised after the terminal state is restored.

Source code in terminaltexteffects/engine/base_effect.py
@contextmanager
def terminal_output(self, end_symbol: str = "\n") -> Generator[Terminal, None, None]:
    """Context manager for terminal output. Prepares the terminal for output and restores it after.

    Args:
        end_symbol (str, optional): Symbol to print after the effect has completed. Defaults to newline.

    Yields:
        Terminal: Terminal object for handling output.

    Raises:
        Exception: Any exception that occurs within the context manager is re-raised
            after the terminal state is restored.

    """
    terminal = Terminal(self.input_data, self.terminal_config)
    try:
        terminal.prep_canvas()
        yield terminal

    finally:
        terminal.restore_cursor(end_symbol)

BaseEffectIterator

Bases: ABC, Generic[T]

Base iterator class for all effects.

Parameters:

Name Type Description Default
effect BaseEffect

Effect to apply to the input data.

required

Attributes:

Name Type Description
config T

Configuration for the effect.

terminal Terminal

Terminal to use for output.

active_characters set[EffectCharacter]

Set of active characters in the effect.

preexisting_colors_present bool

Whether any terminal input characters were initialized with parsed foreground or background input colors.

Properties: frame (str): Current frame of the effect.

Methods:

Name Description
update

Run the tick method for all active characters and remove inactive characters from the active list.

__iter__

Return the iterator object.

__next__

Return the next frame of the effect.

Source code in terminaltexteffects/engine/base_effect.py
class BaseEffectIterator(ABC, Generic[T]):
    """Base iterator class for all effects.

    Args:
        effect (BaseEffect): Effect to apply to the input data.

    Attributes:
        config (T): Configuration for the effect.
        terminal (Terminal): Terminal to use for output.
        active_characters (set[EffectCharacter]): Set of active characters in the effect.
        preexisting_colors_present (bool): Whether any terminal input characters were
            initialized with parsed foreground or background input colors.
    Properties:
        frame (str): Current frame of the effect.

    Methods:
        update: Run the tick method for all active characters and remove inactive characters from the active list.
        __iter__: Return the iterator object.
        __next__: Return the next frame of the effect.

    """

    def __init__(self, effect: BaseEffect) -> None:
        """Initialize the iterator with the Effect.

        Args:
            effect (BaseEffect): Effect to apply to the input data.

        """
        self.config: T = deepcopy(effect.effect_config)
        self.terminal = Terminal(effect.input_data, deepcopy(effect.terminal_config))
        self.active_characters: set[EffectCharacter] = set()
        self.preexisting_colors_present: bool = any(
            any((character.animation.input_fg_color, character.animation.input_bg_color))
            for character in self.terminal.get_characters()
        )

    @property
    def frame(self) -> str:
        """Return the current formatted frame from the terminal.

        If the configured terminal frame rate is greater than `0`, enforce the frame rate
        before reading the formatted output string. This property does not advance effect
        state on its own.

        Returns:
            str: Current frame of the effect.

        """
        if self.terminal._frame_rate:
            self.terminal.enforce_framerate()
        return self.terminal.get_formatted_output_string()

    def update(self) -> None:
        """Run one tick for each active character and prune inactive characters.

        Each character in `active_characters` is ticked once. After all ticks complete,
        characters whose `is_active` flag is false are removed from the set.
        """
        for character in self.active_characters:
            character.tick()
        self.active_characters -= {character for character in self.active_characters if not character.is_active}

    def __iter__(self) -> BaseEffectIterator:
        """Return this iterator instance.

        Returns:
            BaseEffectIterator: This iterator.

        """
        return self

    @abstractmethod
    def __next__(self) -> str:
        """Return the next frame of the effect.

        Perform any necessary updates to the effect to progress
        the effect logic and return the next frame.

        Raises:
            NotImplementedError: This method must be implemented by the subclass.

        Returns:
            str: Next frame of the effect.

        """

frame property

Return the current formatted frame from the terminal.

If the configured terminal frame rate is greater than 0, enforce the frame rate before reading the formatted output string. This property does not advance effect state on its own.

Returns:

Name Type Description
str str

Current frame of the effect.

__init__(effect)

Initialize the iterator with the Effect.

Parameters:

Name Type Description Default
effect BaseEffect

Effect to apply to the input data.

required
Source code in terminaltexteffects/engine/base_effect.py
def __init__(self, effect: BaseEffect) -> None:
    """Initialize the iterator with the Effect.

    Args:
        effect (BaseEffect): Effect to apply to the input data.

    """
    self.config: T = deepcopy(effect.effect_config)
    self.terminal = Terminal(effect.input_data, deepcopy(effect.terminal_config))
    self.active_characters: set[EffectCharacter] = set()
    self.preexisting_colors_present: bool = any(
        any((character.animation.input_fg_color, character.animation.input_bg_color))
        for character in self.terminal.get_characters()
    )

__iter__()

Return this iterator instance.

Returns:

Name Type Description
BaseEffectIterator BaseEffectIterator

This iterator.

Source code in terminaltexteffects/engine/base_effect.py
def __iter__(self) -> BaseEffectIterator:
    """Return this iterator instance.

    Returns:
        BaseEffectIterator: This iterator.

    """
    return self

__next__() abstractmethod

Return the next frame of the effect.

Perform any necessary updates to the effect to progress the effect logic and return the next frame.

Raises:

Type Description
NotImplementedError

This method must be implemented by the subclass.

Returns:

Name Type Description
str str

Next frame of the effect.

Source code in terminaltexteffects/engine/base_effect.py
@abstractmethod
def __next__(self) -> str:
    """Return the next frame of the effect.

    Perform any necessary updates to the effect to progress
    the effect logic and return the next frame.

    Raises:
        NotImplementedError: This method must be implemented by the subclass.

    Returns:
        str: Next frame of the effect.

    """

update()

Run one tick for each active character and prune inactive characters.

Each character in active_characters is ticked once. After all ticks complete, characters whose is_active flag is false are removed from the set.

Source code in terminaltexteffects/engine/base_effect.py
def update(self) -> None:
    """Run one tick for each active character and prune inactive characters.

    Each character in `active_characters` is ticked once. After all ticks complete,
    characters whose `is_active` flag is false are removed from the set.
    """
    for character in self.active_characters:
        character.tick()
    self.active_characters -= {character for character in self.active_characters if not character.is_active}