printbuddies.printbuddies API documentation

# printbuddies.printbuddies

View Source

      1from os import get_terminal_size
      2from time import sleep
      3from typing import Any
      4
      5from noiftimer import Timer
      6
      7
      8def clear():
      9    """Erase the current line from the terminal."""
     10    print(" " * (get_terminal_size().columns - 1), flush=True, end="\r")
     11
     12
     13def print_in_place(string: str, animate: bool = False, animate_refresh: float = 0.01):
     14    """Calls to print_in_place will overwrite
     15    the previous line of text in the terminal
     16    with the 'string' param.
     17
     18    :param animate: Will cause the string
     19    to be printed to the terminal
     20    one character at a time.
     21
     22    :param animate_refresh: Number of seconds
     23    between the addition of characters
     24    when 'animate' is True."""
     25    clear()
     26    string = str(string)
     27    width = get_terminal_size().columns
     28    string = string[: width - 2]
     29    if animate:
     30        for i in range(len(string)):
     31            print(f"{string[:i+1]}", flush=True, end=" \r")
     32            sleep(animate_refresh)
     33    else:
     34        print(string, flush=True, end="\r")
     35
     36
     37def ticker(info: list[str]):
     38    """Prints info to terminal with
     39    top and bottom padding so that repeated
     40    calls print info without showing previous
     41    outputs from ticker calls.
     42
     43    Similar visually to print_in_place,
     44    but for multiple lines."""
     45    width = get_terminal_size().columns
     46    info = [str(line)[: width - 1] for line in info]
     47    height = get_terminal_size().lines - len(info)
     48    print("\n" * (height * 2), end="")
     49    print(*info, sep="\n", end="")
     50    print("\n" * (int((height) / 2)), end="")
     51
     52
     53class ProgBar:
     54    """Self incrementing, dynamically sized progress bar.
     55
     56    Includes an internal timer that starts when this object is created.
     57    It can be easily added to the progress bar display by adding
     58    the 'runtime' property to display's prefix or suffix param:
     59
     60    >>> bar = ProgBar(total=100)
     61    >>> time.sleep(30)
     62    >>> bar.display(prefix=bar.runtime)
     63    >>> "runtime: 30s [_///////////////////]1.00%" """
     64
     65    def __init__(
     66        self,
     67        total: float,
     68        update_frequency: int = 1,
     69        fill_ch: str = "_",
     70        unfill_ch: str = "/",
     71        width_ratio: float = 0.75,
     72        new_line_after_completion: bool = True,
     73        clear_after_completion: bool = False,
     74    ):
     75        """:param total: The number of calls to reach 100% completion.
     76
     77        :param update_frequency: The progress bar will only update once every this number of calls to display().
     78        The larger the value, the less performance impact ProgBar has on the loop in which it is called.
     79        e.g.
     80        >>> bar = ProgBar(100, update_frequency=10)
     81        >>> for _ in range(100):
     82        >>>     bar.display()
     83
     84        ^The progress bar in the terminal will only update once every ten calls, going from 0%->100% in 10% increments.
     85        Note: If 'total' is not a multiple of 'update_frequency', the display will not show 100% completion when the loop finishes.
     86
     87        :param fill_ch: The character used to represent the completed part of the bar.
     88
     89        :param unfill_ch: The character used to represent the uncompleted part of the bar.
     90
     91        :param width_ratio: The width of the progress bar relative to the width of the terminal window.
     92
     93        :param new_line_after_completion: Make a call to print() once self.counter >= self.total.
     94
     95        :param clear_after_completion: Make a call to printbuddies.clear() once self.counter >= self.total.
     96
     97        Note: if new_line_after_completion and clear_after_completion are both True, the line will be cleared
     98        then a call to print() will be made."""
     99        self.total = total
    100        self.update_frequency = update_frequency
    101        self.fill_ch = fill_ch[0]
    102        self.unfill_ch = unfill_ch[0]
    103        self.width_ratio = width_ratio
    104        self.new_line_after_completion = new_line_after_completion
    105        self.clear_after_completion = clear_after_completion
    106        self.reset()
    107        self.with_context = False
    108
    109    def __enter__(self):
    110        self.with_context = True
    111        return self
    112
    113    def __exit__(self, *args, **kwargs):
    114        if self.clear_after_completion:
    115            clear()
    116        else:
    117            print()
    118
    119    def reset(self):
    120        self.counter = 1
    121        self.percent = ""
    122        self.prefix = ""
    123        self.suffix = ""
    124        self.filled = ""
    125        self.unfilled = ""
    126        self.bar = ""
    127        self.timer = Timer(subsecond_resolution=False).start()
    128
    129    @property
    130    def runtime(self) -> str:
    131        return f"runtime:{self.timer.elapsed_str}"
    132
    133    def get_percent(self) -> str:
    134        """Returns the percentage complete to two decimal places
    135        as a string without the %."""
    136        percent = str(round(100.0 * self.counter / self.total, 2))
    137        if len(percent.split(".")[1]) == 1:
    138            percent = percent + "0"
    139        if len(percent.split(".")[0]) == 1:
    140            percent = "0" + percent
    141        return percent
    142
    143    def _prepare_bar(self):
    144        self.terminal_width = get_terminal_size().columns - 1
    145        bar_length = int(self.terminal_width * self.width_ratio)
    146        progress = int(bar_length * min(self.counter / self.total, 1.0))
    147        self.filled = self.fill_ch * progress
    148        self.unfilled = self.unfill_ch * (bar_length - progress)
    149        self.percent = self.get_percent()
    150        self.bar = self.get_bar()
    151
    152    def _trim_bar(self):
    153        original_width = self.width_ratio
    154        while len(self.bar) > self.terminal_width and self.width_ratio > 0:
    155            self.width_ratio -= 0.01
    156            self._prepare_bar()
    157        self.width_ratio = original_width
    158
    159    def get_bar(self):
    160        return f"{self.prefix}{' '*bool(self.prefix)}[{self.filled}{self.unfilled}]-{self.percent}% {self.suffix}"
    161
    162    def display(
    163        self,
    164        prefix: str = "",
    165        suffix: str = "",
    166        counter_override: float | None = None,
    167        total_override: float | None = None,
    168        return_object: Any | None = None,
    169    ) -> Any:
    170        """Writes the progress bar to the terminal.
    171
    172        :param prefix: String affixed to the front of the progress bar.
    173
    174        :param suffix: String appended to the end of the progress bar.
    175
    176        :param counter_override: When an externally incremented completion counter is needed.
    177
    178        :param total_override: When an externally controlled bar total is needed.
    179
    180        :param return_object: An object to be returned by display().
    181
    182        Allows display() to be called within a comprehension:
    183
    184        e.g.
    185
    186        >>> bar = ProgBar(10)
    187        >>> def square(x: int | float)->int|float:
    188        >>>     return x * x
    189        >>> myList = [bar.display(return_object=square(i)) for i in range(10)]
    190        >>> <progress bar gets displayed>
    191        >>> myList
    192        >>> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"""
    193        if not self.timer.started:
    194            self.timer.start()
    195        if counter_override is not None:
    196            self.counter = counter_override
    197        if total_override:
    198            self.total = total_override
    199        # Don't wanna divide by 0 there, pal
    200        while self.total <= 0:
    201            self.total += 1
    202        if self.counter % self.update_frequency == 0:
    203            self.prefix = prefix
    204            self.suffix = suffix
    205            self._prepare_bar()
    206            self._trim_bar()
    207            pad = " " * (self.terminal_width - len(self.bar))
    208            width = get_terminal_size().columns
    209            print(f"{self.bar}{pad}"[: width - 2], flush=True, end="\r")
    210        if self.counter >= self.total:
    211            self.timer.stop()
    212            if not self.with_context:
    213                if self.clear_after_completion:
    214                    clear()
    215                if self.new_line_after_completion:
    216                    print()
    217        self.counter += 1
    218        return return_object
    219
    220
    221class Spinner:
    222    """Prints one of a sequence of characters in order everytime display() is called.
    223
    224    The display function writes the new character to the same line, overwriting the previous character.
    225
    226    The sequence will be cycled through indefinitely.
    227
    228    If used as a context manager, the last printed character will be cleared upon exiting.
    229    """
    230
    231    def __init__(
    232        self, sequence: list[str] = ["/", "-", "\\"], width_ratio: float = 0.25
    233    ):
    234        """
    235        :param sequence: Override the built in spin sequence.
    236
    237        :param width: The fractional amount of the terminal for characters to move across."""
    238        self._base_sequence = sequence
    239        self.width_ratio = width_ratio
    240        self.sequence = self._base_sequence
    241
    242    def __enter__(self):
    243        return self
    244
    245    def __exit__(self, *args, **kwargs):
    246        clear()
    247
    248    @property
    249    def width_ratio(self) -> float:
    250        return self._width_ratio
    251
    252    @width_ratio.setter
    253    def width_ratio(self, ratio: float):
    254        self._width_ratio = ratio
    255        self._update_width()
    256
    257    def _update_width(self):
    258        self._current_terminal_width = get_terminal_size().columns
    259        self._width = int((self._current_terminal_width - 1) * self.width_ratio)
    260
    261    @property
    262    def sequence(self) -> list[Any]:
    263        return self._sequence
    264
    265    @sequence.setter
    266    def sequence(self, character_list: list[Any]):
    267        self._sequence = [
    268            ch.rjust(i + j)
    269            for i in range(1, self._width, len(character_list))
    270            for j, ch in enumerate(character_list)
    271        ]
    272        self._sequence += self._sequence[::-1]
    273
    274    def _get_next(self) -> str:
    275        """Pop the first element of self._sequence, append it to the end, and return the element."""
    276        ch = self.sequence.pop(0)
    277        self.sequence.append(ch)
    278        return ch
    279
    280    def display(self):
    281        """Print the next character in the sequence."""
    282        if get_terminal_size().columns != self._current_terminal_width:
    283            self._update_width()
    284            self.sequence = self._base_sequence
    285        print_in_place(self._get_next())

def clear(): View Source

     9def clear():
    10    """Erase the current line from the terminal."""
    11    print(" " * (get_terminal_size().columns - 1), flush=True, end="\r")

Erase the current line from the terminal.

def print_in_place(string: str, animate: bool = False, animate_refresh: float = 0.01): View Source

    14def print_in_place(string: str, animate: bool = False, animate_refresh: float = 0.01):
    15    """Calls to print_in_place will overwrite
    16    the previous line of text in the terminal
    17    with the 'string' param.
    18
    19    :param animate: Will cause the string
    20    to be printed to the terminal
    21    one character at a time.
    22
    23    :param animate_refresh: Number of seconds
    24    between the addition of characters
    25    when 'animate' is True."""
    26    clear()
    27    string = str(string)
    28    width = get_terminal_size().columns
    29    string = string[: width - 2]
    30    if animate:
    31        for i in range(len(string)):
    32            print(f"{string[:i+1]}", flush=True, end=" \r")
    33            sleep(animate_refresh)
    34    else:
    35        print(string, flush=True, end="\r")

Calls to print_in_place will overwrite the previous line of text in the terminal with the 'string' param.

###### Parameters

- animate: Will cause the string to be printed to the terminal one character at a time.

- animate_refresh: Number of seconds between the addition of characters when 'animate' is True.

def ticker(info: list[str]): View Source

    38def ticker(info: list[str]):
    39    """Prints info to terminal with
    40    top and bottom padding so that repeated
    41    calls print info without showing previous
    42    outputs from ticker calls.
    43
    44    Similar visually to print_in_place,
    45    but for multiple lines."""
    46    width = get_terminal_size().columns
    47    info = [str(line)[: width - 1] for line in info]
    48    height = get_terminal_size().lines - len(info)
    49    print("\n" * (height * 2), end="")
    50    print(*info, sep="\n", end="")
    51    print("\n" * (int((height) / 2)), end="")

Prints info to terminal with top and bottom padding so that repeated calls print info without showing previous outputs from ticker calls.

Similar visually to print_in_place, but for multiple lines.

class ProgBar: View Source

     54class ProgBar:
     55    """Self incrementing, dynamically sized progress bar.
     56
     57    Includes an internal timer that starts when this object is created.
     58    It can be easily added to the progress bar display by adding
     59    the 'runtime' property to display's prefix or suffix param:
     60
     61    >>> bar = ProgBar(total=100)
     62    >>> time.sleep(30)
     63    >>> bar.display(prefix=bar.runtime)
     64    >>> "runtime: 30s [_///////////////////]1.00%" """
     65
     66    def __init__(
     67        self,
     68        total: float,
     69        update_frequency: int = 1,
     70        fill_ch: str = "_",
     71        unfill_ch: str = "/",
     72        width_ratio: float = 0.75,
     73        new_line_after_completion: bool = True,
     74        clear_after_completion: bool = False,
     75    ):
     76        """:param total: The number of calls to reach 100% completion.
     77
     78        :param update_frequency: The progress bar will only update once every this number of calls to display().
     79        The larger the value, the less performance impact ProgBar has on the loop in which it is called.
     80        e.g.
     81        >>> bar = ProgBar(100, update_frequency=10)
     82        >>> for _ in range(100):
     83        >>>     bar.display()
     84
     85        ^The progress bar in the terminal will only update once every ten calls, going from 0%->100% in 10% increments.
     86        Note: If 'total' is not a multiple of 'update_frequency', the display will not show 100% completion when the loop finishes.
     87
     88        :param fill_ch: The character used to represent the completed part of the bar.
     89
     90        :param unfill_ch: The character used to represent the uncompleted part of the bar.
     91
     92        :param width_ratio: The width of the progress bar relative to the width of the terminal window.
     93
     94        :param new_line_after_completion: Make a call to print() once self.counter >= self.total.
     95
     96        :param clear_after_completion: Make a call to printbuddies.clear() once self.counter >= self.total.
     97
     98        Note: if new_line_after_completion and clear_after_completion are both True, the line will be cleared
     99        then a call to print() will be made."""
    100        self.total = total
    101        self.update_frequency = update_frequency
    102        self.fill_ch = fill_ch[0]
    103        self.unfill_ch = unfill_ch[0]
    104        self.width_ratio = width_ratio
    105        self.new_line_after_completion = new_line_after_completion
    106        self.clear_after_completion = clear_after_completion
    107        self.reset()
    108        self.with_context = False
    109
    110    def __enter__(self):
    111        self.with_context = True
    112        return self
    113
    114    def __exit__(self, *args, **kwargs):
    115        if self.clear_after_completion:
    116            clear()
    117        else:
    118            print()
    119
    120    def reset(self):
    121        self.counter = 1
    122        self.percent = ""
    123        self.prefix = ""
    124        self.suffix = ""
    125        self.filled = ""
    126        self.unfilled = ""
    127        self.bar = ""
    128        self.timer = Timer(subsecond_resolution=False).start()
    129
    130    @property
    131    def runtime(self) -> str:
    132        return f"runtime:{self.timer.elapsed_str}"
    133
    134    def get_percent(self) -> str:
    135        """Returns the percentage complete to two decimal places
    136        as a string without the %."""
    137        percent = str(round(100.0 * self.counter / self.total, 2))
    138        if len(percent.split(".")[1]) == 1:
    139            percent = percent + "0"
    140        if len(percent.split(".")[0]) == 1:
    141            percent = "0" + percent
    142        return percent
    143
    144    def _prepare_bar(self):
    145        self.terminal_width = get_terminal_size().columns - 1
    146        bar_length = int(self.terminal_width * self.width_ratio)
    147        progress = int(bar_length * min(self.counter / self.total, 1.0))
    148        self.filled = self.fill_ch * progress
    149        self.unfilled = self.unfill_ch * (bar_length - progress)
    150        self.percent = self.get_percent()
    151        self.bar = self.get_bar()
    152
    153    def _trim_bar(self):
    154        original_width = self.width_ratio
    155        while len(self.bar) > self.terminal_width and self.width_ratio > 0:
    156            self.width_ratio -= 0.01
    157            self._prepare_bar()
    158        self.width_ratio = original_width
    159
    160    def get_bar(self):
    161        return f"{self.prefix}{' '*bool(self.prefix)}[{self.filled}{self.unfilled}]-{self.percent}% {self.suffix}"
    162
    163    def display(
    164        self,
    165        prefix: str = "",
    166        suffix: str = "",
    167        counter_override: float | None = None,
    168        total_override: float | None = None,
    169        return_object: Any | None = None,
    170    ) -> Any:
    171        """Writes the progress bar to the terminal.
    172
    173        :param prefix: String affixed to the front of the progress bar.
    174
    175        :param suffix: String appended to the end of the progress bar.
    176
    177        :param counter_override: When an externally incremented completion counter is needed.
    178
    179        :param total_override: When an externally controlled bar total is needed.
    180
    181        :param return_object: An object to be returned by display().
    182
    183        Allows display() to be called within a comprehension:
    184
    185        e.g.
    186
    187        >>> bar = ProgBar(10)
    188        >>> def square(x: int | float)->int|float:
    189        >>>     return x * x
    190        >>> myList = [bar.display(return_object=square(i)) for i in range(10)]
    191        >>> <progress bar gets displayed>
    192        >>> myList
    193        >>> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"""
    194        if not self.timer.started:
    195            self.timer.start()
    196        if counter_override is not None:
    197            self.counter = counter_override
    198        if total_override:
    199            self.total = total_override
    200        # Don't wanna divide by 0 there, pal
    201        while self.total <= 0:
    202            self.total += 1
    203        if self.counter % self.update_frequency == 0:
    204            self.prefix = prefix
    205            self.suffix = suffix
    206            self._prepare_bar()
    207            self._trim_bar()
    208            pad = " " * (self.terminal_width - len(self.bar))
    209            width = get_terminal_size().columns
    210            print(f"{self.bar}{pad}"[: width - 2], flush=True, end="\r")
    211        if self.counter >= self.total:
    212            self.timer.stop()
    213            if not self.with_context:
    214                if self.clear_after_completion:
    215                    clear()
    216                if self.new_line_after_completion:
    217                    print()
    218        self.counter += 1
    219        return return_object

