Skip to content

Commit

Permalink
bump version, Merge branch 'cli_tidy'
Browse files Browse the repository at this point in the history
  • Loading branch information
casperdcl committed Apr 24, 2016
2 parents f5c75e4 + c31b01c commit 25369f5
Show file tree
Hide file tree
Showing 6 changed files with 123 additions and 71 deletions.
55 changes: 34 additions & 21 deletions README.rst
Expand Up @@ -31,7 +31,7 @@ It can also be executed as a module with pipes:

.. code:: sh
$ seq 9999999 | tqdm --unit_scale True | wc -l
$ seq 9999999 | tqdm --unit_scale | wc -l
10.0Mit [00:02, 3.58Mit/s]
9999999
Expand Down Expand Up @@ -177,9 +177,17 @@ Note that the usual arguments for ``tqdm`` can also be specified.
.. code:: sh
$ find . -name '*.py' -exec cat \{} \; |
tqdm --unit loc --unit_scale True --total 857366 >> /dev/null
tqdm --unit loc --unit_scale --total 857366 >> /dev/null
100%|███████████████████████████████████| 857K/857K [00:04<00:00, 246Kloc/s]
Backing up a large directory?

.. code:: sh
$ 7z a -bd -r backup.7z docs/ | grep Compressing |
tqdm --total $(find docs/ -type f | wc -l) --unit files >> backup.log
100%|███████████████████████████████▉| 8014/8014 [01:37<00:00, 82.29files/s]
Documentation
-------------
Expand All @@ -204,15 +212,16 @@ Parameters

* iterable : iterable, optional
Iterable to decorate with a progressbar.
Leave blank [default: None] to manually manage the updates.
Leave blank to manually manage the updates.
* desc : str, optional
Prefix for the progressbar [default: None].
Prefix for the progressbar.
* total : int, optional
The number of expected iterations. If [default: None], 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).
The number of expected iterations. If (default: None),
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).
* leave : bool, optional
If [default: True], keeps all traces of the progressbar
upon termination of iteration.
Expand All @@ -223,20 +232,20 @@ Parameters
* ncols : int, optional
The width of the entire output message. If specified,
dynamically resizes the progressbar to stay within this bound.
If [default: None], attempts to use environment width. The
If unspecified, attempts to use environment width. The
fallback is a meter width of 10 and no limit for the counter and
statistics. If 0, will not print any meter (only stats).
* mininterval : float, optional
Minimum progress update interval, in seconds [default: 0.1].
* maxinterval : float, optional
Maximum progress update interval, in seconds [default: 10.0].
* miniters : int, optional
Minimum progress update interval, in iterations [default: None].
Minimum progress update interval, in iterations.
If specified, will set `mininterval` to 0.
* ascii : bool, optional
If [default: None] or False, use unicode (smooth blocks) to fill
If unspecified or False, use unicode (smooth blocks) to fill
the meter. The fallback is to use ASCII characters `1-9 #`.
* disable : bool
* disable : bool, optional
Whether to disable the entire progressbar wrapper
[default: False].
* unit : str, optional
Expand All @@ -250,24 +259,28 @@ Parameters
* dynamic_ncols : bool, optional
If set, constantly alters `ncols` to the environment (allowing
for window resizes) [default: False].
* smoothing : float
* smoothing : float, optional
Exponential moving average smoothing factor for speed estimates
(ignored in GUI mode). Ranges from 0 (average speed) to 1
(current/instantaneous speed) [default: 0.3].
* bar_format : str, optional
Specify a custom bar string formatting. May impact performance.
If [default: None], will use '{l_bar}{bar}{r_bar}', where l_bar is
If unspecified, will use '{l_bar}{bar}{r_bar}', where l_bar is
'{desc}{percentage:3.0f}%|' and r_bar is
'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}]'.
'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}]'
Possible vars: bar, n, n_fmt, total, total_fmt, percentage,
rate, rate_fmt, elapsed, remaining, l_bar, r_bar, desc.
* initial : int, optional
The initial counter value. Useful when restarting a progress
bar [default: 0].
* position : int, optional
Specify the line offset to print this bar (starting from 0)
Automatic if [default: None].
Automatic if unspecified.
Useful to manage multiple bars at once (eg, from threads).
* gui : bool, optional
WARNING: internal parameter - do not use.
Use tqdm_gui(...) instead. If set, will attempt to use
matplotlib animations for a graphical output [default: False].

