from __future__ import absolute_import, print_function, unicode_literals import sys import threading import halo.cursor as cursor from halo import Halo from halo._utils import colored_frame, decode_utf_8_text class HaloNotebook(Halo): def __init__( self, text="", color="cyan", text_color=None, spinner=None, placement="left", animation=None, interval=-1, enabled=True, stream=sys.stdout, ): super(HaloNotebook, self).__init__( text=text, color=color, text_color=text_color, spinner=spinner, placement=placement, animation=animation, interval=interval, enabled=enabled, stream=stream, ) self.output = self._make_output_widget() def _make_output_widget(self): from ipywidgets.widgets import Output return Output() # TODO: using property and setter def _output(self, text=""): return ({"name": "stdout", "output_type": "stream", "text": text},) def clear(self): if not self.enabled: return self with self.output: self.output.outputs += self._output("\r") self.output.outputs += self._output(self.CLEAR_LINE) self.output.outputs = self._output() return self def _render_frame(self): frame = self.frame() output = "\r{}".format(frame) with self.output: self.output.outputs += self._output(output) def start(self, text=None): if text is not None: self.text = text if not self.enabled or self._spinner_id is not None: return self if self._stream.isatty(): cursor.hide() self.output = self._make_output_widget() from IPython.display import display display(self.output) self._stop_spinner = threading.Event() self._spinner_thread = threading.Thread(target=self.render) self._spinner_thread.setDaemon(True) self._render_frame() self._spinner_id = self._spinner_thread.name self._spinner_thread.start() return self def stop_and_persist(self, symbol=" ", text=None): """Stops the spinner and persists the final frame to be shown. Parameters ---------- symbol : str, optional Symbol to be shown in final frame text: str, optional Text to be shown in final frame Returns ------- self """ if not self.enabled: return self symbol = decode_utf_8_text(symbol) if text is not None: text = decode_utf_8_text(text) else: text = self._text["original"] text = text.strip() if self._text_color: text = colored_frame(text, self._text_color) self.stop() output = "\r{} {}\n".format( *[(text, symbol) if self._placement == "right" else (symbol, text)][0] ) with self.output: self.output.outputs = self._output(output)