manrajgrover / halo

💫 Beautiful spinners for terminal, IPython and Jupyter
MIT License
2.86k stars 148 forks source link

Suggestion: Allow text to change when using decorate pattern. #157

Open liudonghua123 opened 3 years ago

liudonghua123 commented 3 years ago

Description

I like the decorate pattern, but I found the text is always constant. I hope the text could change using some format strings.

I also write a simple version, it seems work as expected. Maybe the exist Halo.__call__ could be refactor.

from halo import Halo
from time import sleep

from functools import wraps
class HaloExtend:
  def __init__(self, text, spinner='dots', **kwargs):
    self.text = text
    self.spinner = spinner
    self.kwargs = kwargs

  def __call__(self, func):
    @wraps(func)
    def wrapped(*args, **kwargs):
      halo = Halo(text=self.text.format(*args, **kwargs), spinner=self.spinner)
      halo.start()
      func(*args, **kwargs)
      halo.succeed()
    return wrapped

@HaloExtend(text='Loading {task}', spinner='line')
def run_task(task):
  sleep(3)

tasks = ['breakfest', 'launch', 'dinner']

for task in tasks:
  run_task(task=task)
liudonghua123 commented 3 years ago

I tried to refactor the above code using with/__enter__/__exit__ form, however I failed because the execution flow is __call__ (only once) -> __enter__ -> wrapped -> __exit__. And in the __enter__ I couldn't got args/kwargs, so the text could not substitute.

some helpful links: https://www.geeksforgeeks.org/with-statement-in-python/ https://www.geeksforgeeks.org/python-functools-wraps-function/