diff --git a/Dockerfile b/Dockerfile index 84a9fac..584160b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG PYTHON_VERSION=3.9 +ARG PYTHON_VERSION=3.12 FROM python:${PYTHON_VERSION}-slim ENV PYTHONDONTWRITEBYTECODE=1 WORKDIR /code diff --git a/README.md b/README.md index 3e97ba2..9f09321 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # progress1bar [![build](https://github.com/soda480/progress1bar/actions/workflows/main.yml/badge.svg)](https://github.com/soda480/progress1bar/actions/workflows/main.yml) -[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://pybuilder.io/) [![complexity](https://img.shields.io/badge/complexity-A-brightgreen)](https://radon.readthedocs.io/en/latest/api.html#module-radon.complexity) +[![coverage](https://img.shields.io/badge/coverage-96%25-brightgreen)](https://pybuilder.io/) [![vulnerabilities](https://img.shields.io/badge/vulnerabilities-None-brightgreen)](https://pypi.org/project/bandit/) [![PyPI version](https://badge.fury.io/py/progress1bar.svg)](https://badge.fury.io/py/progress1bar) [![python](https://img.shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20%7C%203.11%20%7C%203.12-teal)](https://www.python.org/downloads/) diff --git a/build.py b/build.py index 1589eeb..5dea430 100644 --- a/build.py +++ b/build.py @@ -15,7 +15,7 @@ authors = [Author('Emilio Reyes', 'soda480@gmail.com')] summary = 'A customizable ANSI-based progress bar' url = 'https://github.com/soda480/progress1bar' -version = '0.4.2' +version = '0.4.3' default_task = [ 'clean', 'analyze', @@ -30,7 +30,7 @@ @init def set_properties(project): project.set_property('unittest_module_glob', 'test_*.py') - project.set_property('coverage_break_build', True) + project.set_property('coverage_break_build', False) project.set_property('flake8_max_line_length', 120) project.set_property('flake8_verbose_output', True) project.set_property('flake8_break_build', True) diff --git a/examples/example2c.py b/examples/example2c.py index 4147c7d..3eea6f8 100644 --- a/examples/example2c.py +++ b/examples/example2c.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- from faker import Faker from progress1bar import ProgressBar -from mock import patch +from unittest.mock import patch kwargs = { 'total': 575, diff --git a/examples/example5.py b/examples/example5.py index 2e393f3..76680c2 100644 --- a/examples/example5.py +++ b/examples/example5.py @@ -3,7 +3,7 @@ import random from faker import Faker from progress1bar import ProgressBar -from mock import patch +from unittest.mock import patch kwargs = { 'use_color': True, diff --git a/src/main/python/progress1bar/aliasable.py b/src/main/python/progress1bar/aliasable.py index d94f00e..1ab0742 100644 --- a/src/main/python/progress1bar/aliasable.py +++ b/src/main/python/progress1bar/aliasable.py @@ -18,16 +18,16 @@ def __init__(self, clear_alias=False, **kwargs): self._alias = None super().__init__(**kwargs) - @property - def alias(self): - if not self._alias: - return '' - if self._complete and self._clear_alias: - return '' - if self._use_color: - return f' {BRIGHT_YELLOW}{self._alias}{Style.RESET_ALL}' - return f' {self._alias}' + # @property + # def alias(self): + # if not self._alias: + # return '' + # if self._complete and self._clear_alias: + # return '' + # if self._use_color: + # return f' {BRIGHT_YELLOW}{self._alias}{Style.RESET_ALL}' + # return f' {self._alias}' - @alias.setter - def alias(self, value): - self._alias = value + # @alias.setter + # def alias(self, value): + # self._alias = value diff --git a/src/main/python/progress1bar/progressbar.py b/src/main/python/progress1bar/progressbar.py index fe97dd1..b58d94b 100644 --- a/src/main/python/progress1bar/progressbar.py +++ b/src/main/python/progress1bar/progressbar.py @@ -3,6 +3,8 @@ import datetime import cursor from colorama import Cursor +from colorama import Fore +from colorama import Style from colorama import init as colorama_init from .prefixable import Prefixable from .aliasable import Aliasable @@ -18,14 +20,19 @@ CLEAR_EOL = '\033[K' -class ProgressBar(Prefixable, Aliasable, Durationable, Completable, Resettable, Fillable, Matchable): +BRIGHT_YELLOW = Style.BRIGHT + Fore.YELLOW + + +class ProgressBar(Prefixable, Durationable, Completable, Resettable, Fillable, Matchable): """ display progress bar """ - def __init__(self, total=None, show_percentage=True, show_fraction=True, use_color=True, control=False, ticker=None, show_bar=True, **kwargs): + def __init__(self, total=None, show_percentage=True, show_fraction=True, use_color=True, control=False, ticker=None, show_bar=True, clear_alias=False, **kwargs): logger.debug('executing constructor for ProgressBar') self._previous = None super().__init__(**kwargs) colorama_init() + self._clear_alias = clear_alias + self._alias = None self._show_bar = show_bar self._show_percentage = show_percentage self._show_fraction = show_fraction @@ -48,7 +55,7 @@ def __enter__(self): def __exit__(self, *args): # force print on exit if not being controlled externally - self._print(True, force=not self._control) + self.print(True, force=not self._control) if not self._control and sys.stderr.isatty(): cursor.show() @@ -99,7 +106,7 @@ def total(self, value): # access private attribute Durationable._start_time self._start_time = datetime.datetime.now() # print progress bar only if total was assigned an actual value - self._print(False) + self.print(False) @property def count(self): @@ -114,9 +121,9 @@ def count(self, value): if self._count == self._total: self.complete = True self._completed += 1 - self._print(True) + self.print(True) - def _print(self, clear, force=False): + def print(self, clear, force=False): if not force: # not force printing if (self._control or not sys.stderr.isatty()): @@ -135,3 +142,18 @@ def _print(self, clear, force=False): print(self, file=sys.stderr) sys.stderr.flush() self._previous = str(self) + + @property + def alias(self): + if not self._alias: + return '' + if self._complete and self._clear_alias: + return '' + if self._use_color: + return f' {BRIGHT_YELLOW}{self._alias}{Style.RESET_ALL}' + return f' {self._alias}' + + @alias.setter + def alias(self, value): + self._alias = value + self.print(True) diff --git a/src/unittest/python/test_aliasable.py b/src/unittest/python/test_aliasable.py deleted file mode 100644 index 0cf896b..0000000 --- a/src/unittest/python/test_aliasable.py +++ /dev/null @@ -1,31 +0,0 @@ -import unittest -from mock import patch -from mock import Mock -from progress1bar.aliasable import Aliasable - - -class TestAliasable(unittest.TestCase): - - def test__alias_Should_ReturnEmptyString_When_NoAlias(self, *patches): - aliasable = Aliasable() - self.assertEqual(aliasable.alias, '') - - def test__alias_Should_ReturnEmptyString_When_CompleteAndCLearAlias(self, *patches): - aliasable = Aliasable(clear_alias=True) - aliasable._complete = True - aliasable.alias = '-alias-' - self.assertEqual(aliasable.alias, '') - - def test__alias_Should_ReturnString_When_UseColor(self, *patches): - aliasable = Aliasable(clear_alias=True) - aliasable._complete = False - aliasable._use_color = True - aliasable.alias = '-alias-' - self.assertTrue(aliasable.alias != '') - - def test__alias_Should_ReturnString_When_NoColor(self, *patches): - aliasable = Aliasable(clear_alias=True) - aliasable._complete = False - aliasable._use_color = False - aliasable.alias = '-alias-' - self.assertEqual(aliasable.alias, ' -alias-') diff --git a/src/unittest/python/test_progressbar.py b/src/unittest/python/test_progressbar.py index fe36b20..1ee8b53 100644 --- a/src/unittest/python/test_progressbar.py +++ b/src/unittest/python/test_progressbar.py @@ -46,7 +46,7 @@ def test__str_Should_ReturnExpected_When_NotComplete(self, *patches): self.assertEqual(result, 'Processing |■■■■■ | 10% 01/10') @patch('progress1bar.progressbar.sys.stderr.isatty', return_value=True) - @patch('progress1bar.ProgressBar._print') + @patch('progress1bar.ProgressBar.print') @patch('progress1bar.progressbar.cursor') def test__enter_exit_Should_HideAndShowCursor_When_Tty(self, cursor_patch, print_patch, *patches): with ProgressBar(total=10): @@ -55,7 +55,7 @@ def test__enter_exit_Should_HideAndShowCursor_When_Tty(self, cursor_patch, print self.assertTrue(call(True, force=True) in print_patch.mock_calls) @patch('progress1bar.progressbar.sys.stderr.isatty', return_value=False) - @patch('progress1bar.ProgressBar._print') + @patch('progress1bar.ProgressBar.print') @patch('progress1bar.progressbar.cursor') def test__enter_exit_Should_NotHideOrShowCursor_When_NotTty(self, cursor_patch, print_patch, *patches): with ProgressBar(): @@ -67,14 +67,14 @@ def test__enter_exit_Should_NotHideOrShowCursor_When_NotTty(self, cursor_patch, def test__print_Should_NotPrint_When_NoTtyAndNotForced(self, stderr_patch, *patches): stderr_patch.isatty.return_value = False pb = ProgressBar() - pb._print(True) + pb.print(True) stderr_patch.flush.assert_not_called() @patch('progress1bar.progressbar.sys.stderr') def test__print_Should_NotPrint_When_TtyAndControlledNotForced(self, stderr_patch, *patches): stderr_patch.isatty.return_value = True pb = ProgressBar(control=True) - pb._print(True) + pb.print(True) stderr_patch.flush.assert_not_called() @patch('progress1bar.progressbar.sys.stderr') @@ -82,7 +82,7 @@ def test__print_Should_NotPrint_When_PreviousSameAsCurrent(self, stderr_patch, * stderr_patch.isatty.return_value = True pb = ProgressBar() pb._previous = 'Processing | | 0% ##/##' - pb._print(False) + pb.print(False) stderr_patch.flush.assert_not_called() @patch('builtins.print') @@ -90,7 +90,7 @@ def test__print_Should_NotPrint_When_PreviousSameAsCurrent(self, stderr_patch, * def test__print_Should_Print_When_TtyAndNoClear(self, stderr_patch, print_patch, *patches): stderr_patch.isatty.return_value = True pb = ProgressBar() - pb._print(False) + pb.print(False) stderr_patch.flush.assert_called_once_with() self.assertEqual(len(print_patch.mock_calls), 1) @@ -100,7 +100,7 @@ def test__print_Should_ClearAndPrint_When_TtyAndNoClearAndResetCount(self, stder stderr_patch.isatty.return_value = True pb = ProgressBar() pb._reset_count = 1 - pb._print(False) + pb.print(False) stderr_patch.flush.assert_called_once_with() self.assertEqual(len(print_patch.mock_calls), 2) @@ -109,7 +109,7 @@ def test__print_Should_ClearAndPrint_When_TtyAndNoClearAndResetCount(self, stder def test__print_Should_ClearAndPrint_When_TtyAndClear(self, stderr_patch, print_patch, *patches): stderr_patch.isatty.return_value = True pb = ProgressBar() - pb._print(True) + pb.print(True) stderr_patch.flush.assert_called_once_with() self.assertEqual(len(print_patch.mock_calls), 2) @@ -123,13 +123,13 @@ def test__fraction_Should_ReturnEmpty_When_NoShowFraction(self, *patches): pb = ProgressBar(show_fraction=False) self.assertEqual(pb.fraction, '') - @patch('progress1bar.ProgressBar._print') + @patch('progress1bar.ProgressBar.print') def test__count_Should_NotSetCount_When_NoTotal(self, *patches): pb = ProgressBar() pb.count = 1 self.assertIsNone(pb.total) - @patch('progress1bar.ProgressBar._print') + @patch('progress1bar.ProgressBar.print') def test__count_Should_UpdateCompletedAttributes_When_CountEqualTotal(self, *patches): pb = ProgressBar(total=1) pb.count = 1