diff --git a/package/CHANGELOG b/package/CHANGELOG index 874097f39b4..b5b9e2a52c0 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -24,6 +24,7 @@ Fixes Enhancements Changes + * Removes deprecated ProgressMeter (Issue #2739) * Removes deprecated MDAnalysis.units.N_Avogadro (PR #2737) * Dropped Python 2 support diff --git a/package/MDAnalysis/analysis/density.py b/package/MDAnalysis/analysis/density.py index 6bc1dd6d5dd..986e94a2aab 100644 --- a/package/MDAnalysis/analysis/density.py +++ b/package/MDAnalysis/analysis/density.py @@ -191,8 +191,7 @@ from MDAnalysis import NoDataError, MissingDataWarning from .. import units from ..lib import distances -from MDAnalysis.lib.log import ProgressBar -from MDAnalysis.lib.log import ProgressMeter # remove in 2.0 +from MDAnalysis.lib.log import ProgressBar from MDAnalysis.lib.util import deprecate from .base import AnalysisBase diff --git a/package/MDAnalysis/analysis/hbonds/hbond_analysis.py b/package/MDAnalysis/analysis/hbonds/hbond_analysis.py index e0d34ca721d..936502a1b51 100644 --- a/package/MDAnalysis/analysis/hbonds/hbond_analysis.py +++ b/package/MDAnalysis/analysis/hbonds/hbond_analysis.py @@ -897,8 +897,8 @@ def run(self, start=None, stop=None, step=None, verbose=None, **kwargs): read every `step` between `start` (included) and `stop` (excluded), ``None`` selects 1. [``None``] verbose : bool (optional) - toggle progress meter output :class:`~MDAnalysis.lib.log.ProgressMeter` - [``True``] + toggle progress meter output + :class:`~MDAnalysis.lib.log.ProgressBar` [``True``] debug : bool (optional) enable detailed logging of debugging information; this can create *very big* log files so it is disabled (``False``) by default; setting diff --git a/package/MDAnalysis/lib/log.py b/package/MDAnalysis/lib/log.py index 73e60437c32..234c0dd6e56 100644 --- a/package/MDAnalysis/lib/log.py +++ b/package/MDAnalysis/lib/log.py @@ -77,15 +77,18 @@ Other functions and classes for logging purposes ------------------------------------------------ + +.. versionchanged:: 2.0.0 + Deprecated :class:`MDAnalysis.lib.log.ProgressMeter` has now been removed. + .. autogenerated, see Online Docs """ -from __future__ import print_function, division, absolute_import +from __future__ import absolute_import import sys import logging import re -import warnings from tqdm.auto import tqdm @@ -224,193 +227,6 @@ def _guess_string_format(template): return _legacy_format -class ProgressMeter(object): - r"""Simple progress meter (Deprecated) - - ..Warning: - This class is deprecated and will be removed in version 2.0. - Please use :class:`MDAnalysis.lib.log.ProgressBar` instead. - - The :class:`ProgressMeter` class can be used to show running progress such - as frames processed or percentage done to give the user feedback on the - duration and progress of a task. It is structures as a class that is - customized on instantation (e.g., using a custom `format` string and the - expected total number of frames to be processed). Within a processing loop, - call :meth:`echo` with the current frame number to print the output to - stderr. - - Parameters - ---------- - numsteps: int - total number of steps - interval: int - only calculate and print progress every `interval` steps [10] - format: str - a format string with Python variable interpolation. Allowed - values: - - * *step*: current step - * *numsteps*: total number of steps as supplied in *numsteps* - * *percentage*: percentage of total - - The last call to :meth:`ProgressMeter.print` will automatically - issue a newline ``\n``. - - If *format* is ``None`` then the default is used:: - - Step {step:5d}/{numsteps} [{percentage:5.1f}%] - - offset: int - number to add to *step*; e.g. if *step* is 0-based (as in MDAnalysis) - then one should set *offset* = 1; for 1-based steps, choose 0. [1] - verbose: bool - If ``False``, disable all output, ``True`` print all messages as - specified, [``True``] - dynamic: bool - If ``True``, each line will be printed on top of the previous one. - This is done by prepedind the format with ``\r``. [``True``] - format_handling: str - how to handle the format string. Allowed values are: - - * *new*: the format string uses {}-based formating - * *legacy*: the format string uses %-basedd formating - * *auto*: default, try to guess how the format string should be - handled - - - Examples - -------- - The typical use case is to show progress as frames of a trajectory are - processed:: - - u = Universe(PSF, DCD) - pm = ProgressMeter(u.trajectory.n_frames, interval=100) - for ts in u.trajectory: - pm.echo(ts.frame) - ... - - For a trajectory with 10000 frames this will produce output such - as :: - - Step 100/10000 [ 1.0%] - Step 200/10000 [ 2.0%] - ... - - The default *format* string is:: - - Step {step:5d}/{numsteps} [{percentage:5.1f}%] - - By default, each line of the progress meter is displayed on top of the - previous one. To prevent this behaviour, set the `dynamic` keyword to - ``False``. - - It is possible to embed (almost) arbitrary additional data in the - format string, for example a current RMSD value:: - - format_line = "RMSD {rmsd:5.2f} at {step:5d}/{numsteps} [{percentage:5.1f}%]" - pm = ProgressMeter(u.trajectory.n_frames, - interval=100, format=format_line) - for ts in u.trajectory: - pm.echo(ts.frame, rmsd=current_rmsd) - ... - - This will print something like:: - - RMSD 1.02 at 100/10000 [ 1.0%] - RMSD 1.89 at 200/10000 [ 2.0%] - ... - - .. versionchanged:: 0.8 - Keyword argument *quiet* was added. - - .. versionchanged:: 0.16 - Keyword argument *dynamic* replaces ``\r`` in the format. - - .. deprecated:: 0.16 - Keyword argument *quiet* is deprecated in favor of *verbose*. - - .. deprecated:: 1.0 - This class is deprecated in favor of *ProgressBar*. - - """ - - def __init__(self, numsteps, format=None, interval=10, offset=1, - verbose=True, dynamic=True, - format_handling='auto'): - warnings.warn( - "This class is deprecated as of MDAnalysis version 1.0. " - "It will be removed in MDAnalysis version 2.0. " - "Please use MDAnalysis.lib.log.ProgressBar instead.", - category=DeprecationWarning - ) - self.numsteps = numsteps - self.interval = int(interval) - self.offset = int(offset) - self.verbose = verbose - self.dynamic = dynamic - self.numouts = -1 - - if format is None: - format = "Step {step:5d}/{numsteps} [{percentage:5.1f}%]" - self.format_handler = _new_format - else: - if format_handling == 'auto': - self.format_handler = _guess_string_format(format) - else: - self.format_handler = {'new': _new_format, - 'legacy': _legacy_format}[format_handling] - self.format = format - self.step = 0 - self.percentage = 0.0 - assert numsteps > 0, "numsteps step must be >0" - assert interval > 0, "interval step must be >0" - - def update(self, step, **kwargs): - """Update the state of the ProgressMeter. - - *kwargs* are additional attributes that can be references in - the format string. - """ - self.step = step + self.offset - self.percentage = 100. * self.step / self.numsteps - for k, v in kwargs.items(): - setattr(self, k, v) - - self.numouts += 1 - - def echo(self, step, **kwargs): - """Print the state to stderr, but only every *interval* steps. - - 1) calls :meth:`~ProgressMeter.update` - 2) writes step and percentage to stderr with :func:`echo`, - using the format string (in :attr:`ProgressMeter.format`) - - The last step is always shown, even if not on an *interval*, and a - carriage return is replaced with a new line for a cleaner display. - - *kwargs* are additional attributes that can be references in - the format string. - - .. Note:: If *verbose* = ``False`` has been set in the - constructor or if :attr:`ProgressMeter.verbose` has - been set to ``False``, then no messages will be - printed. - """ - if not self.verbose: - return - self.update(step, **kwargs) - format = self.format - newline = not self.dynamic - if self.step == self.numsteps: - newline = True - elif self.numouts % self.interval == 0: - pass - else: - return - echo(self.format_handler(format, vars(self)), - replace=self.dynamic, newline=newline) - - class ProgressBar(tqdm): def __init__(self, *args, **kwargs): verbose = kwargs.pop('verbose', True) diff --git a/testsuite/MDAnalysisTests/lib/test_log.py b/testsuite/MDAnalysisTests/lib/test_log.py index 91369a85c78..f591a4c81cd 100644 --- a/testsuite/MDAnalysisTests/lib/test_log.py +++ b/testsuite/MDAnalysisTests/lib/test_log.py @@ -25,32 +25,9 @@ import warnings import pytest -from MDAnalysis.lib.log import ProgressMeter, ProgressBar +from MDAnalysis.lib.log import ProgressBar -class TestProgressMeter(object): - - def test_deprecated(self, capsys): - with warnings.catch_warnings(record=True) as w: - # Cause all warnings to always be triggered. - warnings.simplefilter("always") - # Trigger a warning. - pm = ProgressMeter(10) - # Verify the warning - assert len(w) == 1 - assert issubclass(w[-1].category, DeprecationWarning) - assert "MDAnalysis.lib.log.ProgressBar" in str(w[-1].message) - - def test_output(self, capsys): - pm = ProgressMeter(10, interval=1) - for i in range(10): - pm.echo(i) - out, err = capsys.readouterr() - expected = 'Step 10/10 [100.0%]' - actual = err.strip().split('\r')[-1] - assert actual == expected - - class TestProgressBar(object): def test_output(self, capsys): diff --git a/testsuite/MDAnalysisTests/utils/test_log.py b/testsuite/MDAnalysisTests/utils/test_log.py index 54b4d94aa88..60b42a8d474 100644 --- a/testsuite/MDAnalysisTests/utils/test_log.py +++ b/testsuite/MDAnalysisTests/utils/test_log.py @@ -72,74 +72,3 @@ def buffer(): def _assert_in(output, string): assert string in output, "Output '{0}' does not match required format '{1}'.".format(output.replace('\r', '\\r'), string.replace('\r', '\\r')) - -def test_default_ProgressMeter(buffer, n=101, interval=10): - template = "Step {step:5d}/{numsteps} [{percentage:5.1f}%]" - with RedirectedStderr(buffer): - pm = MDAnalysis.lib.log.ProgressMeter(n, interval=interval) - for frame in range(n): - pm.echo(frame) - buffer.seek(0) - output = "".join(buffer.readlines()) - _assert_in(output, ('\r' + template).format(**{'step': 1, 'numsteps': n, 'percentage': 100./n})) - # last line always ends with \n! - _assert_in(output, - ('\r' + template + '\n').format(**{'step': n, 'numsteps': n, - 'percentage': 100.})) - - -def test_custom_ProgressMeter(buffer, n=51, interval=7): - template = "RMSD {rmsd:5.2f} at {step:03d}/{numsteps:4d} [{percentage:5.1f}%]" - with RedirectedStderr(buffer): - pm = MDAnalysis.lib.log.ProgressMeter(n, interval=interval, - format=template, offset=1) - for frame in range(n): - # n+1/n correction for 0-based frame vs 1-based counting - rmsd = 0.02 * frame * (n+1)/ n - pm.echo(frame, rmsd=rmsd) - buffer.seek(0) - output = "".join(buffer.readlines()) - _assert_in(output, - ('\r' + template).format(**{'rmsd': 0.0, 'step': 1, - 'numsteps': n, 'percentage': 100./n})) - # last line always ends with \n! - _assert_in(output, - ('\r' + template + '\n').format( - **{'rmsd': 0.02*n, 'step': n, - 'numsteps': n, 'percentage': 100.0})) - - -def test_legacy_ProgressMeter(buffer, n=51, interval=7): - template = "RMSD %(rmsd)5.2f at %(step)03d/%(numsteps)4d [%(percentage)5.1f%%]" - with RedirectedStderr(buffer): - pm = MDAnalysis.lib.log.ProgressMeter(n, interval=interval, - format=template, offset=1) - for frame in range(n): - # n+1/n correction for 0-based frame vs 1-based counting - rmsd = 0.02 * frame * (n+1)/ n - pm.echo(frame, rmsd=rmsd) - buffer.seek(0) - output = "".join(buffer.readlines()) - _assert_in(output, - ('\r' + template) % {'rmsd': 0.0, 'step': 1, - 'numsteps': n, 'percentage': 100./n}) - # last line always ends with \n! - _assert_in(output, - ('\r' + template + '\n') % {'rmsd': 0.02*n, 'step': n, - 'numsteps': n, 'percentage': 100.0}) - - -@pytest.mark.parametrize('step, percentage', [ - (1, 100./51), - (51, 100.) -]) -def test_not_dynamic_ProgressMeter(buffer, step, percentage, n=51, interval=10): - template = "Step {step:5d}/{numsteps} [{percentage:5.1f}%]" - with RedirectedStderr(buffer): - pm = MDAnalysis.lib.log.ProgressMeter(n, interval=interval, - dynamic=False) - for frame in range(n): - pm.echo(frame) - buffer.seek(0) - output = "".join(buffer.readlines()) - _assert_in(output, (template + '\n').format(**{'step': step, 'numsteps': n, 'percentage': percentage}))