[pypy-commit] pypy app_main-refactor: port the logic to find sys.executable from app_main to interp-level and test

antocuni noreply at buildbot.pypy.org
Fri Jun 8 17:33:11 CEST 2012


Author: Antonio Cuni <anto.cuni at 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
+
+ at 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')


More information about the pypy-commit mailing list