tqdm/tests/tests_main.py

245 lines
7.8 KiB
Python
Raw Normal View History

2020-10-24 22:43:59 +00:00
"""Test CLI usage."""
2021-01-04 01:09:46 +00:00
import logging
2021-02-17 16:03:15 +00:00
import subprocess # nosec
2021-01-09 17:00:18 +00:00
import sys
from functools import wraps
from os import linesep
2021-01-09 17:00:18 +00:00
from tqdm.cli import TqdmKeyError, TqdmTypeError, main
2019-11-10 15:03:30 +00:00
from tqdm.utils import IS_WIN
2021-01-09 17:00:18 +00:00
2023-03-03 15:43:42 +00:00
from .tests_tqdm import BytesIO, closing, mark, raises
2016-04-03 21:03:10 +00:00
2021-01-04 01:58:06 +00:00
def restore_sys(func):
2023-03-03 15:43:42 +00:00
"""Decorates `func(capsysbinary)` to save & restore `sys.(stdin|argv)`."""
2021-01-04 01:58:06 +00:00
@wraps(func)
2023-03-03 15:43:42 +00:00
def inner(capsysbinary):
"""function requiring capsysbinary which may alter `sys.(stdin|argv)`"""
2021-01-04 01:58:06 +00:00
_SYS = sys.stdin, sys.argv
try:
2023-03-03 15:43:42 +00:00
res = func(capsysbinary)
2021-01-04 01:58:06 +00:00
finally:
sys.stdin, sys.argv = _SYS
2021-01-04 02:35:03 +00:00
return res
2021-01-04 01:58:06 +00:00
return inner
2021-01-04 01:09:46 +00:00
def norm(bytestr):
"""Normalise line endings."""
return bytestr if linesep == "\n" else bytestr.replace(linesep.encode(), b"\n")
2019-01-24 20:43:36 +00:00
2021-01-04 03:00:27 +00:00
@mark.slow
2020-10-24 18:36:45 +00:00
def test_pipes():
"""Test command line pipes"""
2021-02-17 16:03:15 +00:00
ls_out = subprocess.check_output(['ls']) # nosec
ls = subprocess.Popen(['ls'], stdout=subprocess.PIPE) # nosec
2021-02-22 22:25:17 +00:00
res = subprocess.Popen( # nosec
2021-01-03 22:33:43 +00:00
[sys.executable, '-c', 'from tqdm.cli import main; main()'],
2021-02-22 22:25:17 +00:00
stdin=ls.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
2021-01-04 01:09:46 +00:00
out, err = res.communicate()
2021-01-03 22:33:43 +00:00
assert ls.poll() == 0
2020-10-24 18:36:45 +00:00
# actual test:
2021-01-04 01:09:46 +00:00
assert norm(ls_out) == norm(out)
2021-01-03 22:33:43 +00:00
assert b"it/s" in err
2022-02-18 00:25:04 +00:00
assert b"Error" not in err
2021-01-03 22:33:43 +00:00
2020-10-24 18:36:45 +00:00
2021-01-03 22:33:43 +00:00
if sys.version_info[:2] >= (3, 8):
test_pipes = mark.filterwarnings("ignore:unclosed file:ResourceWarning")(
test_pipes)
2020-10-24 18:36:45 +00:00
2021-01-04 01:09:46 +00:00
def test_main_import():
"""Test main CLI import"""
2020-10-24 18:36:45 +00:00
N = 123
2021-01-04 01:58:06 +00:00
_SYS = sys.stdin, sys.argv
2020-10-24 18:36:45 +00:00
# test direct import
2023-03-03 15:43:42 +00:00
sys.stdin = [str(i).encode() for i in range(N)]
2020-10-24 18:36:45 +00:00
sys.argv = ['', '--desc', 'Test CLI import',
'--ascii', 'True', '--unit_scale', 'True']
2021-01-04 01:58:06 +00:00
try:
2021-02-22 22:42:24 +00:00
import tqdm.__main__ # NOQA, pylint: disable=unused-variable
2021-01-04 01:58:06 +00:00
finally:
sys.stdin, sys.argv = _SYS
2021-01-04 01:09:46 +00:00
2021-01-04 01:58:06 +00:00
@restore_sys
2023-03-03 15:43:42 +00:00
def test_main_bytes(capsysbinary):
2021-01-04 01:09:46 +00:00
"""Test CLI --bytes"""
N = 123
2020-10-24 18:36:45 +00:00
# test --delim
2023-03-03 15:43:42 +00:00
IN_DATA = '\0'.join(map(str, range(N))).encode()
2020-10-24 22:26:18 +00:00
with closing(BytesIO()) as sys.stdin:
2020-10-24 18:36:45 +00:00
sys.stdin.write(IN_DATA)
# sys.stdin.write(b'\xff') # TODO
sys.stdin.seek(0)
2021-01-04 01:09:46 +00:00
main(sys.stderr, ['--desc', 'Test CLI delim', '--ascii', 'True',
'--delim', r'\0', '--buf_size', '64'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert out == IN_DATA
assert str(N) + "it" in err.decode("U8")
2020-10-24 18:36:45 +00:00
# test --bytes
2020-10-24 22:26:18 +00:00
IN_DATA = IN_DATA.replace(b'\0', b'\n')
with closing(BytesIO()) as sys.stdin:
2020-10-24 18:36:45 +00:00
sys.stdin.write(IN_DATA)
sys.stdin.seek(0)
2021-01-04 01:09:46 +00:00
main(sys.stderr, ['--ascii', '--bytes=True', '--unit_scale', 'False'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert out == IN_DATA
assert str(len(IN_DATA)) + "B" in err.decode("U8")
2020-10-24 18:36:45 +00:00
2023-03-03 15:43:42 +00:00
def test_main_log(capsysbinary, caplog):
2021-01-04 01:58:06 +00:00
"""Test CLI --log"""
_SYS = sys.stdin, sys.argv
N = 123
2023-03-03 15:43:42 +00:00
sys.stdin = [(str(i) + '\n').encode() for i in range(N)]
2021-01-04 01:58:06 +00:00
IN_DATA = b''.join(sys.stdin)
try:
with caplog.at_level(logging.INFO):
main(sys.stderr, ['--log', 'INFO'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:58:06 +00:00
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'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:58:06 +00:00
assert norm(out) == IN_DATA and b"123/123" in err
assert caplog.record_tuples
finally:
sys.stdin, sys.argv = _SYS
@restore_sys
2023-03-03 15:43:42 +00:00
def test_main(capsysbinary):
2021-01-04 01:09:46 +00:00
"""Test misc CLI options"""
N = 123
2023-03-03 15:43:42 +00:00
sys.stdin = [(str(i) + '\n').encode() for i in range(N)]
2021-01-04 01:09:46 +00:00
IN_DATA = b''.join(sys.stdin)
2020-10-24 18:36:45 +00:00
2021-01-04 01:09:46 +00:00
# test --tee
main(sys.stderr, ['--mininterval', '0', '--miniters', '1'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
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'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
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'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert not out and b"123/123" in err
2020-10-24 18:36:45 +00:00
2021-01-04 01:09:46 +00:00
# test integer --update
main(sys.stderr, ['--update'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum formula"
2020-10-24 18:36:45 +00:00
# test integer --update_to
2021-01-04 01:09:46 +00:00
main(sys.stderr, ['--update-to'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
assert (str(N - 1) + "it").encode() in err
assert (str(N) + "it").encode() not in err
2020-10-24 18:36:45 +00:00
2020-10-24 22:26:18 +00:00
with closing(BytesIO()) as sys.stdin:
sys.stdin.write(IN_DATA.replace(b'\n', b'D'))
2020-10-24 18:36:45 +00:00
2021-01-04 01:09:46 +00:00
# test integer --update --delim
2020-10-24 18:36:45 +00:00
sys.stdin.seek(0)
2021-01-04 01:09:46 +00:00
main(sys.stderr, ['--update', '--delim', 'D'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert out == IN_DATA.replace(b'\n', b'D')
assert (str(N // 2 * N) + "it").encode() in err, "expected arithmetic sum"
2020-10-24 18:36:45 +00:00
2021-01-04 01:09:46 +00:00
# test integer --update_to --delim
2020-10-24 18:36:45 +00:00
sys.stdin.seek(0)
2021-01-04 01:09:46 +00:00
main(sys.stderr, ['--update-to', '--delim', 'D'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
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
2023-03-03 15:43:42 +00:00
sys.stdin = [(str(i / 2.0) + '\n').encode() for i in range(N)]
2021-01-04 01:09:46 +00:00
IN_DATA = b''.join(sys.stdin)
main(sys.stderr, ['--update-to'])
2023-03-03 15:43:42 +00:00
out, err = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
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
2020-10-24 18:36:45 +00:00
2021-01-04 03:00:27 +00:00
@mark.slow
2021-01-04 01:09:46 +00:00
@mark.skipif(IS_WIN, reason="no manpages on windows")
def test_manpath(tmp_path):
2020-10-24 18:36:45 +00:00
"""Test CLI --manpath"""
2021-01-04 01:09:46 +00:00
man = tmp_path / "tqdm.1"
assert not man.exists()
with raises(SystemExit):
main(argv=['--manpath', str(tmp_path)])
assert man.is_file()
2021-01-04 03:00:27 +00:00
@mark.slow
2021-01-04 01:09:46 +00:00
@mark.skipif(IS_WIN, reason="no completion on windows")
def test_comppath(tmp_path):
2020-10-24 18:36:45 +00:00
"""Test CLI --comppath"""
2021-01-04 01:09:46 +00:00
man = tmp_path / "tqdm_completion.sh"
assert not man.exists()
with raises(SystemExit):
main(argv=['--comppath', str(tmp_path)])
assert man.is_file()
2020-10-24 18:36:45 +00:00
# check most important options appear
2021-01-04 01:09:46 +00:00
script = man.read_text()
opts = {'--help', '--desc', '--total', '--leave', '--ncols', '--ascii',
'--dynamic_ncols', '--position', '--bytes', '--nrows', '--delim',
'--manpath', '--comppath'}
2020-10-24 18:36:45 +00:00
assert all(args in script for args in opts)
2021-01-04 01:58:06 +00:00
@restore_sys
2023-03-03 15:43:42 +00:00
def test_exceptions(capsysbinary):
2020-10-24 18:36:45 +00:00
"""Test CLI Exceptions"""
2021-01-04 01:09:46 +00:00
N = 123
2023-03-03 15:43:42 +00:00
sys.stdin = [str(i) + '\n' for i in range(N)]
2021-01-04 01:09:46 +00:00
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'])
2023-03-03 15:43:42 +00:00
out, _ = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
with raises(TqdmTypeError, match="invalid_bool_value"):
main(sys.stderr, argv=['-ascii', '-unit_scale', 'invalid_bool_value'])
2023-03-03 15:43:42 +00:00
out, _ = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
with raises(TqdmTypeError, match="invalid_int_value"):
main(sys.stderr, argv=['-ascii', '--total', 'invalid_int_value'])
2023-03-03 15:43:42 +00:00
out, _ = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
with raises(TqdmKeyError, match="Can only have one of --"):
main(sys.stderr, argv=['--update', '--update_to'])
2023-03-03 15:43:42 +00:00
out, _ = capsysbinary.readouterr()
2021-01-04 01:09:46 +00:00
assert norm(out) == IN_DATA
2020-10-19 12:14:53 +00:00
2020-10-24 18:36:45 +00:00
# test SystemExits
for i in ('-h', '--help', '-v', '--version'):
2021-01-04 01:09:46 +00:00
with raises(SystemExit):
main(argv=[i])