Skip to content

Commit

Permalink
Merging
Browse files Browse the repository at this point in the history
  • Loading branch information
wolph committed Dec 8, 2023
2 parents 4f1efba + c66f275 commit 10469d0
Show file tree
Hide file tree
Showing 18 changed files with 162 additions and 115 deletions.
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,4 @@


# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'http://docs.python.org/': None}
intersphinx_mapping = {'python': ('https://docs.python.org/3', None)}
42 changes: 23 additions & 19 deletions progressbar/bar.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@

from python_utils import converters, types

import progressbar.terminal
import progressbar.env
import progressbar.terminal
import progressbar.terminal.stream

from . import (
Expand All @@ -30,8 +30,9 @@

# float also accepts integers and longs but we don't want an explicit union
# due to type checking complexity
T = float
NumberT = float

T = types.TypeVar('T')

class ProgressBarMixinBase(abc.ABC):
_started = False
Expand Down Expand Up @@ -76,14 +77,14 @@ class ProgressBarMixinBase(abc.ABC):
next_update: int = 0

#: Current progress (min_value <= value <= max_value)
value: T
value: NumberT
#: Previous progress value
previous_value: types.Optional[T]
previous_value: types.Optional[NumberT]
#: The minimum/start value for the progress bar
min_value: T
min_value: NumberT
#: Maximum (and final) value. Beyond this value an error will be raised
#: unless the `max_error` parameter is `False`.
max_value: T | types.Type[base.UnknownLength]
max_value: NumberT | types.Type[base.UnknownLength]
#: The time the progressbar reached `max_value` or when `finish()` was
#: called.
end_time: types.Optional[datetime]
Expand Down Expand Up @@ -156,7 +157,7 @@ def __repr__(self):

class DefaultFdMixin(ProgressBarMixinBase):
# The file descriptor to write to. Defaults to `sys.stderr`
fd: base.IO = sys.stderr
fd: base.TextIO = sys.stderr
#: Set the terminal to be ANSI compatible. If a terminal is ANSI
#: compatible we will automatically enable `colors` and disable
#: `line_breaks`.
Expand All @@ -177,11 +178,13 @@ class DefaultFdMixin(ProgressBarMixinBase):
#: For true (24 bit/16M) color support you can use `COLORTERM=truecolor`.
#: For 256 color support you can use `TERM=xterm-256color`.
#: For 16 colorsupport you can use `TERM=xterm`.
enable_colors: progressbar.env.ColorSupport | bool | None = progressbar.env.COLOR_SUPPORT
enable_colors: progressbar.env.ColorSupport | bool | None = (
progressbar.env.COLOR_SUPPORT
)

def __init__(
self,
fd: base.IO = sys.stderr,
fd: base.IO[str] = sys.stderr,
is_terminal: bool | None = None,
line_breaks: bool | None = None,
enable_colors: progressbar.env.ColorSupport | None = None,
Expand All @@ -202,7 +205,7 @@ def __init__(

super().__init__(**kwargs)

def _apply_line_offset(self, fd: base.IO, line_offset: int) -> base.IO:
def _apply_line_offset(self, fd: base.IO[T], line_offset: int) -> base.IO[T]:
if line_offset:
return progressbar.terminal.stream.LineOffsetStreamWrapper(
line_offset,
Expand All @@ -213,7 +216,7 @@ def _apply_line_offset(self, fd: base.IO, line_offset: int) -> base.IO:

def _determine_is_terminal(
self,
fd: base.IO,
fd: base.TextIO,
is_terminal: bool | None,
) -> bool:
if is_terminal is not None:
Expand Down Expand Up @@ -257,8 +260,7 @@ def _determine_enable_colors(
enable_colors = progressbar.env.ColorSupport.XTERM_256
elif enable_colors is False:
enable_colors = progressbar.env.ColorSupport.NONE
elif not isinstance(enable_colors,
progressbar.env.ColorSupport):
elif not isinstance(enable_colors, progressbar.env.ColorSupport):
raise ValueError(f'Invalid color support value: {enable_colors}')

return enable_colors
Expand All @@ -281,7 +283,9 @@ def update(self, *args: types.Any, **kwargs: types.Any) -> None:
self.fd.write(line.encode('ascii', 'replace'))

def finish(
self, *args: types.Any, **kwargs: types.Any,
self,
*args: types.Any,
**kwargs: types.Any,
) -> None: # pragma: no cover
if self._finished:
return
Expand Down Expand Up @@ -516,13 +520,13 @@ class ProgressBar(

def __init__(
self,
min_value: T = 0,
max_value: T | types.Type[base.UnknownLength] | None = None,
min_value: NumberT = 0,
max_value: NumberT | types.Type[base.UnknownLength] | None = None,
widgets: types.Optional[
types.Sequence[widgets_module.WidgetBase | str]
] = None,
left_justify: bool = True,
initial_value: T = 0,
initial_value: NumberT = 0,
poll_interval: types.Optional[float] = None,
widget_kwargs: types.Optional[types.Dict[str, types.Any]] = None,
custom_len: types.Callable[[str], int] = utils.len_color,
Expand Down Expand Up @@ -555,7 +559,7 @@ def __init__(
)
poll_interval = kwargs.get('poll')

if max_value and min_value > types.cast(T, max_value):
if max_value and min_value > types.cast(NumberT, max_value):
raise ValueError(
'Max value needs to be bigger than the min value',
)
Expand Down Expand Up @@ -996,7 +1000,7 @@ def _verify_max_value(self):
):
raise ValueError('max_value out of range, got %r' % self.max_value)

def _calculate_poll_interval(self):
def _calculate_poll_interval(self) -> None:
self.num_intervals = max(100, self.term_width)
for widget in self.widgets:
interval: int | float | None = utils.deltas_to_seconds(
Expand Down
8 changes: 4 additions & 4 deletions progressbar/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def from_env(cls):
)

if os.environ.get('JUPYTER_COLUMNS') or os.environ.get(
'JUPYTER_LINES',
'JUPYTER_LINES',
):
# Jupyter notebook always supports true color.
return cls.XTERM_TRUECOLOR
Expand All @@ -88,8 +88,8 @@ def from_env(cls):


def is_ansi_terminal(
fd: base.IO,
is_terminal: bool | None = None,
fd: base.IO,
is_terminal: bool | None = None,
) -> bool: # pragma: no cover
if is_terminal is None:
# Jupyter Notebooks define this variable and support progress bars
Expand All @@ -98,7 +98,7 @@ def is_ansi_terminal(
# This works for newer versions of pycharm only. With older versions
# there is no way to check.
elif os.environ.get('PYCHARM_HOSTED') == '1' and not os.environ.get(
'PYTEST_CURRENT_TEST',
'PYTEST_CURRENT_TEST',
):
is_terminal = True

Expand Down
87 changes: 46 additions & 41 deletions progressbar/multi.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,22 @@ class MultiBar(typing.Dict[str, bar.ProgressBar]):
_thread_closed: threading.Event = threading.Event()

def __init__(
self,
bars: typing.Iterable[tuple[str, bar.ProgressBar]] | None = None,
fd=sys.stderr,
prepend_label: bool = True,
append_label: bool = False,
label_format='{label:20.20} ',
initial_format: str | None = '{label:20.20} Not yet started',
finished_format: str | None = None,
update_interval: float = 1 / 60.0, # 60fps
show_initial: bool = True,
show_finished: bool = True,
remove_finished: timedelta | float = timedelta(seconds=3600),
sort_key: str | SortKey = SortKey.CREATED,
sort_reverse: bool = True,
sort_keyfunc: SortKeyFunc | None = None,
**progressbar_kwargs,
self,
bars: typing.Iterable[tuple[str, bar.ProgressBar]] | None = None,
fd: typing.TextIO = sys.stderr,
prepend_label: bool = True,
append_label: bool = False,
label_format='{label:20.20} ',
initial_format: str | None = '{label:20.20} Not yet started',
finished_format: str | None = None,
update_interval: float = 1 / 60.0, # 60fps
show_initial: bool = True,
show_finished: bool = True,
remove_finished: timedelta | float = timedelta(seconds=3600),
sort_key: str | SortKey = SortKey.CREATED,
sort_reverse: bool = True,
sort_keyfunc: SortKeyFunc | None = None,
**progressbar_kwargs,
):
self.fd = fd

Expand Down Expand Up @@ -130,7 +130,7 @@ def __setitem__(self, key: str, bar: bar.ProgressBar):
bar.fd = stream.LastLineStream(self.fd)
bar.paused = True
# Essentially `bar.print = self.print`, but `mypy` doesn't like that
bar.print = self.print
bar.print = self.print # type: ignore

# Just in case someone is using a progressbar with a custom
# constructor and forgot to call the super constructor
Expand Down Expand Up @@ -186,7 +186,9 @@ def render(self, flush: bool = True, force: bool = False):
with self._print_lock:
# Clear the previous output if progressbars have been removed
for i in range(len(output), len(self._previous_output)):
self._buffer.write(terminal.clear_line(i + 1)) # pragma: no cover
self._buffer.write(
terminal.clear_line(i + 1),
) # pragma: no cover

# Add empty lines to the end of the output if progressbars have
# been added
Expand All @@ -195,13 +197,13 @@ def render(self, flush: bool = True, force: bool = False):
self._buffer.write('\n')

for i, (previous, current) in enumerate(
itertools.zip_longest(
self._previous_output,
output,
fillvalue='',
),
itertools.zip_longest(
self._previous_output,
output,
fillvalue='',
),
):
if previous != current or force: # pragma: no branch
if previous != current or force: # pragma: no branch
self.print(
'\r' + current.strip(),
offset=i + 1,
Expand All @@ -212,11 +214,14 @@ def render(self, flush: bool = True, force: bool = False):

self._previous_output = output

if flush: # pragma: no branch
if flush: # pragma: no branch
self.flush()

def _render_bar(
self, bar_: bar.ProgressBar, now, expired,
self,
bar_: bar.ProgressBar,
now,
expired,
) -> typing.Iterable[str]:
def update(force=True, write=True):
self._label_bar(bar_)
Expand All @@ -237,21 +242,21 @@ def update(force=True, write=True):
yield self.initial_format.format(label=bar_.label)

def _render_finished_bar(
self,
bar_: bar.ProgressBar,
now,
expired,
update,
self,
bar_: bar.ProgressBar,
now,
expired,
update,
) -> typing.Iterable[str]:
if bar_ not in self._finished_at:
self._finished_at[bar_] = now
# Force update to get the finished format
update(write=False)

if (
self.remove_finished
and expired is not None
and expired >= self._finished_at[bar_]
self.remove_finished
and expired is not None
and expired >= self._finished_at[bar_]
):
del self[bar_.label]
return
Expand All @@ -266,13 +271,13 @@ def _render_finished_bar(
yield self.finished_format.format(label=bar_.label)

def print(
self,
*args,
end='\n',
offset=None,
flush=True,
clear=True,
**kwargs,
self,
*args,
end='\n',
offset=None,
flush=True,
clear=True,
**kwargs,
):
'''
Print to the progressbar stream without overwriting the progressbars.
Expand Down
2 changes: 1 addition & 1 deletion progressbar/terminal/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from __future__ import annotations

from .base import * # noqa F403
from .stream import TextIOOutputWrapper, LineOffsetStreamWrapper, LastLineStream
from .stream import * # noqa F403
23 changes: 18 additions & 5 deletions progressbar/terminal/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@

from python_utils import converters, types

from .. import base as pbase, env
from .. import (
base as pbase,
env,
)
from .os_specific import getch

ESC = '\x1B'
Expand Down Expand Up @@ -218,14 +221,19 @@ class HSL(collections.namedtuple('HSL', ['hue', 'saturation', 'lightness'])):
and 100(%).
'''

__slots__ = ()

@classmethod
def from_rgb(cls, rgb: RGB) -> HSL:
'''
Convert a 0-255 RGB color to a 0-255 HLS color.
'''
hls = colorsys.rgb_to_hls(rgb.red/255,rgb.green/255,rgb.blue/255)
hls = colorsys.rgb_to_hls(
rgb.red / 255,
rgb.green / 255,
rgb.blue / 255,
)
return cls(
round(hls[0] * 360),
round(hls[2] * 100),
Expand Down Expand Up @@ -288,12 +296,16 @@ def underline(self):

@property
def ansi(self) -> types.Optional[str]:
if env.COLOR_SUPPORT is env.ColorSupport.XTERM_TRUECOLOR: # pragma: no branch
if (
env.COLOR_SUPPORT is env.ColorSupport.XTERM_TRUECOLOR
): # pragma: no branch
return f'2;{self.rgb.red};{self.rgb.green};{self.rgb.blue}'

if self.xterm: # pragma: no branch
color = self.xterm
elif env.COLOR_SUPPORT is env.ColorSupport.XTERM_256: # pragma: no branch
elif (
env.COLOR_SUPPORT is env.ColorSupport.XTERM_256
): # pragma: no branch
color = self.rgb.to_ansi_256
elif env.COLOR_SUPPORT is env.ColorSupport.XTERM: # pragma: no branch
color = self.rgb.to_ansi_16
Expand Down Expand Up @@ -395,7 +407,8 @@ def get_color(self, value: float) -> Color:
elif self.interpolate:
if max_color_idx > 1:
index = round(
converters.remap(value, 0, 1, 0, max_color_idx - 1))
converters.remap(value, 0, 1, 0, max_color_idx - 1),
)
else:
index = 0

Expand Down
Loading

0 comments on commit 10469d0

Please sign in to comment.