Skip to main content

Yet Another Terminal Spinner

Project description

yaspin Logo

yaspin: Yet Another Terminal Spinner for Python

Coverage pypi black-fmt

Versions Wheel Examples

DownloadsTot DownloadsW

Yaspin provides a full-featured terminal spinner to show the progress during long-hanging operations.

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/demo.gif

It is easy to integrate into existing codebase by using it as a context manager or as a function decorator:

import time
from yaspin import yaspin

# Context manager:
with yaspin():
    time.sleep(3)  # time consuming code

# Function decorator:
@yaspin(text="Loading...")
def some_operations():
    time.sleep(3)  # time consuming code

some_operations()

Yaspin also provides an intuitive and powerful API. For example, you can easily summon a shark:

import time
from yaspin import yaspin

with yaspin().white.bold.shark.on_blue as sp:
    sp.text = "White bold shark in a blue sea"
    time.sleep(5)
https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/shark.gif

Features

  • Runs at all major CPython versions (3.9, 3.10, 3.11, 3.12), PyPy

  • Supports all (70+) spinners from cli-spinners

  • Supports all colors, highlights, attributes and their mixes from termcolor library

  • Easy to combine with other command-line libraries, e.g. prompt-toolkit

  • Flexible API, easy to integrate with existing code

  • User-friendly API for handling POSIX signals

  • Safe pipes and redirects:

$ python script_that_uses_yaspin.py > script.log
$ python script_that_uses_yaspin.py | grep ERROR

Installation

From PyPI using pip package manager:

pip install --upgrade yaspin

Or install the latest sources from GitHub:

pip install https://github.com/pavdmyt/yaspin/archive/master.zip

Usage

Basic Example

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_example.gif
import time
from random import randint
from yaspin import yaspin

with yaspin(text="Loading", color="yellow") as spinner:
    time.sleep(2)  # time consuming code

    success = randint(0, 1)
    if success:
        spinner.ok("✅ ")
    else:
        spinner.fail("💥 ")

It is also possible to control spinner manually:

import time
from yaspin import yaspin

spinner = yaspin()
spinner.start()

time.sleep(3)  # time consuming tasks

spinner.stop()

Run any spinner from cli-spinners

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/cli_spinners.gif
import time
from yaspin import yaspin
from yaspin.spinners import Spinners

with yaspin(Spinners.earth, text="Earth") as sp:
    time.sleep(2)                # time consuming code

    # change spinner
    sp.spinner = Spinners.moon
    sp.text = "Moon"

    time.sleep(2)                # time consuming code

Any Colour You Like 🌈

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_colors.gif
import time
from yaspin import yaspin

with yaspin(text="Colors!") as sp:
    # Support all basic termcolor text colors
    colors = ("red", "green", "yellow", "blue", "magenta", "cyan", "white")

    for color in colors:
        sp.color, sp.text = color, color
        time.sleep(1)

Advanced colors usage

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/advanced_colors.gif
import time
from yaspin import yaspin
from yaspin.spinners import Spinners

text = "Bold blink magenta spinner on cyan color"
with yaspin().bold.blink.magenta.bouncingBall.on_cyan as sp:
    sp.text = text
    time.sleep(3)

# The same result can be achieved by passing arguments directly
with yaspin(
    Spinners.bouncingBall,
    color="magenta",
    on_color="on_cyan",
    attrs=["bold", "blink"],
) as sp:
    sp.text = text
    time.sleep(3)

Run any spinner you want

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/custom_spinners.gif
import time
from yaspin import yaspin, Spinner

# Compose new spinners with custom frame sequence and interval value
sp = Spinner(["😸", "😹", "😺", "😻", "😼", "😽", "😾", "😿", "🙀"], 200)

with yaspin(sp, text="Cat!"):
    time.sleep(3)  # cat consuming code :)

Change spinner properties on the fly

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/sp_properties.gif
import time
from yaspin import yaspin
from yaspin.spinners import Spinners

with yaspin(Spinners.noise, text="Noise spinner") as sp:
    time.sleep(2)

    sp.spinner = Spinners.arc  # spinner type
    sp.text = "Arc spinner"    # text along with spinner
    sp.color = "green"         # spinner color
    sp.side = "right"          # put spinner to the right
    sp.reversal = True         # reverse spin direction

    time.sleep(2)

Spinner with timer

import time
from yaspin import yaspin

with yaspin(text="elapsed time", timer=True) as sp:
    time.sleep(3.1415)
    sp.ok()

Dynamic text

import time
from datetime import datetime
from yaspin import yaspin

