Commit 377e44cb authored by Kirill Smelkov's avatar Kirill Smelkov

gpython: Fix startup on Windows when installed by pip

On windows setuptools install gpython.exe and gpython-script.py while
pip/distlib install gpython.exe with gpython-script sometimes embedded
into gpython.exe itself with argv[0] pointing to 'gpython' without .exe
suffix. This leads to gpython startup failure:

    (1.wenv) Z:\home\kirr\src\tools\go\pygo-win\pygolang>gpython
    Traceback (most recent call last):
      File "C:\Program Files\Python310\lib\runpy.py", line 196, in _run_module_as_main
        return _run_code(code, main_globals, None,
      File "C:\Program Files\Python310\lib\runpy.py", line 86, in _run_code
        exec(code, run_globals)
      File "Z:\home\kirr\src\tools\go\pygo-win\1.wenv\Scripts\gpython.exe\__main__.py", line 7, in <module>
      File "Z:\home\kirr\src\tools\go\pygo-win\pygolang\gpython\__init__.py", line 437, in main
        pymain(argv, init)
      File "Z:\home\kirr\src\tools\go\pygo-win\pygolang\gpython\__init__.py", line 79, in pymain
        if not _is_buildout_script(exe):
      File "Z:\home\kirr\src\tools\go\pygo-win\pygolang\gpython\__init__.py", line 442, in _is_buildout_script
        with open(path, 'rb') as f:
    FileNotFoundError: [Errno 2] No such file or directory: 'Z:\\home\\kirr\\src\\tools\\go\\pygo-win\\1.wenv\\Scripts\\gpython'

    (1.wenv) Z:\home\kirr\src\tools\go\pygo-win\pygolang>dir ../1.wenv/scripts/gpython*

    Directory of Z:\home\kirr\src\tools\go\pygo-win\1.wenv\scripts

    26.04.2023     14:17       108,404  gpython.exe
           1 file                   108,404 bytes
           0 directories     88,508,866,560 bytes free

-> Adjust pymain to handle this case accordingly.
parent 2f632a3e
...@@ -50,19 +50,27 @@ _pyopt_long = ('version',) ...@@ -50,19 +50,27 @@ _pyopt_long = ('version',)
# init, if provided, is called after options are parsed, but before interpreter start. # init, if provided, is called after options are parsed, but before interpreter start.
def pymain(argv, init=None): def pymain(argv, init=None):
import sys import sys
from os.path import dirname, realpath import os
from os.path import dirname, realpath, splitext
# sys.executable # sys.executable
# on windows there are # on windows there are
# gpython-script.py
# gpython.exe # gpython.exe
# gpython-script.py
# gpython.manifest # gpython.manifest
# and argv[0] is gpython-script.py # with gpython-script.py sometimes embedded into gpython.exe (pip/distlib)
# and argv[0] is 'gpython-script.py' (setuptools) or 'gpython' (pip/distlib; note no .exe)
exe = realpath(argv[0]) exe = realpath(argv[0])
argv = argv[1:] argv = argv[1:]
if exe.endswith('-script.py'): if os.name == 'nt':
exe = exe[:-len('-script.py')] if exe.endswith('-script.py'):
exe = exe + '.exe' exe = exe[:-len('-script.py')] # gpython-script.py -> gpython.exe
exe = exe + '.exe'
else:
_, ext = splitext(exe) # gpython -> gpython.exe
if not ext:
exe += '.exe'
sys._gpy_underlying_executable = sys.executable sys._gpy_underlying_executable = sys.executable
sys.executable = exe sys.executable = exe
...@@ -70,20 +78,26 @@ def pymain(argv, init=None): ...@@ -70,20 +78,26 @@ def pymain(argv, init=None):
# `gpython file` will add path-to-file to sys.path[0] by itself, and # `gpython file` will add path-to-file to sys.path[0] by itself, and
# /path/to/gpython is unnecessary and would create difference in behaviour # /path/to/gpython is unnecessary and would create difference in behaviour
# in between gpython and python. # in between gpython and python.
#
# on windows when gpython.exe comes with embedded __main__.py, it is
# gpython.exe that is installed into sys.path[0] .
exedir = dirname(exe) exedir = dirname(exe)
if sys.path[0] == exedir: if sys.path[0] in (exedir, exe):
del sys.path[0] del sys.path[0]
else: else:
# buildout injects `sys.path[0:0] = eggs` into python scripts. # buildout injects `sys.path[0:0] = eggs` into python scripts.
# detect that and remove sys.path entry corresponding to exedir. # detect that and remove sys.path entry corresponding to exedir.
if not _is_buildout_script(exe): if not _is_buildout_script(exe):
raise RuntimeError('pymain: internal error: sys.path[0] was not set by underlying python to dirname(exe):' raise RuntimeError('pymain: internal error: sys.path[0] was not set by underlying python to dirname(exe) or exe:'
'\n\n\texe:\t%s\n\tsys.path[0]:\t%s' % (exe, sys.path[0])) '\n\n\texe:\t%s\n\tsys.path[0]:\t%s' % (exe, sys.path[0]))
else: else:
if exedir in sys.path: ok = False
sys.path.remove(exedir) for _ in (exedir, exe):
else: if _ in sys.path:
raise RuntimeError('pymain: internal error: sys.path does not contain dirname(exe):' sys.path.remove(_)
ok = True
if not ok:
raise RuntimeError('pymain: internal error: sys.path does not contain dirname(exe) or exe:'
'\n\n\texe:\t%s\n\tsys.path:\t%s' % (exe, sys.path)) '\n\n\texe:\t%s\n\tsys.path:\t%s' % (exe, sys.path))
...@@ -202,7 +216,6 @@ def pymain(argv, init=None): ...@@ -202,7 +216,6 @@ def pymain(argv, init=None):
# #
# python -O gpython file.py # python -O gpython file.py
if len(reexec_with) > 0: if len(reexec_with) > 0:
import os
argv = [sys._gpy_underlying_executable] + reexec_with + [sys.executable] + reexec_argv argv = [sys._gpy_underlying_executable] + reexec_with + [sys.executable] + reexec_argv
os.execv(argv[0], argv) os.execv(argv[0], argv)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment