Skip to content

Commit 4bb0bcc

Browse files
authored
Added untar progress similar to existing unzip (#17519)
* Added untar progress similar to existing unzip * Python 3.6 compatible * Refactor FileProgress class and use it on uncompress * Restored prev FileProgress location and use with * Removed tell() call and added size limitation
1 parent aee9710 commit 4bb0bcc

File tree

2 files changed

+24
-42
lines changed

2 files changed

+24
-42
lines changed

conan/tools/files/files.py

+3-21
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
import platform
44
import shutil
55
import subprocess
6-
import sys
76
from contextlib import contextmanager
87
from fnmatch import fnmatch
98
from shutil import which
109

1110

1211
from conans.client.downloaders.caching_file_downloader import SourcesCachingDownloader
1312
from conan.errors import ConanException
13+
from conans.client.rest.file_uploader import FileProgress
1414
from conans.util.files import rmdir as _internal_rmdir, human_size, check_with_algorithm_sum
1515

1616

@@ -261,7 +261,6 @@ def chdir(conanfile, newdir):
261261
finally:
262262
os.chdir(old_path)
263263

264-
265264
def unzip(conanfile, filename, destination=".", keep_permissions=False, pattern=None,
266265
strip_root=False, extract_filter=None):
267266
"""
@@ -305,20 +304,7 @@ def unzip(conanfile, filename, destination=".", keep_permissions=False, pattern=
305304
import zipfile
306305
full_path = os.path.normpath(os.path.join(os.getcwd(), destination))
307306

308-
if hasattr(sys.stdout, "isatty") and sys.stdout.isatty():
309-
def print_progress(the_size, uncomp_size):
310-
the_size = (the_size * 100.0 / uncomp_size) if uncomp_size != 0 else 0
311-
txt_msg = "Unzipping %d %%"
312-
if the_size > print_progress.last_size + 1:
313-
output.rewrite_line(txt_msg % the_size)
314-
print_progress.last_size = the_size
315-
if int(the_size) == 99:
316-
output.rewrite_line(txt_msg % 100)
317-
else:
318-
def print_progress(_, __):
319-
pass
320-
321-
with zipfile.ZipFile(filename, "r") as z:
307+
with FileProgress(filename, msg="Unzipping", mode="r") as file, zipfile.ZipFile(file) as z:
322308
zip_info = z.infolist()
323309
if pattern:
324310
zip_info = [zi for zi in zip_info if fnmatch(zi.filename, pattern)]
@@ -343,19 +329,16 @@ def print_progress(_, __):
343329
output.info("Unzipping %s" % human_size(uncompress_size))
344330
extracted_size = 0
345331

346-
print_progress.last_size = -1
347332
if platform.system() == "Windows":
348333
for file_ in zip_info:
349334
extracted_size += file_.file_size
350-
print_progress(extracted_size, uncompress_size)
351335
try:
352336
z.extract(file_, full_path)
353337
except Exception as e:
354338
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="exception")
355339
else: # duplicated for, to avoid a platform check for each zipped file
356340
for file_ in zip_info:
357341
extracted_size += file_.file_size
358-
print_progress(extracted_size, uncompress_size)
359342
try:
360343
z.extract(file_, full_path)
361344
if keep_permissions:
@@ -367,11 +350,10 @@ def print_progress(_, __):
367350
output.error(f"Error extract {file_.filename}\n{str(e)}", error_type="exception")
368351
output.writeln("")
369352

370-
371353
def untargz(filename, destination=".", pattern=None, strip_root=False, extract_filter=None):
372354
# NOT EXPOSED at `conan.tools.files` but used in tests
373355
import tarfile
374-
with tarfile.TarFile.open(filename, 'r:*') as tarredgzippedFile:
356+
with FileProgress(filename, msg="Uncompressing") as fileobj, tarfile.TarFile.open(fileobj=fileobj, mode='r:*') as tarredgzippedFile:
375357
f = getattr(tarfile, f"{extract_filter}_filter", None) if extract_filter else None
376358
tarredgzippedFile.extraction_filter = f or (lambda member_, _: member_)
377359
if not pattern and not strip_root:

conans/client/rest/file_uploader.py

+21-21
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import io
12
import os
23
import time
34

@@ -81,27 +82,7 @@ def upload(self, url, abs_path, auth=None, dedup=False, retry=None, retry_wait=N
8182
time.sleep(retry_wait)
8283

8384
def _upload_file(self, url, abs_path, headers, auth, ref):
84-
class FileProgress: # Wrapper just to provide an upload progress every 10 seconds
85-
def __init__(self, f, total_size):
86-
self._f = f
87-
self._total = total_size
88-
self._name = os.path.basename(f.name)
89-
self._t = TimedOutput(interval=10)
90-
self._read = 0
91-
92-
def __getattr__(self, item):
93-
return getattr(self._f, item)
94-
95-
def read(self, n=-1):
96-
read_bytes = self._f.read(n)
97-
self._read += len(read_bytes)
98-
self._t.info(f"{ref}: Uploading {self._name}: {int(self._read*100/self._total)}%")
99-
return read_bytes
100-
101-
filesize = os.path.getsize(abs_path)
102-
with open(abs_path, mode='rb') as file_handler:
103-
big_file = filesize > 100000000 # 100 MB
104-
file_handler = FileProgress(file_handler, filesize) if big_file else file_handler
85+
with FileProgress(abs_path, mode='rb', msg=f"{ref}: Uploading") as file_handler:
10586
try:
10687
response = self._requester.put(url, data=file_handler, verify=self._verify_ssl,
10788
headers=headers, auth=auth,
@@ -113,3 +94,22 @@ def read(self, n=-1):
11394
raise
11495
except Exception as exc:
11596
raise ConanException(exc)
97+
98+
99+
class FileProgress(io.FileIO):
100+
def __init__(self, path: str, msg: str = "Uploading", report_interval: float = 1 , *args, **kwargs):
101+
super().__init__(path, *args, **kwargs)
102+
self._total_size = os.path.getsize(path)
103+
self._filename = os.path.basename(path)
104+
# Report only on big sizes (>100MB)
105+
self._reporter = TimedOutput(interval=report_interval) if self._total_size > 100_000_000 else None
106+
self._bytes_read = 0
107+
self.msg = msg
108+
109+
def read(self, size: int = -1) -> bytes:
110+
block = super().read(size)
111+
self._bytes_read += len(block)
112+
if self._reporter:
113+
current_percentage = int(self._bytes_read * 100.0 / self._total_size) if self._total_size != 0 else 0
114+
self._reporter.info(f"{self.msg} {self._filename}: {current_percentage}%")
115+
return block

0 commit comments

Comments
 (0)