@@ -715,29 +715,34 @@ def download_keys(scheme: str) -> None:
715715
716716 print (f"Downloading { scheme } keys from { url } ..." )
717717
718- # Download to a temporary file to avoid partial-write corruption.
719- with tempfile .NamedTemporaryFile (suffix = ".tar.gz" , delete = False ) as tmp_file :
720- tmp_path = Path (tmp_file .name )
721- try :
722- # Stream the response directly into the temp file.
723- with urllib .request .urlopen (url ) as response :
724- shutil .copyfileobj (response , tmp_file )
725-
726- # Remove any existing keys for this scheme before extracting.
727- target_dir = base_dir / f"{ scheme } _scheme"
728- if target_dir .exists ():
729- shutil .rmtree (target_dir )
730- base_dir .mkdir (parents = True , exist_ok = True )
731-
732- # Extract the archive into the base directory.
733- # The archive root is the scheme directory itself.
734- with tarfile .open (tmp_path , "r:gz" ) as tar :
735- tar .extractall (path = base_dir , filter = "data" )
736-
737- print (f"Extracted { scheme } keys to { target_dir } /" )
738- finally :
739- # Always clean up the temporary download file.
740- tmp_path .unlink (missing_ok = True )
718+ # Reserve a temp path; we open it explicitly below so the writer can close
719+ # before the reader opens.
720+ tmp_fd , tmp_name = tempfile .mkstemp (suffix = ".tar.gz" )
721+ os .close (tmp_fd )
722+ tmp_path = Path (tmp_name )
723+
724+ try :
725+ # Close the writer before opening the reader.
726+ # Otherwise Python's userspace buffer can withhold the tail of the gzip stream.
727+ # That produces a near-end decompression failure that looks like a truncated download.
728+ with urllib .request .urlopen (url ) as response , tmp_path .open ("wb" ) as out :
729+ shutil .copyfileobj (response , out )
730+
731+ # Remove any existing keys for this scheme before extracting.
732+ target_dir = base_dir / f"{ scheme } _scheme"
733+ if target_dir .exists ():
734+ shutil .rmtree (target_dir )
735+ base_dir .mkdir (parents = True , exist_ok = True )
736+
737+ # Extract the archive into the base directory.
738+ # The archive root is the scheme directory itself.
739+ with tarfile .open (tmp_path , "r:gz" ) as tar :
740+ tar .extractall (path = base_dir , filter = "data" )
741+
742+ print (f"Extracted { scheme } keys to { target_dir } /" )
743+ finally :
744+ # Always clean up the temporary download file.
745+ tmp_path .unlink (missing_ok = True )
741746
742747 print ("Download complete!" )
743748
0 commit comments