4747 model_validator ,
4848)
4949from pydantic_core import core_schema
50+ from tqdm import tqdm
5051from typing_extensions import (
5152 Annotated ,
5253 LiteralString ,
@@ -725,10 +726,16 @@ def resolve(
725726 if settings .user_agent is not None :
726727 headers ["User-Agent" ] = settings .user_agent
727728
728- if settings .cache_path and not get_validation_context ().disable_cache :
729+ chunk_size = 1024
730+ if (
731+ settings .cache_path
732+ and not get_validation_context ().disable_cache
733+ and any (v is not None for v in kwargs .values ())
734+ ):
729735 downloader = pooch .HTTPDownloader (
730736 headers = headers ,
731737 progressbar = progressbar , # pyright: ignore[reportArgumentType]
738+ chunk_size = chunk_size ,
732739 )
733740 fname = _get_unique_file_name (source )
734741 _ls : Any = pooch .retrieve (
@@ -746,23 +753,47 @@ def resolve(
746753 )
747754 else :
748755 # cacheless download to memory using an in memory zip file
749- r = requests .get (str (source ))
756+ r = requests .get (str (source ), stream = True )
750757 r .raise_for_status ()
751- if not isinstance (r .content , bytes ):
752- raise TypeError (
753- f"Request content of { source } has unexpected type { type (r .content )} ."
754- )
755758
756759 zf = zipfile .ZipFile (io .BytesIO (), "w" )
757760 fn = extract_file_name (source )
758- # alternative implementation; TODO: remove commented code
759- # zf.writestr(fn, r.content)
760- # zp = ZipPath(zf) / fn
761- # assert zp.exists(), f"failed to write {fn} to in-memory zip file"
761+ total = int (r .headers .get ("content-length" , 0 ))
762+
763+ if isinstance (progressbar , bool ):
764+ if progressbar :
765+ use_ascii = bool (sys .platform == "win32" )
766+ pbar = tqdm (
767+ total = total ,
768+ ncols = 79 ,
769+ ascii = use_ascii ,
770+ unit = "B" ,
771+ unit_scale = True ,
772+ leave = True ,
773+ )
774+ pbar = tqdm (desc = f"Downloading { fn } " )
775+ else :
776+ pbar = None
777+ else :
778+ pbar = progressbar
779+
762780 zp = ZipPath (zf , fn )
763781 with zp .open ("wb" ) as z :
764782 assert not isinstance (z , io .TextIOWrapper )
765- _ = z .write (r .content )
783+ for chunk in r .iter_content (chunk_size = chunk_size ):
784+ n = z .write (chunk )
785+ if pbar is not None :
786+ _ = pbar .update (n )
787+
788+ # Make sure the progress bar gets filled even if the actual number
789+ # is chunks is smaller than expected. This happens when streaming
790+ # text files that are compressed by the server when sending (gzip).
791+ # Binary files don't experience this.
792+ # (adapted from pooch.HttpDownloader)
793+ if pbar is not None :
794+ pbar .reset ()
795+ _ = pbar .update (total )
796+ pbar .close ()
766797
767798 return FileInZip (
768799 path = zp ,
0 commit comments