99
1010def file_hash (file ):
1111 h = hashlib .md5 ()
12-
1312 with open (file , "rb" ) as f :
1413 h .update (f .read ())
15-
1614 return h .hexdigest ()
1715
1816
1917def should_exclude (path , name , exclude_patterns ):
20- """Check if a path should be excluded based on patterns."""
21- # Check if the name itself matches any pattern
2218 for pattern in exclude_patterns :
23- # Exact name match
2419 if name == pattern :
2520 return True
2621
27- # Directory patterns (e.g., __pycache__, test)
2822 if pattern .startswith ('**/' ):
2923 pattern_name = pattern [3 :]
3024 if name == pattern_name :
3125 return True
3226
33- # Extension patterns (e.g., *.pyc)
3427 if pattern .startswith ('**/*.' ):
3528 ext = pattern [4 :] # Remove **/*
3629 if name .endswith (ext ):
3730 return True
3831
39- # Wildcard patterns
4032 if '*' in pattern and not pattern .startswith ('**/' ):
4133 import fnmatch
4234 if fnmatch .fnmatch (name , pattern ):
@@ -45,71 +37,49 @@ def should_exclude(path, name, exclude_patterns):
4537 return False
4638
4739
48- def copy_filtered_tree (src , dst , exclude_patterns , verbose = False ):
49- """Recursively copy directory tree with filtering."""
40+ def copy_filtered_tree (src , dst , exclude_patterns ):
5041 if not os .path .exists (dst ):
5142 os .makedirs (dst )
5243
5344 for item in os .listdir (src ):
5445 src_path = os .path .join (src , item )
5546 dst_path = os .path .join (dst , item )
5647
57- # Check if should exclude
5848 if should_exclude (src_path , item , exclude_patterns ):
59- if verbose :
60- print (f"Excluding: { os .path .relpath (src_path , src )} " )
6149 continue
6250
6351 if os .path .isdir (src_path ):
64- copy_filtered_tree (src_path , dst_path , exclude_patterns , verbose )
52+ copy_filtered_tree (src_path , dst_path , exclude_patterns )
6553 else :
6654 shutil .copy2 (src_path , dst_path )
67- if verbose :
68- print (f"Copied: { os .path .relpath (src_path , src )} " )
6955
7056
71- def clean_duplicate_libraries (directory , verbose = False ):
72- """Keep only one of each dynamic library type."""
57+ def clean_duplicate_libraries (directory ):
7358 lib_files = {}
74-
75- for root , dirs , files in os .walk (directory ):
59+ for root , _ , files in os .walk (directory ):
7660 for file in files :
7761 file_path = os .path .join (root , file )
7862
79- # Group by base name without version numbers
80- # e.g., libpython3.13.dylib -> libpython, libpython3.13.a -> libpython
81- if any (ext in file for ext in ['.dylib' , '.dll' , '.so' , '.a' , '.lib' ]):
82- # Extract base name and extension type
83- base_name = file .split ('.' )[0 ]
84-
85- # Determine library type
86- if '.dylib' in file :
87- lib_type = 'dylib'
88- elif '.dll' in file :
89- lib_type = 'dll'
90- elif '.so' in file :
91- lib_type = 'so'
92- elif '.a' in file :
93- lib_type = 'static'
94- elif '.lib' in file :
95- lib_type = 'lib'
96- else :
97- continue
63+ if not any (ext in file for ext in ['.dylib' , '.dll' , '.so' , '.a' , '.lib' ]):
64+ continue
9865
99- key = ( base_name , lib_type )
66+ base_name = file . split ( '.' )[ 0 ]
10067
101- if key not in lib_files :
102- lib_files [key ] = file_path
103- if verbose :
104- print (f"Keeping library: { file } " )
105- else :
106- # Remove duplicate
107- if verbose :
108- print (f"Removing duplicate library: { file } " )
109- os .remove (file_path )
68+ if '.dylib' in file : lib_type = 'dylib'
69+ elif '.dll' in file : lib_type = 'dll'
70+ elif '.so' in file : lib_type = 'so'
71+ elif '.a' in file : lib_type = 'static'
72+ elif '.lib' in file : lib_type = 'lib'
73+ else : continue
74+
75+ key = (base_name , lib_type )
76+ if key not in lib_files :
77+ lib_files [key ] = file_path
78+ else :
79+ os .remove (file_path )
11080
11181
112- def make_archive (file , directory , verbose = False ):
82+ def make_archive (file , directory ):
11383 archived_files = []
11484 for dirname , _ , files in os .walk (directory ):
11585 for filename in files :
@@ -127,20 +97,16 @@ def make_archive(file, directory, verbose=False):
12797 with open (path , "rb" ) as fp :
12898 zf .writestr (zip_info , fp .read (), compress_type = zipfile .ZIP_DEFLATED , compresslevel = 9 )
12999
130- if verbose :
131- print (f"Added to zip: { archive_path } " )
132-
133100
134101if __name__ == "__main__" :
135- print (f"starting python standard lib archiving tool..." )
102+ print (f"-- YUP -- Starting python standard lib archiving tool..." )
136103
137104 parser = ArgumentParser ()
138105 parser .add_argument ("-r" , "--root-folder" , type = Path , help = "Path to the python base folder." )
139106 parser .add_argument ("-o" , "--output-folder" , type = Path , help = "Path to the output folder." )
140107 parser .add_argument ("-M" , "--version-major" , type = int , help = "Major version number (integer)." )
141108 parser .add_argument ("-m" , "--version-minor" , type = int , help = "Minor version number (integer)." )
142109 parser .add_argument ("-x" , "--exclude-patterns" , type = str , default = None , help = "Excluded patterns (semicolon separated list)." )
143- parser .add_argument ("-v" , "--verbose" , action = "store_true" , help = "Enable verbose output." )
144110
145111 args = parser .parse_args ()
146112
@@ -180,7 +146,7 @@ def make_archive(file, directory, verbose=False):
180146 custom_patterns = [x .strip () for x in args .exclude_patterns .replace ('"' , '' ).split (";" )]
181147 base_patterns += custom_patterns
182148
183- print (f"cleaning up { final_location } ..." )
149+ print (f"-- YUP -- Cleaning up { final_location } ..." )
184150 if final_location .exists ():
185151 shutil .rmtree (final_location )
186152
@@ -196,34 +162,32 @@ def make_archive(file, directory, verbose=False):
196162 python_lib_src = lib_src / python_folder_name
197163 if python_lib_src .exists ():
198164 python_lib_dst = lib_dst / python_folder_name
199- print (f"copying library from { python_lib_src } to { python_lib_dst } ..." )
200- copy_filtered_tree (python_lib_src , python_lib_dst , base_patterns , verbose = args . verbose )
165+ print (f"-- YUP -- Copying library from { python_lib_src } to { python_lib_dst } ..." )
166+ copy_filtered_tree (python_lib_src , python_lib_dst , base_patterns )
201167
202168 # Create site-packages directory
203169 site_packages = python_lib_dst / "site-packages"
204170 site_packages .mkdir (parents = True , exist_ok = True )
205171 else :
206- print (f"Warning: Python library path { python_lib_src } does not exist" )
172+ print (f"-- YUP -- Warning: Python library path { python_lib_src } does not exist" )
207173
208174 # Copy dynamic libraries from lib root (e.g., libpython3.13.dylib)
209- print (f"copying dynamic libraries from { lib_src } ..." )
175+ print (f"-- YUP -- Copying dynamic libraries from { lib_src } ..." )
210176 for item in lib_src .iterdir ():
211177 if item .is_file ():
212178 if any (ext in item .name for ext in ['.dylib' , '.dll' , '.so' , '.a' , '.lib' ]):
213179 if not should_exclude (str (item ), item .name , base_patterns ):
214180 shutil .copy2 (item , lib_dst / item .name )
215- if args .verbose :
216- print (f"Copied library: { item .name } " )
217181 else :
218- print (f"Warning: Library path { lib_src } does not exist" )
182+ print (f"-- YUP -- Warning: Library path { lib_src } does not exist" )
219183
220184 # Copy bin folder
221185 bin_src = base_python / "bin"
222186 if bin_src .exists ():
223187 bin_dst = final_location / "bin"
224188 bin_dst .mkdir (parents = True , exist_ok = True )
225189
226- print (f"copying binaries from { bin_src } to { bin_dst } ..." )
190+ print (f"-- YUP -- Copying binaries from { bin_src } to { bin_dst } ..." )
227191
228192 # Copy python executables and symlinks (deduplicate with set)
229193 executables = list (set ([
@@ -241,8 +205,6 @@ def make_archive(file, directory, verbose=False):
241205 if exe_path .exists ():
242206 # Skip if destination already exists
243207 if dst_path .exists ():
244- if args .verbose :
245- print (f"Skipping existing binary: { executable } " )
246208 continue
247209
248210 if exe_path .is_symlink ():
@@ -251,18 +213,16 @@ def make_archive(file, directory, verbose=False):
251213 os .symlink (link_target , dst_path )
252214 else :
253215 shutil .copy2 (exe_path , dst_path )
254- if args .verbose :
255- print (f"Copied binary: { executable } " )
256216 else :
257- print (f"Warning: Binary path { bin_src } does not exist" )
217+ print (f"-- YUP -- Warning: Binary path { bin_src } does not exist" )
258218
259219 # Copy include folder
260220 include_src = base_python / "include"
261221 if include_src .exists ():
262222 include_dst = final_location / "include"
263223 include_dst .mkdir (parents = True , exist_ok = True )
264224
265- print (f"copying include files from { include_src } to { include_dst } ..." )
225+ print (f"-- YUP -- Copying include files from { include_src } to { include_dst } ..." )
266226
267227 # Copy the python version include folder
268228 python_include_src = include_src / python_folder_name
@@ -276,33 +236,28 @@ def make_archive(file, directory, verbose=False):
276236 shutil .copytree (item , include_dst / item .name , dirs_exist_ok = True )
277237 else :
278238 shutil .copy2 (item , include_dst / item .name )
279-
280- if args .verbose :
281- print (f"Copied include files" )
282239 else :
283- print (f"Warning: Include path { include_src } does not exist" )
240+ print (f"-- YUP -- Warning: Include path { include_src } does not exist" )
284241
285242 # Clean up duplicate libraries
286- print (f"cleaning up duplicate libraries..." )
287- clean_duplicate_libraries (final_location , verbose = args . verbose )
243+ print (f"-- YUP -- Cleaning up duplicate libraries..." )
244+ clean_duplicate_libraries (final_location )
288245
289246 # Create archive from final_location contents (not including the python/ wrapper)
290- print (f"making archive { temp_archive } to { final_archive } ..." )
247+ print (f"-- YUP -- Making archive { temp_archive } to { final_archive } ..." )
291248 if os .path .exists (final_archive ):
292- make_archive (temp_archive , final_location , verbose = args . verbose )
249+ make_archive (temp_archive , final_location )
293250 if file_hash (temp_archive ) != file_hash (final_archive ):
294251 shutil .copy (temp_archive , final_archive )
295252 os .remove (temp_archive )
296- print (f" Archive updated" )
253+ print ("-- YUP -- Archive updated" )
297254 else :
298255 os .remove (temp_archive )
299- print (f" Archive unchanged" )
256+ print ("-- YUP -- Archive unchanged" )
300257 else :
301- make_archive (final_archive , final_location , verbose = args . verbose )
302- print (f" Archive created" )
258+ make_archive (final_archive , final_location )
259+ print ("-- YUP -- Archive created" )
303260
304261 # Clean up temporary directory
305- print (f"cleaning up { final_location } ..." )
262+ print (f"-- YUP -- Cleaning up { final_location } ..." )
306263 shutil .rmtree (final_location )
307-
308- print ("Done!" )
0 commit comments