Returns
~~~~~~~
Expand Down Expand Up @@ -379,7 +392,7 @@ Here's an example with ``urllib``:
return inner
eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'
with tqdm(unit='B', unit_scale=True, leave=True, miniters=1,
with tqdm(unit='B', unit_scale=True, miniters=1,
desc=eg_link.split('/')[-1]) as t: # all optional kwargs
urllib.urlretrieve(eg_link, filename='/dev/null',
reporthook=my_hook(t), data=None)
Expand Down Expand Up @@ -488,7 +501,7 @@ To quickly fix that using ``tqdm``, we can use this naive approach:
.. code:: python
def process_content_with_progress1(inputpath, blocksize=1024):
for filepath in tqdm(walkdir(inputpath), leave=True):
for filepath in tqdm(walkdir(inputpath)):
with open(filepath, 'rb') as fh:
buf = 1
while (buf):
Expand All @@ -515,7 +528,7 @@ precompute this by ourselves:
for filename in files:
filecounter += 1
for filepath in tqdm(walkdir(inputpath), total=filecounter, leave=True):
for filepath in tqdm(walkdir(inputpath), total=filecounter):
with open(filepath, 'rb') as fh:
buf = 1
while (buf):
Expand Down Expand Up @@ -553,7 +566,7 @@ Below we implement this approach using a manually updated ``tqdm`` bar, where
sizecounter += os.stat(fullpath).st_size
# Load tqdm with size counter instead of files counter
with tqdm(total=sizecounter, leave=True, unit='B', unit_scale=True) as pbar:
with tqdm(total=sizecounter, unit='B', unit_scale=True) as pbar:
for dirpath, dirs, files in os.walk(inputpath):
for filename in files:
fullpath = os.path.abspath(os.path.join(dirpath, filename))
Expand Down
2 changes: 0 additions & 2 deletions tox.ini
Expand Up @@ -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
Expand All @@ -38,6 +37,5 @@ commands =
deps =
nose
nose-timer
docopt
commands =
nosetests --with-timer tqdm/tests/tests_perf.py -d -v
75 changes: 46 additions & 29 deletions tqdm/_main.py
Expand Up @@ -6,51 +6,68 @@


def cast(val, typ):
if val == 'None':
return None
if typ == 'bool':
return str(val) == 'True'
# try:
return eval(typ + '("' + str(val) + '")')
# except:
# # print val, typ
# if val == 'special':
# return 'whatever... just an example'
# else:
# return eval(typ + '()')
# sys.stderr.write('\ndebug | `val:type`: `' + val + ':' + typ + '`.\n')
if (val == 'True') or (val == ''):
return True
elif val == 'False':
return False
else:
raise ValueError(val + ' : ' + typ)

return eval(typ + '("' + val + '")')

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)

# RE_OPTS = re.compile(r' {8}(\S+)\s{2,}:\s*(str|int|float|bool)', flags=re.M)
RE_OPTS = re.compile(r'\n {8}(\S+)\s{2,}:\s*([^\s,]+)')