Self incrementing, dynamically sized progress bar.

Includes an internal timer that starts when this object is created. It can be easily added to the progress bar display by adding the 'runtime' property to display's prefix or suffix param:

    >>> bar = ProgBar(total=100)
    >>> time.sleep(30)
    >>> bar.display(prefix=bar.runtime)
    >>> "runtime: 30s [_///////////////////]1.00%"

ProgBar( total: float, update_frequency: int = 1, fill_ch: str = '_', unfill_ch: str = '/', width_ratio: float = 0.75, new_line_after_completion: bool = True, clear_after_completion: bool = False) View Source

     66    def __init__(
     67        self,
     68        total: float,
     69        update_frequency: int = 1,
     70        fill_ch: str = "_",
     71        unfill_ch: str = "/",
     72        width_ratio: float = 0.75,
     73        new_line_after_completion: bool = True,
     74        clear_after_completion: bool = False,
     75    ):
     76        """:param total: The number of calls to reach 100% completion.
     77
     78        :param update_frequency: The progress bar will only update once every this number of calls to display().
     79        The larger the value, the less performance impact ProgBar has on the loop in which it is called.
     80        e.g.
     81        >>> bar = ProgBar(100, update_frequency=10)
     82        >>> for _ in range(100):
     83        >>>     bar.display()
     84
     85        ^The progress bar in the terminal will only update once every ten calls, going from 0%->100% in 10% increments.
     86        Note: If 'total' is not a multiple of 'update_frequency', the display will not show 100% completion when the loop finishes.
     87
     88        :param fill_ch: The character used to represent the completed part of the bar.
     89
     90        :param unfill_ch: The character used to represent the uncompleted part of the bar.
     91
     92        :param width_ratio: The width of the progress bar relative to the width of the terminal window.
     93
     94        :param new_line_after_completion: Make a call to print() once self.counter >= self.total.
     95
     96        :param clear_after_completion: Make a call to printbuddies.clear() once self.counter >= self.total.
     97
     98        Note: if new_line_after_completion and clear_after_completion are both True, the line will be cleared
     99        then a call to print() will be made."""
    100        self.total = total
    101        self.update_frequency = update_frequency
    102        self.fill_ch = fill_ch[0]
    103        self.unfill_ch = unfill_ch[0]
    104        self.width_ratio = width_ratio
    105        self.new_line_after_completion = new_line_after_completion
    106        self.clear_after_completion = clear_after_completion
    107        self.reset()
    108        self.with_context = False

