Author: Antonio Cuni <anto.c...@gmail.com> Branch: app_main-refactor Changeset: r55506:54e164d970a6 Date: 2012-06-08 13:41 +0200 http://bitbucket.org/pypy/pypy/changeset/54e164d970a6/
Log: port the logic to find sys.executable from app_main to interp-level and test it thoughtfully. This is not yet complete, because os.path.abspath is not RPython on windows (but it is on posix) diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py --- a/pypy/module/sys/__init__.py +++ b/pypy/module/sys/__init__.py @@ -45,6 +45,7 @@ 'builtin_module_names' : 'space.w_None', 'pypy_getudir' : 'state.pypy_getudir', # not translated 'pypy_initial_path' : 'state.pypy_initial_path', + 'pypy_find_executable' : 'state.pypy_find_executable', '_getframe' : 'vm._getframe', '_current_frames' : 'currentframes._current_frames', diff --git a/pypy/module/sys/state.py b/pypy/module/sys/state.py --- a/pypy/module/sys/state.py +++ b/pypy/module/sys/state.py @@ -2,6 +2,7 @@ Implementation of interpreter-level 'sys' routines. """ import pypy +from pypy.rlib.objectmodel import we_are_translated from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import unwrap_spec @@ -115,3 +116,32 @@ (should be removed from interpleveldefs before translation)""" from pypy.tool.udir import udir return space.wrap(str(udir)) + + +IS_WINDOWS = 'nt' in sys.builtin_module_names + +def find_executable(executable): + if we_are_translated() and IS_WINDOWS and not executable.lower().endswith('.exe'): + executable += '.exe' + if os.sep in executable or (IS_WINDOWS and ':' in executable): + pass # the path is already more than just an executable name + else: + path = os.environ.get('PATH') + if path: + for dir in path.split(os.pathsep): + fn = os.path.join(dir, executable) + if os.path.isfile(fn): + executable = fn + break + executable = os.path.abspath(executable) + # + # 'sys.executable' should not end up being an non-existing file; + # just use '' in this case. (CPython issue #7774) + if not os.path.isfile(executable): + executable = '' + return executable + +@unwrap_spec(executable='str0') +def pypy_find_executable(space, executable): + executable = find_executable(executable) + return space.wrap() diff --git a/pypy/module/sys/test/test_initialpath.py b/pypy/module/sys/test/test_initialpath.py --- a/pypy/module/sys/test/test_initialpath.py +++ b/pypy/module/sys/test/test_initialpath.py @@ -1,5 +1,6 @@ import py -from pypy.module.sys.state import getinitialpath +import os.path +from pypy.module.sys.state import getinitialpath, find_executable from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION def build_hierarchy(prefix): @@ -20,3 +21,47 @@ lib_tk = lib_python.join('lib-tk') path = getinitialpath(None, str(tmpdir)) assert lib_tk in path + + +def test_find_executable(tmpdir, monkeypatch): + from pypy.module.sys import state + # /tmp/a/pypy + # /tmp/b/pypy + # /tmp/c + a = tmpdir.join('a').ensure(dir=True) + b = tmpdir.join('b').ensure(dir=True) + c = tmpdir.join('c').ensure(dir=True) + a.join('pypy').ensure(file=True) + b.join('pypy').ensure(file=True) + # + # if there is already a slash, don't do anything + monkeypatch.chdir(tmpdir) + assert find_executable('a/pypy') == a.join('pypy') + # + # if path is None, try abspath (if the file exists) + monkeypatch.setenv('PATH', None) + monkeypatch.chdir(a) + assert find_executable('pypy') == a.join('pypy') + monkeypatch.chdir(tmpdir) # no pypy there + assert find_executable('pypy') == '' + # + # find it in path + monkeypatch.setenv('PATH', str(a)) + assert find_executable('pypy') == a.join('pypy') + # + # find it in the first dir in path + monkeypatch.setenv('PATH', '%s%s%s' % (b, os.pathsep, a)) + assert find_executable('pypy') == b.join('pypy') + # + # find it in the second, because in the first it's not there + monkeypatch.setenv('PATH', '%s%s%s' % (c, os.pathsep, a)) + assert find_executable('pypy') == a.join('pypy') + # if pypy is found but it's not a file, ignore it + c.join('pypy').ensure(dir=True) + assert find_executable('pypy') == a.join('pypy') + # + monkeypatch.setattr(state, 'we_are_translated', lambda: True) + monkeypatch.setattr(state, 'IS_WINDOWS', True) + monkeypatch.setenv('PATH', str(a)) + a.join('pypy.exe').ensure(file=True) + assert find_executable('pypy') == a.join('pypy.exe') _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit