@@ -76,6 +76,8 @@ def save(self) -> None:
76
76
RecordPath = NewType ("RecordPath" , str )
77
77
InstalledCSVRow = Tuple [RecordPath , str , Union [int , str ]]
78
78
79
+ IS_NOT_PYTHON_FILE_RE = re .compile (r'^.*(?<!\.py)$' )
80
+
79
81
80
82
def rehash (path : str , blocksize : int = 1 << 20 ) -> Tuple [str , str ]:
81
83
"""Return (encoded_digest, length) for path using hashlib.sha256()"""
@@ -596,13 +598,34 @@ def pyc_source_file_paths() -> Generator[str, None, None]:
596
598
# Sorting installation paths makes it easier to reproduce and debug
597
599
# issues related to permissions on existing files.
598
600
for installed_path in sorted (set (installed .values ())):
601
+ if not installed_path .endswith (".py" ):
602
+ continue
603
+
599
604
full_installed_path = os .path .join (lib_dir , installed_path )
600
605
if not os .path .isfile (full_installed_path ):
601
606
continue
602
- if not full_installed_path .endswith (".py" ):
603
- continue
604
607
yield full_installed_path
605
608
609
+ def pyc_source_root_dirs () -> Generator [str , None , None ]:
610
+ # All root source directories of the install (i.e. those that
611
+ # are direct children of lib_dir) that the source Python files
612
+ # are located within. Typically this is just one directory.
613
+ source_root_dirs = set ()
614
+ for installed_path in installed .values ():
615
+ if not installed_path .endswith (".py" ):
616
+ continue
617
+
618
+ full_installed_path = os .path .join (lib_dir , installed_path )
619
+ if not os .path .isfile (full_installed_path ):
620
+ continue
621
+
622
+ parent_full_installed_path = os .path .dirname (full_installed_path )
623
+ if os .path .dirname (parent_full_installed_path ) == lib_dir :
624
+ if parent_full_installed_path in source_root_dirs :
625
+ continue
626
+ source_root_dirs .add (parent_full_installed_path )
627
+ yield parent_full_installed_path
628
+
606
629
def pyc_output_path (path : str ) -> str :
607
630
"""Return the path the pyc file would have been written to."""
608
631
return importlib .util .cache_from_source (path )
@@ -614,11 +637,16 @@ def pyc_output_path(path: str) -> str:
614
637
) as stdout :
615
638
with warnings .catch_warnings ():
616
639
warnings .filterwarnings ("ignore" )
640
+ # Use compile_dir on the root directories in the package,
641
+ # as compile_dir uses multiprocess this will be quicker
642
+ # than using compile_file on each file.
643
+ for dir in pyc_source_root_dirs ():
644
+ compileall .compile_dir (dir , force = True , quiet = 2 , workers = 0 , rx = IS_NOT_PYTHON_FILE_RE )
645
+
646
+ # Now check indivdual files were created
617
647
for path in pyc_source_file_paths ():
618
- success = compileall .compile_file (path , force = True , quiet = True )
619
- if success :
620
- pyc_path = pyc_output_path (path )
621
- assert os .path .exists (pyc_path )
648
+ pyc_path = pyc_output_path (path )
649
+ if os .path .exists (pyc_path ):
622
650
pyc_record_path = cast (
623
651
"RecordPath" , pyc_path .replace (os .path .sep , "/" )
624
652
)
0 commit comments