From a587f3037eb6822573ffe36eda79105569a5a8b4 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Fri, 3 Mar 2023 15:43:42 +0000 Subject: [PATCH] drop py<=3.6 --- .meta/.readme.rst | 5 +- .meta/requirements-test.txt | 2 +- CONTRIBUTING.md | 2 +- DEMO.ipynb | 2 +- README.rst | 9 +-- benchmarks/benchmarks.py | 5 +- environment.yml | 4 +- examples/parallel_bars.py | 11 +-- examples/simple_examples.py | 7 +- examples/tqdm_wget.py | 5 +- setup.cfg | 12 +-- tests/conftest.py | 12 --- tests/py37_asyncio.py | 128 ------------------------------ tests/tests_asyncio.py | 138 ++++++++++++++++++++++++++++++--- tests/tests_contrib.py | 22 ++---- tests/tests_main.py | 63 ++++++++------- tests/tests_perf.py | 20 ++--- tests/tests_rich.py | 5 +- tests/tests_synchronisation.py | 23 +----- tests/tests_tqdm.py | 105 +++++++++++-------------- tqdm/__init__.py | 5 +- tqdm/_utils.py | 7 +- tqdm/asyncio.py | 2 +- tqdm/auto.py | 40 +++++----- tqdm/cli.py | 5 +- tqdm/contrib/__init__.py | 16 ++-- tqdm/contrib/concurrent.py | 15 +--- tqdm/contrib/discord.py | 8 +- tqdm/contrib/slack.py | 8 +- tqdm/contrib/telegram.py | 8 +- tqdm/gui.py | 9 +-- tqdm/notebook.py | 8 +- tqdm/rich.py | 8 +- tqdm/std.py | 35 ++++----- tqdm/tk.py | 8 +- tqdm/utils.py | 23 +----- 36 files changed, 309 insertions(+), 476 deletions(-) delete mode 100644 tests/py37_asyncio.py diff --git a/.meta/.readme.rst b/.meta/.readme.rst index 23aac0771..2f779d76d 100644 --- a/.meta/.readme.rst +++ b/.meta/.readme.rst @@ -412,10 +412,7 @@ Returns """Registers the current `tqdm` class with `pandas`.""" def trange(*args, **tqdm_kwargs): - """ - A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ + """Shortcut for `tqdm(range(*args), **tqdm_kwargs)`.""" Convenience Functions ~~~~~~~~~~~~~~~~~~~~~ diff --git a/.meta/requirements-test.txt b/.meta/requirements-test.txt index 80f291620..4fc41b89a 100644 --- a/.meta/requirements-test.txt +++ b/.meta/requirements-test.txt @@ -1,7 +1,7 @@ pre-commit pytest +pytest-asyncio pytest-cov pytest-timeout nbval ipywidgets -# py>=37: pytest-asyncio diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4cd86d02a..509f86aee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -51,7 +51,7 @@ However it would be helpful to bear in mind: * use two spaces between variable name and colon, specify a type, and most likely state that it's optional: `VAR:TYPE[, optional]` * use [default: ...] for default values of keyword arguments + will not break backward compatibility unless there is a very good reason - * e.g. breaking py26 compatibility purely in favour of readability (such as converting `dict(a=1)` to `{'a': 1}`) is not a good enough reason + * e.g. breaking py26 compatibility purely in favour of minor readability changes (such as converting `dict(a=1)` to `{'a': 1}`) is not a good enough reason + API changes should be discussed carefully + remember, with millions of downloads per month, `tqdm` must be extremely fast and reliable - Any other kind of change may be included in a (possibly new) submodule diff --git a/DEMO.ipynb b/DEMO.ipynb index b892af4b7..3354e7dfb 100644 --- a/DEMO.ipynb +++ b/DEMO.ipynb @@ -40,7 +40,7 @@ "metadata": {}, "source": [ "`trange(N)` can be also used as a convenient shortcut for\n", - "`tqdm(xrange(N))`." + "`tqdm(range(N))`." ] }, { diff --git a/README.rst b/README.rst index a45f98d25..c10ab87c3 100644 --- a/README.rst +++ b/README.rst @@ -450,9 +450,7 @@ Parameters * unit_divisor : float, optional [default: 1000], ignored unless ``unit_scale`` is True. * write_bytes : bool, optional - If (default: None) and ``file`` is unspecified, - bytes will be written in Python 2. If ``True`` will also write - bytes. In all other cases will default to unicode. + Whether to write bytes. If (default: False) will write unicode. * lock_args : tuple, optional Passed to ``refresh`` for intermediate output (initialisation, iterating, and updating). @@ -631,10 +629,7 @@ Returns """Registers the current `tqdm` class with `pandas`.""" def trange(*args, **tqdm_kwargs): - """ - A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ + """Shortcut for `tqdm(range(*args), **tqdm_kwargs)`.""" Convenience Functions ~~~~~~~~~~~~~~~~~~~~~ diff --git a/benchmarks/benchmarks.py b/benchmarks/benchmarks.py index 37f5df419..fcf43bbe7 100644 --- a/benchmarks/benchmarks.py +++ b/benchmarks/benchmarks.py @@ -14,10 +14,7 @@ def __init__(self, length): except ImportError: from time import clock self.time = clock - try: - self.iterable = xrange(int(length)) - except NameError: - self.iterable = range(int(length)) + self.iterable = range(int(length)) def run(self, cls): pbar = cls(self.iterable) diff --git a/environment.yml b/environment.yml index 871e3e8ed..95e6dae53 100644 --- a/environment.yml +++ b/environment.yml @@ -5,7 +5,7 @@ channels: - defaults dependencies: # base -- python=3 +- python >=3.7 - pip - ipykernel - ipywidgets @@ -20,7 +20,7 @@ dependencies: - pytest - pytest-cov - pytest-timeout -- pytest-asyncio # [py>=3.7] +- pytest-asyncio - nbval - coverage # extras diff --git a/examples/parallel_bars.py b/examples/parallel_bars.py index 498fd61df..c6aef2926 100644 --- a/examples/parallel_bars.py +++ b/examples/parallel_bars.py @@ -1,6 +1,5 @@ from __future__ import print_function -import sys from concurrent.futures import ThreadPoolExecutor from functools import partial from multiprocessing import Pool, RLock, freeze_support @@ -12,7 +11,6 @@ from tqdm.contrib.concurrent import process_map, thread_map NUM_SUBITERS = 9 -PY2 = sys.version_info[:1] <= (2,) def progresser(n, auto_position=True, write_safe=False, blocking=True, progress=False): @@ -37,7 +35,7 @@ def progresser(n, auto_position=True, write_safe=False, blocking=True, progress= L = list(range(NUM_SUBITERS))[::-1] print("Simple thread mapping") - thread_map(partial(progresser, write_safe=not PY2), L, max_workers=4) + thread_map(partial(progresser, write_safe=True), L, max_workers=4) print("Simple process mapping") process_map(partial(progresser), L, max_workers=4) @@ -54,8 +52,5 @@ def progresser(n, auto_position=True, write_safe=False, blocking=True, progress= print("Multi-threading") tqdm.set_lock(TRLock()) - pool_args = {} - if not PY2: - pool_args.update(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) - with ThreadPoolExecutor(**pool_args) as p: - p.map(partial(progresser, progress=True, write_safe=not PY2, blocking=False), L) + with ThreadPoolExecutor(initializer=tqdm.set_lock, initargs=(tqdm.get_lock(),)) as p: + p.map(partial(progresser, progress=True, write_safe=True, blocking=False), L) diff --git a/examples/simple_examples.py b/examples/simple_examples.py index f3401d357..bff1c9e02 100644 --- a/examples/simple_examples.py +++ b/examples/simple_examples.py @@ -2,7 +2,7 @@ # Simple tqdm examples and profiling # Benchmark -for i in _range(int(1e8)): +for i in range(int(1e8)): pass # Basic demo @@ -33,7 +33,7 @@ except ImportError: pass else: - for i in ProgressBar()(_range(int(1e8))): + for i in ProgressBar()(range(int(1e8))): pass # Dynamic miniters benchmark @@ -61,5 +61,4 @@ stmts = filter(None, re.split(r'\n\s*#.*?\n', __doc__)) for s in stmts: print(s.replace('import tqdm\n', '')) - print(timeit(stmt='try:\n\t_range = xrange' - '\nexcept:\n\t_range = range\n' + s, number=1), 'seconds') + print(timeit(stmt=s, number=1), 'seconds') diff --git a/examples/tqdm_wget.py b/examples/tqdm_wget.py index 8663e5a39..ee8b9f374 100644 --- a/examples/tqdm_wget.py +++ b/examples/tqdm_wget.py @@ -20,11 +20,8 @@ The local file path in which to save the url [default: /dev/null]. """ -try: - from urllib import request as urllib -except ImportError: # py2 - import urllib from os import devnull +from urllib import request as urllib from docopt import docopt diff --git a/setup.cfg b/setup.cfg index 8b703af11..029b29a4b 100644 --- a/setup.cfg +++ b/setup.cfg @@ -44,15 +44,13 @@ classifiers= Operating System :: POSIX :: SunOS/Solaris Operating System :: Unix Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 Programming Language :: Python :: 3 - Programming Language :: Python :: 3.5 - Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 + Programming Language :: Python :: 3 :: Only Programming Language :: Python :: Implementation Programming Language :: Python :: Implementation :: IronPython Programming Language :: Python :: Implementation :: PyPy @@ -75,10 +73,9 @@ classifiers= Topic :: Utilities [options] setup_requires=setuptools>=42; setuptools_scm[toml]>=3.4 -python_requires=>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +python_requires=>=3.7 install_requires= colorama; platform_system == 'Windows' - importlib_resources; python_version < "3.7" tests_require=tox include_package_data=True packages=find: @@ -93,9 +90,6 @@ console_scripts= [options.packages.find] exclude=benchmarks, tests -[bdist_wheel] -universal=1 - [flake8] max_line_length=99 exclude=.asv,.eggs,.tox,.ipynb_checkpoints,build,dist,.git,__pycache__ diff --git a/tests/conftest.py b/tests/conftest.py index 67170442b..ce1f96569 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -27,15 +27,3 @@ def pretest_posttest(): tqdm._instances.clear() raise EnvironmentError( "{0} `tqdm` instances still in existence POST-test".format(n)) - - -if sys.version_info[0] > 2: - @fixture - def capsysbin(capsysbinary): - """alias for capsysbinary (py3)""" - return capsysbinary -else: - @fixture - def capsysbin(capsys): - """alias for capsys (py2)""" - return capsys diff --git a/tests/py37_asyncio.py b/tests/py37_asyncio.py deleted file mode 100644 index 8bf61e76a..000000000 --- a/tests/py37_asyncio.py +++ /dev/null @@ -1,128 +0,0 @@ -import asyncio -from functools import partial -from sys import platform -from time import time - -from tqdm.asyncio import tarange, tqdm_asyncio - -from .tests_tqdm import StringIO, closing, mark - -tqdm = partial(tqdm_asyncio, miniters=0, mininterval=0) -trange = partial(tarange, miniters=0, mininterval=0) -as_completed = partial(tqdm_asyncio.as_completed, miniters=0, mininterval=0) -gather = partial(tqdm_asyncio.gather, miniters=0, mininterval=0) - - -def count(start=0, step=1): - i = start - while True: - new_start = yield i - if new_start is None: - i += step - else: - i = new_start - - -async def acount(*args, **kwargs): - for i in count(*args, **kwargs): - yield i - - -@mark.asyncio -async def test_break(): - """Test asyncio break""" - pbar = tqdm(count()) - async for _ in pbar: - break - pbar.close() - - -@mark.asyncio -async def test_generators(capsys): - """Test asyncio generators""" - with tqdm(count(), desc="counter") as pbar: - async for i in pbar: - if i >= 8: - break - _, err = capsys.readouterr() - assert '9it' in err - - with tqdm(acount(), desc="async_counter") as pbar: - async for i in pbar: - if i >= 8: - break - _, err = capsys.readouterr() - assert '9it' in err - - -@mark.asyncio -async def test_range(): - """Test asyncio range""" - with closing(StringIO()) as our_file: - async for _ in tqdm(range(9), desc="range", file=our_file): - pass - assert '9/9' in our_file.getvalue() - our_file.seek(0) - our_file.truncate() - - async for _ in trange(9, desc="trange", file=our_file): - pass - assert '9/9' in our_file.getvalue() - - -@mark.asyncio -async def test_nested(): - """Test asyncio nested""" - with closing(StringIO()) as our_file: - async for _ in tqdm(trange(9, desc="inner", file=our_file), - desc="outer", file=our_file): - pass - assert 'inner: 100%' in our_file.getvalue() - assert 'outer: 100%' in our_file.getvalue() - - -@mark.asyncio -async def test_coroutines(): - """Test asyncio coroutine.send""" - with closing(StringIO()) as our_file: - with tqdm(count(), file=our_file) as pbar: - async for i in pbar: - if i == 9: - pbar.send(-10) - elif i < 0: - assert i == -9 - break - assert '10it' in our_file.getvalue() - - -@mark.slow -@mark.asyncio -@mark.parametrize("tol", [0.2 if platform.startswith("darwin") else 0.1]) -async def test_as_completed(capsys, tol): - """Test asyncio as_completed""" - for retry in range(3): - t = time() - skew = time() - t - for i in as_completed([asyncio.sleep(0.01 * i) for i in range(30, 0, -1)]): - await i - t = time() - t - 2 * skew - try: - assert 0.3 * (1 - tol) < t < 0.3 * (1 + tol), t - _, err = capsys.readouterr() - assert '30/30' in err - except AssertionError: - if retry == 2: - raise - - -async def double(i): - return i * 2 - - -@mark.asyncio -async def test_gather(capsys): - """Test asyncio gather""" - res = await gather(*map(double, range(30))) - _, err = capsys.readouterr() - assert '30/30' in err - assert res == list(range(0, 30 * 2, 2)) diff --git a/tests/tests_asyncio.py b/tests/tests_asyncio.py index 6f089264c..ddfa1b1b0 100644 --- a/tests/tests_asyncio.py +++ b/tests/tests_asyncio.py @@ -1,11 +1,129 @@ """Tests `tqdm.asyncio` on `python>=3.7`.""" -import sys - -if sys.version_info[:2] > (3, 6): - from .py37_asyncio import * # NOQA, pylint: disable=wildcard-import -else: - from .tests_tqdm import skip - try: - skip("async not supported", allow_module_level=True) - except TypeError: - pass +import asyncio +from functools import partial +from sys import platform +from time import time + +from tqdm.asyncio import tarange, tqdm_asyncio + +from .tests_tqdm import StringIO, closing, mark + +tqdm = partial(tqdm_asyncio, miniters=0, mininterval=0) +trange = partial(tarange, miniters=0, mininterval=0) +as_completed = partial(tqdm_asyncio.as_completed, miniters=0, mininterval=0) +gather = partial(tqdm_asyncio.gather, miniters=0, mininterval=0) + + +def count(start=0, step=1): + i = start + while True: + new_start = yield i + if new_start is None: + i += step + else: + i = new_start + + +async def acount(*args, **kwargs): + for i in count(*args, **kwargs): + yield i + + +@mark.asyncio +async def test_break(): + """Test asyncio break""" + pbar = tqdm(count()) + async for _ in pbar: + break + pbar.close() + + +@mark.asyncio +async def test_generators(capsys): + """Test asyncio generators""" + with tqdm(count(), desc="counter") as pbar: + async for i in pbar: + if i >= 8: + break + _, err = capsys.readouterr() + assert '9it' in err + + with tqdm(acount(), desc="async_counter") as pbar: + async for i in pbar: + if i >= 8: + break + _, err = capsys.readouterr() + assert '9it' in err + + +@mark.asyncio +async def test_range(): + """Test asyncio range""" + with closing(StringIO()) as our_file: + async for _ in tqdm(range(9), desc="range", file=our_file): + pass + assert '9/9' in our_file.getvalue() + our_file.seek(0) + our_file.truncate() + + async for _ in trange(9, desc="trange", file=our_file): + pass + assert '9/9' in our_file.getvalue() + + +@mark.asyncio +async def test_nested(): + """Test asyncio nested""" + with closing(StringIO()) as our_file: + async for _ in tqdm(trange(9, desc="inner", file=our_file), + desc="outer", file=our_file): + pass + assert 'inner: 100%' in our_file.getvalue() + assert 'outer: 100%' in our_file.getvalue() + + +@mark.asyncio +async def test_coroutines(): + """Test asyncio coroutine.send""" + with closing(StringIO()) as our_file: + with tqdm(count(), file=our_file) as pbar: + async for i in pbar: + if i == 9: + pbar.send(-10) + elif i < 0: + assert i == -9 + break + assert '10it' in our_file.getvalue() + + +@mark.slow +@mark.asyncio +@mark.parametrize("tol", [0.2 if platform.startswith("darwin") else 0.1]) +async def test_as_completed(capsys, tol): + """Test asyncio as_completed""" + for retry in range(3): + t = time() + skew = time() - t + for i in as_completed([asyncio.sleep(0.01 * i) for i in range(30, 0, -1)]): + await i + t = time() - t - 2 * skew + try: + assert 0.3 * (1 - tol) < t < 0.3 * (1 + tol), t + _, err = capsys.readouterr() + assert '30/30' in err + except AssertionError: + if retry == 2: + raise + + +async def double(i): + return i * 2 + + +@mark.asyncio +async def test_gather(capsys): + """Test asyncio gather""" + res = await gather(*map(double, range(30))) + _, err = capsys.readouterr() + assert '30/30' in err + assert res == list(range(0, 30 * 2, 2)) diff --git a/tests/tests_contrib.py b/tests/tests_contrib.py index 69a1cada9..65c8cd558 100644 --- a/tests/tests_contrib.py +++ b/tests/tests_contrib.py @@ -1,8 +1,6 @@ """ Tests for `tqdm.contrib`. """ -import sys - import pytest from tqdm import tqdm @@ -47,12 +45,9 @@ def test_zip(tqdm_kwargs): 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, **tqdm_kwargs) == zip(a, b) - else: - gen = tzip(a, b, file=our_file, **tqdm_kwargs) - assert gen != list(zip(a, b)) - assert list(gen) == list(zip(a, b)) + gen = tzip(a, b, file=our_file, **tqdm_kwargs) + assert gen != list(zip(a, b)) + assert list(gen) == list(zip(a, b)) @pytest.mark.parametrize("tqdm_kwargs", [{}, {"tqdm_class": tqdm}]) @@ -61,11 +56,6 @@ def test_map(tqdm_kwargs): 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, **tqdm_kwargs) == map( - incr, a - ) - else: - gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs) - assert gen != b - assert list(gen) == b + gen = tmap(lambda x: x + 1, a, file=our_file, **tqdm_kwargs) + assert gen != b + assert list(gen) == b diff --git a/tests/tests_main.py b/tests/tests_main.py index 0523cc795..039ce3380 100644 --- a/tests/tests_main.py +++ b/tests/tests_main.py @@ -8,17 +8,17 @@ from tqdm.cli import TqdmKeyError, TqdmTypeError, main from tqdm.utils import IS_WIN -from .tests_tqdm import BytesIO, _range, closing, mark, raises +from .tests_tqdm import BytesIO, closing, mark, raises def restore_sys(func): - """Decorates `func(capsysbin)` to save & restore `sys.(stdin|argv)`.""" + """Decorates `func(capsysbinary)` to save & restore `sys.(stdin|argv)`.""" @wraps(func) - def inner(capsysbin): - """function requiring capsysbin which may alter `sys.(stdin|argv)`""" + def inner(capsysbinary): + """function requiring capsysbinary which may alter `sys.(stdin|argv)`""" _SYS = sys.stdin, sys.argv try: - res = func(capsysbin) + res = func(capsysbinary) finally: sys.stdin, sys.argv = _SYS return res @@ -58,7 +58,7 @@ def test_main_import(): N = 123 _SYS = sys.stdin, sys.argv # test direct import - sys.stdin = [str(i).encode() for i in _range(N)] + sys.stdin = [str(i).encode() for i in range(N)] sys.argv = ['', '--desc', 'Test CLI import', '--ascii', 'True', '--unit_scale', 'True'] try: @@ -68,19 +68,19 @@ def test_main_import(): @restore_sys -def test_main_bytes(capsysbin): +def test_main_bytes(capsysbinary): """Test CLI --bytes""" N = 123 # test --delim - IN_DATA = '\0'.join(map(str, _range(N))).encode() + IN_DATA = '\0'.join(map(str, range(N))).encode() with closing(BytesIO()) as sys.stdin: sys.stdin.write(IN_DATA) # sys.stdin.write(b'\xff') # TODO sys.stdin.seek(0) main(sys.stderr, ['--desc', 'Test CLI delim', '--ascii', 'True', '--delim', r'\0', '--buf_size', '64']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert out == IN_DATA assert str(N) + "it" in err.decode("U8") @@ -90,27 +90,26 @@ def test_main_bytes(capsysbin): sys.stdin.write(IN_DATA) sys.stdin.seek(0) main(sys.stderr, ['--ascii', '--bytes=True', '--unit_scale', 'False']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert out == IN_DATA assert str(len(IN_DATA)) + "B" in err.decode("U8") -@mark.skipif(sys.version_info[0] == 2, reason="no caplog on py2") -def test_main_log(capsysbin, caplog): +def test_main_log(capsysbinary, caplog): """Test CLI --log""" _SYS = sys.stdin, sys.argv N = 123 - sys.stdin = [(str(i) + '\n').encode() for i in _range(N)] + sys.stdin = [(str(i) + '\n').encode() for i in range(N)] IN_DATA = b''.join(sys.stdin) try: with caplog.at_level(logging.INFO): main(sys.stderr, ['--log', 'INFO']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA and b"123/123" in err assert not caplog.record_tuples with caplog.at_level(logging.DEBUG): main(sys.stderr, ['--log', 'DEBUG']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA and b"123/123" in err assert caplog.record_tuples finally: @@ -118,39 +117,39 @@ def test_main_log(capsysbin, caplog): @restore_sys -def test_main(capsysbin): +def test_main(capsysbinary): """Test misc CLI options""" N = 123 - sys.stdin = [(str(i) + '\n').encode() for i in _range(N)] + sys.stdin = [(str(i) + '\n').encode() for i in range(N)] IN_DATA = b''.join(sys.stdin) # test --tee main(sys.stderr, ['--mininterval', '0', '--miniters', '1']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA and b"123/123" in err assert N <= len(err.split(b"\r")) < N + 5 len_err = len(err) main(sys.stderr, ['--tee', '--mininterval', '0', '--miniters', '1']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA and b"123/123" in err # spaces to clear intermediate lines could increase length assert len_err + len(norm(out)) <= len(err) # test --null main(sys.stderr, ['--null']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert not out and b"123/123" in err # test integer --update main(sys.stderr, ['--update']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum formula" # test integer --update_to main(sys.stderr, ['--update-to']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA assert (str(N - 1) + "it").encode() in err assert (str(N) + "it").encode() not in err @@ -161,23 +160,23 @@ def test_main(capsysbin): # test integer --update --delim sys.stdin.seek(0) main(sys.stderr, ['--update', '--delim', 'D']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert out == IN_DATA.replace(b'\n', b'D') assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum" # test integer --update_to --delim sys.stdin.seek(0) main(sys.stderr, ['--update-to', '--delim', 'D']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert out == IN_DATA.replace(b'\n', b'D') assert (str(N - 1) + "it").encode() in err assert (str(N) + "it").encode() not in err # test float --update_to - sys.stdin = [(str(i / 2.0) + '\n').encode() for i in _range(N)] + sys.stdin = [(str(i / 2.0) + '\n').encode() for i in range(N)] IN_DATA = b''.join(sys.stdin) main(sys.stderr, ['--update-to']) - out, err = capsysbin.readouterr() + out, err = capsysbinary.readouterr() assert norm(out) == IN_DATA assert (str((N - 1) / 2.0) + "it").encode() in err assert (str(N / 2.0) + "it").encode() not in err @@ -213,30 +212,30 @@ def test_comppath(tmp_path): @restore_sys -def test_exceptions(capsysbin): +def test_exceptions(capsysbinary): """Test CLI Exceptions""" N = 123 - sys.stdin = [str(i) + '\n' for i in _range(N)] + sys.stdin = [str(i) + '\n' for i in range(N)] IN_DATA = ''.join(sys.stdin).encode() with raises(TqdmKeyError, match="bad_arg_u_ment"): main(sys.stderr, argv=['-ascii', '-unit_scale', '--bad_arg_u_ment', 'foo']) - out, _ = capsysbin.readouterr() + out, _ = capsysbinary.readouterr() assert norm(out) == IN_DATA with raises(TqdmTypeError, match="invalid_bool_value"): main(sys.stderr, argv=['-ascii', '-unit_scale', 'invalid_bool_value']) - out, _ = capsysbin.readouterr() + out, _ = capsysbinary.readouterr() assert norm(out) == IN_DATA with raises(TqdmTypeError, match="invalid_int_value"): main(sys.stderr, argv=['-ascii', '--total', 'invalid_int_value']) - out, _ = capsysbin.readouterr() + out, _ = capsysbinary.readouterr() assert norm(out) == IN_DATA with raises(TqdmKeyError, match="Can only have one of --"): main(sys.stderr, argv=['--update', '--update_to']) - out, _ = capsysbin.readouterr() + out, _ = capsysbinary.readouterr() assert norm(out) == IN_DATA # test SystemExits diff --git a/tests/tests_perf.py b/tests/tests_perf.py index 552a1694b..92bed3755 100644 --- a/tests/tests_perf.py +++ b/tests/tests_perf.py @@ -14,7 +14,7 @@ from tqdm import tqdm, trange -from .tests_tqdm import _range, importorskip, mark, patch_lock, skip +from .tests_tqdm import importorskip, mark, patch_lock, skip pytestmark = mark.slow @@ -173,7 +173,7 @@ def test_iter_basic_overhead(): a = 0 with relative_timer() as time_bench: - for i in _range(total): + for i in range(total): a += i sys.stdout.write(str(a)) @@ -188,13 +188,13 @@ def test_manual_basic_overhead(): with tqdm(total=total * 10, leave=True) as t: a = 0 with relative_timer() as time_tqdm: - for i in _range(total): + for i in range(total): a += i t.update(10) a = 0 with relative_timer() as time_bench: - for i in _range(total): + for i in range(total): a += i sys.stdout.write(str(a)) @@ -249,7 +249,7 @@ def test_iter_overhead_hard(): a = 0 with relative_timer() as time_bench: - for i in _range(total): + for i in range(total): a += i sys.stdout.write(("%i" % a) * 40) @@ -265,13 +265,13 @@ def test_manual_overhead_hard(): mininterval=0, maxinterval=0) as t: a = 0 with relative_timer() as time_tqdm: - for i in _range(total): + for i in range(total): a += i t.update(10) a = 0 with relative_timer() as time_bench: - for i in _range(total): + for i in range(total): a += i sys.stdout.write(("%i" % a) * 40) @@ -292,7 +292,7 @@ def test_iter_overhead_simplebar_hard(): assert a == (total ** 2 - total) / 2.0 a = 0 - s = simple_progress(_range(total), leave=True, + s = simple_progress(range(total), leave=True, miniters=1, mininterval=0) with relative_timer() as time_bench: for i in s: @@ -310,7 +310,7 @@ def test_manual_overhead_simplebar_hard(): mininterval=0, maxinterval=0) as t: a = 0 with relative_timer() as time_tqdm: - for i in _range(total): + for i in range(total): a += i t.update(10) @@ -318,7 +318,7 @@ def test_manual_overhead_simplebar_hard(): miniters=1, mininterval=0) a = 0 with relative_timer() as time_bench: - for i in _range(total): + for i in range(total): a += i simplebar_update(10) diff --git a/tests/tests_rich.py b/tests/tests_rich.py index c75e246d9..2fff78cc4 100644 --- a/tests/tests_rich.py +++ b/tests/tests_rich.py @@ -1,10 +1,7 @@ """Test `tqdm.rich`.""" -import sys +from .tests_tqdm import importorskip -from .tests_tqdm import importorskip, mark - -@mark.skipif(sys.version_info[:3] < (3, 6, 1), reason="`rich` needs py>=3.6.1") def test_rich_import(): """Test `tqdm.rich` import""" importorskip('tqdm.rich') diff --git a/tests/tests_synchronisation.py b/tests/tests_synchronisation.py index 7ee55fb1d..5b0ad1df4 100644 --- a/tests/tests_synchronisation.py +++ b/tests/tests_synchronisation.py @@ -1,13 +1,11 @@ from __future__ import division -import sys from functools import wraps from threading import Event from time import sleep, time from tqdm import TMonitor, tqdm, trange -from .tests_perf import retry_on_except from .tests_tqdm import StringIO, closing, importorskip, patch_lock, skip @@ -37,18 +35,13 @@ def fake_sleep(cls, dur): sleep(0.000001) # sleep to allow interrupt (instead of pass) -def FakeEvent(): +class FakeEvent(Event): """patched `threading.Event` where `wait()` uses `Time.fake_sleep()`""" - event = Event() # not a class in py2 so can't inherit - - def wait(timeout=None): + def wait(self, timeout=None): """uses Time.fake_sleep""" if timeout is not None: Time.fake_sleep(timeout) - return event.is_set() - - event.wait = wait - return event + return self.is_set() def patch_sleep(func): @@ -206,19 +199,11 @@ def test_imap(): 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, check_cpu_time=False) @patch_lock(thread=True) def test_threadpool(): """Test concurrent.futures.ThreadPoolExecutor""" ThreadPoolExecutor = importorskip('concurrent.futures').ThreadPoolExecutor with ThreadPoolExecutor(8) as pool: - try: - res = list(tqdm(pool.map(incr_bar, range(100)), disable=True)) - except AttributeError: - if sys.version_info < (3,): - skip("not supported on py2") - else: - raise + res = list(tqdm(pool.map(incr_bar, range(100)), disable=True)) assert sum(res) == sum(range(1, 101)) diff --git a/tests/tests_tqdm.py b/tests/tests_tqdm.py index bba457aa2..513be5010 100644 --- a/tests/tests_tqdm.py +++ b/tests/tests_tqdm.py @@ -37,16 +37,6 @@ def closing(arg): else: from contextlib import closing -try: - _range = xrange -except NameError: - _range = range - -try: - _unicode = unicode -except NameError: - _unicode = str - nt_and_no_colorama = False if os.name == 'nt': try: @@ -271,11 +261,10 @@ def test_format_meter(): 20, 100, 12, ncols=14, rate=8.1, bar_format=r'{l_bar}{bar}|{n_fmt}/{total_fmt}') == " 20%|" + unich(0x258d) + " |20/100" # Check wide characters - if sys.version_info >= (3,): - assert format_meter(0, 1000, 13, ncols=68, prefix='fullwidth: ') == ( - "fullwidth: 0%| | 0/1000 [00:13>> for i in trange(10): ... ... """ -import sys import warnings from .std import TqdmExperimentalWarning @@ -20,25 +19,22 @@ with warnings.catch_warnings(): warnings.simplefilter("ignore", category=TqdmExperimentalWarning) from .autonotebook import tqdm as notebook_tqdm - from .autonotebook import trange as notebook_trange - -if sys.version_info[:2] < (3, 6): - tqdm = notebook_tqdm - trange = notebook_trange -else: # Python3.6+ - from .asyncio import tqdm as asyncio_tqdm - from .std import tqdm as std_tqdm - - if notebook_tqdm != std_tqdm: - class tqdm(notebook_tqdm, asyncio_tqdm): # pylint: disable=inconsistent-mro - pass - else: - tqdm = asyncio_tqdm - - def trange(*args, **kwargs): - """ - A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`. - """ - return tqdm(range(*args), **kwargs) + +from .asyncio import tqdm as asyncio_tqdm +from .std import tqdm as std_tqdm + +if notebook_tqdm != std_tqdm: + class tqdm(notebook_tqdm, asyncio_tqdm): # pylint: disable=inconsistent-mro + pass +else: + tqdm = asyncio_tqdm + + +def trange(*args, **kwargs): + """ + A shortcut for `tqdm.auto.tqdm(range(*args), **kwargs)`. + """ + return tqdm(range(*args), **kwargs) + __all__ = ["tqdm", "trange"] diff --git a/tqdm/cli.py b/tqdm/cli.py index 3ed25fbb4..dd0ea3590 100644 --- a/tqdm/cli.py +++ b/tqdm/cli.py @@ -245,12 +245,9 @@ def write(_): stdout = getattr(stdout, 'buffer', stdout) stdin = getattr(sys.stdin, 'buffer', sys.stdin) if manpath or comppath: + from importlib import resources from os import path from shutil import copyfile - try: # py<3.7 - import importlib_resources as resources - except ImportError: - from importlib import resources def cp(name, dst): """copy resource `name` to `dst`""" diff --git a/tqdm/contrib/__init__.py b/tqdm/contrib/__init__.py index 0b5217707..7338c960a 100644 --- a/tqdm/contrib/__init__.py +++ b/tqdm/contrib/__init__.py @@ -3,11 +3,10 @@ Subpackages contain potentially unstable extensions. """ -import sys -from functools import wraps +from warnings import warn from ..auto import tqdm as tqdm_auto -from ..std import tqdm +from ..std import TqdmDeprecationWarning, tqdm from ..utils import ObjectWrapper __author__ = {"github.com/": ["casperdcl"]} @@ -42,12 +41,9 @@ def __del__(self): def builtin_iterable(func): - """Wraps `func()` output in a `list()` in py2""" - if sys.version_info[:1] < (3,): - @wraps(func) - def inner(*args, **kwargs): - return list(func(*args, **kwargs)) - return inner + """Returns `func`""" + warn("This function has no effect, and will be removed in tqdm==5.0.0", + TqdmDeprecationWarning, stacklevel=2) return func @@ -70,7 +66,6 @@ def tenumerate(iterable, start=0, total=None, tqdm_class=tqdm_auto, **tqdm_kwarg return enumerate(tqdm_class(iterable, total=total, **tqdm_kwargs), start) -@builtin_iterable def tzip(iter1, *iter2plus, **tqdm_kwargs): """ Equivalent of builtin `zip`. @@ -85,7 +80,6 @@ def tzip(iter1, *iter2plus, **tqdm_kwargs): yield i -@builtin_iterable def tmap(function, *sequences, **tqdm_kwargs): """ Equivalent of builtin `map`. diff --git a/tqdm/contrib/concurrent.py b/tqdm/contrib/concurrent.py index ccb5e1252..ded24aca8 100644 --- a/tqdm/contrib/concurrent.py +++ b/tqdm/contrib/concurrent.py @@ -25,7 +25,6 @@ def length_hint(it, default=0): except ImportError: def cpu_count(): return 4 -import sys __author__ = {"github.com/": ["casperdcl"]} __all__ = ['thread_map', 'process_map'] @@ -64,16 +63,10 @@ def _executor_map(PoolExecutor, fn, *iterables, **tqdm_kwargs): chunksize = kwargs.pop("chunksize", 1) lock_name = kwargs.pop("lock_name", "") with ensure_lock(tqdm_class, lock_name=lock_name) as lk: - pool_kwargs = {'max_workers': max_workers} - sys_version = sys.version_info[:2] - if sys_version >= (3, 7): - # share lock in case workers are already using `tqdm` - pool_kwargs.update(initializer=tqdm_class.set_lock, initargs=(lk,)) - map_args = {} - if not (3, 0) < sys_version < (3, 5): - map_args.update(chunksize=chunksize) - with PoolExecutor(**pool_kwargs) as ex: - return list(tqdm_class(ex.map(fn, *iterables, **map_args), **kwargs)) + # share lock in case workers are already using `tqdm` + with PoolExecutor(max_workers=max_workers, initializer=tqdm_class.set_lock, + initargs=(lk,)) as ex: + return list(tqdm_class(ex.map(fn, *iterables, chunksize=chunksize), **kwargs)) def thread_map(fn, *iterables, **tqdm_kwargs): diff --git a/tqdm/contrib/discord.py b/tqdm/contrib/discord.py index 0edd35cca..fe14078fd 100644 --- a/tqdm/contrib/discord.py +++ b/tqdm/contrib/discord.py @@ -19,7 +19,6 @@ raise ImportError("Please `pip install disco-py`") from ..auto import tqdm as tqdm_auto -from ..utils import _range from .utils_worker import MonoWorker __author__ = {"github.com/": ["casperdcl"]} @@ -113,11 +112,8 @@ def clear(self, *args, **kwargs): def tdrange(*args, **kwargs): - """ - A shortcut for `tqdm.contrib.discord.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_discord(_range(*args), **kwargs) + """Shortcut for `tqdm.contrib.discord.tqdm(range(*args), **kwargs)`.""" + return tqdm_discord(range(*args), **kwargs) # Aliases diff --git a/tqdm/contrib/slack.py b/tqdm/contrib/slack.py index b478d9236..78b2c5269 100644 --- a/tqdm/contrib/slack.py +++ b/tqdm/contrib/slack.py @@ -19,7 +19,6 @@ raise ImportError("Please `pip install slack-sdk`") from ..auto import tqdm as tqdm_auto -from ..utils import _range from .utils_worker import MonoWorker __author__ = {"github.com/": ["0x2b3bfa0", "casperdcl"]} @@ -114,11 +113,8 @@ def clear(self, *args, **kwargs): def tsrange(*args, **kwargs): - """ - A shortcut for `tqdm.contrib.slack.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_slack(_range(*args), **kwargs) + """Shortcut for `tqdm.contrib.slack.tqdm(range(*args), **kwargs)`.""" + return tqdm_slack(range(*args), **kwargs) # Aliases diff --git a/tqdm/contrib/telegram.py b/tqdm/contrib/telegram.py index 99cbe8c88..6eb598e21 100644 --- a/tqdm/contrib/telegram.py +++ b/tqdm/contrib/telegram.py @@ -17,7 +17,6 @@ from ..auto import tqdm as tqdm_auto from ..std import TqdmWarning -from ..utils import _range from .utils_worker import MonoWorker __author__ = {"github.com/": ["casperdcl"]} @@ -147,11 +146,8 @@ def close(self): def ttgrange(*args, **kwargs): - """ - A shortcut for `tqdm.contrib.telegram.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_telegram(_range(*args), **kwargs) + """Shortcut for `tqdm.contrib.telegram.tqdm(range(*args), **kwargs)`.""" + return tqdm_telegram(range(*args), **kwargs) # Aliases diff --git a/tqdm/gui.py b/tqdm/gui.py index 4612701d2..500142637 100644 --- a/tqdm/gui.py +++ b/tqdm/gui.py @@ -16,8 +16,8 @@ # to inherit from the tqdm class from .std import TqdmExperimentalWarning from .std import tqdm as std_tqdm + # import compatibility functions and utilities -from .utils import _range __author__ = {"github.com/": ["casperdcl", "lrq3000"]} __all__ = ['tqdm_gui', 'tgrange', 'tqdm', 'trange'] @@ -179,11 +179,8 @@ def display(self, *_, **__): def tgrange(*args, **kwargs): - """ - A shortcut for `tqdm.gui.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_gui(_range(*args), **kwargs) + """Shortcut for `tqdm.gui.tqdm(range(*args), **kwargs)`.""" + return tqdm_gui(range(*args), **kwargs) # Aliases diff --git a/tqdm/notebook.py b/tqdm/notebook.py index ffd094783..05559ea72 100644 --- a/tqdm/notebook.py +++ b/tqdm/notebook.py @@ -18,7 +18,6 @@ # to inherit from the tqdm class from .std import tqdm as std_tqdm -from .utils import _range if True: # pragma: no cover # import IPython/Jupyter base widget and display utilities @@ -317,11 +316,8 @@ def reset(self, total=None): def tnrange(*args, **kwargs): - """ - A shortcut for `tqdm.notebook.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_notebook(_range(*args), **kwargs) + """Shortcut for `tqdm.notebook.tqdm(range(*args), **kwargs)`.""" + return tqdm_notebook(range(*args), **kwargs) # Aliases diff --git a/tqdm/rich.py b/tqdm/rich.py index 69893ffdd..b3426f21f 100644 --- a/tqdm/rich.py +++ b/tqdm/rich.py @@ -15,7 +15,6 @@ from .std import TqdmExperimentalWarning from .std import tqdm as std_tqdm -from .utils import _range __author__ = {"github.com/": ["casperdcl"]} __all__ = ['tqdm_rich', 'trrange', 'tqdm', 'trange'] @@ -144,11 +143,8 @@ def reset(self, total=None): def trrange(*args, **kwargs): - """ - A shortcut for `tqdm.rich.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_rich(_range(*args), **kwargs) + """Shortcut for `tqdm.rich.tqdm(range(*args), **kwargs)`.""" + return tqdm_rich(range(*args), **kwargs) # Aliases diff --git a/tqdm/std.py b/tqdm/std.py index 5f9dccafe..701151cb1 100644 --- a/tqdm/std.py +++ b/tqdm/std.py @@ -21,8 +21,7 @@ from ._monitor import TMonitor from .utils import ( CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper, - _basestring, _is_ascii, _range, _screen_shape_wrapper, _supports_unicode, _term_move_up, - _unich, _unicode, disp_len, disp_trim) + _is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim) __author__ = "https://github.com/tqdm/tqdm#contributions" __all__ = ['tqdm', 'trange', @@ -144,7 +143,7 @@ class Bar(object): + `b`: blank (`charset=" "` override) """ ASCII = " 123456789#" - UTF = u" " + u''.join(map(_unich, range(0x258F, 0x2587, -1))) + UTF = u" " + u''.join(map(chr, range(0x258F, 0x2587, -1))) BLANK = " " COLOUR_RESET = '\x1b[0m' COLOUR_RGB = '\x1b[38;2;%d;%d;%dm' @@ -340,7 +339,7 @@ def status_printer(file): getattr(sys.stdout, 'flush', lambda: None)() def fp_write(s): - fp.write(_unicode(s)) + fp.write(str(s)) fp_flush() last_len = [0] @@ -523,7 +522,7 @@ def format_meter(n, total, elapsed, ncols=None, prefix='', ascii=False, unit='it try: nobar = bar_format.format(bar=full_bar, **format_dict) except UnicodeEncodeError: - bar_format = _unicode(bar_format) + bar_format = str(bar_format) nobar = bar_format.format(bar=full_bar, **format_dict) if not full_bar.format_called: # no {bar}, we can just format and return @@ -535,7 +534,7 @@ def format_meter(n, total, elapsed, ncols=None, prefix='', ascii=False, unit='it charset=Bar.ASCII if ascii is True else ascii or Bar.UTF, colour=colour) if not _is_ascii(full_bar.charset) and _is_ascii(bar_format): - bar_format = _unicode(bar_format) + bar_format = str(bar_format) res = bar_format.format(bar=full_bar, **format_dict) return disp_trim(res, ncols) if ncols else res @@ -847,7 +846,7 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None, ascii=None, disable=False, unit='it', unit_scale=False, dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0, - position=None, postfix=None, unit_divisor=1000, write_bytes=None, + position=None, postfix=None, unit_divisor=1000, write_bytes=False, lock_args=None, nrows=None, colour=None, delay=0, gui=False, **kwargs): """ @@ -944,9 +943,7 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, unit_divisor : float, optional [default: 1000], ignored unless `unit_scale` is True. write_bytes : bool, optional - If (default: None) and `file` is unspecified, - bytes will be written in Python 2. If `True` will also write - bytes. In all other cases will default to unicode. + Whether to write bytes. If (default: False) will write unicode. lock_args : tuple, optional Passed to `refresh` for intermediate output (initialisation, iterating, and updating). @@ -967,9 +964,6 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, ------- out : decorated iterator. """ - if write_bytes is None: - write_bytes = file is None and sys.version_info < (3,) - if file is None: file = sys.stderr @@ -1051,7 +1045,7 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, if bar_format and ascii is not True and not _is_ascii(ascii): # Convert bar format into unicode since terminal uses unicode - bar_format = _unicode(bar_format) + bar_format = str(bar_format) if smoothing is None: smoothing = 0 @@ -1298,7 +1292,7 @@ def close(self): # annoyingly, _supports_unicode isn't good enough def fp_write(s): - self.fp.write(_unicode(s)) + self.fp.write(str(s)) try: fp_write('') @@ -1435,7 +1429,7 @@ def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): if isinstance(postfix[key], Number): postfix[key] = self.format_num(postfix[key]) # Else for any other type, try to get the string conversion - elif not isinstance(postfix[key], _basestring): + elif not isinstance(postfix[key], str): postfix[key] = str(postfix[key]) # Else if it's a string, don't need to preprocess anything # Stitch together to get the final postfix @@ -1454,7 +1448,7 @@ def set_postfix_str(self, s='', refresh=True): def moveto(self, n): # TODO: private method - self.fp.write(_unicode('\n' * n + _term_move_up() * -n)) + self.fp.write('\n' * n + _term_move_up() * -n) getattr(self.fp, 'flush', lambda: None)() @property @@ -1534,8 +1528,5 @@ def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): def trange(*args, **kwargs): - """ - A shortcut for tqdm(xrange(*args), **kwargs). - On Python3+ range is used instead of xrange. - """ - return tqdm(_range(*args), **kwargs) + """Shortcut for tqdm(range(*args), **kwargs).""" + return tqdm(range(*args), **kwargs) diff --git a/tqdm/tk.py b/tqdm/tk.py index 92adb51db..1fc68d3f2 100644 --- a/tqdm/tk.py +++ b/tqdm/tk.py @@ -21,7 +21,6 @@ from .std import TqdmExperimentalWarning, TqdmWarning from .std import tqdm as std_tqdm -from .utils import _range __author__ = {"github.com/": ["richardsheridan", "casperdcl"]} __all__ = ['tqdm_tk', 'ttkrange', 'tqdm', 'trange'] @@ -195,11 +194,8 @@ def _tk_dispatching_helper(): def ttkrange(*args, **kwargs): - """ - A shortcut for `tqdm.tk.tqdm(xrange(*args), **kwargs)`. - On Python3+, `range` is used instead of `xrange`. - """ - return tqdm_tk(_range(*args), **kwargs) + """Shortcut for `tqdm.tk.tqdm(range(*args), **kwargs)`.""" + return tqdm_tk(range(*args), **kwargs) # Aliases diff --git a/tqdm/utils.py b/tqdm/utils.py index 0632b8dd0..ea3634253 100644 --- a/tqdm/utils.py +++ b/tqdm/utils.py @@ -8,26 +8,7 @@ from warnings import warn from weakref import proxy -# py2/3 compat -try: - _range = xrange -except NameError: - _range = range - -try: - _unich = unichr -except NameError: - _unich = chr - -try: - _unicode = unicode -except NameError: - _unicode = str - -try: - _basestring = basestring -except NameError: - _basestring = str +_range, _unich, _unicode, _basestring = range, chr, str, str CUR_OS = sys.platform IS_WIN = any(CUR_OS.startswith(i) for i in ['win32', 'cygwin']) @@ -327,7 +308,7 @@ def _term_move_up(): # pragma: no cover _text_width = len else: def _text_width(s): - return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in _unicode(s)) + return sum(2 if east_asian_width(ch) in 'FW' else 1 for ch in str(s)) def disp_len(data):