diff --git a/httpie/downloads.py b/httpie/downloads.py index 28ffe24a..df7382db 100644 --- a/httpie/downloads.py +++ b/httpie/downloads.py @@ -157,6 +157,7 @@ class Download(object): self._output_file = output_file self._resume = resume self._resumed_from = 0 + self._finished = False self._progress = Progress() self._progress_reporter = ProgressReporter( @@ -256,8 +257,8 @@ class Download(object): return stream, self._output_file def finish(self): - assert not self._output_file.closed - self._output_file.close() + assert not self._finished + self._finished = True self._progress.finished() @property @@ -351,12 +352,16 @@ class ProgressReporter(object): speed = 0 if not self.progress.total_size: - template = PROGRESS_NO_CONTENT_LENGTH - percentage = None - eta = None + self._status_line = PROGRESS_NO_CONTENT_LENGTH.format( + downloaded=humanize_bytes(downloaded), + speed=humanize_bytes(speed), + ) else: - template = PROGRESS - percentage = downloaded / self.progress.total_size * 100 + try: + percentage = downloaded / self.progress.total_size * 100 + except ZeroDivisionError: + percentage = 0 + if not speed: eta = '-:--:--' else: @@ -365,12 +370,12 @@ class ProgressReporter(object): m, s = divmod(s, 60) eta = '{}:{:0>2}:{:0>2}'.format(h, m, s) - self._status_line = template.format( - percentage=percentage, - downloaded=humanize_bytes(downloaded), - speed=humanize_bytes(speed), - eta=eta, - ) + self._status_line = PROGRESS.format( + percentage=percentage, + downloaded=humanize_bytes(downloaded), + speed=humanize_bytes(speed), + eta=eta, + ) self._prev_time = now self._prev_bytes = downloaded diff --git a/tests/tests.py b/tests/tests.py index 5dc740a2..b99a5f91 100755 --- a/tests/tests.py +++ b/tests/tests.py @@ -27,6 +27,7 @@ import argparse import tempfile import unittest import shutil +import time try: from urllib.request import urlopen @@ -69,7 +70,7 @@ from httpie.downloads import ( filename_from_content_disposition, filename_from_url, get_unique_filename, - ContentRangeError + ContentRangeError, ) @@ -189,20 +190,25 @@ def http(*args, **kwargs): if not env: env = kwargs['env'] = TestEnvironment() + stdout = env.stdout + stderr = env.stderr try: try: exit_status = main(args=['--traceback'] + list(args), **kwargs) + if '--download' in args: + # Let the progress reporter thread finish. + time.sleep(.5) except Exception: - sys.stderr.write(env.stderr.read()) + sys.stderr.write(stderr.read()) raise except SystemExit: exit_status = ExitStatus.ERROR - env.stdout.seek(0) - env.stderr.seek(0) + stdout.seek(0) + stderr.seek(0) - output = env.stdout.read() + output = stdout.read() try: r = StrResponse(output.decode('utf8')) except UnicodeDecodeError: @@ -224,14 +230,14 @@ def http(*args, **kwargs): except ValueError: pass - r.stderr = env.stderr.read() + r.stderr = stderr.read() r.exit_status = exit_status return r finally: - env.stdout.close() - env.stderr.close() + stdout.close() + stderr.close() class BaseTestCase(unittest.TestCase): @@ -1521,7 +1527,22 @@ class DownloadUtilsTest(BaseTestCase): class DownloadTest(BaseTestCase): # TODO: Download tests. - pass + + def test_download(self): + url = httpbin('/robots.txt') + body = urlopen(url).read().decode() + r = http( + '--download', + url, + env=TestEnvironment( + stdin_isatty=True, + stdout_isatty=False + ) + ) + self.assertIn('Downloading', r.stderr) + self.assertIn('[K', r.stderr) + self.assertIn('Done', r.stderr) + self.assertEqual(body, r) if __name__ == '__main__':