From c2b7b02c0b5bb132eb3a4110f53a99a723aabd84 Mon Sep 17 00:00:00 2001 From: Paulo Costa Date: Thu, 19 Sep 2019 02:44:48 -0300 Subject: [PATCH] Avoid flickering StdRedirectMixin makes the bar erase itself before writing the new update. This works fine and is invisible most of the time. Most of the time -- If the refreshes are very fast, flickering becomes visible This PR first checks if there is something buffered to be written in stdout/stderr, and doesn't erase the current line otherwise --- examples.py | 13 +++++++++++++ progressbar/bar.py | 7 ++++--- progressbar/utils.py | 12 ++++++++++++ 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/examples.py b/examples.py index 05099efc..cf8b7e51 100644 --- a/examples.py +++ b/examples.py @@ -31,6 +31,19 @@ def wrapped(): return wrapped +@example +def fast_example(): + ''' Updates bar really quickly to cause flickering ''' + with progressbar.ProgressBar(max_value=1, widgets=[progressbar.Bar()]) as bar: + start = time.time() + while True: + elapsed = time.time() - start + if elapsed > 1: + break + else: + bar.update(elapsed, force=True) + + @example def shortcut_example(): for i in progressbar.progressbar(range(10)): diff --git a/progressbar/bar.py b/progressbar/bar.py index fe945282..1cfcf4af 100644 --- a/progressbar/bar.py +++ b/progressbar/bar.py @@ -180,9 +180,10 @@ def start(self, *args, **kwargs): DefaultFdMixin.start(self, *args, **kwargs) def update(self, value=None): - if not self.line_breaks: - self.fd.write('\r' + ' ' * self.term_width + '\r') - utils.streams.flush() + if utils.streams.needs_flush(): + if not self.line_breaks: + self.fd.write('\r' + ' ' * self.term_width + '\r') + utils.streams.flush() DefaultFdMixin.update(self, value=value) def finish(self, end='\n'): diff --git a/progressbar/utils.py b/progressbar/utils.py index aba7477c..aa130cab 100644 --- a/progressbar/utils.py +++ b/progressbar/utils.py @@ -135,6 +135,9 @@ def write(self, value): def flush(self): self.buffer.flush() + def _needs_flush(self): + return bool(self.buffer.getvalue()) + def _flush(self): value = self.buffer.getvalue() if value: @@ -249,6 +252,15 @@ def unwrap_stderr(self): sys.stderr = self.original_stderr self.wrapped_stderr = 0 + def needs_flush(self): + if self.wrapped_stdout: + if self.stdout._needs_flush(): + return True + if self.wrapped_stderr: + if self.stderr._needs_flush(): + return True + return False + def flush(self): if self.wrapped_stdout: # pragma: no branch try: