comparison contrib/packaging/hgpackaging/py2exe.py @ 43076:2372284d9457

formatting: blacken the codebase This is using my patch to black (https://github.com/psf/black/pull/826) so we don't un-wrap collection literals. Done with: hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S # skip-blame mass-reformatting only # no-check-commit reformats foo_bar functions Differential Revision: https://phab.mercurial-scm.org/D6971
author Augie Fackler <augie@google.com>
date Sun, 06 Oct 2019 09:45:02 -0400
parents 399ed3e86a49
children d053d3f10b6a
comparison
equal deleted inserted replaced
43075:57875cf423c9 43076:2372284d9457
9 9
10 import os 10 import os
11 import pathlib 11 import pathlib
12 import subprocess 12 import subprocess
13 13
14 from .downloads import ( 14 from .downloads import download_entry
15 download_entry,
16 )
17 from .util import ( 15 from .util import (
18 extract_tar_to_directory, 16 extract_tar_to_directory,
19 extract_zip_to_directory, 17 extract_zip_to_directory,
20 python_exe_info, 18 python_exe_info,
21 ) 19 )
22 20
23 21
24 def build_py2exe(source_dir: pathlib.Path, build_dir: pathlib.Path, 22 def build_py2exe(
25 python_exe: pathlib.Path, build_name: str, 23 source_dir: pathlib.Path,
26 venv_requirements_txt: pathlib.Path, 24 build_dir: pathlib.Path,
27 extra_packages=None, extra_excludes=None, 25 python_exe: pathlib.Path,
28 extra_dll_excludes=None, 26 build_name: str,
29 extra_packages_script=None): 27 venv_requirements_txt: pathlib.Path,
28 extra_packages=None,
29 extra_excludes=None,
30 extra_dll_excludes=None,
31 extra_packages_script=None,
32 ):
30 """Build Mercurial with py2exe. 33 """Build Mercurial with py2exe.
31 34
32 Build files will be placed in ``build_dir``. 35 Build files will be placed in ``build_dir``.
33 36
34 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic 37 py2exe's setup.py doesn't use setuptools. It doesn't have modern logic
35 for finding the Python 2.7 toolchain. So, we require the environment 38 for finding the Python 2.7 toolchain. So, we require the environment
36 to already be configured with an active toolchain. 39 to already be configured with an active toolchain.
37 """ 40 """
38 if 'VCINSTALLDIR' not in os.environ: 41 if 'VCINSTALLDIR' not in os.environ:
39 raise Exception('not running from a Visual C++ build environment; ' 42 raise Exception(
40 'execute the "Visual C++ <version> Command Prompt" ' 43 'not running from a Visual C++ build environment; '
41 'application shortcut or a vcsvarsall.bat file') 44 'execute the "Visual C++ <version> Command Prompt" '
45 'application shortcut or a vcsvarsall.bat file'
46 )
42 47
43 # Identity x86/x64 and validate the environment matches the Python 48 # Identity x86/x64 and validate the environment matches the Python
44 # architecture. 49 # architecture.
45 vc_x64 = r'\x64' in os.environ['LIB'] 50 vc_x64 = r'\x64' in os.environ['LIB']
46 51
47 py_info = python_exe_info(python_exe) 52 py_info = python_exe_info(python_exe)
48 53
49 if vc_x64: 54 if vc_x64:
50 if py_info['arch'] != '64bit': 55 if py_info['arch'] != '64bit':
51 raise Exception('architecture mismatch: Visual C++ environment ' 56 raise Exception(
52 'is configured for 64-bit but Python is 32-bit') 57 'architecture mismatch: Visual C++ environment '
58 'is configured for 64-bit but Python is 32-bit'
59 )
53 else: 60 else:
54 if py_info['arch'] != '32bit': 61 if py_info['arch'] != '32bit':
55 raise Exception('architecture mismatch: Visual C++ environment ' 62 raise Exception(
56 'is configured for 32-bit but Python is 64-bit') 63 'architecture mismatch: Visual C++ environment '
64 'is configured for 32-bit but Python is 64-bit'
65 )
57 66
58 if py_info['py3']: 67 if py_info['py3']:
59 raise Exception('Only Python 2 is currently supported') 68 raise Exception('Only Python 2 is currently supported')
60 69
61 build_dir.mkdir(exist_ok=True) 70 build_dir.mkdir(exist_ok=True)
63 gettext_pkg, gettext_entry = download_entry('gettext', build_dir) 72 gettext_pkg, gettext_entry = download_entry('gettext', build_dir)
64 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0] 73 gettext_dep_pkg = download_entry('gettext-dep', build_dir)[0]
65 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir) 74 virtualenv_pkg, virtualenv_entry = download_entry('virtualenv', build_dir)
66 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir) 75 py2exe_pkg, py2exe_entry = download_entry('py2exe', build_dir)
67 76
68 venv_path = build_dir / ('venv-%s-%s' % (build_name, 77 venv_path = build_dir / (
69 'x64' if vc_x64 else 'x86')) 78 'venv-%s-%s' % (build_name, 'x64' if vc_x64 else 'x86')
79 )
70 80
71 gettext_root = build_dir / ( 81 gettext_root = build_dir / ('gettext-win-%s' % gettext_entry['version'])
72 'gettext-win-%s' % gettext_entry['version'])
73 82
74 if not gettext_root.exists(): 83 if not gettext_root.exists():
75 extract_zip_to_directory(gettext_pkg, gettext_root) 84 extract_zip_to_directory(gettext_pkg, gettext_root)
76 extract_zip_to_directory(gettext_dep_pkg, gettext_root) 85 extract_zip_to_directory(gettext_dep_pkg, gettext_root)
77 86
78 # This assumes Python 2. We don't need virtualenv on Python 3. 87 # This assumes Python 2. We don't need virtualenv on Python 3.
79 virtualenv_src_path = build_dir / ( 88 virtualenv_src_path = build_dir / (
80 'virtualenv-%s' % virtualenv_entry['version']) 89 'virtualenv-%s' % virtualenv_entry['version']
90 )
81 virtualenv_py = virtualenv_src_path / 'virtualenv.py' 91 virtualenv_py = virtualenv_src_path / 'virtualenv.py'
82 92
83 if not virtualenv_src_path.exists(): 93 if not virtualenv_src_path.exists():
84 extract_tar_to_directory(virtualenv_pkg, build_dir) 94 extract_tar_to_directory(virtualenv_pkg, build_dir)
85 95
89 extract_zip_to_directory(py2exe_pkg, build_dir) 99 extract_zip_to_directory(py2exe_pkg, build_dir)
90 100
91 if not venv_path.exists(): 101 if not venv_path.exists():
92 print('creating virtualenv with dependencies') 102 print('creating virtualenv with dependencies')
93 subprocess.run( 103 subprocess.run(
94 [str(python_exe), str(virtualenv_py), str(venv_path)], 104 [str(python_exe), str(virtualenv_py), str(venv_path)], check=True
95 check=True) 105 )
96 106
97 venv_python = venv_path / 'Scripts' / 'python.exe' 107 venv_python = venv_path / 'Scripts' / 'python.exe'
98 venv_pip = venv_path / 'Scripts' / 'pip.exe' 108 venv_pip = venv_path / 'Scripts' / 'pip.exe'
99 109
100 subprocess.run([str(venv_pip), 'install', '-r', str(venv_requirements_txt)], 110 subprocess.run(
101 check=True) 111 [str(venv_pip), 'install', '-r', str(venv_requirements_txt)], check=True
112 )
102 113
103 # Force distutils to use VC++ settings from environment, which was 114 # Force distutils to use VC++ settings from environment, which was
104 # validated above. 115 # validated above.
105 env = dict(os.environ) 116 env = dict(os.environ)
106 env['DISTUTILS_USE_SDK'] = '1' 117 env['DISTUTILS_USE_SDK'] = '1'
107 env['MSSdk'] = '1' 118 env['MSSdk'] = '1'
108 119
109 if extra_packages_script: 120 if extra_packages_script:
110 more_packages = set(subprocess.check_output( 121 more_packages = set(
111 extra_packages_script, 122 subprocess.check_output(extra_packages_script, cwd=build_dir)
112 cwd=build_dir).split(b'\0')[-1].strip().decode('utf-8').splitlines()) 123 .split(b'\0')[-1]
124 .strip()
125 .decode('utf-8')
126 .splitlines()
127 )
113 if more_packages: 128 if more_packages:
114 if not extra_packages: 129 if not extra_packages:
115 extra_packages = more_packages 130 extra_packages = more_packages
116 else: 131 else:
117 extra_packages |= more_packages 132 extra_packages |= more_packages
118 133
119 if extra_packages: 134 if extra_packages:
120 env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages)) 135 env['HG_PY2EXE_EXTRA_PACKAGES'] = ' '.join(sorted(extra_packages))
121 hgext3rd_extras = sorted( 136 hgext3rd_extras = sorted(
122 e for e in extra_packages if e.startswith('hgext3rd.')) 137 e for e in extra_packages if e.startswith('hgext3rd.')
138 )
123 if hgext3rd_extras: 139 if hgext3rd_extras:
124 env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras) 140 env['HG_PY2EXE_EXTRA_INSTALL_PACKAGES'] = ' '.join(hgext3rd_extras)
125 if extra_excludes: 141 if extra_excludes:
126 env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes)) 142 env['HG_PY2EXE_EXTRA_EXCLUDES'] = ' '.join(sorted(extra_excludes))
127 if extra_dll_excludes: 143 if extra_dll_excludes:
128 env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join( 144 env['HG_PY2EXE_EXTRA_DLL_EXCLUDES'] = ' '.join(
129 sorted(extra_dll_excludes)) 145 sorted(extra_dll_excludes)
146 )
130 147
131 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe' 148 py2exe_py_path = venv_path / 'Lib' / 'site-packages' / 'py2exe'
132 if not py2exe_py_path.exists(): 149 if not py2exe_py_path.exists():
133 print('building py2exe') 150 print('building py2exe')
134 subprocess.run([str(venv_python), 'setup.py', 'install'], 151 subprocess.run(
135 cwd=py2exe_source_path, 152 [str(venv_python), 'setup.py', 'install'],
136 env=env, 153 cwd=py2exe_source_path,
137 check=True) 154 env=env,
155 check=True,
156 )
138 157
139 # Register location of msgfmt and other binaries. 158 # Register location of msgfmt and other binaries.
140 env['PATH'] = '%s%s%s' % ( 159 env['PATH'] = '%s%s%s' % (
141 env['PATH'], os.pathsep, str(gettext_root / 'bin')) 160 env['PATH'],
161 os.pathsep,
162 str(gettext_root / 'bin'),
163 )
142 164
143 print('building Mercurial') 165 print('building Mercurial')
144 subprocess.run( 166 subprocess.run(
145 [str(venv_python), 'setup.py', 167 [str(venv_python), 'setup.py', 'py2exe', 'build_doc', '--html'],
146 'py2exe',
147 'build_doc', '--html'],
148 cwd=str(source_dir), 168 cwd=str(source_dir),
149 env=env, 169 env=env,
150 check=True) 170 check=True,
171 )