diff --git a/.gitignore b/.gitignore index ded6067..1a1f52a 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,6 @@ nosetests.xml .mr.developer.cfg .project .pydevproject + +# PyCharm +.idea diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b509775 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: python +python: 2.7 +env: +- TOXENV=py26 +- TOXENV=py27 +- TOXENV=py32 +- TOXENV=py33 +- TOXENV=py34 +- TOXENV=pypy +- TOXENV=pypy3 +install: +- pip install tox +script: +- tox diff --git a/README.md b/README.md index f65d305..b749ccf 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ tqdm ==== -Instantly make your loops show a progress meter - just wrap any iterator with "tqdm(iterator)", and you're done! +[![Build Status](https://img.shields.io/travis/kmike/tqdm.svg?branch=all-fixes)](https://travis-ci.org/kmike/tqdm) + +Instantly make your loops show a progress meter - just wrap any iterable with "tqdm(iterable)", and you're done! ![ScreenShot](https://i.imgur.com/he9Aw5C.gif) @@ -31,3 +33,9 @@ def trange(*args, **kwargs): """A shortcut for writing tqdm(xrange)""" return tqdm(xrange(*args), **kwargs) ``` + +Running tests +------------- + +Please make sure tox (http://tox.testrun.org/) is installed and type +`tox` from the command line. diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..8722621 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +python_files = test*.py diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..2a9acf1 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,2 @@ +[bdist_wheel] +universal = 1 diff --git a/setup.py b/setup.py index 7b36604..2b9a035 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,27 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- +from setuptools import setup -from distutils.core import setup - -setup(name='tqdm', - version='1.0', - description='A Simple Python Progress Meter', - author='Noam Yorav-Raphael', - author_email='noamraph@gmail.com', - url='https://github.com/noamraph/tqdm', - py_modules=['tqdm'], - ) +setup( + name='tqdm', + version='1.0', + description='A Simple Python Progress Meter', + license='MIT License', + author='Noam Yorav-Raphael', + author_email='noamraph@gmail.com', + url='https://github.com/noamraph/tqdm', + py_modules=['tqdm'], + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'License :: OSI Approved :: MIT License', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.2', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Software Development :: Libraries', + 'Intended Audience :: Developers', + ], +) diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..c377bf1 --- /dev/null +++ b/tests.py @@ -0,0 +1,69 @@ +from __future__ import unicode_literals + +import csv +from six import StringIO +from tqdm import format_interval, format_meter, tqdm + + +def test_format_interval(): + assert format_interval(60) == '01:00' + assert format_interval(6160) == '1:42:40' + assert format_interval(238113) == '66:08:33' + + +def test_format_meter(): + assert format_meter(0, 1000, 13) == \ + "|----------| 0/1000 0% [elapsed: " \ + "00:13 left: ?, 0.00 iters/sec]" + assert format_meter(231, 1000, 392) == \ + "|##--------| 231/1000 23% [elapsed: " \ + "06:32 left: 21:44, 0.59 iters/sec]" + + +def test_nothing_fails(): + """ Just make sure we're able to iterate using tqdm """ + for i in tqdm(range(10)): + pass + + +def test_iterate_over_csv_rows(): + # Create a test csv pseudo file + test_csv_file = StringIO() + writer = csv.writer(test_csv_file) + for i in range(3): + writer.writerow(['test', 'test', 'test']) + test_csv_file.seek(0) + + # Test that nothing fails if we iterate over rows + reader = csv.DictReader(test_csv_file, fieldnames=('row1', 'row2', 'row3')) + for row in tqdm(reader): + pass + + +def test_file_output(): + """ Tests that output to arbitrary file-like objects works """ + our_file = StringIO() + for i in tqdm(range(3), file=our_file): + if i == 1: + our_file.seek(0) + assert '0/3' in our_file.read() + + +def test_leave_option(): + """ + Tests that if leave=True, tqdm will leave the info + about the last iteration on the screen + """ + our_file = StringIO() + for i in tqdm(range(3), file=our_file, leave=True): + pass + our_file.seek(0) + assert '3/3 100%' in our_file.read() + our_file.close() + + our_file2 = StringIO() + for i in tqdm(range(3), file=our_file2, leave=False): + pass + our_file2.seek(0) + assert '3/3 100%' not in our_file2.read() + our_file2.close() diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..00fd947 --- /dev/null +++ b/tox.ini @@ -0,0 +1,13 @@ +# Tox (http://tox.testrun.org/) is a tool for running tests +# in multiple virtualenvs. This configuration file will run the +# test suite on all supported python versions. To use it, "pip install tox" +# and then run "tox" from this directory. + +[tox] +envlist = py26, py27, py32, py33, py34, pypy, pypy3 + +[testenv] +commands = py.test +deps = + six + pytest diff --git a/tqdm.py b/tqdm.py index 8c21092..14fcbe5 100644 --- a/tqdm.py +++ b/tqdm.py @@ -1,9 +1,12 @@ -__all__ = ['tqdm', 'trange'] +from __future__ import division import sys import time +__all__ = ['tqdm', 'trange'] + + def format_interval(t): mins, s = divmod(int(t), 60) h, m = divmod(mins, 60) @@ -17,7 +20,7 @@ def format_meter(n, total, elapsed): # n - number of finished iterations # total - total number of iterations, or None # elapsed - number of seconds passed since start - if n > total: + if total and n > total: total = None elapsed_str = format_interval(elapsed) @@ -71,7 +74,7 @@ def tqdm(iterable, desc='', total=None, leave=False, file=sys.stderr, if total is None: try: total = len(iterable) - except TypeError: + except (TypeError, AttributeError): total = None prefix = desc+': ' if desc else ''