Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-tqdm for openSUSE:Factory 
checked in at 2021-05-05 20:39:05
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tqdm (Old)
 and      /work/SRC/openSUSE:Factory/.python-tqdm.new.2988 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tqdm"

Wed May  5 20:39:05 2021 rev:43 rq:889727 version:4.60.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tqdm/python-tqdm.changes  2021-04-08 
21:03:13.281969060 +0200
+++ /work/SRC/openSUSE:Factory/.python-tqdm.new.2988/python-tqdm.changes        
2021-05-05 20:39:06.303146948 +0200
@@ -1,0 +2,11 @@
+Fri Apr 30 19:43:53 UTC 2021 - Arun Persaud <a...@gmx.de>
+
+- update to version 4.60.0:
+  * add contrib.logging helpers for redirecting to tqdm.write() (#1155
+    <- #786)
+  * support delay in notebook (#1142)
+  * fix contrib.tmap, tzip not using tqdm_class (#1148)
+  * add notebook tests (#1143)
+  * updates & misc minor fixes for documentation
+
+-------------------------------------------------------------------

Old:
----
  tqdm-4.59.0.tar.gz

New:
----
  tqdm-4.60.0.tar.gz

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

Other differences:
------------------
++++++ python-tqdm.spec ++++++
--- /var/tmp/diff_new_pack.duEwJy/_old  2021-05-05 20:39:06.751145026 +0200
+++ /var/tmp/diff_new_pack.duEwJy/_new  2021-05-05 20:39:06.751145026 +0200
@@ -28,7 +28,7 @@
 %bcond_with test
 %endif
 Name:           python-tqdm%{pkg_suffix}
-Version:        4.59.0
+Version:        4.60.0
 Release:        0
 Summary:        An extensible progress meter
 License:        MIT AND MPL-2.0

++++++ tqdm-4.59.0.tar.gz -> tqdm-4.60.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/.pre-commit-config.yaml 
new/tqdm-4.60.0/.pre-commit-config.yaml
--- old/tqdm-4.59.0/.pre-commit-config.yaml     2021-03-05 21:14:01.000000000 
+0100
+++ new/tqdm-4.60.0/.pre-commit-config.yaml     2021-04-06 03:22:58.000000000 
+0200
@@ -52,3 +52,8 @@
   rev: 5.7.0
   hooks:
   - id: isort
+- repo: https://github.com/kynan/nbstripout
+  rev: 0.3.9
+  hooks:
+  - id: nbstripout
+    args: ['--keep-count', '--keep-output']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/DEMO.ipynb new/tqdm-4.60.0/DEMO.ipynb
--- old/tqdm-4.59.0/DEMO.ipynb  2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/DEMO.ipynb  2021-04-06 03:22:58.000000000 +0200
@@ -1714,15 +1714,12 @@
   },
   "language_info": {
    "codemirror_mode": {
-    "name": "ipython",
-    "version": 3
+    "name": "ipython"
    },
    "file_extension": ".py",
    "mimetype": "text/x-python",
    "name": "python",
-   "nbconvert_exporter": "python",
-   "pygments_lexer": "ipython3",
-   "version": "3.7.8"
+   "nbconvert_exporter": "python"
   }
  },
  "nbformat": 4,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/Makefile new/tqdm-4.60.0/Makefile
--- old/tqdm-4.59.0/Makefile    2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/Makefile    2021-04-06 03:22:58.000000000 +0200
@@ -10,6 +10,7 @@
        test
        pytest
        testsetup
+       testnb
        testcoverage
        testperf
        testtimer
@@ -59,9 +60,13 @@
        python setup.py check --metadata --restructuredtext --strict
        python setup.py make none
 
+testnb:
+       pytest tests_notebook.ipynb --nbval --current-env -W=ignore 
--sanitize-with=setup.cfg --cov=tqdm.notebook --cov-report=term
+
 testcoverage:
        @make coverclean
-       pytest -k "not perf" --cov=tqdm --cov-report=xml --cov-report=term 
--cov-fail-under=80
+       pytest tests_notebook.ipynb --cov=tqdm --cov-report= --nbval 
--current-env --sanitize-with=setup.cfg -W=ignore
+       pytest -k "not perf" --cov=tqdm --cov-report=xml --cov-report=term 
--cov-append --cov-fail-under=80
 
 testperf:
        # do not use coverage (which is extremely slow)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/PKG-INFO new/tqdm-4.60.0/PKG-INFO
--- old/tqdm-4.59.0/PKG-INFO    2021-03-05 21:14:25.801780700 +0100
+++ new/tqdm-4.60.0/PKG-INFO    2021-04-06 03:23:18.062384800 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tqdm
-Version: 4.59.0
+Version: 4.60.0
 Summary: Fast, Extensible Progress Meter
 Home-page: https://github.com/tqdm/tqdm
 Maintainer: tqdm developers
@@ -1333,6 +1333,33 @@
             # After the `with`, printing is restored
             print("Done!")
         
+        Redirecting ``logging``
+        ~~~~~~~~~~~~~~~~~~~~~~~
+        
+        Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console 
``logging``
+        may also be redirected to ``tqdm.write()``.
+        
+        Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure 
to
+        redirect ``logging`` first if needed.
+        
+        Helper methods are available in ``tqdm.contrib.logging``. For example:
+        
+        .. code:: python
+        
+            import logging
+            from tqdm import trange
+            from tqdm.contrib.logging import logging_redirect_tqdm
+        
+            LOG = logging.getLogger(__name__)
+        
+            if __name__ == '__main__':
+                logging.basicConfig(level=logging.INFO)
+                with logging_redirect_tqdm():
+                    for i in trange(9):
+                        if i == 4:
+                            LOG.info("console logging redirected to 
`tqdm.write()`")
+                # logging restored
+        
         Monitoring thread, intervals and miniters
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/README.rst new/tqdm-4.60.0/README.rst
--- old/tqdm-4.59.0/README.rst  2021-03-05 21:14:21.000000000 +0100
+++ new/tqdm-4.60.0/README.rst  2021-04-06 03:23:14.000000000 +0200
@@ -1321,6 +1321,33 @@
     # After the `with`, printing is restored
     print("Done!")
 
+Redirecting ``logging``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console ``logging``
+may also be redirected to ``tqdm.write()``.
+
+Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure to
+redirect ``logging`` first if needed.
+
+Helper methods are available in ``tqdm.contrib.logging``. For example:
+
+.. code:: python
+
+    import logging
+    from tqdm import trange
+    from tqdm.contrib.logging import logging_redirect_tqdm
+
+    LOG = logging.getLogger(__name__)
+
+    if __name__ == '__main__':
+        logging.basicConfig(level=logging.INFO)
+        with logging_redirect_tqdm():
+            for i in trange(9):
+                if i == 4:
+                    LOG.info("console logging redirected to `tqdm.write()`")
+        # logging restored
+
 Monitoring thread, intervals and miniters
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/environment.yml 
new/tqdm-4.60.0/environment.yml
--- old/tqdm-4.59.0/environment.yml     2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/environment.yml     2021-04-06 03:22:58.000000000 +0200
@@ -8,6 +8,7 @@
 - python=3
 - pip
 - ipykernel
+- ipywidgets
 - setuptools
 - setuptools_scm
 - toml
@@ -20,6 +21,7 @@
 - pytest-cov
 - pytest-timeout
 - pytest-asyncio  # [py>=3.7]
+- nbval
 - flake8
 - flake8-bugbear
 - flake8-comprehensions
@@ -27,6 +29,7 @@
 # extras
 - dask               # dask
 - matplotlib         # gui
+- nbstripout         # notebook editing
 - numpy              # pandas, keras, contrib.tenumerate
 - pandas
 - tensorflow         # keras
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/setup.cfg new/tqdm-4.60.0/setup.cfg
--- old/tqdm-4.59.0/setup.cfg   2021-03-05 21:14:25.801780700 +0100
+++ new/tqdm-4.60.0/setup.cfg   2021-04-06 03:23:18.062384800 +0200
@@ -122,10 +122,18 @@
 markers = 
        asyncio
        slow
-python_files = tests_*.py
+python_files = tests_*.py tests_*.ipynb
 testpaths = tests
 addopts = -v --tb=short -rxs -W=error --durations=0 --durations-min=0.1
 
+[regex1]
+regex = (?<= )[\s\d.]+(it/s|s/it)
+replace = ??.??it/s
+
+[regex2]
+regex = 00:0[01]<00:0[01]
+replace = 00:00<00:00
+
 [coverage:run]
 branch = True
 include = tqdm/*
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tests/tests_contrib.py 
new/tqdm-4.60.0/tests/tests_contrib.py
--- old/tqdm-4.59.0/tests/tests_contrib.py      2021-03-05 21:14:01.000000000 
+0100
+++ new/tqdm-4.60.0/tests/tests_contrib.py      2021-04-06 03:22:58.000000000 
+0200
@@ -3,6 +3,9 @@
 """
 import sys
 
+import pytest
+
+from tqdm import tqdm
 from tqdm.contrib import tenumerate, tmap, tzip
 
 from .tests_tqdm import StringIO, closing, importorskip
@@ -13,49 +16,56 @@
     return x + 1
 
 
-def test_enumerate():
+@pytest.mark.parametrize("tqdm_kwargs", [{}, {"tqdm_class": tqdm}])
+def test_enumerate(tqdm_kwargs):
     """Test contrib.tenumerate"""
     with closing(StringIO()) as our_file:
         a = range(9)
-        assert list(tenumerate(a, file=our_file)) == list(enumerate(a))
-        assert list(tenumerate(a, 42, file=our_file)) == list(enumerate(a, 42))
+        assert list(tenumerate(a, file=our_file, **tqdm_kwargs)) == 
list(enumerate(a))
+        assert list(tenumerate(a, 42, file=our_file, **tqdm_kwargs)) == list(
+            enumerate(a, 42)
+        )
     with closing(StringIO()) as our_file:
-        _ = list(tenumerate((i for i in a), file=our_file))
+        _ = list(tenumerate((i for i in a), file=our_file, **tqdm_kwargs))
         assert "100%" not in our_file.getvalue()
     with closing(StringIO()) as our_file:
-        _ = list(tenumerate((i for i in a), file=our_file, total=len(a)))
+        _ = list(tenumerate((i for i in a), file=our_file, total=len(a), 
**tqdm_kwargs))
         assert "100%" in our_file.getvalue()
 
 
 def test_enumerate_numpy():
     """Test contrib.tenumerate(numpy.ndarray)"""
-    np = importorskip('numpy')
+    np = importorskip("numpy")
     with closing(StringIO()) as our_file:
         a = np.random.random((42, 7))
         assert list(tenumerate(a, file=our_file)) == list(np.ndenumerate(a))
 
 
-def test_zip():
+@pytest.mark.parametrize("tqdm_kwargs", [{}, {"tqdm_class": tqdm}])
+def test_zip(tqdm_kwargs):
     """Test contrib.tzip"""
     with closing(StringIO()) as our_file:
         a = range(9)
         b = [i + 1 for i in a]
         if sys.version_info[:1] < (3,):
-            assert tzip(a, b, file=our_file) == zip(a, b)
+            assert tzip(a, b, file=our_file, **tqdm_kwargs) == zip(a, b)
         else:
-            gen = tzip(a, b, file=our_file)
+            gen = tzip(a, b, file=our_file, **tqdm_kwargs)
             assert gen != list(zip(a, b))
             assert list(gen) == list(zip(a, b))
 
 
-def test_map():
+@pytest.mark.parametrize("tqdm_kwargs", [{}, {"tqdm_class": tqdm}])
+def test_map(tqdm_kwargs):
     """Test contrib.tmap"""
     with closing(StringIO()) as our_file:
         a = range(9)
         b = [i + 1 for i in a]
         if sys.version_info[:1] < (3,):
-            assert tmap(lambda x: x + 1, a, file=our_file) == map(incr, a)
+            assert tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs) == 
map(
+                incr, a
+            )
         else:
-            gen = tmap(lambda x: x + 1, a, file=our_file)
+            gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs)
             assert gen != b
             assert list(gen) == b
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tests/tests_contrib_logging.py 
new/tqdm-4.60.0/tests/tests_contrib_logging.py
--- old/tqdm-4.59.0/tests/tests_contrib_logging.py      1970-01-01 
01:00:00.000000000 +0100
+++ new/tqdm-4.60.0/tests/tests_contrib_logging.py      2021-04-06 
03:22:58.000000000 +0200
@@ -0,0 +1,181 @@
+# pylint: disable=missing-module-docstring, missing-class-docstring
+# pylint: disable=missing-function-docstring, no-self-use
+from __future__ import absolute_import
+
+import logging
+import logging.handlers
+import sys
+from io import StringIO
+
+import pytest
+
+from tqdm import tqdm
+from tqdm.contrib.logging import _get_first_found_console_logging_formatter
+from tqdm.contrib.logging import _TqdmLoggingHandler as TqdmLoggingHandler
+from tqdm.contrib.logging import logging_redirect_tqdm, tqdm_logging_redirect
+
+from .tests_tqdm import importorskip
+
+LOGGER = logging.getLogger(__name__)
+
+TEST_LOGGING_FORMATTER = logging.Formatter()
+
+
+class CustomTqdm(tqdm):
+    messages = []
+
+    @classmethod
+    def write(cls, s, **__):  # pylint: disable=arguments-differ
+        CustomTqdm.messages.append(s)
+
+
+class ErrorRaisingTqdm(tqdm):
+    exception_class = RuntimeError
+
+    @classmethod
+    def write(cls, s, **__):  # pylint: disable=arguments-differ
+        raise ErrorRaisingTqdm.exception_class('fail fast')
+
+
+class TestTqdmLoggingHandler:
+    def test_should_call_tqdm_write(self):
+        CustomTqdm.messages = []
+        logger = logging.Logger('test')
+        logger.handlers = [TqdmLoggingHandler(CustomTqdm)]
+        logger.info('test')
+        assert CustomTqdm.messages == ['test']
+
+    def test_should_call_handle_error_if_exception_was_thrown(self):
+        patch = importorskip('unittest.mock').patch
+        logger = logging.Logger('test')
+        ErrorRaisingTqdm.exception_class = RuntimeError
+        handler = TqdmLoggingHandler(ErrorRaisingTqdm)
+        logger.handlers = [handler]
+        with patch.object(handler, 'handleError') as mock:
+            logger.info('test')
+            assert mock.called
+
+    @pytest.mark.parametrize('exception_class', [
+        KeyboardInterrupt,
+        SystemExit
+    ])
+    def test_should_not_swallow_certain_exceptions(self, exception_class):
+        logger = logging.Logger('test')
+        ErrorRaisingTqdm.exception_class = exception_class
+        handler = TqdmLoggingHandler(ErrorRaisingTqdm)
+        logger.handlers = [handler]
+        with pytest.raises(exception_class):
+            logger.info('test')
+
+
+class TestGetFirstFoundConsoleLoggingFormatter:
+    def test_should_return_none_for_no_handlers(self):
+        assert _get_first_found_console_logging_formatter([]) is None
+
+    def test_should_return_none_without_stream_handler(self):
+        handler = logging.handlers.MemoryHandler(capacity=1)
+        handler.formatter = TEST_LOGGING_FORMATTER
+        assert _get_first_found_console_logging_formatter([handler]) is None
+
+    def test_should_return_none_for_stream_handler_not_stdout_or_stderr(self):
+        handler = logging.StreamHandler(StringIO())
+        handler.formatter = TEST_LOGGING_FORMATTER
+        assert _get_first_found_console_logging_formatter([handler]) is None
+
+    def test_should_return_stream_handler_formatter_if_stream_is_stdout(self):
+        handler = logging.StreamHandler(sys.stdout)
+        handler.formatter = TEST_LOGGING_FORMATTER
+        assert _get_first_found_console_logging_formatter(
+            [handler]
+        ) == TEST_LOGGING_FORMATTER
+
+    def test_should_return_stream_handler_formatter_if_stream_is_stderr(self):
+        handler = logging.StreamHandler(sys.stderr)
+        handler.formatter = TEST_LOGGING_FORMATTER
+        assert _get_first_found_console_logging_formatter(
+            [handler]
+        ) == TEST_LOGGING_FORMATTER
+
+
+class TestRedirectLoggingToTqdm:
+    def test_should_add_and_remove_tqdm_handler(self):
+        logger = logging.Logger('test')
+        with logging_redirect_tqdm(loggers=[logger]):
+            assert len(logger.handlers) == 1
+            assert isinstance(logger.handlers[0], TqdmLoggingHandler)
+        assert not logger.handlers
+
+    def test_should_remove_and_restore_console_handlers(self):
+        logger = logging.Logger('test')
+        stderr_console_handler = logging.StreamHandler(sys.stderr)
+        stdout_console_handler = logging.StreamHandler(sys.stderr)
+        logger.handlers = [stderr_console_handler, stdout_console_handler]
+        with logging_redirect_tqdm(loggers=[logger]):
+            assert len(logger.handlers) == 1
+            assert isinstance(logger.handlers[0], TqdmLoggingHandler)
+        assert logger.handlers == [stderr_console_handler, 
stdout_console_handler]
+
+    def test_should_inherit_console_logger_formatter(self):
+        logger = logging.Logger('test')
+        formatter = logging.Formatter('custom: %(message)s')
+        console_handler = logging.StreamHandler(sys.stderr)
+        console_handler.setFormatter(formatter)
+        logger.handlers = [console_handler]
+        with logging_redirect_tqdm(loggers=[logger]):
+            assert logger.handlers[0].formatter == formatter
+
+    def test_should_not_remove_stream_handlers_not_fot_stdout_or_stderr(self):
+        logger = logging.Logger('test')
+        stream_handler = logging.StreamHandler(StringIO())
+        logger.addHandler(stream_handler)
+        with logging_redirect_tqdm(loggers=[logger]):
+            assert len(logger.handlers) == 2
+            assert logger.handlers[0] == stream_handler
+            assert isinstance(logger.handlers[1], TqdmLoggingHandler)
+        assert logger.handlers == [stream_handler]
+
+
+class TestTqdmWithLoggingRedirect:
+    def test_should_add_and_remove_handler_from_root_logger_by_default(self):
+        original_handlers = list(logging.root.handlers)
+        with tqdm_logging_redirect(total=1) as pbar:
+            assert isinstance(logging.root.handlers[-1], TqdmLoggingHandler)
+            LOGGER.info('test')
+            pbar.update(1)
+        assert logging.root.handlers == original_handlers
+
+    def test_should_add_and_remove_handler_from_custom_logger(self):
+        logger = logging.Logger('test')
+        with tqdm_logging_redirect(total=1, loggers=[logger]) as pbar:
+            assert len(logger.handlers) == 1
+            assert isinstance(logger.handlers[0], TqdmLoggingHandler)
+            logger.info('test')
+            pbar.update(1)
+        assert not logger.handlers
+
+    def test_should_not_fail_with_logger_without_console_handler(self):
+        logger = logging.Logger('test')
+        logger.handlers = []
+        with tqdm_logging_redirect(total=1, loggers=[logger]):
+            logger.info('test')
+        assert not logger.handlers
+
+    def test_should_format_message(self):
+        logger = logging.Logger('test')
+        console_handler = logging.StreamHandler(sys.stdout)
+        console_handler.setFormatter(logging.Formatter(
+            r'prefix:%(message)s'
+        ))
+        logger.handlers = [console_handler]
+        CustomTqdm.messages = []
+        with tqdm_logging_redirect(loggers=[logger], tqdm_class=CustomTqdm):
+            logger.info('test')
+        assert CustomTqdm.messages == ['prefix:test']
+
+    def test_use_root_logger_by_default_and_write_to_custom_tqdm(self):
+        logger = logging.root
+        CustomTqdm.messages = []
+        with tqdm_logging_redirect(total=1, tqdm_class=CustomTqdm) as pbar:
+            assert isinstance(pbar, CustomTqdm)
+            logger.info('test')
+            assert CustomTqdm.messages == ['test']
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tests_notebook.ipynb 
new/tqdm-4.60.0/tests_notebook.ipynb
--- old/tqdm-4.59.0/tests_notebook.ipynb        1970-01-01 01:00:00.000000000 
+0100
+++ new/tqdm-4.60.0/tests_notebook.ipynb        2021-04-06 03:22:58.000000000 
+0200
@@ -0,0 +1,512 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "This file is part of the [test suite](./tests) and will be moved there 
when 
[nbval#116](https://github.com/computationalmodelling/nbval/issues/116#issuecomment-793148404)
 is fixed.\n",
+    "\n",
+    "See [DEMO.ipynb](DEMO.ipynb) instead for notebook examples."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from functools import partial\n",
+    "from time import sleep\n",
+    "\n",
+    "from tqdm.notebook import tqdm_notebook\n",
+    "from tqdm.notebook import tnrange\n",
+    "\n",
+    "# avoid displaying widgets by default (pollutes output cells)\n",
+    "tqdm = partial(tqdm_notebook, display=False)\n",
+    "trange = partial(tnrange, display=False)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Help on function display in module tqdm.notebook:\n",
+      "\n",
+      "display(self, msg=None, pos=None, close=False, bar_style=None, 
check_delay=True)\n",
+      "    Use `self.sp` to display `msg` in the specified `pos`.\n",
+      "    \n",
+      "    Consider overloading this function when inheriting to use e.g.:\n",
+      "    `self.some_frontend(**self.format_dict)` instead of `self.sp`.\n",
+      "    \n",
+      "    Parameters\n",
+      "    ----------\n",
+      "    msg  : str, optional. What to display (default: `repr(self)`).\n",
+      "    pos  : int, optional. Position to `moveto`\n",
+      "      (default: `abs(self.pos)`).\n",
+      "\n"
+     ]
+    }
+   ],
+   "source": [
+    "help(tqdm_notebook.display)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "7c18c038bf964b55941e228503292506",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "  0%|          | 0/9 [00:00<?, ?it/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0\n",
+      "1\n",
+      "2\n",
+      "3\n",
+      "4\n",
+      "5\n",
+      "6\n",
+      "7\n",
+      "8\n"
+     ]
+    },
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "e29668be41ca4e40b16fb98572b333a5",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "  0%|          | 0/9 [00:00<?, ?it/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    },
+    {
+     "data": {
+      "text/plain": [
+       "True"
+      ]
+     },
+     "execution_count": 3,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: basic use\n",
+    "with tqdm_notebook(range(9)) as t:\n",
+    "    for i in t:\n",
+    "        print(i)\n",
+    "assert t.container.children[1].bar_style == 'success'\n",
+    "\n",
+    "t = tqdm_notebook(total=9)\n",
+    "t.update()\n",
+    "t.refresh()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      " 11%|???         | 1/9 [00:00<00:00, 17.73it/s]\n",
+      " 20%|??????        | 1/5 [00:00<00:00, 341.50it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: reset\n",
+    "print(t)\n",
+    "t.reset(total=5)\n",
+    "t.update(1)\n",
+    "print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 5,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# NBVAL_TEST_NAME: bar_style\n",
+    "assert t.container.children[1].bar_style != 'danger'\n",
+    "t.close()\n",
+    "assert t.container.children[1].bar_style == 'danger'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 6,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|          | 0/8 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/8 [00:00<?, ?it/s]\n",
+      "1\n",
+      "  0%|          | 0/8 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/8 [00:00<?, ?it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: repr\n",
+    "with trange(1, 9) as t:\n",
+    "    print(t)\n",
+    "    print(t.container)\n",
+    "    it = iter(t)\n",
+    "    print(next(it))\n",
+    "    print(t)\n",
+    "    print(t.container)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 7,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "t = trange(9)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 8,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: display pre\n",
+    "print(t)\n",
+    "print(t.container)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 9,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "for i in t:\n",
+    "    pass"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 10,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "100%|??????????????????????????????| 9/9 [00:00<00:00, 132.23it/s]\n",
+      "100%|##########| 9/9 [00:00<00:00, 131.02it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: display post\n",
+    "print(t)\n",
+    "print(t.container)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 11,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "no total: 0it [00:00, ?it/s]\n",
+      "no total: 1it [00:00, 47.83it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: no total\n",
+    "with tqdm(desc=\"no total\") as t:\n",
+    "    print(t)\n",
+    "    t.update()\n",
+    "    print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|                                       | 0/9 [00:00<?, ?it/s]\n",
+      " 11%|????????????                           | 1/9 [00:00<00:00, 
45.06it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: ncols\n",
+    "with trange(9, ncols=66) as t:\n",
+    "    print(t)\n",
+    "    for i in t:\n",
+    "        if i == 1:\n",
+    "            break\n",
+    "    print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 13,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "100%|??????????????????????????????| 1/1 [00:00<00:00, 54.60it/s]\n",
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n",
+      " 11%|???         | 1/9 [00:00<00:00, 57.43it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: leave\n",
+    "assert (False, None) != (getattr(t.container, \"visible\", False), 
getattr(t.container, \"_ipython_display_\", None))\n",
+    "for total in (1, 9):\n",
+    "    with tqdm(total=total, leave=False) as t:\n",
+    "        print(t)\n",
+    "        t.update()\n",
+    "        print(t)\n",
+    "    assert total != 1 or (False, None) == (\n",
+    "        getattr(t.container, \"visible\", False), getattr(t.container, 
\"_ipython_display_\", None)\n",
+    "    )"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "0it [00:00, ?it/s]\n",
+      "1it [00:00, 47.87it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: no total\n",
+    "with tqdm() as t:\n",
+    "    print(t)\n",
+    "    t.update()\n",
+    "    print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 15,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "disable: None\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "100%|??????????????????????????????| 1/1 [00:00<00:00, 53.24it/s]\n",
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n",
+      " 11%|???         | 1/9 [00:00<00:00, 1752.01it/s]\n",
+      "0it [00:00, ?it/s]\n",
+      "1it [00:00, 35.88it/s]\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "100%|??????????????????????????????| 1/1 [00:00<00:00, 1880.85it/s]\n",
+      "disable: True\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/9 [00:00<?, ?it/s]\n",
+      "0it [00:00, ?it/s]\n",
+      "0it [00:00, ?it/s]\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n",
+      "  0%|          | 0/1 [00:00<?, ?it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: reset and disable\n",
+    "for disable in (None, True):\n",
+    "    print(\"disable:\", disable)\n",
+    "    with tqdm(total=1, disable=disable) as t:\n",
+    "        print(t)\n",
+    "        t.update()\n",
+    "        print(t)\n",
+    "\n",
+    "        t.reset(total=9)\n",
+    "        print(t)\n",
+    "        t.update()\n",
+    "        print(t)\n",
+    "    with tqdm(disable=disable) as t:\n",
+    "        print(t)\n",
+    "        t.update()\n",
+    "        print(t)\n",
+    "\n",
+    "        t.reset(total=1)\n",
+    "        print(t)\n",
+    "        t.update()\n",
+    "        print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 16,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|| 0/1 [00:00<?, ?it/s]\n",
+      "100%|| 1/1 [00:00<00:00, 32.57it/s]\n",
+      "  0%|          \n",
+      "100%|??????????????????????????????\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: bar_format\n",
+    "with tqdm(total=1, bar_format='{l_bar}{r_bar}') as t:\n",
+    "    print(t)\n",
+    "    t.update()\n",
+    "    print(t)\n",
+    "\n",
+    "with tqdm(total=1, bar_format='{l_bar}{bar}') as t:\n",
+    "    print(t)\n",
+    "    t.update()\n",
+    "    print(t)"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 17,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "  0%|\u001b[33m          \u001b[0m| 0/1 [00:00<?, ?it/s]\n",
+      "100%|\u001b[33m??????????????????????????????\u001b[0m| 1/1 
[00:00<00:00, 47.14it/s]\n"
+     ]
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: colour\n",
+    "assert t.colour != 'yellow'\n",
+    "with tqdm(total=1, colour='yellow') as t:\n",
+    "    print(t)\n",
+    "    t.update()\n",
+    "    print(t)\n",
+    "    assert t.colour == 'yellow'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 18,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "# NBVAL_TEST_NAME: delay no trigger\n",
+    "with tqdm_notebook(total=1, delay=10) as t:\n",
+    "    t.update()"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 19,
+   "metadata": {},
+   "outputs": [
+    {
+     "data": {
+      "application/vnd.jupyter.widget-view+json": {
+       "model_id": "fe102eedbb4f437783fbd0cff32f6613",
+       "version_major": 2,
+       "version_minor": 0
+      },
+      "text/plain": [
+       "100%|##########| 1/1 [00:00<00:00,  7.68it/s]"
+      ]
+     },
+     "metadata": {},
+     "output_type": "display_data"
+    }
+   ],
+   "source": [
+    "# NBVAL_TEST_NAME: delay trigger\n",
+    "with tqdm_notebook(total=1, delay=0.1) as t:\n",
+    "    sleep(0.1)\n",
+    "    t.update()"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python [conda env:tqdm]",
+   "language": "python",
+   "name": "conda-env-tqdm-py"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython"
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tox.ini new/tqdm-4.60.0/tox.ini
--- old/tqdm-4.59.0/tox.ini     2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/tox.ini     2021-04-06 03:22:58.000000000 +0200
@@ -4,7 +4,7 @@
 # and then run "tox" from this directory.
 
 [tox]
-# deprecation warning: py{27,py2,34,35}
+# deprecation warning: py{27,py2,34,35,36}
 envlist=py{27,34,35,36,37,38,39,py2,py3}{,-tf}{,-keras}, perf, setup.py
 isolated_build=True
 
@@ -13,7 +13,9 @@
     pytest
     pytest-cov
     pytest-timeout
-    py{37,38,39}: pytest-asyncio
+    py3{7,8,9}: pytest-asyncio
+    py3{6,7,8,9}: ipywidgets
+    py3{6,7,8,9}: 
git+https://github.com/casperdcl/nbval.git@named_cells#egg=nbval
     coverage
     coveralls
     codecov
@@ -32,10 +34,11 @@
     numpy
     pandas
     keras: keras
-    py{36,37,38,39}: rich
+    py3{6,7,8,9}: rich
     tf: tensorflow
 commands=
-    pytest --cov=tqdm --cov-report=xml --cov-report=term -k "not perf"
+    py3{6,7,8,9}: pytest --cov=tqdm --cov-report= tests_notebook.ipynb --nbval 
--current-env -W=ignore --sanitize-with=setup.cfg
+    pytest --cov=tqdm --cov-report=xml --cov-report=term --cov-append -k "not 
perf"
     {[core]commands}
 allowlist_externals=codacy
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/_dist_ver.py 
new/tqdm-4.60.0/tqdm/_dist_ver.py
--- old/tqdm-4.59.0/tqdm/_dist_ver.py   2021-03-05 21:14:25.000000000 +0100
+++ new/tqdm-4.60.0/tqdm/_dist_ver.py   2021-04-06 03:23:17.000000000 +0200
@@ -1 +1 @@
-__version__ = '4.59.0'
+__version__ = '4.60.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/contrib/__init__.py 
new/tqdm-4.60.0/tqdm/contrib/__init__.py
--- old/tqdm-4.59.0/tqdm/contrib/__init__.py    2021-03-05 21:14:01.000000000 
+0100
+++ new/tqdm-4.60.0/tqdm/contrib/__init__.py    2021-04-06 03:22:58.000000000 
+0200
@@ -16,6 +16,7 @@
 
 class DummyTqdmFile(ObjectWrapper):
     """Dummy file-like that will write to tqdm"""
+
     def __init__(self, wrapped):
         super(DummyTqdmFile, self).__init__(wrapped)
         self._buf = []
@@ -80,7 +81,7 @@
     """
     kwargs = tqdm_kwargs.copy()
     tqdm_class = kwargs.pop("tqdm_class", tqdm_auto)
-    for i in zip(tqdm_class(iter1, **tqdm_kwargs), *iter2plus):
+    for i in zip(tqdm_class(iter1, **kwargs), *iter2plus):
         yield i
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/contrib/logging.py 
new/tqdm-4.60.0/tqdm/contrib/logging.py
--- old/tqdm-4.59.0/tqdm/contrib/logging.py     1970-01-01 01:00:00.000000000 
+0100
+++ new/tqdm-4.60.0/tqdm/contrib/logging.py     2021-04-06 03:22:58.000000000 
+0200
@@ -0,0 +1,126 @@
+"""
+Helper functionality for interoperability with stdlib `logging`.
+"""
+from __future__ import absolute_import
+
+import logging
+import sys
+from contextlib import contextmanager
+
+try:
+    from typing import Iterator, List, Optional, Type  # pylint: 
disable=unused-import
+except ImportError:
+    pass
+
+from ..std import tqdm as std_tqdm
+
+
+class _TqdmLoggingHandler(logging.StreamHandler):
+    def __init__(
+        self,
+        tqdm_class=std_tqdm  # type: Type[std_tqdm]
+    ):
+        super(_TqdmLoggingHandler, self).__init__()
+        self.tqdm_class = tqdm_class
+
+    def emit(self, record):
+        try:
+            msg = self.format(record)
+            self.tqdm_class.write(msg)
+            self.flush()
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except:  # noqa pylint: disable=bare-except
+            self.handleError(record)
+
+
+def _is_console_logging_handler(handler):
+    return (isinstance(handler, logging.StreamHandler)
+            and handler.stream in {sys.stdout, sys.stderr})
+
+
+def _get_first_found_console_logging_formatter(handlers):
+    for handler in handlers:
+        if _is_console_logging_handler(handler):
+            return handler.formatter
+
+
+@contextmanager
+def logging_redirect_tqdm(
+    loggers=None,  # type: Optional[List[logging.Logger]],
+    tqdm_class=std_tqdm  # type: Type[std_tqdm]
+):
+    # type: (...) -> Iterator[None]
+    """
+    Context manager redirecting console logging to `tqdm.write()`, leaving
+    other logging handlers (e.g. log files) unaffected.
+
+    Parameters
+    ----------
+    loggers  : list, optional
+      Which handlers to redirect (default: [logging.root]).
+    tqdm_class  : optional
+
+    Example
+    -------
+    ```python
+    import logging
+    from tqdm import trange
+    from tqdm.contrib.logging import logging_redirect_tqdm
+
+    LOG = logging.getLogger(__name__)
+
+    if __name__ == '__main__':
+        logging.basicConfig(level=logging.INFO)
+        with logging_redirect_tqdm():
+            for i in trange(9):
+                if i == 4:
+                    LOG.info("console logging redirected to `tqdm.write()`")
+        # logging restored
+    ```
+    """
+    if loggers is None:
+        loggers = [logging.root]
+    original_handlers_list = [logger.handlers for logger in loggers]
+    try:
+        for logger in loggers:
+            tqdm_handler = _TqdmLoggingHandler(tqdm_class)
+            tqdm_handler.setFormatter(
+                _get_first_found_console_logging_formatter(logger.handlers))
+            logger.handlers = [
+                handler for handler in logger.handlers
+                if not _is_console_logging_handler(handler)] + [tqdm_handler]
+        yield
+    finally:
+        for logger, original_handlers in zip(loggers, original_handlers_list):
+            logger.handlers = original_handlers
+
+
+@contextmanager
+def tqdm_logging_redirect(
+    *args,
+    # loggers=None,  # type: Optional[List[logging.Logger]]
+    # tqdm=None,  # type: Optional[Type[tqdm.tqdm]]
+    **kwargs
+):
+    # type: (...) -> Iterator[None]
+    """
+    Convenience shortcut for:
+    ```python
+    with tqdm_class(*args, **tqdm_kwargs) as pbar:
+        with logging_redirect_tqdm(loggers=loggers, tqdm_class=tqdm_class):
+            yield pbar
+    ```
+
+    Parameters
+    ----------
+    tqdm_class  : optional, (default: tqdm.std.tqdm).
+    loggers  : optional, list.
+    **tqdm_kwargs  : passed to `tqdm_class`.
+    """
+    tqdm_kwargs = kwargs.copy()
+    loggers = tqdm_kwargs.pop('loggers', None)
+    tqdm_class = tqdm_kwargs.pop('tqdm_class', std_tqdm)
+    with tqdm_class(*args, **tqdm_kwargs) as pbar:
+        with logging_redirect_tqdm(loggers=loggers, tqdm_class=tqdm_class):
+            yield pbar
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/dask.py new/tqdm-4.60.0/tqdm/dask.py
--- old/tqdm-4.59.0/tqdm/dask.py        2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/tqdm/dask.py        2021-04-06 03:22:58.000000000 +0200
@@ -17,7 +17,7 @@
         """
         Parameters
         ----------
-        tqdm_class : optional
+        tqdm_class  : optional
             `tqdm` class to use for bars [default: `tqdm.auto.tqdm`].
         tqdm_kwargs  : optional
             Any other arguments used for all bars.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/keras.py 
new/tqdm-4.60.0/tqdm/keras.py
--- old/tqdm-4.59.0/tqdm/keras.py       2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/tqdm/keras.py       2021-04-06 03:22:58.000000000 +0200
@@ -45,7 +45,7 @@
             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  : optional
             `tqdm` class to use for bars [default: `tqdm.auto.tqdm`].
         tqdm_kwargs  : optional
             Any other arguments used for all bars.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm/notebook.py 
new/tqdm-4.60.0/tqdm/notebook.py
--- old/tqdm-4.59.0/tqdm/notebook.py    2021-03-05 21:14:01.000000000 +0100
+++ new/tqdm-4.60.0/tqdm/notebook.py    2021-04-06 03:22:58.000000000 +0200
@@ -145,7 +145,7 @@
 
     def display(self, msg=None, pos=None,
                 # additional signals
-                close=False, bar_style=None):
+                close=False, bar_style=None, check_delay=True):
         # Note: contrary to native tqdm, msg='' does NOT clear bar
         # goal is to keep all infos if error happens so user knows
         # at which iteration the loop failed.
@@ -190,6 +190,10 @@
             except AttributeError:
                 self.container.visible = False
 
+        if check_delay and self.delay > 0 and not self.displayed:
+            display(self.container)
+            self.displayed = True
+
     @property
     def colour(self):
         if hasattr(self, 'container'):
@@ -234,14 +238,16 @@
         total = self.total * unit_scale if self.total else self.total
         self.container = self.status_printer(self.fp, total, self.desc, 
self.ncols)
         self.container.pbar = self
-        if display_here:
+        self.displayed = False
+        if display_here and self.delay <= 0:
             display(self.container)
+            self.displayed = True
         self.disp = self.display
         self.colour = colour
 
         # Print initial bar state
         if not self.disable:
-            self.display()
+            self.display(check_delay=False)
 
     def __iter__(self):
         try:
@@ -268,16 +274,18 @@
         # since this could be a shared bar which the user will `reset()`
 
     def close(self):
+        if self.disable:
+            return
         super(tqdm_notebook, self).close()
         # Try to detect if there was an error or KeyboardInterrupt
         # in manual mode: if n < total, things probably got wrong
         if self.total and self.n < self.total:
-            self.disp(bar_style='danger')
+            self.disp(bar_style='danger', check_delay=False)
         else:
             if self.leave:
-                self.disp(bar_style='success')
+                self.disp(bar_style='success', check_delay=False)
             else:
-                self.disp(close=True)
+                self.disp(close=True, check_delay=False)
 
     def clear(self, *_, **__):
         pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm.egg-info/PKG-INFO 
new/tqdm-4.60.0/tqdm.egg-info/PKG-INFO
--- old/tqdm-4.59.0/tqdm.egg-info/PKG-INFO      2021-03-05 21:14:25.000000000 
+0100
+++ new/tqdm-4.60.0/tqdm.egg-info/PKG-INFO      2021-04-06 03:23:17.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: tqdm
-Version: 4.59.0
+Version: 4.60.0
 Summary: Fast, Extensible Progress Meter
 Home-page: https://github.com/tqdm/tqdm
 Maintainer: tqdm developers
@@ -1333,6 +1333,33 @@
             # After the `with`, printing is restored
             print("Done!")
         
+        Redirecting ``logging``
+        ~~~~~~~~~~~~~~~~~~~~~~~
+        
+        Similar to ``sys.stdout``/``sys.stderr`` as detailed above, console 
``logging``
+        may also be redirected to ``tqdm.write()``.
+        
+        Warning: if also redirecting ``sys.stdout``/``sys.stderr``, make sure 
to
+        redirect ``logging`` first if needed.
+        
+        Helper methods are available in ``tqdm.contrib.logging``. For example:
+        
+        .. code:: python
+        
+            import logging
+            from tqdm import trange
+            from tqdm.contrib.logging import logging_redirect_tqdm
+        
+            LOG = logging.getLogger(__name__)
+        
+            if __name__ == '__main__':
+                logging.basicConfig(level=logging.INFO)
+                with logging_redirect_tqdm():
+                    for i in trange(9):
+                        if i == 4:
+                            LOG.info("console logging redirected to 
`tqdm.write()`")
+                # logging restored
+        
         Monitoring thread, intervals and miniters
         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tqdm-4.59.0/tqdm.egg-info/SOURCES.txt 
new/tqdm-4.60.0/tqdm.egg-info/SOURCES.txt
--- old/tqdm-4.59.0/tqdm.egg-info/SOURCES.txt   2021-03-05 21:14:25.000000000 
+0100
+++ new/tqdm-4.60.0/tqdm.egg-info/SOURCES.txt   2021-04-06 03:23:17.000000000 
+0200
@@ -11,6 +11,7 @@
 pyproject.toml
 setup.cfg
 setup.py
+tests_notebook.ipynb
 tox.ini
 examples/7zx.py
 examples/async_coroutines.py
@@ -31,6 +32,7 @@
 tests/tests_asyncio.py
 tests/tests_concurrent.py
 tests/tests_contrib.py
+tests/tests_contrib_logging.py
 tests/tests_dask.py
 tests/tests_gui.py
 tests/tests_itertools.py
@@ -80,5 +82,6 @@
 tqdm/contrib/concurrent.py
 tqdm/contrib/discord.py
 tqdm/contrib/itertools.py
+tqdm/contrib/logging.py
 tqdm/contrib/telegram.py
 tqdm/contrib/utils_worker.py
\ No newline at end of file

Reply via email to