###### Parameters

- total: The number of calls to reach 100% completion.

- update_frequency: The progress bar will only update once every this number of calls to display(). The larger the value, the less performance impact ProgBar has on the loop in which it is called. e.g.

      >>> bar = ProgBar(100, update_frequency=10)
      >>> for _ in range(100):
      >>>     bar.display()

^The progress bar in the terminal will only update once every ten calls, going from 0%->100% in 10% increments. Note: If 'total' is not a multiple of 'update_frequency', the display will not show 100% completion when the loop finishes.

- fill_ch: The character used to represent the completed part of the bar.

- unfill_ch: The character used to represent the uncompleted part of the bar.

- width_ratio: The width of the progress bar relative to the width of the terminal window.

- new_line_after_completion: Make a call to print() once self.counter >= self.total.

- clear_after_completion: Make a call to printbuddies.clear() once self.counter >= self.total.

Note: if new_line_after_completion and clear_after_completion are both True, the line will be cleared then a call to print() will be made.

def reset(self): View Source

    120    def reset(self):
    121        self.counter = 1
    122        self.percent = ""
    123        self.prefix = ""
    124        self.suffix = ""
    125        self.filled = ""
    126        self.unfilled = ""
    127        self.bar = ""
    128        self.timer = Timer(subsecond_resolution=False).start()

