| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | """
 | 
					
						
							|  |  |  | Generates a layout of Python for Windows from a build. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | See python make_layout.py --help for usage. | 
					
						
							|  |  |  | """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | __author__ = "Steve Dower <steve.dower@python.org>" | 
					
						
							|  |  |  | __version__ = "3.8" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import argparse | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import shutil | 
					
						
							|  |  |  | import sys | 
					
						
							|  |  |  | import tempfile | 
					
						
							|  |  |  | import zipfile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from pathlib import Path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     # Started directly, so enable relative imports | 
					
						
							|  |  |  |     __path__ = [str(Path(__file__).resolve().parent)] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | from .support.appxmanifest import * | 
					
						
							|  |  |  | from .support.catalog import * | 
					
						
							|  |  |  | from .support.constants import * | 
					
						
							|  |  |  | from .support.filesets import * | 
					
						
							|  |  |  | from .support.logging import * | 
					
						
							|  |  |  | from .support.options import * | 
					
						
							|  |  |  | from .support.pip import * | 
					
						
							|  |  |  | from .support.props import * | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  | from .support.nuspec import * | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-08 17:36:53 +01:00
										 |  |  | TEST_PYDS_ONLY = FileStemSet("xxlimited", "xxlimited_35", "_ctypes_test", "_test*") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | TEST_DIRS_ONLY = FileNameSet("test", "tests") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IDLE_DIRS_ONLY = FileNameSet("idlelib") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-26 20:47:24 +00:00
										 |  |  | TCLTK_PYDS_ONLY = FileStemSet("tcl*", "tk*", "_tkinter", "zlib1") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | TCLTK_DIRS_ONLY = FileNameSet("tkinter", "turtledemo") | 
					
						
							|  |  |  | TCLTK_FILES_ONLY = FileNameSet("turtle.py") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | VENV_DIRS_ONLY = FileNameSet("venv", "ensurepip") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  | EXCLUDE_FROM_DLLS = FileStemSet("python*", "pyshellext", "vcruntime*") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | EXCLUDE_FROM_LIB = FileNameSet("*.pyc", "__pycache__", "*.pickle") | 
					
						
							|  |  |  | EXCLUDE_FROM_PACKAGED_LIB = FileNameSet("readme.txt") | 
					
						
							|  |  |  | EXCLUDE_FROM_COMPILE = FileNameSet("badsyntax_*", "bad_*") | 
					
						
							|  |  |  | EXCLUDE_FROM_CATALOG = FileSuffixSet(".exe", ".pyd", ".dll") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-29 16:30:10 -07:00
										 |  |  | REQUIRED_DLLS = FileStemSet("libcrypto*", "libssl*", "libffi*") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | PY_FILES = FileSuffixSet(".py") | 
					
						
							|  |  |  | PYC_FILES = FileSuffixSet(".pyc") | 
					
						
							|  |  |  | CAT_FILES = FileSuffixSet(".cat") | 
					
						
							|  |  |  | CDF_FILES = FileSuffixSet(".cdf") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | DATA_DIRS = FileNameSet("data") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-03 17:09:02 +02:00
										 |  |  | TOOLS_DIRS = FileNameSet("scripts", "i18n", "parser") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | TOOLS_FILES = FileSuffixSet(".py", ".pyw", ".txt") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-12 09:55:57 -07:00
										 |  |  | def copy_if_modified(src, dest): | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         dest_stat = os.stat(dest) | 
					
						
							|  |  |  |     except FileNotFoundError: | 
					
						
							|  |  |  |         do_copy = True | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         src_stat = os.stat(src) | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |         do_copy = ( | 
					
						
							|  |  |  |             src_stat.st_mtime != dest_stat.st_mtime | 
					
						
							|  |  |  |             or src_stat.st_size != dest_stat.st_size | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2019-04-12 09:55:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if do_copy: | 
					
						
							| 
									
										
										
										
											2023-12-13 15:38:45 +00:00
										 |  |  |         try: | 
					
						
							|  |  |  |             shutil.copy2(src, dest) | 
					
						
							|  |  |  |         except FileNotFoundError: | 
					
						
							|  |  |  |             raise FileNotFoundError(src) from None | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | def get_lib_layout(ns): | 
					
						
							|  |  |  |     def _c(f): | 
					
						
							|  |  |  |         if f in EXCLUDE_FROM_LIB: | 
					
						
							|  |  |  |             return False | 
					
						
							|  |  |  |         if f.is_dir(): | 
					
						
							|  |  |  |             if f in TEST_DIRS_ONLY: | 
					
						
							|  |  |  |                 return ns.include_tests | 
					
						
							|  |  |  |             if f in TCLTK_DIRS_ONLY: | 
					
						
							|  |  |  |                 return ns.include_tcltk | 
					
						
							|  |  |  |             if f in IDLE_DIRS_ONLY: | 
					
						
							|  |  |  |                 return ns.include_idle | 
					
						
							|  |  |  |             if f in VENV_DIRS_ONLY: | 
					
						
							|  |  |  |                 return ns.include_venv | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if f in TCLTK_FILES_ONLY: | 
					
						
							|  |  |  |                 return ns.include_tcltk | 
					
						
							|  |  |  |         return True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for dest, src in rglob(ns.source / "Lib", "**/*", _c): | 
					
						
							|  |  |  |         yield dest, src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_tcltk_lib(ns): | 
					
						
							|  |  |  |     if not ns.include_tcltk: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tcl_lib = os.getenv("TCL_LIBRARY") | 
					
						
							|  |  |  |     if not tcl_lib or not os.path.isdir(tcl_lib): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             with open(ns.build / "TCL_LIBRARY.env", "r", encoding="utf-8-sig") as f: | 
					
						
							|  |  |  |                 tcl_lib = f.read().strip() | 
					
						
							|  |  |  |         except FileNotFoundError: | 
					
						
							|  |  |  |             pass | 
					
						
							|  |  |  |         if not tcl_lib or not os.path.isdir(tcl_lib): | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |             log_warning("Failed to find TCL_LIBRARY") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |             return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for dest, src in rglob(Path(tcl_lib).parent, "**/*"): | 
					
						
							|  |  |  |         yield "tcl/{}".format(dest), src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def get_layout(ns): | 
					
						
							|  |  |  |     def in_build(f, dest="", new_name=None): | 
					
						
							|  |  |  |         n, _, x = f.rpartition(".") | 
					
						
							|  |  |  |         n = new_name or n | 
					
						
							|  |  |  |         src = ns.build / f | 
					
						
							|  |  |  |         if ns.debug and src not in REQUIRED_DLLS: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |             if not "_d." in src.name: | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |                 src = src.parent / (src.stem + "_d" + src.suffix) | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |             if "_d." not in f: | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |                 n += "_d" | 
					
						
							|  |  |  |                 f = n + "." + x | 
					
						
							|  |  |  |         yield dest + n + "." + x, src | 
					
						
							|  |  |  |         if ns.include_symbols: | 
					
						
							|  |  |  |             pdb = src.with_suffix(".pdb") | 
					
						
							|  |  |  |             if pdb.is_file(): | 
					
						
							|  |  |  |                 yield dest + n + ".pdb", pdb | 
					
						
							|  |  |  |         if ns.include_dev: | 
					
						
							|  |  |  |             lib = src.with_suffix(".lib") | 
					
						
							|  |  |  |             if lib.is_file(): | 
					
						
							|  |  |  |                 yield "libs/" + n + ".lib", lib | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |     source = "python.exe" | 
					
						
							|  |  |  |     sourcew = "pythonw.exe" | 
					
						
							|  |  |  |     alias = [ | 
					
						
							|  |  |  |         "python", | 
					
						
							|  |  |  |         "python{}".format(VER_MAJOR) if ns.include_alias3 else "", | 
					
						
							|  |  |  |         "python{}".format(VER_DOT) if ns.include_alias3x else "", | 
					
						
							|  |  |  |     ] | 
					
						
							|  |  |  |     aliasw = [ | 
					
						
							|  |  |  |         "pythonw", | 
					
						
							|  |  |  |         "pythonw{}".format(VER_MAJOR) if ns.include_alias3 else "", | 
					
						
							|  |  |  |         "pythonw{}".format(VER_DOT) if ns.include_alias3x else "", | 
					
						
							|  |  |  |     ] | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     if ns.include_appxmanifest: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |         source = "python_uwp.exe" | 
					
						
							|  |  |  |         sourcew = "pythonw_uwp.exe" | 
					
						
							|  |  |  |     elif ns.include_freethreaded: | 
					
						
							|  |  |  |         source = "python{}t.exe".format(VER_DOT) | 
					
						
							|  |  |  |         sourcew = "pythonw{}t.exe".format(VER_DOT) | 
					
						
							|  |  |  |         if not ns.include_alias: | 
					
						
							|  |  |  |             alias = [] | 
					
						
							|  |  |  |             aliasw = [] | 
					
						
							|  |  |  |         alias.extend([ | 
					
						
							|  |  |  |             "python{}t".format(VER_DOT), | 
					
						
							|  |  |  |             "python{}t".format(VER_MAJOR) if ns.include_alias3 else None, | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  |         aliasw.extend([ | 
					
						
							|  |  |  |             "pythonw{}t".format(VER_DOT), | 
					
						
							|  |  |  |             "pythonw{}t".format(VER_MAJOR) if ns.include_alias3 else None, | 
					
						
							|  |  |  |         ]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for a in filter(None, alias): | 
					
						
							|  |  |  |         yield from in_build(source, new_name=a) | 
					
						
							|  |  |  |     for a in filter(None, aliasw): | 
					
						
							|  |  |  |         yield from in_build(sourcew, new_name=a) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_freethreaded: | 
					
						
							|  |  |  |         yield from in_build(FREETHREADED_PYTHON_DLL_NAME) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     else: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |         yield from in_build(PYTHON_DLL_NAME) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_launchers and ns.include_appxmanifest: | 
					
						
							|  |  |  |         if ns.include_pip: | 
					
						
							| 
									
										
										
										
											2019-08-07 10:49:40 -07:00
										 |  |  |             yield from in_build("python_uwp.exe", new_name="pip{}".format(VER_DOT)) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         if ns.include_idle: | 
					
						
							| 
									
										
										
										
											2019-08-07 10:49:40 -07:00
										 |  |  |             yield from in_build("pythonw_uwp.exe", new_name="idle{}".format(VER_DOT)) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_stable: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |         if ns.include_freethreaded: | 
					
						
							|  |  |  |             yield from in_build(FREETHREADED_PYTHON_STABLE_DLL_NAME) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             yield from in_build(PYTHON_STABLE_DLL_NAME) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-11 14:12:31 +00:00
										 |  |  |     found_any = False | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     for dest, src in rglob(ns.build, "vcruntime*.dll"): | 
					
						
							| 
									
										
										
										
											2020-03-11 14:12:31 +00:00
										 |  |  |         found_any = True | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         yield dest, src | 
					
						
							| 
									
										
										
										
											2020-03-11 14:12:31 +00:00
										 |  |  |     if not found_any: | 
					
						
							|  |  |  |         log_error("Failed to locate vcruntime DLL in the build.") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |     yield "LICENSE.txt", ns.build / "LICENSE.txt" | 
					
						
							| 
									
										
										
										
											2019-01-22 10:49:52 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |     for dest, src in rglob(ns.build, "*.pyd"): | 
					
						
							|  |  |  |         if ns.include_freethreaded: | 
					
						
							|  |  |  |             if not src.match("*.cp*t-win*.pyd"): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if bool(src.match("*_d.cp*.pyd")) != bool(ns.debug): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if src.match("*.cp*t-win*.pyd"): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             if bool(src.match("*_d.pyd")) != bool(ns.debug): | 
					
						
							|  |  |  |                 continue | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         if src in TEST_PYDS_ONLY and not ns.include_tests: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if src in TCLTK_PYDS_ONLY and not ns.include_tcltk: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |         yield from in_build(src.name, dest="" if ns.flat_dlls else "DLLs/") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |     for dest, src in rglob(ns.build, "*.dll"): | 
					
						
							|  |  |  |         if src.stem.endswith("_d") != bool(ns.debug) and src not in REQUIRED_DLLS: | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if src in EXCLUDE_FROM_DLLS: | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |         yield from in_build(src.name, dest="" if ns.flat_dlls else "DLLs/") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.zip_lib: | 
					
						
							|  |  |  |         zip_name = PYTHON_ZIP_NAME | 
					
						
							|  |  |  |         yield zip_name, ns.temp / zip_name | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         for dest, src in get_lib_layout(ns): | 
					
						
							|  |  |  |             yield "Lib/{}".format(dest), src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ns.include_venv: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |             if ns.include_freethreaded: | 
					
						
							|  |  |  |                 yield from in_build("venvlaunchert.exe", "Lib/venv/scripts/nt/") | 
					
						
							|  |  |  |                 yield from in_build("venvwlaunchert.exe", "Lib/venv/scripts/nt/") | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 yield from in_build("venvlauncher.exe", "Lib/venv/scripts/nt/") | 
					
						
							|  |  |  |                 yield from in_build("venvwlauncher.exe", "Lib/venv/scripts/nt/") | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_tools: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def _c(d): | 
					
						
							|  |  |  |             if d.is_dir(): | 
					
						
							|  |  |  |                 return d in TOOLS_DIRS | 
					
						
							|  |  |  |             return d in TOOLS_FILES | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for dest, src in rglob(ns.source / "Tools", "**/*", _c): | 
					
						
							|  |  |  |             yield "Tools/{}".format(dest), src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_underpth: | 
					
						
							|  |  |  |         yield PYTHON_PTH_NAME, ns.temp / PYTHON_PTH_NAME | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_dev: | 
					
						
							| 
									
										
										
										
											2019-10-28 11:03:27 -06:00
										 |  |  |         for dest, src in rglob(ns.source / "Include", "**/*.h"): | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |             yield "include/{}".format(dest), src | 
					
						
							| 
									
										
										
										
											2023-12-13 15:38:45 +00:00
										 |  |  |         yield "include/pyconfig.h", ns.build / "pyconfig.h" | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     for dest, src in get_tcltk_lib(ns): | 
					
						
							|  |  |  |         yield dest, src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_pip: | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |         for dest, src in get_pip_layout(ns): | 
					
						
							| 
									
										
										
										
											2019-07-24 15:13:22 -07:00
										 |  |  |             if not isinstance(src, tuple) and ( | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |                 src in EXCLUDE_FROM_LIB or src in EXCLUDE_FROM_PACKAGED_LIB | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  |             yield dest, src | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_chm: | 
					
						
							|  |  |  |         for dest, src in rglob(ns.doc_build / "htmlhelp", PYTHON_CHM_NAME): | 
					
						
							|  |  |  |             yield "Doc/{}".format(dest), src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_html_doc: | 
					
						
							|  |  |  |         for dest, src in rglob(ns.doc_build / "html", "**/*"): | 
					
						
							|  |  |  |             yield "Doc/html/{}".format(dest), src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_props: | 
					
						
							|  |  |  |         for dest, src in get_props_layout(ns): | 
					
						
							|  |  |  |             yield dest, src | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |     if ns.include_nuspec: | 
					
						
							|  |  |  |         for dest, src in get_nuspec_layout(ns): | 
					
						
							|  |  |  |             yield dest, src | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     for dest, src in get_appx_layout(ns): | 
					
						
							|  |  |  |         yield dest, src | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_cat: | 
					
						
							|  |  |  |         if ns.flat_dlls: | 
					
						
							|  |  |  |             yield ns.include_cat.name, ns.include_cat | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             yield "DLLs/{}".format(ns.include_cat.name), ns.include_cat | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 02:38:01 -08:00
										 |  |  | def _compile_one_py(src, dest, name, optimize, checked=True): | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     import py_compile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if dest is not None: | 
					
						
							|  |  |  |         dest = str(dest) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 02:38:01 -08:00
										 |  |  |     mode = ( | 
					
						
							|  |  |  |         py_compile.PycInvalidationMode.CHECKED_HASH | 
					
						
							|  |  |  |         if checked | 
					
						
							|  |  |  |         else py_compile.PycInvalidationMode.UNCHECKED_HASH | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     try: | 
					
						
							|  |  |  |         return Path( | 
					
						
							|  |  |  |             py_compile.compile( | 
					
						
							|  |  |  |                 str(src), | 
					
						
							|  |  |  |                 dest, | 
					
						
							|  |  |  |                 str(name), | 
					
						
							|  |  |  |                 doraise=True, | 
					
						
							|  |  |  |                 optimize=optimize, | 
					
						
							| 
									
										
										
										
											2019-01-08 02:38:01 -08:00
										 |  |  |                 invalidation_mode=mode, | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |             ) | 
					
						
							|  |  |  |         ) | 
					
						
							|  |  |  |     except py_compile.PyCompileError: | 
					
						
							|  |  |  |         log_warning("Failed to compile {}", src) | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 22:36:58 +01:00
										 |  |  | # name argument added to address bpo-37641 | 
					
						
							|  |  |  | def _py_temp_compile(src, name, ns, dest_dir=None, checked=True): | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     if not ns.precompile or src not in PY_FILES or src.parent in DATA_DIRS: | 
					
						
							|  |  |  |         return None | 
					
						
							| 
									
										
										
										
											2019-07-25 22:36:58 +01:00
										 |  |  |     dest = (dest_dir or ns.temp) / (src.stem + ".pyc") | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  |     return _compile_one_py(src, dest, name, optimize=2, checked=checked) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-08 02:38:01 -08:00
										 |  |  | def _write_to_zip(zf, dest, src, ns, checked=True): | 
					
						
							| 
									
										
										
										
											2019-07-25 22:36:58 +01:00
										 |  |  |     pyc = _py_temp_compile(src, dest, ns, checked=checked) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     if pyc: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             zf.write(str(pyc), dest.with_suffix(".pyc")) | 
					
						
							|  |  |  |         finally: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 pyc.unlink() | 
					
						
							|  |  |  |             except: | 
					
						
							|  |  |  |                 log_exception("Failed to delete {}", pyc) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     zf.write(str(src), str(dest)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def generate_source_files(ns): | 
					
						
							|  |  |  |     if ns.zip_lib: | 
					
						
							|  |  |  |         zip_name = PYTHON_ZIP_NAME | 
					
						
							|  |  |  |         zip_path = ns.temp / zip_name | 
					
						
							|  |  |  |         if zip_path.is_file(): | 
					
						
							|  |  |  |             zip_path.unlink() | 
					
						
							|  |  |  |         elif zip_path.is_dir(): | 
					
						
							|  |  |  |             log_error( | 
					
						
							|  |  |  |                 "Cannot create zip file because a directory exists by the same name" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         log_info("Generating {} in {}", zip_name, ns.temp) | 
					
						
							|  |  |  |         ns.temp.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |         with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zf: | 
					
						
							|  |  |  |             for dest, src in get_lib_layout(ns): | 
					
						
							| 
									
										
										
										
											2019-01-08 02:38:01 -08:00
										 |  |  |                 _write_to_zip(zf, dest, src, ns, checked=False) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_underpth: | 
					
						
							|  |  |  |         log_info("Generating {} in {}", PYTHON_PTH_NAME, ns.temp) | 
					
						
							|  |  |  |         ns.temp.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |         with open(ns.temp / PYTHON_PTH_NAME, "w", encoding="utf-8") as f: | 
					
						
							|  |  |  |             if ns.zip_lib: | 
					
						
							|  |  |  |                 print(PYTHON_ZIP_NAME, file=f) | 
					
						
							|  |  |  |                 if ns.include_pip: | 
					
						
							|  |  |  |                     print("packages", file=f) | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 print("Lib", file=f) | 
					
						
							|  |  |  |                 print("Lib/site-packages", file=f) | 
					
						
							|  |  |  |             if not ns.flat_dlls: | 
					
						
							|  |  |  |                 print("DLLs", file=f) | 
					
						
							|  |  |  |             print(".", file=f) | 
					
						
							|  |  |  |             print(file=f) | 
					
						
							|  |  |  |             print("# Uncomment to run site.main() automatically", file=f) | 
					
						
							|  |  |  |             print("#import site", file=f) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.include_pip: | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |         log_info("Extracting pip") | 
					
						
							|  |  |  |         extract_pip_files(ns) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _create_zip_file(ns): | 
					
						
							|  |  |  |     if not ns.zip: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if ns.zip.is_file(): | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             ns.zip.unlink() | 
					
						
							|  |  |  |         except OSError: | 
					
						
							|  |  |  |             log_exception("Unable to remove {}", ns.zip) | 
					
						
							|  |  |  |             sys.exit(8) | 
					
						
							|  |  |  |     elif ns.zip.is_dir(): | 
					
						
							|  |  |  |         log_error("Cannot create ZIP file because {} is a directory", ns.zip) | 
					
						
							|  |  |  |         sys.exit(8) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ns.zip.parent.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |     return zipfile.ZipFile(ns.zip, "w", zipfile.ZIP_DEFLATED) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def copy_files(files, ns): | 
					
						
							|  |  |  |     if ns.copy: | 
					
						
							|  |  |  |         ns.copy.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         total = len(files) | 
					
						
							|  |  |  |     except TypeError: | 
					
						
							|  |  |  |         total = None | 
					
						
							|  |  |  |     count = 0 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     zip_file = _create_zip_file(ns) | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         need_compile = [] | 
					
						
							|  |  |  |         in_catalog = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for dest, src in files: | 
					
						
							|  |  |  |             count += 1 | 
					
						
							|  |  |  |             if count % 10 == 0: | 
					
						
							|  |  |  |                 if total: | 
					
						
							|  |  |  |                     log_info("Processed {:>4} of {} files", count, total) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     log_info("Processed {} files", count) | 
					
						
							|  |  |  |             log_debug("Processing {!s}", src) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-14 08:29:20 -07:00
										 |  |  |             if isinstance(src, tuple): | 
					
						
							|  |  |  |                 src, content = src | 
					
						
							|  |  |  |                 if ns.copy: | 
					
						
							|  |  |  |                     log_debug("Copy {} -> {}", src, ns.copy / dest) | 
					
						
							|  |  |  |                     (ns.copy / dest).parent.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |                     with open(ns.copy / dest, "wb") as f: | 
					
						
							|  |  |  |                         f.write(content) | 
					
						
							|  |  |  |                 if ns.zip: | 
					
						
							|  |  |  |                     log_debug("Zip {} into {}", src, ns.zip) | 
					
						
							|  |  |  |                     zip_file.writestr(str(dest), content) | 
					
						
							|  |  |  |                 continue | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |             if ( | 
					
						
							|  |  |  |                 ns.precompile | 
					
						
							|  |  |  |                 and src in PY_FILES | 
					
						
							|  |  |  |                 and src not in EXCLUDE_FROM_COMPILE | 
					
						
							|  |  |  |                 and src.parent not in DATA_DIRS | 
					
						
							|  |  |  |                 and os.path.normcase(str(dest)).startswith(os.path.normcase("Lib")) | 
					
						
							|  |  |  |             ): | 
					
						
							|  |  |  |                 if ns.copy: | 
					
						
							|  |  |  |                     need_compile.append((dest, ns.copy / dest)) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     (ns.temp / "Lib" / dest).parent.mkdir(parents=True, exist_ok=True) | 
					
						
							| 
									
										
										
										
											2019-04-12 09:55:57 -07:00
										 |  |  |                     copy_if_modified(src, ns.temp / "Lib" / dest) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |                     need_compile.append((dest, ns.temp / "Lib" / dest)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if src not in EXCLUDE_FROM_CATALOG: | 
					
						
							|  |  |  |                 in_catalog.append((src.name, src)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ns.copy: | 
					
						
							|  |  |  |                 log_debug("Copy {} -> {}", src, ns.copy / dest) | 
					
						
							|  |  |  |                 (ns.copy / dest).parent.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |                 try: | 
					
						
							| 
									
										
										
										
											2019-04-12 09:55:57 -07:00
										 |  |  |                     copy_if_modified(src, ns.copy / dest) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |                 except shutil.SameFileError: | 
					
						
							|  |  |  |                     pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if ns.zip: | 
					
						
							|  |  |  |                 log_debug("Zip {} into {}", src, ns.zip) | 
					
						
							|  |  |  |                 zip_file.write(src, str(dest)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if need_compile: | 
					
						
							|  |  |  |             for dest, src in need_compile: | 
					
						
							|  |  |  |                 compiled = [ | 
					
						
							|  |  |  |                     _compile_one_py(src, None, dest, optimize=0), | 
					
						
							|  |  |  |                     _compile_one_py(src, None, dest, optimize=1), | 
					
						
							|  |  |  |                     _compile_one_py(src, None, dest, optimize=2), | 
					
						
							|  |  |  |                 ] | 
					
						
							|  |  |  |                 for c in compiled: | 
					
						
							|  |  |  |                     if not c: | 
					
						
							|  |  |  |                         continue | 
					
						
							|  |  |  |                     cdest = Path(dest).parent / Path(c).relative_to(src.parent) | 
					
						
							|  |  |  |                     if ns.zip: | 
					
						
							|  |  |  |                         log_debug("Zip {} into {}", c, ns.zip) | 
					
						
							|  |  |  |                         zip_file.write(c, str(cdest)) | 
					
						
							|  |  |  |                     in_catalog.append((cdest.name, cdest)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ns.catalog: | 
					
						
							|  |  |  |             # Just write out the CDF now. Compilation and signing is | 
					
						
							|  |  |  |             # an extra step | 
					
						
							|  |  |  |             log_info("Generating {}", ns.catalog) | 
					
						
							|  |  |  |             ns.catalog.parent.mkdir(parents=True, exist_ok=True) | 
					
						
							|  |  |  |             write_catalog(ns.catalog, in_catalog) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     finally: | 
					
						
							|  |  |  |         if zip_file: | 
					
						
							|  |  |  |             zip_file.close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							|  |  |  |     parser = argparse.ArgumentParser() | 
					
						
							|  |  |  |     parser.add_argument("-v", help="Increase verbosity", action="count") | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-s", | 
					
						
							|  |  |  |         "--source", | 
					
						
							|  |  |  |         metavar="dir", | 
					
						
							|  |  |  |         help="The directory containing the repository root", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-b", "--build", metavar="dir", help="Specify the build directory", type=Path | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--arch", | 
					
						
							|  |  |  |         metavar="architecture", | 
					
						
							|  |  |  |         help="Specify the target architecture", | 
					
						
							|  |  |  |         type=str, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--doc-build", | 
					
						
							|  |  |  |         metavar="dir", | 
					
						
							|  |  |  |         help="Specify the docs build directory", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--copy", | 
					
						
							|  |  |  |         metavar="directory", | 
					
						
							|  |  |  |         help="The name of the directory to copy an extracted layout to", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--zip", | 
					
						
							|  |  |  |         metavar="file", | 
					
						
							|  |  |  |         help="The ZIP file to write all files to", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--catalog", | 
					
						
							|  |  |  |         metavar="file", | 
					
						
							|  |  |  |         help="The CDF file to write catalog entries to", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--log", | 
					
						
							|  |  |  |         metavar="file", | 
					
						
							|  |  |  |         help="Write all operations to the specified file", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-t", | 
					
						
							|  |  |  |         "--temp", | 
					
						
							|  |  |  |         metavar="file", | 
					
						
							|  |  |  |         help="A temporary working directory", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-d", "--debug", help="Include debug build", action="store_true" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-p", | 
					
						
							|  |  |  |         "--precompile", | 
					
						
							|  |  |  |         help="Include .pyc files instead of .py", | 
					
						
							|  |  |  |         action="store_true", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-z", "--zip-lib", help="Include library in a ZIP file", action="store_true" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--flat-dlls", help="Does not create a DLLs directory", action="store_true" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "-a", | 
					
						
							|  |  |  |         "--include-all", | 
					
						
							|  |  |  |         help="Include all optional components", | 
					
						
							|  |  |  |         action="store_true", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--include-cat", | 
					
						
							|  |  |  |         metavar="file", | 
					
						
							|  |  |  |         help="Specify the catalog file to include", | 
					
						
							|  |  |  |         type=Path, | 
					
						
							|  |  |  |         default=None, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     for opt, help in get_argparse_options(): | 
					
						
							|  |  |  |         parser.add_argument(opt, help=help, action="store_true") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ns = parser.parse_args() | 
					
						
							|  |  |  |     update_presets(ns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ns.source = ns.source or (Path(__file__).resolve().parent.parent.parent) | 
					
						
							|  |  |  |     ns.build = ns.build or Path(sys.executable).parent | 
					
						
							|  |  |  |     ns.doc_build = ns.doc_build or (ns.source / "Doc" / "build") | 
					
						
							| 
									
										
										
										
											2024-05-13 04:30:16 -07:00
										 |  |  |     if ns.copy and not ns.copy.is_absolute(): | 
					
						
							|  |  |  |         ns.copy = (Path.cwd() / ns.copy).resolve() | 
					
						
							|  |  |  |     if not ns.temp: | 
					
						
							|  |  |  |         # Put temp on a Dev Drive for speed if we're copying to one. | 
					
						
							|  |  |  |         # If not, the regular temp dir will have to do. | 
					
						
							|  |  |  |         if ns.copy and getattr(os.path, "isdevdrive", lambda d: False)(ns.copy): | 
					
						
							|  |  |  |             ns.temp = ns.copy.with_name(ns.copy.name + "_temp") | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             ns.temp = Path(tempfile.mkdtemp()) | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     if not ns.source.is_absolute(): | 
					
						
							|  |  |  |         ns.source = (Path.cwd() / ns.source).resolve() | 
					
						
							|  |  |  |     if not ns.build.is_absolute(): | 
					
						
							|  |  |  |         ns.build = (Path.cwd() / ns.build).resolve() | 
					
						
							|  |  |  |     if not ns.temp.is_absolute(): | 
					
						
							|  |  |  |         ns.temp = (Path.cwd() / ns.temp).resolve() | 
					
						
							|  |  |  |     if not ns.doc_build.is_absolute(): | 
					
						
							|  |  |  |         ns.doc_build = (Path.cwd() / ns.doc_build).resolve() | 
					
						
							|  |  |  |     if ns.include_cat and not ns.include_cat.is_absolute(): | 
					
						
							|  |  |  |         ns.include_cat = (Path.cwd() / ns.include_cat).resolve() | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  |     if not ns.arch: | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |         if sys.winver.endswith("-arm64"): | 
					
						
							|  |  |  |             ns.arch = "arm64" | 
					
						
							|  |  |  |         elif sys.winver.endswith("-32"): | 
					
						
							|  |  |  |             ns.arch = "win32" | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             ns.arch = "amd64" | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if ns.zip and not ns.zip.is_absolute(): | 
					
						
							|  |  |  |         ns.zip = (Path.cwd() / ns.zip).resolve() | 
					
						
							|  |  |  |     if ns.catalog and not ns.catalog.is_absolute(): | 
					
						
							|  |  |  |         ns.catalog = (Path.cwd() / ns.catalog).resolve() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     configure_logger(ns) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     log_info( | 
					
						
							|  |  |  |         """OPTIONS
 | 
					
						
							|  |  |  | Source: {ns.source} | 
					
						
							|  |  |  | Build:  {ns.build} | 
					
						
							|  |  |  | Temp:   {ns.temp} | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  | Arch:   {ns.arch} | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Copy to: {ns.copy} | 
					
						
							|  |  |  | Zip to:  {ns.zip} | 
					
						
							|  |  |  | Catalog: {ns.catalog}""",
 | 
					
						
							|  |  |  |         ns=ns, | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-20 09:30:47 -08:00
										 |  |  |     if ns.arch not in ("win32", "amd64", "arm32", "arm64"): | 
					
						
							|  |  |  |         log_error("--arch is not a valid value (win32, amd64, arm32, arm64)") | 
					
						
							|  |  |  |         return 4 | 
					
						
							|  |  |  |     if ns.arch in ("arm32", "arm64"): | 
					
						
							|  |  |  |         for n in ("include_idle", "include_tcltk"): | 
					
						
							|  |  |  |             if getattr(ns, n): | 
					
						
							|  |  |  |                 log_warning(f"Disabling --{n.replace('_', '-')} on unsupported platform") | 
					
						
							|  |  |  |                 setattr(ns, n, False) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     if ns.include_idle and not ns.include_tcltk: | 
					
						
							|  |  |  |         log_warning("Assuming --include-tcltk to support --include-idle") | 
					
						
							|  |  |  |         ns.include_tcltk = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-17 21:52:23 +00:00
										 |  |  |     if not (ns.include_alias or ns.include_alias3 or ns.include_alias3x): | 
					
						
							|  |  |  |         if ns.include_freethreaded: | 
					
						
							|  |  |  |             ns.include_alias3x = True | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             ns.include_alias = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-10 18:52:57 -08:00
										 |  |  |     try: | 
					
						
							|  |  |  |         generate_source_files(ns) | 
					
						
							|  |  |  |         files = list(get_layout(ns)) | 
					
						
							|  |  |  |         copy_files(files, ns) | 
					
						
							|  |  |  |     except KeyboardInterrupt: | 
					
						
							|  |  |  |         log_info("Interrupted by Ctrl+C") | 
					
						
							|  |  |  |         return 3 | 
					
						
							|  |  |  |     except SystemExit: | 
					
						
							|  |  |  |         raise | 
					
						
							|  |  |  |     except: | 
					
						
							|  |  |  |         log_exception("Unhandled error") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if error_was_logged(): | 
					
						
							|  |  |  |         log_error("Errors occurred.") | 
					
						
							|  |  |  |         return 1 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  |     sys.exit(int(main() or 0)) |