Skip to content

Commit fbd5292

Browse files
committed
make an exe stub for windows
1 parent bc198b8 commit fbd5292

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
covdefaults
22
coverage
3+
distlib
34
pytest
45
pytest-env
56
re-assert

testing/zipapp/entry

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ def _ensure_cache(zipf: zipfile.ZipFile, cache_key: str) -> str:
3333
try:
3434
zipf.extractall(tmpdir)
3535
# zip doesn't maintain permissions
36-
_make_executable(os.path.join(tmpdir, 'fakepython'))
36+
_make_executable(os.path.join(tmpdir, 'python'))
37+
_make_executable(os.path.join(tmpdir, 'python.exe'))
3738
os.rename(tmpdir, cache_dest)
3839
except BaseException:
3940
shutil.rmtree(tmpdir)
@@ -49,8 +50,12 @@ def main() -> int:
4950

5051
cache_dest = _ensure_cache(zipf, cache_key)
5152

52-
fakepython = os.path.join(cache_dest, 'fakepython')
53-
cmd = (sys.executable, fakepython, '-mpre_commit', *sys.argv[1:])
53+
if sys.platform != 'win32':
54+
exe = os.path.join(cache_dest, 'python')
55+
else:
56+
exe = os.path.join(cache_dest, 'python.exe')
57+
58+
cmd = (exe, '-mpre_commit', *sys.argv[1:])
5459
if sys.platform == 'win32': # https://bugs.python.org/issue19124
5560
import subprocess
5661

testing/zipapp/make

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import argparse
33
import base64
44
import hashlib
5+
import importlib.resources
6+
import io
57
import os.path
68
import shutil
79
import subprocess
@@ -30,11 +32,25 @@ def _check_no_shared_objects(wheeldir: str) -> None:
3032
raise AssertionError(zip_filename, filename)
3133

3234

35+
def _add_shim(dest: str) -> None:
36+
shim = os.path.join(HERE, 'python')
37+
shutil.copy(shim, dest)
38+
39+
bio = io.BytesIO()
40+
with zipfile.ZipFile(bio, 'w') as zipf:
41+
zipf.write(shim, arcname='__main__.py')
42+
43+
with open(os.path.join(dest, 'python.exe'), 'wb') as f:
44+
f.write(importlib.resources.read_binary('distlib', 't32.exe'))
45+
f.write(b'#!py.exe -3\n')
46+
f.write(bio.getvalue())
47+
48+
3349
def _write_cache_key(version: str, wheeldir: str, dest: str) -> None:
3450
cache_hash = hashlib.sha256(f'{version}\n'.encode())
3551
for filename in sorted(os.listdir(wheeldir)):
3652
cache_hash.update(f'{filename}\n'.encode())
37-
with open(os.path.join(HERE, 'fakepython'), 'rb') as f:
53+
with open(os.path.join(HERE, 'python'), 'rb') as f:
3854
cache_hash.update(f.read())
3955
with open(os.path.join(dest, 'CACHE_KEY'), 'wb') as f:
4056
f.write(base64.urlsafe_b64encode(cache_hash.digest()).rstrip(b'='))
@@ -62,11 +78,13 @@ def main() -> int:
6278
_msg('validating wheels...')
6379
_check_no_shared_objects(wheeldir)
6480

65-
_msg('adding fakepython / __main__.py...')
66-
shutil.copy(os.path.join(HERE, 'fakepython'), tmpdir)
81+
_msg('adding __main__.py...')
6782
mainfile = os.path.join(tmpdir, '__main__.py')
6883
shutil.copy(os.path.join(HERE, 'entry'), mainfile)
6984

85+
_msg('adding shim...')
86+
_add_shim(tmpdir)
87+
7088
_msg('copying file_lock.py...')
7189
file_lock_py = os.path.join(HERE, '../../pre_commit/file_lock.py')
7290
file_lock_py_dest = os.path.join(tmpdir, 'pre_commit/file_lock.py')
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import os.path
55
import runpy
66
import sys
77

8-
HERE = os.path.dirname(os.path.realpath(__file__))
8+
# an exe-zipapp will have a __file__ of shim.exe/__main__.py
9+
EXE = __file__ if os.path.isfile(__file__) else os.path.dirname(__file__)
10+
EXE = os.path.realpath(EXE)
11+
HERE = os.path.dirname(EXE)
912
WHEELDIR = os.path.join(HERE, 'wheels')
1013
SITE_DIRS = frozenset(('dist-packages', 'site-packages'))
1114

@@ -24,7 +27,7 @@ def main() -> int:
2427
for wheel in sorted(os.listdir(WHEELDIR)):
2528
sys.path.append(os.path.join(WHEELDIR, wheel))
2629
if args.m == 'pre_commit' or args.m.startswith('pre_commit.'):
27-
sys.executable = os.path.abspath(__file__)
30+
sys.executable = EXE
2831
sys.argv[1:] = rest
2932
runpy.run_module(args.m, run_name='__main__', alter_sys=True)
3033
return 0

0 commit comments

Comments
 (0)