def get_percent(self) -> str: View Source

    134    def get_percent(self) -> str:
    135        """Returns the percentage complete to two decimal places
    136        as a string without the %."""
    137        percent = str(round(100.0 * self.counter / self.total, 2))
    138        if len(percent.split(".")[1]) == 1:
    139            percent = percent + "0"
    140        if len(percent.split(".")[0]) == 1:
    141            percent = "0" + percent
    142        return percent

Returns the percentage complete to two decimal places as a string without the %.

def get_bar(self): View Source

    160    def get_bar(self):
    161        return f"{self.prefix}{' '*bool(self.prefix)}[{self.filled}{self.unfilled}]-{self.percent}% {self.suffix}"

def display( self, prefix: str = '', suffix: str = '', counter_override: float | None = None, total_override: float | None = None, return_object: typing.Any | None = None) -> Any: View Source

    163    def display(
    164        self,
    165        prefix: str = "",
    166        suffix: str = "",
    167        counter_override: float | None = None,
    168        total_override: float | None = None,
    169        return_object: Any | None = None,
    170    ) -> Any:
    171        """Writes the progress bar to the terminal.
    172
    173        :param prefix: String affixed to the front of the progress bar.
    174
    175        :param suffix: String appended to the end of the progress bar.
    176
    177        :param counter_override: When an externally incremented completion counter is needed.
    178
    179        :param total_override: When an externally controlled bar total is needed.
    180
    181        :param return_object: An object to be returned by display().
    182
    183        Allows display() to be called within a comprehension:
    184
    185        e.g.
    186
    187        >>> bar = ProgBar(10)
    188        >>> def square(x: int | float)->int|float:
    189        >>>     return x * x
    190        >>> myList = [bar.display(return_object=square(i)) for i in range(10)]
    191        >>> <progress bar gets displayed>
    192        >>> myList
    193        >>> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]"""
    194        if not self.timer.started:
    195            self.timer.start()
    196        if counter_override is not None:
    197            self.counter = counter_override
    198        if total_override:
    199            self.total = total_override
    200        # Don't wanna divide by 0 there, pal
    201        while self.total <= 0:
    202            self.total += 1
    203        if self.counter % self.update_frequency == 0:
    204            self.prefix = prefix
    205            self.suffix = suffix
    206            self._prepare_bar()
    207            self._trim_bar()
    208            pad = " " * (self.terminal_width - len(self.bar))
    209            width = get_terminal_size().columns
    210            print(f"{self.bar}{pad}"[: width - 2], flush=True, end="\r")
    211        if self.counter >= self.total:
    212            self.timer.stop()
    213            if not self.with_context:
    214                if self.clear_after_completion:
    215                    clear()
    216                if self.new_line_after_completion:
    217                    print()
    218        self.counter += 1
    219        return return_object

