Skip to content

Commit

Permalink
Merge branch 'release/v3.47.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
wolph committed Sep 30, 2019
2 parents 31a871a + 5025ed3 commit f57ab37
Show file tree
Hide file tree
Showing 13 changed files with 316 additions and 59 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ source =
omit =
*/mock/*
*/nose/*
.tox/*
[paths]
source =
progressbar
Expand Down
6 changes: 3 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ python:
- '3.7'
- pypy
install:
- pip install .
- pip install -r tests/requirements.txt
before_script: flake8 progressbar tests
- pip install -U .
- pip install -U -r tests/requirements.txt
before_script: flake8 progressbar tests examples
script:
- python setup.py test
- python examples.py
Expand Down
84 changes: 77 additions & 7 deletions examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ def example(fn):
'''Wrap the examples so they generate readable output'''

@functools.wraps(fn)
def wrapped():
def wrapped(*args, **kwargs):
try:
sys.stdout.write('Running: %s\n' % fn.__name__)
fn()
fn(*args, **kwargs)
sys.stdout.write('\n')
except KeyboardInterrupt:
sys.stdout.write('\nSkipping example.\n\n')
Expand All @@ -31,6 +31,14 @@ def wrapped():
return wrapped


@example
def fast_example():
''' Updates bar really quickly to cause flickering '''
with progressbar.ProgressBar(widgets=[progressbar.Bar()]) as bar:
for i in range(100):
bar.update(int(i / 10), force=True)


@example
def shortcut_example():
for i in progressbar.progressbar(range(10)):
Expand Down Expand Up @@ -73,7 +81,8 @@ def basic_widget_example():

@example
def color_bar_example():
widgets = ['\x1b[33mColorful example\x1b[39m', progressbar.Percentage(), progressbar.Bar(marker='\x1b[32m#\x1b[39m')]
widgets = ['\x1b[33mColorful example\x1b[39m', progressbar.Percentage(),
progressbar.Bar(marker='\x1b[32m#\x1b[39m')]
bar = progressbar.ProgressBar(widgets=widgets, max_value=10).start()
for i in range(10):
# do something
Expand All @@ -82,6 +91,66 @@ def color_bar_example():
bar.finish()


@example
def multi_range_bar_example():
markers = [
'\x1b[32m█\x1b[39m', # Done
'\x1b[33m#\x1b[39m', # Processing
'\x1b[31m.\x1b[39m', # Scheduling
' ' # Not started
]
widgets = [progressbar.MultiRangeBar("amounts", markers=markers)]
amounts = [0] * (len(markers) - 1) + [25]

with progressbar.ProgressBar(widgets=widgets, max_value=10).start() as bar:
while True:
incomplete_items = [
idx
for idx, amount in enumerate(amounts)
for i in range(amount)
if idx != 0
]
if not incomplete_items:
break
which = random.choice(incomplete_items)
amounts[which] -= 1
amounts[which - 1] += 1

bar.update(amounts=amounts, force=True)
time.sleep(0.02)


@example
def multi_progress_bar_example(left=True):
jobs = [
# Each job takes between 1 and 10 steps to complete
[0, random.randint(1, 10)]
for i in range(25) # 25 jobs total
]

widgets = [
progressbar.Percentage(),
' ', progressbar.MultiProgressBar('jobs', fill_left=left),
]

max_value = sum([total for progress, total in jobs])
with progressbar.ProgressBar(widgets=widgets, max_value=max_value) as bar:
while True:
incomplete_jobs = [
idx
for idx, (progress, total) in enumerate(jobs)
if progress < total
]
if not incomplete_jobs:
break
which = random.choice(incomplete_jobs)
jobs[which][0] += 1
progress = sum([progress for progress, total in jobs])

bar.update(progress, jobs=jobs, force=True)
time.sleep(0.02)


@example
def file_transfer_example():
widgets = [
Expand Down Expand Up @@ -386,9 +455,9 @@ def increment_bar_with_output_redirection():
' ', progressbar.ETA(),
' ', progressbar.FileTransferSpeed(),
]
bar = progressbar.ProgressBar(widgets=widgets, max_value=1000,
bar = progressbar.ProgressBar(widgets=widgets, max_value=100,
redirect_stdout=True).start()
for i in range(100):
for i in range(10):
# do something
time.sleep(0.01)
bar += 10
Expand Down Expand Up @@ -507,11 +576,12 @@ def user_variables():
with progressbar.ProgressBar(
prefix='{variables.task} >> {variables.subtask}',
variables={'task': '--', 'subtask': '--'},
max_value=10*num_subtasks) as bar:
max_value=10 * num_subtasks) as bar:
for tasks_name, subtasks in tasks.items():
for subtask_name in subtasks:
for i in range(10):
bar.update(bar.value+1, task=tasks_name, subtask=subtask_name)
bar.update(bar.value + 1, task=tasks_name,
subtask=subtask_name)
time.sleep(0.1)


Expand Down
2 changes: 1 addition & 1 deletion progressbar/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
long running operations.
'''.strip().split())
__email__ = '[email protected]'
__version__ = '3.46.1'
__version__ = '3.47.0'
__license__ = 'BSD'
__copyright__ = 'Copyright 2015 Rick van Hattem (Wolph)'
__url__ = 'https://github.com/WoLpH/python-progressbar'
6 changes: 6 additions & 0 deletions progressbar/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
ReverseBar,
BouncingBar,
RotatingMarker,
VariableMixin,
MultiRangeBar,
MultiProgressBar,
Variable,
DynamicMessage,
FormatCustomText,
Expand Down Expand Up @@ -66,6 +69,9 @@
'ProgressBar',
'DataTransferBar',
'RotatingMarker',
'VariableMixin',
'MultiRangeBar',
'MultiProgressBar',
'Variable',
'DynamicMessage',
'FormatCustomText',
Expand Down
24 changes: 9 additions & 15 deletions progressbar/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,7 @@ def __init__(self, fd=sys.stderr, is_terminal=None, line_breaks=None,
self.fd = fd

# Check if this is an interactive terminal
if is_terminal is None:
is_terminal = utils.env_flag('PROGRESSBAR_IS_TERMINAL', None)
if is_terminal is None: # pragma: no cover
try:
is_terminal = fd.isatty()
except Exception:
is_terminal = False
self.is_terminal = is_terminal
self.is_terminal = is_terminal = utils.is_terminal(fd, is_terminal)

# Check if it should overwrite the current line (suitable for
# iteractive terminals) or write line breaks (suitable for log files)
Expand Down Expand Up @@ -180,8 +173,9 @@ def start(self, *args, **kwargs):
DefaultFdMixin.start(self, *args, **kwargs)

def update(self, value=None):
if not self.line_breaks:
if not self.line_breaks and utils.streams.needs_clear():
self.fd.write('\r' + ' ' * self.term_width + '\r')

utils.streams.flush()
DefaultFdMixin.update(self, value=value)

Expand Down Expand Up @@ -228,15 +222,15 @@ class ProgressBar(StdRedirectMixin, ResizableMixin, ProgressBarBase):
prefix (str): Prefix the progressbar with the given string
suffix (str): Prefix the progressbar with the given string
variables (dict): User-defined variables variables that can be used
from a label using `format="{variables.my_var}"`. These values can
be updated using `bar.update(my_var="newValue")` This can also be
used to set initial values for `Variable`s widgets
from a label using `format='{variables.my_var}'`. These values can
be updated using `bar.update(my_var='newValue')` This can also be
used to set initial values for variables' widgets
A common way of using it is like:
>>> progress = ProgressBar().start()
>>> for i in range(100):
... progress.update(i+1)
... progress.update(i + 1)
... # do something
...
>>> progress.finish()
Expand Down Expand Up @@ -342,7 +336,7 @@ def __init__(self, min_value=0, max_value=None, widgets=None,
# A dictionary of names that can be used by Variable and FormatWidget
self.variables = utils.AttributeDict(variables or {})
for widget in (self.widgets or []):
if isinstance(widget, widgets_module.Variable):
if isinstance(widget, widgets_module.VariableMixin):
if widget.name not in self.variables:
self.variables[widget.name] = None

Expand Down Expand Up @@ -734,7 +728,7 @@ def start(self, max_value=None, init=True):
self.next_update = 0

if self.max_value is not base.UnknownLength and self.max_value < 0:
raise ValueError('Value out of range')
raise ValueError('max_value out of range, got %r' % self.max_value)

self.start_time = self.last_update_time = datetime.now()
self._last_update_timer = timeit.default_timer()
Expand Down
24 changes: 24 additions & 0 deletions progressbar/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,22 @@
assert epoch


def is_terminal(fd, is_terminal=None):
if is_terminal is None:
if 'JPY_PARENT_PID' in os.environ:
is_terminal = True
else:
is_terminal = env_flag('PROGRESSBAR_IS_TERMINAL', None)

if is_terminal is None: # pragma: no cover
try:
is_terminal = fd.isatty()
except Exception:
is_terminal = False

return is_terminal


def deltas_to_seconds(*deltas, **kwargs): # default=ValueError):
'''
Convert timedeltas and seconds as int to seconds as float while coalescing
Expand Down Expand Up @@ -122,17 +138,20 @@ def __init__(self, target, capturing=False, listeners=set()):
self.target = target
self.capturing = capturing
self.listeners = listeners
self.needs_clear = False

def write(self, value):
if self.capturing:
self.buffer.write(value)
if '\n' in value:
self.needs_clear = True
for listener in self.listeners: # pragma: no branch
listener.update()
else:
self.target.write(value)

def flush(self):
self.needs_clear = False
self.buffer.flush()

def _flush(self):
Expand Down Expand Up @@ -249,6 +268,11 @@ def unwrap_stderr(self):
sys.stderr = self.original_stderr
self.wrapped_stderr = 0

def needs_clear(self): # pragma: no cover
stdout_needs_clear = getattr(self.stdout, 'needs_clear', False)
stderr_needs_clear = getattr(self.stderr, 'needs_clear', False)
return stderr_needs_clear or stdout_needs_clear

def flush(self):
if self.wrapped_stdout: # pragma: no branch
try:
Expand Down
Loading

0 comments on commit f57ab37

Please sign in to comment.