Ë –‡. & ûãó„—dZddlZddlZddlZddlmZddlmZddlm Z dZ gd¢Z dZ Gd „d e «ZGd „d e «Zy) aY Support for spinners that represent progress on interactive terminals. The :class:`Spinner` class shows a "spinner" on the terminal to let the user know that something is happening during long running operations that would otherwise be silent (leaving the user to wonder what they're waiting for). Below are some visual examples that should illustrate the point. **Simple spinners:** Here's a screen capture that shows the simplest form of spinner: .. image:: images/spinner-basic.gif :alt: Animated screen capture of a simple spinner. The following code was used to create the spinner above: .. code-block:: python import itertools import time from humanfriendly import Spinner with Spinner(label="Downloading") as spinner: for i in itertools.count(): # Do something useful here. time.sleep(0.1) # Advance the spinner. spinner.step() **Spinners that show elapsed time:** Here's a spinner that shows the elapsed time since it started: .. image:: images/spinner-with-timer.gif :alt: Animated screen capture of a spinner showing elapsed time. The following code was used to create the spinner above: .. code-block:: python import itertools import time from humanfriendly import Spinner, Timer with Spinner(label="Downloading", timer=Timer()) as spinner: for i in itertools.count(): # Do something useful here. time.sleep(0.1) # Advance the spinner. spinner.step() **Spinners that show progress:** Here's a spinner that shows a progress percentage: .. image:: images/spinner-with-progress.gif :alt: Animated screen capture of spinner showing progress. The following code was used to create the spinner above: .. code-block:: python import itertools import random import time from humanfriendly import Spinner, Timer with Spinner(label="Downloading", total=100) as spinner: progress = 0 while progress < 100: # Do something useful here. time.sleep(0.1) # Advance the spinner. spinner.step(progress) # Determine the new progress value. progress += random.random() * 5 If you want to provide user feedback during a long running operation but it's not practical to periodically call the :func:`~Spinner.step()` method consider using :class:`AutomaticSpinner` instead. As you may already have noticed in the examples above, :class:`Spinner` objects can be used as context managers to automatically call :func:`Spinner.clear()` when the spinner ends. éN)ÚTimer)Údeprecated_args)ÚANSI_ERASE_LINE)ÚAutomaticSpinnerÚGLYPHSÚMINIMUM_INTERVALÚSpinner)Ú-Ú\Ú|Ú/gš™™™™™É?cóV—eZdZdZeddddd«d„«Zdd „Zd „Zd „Zd „Z dd „Z y)r zIShow a spinner on the terminal as a simple means of feedback to the user.ÚlabelÚtotalÚstreamÚ interactiveÚtimerc ó —|jd«|_|jdt«|_|jd«|_|jdt «|_|jdtj«|_ |jd«|_ |jd«|_ d|_ d|_ |j€! |jj«|_y y #t$r d |_Yy wxYw) a¹ Initialize a :class:`Spinner` object. :param label: The label for the spinner (a string or :data:`None`, defaults to :data:`None`). :param total: The expected number of steps (an integer or :data:`None`). If this is provided the spinner will show a progress percentage. :param stream: The output stream to show the spinner on (a file-like object, defaults to :data:`sys.stderr`). :param interactive: :data:`True` to enable rendering of the spinner, :data:`False` to disable (defaults to the result of ``stream.isatty()``). :param timer: A :class:`.Timer` object (optional). If this is given the spinner will show the elapsed time according to the timer. :param interval: The spinner will be updated at most once every this many seconds (a floating point number, defaults to :data:`MINIMUM_INTERVAL`). :param glyphs: A list of strings with single characters that are drawn in the same place in succession to implement a simple animated effect (defaults to :data:`GLYPHS`). rÚintervalrÚglyphsrrrrNF)ÚgetrrrrrÚstatesÚsysÚstderrrrrÚcounterÚ last_updateÚisattyÚ Exception)ÚselfÚoptionss úD/usr/lib/python3.12/site-packages/humanfriendly/terminal/spinners.pyÚ__init__zSpinner.__init__vsÖ€ðT#Ÿ;™; }Ó5ˆÔØŸ ™  JÔ0@ÓAˆŒ Ø—[‘[ Ó)ˆŒ Ø—k‘k (¬FÓ3ˆŒ Ø—k‘k (¬C¯J©JÓ7ˆŒ Ø—[‘[ Ó)ˆŒ Ø—[‘[ Ó)ˆŒ àˆŒ ؈Ôð × Ñ Ð #ð )Ø#'§;¡;×#5Ñ#5Ó#7�Õ ð $øôò )Ø#(�Ö ð )úsÃC0Ã0DÄDNcóp—|j�r)tj«}||jz |jk\rø||_|j|j t |j«z}|xs |j}|s td«‚|jr|rd|||jdz z fz}nA|jr5|jjdkDr|›d|jj›d�}|jjt›d|›d|›d�«|xj d z c_y y y ) a¦ Advance the spinner by one step and redraw it. :param progress: The number of the current step, relative to the total given to the :class:`Spinner` constructor (an integer, optional). If not provided the spinner will not show progress. :param label: The label to use while redrawing (a string, optional). If not provided the label given to the :class:`Spinner` constructor is used instead. This method advances the spinner by one step without starting a new line, causing an animated effect which is very simple but much nicer than waiting for a prompt which is completely silent for a long time. .. note:: This method uses time based rate limiting to avoid redrawing the spinner too frequently. If you know you're dealing with code that will call :func:`step()` at a high frequency, consider using :func:`sleep()` to avoid creating the equivalent of a busy loop that's rate limiting the spinner 99% of the time. zNo label set for spinner!z %s: %.2f%%gY@éz (Ú)Ú z .. éN)rÚtimerrrrÚlenrrrrÚ elapsed_timeÚroundedrÚwriter)rÚprogressrÚtime_nowÚstates r!Ústepz Spinner.step²s÷€ð. × Ó Ü—y‘y“{ˆHؘ$×*Ñ*Ñ*¨d¯m©mÒ;Ø#+�Ô ØŸ ™  D§L¡L´3°t·{±{Ó3CÑ$CÑD�ØÒ+ §¡�ÙÜ#Ð$?Ó@Ð@Ø—Z’Z¡HØ(¨E°8¸t¿z¹zÈEÑ?QÑ3RÐ+SÑS‘EØ—Z’Z D§J¡J×$;Ñ$;¸aÒ$?Ú).°· ± ×0BÓ0BÐC�EØ— ‘ ×!Ñ!¶_ÂeÊUÐ"SÔTØ— ’  Ñ!– ð<ð ócó6—tjt«y)a Sleep for a short period before redrawing the spinner. This method is useful when you know you're dealing with code that will call :func:`step()` at a high frequency. It will sleep for the interval with which the spinner is redrawn (less than a second). This avoids creating the equivalent of a busy loop that's rate limiting the spinner 99% of the time. This method doesn't redraw the spinner, you still have to call :func:`step()` in order to do that. N)r(Úsleepr©rs r!r3z Spinner.sleepØs€ô � ‰ Ô#Õ$r1có\—|jr |jjt«yy)zÒ Clear the spinner. The next line which is shown on the standard output or error stream after calling this method will overwrite the line that used to show the spinner. N)rrr,rr4s r!Úclearz Spinner.clearçs$€ð × Ò Ø �K‰K× Ñ œoÕ .ð r1có—|S)zq Enable the use of spinners as context managers. :returns: The :class:`Spinner` object. ©r4s r!Ú __enter__zSpinner.__enter__òs €ð ˆ r1có$—|j«y)z+Clear the spinner when leaving the context.N)r6©rÚexc_typeÚ exc_valueÚ tracebacks r!Ú__exit__zSpinner.__exit__ús €à � ‰ � r1)rN©NNN) Ú__name__Ú __module__Ú __qualname__Ú__doc__rr"r0r3r6r9r?r8r1r!r r rs@„áSá�W˜g x°ÀÓHñ9)óIð9)óv$"òL %ò /òôr1r có,—eZdZdZdd„Zd„Zdd„Zd„Zy) raý Show a spinner on the terminal that automatically starts animating. This class shows a spinner on the terminal (just like :class:`Spinner` does) that automatically starts animating. This class should be used as a context manager using the :keyword:`with` statement. The animation continues for as long as the context is active. :class:`AutomaticSpinner` provides an alternative to :class:`Spinner` for situations where it is not practical for the caller to periodically call :func:`~Spinner.step()` to advance the animation, e.g. because you're performing a blocking call and don't fancy implementing threading or subprocess handling just to provide some user feedback. This works using the :mod:`multiprocessing` module by spawning a subprocess to render the spinner while the main process is busy doing something more useful. By using the :keyword:`with` statement you're guaranteed that the subprocess is properly terminated at the appropriate time. cóœ—||_||_tj«|_tj |j ¬«|_y)zî Initialize an automatic spinner. :param label: The label for the spinner (a string). :param show_time: If this is :data:`True` (the default) then the spinner shows elapsed time. )ÚtargetN)rÚ show_timeÚmultiprocessingÚEventÚshutdown_eventÚProcessÚ_targetÚ subprocess)rrrHs r!r"zAutomaticSpinner.__init__s9€ðˆŒ Ø"ˆŒÜ-×3Ñ3Ó5ˆÔÜ)×1Ñ1¸¿¹ÔFˆ�r1có8—|jj«y©z9Enable the use of automatic spinners as context managers.N)rNÚstartr4s r!r9zAutomaticSpinner.__enter__#s€à �‰×ÑÕr1Ncól—|jj«|jj«yrP)rKÚsetrNÚjoinr;s r!r?zAutomaticSpinner.__exit__'s$€à ×Ñ×ÑÔ!Ø �‰×ÑÕr1cóV— |jr t«nd}t|j|¬«5}|jj «s;|j «|j«|jj «sŒ;ddd«y#1swYyxYw#t$rYywxYw)N)rr) rHrr rrKÚis_setr0r3ÚKeyboardInterrupt)rrÚspinners r!rMzAutomaticSpinner._target,s€ð Ø#Ÿ~š~”E”G°4ˆEܘtŸz™z°Õ7¸7Ø×-Ñ-×4Ñ4Ô6Ø—L‘L”NØ—M‘M”Oð×-Ñ-×4Ñ4Õ6÷8×7Ñ7ûô!ò ñ ð ús/‚/B±ABÂBÂBÂBÂB B(Â'B()Tr@)rArBrCrDr"r9r?rMr8r1r!rrÿs„ñó* Gò óó r1r)rDrIrr(Ú humanfriendlyrÚhumanfriendly.deprecationrÚhumanfriendly.terminalrÚ__all__rrÚobjectr rr8r1r!Úr^sVðñUópÛ Û õ Ý5Ý2ð H€â €ØQàÐØlôJˆfôJôZ7�võ7r1