Hello community,

here is the log from the commit of package python-tqdm for openSUSE:Factory 
checked in at 2020-01-04 19:20:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tqdm (Old)
 and      /work/SRC/openSUSE:Factory/.python-tqdm.new.6675 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tqdm"

Sat Jan  4 19:20:24 2020 rev:28 rq:760369 version:4.41.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tqdm/python-tqdm.changes  2019-12-18 
14:47:56.905928463 +0100
+++ /work/SRC/openSUSE:Factory/.python-tqdm.new.6675/python-tqdm.changes        
2020-01-04 19:20:24.781112560 +0100
@@ -1,0 +2,15 @@
+Sun Dec 29 21:17:56 UTC 2019 - Arun Persaud <[email protected]>
+
+- update to version 4.41.0:
+  * trim on ncols overflow with ANSI handling (#850, #716 <- #690)
+  * add notebook.reset() (#864)
+  * add keras.TqdmCallback (#867 <- #835)
+  * documentation updates
+    + document newly added features (above)
+    + notebook ncols percentage/pixels (#276)
+  * test updates
+    + test newly added features (above)
+    + add CI for win and osx (#841)
+    + py2 threading
+
+-------------------------------------------------------------------

Old:
----
  tqdm-4.40.2.tar.gz

New:
----
  tqdm-4.41.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tqdm.spec ++++++
--- /var/tmp/diff_new_pack.5kg81Q/_old  2020-01-04 19:20:25.893113053 +0100
+++ /var/tmp/diff_new_pack.5kg81Q/_new  2020-01-04 19:20:25.897113054 +0100
@@ -28,7 +28,7 @@
 %bcond_with test
 %endif
 Name:           python-tqdm%{pkg_suffix}
-Version:        4.40.2
+Version:        4.41.0
 Release:        0
 Summary:        An extensible progress meter
 License:        MPL-2.0 AND MIT

++++++ tqdm-4.40.2.tar.gz -> tqdm-4.41.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/PKG-INFO new/tqdm-4.41.0/PKG-INFO
--- old/tqdm-4.40.2/PKG-INFO    2019-12-10 01:43:58.000000000 +0100
+++ new/tqdm-4.41.0/PKG-INFO    2019-12-20 19:57:14.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tqdm
-Version: 4.40.2
+Version: 4.41.0
 Summary: Fast, Extensible Progress Meter
 Home-page: https://github.com/tqdm/tqdm
 Maintainer: tqdm developers
@@ -568,6 +568,8 @@
             def tqdm.notebook.trange(*args, **kwargs):
                 """Experimental IPython/Jupyter Notebook widget version of 
trange"""
         
+            class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
+                """`keras` callback for epoch and batch progress"""
         
         Examples and Advanced Usage
         ---------------------------
@@ -842,6 +844,19 @@
         `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
         folder or import the module and run ``help()``.
         
+        Keras Integration
+        ~~~~~~~~~~~~~~~~~
+        
+        A ``keras`` callback is also available:
+        
+        .. code:: python
+        
+            from tqdm.keras import TqdmCallback
+        
+            ...
+        
+            model.fit(..., verbose=0, callbacks=[TqdmCallback()])
+        
         IPython/Jupyter Integration
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
@@ -865,6 +880,9 @@
         |Screenshot-Jupyter2|
         |Screenshot-Jupyter3|
         
+        The ``notebook`` version supports percentage or pixels for overall 
width
+        (e.g.: ``ncols='100%'`` or ``ncols='480px'``).
+        
         It is also possible to let ``tqdm`` automatically choose between
         console or notebook versions by using the ``autonotebook`` submodule:
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/README.rst new/tqdm-4.41.0/README.rst
--- old/tqdm-4.40.2/README.rst  2019-12-10 01:43:56.000000000 +0100
+++ new/tqdm-4.41.0/README.rst  2019-12-20 19:57:13.000000000 +0100
@@ -560,6 +560,8 @@
     def tqdm.notebook.trange(*args, **kwargs):
         """Experimental IPython/Jupyter Notebook widget version of trange"""
 
+    class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
+        """`keras` callback for epoch and batch progress"""
 
 Examples and Advanced Usage
 ---------------------------
@@ -834,6 +836,19 @@
 `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
 folder or import the module and run ``help()``.
 
+Keras Integration
+~~~~~~~~~~~~~~~~~
+
+A ``keras`` callback is also available:
+
+.. code:: python
+
+    from tqdm.keras import TqdmCallback
+
+    ...
+
+    model.fit(..., verbose=0, callbacks=[TqdmCallback()])
+
 IPython/Jupyter Integration
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
@@ -857,6 +872,9 @@
 |Screenshot-Jupyter2|
 |Screenshot-Jupyter3|
 
+The ``notebook`` version supports percentage or pixels for overall width
+(e.g.: ``ncols='100%'`` or ``ncols='480px'``).
+
 It is also possible to let ``tqdm`` automatically choose between
 console or notebook versions by using the ``autonotebook`` submodule:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tox.ini new/tqdm-4.41.0/tox.ini
--- old/tqdm-4.40.2/tox.ini     2019-12-10 01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tox.ini     2019-12-20 19:56:58.000000000 +0100
@@ -33,6 +33,8 @@
     cython
     numpy
     pandas
+    tensorflow
+    keras
 commands = {[extra]commands}
 
 # no cython/numpy/pandas for py{py,py3,26,33,34}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/_version.py 
new/tqdm-4.41.0/tqdm/_version.py
--- old/tqdm-4.40.2/tqdm/_version.py    2019-12-10 01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/_version.py    2019-12-20 19:56:58.000000000 +0100
@@ -5,7 +5,7 @@
 __all__ = ["__version__"]
 
 # major, minor, patch, -extra
-version_info = 4, 40, 2
+version_info = 4, 41, 0
 
 # Nice string for the version
 __version__ = '.'.join(map(str, version_info))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/keras.py 
new/tqdm-4.41.0/tqdm/keras.py
--- old/tqdm-4.40.2/tqdm/keras.py       1970-01-01 01:00:00.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/keras.py       2019-12-20 19:56:58.000000000 +0100
@@ -0,0 +1,85 @@
+from __future__ import absolute_import
+from .auto import tqdm as tqdm_auto
+from copy import deepcopy
+from keras.callbacks import Callback
+
+
+class TqdmCallback(Callback):
+    """`keras` callback for epoch and batch progress"""
+    @staticmethod
+    def bar2callback(bar, pop=None, delta=(lambda logs: 1)):
+        def callback(_, logs=None):
+            n = delta(logs)
+            if logs:
+                if pop:
+                    logs = deepcopy(logs)
+                    [logs.pop(i, 0) for i in pop]
+                bar.set_postfix(logs, refresh=False)
+            bar.update(n)
+
+        return callback
+
+    def __init__(self, epochs=None, data_size=None, batch_size=None, verbose=1,
+                 tqdm_class=tqdm_auto):
+        """
+        Parameters
+        ----------
+        epochs  : int, optional
+        data_size  : int, optional
+            Number of training pairs.
+        batch_size  : int, optional
+            Number of training pairs per batch.
+        verbose  : int
+            0: epoch, 1: batch (transient), 2: batch. [default: 1].
+            Will be set to `0` unless both `data_size` and `batch_size`
+            are given.
+        tqdm_class : optional
+            `tqdm` class to use for bars [default: `tqdm.auto.tqdm`].
+        """
+        self.tqdm_class = tqdm_class
+        self.epoch_bar = tqdm_class(total=epochs, unit='epoch')
+        self.on_epoch_end = self.bar2callback(self.epoch_bar)
+        if data_size and batch_size:
+            self.batches = batches = (data_size + batch_size - 1) // batch_size
+        else:
+            self.batches = batches = None
+        self.verbose = verbose
+        if verbose == 1:
+            self.batch_bar = tqdm_class(total=batches, unit='batch',
+                                        leave=False)
+            self.on_batch_end = self.bar2callback(
+                self.batch_bar,
+                pop=['batch'],
+                delta=lambda logs: logs.get('size', 1))
+
+    def on_train_begin(self, *_, **__):
+        params = self.params.get
+        auto_total = params('epochs', params('nb_epoch', None))
+        if auto_total is not None:
+            self.epoch_bar.reset(total=auto_total)
+
+    def on_epoch_begin(self, *_, **__):
+        if self.verbose:
+            params = self.params.get
+            total = params('samples', params(
+                'nb_sample', params('steps', None))) or self.batches
+            if self.verbose == 2:
+                if hasattr(self, 'batch_bar'):
+                    self.batch_bar.close()
+                self.batch_bar = self.tqdm_class(
+                    total=total, unit='batch', leave=True,
+                    unit_scale=1.0 / params('batch_size', 1))
+                self.on_batch_end = self.bar2callback(
+                    self.batch_bar,
+                    pop=['batch', 'size'],
+                    delta=lambda logs: logs.get('size', 1))
+            elif self.verbose == 1:
+                self.batch_bar.unit_scale = 1.0 / params('batch_size', 1)
+                self.batch_bar.reset(total=total)
+            else:
+                raise KeyError('Unknown verbosity')
+
+    def on_train_end(self, *_, **__):
+        if self.verbose:
+            self.batch_bar.close()
+        self.epoch_bar.close()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/notebook.py 
new/tqdm-4.41.0/tqdm/notebook.py
--- old/tqdm-4.40.2/tqdm/notebook.py    2019-12-10 01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/notebook.py    2019-12-20 19:56:58.000000000 +0100
@@ -247,6 +247,21 @@
         # void -> avoid extraneous `\n` in IPython output cell
         return
 
+    def reset(self, total=None):
+        """
+        Resets to 0 iterations for repeated use.
+
+        Consider combining with `leave=True`.
+
+        Parameters
+        ----------
+        total  : int or float, optional. Total to use for the new bar.
+        """
+        if total is not None:
+            pbar, _ = self.container.children
+            pbar.max = total
+        return super(tqdm_notebook, self).reset(total=total)
+
 
 def tnrange(*args, **kwargs):
     """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/std.py new/tqdm-4.41.0/tqdm/std.py
--- old/tqdm-4.40.2/tqdm/std.py 2019-12-10 01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/std.py 2019-12-20 19:56:58.000000000 +0100
@@ -10,8 +10,8 @@
 from __future__ import absolute_import, division
 # compatibility functions and utilities
 from .utils import _supports_unicode, _environ_cols_wrapper, _range, _unich, \
-    _term_move_up, _unicode, WeakSet, _basestring, _OrderedDict, _text_width, \
-    Comparable, RE_ANSI, _is_ascii, FormatReplace, \
+    _term_move_up, _unicode, WeakSet, _basestring, _OrderedDict, \
+    Comparable, _is_ascii, FormatReplace, disp_len, disp_trim, \
     SimpleTextIOWrapper, CallbackIOWrapper
 from ._monitor import TMonitor
 # native libraries
@@ -479,12 +479,13 @@
             # Formatting progress bar space available for bar's display
             full_bar = Bar(
                 frac,
-                max(1, ncols - _text_width(RE_ANSI.sub('', nobar)))
+                max(1, ncols - disp_len(nobar))
                 if ncols else 10,
                 charset=Bar.ASCII if ascii is True else ascii or Bar.UTF)
             if not _is_ascii(full_bar.charset) and _is_ascii(bar_format):
                 bar_format = _unicode(bar_format)
-            return bar_format.format(bar=full_bar, **format_dict)
+            res = bar_format.format(bar=full_bar, **format_dict)
+            return disp_trim(res, ncols) if ncols else res
 
         elif bar_format:
             # user-specified bar_format but no total
@@ -496,10 +497,11 @@
                 return nobar
             full_bar = Bar(
                 0,
-                max(1, ncols - _text_width(RE_ANSI.sub('', nobar)))
+                max(1, ncols - disp_len(nobar))
                 if ncols else 10,
                 charset=Bar.BLANK)
-            return bar_format.format(bar=full_bar, **format_dict)
+            res = bar_format.format(bar=full_bar, **format_dict)
+            return disp_trim(res, ncols) if ncols else res
         else:
             # no total: no progressbar, ETA, just progress stats
             return ((prefix + ": ") if prefix else '') + \
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/tests/tests_keras.py 
new/tqdm-4.41.0/tqdm/tests/tests_keras.py
--- old/tqdm-4.40.2/tqdm/tests/tests_keras.py   1970-01-01 01:00:00.000000000 
+0100
+++ new/tqdm-4.41.0/tqdm/tests/tests_keras.py   2019-12-20 19:56:58.000000000 
+0100
@@ -0,0 +1,94 @@
+from __future__ import division
+from tqdm import tqdm
+from tests_tqdm import with_setup, pretest, posttest, SkipTest, StringIO, \
+    closing
+
+
+@with_setup(pretest, posttest)
+def test_keras():
+    """Test tqdm.keras.TqdmCallback"""
+    try:
+        from tqdm.keras import TqdmCallback
+        import numpy as np
+        import keras as K
+    except ImportError:
+        raise SkipTest
+
+    # 1D autoencoder
+    dtype = np.float32
+    model = K.models.Sequential(
+        [K.layers.InputLayer((1, 1), dtype=dtype), K.layers.Conv1D(1, 1)]
+    )
+    model.compile("adam", "mse")
+    x = np.random.rand(100, 1, 1).astype(dtype)
+    batch_size = 10
+    batches = len(x) / batch_size
+    epochs = 5
+
+    with closing(StringIO()) as our_file:
+
+        class Tqdm(tqdm):
+            """redirected I/O class"""
+
+            def __init__(self, *a, **k):
+                k.setdefault("file", our_file)
+                super(Tqdm, self).__init__(*a, **k)
+
+        # just epoch (no batch) progress
+        model.fit(
+            x,
+            x,
+            epochs=epochs,
+            batch_size=batch_size,
+            verbose=False,
+            callbacks=[
+                TqdmCallback(
+                    epochs,
+                    data_size=len(x),
+                    batch_size=batch_size,
+                    verbose=0,
+                    tqdm_class=Tqdm,
+                )
+            ],
+        )
+        res = our_file.getvalue()
+        assert "{epochs}/{epochs}".format(epochs=epochs) in res
+        assert "{batches}/{batches}".format(batches=batches) not in res
+
+        # full (epoch and batch) progress
+        our_file.seek(0)
+        our_file.truncate()
+        model.fit(
+            x,
+            x,
+            epochs=epochs,
+            batch_size=batch_size,
+            verbose=False,
+            callbacks=[
+                TqdmCallback(
+                    epochs,
+                    data_size=len(x),
+                    batch_size=batch_size,
+                    verbose=2,
+                    tqdm_class=Tqdm,
+                )
+            ],
+        )
+        res = our_file.getvalue()
+        assert "{epochs}/{epochs}".format(epochs=epochs) in res
+        assert "{batches}/{batches}".format(batches=batches) in res
+
+        # auto-detect epochs and batches
+        our_file.seek(0)
+        our_file.truncate()
+        model.fit(
+            x,
+            x,
+            epochs=epochs,
+            batch_size=batch_size,
+            verbose=False,
+            callbacks=[TqdmCallback(verbose=2, tqdm_class=Tqdm)],
+        )
+        res = our_file.getvalue()
+        assert "{epochs}/{epochs}".format(epochs=epochs) in res
+        assert "{batches}/{batches}".format(batches=batches) in res
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/tests/tests_main.py 
new/tqdm-4.41.0/tqdm/tests/tests_main.py
--- old/tqdm-4.40.2/tqdm/tests/tests_main.py    2019-12-10 01:43:40.000000000 
+0100
+++ new/tqdm-4.41.0/tqdm/tests/tests_main.py    2019-12-20 19:56:58.000000000 
+0100
@@ -4,9 +4,10 @@
 from shutil import rmtree
 from tempfile import mkdtemp
 from tqdm.cli import main, TqdmKeyError, TqdmTypeError
+from tqdm.utils import IS_WIN
 
 from tests_tqdm import with_setup, pretest, posttest, _range, closing, \
-    UnicodeIO, StringIO
+    UnicodeIO, StringIO, SkipTest
 
 
 def _sh(*cmd, **kwargs):
@@ -82,6 +83,8 @@
 
 def test_manpath():
     """Test CLI --manpath"""
+    if IS_WIN:
+        raise SkipTest
     tmp = mkdtemp()
     man = path.join(tmp, "tqdm.1")
     assert not path.exists(man)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/tests/tests_synchronisation.py 
new/tqdm-4.41.0/tqdm/tests/tests_synchronisation.py
--- old/tqdm-4.40.2/tqdm/tests/tests_synchronisation.py 2019-12-10 
01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/tests/tests_synchronisation.py 2019-12-20 
19:56:58.000000000 +0100
@@ -3,7 +3,9 @@
 from tests_tqdm import with_setup, pretest, posttest, SkipTest, \
     StringIO, closing
 from tests_tqdm import DiscreteTimer, cpu_timify
+from tests_perf import retry_on_except
 
+import sys
 from time import sleep
 from threading import Event
 
@@ -188,6 +190,8 @@
     assert res[-1] == 100
 
 
+# py2: locks won't propagate to incr_bar so may cause `AttributeError`
+@retry_on_except(n=3 if sys.version_info < (3,) else 1)
 @with_setup(pretest, posttest)
 def test_threadpool():
     """Test concurrent.futures.ThreadPoolExecutor"""
@@ -199,5 +203,11 @@
 
     tqdm.set_lock(RLock())
     with ThreadPoolExecutor(8) as pool:
-        res = list(tqdm(pool.map(incr_bar, range(100)), disable=True))
+        try:
+            res = list(tqdm(pool.map(incr_bar, range(100)), disable=True))
+        except AttributeError:
+            if sys.version_info < (3,):
+                raise SkipTest
+            else:
+                raise
     assert sum(res) == sum(range(1, 101))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/tests/tests_tqdm.py 
new/tqdm-4.41.0/tqdm/tests/tests_tqdm.py
--- old/tqdm-4.40.2/tqdm/tests/tests_tqdm.py    2019-12-10 01:43:40.000000000 
+0100
+++ new/tqdm-4.41.0/tqdm/tests/tests_tqdm.py    2019-12-20 19:56:58.000000000 
+0100
@@ -9,6 +9,7 @@
 from nose import with_setup
 from nose.plugins.skip import SkipTest
 from nose.tools import assert_raises
+from nose.tools import eq_
 from contextlib import contextmanager
 from warnings import catch_warnings, simplefilter
 
@@ -273,6 +274,59 @@
         "100kiB [00:13, 7.69kiB/s]"
     assert format_meter(100, 1000, 12, ncols=0, rate=7.33) == \
         " 10% 100/1000 [00:12<02:02,  7.33it/s]"
+    eq_(
+        # ncols is small, l_bar is too large
+        # l_bar gets chopped
+        # no bar
+        # no r_bar
+        format_meter(
+            0, 1000, 13, ncols=10,
+            bar_format="************{bar:10}$$$$$$$$$$"),
+        "**********"  # 10/12 stars since ncols is 10
+    )
+    eq_(
+        # n_cols allows for l_bar and some of bar
+        # l_bar displays
+        # bar gets chopped
+        # no r_bar
+        format_meter(
+            0, 1000, 13, ncols=20,
+            bar_format="************{bar:10}$$$$$$$$$$"),
+        "************        "  # all 12 stars and 8/10 bar parts
+    )
+    eq_(
+        # n_cols allows for l_bar, bar, and some of r_bar
+        # l_bar displays
+        # bar displays
+        # r_bar gets chopped
+        format_meter(
+            0, 1000, 13, ncols=30,
+            bar_format="************{bar:10}$$$$$$$$$$"),
+        "************          $$$$$$$$"
+        # all 12 stars and 10 bar parts, but only 8/10 dollar signs
+    )
+    eq_(
+        # trim left ANSI; escape is before trim zone
+        format_meter(
+            0, 1000, 13, ncols=10,
+            bar_format="*****\033[22m****\033[0m***{bar:10}$$$$$$$$$$"),
+        "*****\033[22m****\033[0m*\033[0m"
+        # we only know it has ANSI codes, so we append an END code anyway
+    )
+    eq_(
+        # trim left ANSI; escape is at trim zone
+        format_meter(
+            0, 1000, 13, ncols=10,
+            bar_format="*****\033[22m*****\033[0m**{bar:10}$$$$$$$$$$"),
+        "*****\033[22m*****\033[0m"
+    )
+    eq_(
+        # trim left ANSI; escape is after trim zone
+        format_meter(
+            0, 1000, 13, ncols=10,
+            bar_format="*****\033[22m******\033[0m*{bar:10}$$$$$$$$$$"),
+        "*****\033[22m*****\033[0m"
+    )
     # Check that bar_format correctly adapts {bar} size to the rest
     assert format_meter(20, 100, 12, ncols=13, rate=8.1,
                         bar_format=r'{l_bar}{bar}|{n_fmt}/{total_fmt}') == \
@@ -300,14 +354,18 @@
 
 def test_ansi_escape_codes():
     """Test stripping of ANSI escape codes"""
-    format_meter = tqdm.format_meter
-    ansi = {'BOLD': '\033[1m',
-            'RED': '\033[91m',
-            'END': '\033[0m'}
-    desc = '{BOLD}{RED}Colored{END} description'.format(**ansi)
+    ansi = dict(BOLD='\033[1m', RED='\033[91m', END='\033[0m')
+    desc_raw = '{BOLD}{RED}Colored{END} description'
     ncols = 123
-    ansi_len = sum([len(code) for code in ansi.values()])
-    meter = format_meter(0, 100, 0, ncols=ncols, prefix=desc)
+
+    desc_stripped = desc_raw.format(BOLD='', RED='', END='')
+    meter = tqdm.format_meter(0, 100, 0, ncols=ncols, prefix=desc_stripped)
+    assert len(meter) == ncols
+
+    desc = desc_raw.format(**ansi)
+    meter = tqdm.format_meter(0, 100, 0, ncols=ncols, prefix=desc)
+    # `format_meter` inserts an extra END for safety
+    ansi_len = len(desc) - len(desc_stripped) + len(ansi['END'])
     assert len(meter) == ncols + ansi_len
 
 
@@ -901,7 +959,7 @@
     for ascii in [" .oO0", " #"]:
         with closing(StringIO()) as our_file:
             for _ in tqdm(_range(len(ascii) - 1), file=our_file, miniters=1,
-                          mininterval=0, ascii=ascii, ncols=1):
+                          mininterval=0, ascii=ascii, ncols=27):
                 pass
             res = our_file.getvalue().strip("\r").split("\r")
         for bar, line in zip(ascii, res):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm/utils.py 
new/tqdm-4.41.0/tqdm/utils.py
--- old/tqdm-4.40.2/tqdm/utils.py       2019-12-10 01:43:40.000000000 +0100
+++ new/tqdm-4.41.0/tqdm/utils.py       2019-12-20 19:56:58.000000000 +0100
@@ -343,3 +343,27 @@
     def _text_width(s):
         return sum(
             2 if east_asian_width(ch) in 'FW' else 1 for ch in _unicode(s))
+
+
+def disp_len(data):
+    """
+    Returns the real on-screen length of a string which may contain
+    ANSI control codes and wide chars.
+    """
+    return _text_width(RE_ANSI.sub('', data))
+
+
+def disp_trim(data, length):
+    """
+    Trim a string which may contain ANSI control characters.
+    """
+    if len(data) == disp_len(data):
+        return data[:length]
+
+    ansi_present = bool(RE_ANSI.search(data))
+    while disp_len(data) > length:  # carefully delete one char at a time
+        data = data[:-1]
+    if ansi_present and bool(RE_ANSI.search(data)):
+        # assume ANSI reset is required
+        return data if data.endswith("\033[0m") else data + "\033[0m"
+    return data
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm.egg-info/PKG-INFO 
new/tqdm-4.41.0/tqdm.egg-info/PKG-INFO
--- old/tqdm-4.40.2/tqdm.egg-info/PKG-INFO      2019-12-10 01:43:58.000000000 
+0100
+++ new/tqdm-4.41.0/tqdm.egg-info/PKG-INFO      2019-12-20 19:57:14.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tqdm
-Version: 4.40.2
+Version: 4.41.0
 Summary: Fast, Extensible Progress Meter
 Home-page: https://github.com/tqdm/tqdm
 Maintainer: tqdm developers
@@ -568,6 +568,8 @@
             def tqdm.notebook.trange(*args, **kwargs):
                 """Experimental IPython/Jupyter Notebook widget version of 
trange"""
         
+            class tqdm.keras.TqdmCallback(keras.callbacks.Callback):
+                """`keras` callback for epoch and batch progress"""
         
         Examples and Advanced Usage
         ---------------------------
@@ -842,6 +844,19 @@
         `examples <https://github.com/tqdm/tqdm/tree/master/examples>`__
         folder or import the module and run ``help()``.
         
+        Keras Integration
+        ~~~~~~~~~~~~~~~~~
+        
+        A ``keras`` callback is also available:
+        
+        .. code:: python
+        
+            from tqdm.keras import TqdmCallback
+        
+            ...
+        
+            model.fit(..., verbose=0, callbacks=[TqdmCallback()])
+        
         IPython/Jupyter Integration
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
@@ -865,6 +880,9 @@
         |Screenshot-Jupyter2|
         |Screenshot-Jupyter3|
         
+        The ``notebook`` version supports percentage or pixels for overall 
width
+        (e.g.: ``ncols='100%'`` or ``ncols='480px'``).
+        
         It is also possible to let ``tqdm`` automatically choose between
         console or notebook versions by using the ``autonotebook`` submodule:
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.40.2/tqdm.egg-info/SOURCES.txt 
new/tqdm-4.41.0/tqdm.egg-info/SOURCES.txt
--- old/tqdm-4.40.2/tqdm.egg-info/SOURCES.txt   2019-12-10 01:43:58.000000000 
+0100
+++ new/tqdm-4.41.0/tqdm.egg-info/SOURCES.txt   2019-12-20 19:57:14.000000000 
+0100
@@ -31,6 +31,7 @@
 tqdm/autonotebook.py
 tqdm/cli.py
 tqdm/gui.py
+tqdm/keras.py
 tqdm/notebook.py
 tqdm/std.py
 tqdm/tqdm.1
@@ -42,6 +43,7 @@
 tqdm.egg-info/requires.txt
 tqdm.egg-info/top_level.txt
 tqdm/contrib/__init__.py
+tqdm/tests/tests_keras.py
 tqdm/tests/tests_main.py
 tqdm/tests/tests_pandas.py
 tqdm/tests/tests_perf.py


Reply via email to