Writes the progress bar to the terminal.

###### Parameters

- prefix: String affixed to the front of the progress bar.

- suffix: String appended to the end of the progress bar.

- counter_override: When an externally incremented completion counter is needed.

- total_override: When an externally controlled bar total is needed.

- return_object: An object to be returned by display().

Allows display() to be called within a comprehension:

e.g.

    >>> bar = ProgBar(10)
    >>> def square(x: int | float)->int|float:
    >>>     return x * x
    >>> myList = [bar.display(return_object=square(i)) for i in range(10)]
    >>> <progress bar gets displayed>
    >>> myList
    >>> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

class Spinner: View Source

    222class Spinner:
    223    """Prints one of a sequence of characters in order everytime display() is called.
    224
    225    The display function writes the new character to the same line, overwriting the previous character.
    226
    227    The sequence will be cycled through indefinitely.
    228
    229    If used as a context manager, the last printed character will be cleared upon exiting.
    230    """
    231
    232    def __init__(
    233        self, sequence: list[str] = ["/", "-", "\\"], width_ratio: float = 0.25
    234    ):
    235        """
    236        :param sequence: Override the built in spin sequence.
    237
    238        :param width: The fractional amount of the terminal for characters to move across."""
    239        self._base_sequence = sequence
    240        self.width_ratio = width_ratio
    241        self.sequence = self._base_sequence
    242
    243    def __enter__(self):
    244        return self
    245
    246    def __exit__(self, *args, **kwargs):
    247        clear()
    248
    249    @property
    250    def width_ratio(self) -> float:
    251        return self._width_ratio
    252
    253    @width_ratio.setter
    254    def width_ratio(self, ratio: float):
    255        self._width_ratio = ratio
    256        self._update_width()
    257
    258    def _update_width(self):
    259        self._current_terminal_width = get_terminal_size().columns
    260        self._width = int((self._current_terminal_width - 1) * self.width_ratio)
    261
    262    @property
    263    def sequence(self) -> list[Any]:
    264        return self._sequence
    265
    266    @sequence.setter
    267    def sequence(self, character_list: list[Any]):
    268        self._sequence = [
    269            ch.rjust(i + j)
    270            for i in range(1, self._width, len(character_list))
    271            for j, ch in enumerate(character_list)
    272        ]
    273        self._sequence += self._sequence[::-1]
    274
    275    def _get_next(self) -> str:
    276        """Pop the first element of self._sequence, append it to the end, and return the element."""
    277        ch = self.sequence.pop(0)
    278        self.sequence.append(ch)
    279        return ch
    280
    281    def display(self):
    282        """Print the next character in the sequence."""
    283        if get_terminal_size().columns != self._current_terminal_width:
    284            self._update_width()
    285            self.sequence = self._base_sequence
    286        print_in_place(self._get_next())

Prints one of a sequence of characters in order everytime display() is called.

The display function writes the new character to the same line, overwriting the previous character.

The sequence will be cycled through indefinitely.

If used as a context manager, the last printed character will be cleared upon exiting.

Spinner(sequence: list[str] = ['/', '-', '\\'], width_ratio: float = 0.25) View Source

    232    def __init__(
    233        self, sequence: list[str] = ["/", "-", "\\"], width_ratio: float = 0.25
    234    ):
    235        """
    236        :param sequence: Override the built in spin sequence.
    237
    238        :param width: The fractional amount of the terminal for characters to move across."""
    239        self._base_sequence = sequence
    240        self.width_ratio = width_ratio
    241        self.sequence = self._base_sequence

###### Parameters

- sequence: Override the built in spin sequence.

- width: The fractional amount of the terminal for characters to move across.

def display(self): View Source

    281    def display(self):
    282        """Print the next character in the sequence."""
    283        if get_terminal_size().columns != self._current_terminal_width:
    284            self._update_width()
    285            self.sequence = self._base_sequence
    286        print_in_place(self._get_next())

Print the next character in the sequence.