1|Logo| 2 3===================================================================== 4``yaspin``: **Y**\ et **A**\ nother Terminal **Spin**\ ner for Python 5===================================================================== 6 7|Build Status| |Coverage| |pyup| |black-fmt| 8 9|pypi| |Versions| |Wheel| |Examples| 10 11|DownloadsTot| |DownloadsW| 12 13 14``Yaspin`` provides a full-featured terminal spinner to show the progress during long-hanging operations. 15 16.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/demo.gif 17 18It is easy to integrate into existing codebase by using it as a `context manager`_ 19or as a function `decorator`_: 20 21.. code:: python 22 23 import time 24 from yaspin import yaspin 25 26 # Context manager: 27 with yaspin(): 28 time.sleep(3) # time consuming code 29 30 # Function decorator: 31 @yaspin(text="Loading...") 32 def some_operations(): 33 time.sleep(3) # time consuming code 34 35 some_operations() 36 37 38**Yaspin** also provides an intuitive and powerful API. For example, you can easily summon a shark: 39 40.. code:: python 41 42 import time 43 from yaspin import yaspin 44 45 with yaspin().white.bold.shark.on_blue as sp: 46 sp.text = "White bold shark in a blue sea" 47 time.sleep(5) 48 49.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/shark.gif 50 51 52Features 53-------- 54 55- Runs at all major **CPython** versions (*3.6*, *3.7*, *3.8*, *3.9*), **PyPy** 56- Supports all (70+) spinners from `cli-spinners`_ 57- Supports all *colors*, *highlights*, *attributes* and their mixes from `termcolor`_ library 58- Easy to combine with other command-line libraries, e.g. `prompt-toolkit`_ 59- Flexible API, easy to integrate with existing code 60- User-friendly API for handling POSIX `signals`_ 61- Safe **pipes** and **redirects**: 62 63.. code-block:: bash 64 65 $ python script_that_uses_yaspin.py > script.log 66 $ python script_that_uses_yaspin.py | grep ERROR 67 68 69Installation 70------------ 71 72From `PyPI`_ using ``pip`` package manager: 73 74.. code-block:: bash 75 76 pip install --upgrade yaspin 77 78 79Or install the latest sources from GitHub: 80 81.. code-block:: bash 82 83 pip install https://github.com/pavdmyt/yaspin/archive/master.zip 84 85 86Usage 87----- 88 89Basic Example 90///////////// 91 92.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_example.gif 93 94.. code:: python 95 96 import time 97 from random import randint 98 from yaspin import yaspin 99 100 with yaspin(text="Loading", color="yellow") as spinner: 101 time.sleep(2) # time consuming code 102 103 success = randint(0, 1) 104 if success: 105 spinner.ok("✅ ") 106 else: 107 spinner.fail(" ") 108 109 110It is also possible to control spinner manually: 111 112.. code:: python 113 114 import time 115 from yaspin import yaspin 116 117 spinner = yaspin() 118 spinner.start() 119 120 time.sleep(3) # time consuming tasks 121 122 spinner.stop() 123 124 125Run any spinner from `cli-spinners`_ 126//////////////////////////////////// 127 128.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/cli_spinners.gif 129 130.. code:: python 131 132 import time 133 from yaspin import yaspin 134 from yaspin.spinners import Spinners 135 136 with yaspin(Spinners.earth, text="Earth") as sp: 137 time.sleep(2) # time consuming code 138 139 # change spinner 140 sp.spinner = Spinners.moon 141 sp.text = "Moon" 142 143 time.sleep(2) # time consuming code 144 145 146Any Colour You Like ``_ 147///////////////////////// 148 149.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/basic_colors.gif 150 151.. code:: python 152 153 import time 154 from yaspin import yaspin 155 156 with yaspin(text="Colors!") as sp: 157 # Support all basic termcolor text colors 158 colors = ("red", "green", "yellow", "blue", "magenta", "cyan", "white") 159 160 for color in colors: 161 sp.color, sp.text = color, color 162 time.sleep(1) 163 164 165Advanced colors usage 166///////////////////// 167 168.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/advanced_colors.gif 169 170.. code:: python 171 172 import time 173 from yaspin import yaspin 174 from yaspin.spinners import Spinners 175 176 text = "Bold blink magenta spinner on cyan color" 177 with yaspin().bold.blink.magenta.bouncingBall.on_cyan as sp: 178 sp.text = text 179 time.sleep(3) 180 181 # The same result can be achieved by passing arguments directly 182 with yaspin( 183 Spinners.bouncingBall, 184 color="magenta", 185 on_color="on_cyan", 186 attrs=["bold", "blink"], 187 ) as sp: 188 sp.text = text 189 time.sleep(3) 190 191 192Run any spinner you want 193//////////////////////// 194 195.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/custom_spinners.gif 196 197.. code:: python 198 199 import time 200 from yaspin import yaspin, Spinner 201 202 # Compose new spinners with custom frame sequence and interval value 203 sp = Spinner(["", "", "", "", "", "", "", "", ""], 200) 204 205 with yaspin(sp, text="Cat!"): 206 time.sleep(3) # cat consuming code :) 207 208 209Change spinner properties on the fly 210//////////////////////////////////// 211 212.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/sp_properties.gif 213 214.. code:: python 215 216 import time 217 from yaspin import yaspin 218 from yaspin.spinners import Spinners 219 220 with yaspin(Spinners.noise, text="Noise spinner") as sp: 221 time.sleep(2) 222 223 sp.spinner = Spinners.arc # spinner type 224 sp.text = "Arc spinner" # text along with spinner 225 sp.color = "green" # spinner color 226 sp.side = "right" # put spinner to the right 227 sp.reversal = True # reverse spin direction 228 229 time.sleep(2) 230 231 232Spinner with timer 233////////////////// 234 235.. code:: python 236 237 import time 238 from yaspin import yaspin 239 240 with yaspin(text="elapsed time", timer=True) as sp: 241 time.sleep(3.1415) 242 sp.ok() 243 244 245Dynamic text 246//////////// 247 248.. code:: python 249 250 import time 251 from datetime import datetime 252 from yaspin import yaspin 253 254 class TimedText: 255 def __init__(self, text): 256 self.text = text 257 self._start = datetime.now() 258 259 def __str__(self): 260 now = datetime.now() 261 delta = now - self._start 262 return f"{self.text} ({round(delta.total_seconds(), 1)}s)" 263 264 with yaspin(text=TimedText("time passed:")): 265 time.sleep(3) 266 267 268Writing messages 269//////////////// 270 271.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/write_text.gif 272 273You should not write any message in the terminal using ``print`` while spinner is open. 274To write messages in the terminal without any collision with ``yaspin`` spinner, a ``.write()`` method is provided: 275 276.. code:: python 277 278 import time 279 from yaspin import yaspin 280 281 with yaspin(text="Downloading images", color="cyan") as sp: 282 # task 1 283 time.sleep(1) 284 sp.write("> image 1 download complete") 285 286 # task 2 287 time.sleep(2) 288 sp.write("> image 2 download complete") 289 290 # finalize 291 sp.ok("✔") 292 293 294Integration with other libraries 295//////////////////////////////// 296 297.. image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/gifs/hide_show.gif 298 299Utilizing ``hidden`` context manager it is possible to toggle the display of 300the spinner in order to call custom methods that write to the terminal. This is 301helpful for allowing easy usage in other frameworks like `prompt-toolkit`_. 302Using the powerful ``print_formatted_text`` function allows you even to apply 303HTML formats and CSS styles to the output: 304 305.. code:: python 306 307 import sys 308 import time 309 310 from yaspin import yaspin 311 from prompt_toolkit import HTML, print_formatted_text 312 from prompt_toolkit.styles import Style 313 314 # override print with feature-rich ``print_formatted_text`` from prompt_toolkit 315 print = print_formatted_text 316 317 # build a basic prompt_toolkit style for styling the HTML wrapped text 318 style = Style.from_dict({ 319 'msg': '#4caf50 bold', 320 'sub-msg': '#616161 italic' 321 }) 322 323 324 with yaspin(text='Downloading images') as sp: 325 # task 1 326 time.sleep(1) 327 with sp.hidden(): 328 print(HTML( 329 u'<b>></b> <msg>image 1</msg> <sub-msg>download complete</sub-msg>' 330 ), style=style) 331 332 # task 2 333 time.sleep(2) 334 with sp.hidden(): 335 print(HTML( 336 u'<b>></b> <msg>image 2</msg> <sub-msg>download complete</sub-msg>' 337 ), style=style) 338 339 # finalize 340 sp.ok() 341 342 343Handling POSIX `signals`_ 344///////////////////////// 345 346Handling keyboard interrupts (pressing Control-C): 347 348.. code:: python 349 350 import time 351 352 from yaspin import kbi_safe_yaspin 353 354 355 with kbi_safe_yaspin(text="Press Control+C to send SIGINT (Keyboard Interrupt) signal"): 356 time.sleep(5) # time consuming code 357 358 359Handling other types of signals: 360 361.. code:: python 362 363 import os 364 import time 365 from signal import SIGTERM, SIGUSR1 366 367 from yaspin import yaspin 368 from yaspin.signal_handlers import default_handler, fancy_handler 369 370 371 sigmap = {SIGUSR1: default_handler, SIGTERM: fancy_handler} 372 with yaspin(sigmap=sigmap, text="Handling SIGUSR1 and SIGTERM signals") as sp: 373 sp.write("Send signals using `kill` command") 374 sp.write("E.g. $ kill -USR1 {0}".format(os.getpid())) 375 time.sleep(20) # time consuming code 376 377 378More `examples`_. 379 380 381Development 382----------- 383 384Clone the repository: 385 386.. code-block:: bash 387 388 git clone https://github.com/pavdmyt/yaspin.git 389 390 391Install dev dependencies: 392 393.. code-block:: bash 394 395 poetry install 396 397 # if you don't have poetry installed: 398 pip install -r requirements.txt 399 400 401Lint code: 402 403.. code-block:: bash 404 405 make lint 406 407 408Format code: 409 410.. code-block:: bash 411 412 make black-fmt 413 414 415Run tests: 416 417.. code-block:: bash 418 419 make test 420 421 422Contributing 423------------ 424 4251. Fork it! 4262. Create your feature branch: ``git checkout -b my-new-feature`` 4273. Commit your changes: ``git commit -m 'Add some feature'`` 4284. Push to the branch: ``git push origin my-new-feature`` 4295. Submit a pull request 4306. Make sure tests are passing 431 432 433License 434------- 435 436* MIT - Pavlo Dmytrenko; https://twitter.com/pavdmyt 437* Contains data from `cli-spinners`_: MIT License, Copyright (c) Sindre Sorhus sindresorhus@gmail.com (sindresorhus.com) 438 439 440.. |Logo| image:: https://raw.githubusercontent.com/pavdmyt/yaspin/master/static/logo_80.png 441 :alt: yaspin Logo 442.. |Build Status| image:: https://travis-ci.org/pavdmyt/yaspin.svg?branch=master 443 :target: https://travis-ci.org/pavdmyt/yaspin 444.. |Coverage| image:: https://codecov.io/gh/pavdmyt/yaspin/branch/master/graph/badge.svg 445 :target: https://codecov.io/gh/pavdmyt/yaspin 446.. |pypi| image:: https://img.shields.io/pypi/v/yaspin.svg 447 :target: https://pypi.org/project/yaspin/ 448.. |Versions| image:: https://img.shields.io/pypi/pyversions/yaspin.svg 449 :target: https://pypi.org/project/yaspin/ 450.. |Wheel| image:: https://img.shields.io/pypi/wheel/yaspin.svg 451 :target: https://pypi.org/project/yaspin/ 452.. |Examples| image:: https://img.shields.io/badge/learn%20by-examples-0077b3.svg 453 :target: https://github.com/pavdmyt/yaspin/tree/master/examples 454.. |pyup| image:: https://pyup.io/repos/github/pavdmyt/yaspin/shield.svg 455 :target: https://pyup.io/repos/github/pavdmyt/yaspin/ 456.. |black-fmt| image:: https://img.shields.io/badge/code%20style-black-000000.svg 457 :target: https://github.com/ambv/black 458.. |DownloadsTot| image:: https://pepy.tech/badge/yaspin 459 :target: https://pepy.tech/project/yaspin 460.. |DownloadsW| image:: https://pepy.tech/badge/yaspin/week 461 :target: https://pepy.tech/project/yaspin 462 463 464.. _context manager: https://docs.python.org/3/reference/datamodel.html#context-managers 465.. _decorator: https://www.thecodeship.com/patterns/guide-to-python-function-decorators/ 466.. _cli-spinners: https://github.com/sindresorhus/cli-spinners 467.. _termcolor: https://pypi.org/project/termcolor/ 468.. _PyPI: https://pypi.org/ 469.. _: https://en.wikipedia.org/wiki/Any_Colour_You_Like 470.. _examples: https://github.com/pavdmyt/yaspin/tree/master/examples 471.. _prompt-toolkit: https://github.com/jonathanslenders/python-prompt-toolkit/ 472.. _signals: https://www.computerhope.com/unix/signals.htm 473