From d632b1a8fb20c3e0a94e9fa852a9aeed3592b7d4 Mon Sep 17 00:00:00 2001 From: Casper da Costa-Luis Date: Fri, 22 Apr 2016 14:07:58 +0100 Subject: [PATCH] tests, tidy command line interface and remove docopt dependencies --- tox.ini | 2 -- tqdm/_main.py | 69 ++++++++++++++++++++++++---------------- tqdm/_tqdm.py | 6 ++-- tqdm/tests/tests_main.py | 16 +++++++--- 4 files changed, 56 insertions(+), 37 deletions(-) diff --git a/tox.ini b/tox.ini index 2db7b7fc3..97642fb43 100644 --- a/tox.ini +++ b/tox.ini @@ -13,7 +13,6 @@ deps = nose-timer coverage<4 coveralls - docopt commands = nosetests --with-coverage --with-timer --cover-package=tqdm --ignore-files="tests_perf\.py" -d -v tqdm/ coveralls @@ -38,6 +37,5 @@ commands = deps = nose nose-timer - docopt commands = nosetests --with-timer tqdm/tests/tests_perf.py -d -v diff --git a/tqdm/_main.py b/tqdm/_main.py index fff4d4911..3634c8ad9 100644 --- a/tqdm/_main.py +++ b/tqdm/_main.py @@ -1,3 +1,4 @@ +from __future__ import print_function from ._tqdm import tqdm from ._version import __version__ # NOQA import sys @@ -6,51 +7,63 @@ def cast(val, typ): - if val == 'None': - return None if typ == 'bool': - return str(val) == 'True' - # try: + return (str(val) == 'True') or not str(val) return eval(typ + '("' + str(val) + '")') - # except: - # # print val, typ - # if val == 'special': - # return 'whatever... just an example' - # else: - # return eval(typ + '()') -RE_OPTS = re.compile(r' {8}(\w+)\s{2,}:\s*(str|int|float|bool)', flags=re.M) -# RE_OPTS_SOME = re.compile(r' {8}(\w+) : (str|int|float)', flags=re.M) -# RE_OPTS_BOOL = re.compile(r' {8}(\w+) : bool', flags=re.M) +# Don't have to worry about Python 2.6 not supporting re flags +# since it does not support executing modules either. +# RE_OPTS = re.compile(r' {8}(\S+)\s{2,}:\s*(str|int|float|bool)', flags=re.M) +RE_OPTS = re.compile(r' {8}(\S+)\s{2,}:\s*([^\s,]+)', flags=re.M) +# TODO: add custom support for some of the following? +UNSUPPORTED_OPTS = ('iterable', 'gui', 'out', 'file') -def main(): - from docopt import docopt +def main(): d = tqdm.__init__.__doc__ + opt_types = dict(RE_OPTS.findall(d)) - # d = RE_OPTS_SOME.sub(r' --\1= ', d) - # d = RE_OPTS_BOOL.sub(r' --\1 ', d) - d = RE_OPTS.sub(r' --\1= : \2', d) - d = d[d.find(' --desc='):d.find('Returns\n')] - __doc__ = """ -Usage: - tqdm [--help | options] + + for o in UNSUPPORTED_OPTS: + opt_types.pop(o) + + # d = RE_OPTS.sub(r' --\1=<\1> : \2', d) + split = RE_OPTS.split(d) + opt_types_desc = zip(split[1::3], split[2::3], split[3::3]) + d = ''.join(' --{0}=<{0}> : {1}{2}'.format(*otd) + for otd in opt_types_desc if otd[0] not in UNSUPPORTED_OPTS) + + __doc__ = """Usage: + tqdm [--help | options] Options: -h, --help Print this help and exit -v, --version Print version and exit -""" + d - opts = docopt(__doc__, version=__version__) +""" + d.strip('\n') + '\n' + + # opts = docopt(__doc__, version=__version__) + if any(v in sys.argv for v in ('-v', '--version')): + sys.stdout.write(__version__ + '\n') + sys.exit(0) + elif any(v in sys.argv for v in ('-h', '--help')): + sys.stdout.write(__doc__ + '\n') + sys.exit(0) + + argv = re.split('(--\S+)[=\s]*', ' '.join(sys.argv[1:])) + opts = dict(zip(argv[1::2], argv[2::2])) + tqdm_args = {} try: - for opt in opt_types: - opt_types[opt] = cast(opts['--' + opt], opt_types[opt]) - for i in tqdm(sys.stdin, **opt_types): + for (o, v) in opts.items(): + tqdm_args[o[2:]] = cast(v, opt_types[o[2:]]) + # print('debug |', tqdm_args) + for i in tqdm(sys.stdin, **tqdm_args): sys.stdout.write(i) except: # pragma: no cover - sys.stderr.write(__doc__ + '\n') for i in sys.stdin: sys.stdout.write(i) + sys.stderr.write('\nUsage:\n tqdm [--help | options]\n') + raise diff --git a/tqdm/_tqdm.py b/tqdm/_tqdm.py index c9c2f99ee..cd0653df1 100644 --- a/tqdm/_tqdm.py +++ b/tqdm/_tqdm.py @@ -300,7 +300,8 @@ def write(cls, s, file=sys.stdout, end="\n"): # Force refresh display of all bars for inst in cls._instances: inst.refresh() - # TODO: make a list with all instances including absolutely positioned ones? + # TODO: make a list with all instances + # including absolutely positioned ones? def __init__(self, iterable=None, desc=None, total=None, leave=True, file=sys.stderr, ncols=None, mininterval=0.1, @@ -321,7 +322,8 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True, len(iterable) is used if possible. As a last resort, only basic progress statistics are displayed (no ETA, no progressbar). If `gui` is True and this parameter needs subsequent updating, - specify an initial arbitrary large positive integer, e.g. int(9e9). + specify an initial arbitrary large positive integer, + e.g. int(9e9). leave : bool, optional If [default: True], keeps all traces of the progressbar upon termination of iteration. diff --git a/tqdm/tests/tests_main.py b/tqdm/tests/tests_main.py index e6bcd261b..e7daf86bf 100644 --- a/tqdm/tests/tests_main.py +++ b/tqdm/tests/tests_main.py @@ -1,7 +1,6 @@ import sys import subprocess from tqdm import main -from docopt import DocoptExit from copy import deepcopy from tests_tqdm import with_setup, pretest, posttest, _range @@ -37,15 +36,22 @@ def test_main(): '--ascii', 'True', '--unit_scale', 'True'] import tqdm.__main__ # NOQA - sys.argv = ['', '--bad', 'arg', + sys.argv = ['', '--bad_arg_u_ment', 'foo', '--ascii', 'True', '--unit_scale', 'True'] try: main() - except DocoptExit as e: - if """Usage: - tqdm [--help | options]""" not in str(e): + except KeyError as e: + if 'bad_arg_u_ment' not in str(e): raise + for i in ('-h', '--help', '-v', '--version'): + sys.argv = ['', i] + try: + main() + except SystemExit: + pass + + # clean up try: sys.stdin, sys.argv = _SYS except: