11"""Fixture output configuration for generated test fixtures."""
22
33import shutil
4+ import subprocess
45import tarfile
56from pathlib import Path
67
@@ -219,11 +220,28 @@ def create_directories(self, is_master: bool) -> None:
219220 parents = True , exist_ok = True
220221 )
221222
223+ @staticmethod
224+ def _pigz_available () -> bool :
225+ """Check if pigz (parallel gzip) is available on the system."""
226+ return shutil .which ("pigz" ) is not None
227+
222228 def create_tarball (self ) -> None :
223- """Create tarball of the output directory if configured to do so."""
229+ """
230+ Create tarball of the output directory if configured to do so.
231+
232+ Automatically uses pigz for parallel compression if available,
233+ otherwise falls back to standard single-threaded gzip.
234+ """
224235 if not self .is_tarball :
225236 return
226237
238+ if self ._pigz_available ():
239+ self ._create_tarball_with_pigz ()
240+ else :
241+ self ._create_tarball_standard ()
242+
243+ def _create_tarball_standard (self ) -> None :
244+ """Create tarball using Python's tarfile module (single-threaded)."""
227245 with tarfile .open (self .output_path , "w:gz" ) as tar :
228246 for file in self .directory .rglob ("*" ):
229247 if file .suffix in {".json" , ".ini" }:
@@ -232,6 +250,38 @@ def create_tarball(self) -> None:
232250 )
233251 tar .add (file , arcname = arcname )
234252
253+ def _create_tarball_with_pigz (self ) -> None :
254+ """
255+ Create tarball using Python tarfile + pigz for parallel compression.
256+
257+ This approach uses Python's tarfile to create the uncompressed .tar
258+ (which correctly handles arcnames across all platforms), then uses
259+ pigz for parallel gzip compression with auto-detected core count.
260+ """
261+ # Create uncompressed tar first (output_path minus .gz suffix)
262+ temp_tar = self .output_path .with_suffix ("" ) # Remove .gz suffix
263+
264+ try :
265+ # Use Python tarfile for cross-platform tar creation with arcnames
266+ with tarfile .open (temp_tar , "w" ) as tar :
267+ for file in self .directory .rglob ("*" ):
268+ if file .suffix in {".json" , ".ini" }:
269+ arcname = Path ("fixtures" ) / file .relative_to (
270+ self .directory
271+ )
272+ tar .add (file , arcname = arcname )
273+
274+ # Compress with pigz (parallel gzip, auto-detects available cores)
275+ subprocess .run (
276+ ["pigz" , "-f" , str (temp_tar )], check = True , capture_output = True
277+ )
278+ except subprocess .CalledProcessError :
279+ # Clean up temp file if it exists
280+ if temp_tar .exists ():
281+ temp_tar .unlink ()
282+ # Fall back to standard tarball creation
283+ self ._create_tarball_standard ()
284+
235285 @classmethod
236286 def from_config (cls , config : pytest .Config ) -> "FixtureOutput" :
237287 """Create a FixtureOutput instance from pytest configuration."""
0 commit comments