[PATCH 12/21] lookaside: Add a progress callback
Mathieu Bridon
bochecha at fedoraproject.org
Wed May 6 11:53:08 UTC 2015
From: Mathieu Bridon <bochecha at daitauha.fr>
Due to the way pycurl handles progress callback, this handles both
upload and download progress.
However, we only use it for download at the moment.
---
src/pyrpkg/lookaside.py | 24 +++++++++++++++
test/test_lookaside.py | 81 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 105 insertions(+)
diff --git a/src/pyrpkg/lookaside.py b/src/pyrpkg/lookaside.py
index 1108fcf..8badc73 100644
--- a/src/pyrpkg/lookaside.py
+++ b/src/pyrpkg/lookaside.py
@@ -43,6 +43,24 @@ class CGILookasideCache(object):
self.download_path = '%(name)s/%(filename)s/%(hash)s/%(filename)s'
+ def print_progress(self, to_download, downloaded, to_upload, uploaded):
+ if to_download > 0:
+ done = downloaded / to_download
+
+ elif to_upload > 0:
+ done = uploaded / to_upload
+
+ else:
+ return
+
+ done_chars = int(done * 72)
+ remain_chars = 72 - done_chars
+ done = int(done * 1000) / 10.0
+
+ p = "\r%s%s %s%%" % ("#" * done_chars, " " * remain_chars, done)
+ sys.stdout.write(p)
+ sys.stdout.flush()
+
def hash_file(self, filename, hashtype=None):
"""Compute the hash of a file
@@ -117,6 +135,8 @@ class CGILookasideCache(object):
c = pycurl.Curl()
c.setopt(pycurl.URL, url)
c.setopt(pycurl.HTTPHEADER, ['Pragma:'])
+ c.setopt(pycurl.NOPROGRESS, False)
+ c.setopt(pycurl.PROGRESSFUNCTION, self.print_progress)
c.setopt(pycurl.OPT_FILETIME, True)
c.setopt(pycurl.WRITEDATA, f)
@@ -131,6 +151,10 @@ class CGILookasideCache(object):
finally:
c.close()
+ # Get back a new line, after displaying the download progress
+ sys.stdout.write('\n')
+ sys.stdout.flush()
+
if status != 200:
raise DownloadError('Server returned status code %d' % status)
diff --git a/test/test_lookaside.py b/test/test_lookaside.py
index 89a34cd..7fe1743 100644
--- a/test/test_lookaside.py
+++ b/test/test_lookaside.py
@@ -186,3 +186,84 @@ class CGILookasideCacheTestCase(unittest.TestCase):
lc = CGILookasideCache('sha512', 'http://example.com', '_')
self.assertRaises(DownloadError, lc.download, 'pyrpkg',
'pyrpkg-0.0.tar.xz', hash, outfile)
+
+ @mock.patch('pyrpkg.lookaside.sys.stdout')
+ def test_print_download_progress(self, mock_stdout):
+ def mock_write(msg):
+ written_lines.append(msg)
+
+ written_lines = []
+ expected_lines = [
+ '\r################## 25.0%', # nopep8
+ '\r#################################### 50.0%', # nopep8
+ '\r###################################################### 75.0%', # nopep8
+ '\r######################################################################## 100.0%', # nopep8
+ ]
+
+ mock_stdout.write.side_effect = mock_write
+
+ lc = CGILookasideCache('_', '_', '_')
+ lc.print_progress(2000.0, 500.0, 0.0, 0.0)
+ self.assertEqual(mock_stdout.write.call_count, 1)
+ self.assertEqual(len(written_lines), 1)
+
+ lc.print_progress(2000.0, 1000.0, 0.0, 0.0)
+ self.assertEqual(mock_stdout.write.call_count, 2)
+ self.assertEqual(len(written_lines), 2)
+
+ lc.print_progress(2000.0, 1500.0, 0.0, 0.0)
+ self.assertEqual(mock_stdout.write.call_count, 3)
+ self.assertEqual(len(written_lines), 3)
+
+ lc.print_progress(2000.0, 2000.0, 0.0, 0.0)
+ self.assertEqual(mock_stdout.write.call_count, 4)
+ self.assertEqual(len(written_lines), 4)
+
+ self.assertEqual(written_lines, expected_lines)
+
+ @mock.patch('pyrpkg.lookaside.sys.stdout')
+ def test_print_upload_progress(self, mock_stdout):
+ def mock_write(msg):
+ written_lines.append(msg)
+
+ written_lines = []
+ expected_lines = [
+ '\r################## 25.0%', # nopep8
+ '\r#################################### 50.0%', # nopep8
+ '\r###################################################### 75.0%', # nopep8
+ '\r######################################################################## 100.0%', # nopep8
+ ]
+
+ mock_stdout.write.side_effect = mock_write
+
+ lc = CGILookasideCache('_', '_', '_')
+ lc.print_progress(0.0, 0.0, 2000.0, 500.0)
+ self.assertEqual(mock_stdout.write.call_count, 1)
+ self.assertEqual(len(written_lines), 1)
+
+ lc.print_progress(0.0, 0.0, 2000.0, 1000.0)
+ self.assertEqual(mock_stdout.write.call_count, 2)
+ self.assertEqual(len(written_lines), 2)
+
+ lc.print_progress(0.0, 0.0, 2000.0, 1500.0)
+ self.assertEqual(mock_stdout.write.call_count, 3)
+ self.assertEqual(len(written_lines), 3)
+
+ lc.print_progress(0.0, 0.0, 2000.0, 2000.0)
+ self.assertEqual(mock_stdout.write.call_count, 4)
+ self.assertEqual(len(written_lines), 4)
+
+ self.assertEqual(written_lines, expected_lines)
+
+ @mock.patch('pyrpkg.lookaside.sys.stdout')
+ def test_print_no_progress(self, mock_stdout):
+ def mock_write(msg):
+ written_lines.append(msg)
+
+ written_lines = []
+
+ mock_stdout.write.side_effect = mock_write
+
+ lc = CGILookasideCache('_', '_', '_')
+ lc.print_progress(0.0, 0.0, 0.0, 0.0)
+ self.assertEqual(len(written_lines), 0)
--
2.1.0
More information about the rel-eng
mailing list