# 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=<v> ', d)
# d = RE_OPTS_BOOL.sub(r' --\1 ', d)
d = RE_OPTS.sub(r' --\1=<v> : \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('\n --{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+)[=\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:]])
# sys.stderr.write('\ndebug | args: ' + str(tqdm_args) + '\n')
for i in tqdm(sys.stdin, **tqdm_args):
sys.stdout.write(i)
except: # pragma: no cover
sys.stderr.write(__doc__ + '\n')
sys.stderr.write('\nError:\nUsage:\n tqdm [--help | options]\n')
for i in sys.stdin:
sys.stdout.write(i)
raise
23 changes: 12 additions & 11 deletions tqdm/_tqdm.py
Expand Up @@ -293,15 +293,16 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True,
----------
iterable : iterable, optional
Iterable to decorate with a progressbar.
Leave blank [default: None] to manually manage the updates.
Leave blank to manually manage the updates.
desc : str, optional
Prefix for the progressbar [default: None].
Prefix for the progressbar.
total : int, optional
The number of expected iterations. If [default: None],
The number of expected iterations. If unspecified,
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.
Expand All @@ -312,20 +313,20 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True,
ncols : int, optional
The width of the entire output message. If specified,
dynamically resizes the progressbar to stay within this bound.
If [default: None], attempts to use environment width. The
If unspecified, attempts to use environment width. The
fallback is a meter width of 10 and no limit for the counter and
statistics. If 0, will not print any meter (only stats).
mininterval : float, optional
Minimum progress update interval, in seconds [default: 0.1].
maxinterval : float, optional
Maximum progress update interval, in seconds [default: 10.0].
miniters : int, optional
Minimum progress update interval, in iterations [default: None].
Minimum progress update interval, in iterations.
If specified, will set `mininterval` to 0.
ascii : bool, optional
If [default: None] or False, use unicode (smooth blocks) to fill
If unspecified or False, use unicode (smooth blocks) to fill
the meter. The fallback is to use ASCII characters `1-9 #`.
disable : bool
disable : bool, optional
Whether to disable the entire progressbar wrapper
[default: False].
unit : str, optional
Expand All @@ -339,13 +340,13 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True,
dynamic_ncols : bool, optional
If set, constantly alters `ncols` to the environment (allowing
for window resizes) [default: False].
smoothing : float
smoothing : float, optional
Exponential moving average smoothing factor for speed estimates
(ignored in GUI mode). Ranges from 0 (average speed) to 1
(current/instantaneous speed) [default: 0.3].
bar_format : str, optional
Specify a custom bar string formatting. May impact performance.
If [default: None], will use '{l_bar}{bar}{r_bar}', where l_bar is
If unspecified, will use '{l_bar}{bar}{r_bar}', where l_bar is
'{desc}{percentage:3.0f}%|' and r_bar is
'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}]'
Possible vars: bar, n, n_fmt, total, total_fmt, percentage,
Expand All @@ -355,7 +356,7 @@ def __init__(self, iterable=None, desc=None, total=None, leave=True,
bar [default: 0].
position : int, optional
Specify the line offset to print this bar (starting from 0)
Automatic if [default: None].
Automatic if unspecified.
Useful to manage multiple bars at once (eg, from threads).
gui : bool, optional
WARNING: internal parameter - do not use.
Expand Down
2 changes: 1 addition & 1 deletion tqdm/_version.py
Expand Up @@ -8,7 +8,7 @@
__all__ = ["__version__"]

# major, minor, patch, -extra
version_info = 4, 4, 2
version_info = 4, 4, 3

# Nice string for the version
__version__ = '.'.join(map(str, version_info))
Expand Down
37 changes: 30 additions & 7 deletions 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
Expand Down Expand Up @@ -33,19 +32,43 @@ def test_main():
pass

sys.stdin = map(str, _range(int(1e3)))
sys.argv = ['', '--desc', 'Test command line pipes',
sys.argv = ['', '--desc', 'Test CLI pipes',
'--ascii', 'True', '--unit_scale', 'True']
import tqdm.__main__ # NOQA

sys.argv = ['', '--bad', 'arg',
'--ascii', 'True', '--unit_scale', 'True']
sys.argv = ['', '--ascii', '--unit_scale', 'False',
'--desc', 'Test CLI errors']
main()

sys.argv = ['', '--bad_arg_u_ment', 'foo', '--ascii', '--unit_scale']
try:
main()
except KeyError as e:
if 'bad_arg_u_ment' not in str(e):
raise

sys.argv = ['', '--ascii', '--unit_scale', 'invalid_bool_value']
try:
main()
except DocoptExit as e:
if """Usage:
tqdm [--help | options]""" not in str(e):
except ValueError as e:
if 'invalid_bool_value' not in str(e):
raise

sys.argv = ['', '--ascii', '--total', 'invalid_int_value']
try:
main()
except ValueError as e:
if 'invalid_int_value' 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:
Expand Down

0 comments on commit 25369f5

Please sign in to comment.