class TimedText:
    def __init__(self, text):
        self.text = text
        self._start = datetime.now()

    def __str__(self):
        now = datetime.now()
        delta = now - self._start
        return f"{self.text} ({round(delta.total_seconds(), 1)}s)"

with yaspin(text=TimedText("time passed:")):
    time.sleep(3)

Writing messages

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/write_text.gif

You should not write any message in the terminal using print while spinner is open. To write messages in the terminal without any collision with yaspin spinner, a .write() method is provided:

import time
from yaspin import yaspin

with yaspin(text="Downloading images", color="cyan") as sp:
    # task 1
    time.sleep(1)
    sp.write("> image 1 download complete")

    # task 2
    time.sleep(2)
    sp.write("> image 2 download complete")

    # finalize
    sp.ok("✔")

Integration with other libraries

https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/hide_show.gif

Utilizing hidden context manager it is possible to toggle the display of the spinner in order to call custom methods that write to the terminal. This is helpful for allowing easy usage in other frameworks like prompt-toolkit. Using the powerful print_formatted_text function allows you even to apply HTML formats and CSS styles to the output:

import sys
import time

from yaspin import yaspin
from prompt_toolkit import HTML, print_formatted_text
from prompt_toolkit.styles import Style

# override print with feature-rich ``print_formatted_text`` from prompt_toolkit
print = print_formatted_text

# build a basic prompt_toolkit style for styling the HTML wrapped text
style = Style.from_dict({
    'msg': '#4caf50 bold',
    'sub-msg': '#616161 italic'
})


with yaspin(text='Downloading images') as sp:
    # task 1
    time.sleep(1)
    with sp.hidden():
        print(HTML(
            u'<b>></b> <msg>image 1</msg> <sub-msg>download complete</sub-msg>'
        ), style=style)

    # task 2
    time.sleep(2)
    with sp.hidden():
        print(HTML(
            u'<b>></b> <msg>image 2</msg> <sub-msg>download complete</sub-msg>'
        ), style=style)

    # finalize
    sp.ok()

Handling POSIX signals

Handling keyboard interrupts (pressing Control-C):

import time

from yaspin import kbi_safe_yaspin


with kbi_safe_yaspin(text="Press Control+C to send SIGINT (Keyboard Interrupt) signal"):
    time.sleep(5)  # time consuming code

Handling other types of signals:

import os
import time
from signal import SIGTERM, SIGUSR1

from yaspin import yaspin
from yaspin.signal_handlers import default_handler, fancy_handler


sigmap = {SIGUSR1: default_handler, SIGTERM: fancy_handler}
with yaspin(sigmap=sigmap, text="Handling SIGUSR1 and SIGTERM signals") as sp:
    sp.write("Send signals using `kill` command")
    sp.write("E.g. $ kill -USR1 {0}".format(os.getpid()))
    time.sleep(20)  # time consuming code

More examples.

Development

Clone the repository:

git clone https://github.com/pavdmyt/yaspin.git

Install dev dependencies:

poetry install

# if you don't have poetry installed:
pip install -r requirements.txt

Lint code:

make lint

Format code:

make black-fmt

Run tests:

make test

Contributing

  1. Fork it!

  2. Create your feature branch: git checkout -b my-new-feature

  3. Commit your changes: git commit -m 'Add some feature'

  4. Push to the branch: git push origin my-new-feature

  5. Submit a pull request

  6. Make sure tests are passing

License

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

yaspin-3.0.0.tar.gz (34.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

yaspin-3.0.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file yaspin-3.0.0.tar.gz.

File metadata

  • Download URL: yaspin-3.0.0.tar.gz
  • Upload date:
  • Size: 34.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.11.4 Linux/6.4.9-100.fc37.x86_64

File hashes

Hashes for yaspin-3.0.0.tar.gz
Algorithm Hash digest
SHA256 3b12004f9fb7d5a6295b14e416c652a9cce6a4aab09a6ade0c7f1dd7410c8fb2
MD5 16bfebc530131bbc6af91d375946c7cb
BLAKE2b-256 926ed51aea385b639865a8af39d765429cf2b41d9b0a4d3b509aa53d5b7aaed9

See more details on using hashes here.

File details

Details for the file yaspin-3.0.0-py3-none-any.whl.

File metadata

  • Download URL: yaspin-3.0.0-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.5.1 CPython/3.11.4 Linux/6.4.9-100.fc37.x86_64

File hashes

Hashes for yaspin-3.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 29c4f818f726311aba4694a523827bce715a9362b8e378efa988df28cec92977
MD5 3cea2edd5659b8c9b3beb4dcdccf6336
BLAKE2b-256 79ca8b36ca885f563c2f988ea3453dc9f539b1e26c8beb6ed4c10934b022fa82

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page