Advertisement
AdmiralNemo

Console spinner in Python

Nov 28th, 2012
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.64 KB | None | 0 0
  1. from __future__ import unicode_literals
  2. import sys
  3. import threading
  4. import time
  5.  
  6.  
  7. class Spinner(object):
  8.     '''A console status indicator
  9.  
  10.    Akin to a throbber image or a busy cursor, a console spinner is a
  11.    visual indicator that informs the user that the application is
  12.    currently performing a long process. This class makes drawing
  13.    a spinner simple and effective.
  14.  
  15.    The simplest way to use a ``Spinner`` is to instantiate one and
  16.    then call :py:meth:`Spinner.spin`::
  17.  
  18.        spinner = Spinner()
  19.        spinner.spin()
  20.  
  21.    To stop the spinner, call :py:meth:`Spinner.stop`.
  22.  
  23.    A more appropriate way to use a ``Spinner`` is to use it as a
  24.    `Context Manager`_ using the `with statement`_::
  25.  
  26.        with Spinner():
  27.            do_something()
  28.  
  29.    This will spawn a worker thread to draw the spinner while the
  30.    operation inside the with statement continues. When the code inside
  31.    the with statement block completes, the spinner will stop.
  32.  
  33.    :param start_text: Text to be printed before the spinner
  34.    :param finish_text: Text to be printed in place of the spinner when
  35.       it stops
  36.  
  37.    .. py:attr: chars
  38.        A sequence of characters that will be printed one at a time,
  39.        each replacing the previous, on the console. The characters
  40.        should appear to form some kind of loop when printed in this
  41.        way.
  42.  
  43.    .. _Context Manager:
  44.        http://docs.python.org/3.2/reference/datamodel.html#context-managers
  45.    .. _with statement:
  46.        http://docs.python.org/3.2/reference/compound_stmts.html#with
  47.    '''
  48.  
  49.     chars = '\|/-'
  50.  
  51.     def __init__(self, start_text='', finish_text=''):
  52.         self.start_text = start_text
  53.         self.finish_text = finish_text
  54.         self.event = threading.Event()
  55.  
  56.     def __enter__(self):
  57.         thread = threading.Thread(target=self.spin)
  58.         thread.start()
  59.  
  60.     def __exit__(self, exc_type, exc_value, tb):
  61.         self.stop()
  62.  
  63.     def spin(self):
  64.         # Send the DECTCEM ANSI escape sequence to hide the cursor and
  65.         # display the start text
  66.         sys.stdout.write('\x1b[?25l{0}'.format(self.start_text))
  67.         i = 0
  68.         while not self.event.is_set():
  69.             # Print the next character in the sequence and immediately
  70.             # flush the buffer
  71.             sys.stdout.write(self.chars[i])
  72.             sys.stdout.flush()
  73.             time.sleep(.1)
  74.             # Print the "backspace" character to delete the previous
  75.             # character
  76.             sys.stdout.write('\b')
  77.             # Increment or reset the character index
  78.             i = (i + 1) % len(self.chars)
  79.         # Send the DECTCEM ANSI escape sequence to show the cursor and
  80.         # display the finish text
  81.         sys.stdout.write('\x1b[?25h{0}\n'.format(self.finish_text))
  82.  
  83.     def stop(self):
  84.         self.event.set()
  85.  
  86.  
  87. class TrigramSpinner(Spinner):
  88.     '''A :py:class:`Spinner` that draws using trigrams'''
  89.  
  90.     chars = '☰☱☲☴☳☵☶☷'
  91.  
  92. class NarySpinner(Spinner):
  93.     '''A :py:class:`Spinner` that draws using N-ary operators'''
  94.  
  95.     chars = '⨁⨂'
  96.  
  97. class QuarterCircleSpinner(Spinner):
  98.     '''A :py:class:`Spinner` that draws using circles with segments'''
  99.  
  100.     chars = '◴◵◶◷'
  101.  
  102. class FilledDiamondSpinner(Spinner):
  103.     '''A :py:class:`Spinner` that draws using partially-filled diamonds'''
  104.  
  105.     chars = '⬖⬗⬘⬙'
  106.  
  107. class FilledSquareSpinner(Spinner):
  108.     '''A :py:class:`Spinner` that draws using partially-filled squares'''
  109.  
  110.     chars = '⬒⬓⬔⬕'
  111.  
  112. class FilledCircleSpinner(Spinner):
  113.     '''A :py:class:`Spinner` that draws using partially-filled circles'''
  114.  
  115.     chars = '○◔◑◕●◕◓◑◔'
  116.  
  117. class SmallTriangleSpinner(Spinner):
  118.     '''A :py:class:`Spinner` that draws using small triangles'''
  119.  
  120.     chars = '▵▹▿◃'
  121.  
  122. class FilledSmallTriangleSpinner(Spinner):
  123.     '''A :py:class:`Spinner` that draws using small filled triangles'''
  124.  
  125.     chars = '▴▸▾◂'
  126.  
  127. class FilledTriangleSpinner(Spinner):
  128.     '''A :py:class:`Spinner` that draws using filled triangles'''
  129.  
  130.     chars = '▲▶▼◀'
  131.  
  132. class HalfSquareSpinner(Spinner):
  133.     '''A :py:class:`Spinner` that draws using half-filled squares'''
  134.  
  135.     chars = '◢◣◤◥'
  136.  
  137. class DitheredSquareSpinner(Spinner):
  138.     '''A :py:class:`Spinner` that draws using dithered squares'''
  139.  
  140.     chars = '▤▧▥▨'
  141.  
  142. class DiceSpinner(Spinner):
  143.     '''A :py:class:`Spinner` that draws using die faces'''
  144.  
  145.     chars = '⚀⚁⚂⚃⚄⚅'
  146.  
  147. if __name__ == '__main__':
  148.     with Spinner('Working...', 'Done!'):
  149.         try:
  150.             time.sleep(1.5)
  151.         except KeyboardInterrupt:
  152.             sys.exit(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement