[pypy-commit] pypy app_main-refactor: copy the logic to find the stdlib from app_main into sys.initpath, and make it rpython. Also, add tests for it, which is always good :-)
antocuni
noreply at buildbot.pypy.org
Fri Jun 8 17:33:14 CEST 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: app_main-refactor
Changeset: r55509:203459fe802c
Date: 2012-06-08 16:11 +0200
http://bitbucket.org/pypy/pypy/changeset/203459fe802c/
Log: copy the logic to find the stdlib from app_main into sys.initpath,
and make it rpython. Also, add tests for it, which is always good
:-)
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
@@ -44,7 +44,7 @@
'warnoptions' : 'state.get(space).w_warnoptions',
'builtin_module_names' : 'space.w_None',
'pypy_getudir' : 'state.pypy_getudir', # not translated
- 'pypy_initial_path' : 'initpath.pypy_initial_path',
+ 'pypy_find_stdlib' : 'initpath.pypy_find_stdlib',
'pypy_find_executable' : 'initpath.pypy_find_executable',
'_getframe' : 'vm._getframe',
diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py
--- a/pypy/module/sys/initpath.py
+++ b/pypy/module/sys/initpath.py
@@ -9,11 +9,16 @@
from pypy.rlib import rpath
from pypy.rlib.objectmodel import we_are_translated
from pypy.interpreter.gateway import unwrap_spec
+from pypy.module.sys.state import get_state
platform = sys.platform
IS_WINDOWS = sys.platform == 'win32'
def find_executable(executable):
+ """
+ Return the absolute path of the executable, by looking into PATH and the
+ current directory. If it cannot be found, return ''.
+ """
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):
@@ -35,15 +40,57 @@
return executable
+def readlink_maybe(filename):
+ if hasattr(os, 'readlink'):
+ return os.readlink(filename)
+ raise NotImplementedError
+
+def resolvedirof(filename):
+ try:
+ filename = rpath.rabspath(filename)
+ except OSError:
+ pass
+ dirname = rpath.rabspath(os.path.join(filename, '..'))
+ if os.path.islink(filename):
+ try:
+ link = readlink_maybe(filename)
+ except OSError:
+ pass
+ else:
+ return resolvedirof(os.path.join(dirname, link))
+ return dirname
+
+def find_stdlib(state, executable):
+ """
+ Find and compute the stdlib path, starting from the directory where
+ ``executable`` is and going one level up until we find it. Return a tuple
+ (path, prefix), where ``prefix`` is the root directory which contains the
+ stdlib.
+ If it cannot be found, return (None, None).
+ """
+ search = executable
+ while True:
+ dirname = resolvedirof(search)
+ if dirname == search:
+ return None, None # not found :-(
+ newpath = compute_stdlib_path_maybe(state, dirname)
+ if newpath is not None:
+ return newpath, dirname
+ search = dirname # walk to the parent directory
+
+
def checkdir(path):
st = os.stat(path)
if not stat.S_ISDIR(st[0]):
raise OSError(errno.ENOTDIR, path)
-
-
def compute_stdlib_path(state, prefix):
+ """
+ Compute the paths for the stdlib rooted at ``prefix``. ``prefix`` must at
+ least contain a directory called ``lib-python/X.Y`` and another one called
+ ``lib_pypy``. If they cannot be found, it raises OSError.
+ """
from pypy.module.sys.version import CPYTHON_VERSION
dirname = '%d.%d' % (CPYTHON_VERSION[0],
CPYTHON_VERSION[1])
@@ -77,23 +124,28 @@
#
return importlist
+def compute_stdlib_path_maybe(state, prefix):
+ """
+ Return the stdlib path rooted at ``prefix``, or None if it cannot be
+ found.
+ """
+ try:
+ return compute_stdlib_path(state, prefix)
+ except OSError:
+ return None
@unwrap_spec(executable='str0')
def pypy_find_executable(space, executable):
return space.wrap(find_executable(executable))
-
@unwrap_spec(srcdir='str0')
-def pypy_initial_path(space, srcdir):
- try:
- path = compute_stdlib_path(get(space), srcdir)
- except OSError:
+def pypy_find_stdlib(space, executable):
+ path, prefix = find_stdlib(get_state(space), executable)
+ if path is None:
return space.w_None
else:
space.setitem(space.sys.w_dict, space.wrap('prefix'),
- space.wrap(srcdir))
+ space.wrap(prefix))
space.setitem(space.sys.w_dict, space.wrap('exec_prefix'),
- space.wrap(srcdir))
+ space.wrap(prefix))
return space.newlist([space.wrap(p) for p in path])
-
-
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
@@ -3,7 +3,6 @@
"""
import os
import pypy
-from pypy.module.sys.initpath import compute_stdlib_path
# ____________________________________________________________
#
@@ -18,7 +17,8 @@
self.w_argv = space.newlist([])
self.setinitialpath(space)
- def setinitialpath(self, space):
+ def setinitialpath(self, space):
+ from pypy.module.sys.initpath import compute_stdlib_path
# Initialize the default path
pypydir = os.path.dirname(os.path.abspath(pypy.__file__))
srcdir = os.path.dirname(pypydir)
@@ -26,7 +26,7 @@
self.w_path = space.newlist([space.wrap(p) for p in path])
-def get(space):
+def get_state(space):
return space.fromcache(State)
class IOState:
diff --git a/pypy/module/sys/test/test_initpath.py b/pypy/module/sys/test/test_initpath.py
--- a/pypy/module/sys/test/test_initpath.py
+++ b/pypy/module/sys/test/test_initpath.py
@@ -1,6 +1,6 @@
import py
import os.path
-from pypy.module.sys.initpath import compute_stdlib_path, find_executable
+from pypy.module.sys.initpath import compute_stdlib_path, find_executable, find_stdlib
from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION
def build_hierarchy(prefix):
@@ -9,8 +9,25 @@
b = prefix.join('lib-python', dirname).ensure(dir=1)
return a, b
+def test_find_stdlib(tmpdir):
+ bin_dir = tmpdir.join('bin').ensure(dir=True)
+ pypy = bin_dir.join('pypy').ensure(file=True)
+ build_hierarchy(tmpdir)
+ path, prefix = find_stdlib(None, str(pypy))
+ assert prefix == tmpdir
-def test_stdlib_in_prefix(tmpdir):
+ at py.test.mark.skipif('not hasattr(os, "symlink")')
+def test_find_stdlib_follow_symlink(tmpdir):
+ pypydir = tmpdir.join('opt', 'pypy-xxx')
+ pypy = pypydir.join('bin', 'pypy').ensure(file=True)
+ build_hierarchy(pypydir)
+ pypy_sym = tmpdir.join('pypy_sym')
+ os.symlink(str(pypy), str(pypy_sym))
+ path, prefix = find_stdlib(None, str(pypy_sym))
+ assert prefix == pypydir
+
+
+def test_compute_stdlib_path(tmpdir):
dirs = build_hierarchy(tmpdir)
path = compute_stdlib_path(None, str(tmpdir))
# we get at least 'dirs', and maybe more (e.g. plat-linux2)
diff --git a/pypy/rlib/rpath.py b/pypy/rlib/rpath.py
--- a/pypy/rlib/rpath.py
+++ b/pypy/rlib/rpath.py
@@ -18,4 +18,3 @@
return path
else:
raise ImportError('Unsupported os: %s' % os.name)
-
More information about the pypy-commit
mailing list