[pypy-commit] pypy py3.5: find and follow 'pyvenv.cfg' files, hopefully like CPython does
arigo
pypy.commits at gmail.com
Wed Mar 8 11:11:50 EST 2017
Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r90598:d129aab5df7d
Date: 2017-03-08 17:11 +0100
http://bitbucket.org/pypy/pypy/changeset/d129aab5df7d/
Log: find and follow 'pyvenv.cfg' files, hopefully like CPython does
diff --git a/lib-python/3/venv/__init__.py b/lib-python/3/venv/__init__.py
--- a/lib-python/3/venv/__init__.py
+++ b/lib-python/3/venv/__init__.py
@@ -119,6 +119,14 @@
executable = os.environ['__PYVENV_LAUNCHER__']
else:
executable = sys.executable
+ #
+ # PyPy extension: resolve 'executable' if it is a symlink
+ try:
+ executable = os.path.join(os.path.dirname(executable),
+ os.readlink(executable))
+ except OSError:
+ pass
+ #
dirname, exename = os.path.split(os.path.abspath(executable))
context.executable = executable
context.python_dir = dirname
@@ -217,6 +225,7 @@
copier(context.env_exe, path, relative_symlinks_ok=True)
if not os.path.islink(path):
os.chmod(path, 0o755)
+ #
# PyPy extension: also copy the main library, not just the
# small executable
for libname in ['libpypy-c.so', 'libpypy-c.dylib']:
@@ -228,6 +237,7 @@
copier(src_library, dest_library)
if not os.path.islink(dest_library):
os.chmod(dest_library, 0o755)
+ #
else:
subdir = 'DLLs'
include = self.include_binary
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
@@ -73,18 +73,57 @@
return dirname
+def find_pyvenv_cfg(dirname):
+ try:
+ fd = os.open(os.path.join(dirname, 'pyvenv.cfg'), os.O_RDONLY)
+ try:
+ content = os.read(fd, 16384)
+ finally:
+ os.close(fd)
+ except OSError:
+ return ''
+ # painfully parse the file for a line 'home = PATH'
+ for line in content.splitlines():
+ line += '\n'
+ i = 0
+ while line[i] == ' ':
+ i += 1
+ if (line[i] == 'h' and
+ line[i+1] == 'o' and
+ line[i+2] == 'm' and
+ line[i+3] == 'e'):
+ i += 4
+ while line[i] == ' ':
+ i += 1
+ if line[i] == '=':
+ i += 1
+ return line[i:].strip()
+ return ''
+
+
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).
+
+ On PyPy3, it will also look for 'pyvenv.cfg' either in the same or
+ in the parent directory of 'executable', and search from the 'home'
+ entry instead of from the path to 'executable'.
"""
search = 'pypy-c' if executable == '' else executable
+ search_pyvenv_cfg = 2
while True:
dirname = resolvedirof(search)
if dirname == search:
return None, None # not found :-(
+ if search_pyvenv_cfg > 0:
+ search_pyvenv_cfg -= 1
+ home = find_pyvenv_cfg(dirname)
+ if home:
+ dirname = home
+ search_pyvenv_cfg = 0
newpath = compute_stdlib_path_maybe(state, dirname)
if newpath is not None:
return newpath, dirname
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
@@ -2,7 +2,8 @@
import os.path
from pypy.module.sys.initpath import (compute_stdlib_path, find_executable,
find_stdlib, resolvedirof,
- pypy_init_home, pypy_init_free)
+ pypy_init_home, pypy_init_free,
+ find_pyvenv_cfg)
from pypy.module.sys.version import PYPY_VERSION, CPYTHON_VERSION
from rpython.rtyper.lltypesystem import rffi
@@ -114,3 +115,26 @@
myfile2 = bar.join('myfile')
myfile2.mksymlinkto(myfile)
assert resolvedirof(str(myfile2)) == foo
+
+def test_find_pyvenv_cfg(tmpdir):
+ subdir = tmpdir.join('find_cfg').ensure(dir=True)
+ assert find_pyvenv_cfg(str(subdir)) == ''
+ subdir.join('pyvenv.cfg').write('foobar')
+ assert find_pyvenv_cfg(str(subdir)) == ''
+ subdir.join('pyvenv.cfg').write('foobar\nhome=xyz')
+ assert find_pyvenv_cfg(str(subdir)) == 'xyz'
+ subdir.join('pyvenv.cfg').write('foohome=xyz')
+ assert find_pyvenv_cfg(str(subdir)) == ''
+ subdir.join('pyvenv.cfg').write('home = xyx \nbar = baz\n')
+ assert find_pyvenv_cfg(str(subdir)) == 'xyx'
+
+def test_find_stdlib_follow_pyvenv_cfg(tmpdir):
+ mydir = tmpdir.join('follow_pyvenv_cfg').ensure(dir=True)
+ otherdir = tmpdir.join('otherdir').ensure(dir=True)
+ bin_dir = mydir.join('bin').ensure(dir=True)
+ pypy = bin_dir.join('pypy').ensure(file=True)
+ build_hierarchy(otherdir)
+ for homedir in [otherdir, otherdir.join('bin')]:
+ mydir.join('pyvenv.cfg').write('home = %s\n' % (homedir,))
+ _, prefix = find_stdlib(None, str(pypy))
+ assert prefix == otherdir
More information about the pypy-commit
mailing list