forked from pypa/virtualenv
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Unit test 3 PyPy3Posix.sources() scenarios
1. Portable PyPy3.8 build, as downloaded from upstream. This should include the provided shared libraries, libpypy3-c.so has an rpath of $ORIGIN/../lib to point to them. 2. Debian's /usr/lib/pypy3 layout for PyPy3 < 3.8. This should include libpypy3-c.so. 3. Debian's /usr layout for PyPy3 > 3.8. This should exclude libpypy3-c.so, as it's on the standard linker search path. It should also not include anything else from /usr/lib. (See pypa#2309)
- Loading branch information
Showing
1 changed file
with
292 additions
and
0 deletions.
There are no files selected for viewing
292 changes: 292 additions & 0 deletions
292
tests/unit/create/via_global_ref/builtin/pypy/test_pypy3.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,292 @@ | ||
from virtualenv.create.via_global_ref.builtin.pypy.pypy3 import PyPy3Posix | ||
from virtualenv.create.via_global_ref.builtin.ref import ExePathRefToDest, PathRefToDest | ||
from virtualenv.discovery.py_info import PythonInfo | ||
from virtualenv.util.path import Path | ||
|
||
|
||
# As downloaded from https://www.pypy.org/download.html | ||
PORTABLE_PYPY38 = { | ||
"platform": "linux", | ||
"implementation": "PyPy", | ||
"pypy_version_info": [7, 3, 8, "final", 0], | ||
"version_info": { | ||
"major": 3, | ||
"minor": 8, | ||
"micro": 12, | ||
"releaselevel": "final", | ||
"serial": 0, | ||
}, | ||
"architecture": 64, | ||
"version": "3.8.12 (d00b0afd2a5dd3c13fcda75d738262c864c62fa7, Feb 18 2022, 09:52:33)\n" | ||
"[PyPy 7.3.8 with GCC 10.2.1 20210130 (Red Hat 10.2.1-11)]", | ||
"os": "posix", | ||
"prefix": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"base_prefix": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"real_prefix": None, | ||
"base_exec_prefix": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"exec_prefix": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"executable": "/tmp/pypy3.8-v7.3.8-linux64/bin/pypy", | ||
"original_executable": "/tmp/pypy3.8-v7.3.8-linux64/bin/pypy", | ||
"system_executable": "/tmp/pypy3.8-v7.3.8-linux64/bin/pypy", | ||
"has_venv": True, | ||
"path": [ | ||
"/tmp/pypy3.8-v7.3.8-linux64/lib/pypy3.8", | ||
"/tmp/pypy3.8-v7.3.8-linux64/lib/pypy3.8/site-packages", | ||
], | ||
"file_system_encoding": "utf-8", | ||
"stdout_encoding": "UTF-8", | ||
"sysconfig_scheme": None, | ||
"sysconfig_paths": { | ||
"stdlib": "{installed_base}/lib/{implementation_lower}{py_version_short}", | ||
"platstdlib": "{platbase}/lib/{implementation_lower}{py_version_short}", | ||
"purelib": "{base}/lib/{implementation_lower}{py_version_short}/site-packages", | ||
"platlib": "{platbase}/lib/{implementation_lower}{py_version_short}/site-packages", | ||
"include": "{installed_base}/include/{implementation_lower}{py_version_short}{abiflags}", | ||
"scripts": "{base}/bin", | ||
"data": "{base}", | ||
}, | ||
"distutils_install": { | ||
"purelib": "lib/pypy3.8/site-packages", | ||
"platlib": "lib/pypy3.8/site-packages", | ||
"headers": "include/pypy3.8/UNKNOWN", | ||
"scripts": "bin", | ||
"data": "", | ||
}, | ||
"sysconfig": { | ||
"makefile_filename": "/tmp/pypy3.8-v7.3.8-linux64/lib/pypy3.8/config-3.8-x86_64-linux-gnu/Makefile", | ||
}, | ||
"sysconfig_vars": { | ||
"installed_base": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"implementation_lower": "pypy", | ||
"py_version_short": "3.8", | ||
"platbase": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"base": "/tmp/pypy3.8-v7.3.8-linux64", | ||
"abiflags": "", | ||
"PYTHONFRAMEWORK": "", | ||
}, | ||
"system_stdlib": "/tmp/pypy3.8-v7.3.8-linux64/lib/pypy3.8", | ||
"system_stdlib_platform": "/tmp/pypy3.8-v7.3.8-linux64/lib/pypy3.8", | ||
"max_size": 9223372036854775807, | ||
"_creators": None, | ||
} | ||
|
||
# Debian's pypy3 layout, installed to /usr, before 3.8 allowed a /usr prefix | ||
DEB_PYPY37 = { | ||
"platform": "linux", | ||
"implementation": "PyPy", | ||
"pypy_version_info": [7, 3, 7, "final", 0], | ||
"version_info": { | ||
"major": 3, | ||
"minor": 7, | ||
"micro": 12, | ||
"releaselevel": "final", | ||
"serial": 0, | ||
}, | ||
"architecture": 64, | ||
"version": "3.7.12 (7.3.7+dfsg-5, Jan 27 2022, 12:27:44)\n[PyPy 7.3.7 with GCC 11.2.0]", | ||
"os": "posix", | ||
"prefix": "/usr/lib/pypy3", | ||
"base_prefix": "/usr/lib/pypy3", | ||
"real_prefix": None, | ||
"base_exec_prefix": "/usr/lib/pypy3", | ||
"exec_prefix": "/usr/lib/pypy3", | ||
"executable": "/usr/bin/pypy3", | ||
"original_executable": "/usr/bin/pypy3", | ||
"system_executable": "/usr/bin/pypy3", | ||
"has_venv": True, | ||
"path": [ | ||
"/usr/lib/pypy3/lib_pypy/__extensions__", | ||
"/usr/lib/pypy3/lib_pypy", | ||
"/usr/lib/pypy3/lib-python/3", | ||
"/usr/lib/pypy3/lib-python/3/lib-tk", | ||
"/usr/lib/pypy3/lib-python/3/plat-linux2", | ||
"/usr/local/lib/pypy3.7/dist-packages", | ||
"/usr/lib/python3/dist-packages", | ||
], | ||
"file_system_encoding": "utf-8", | ||
"stdout_encoding": "UTF-8", | ||
"sysconfig_scheme": None, | ||
"sysconfig_paths": { | ||
"stdlib": "{base}/lib-python/{py_version_short}", | ||
"platstdlib": "{base}/lib-python/{py_version_short}", | ||
"purelib": "{base}/../../local/lib/pypy{py_version_short}/lib-python", | ||
"platlib": "{base}/../../local/lib/pypy{py_version_short}/lib-python", | ||
"include": "{base}/include", | ||
"scripts": "{base}/../../local/bin", | ||
"data": "{base}/../../local", | ||
}, | ||
"distutils_install": { | ||
"purelib": "site-packages", | ||
"platlib": "site-packages", | ||
"headers": "include/UNKNOWN", | ||
"scripts": "bin", | ||
"data": "", | ||
}, | ||
"sysconfig": { | ||
"makefile_filename": "/usr/lib/pypy3/lib-python/3.7/config-3.7-x86_64-linux-gnu/Makefile", | ||
}, | ||
"sysconfig_vars": { | ||
"base": "/usr/lib/pypy3", | ||
"py_version_short": "3.7", | ||
"PYTHONFRAMEWORK": "", | ||
}, | ||
"system_stdlib": "/usr/lib/pypy3/lib-python/3.7", | ||
"system_stdlib_platform": "/usr/lib/pypy3/lib-python/3.7", | ||
"max_size": 9223372036854775807, | ||
"_creators": None, | ||
} | ||
|
||
# Debian's pypy3 >= 3.8, with a /usr prefix | ||
DEB_PYPY38 = { | ||
"platform": "linux", | ||
"implementation": "PyPy", | ||
"pypy_version_info": [7, 3, 8, "final", 0], | ||
"version_info": { | ||
"major": 3, | ||
"minor": 8, | ||
"micro": 12, | ||
"releaselevel": "final", | ||
"serial": 0, | ||
}, | ||
"architecture": 64, | ||
"version": "3.8.12 (7.3.8+dfsg-2, Mar 05 2022, 02:04:42)\n[PyPy 7.3.8 with GCC 11.2.0]", | ||
"os": "posix", | ||
"prefix": "/usr", | ||
"base_prefix": "/usr", | ||
"real_prefix": None, | ||
"base_exec_prefix": "/usr", | ||
"exec_prefix": "/usr", | ||
"executable": "/usr/bin/pypy3", | ||
"original_executable": "/usr/bin/pypy3", | ||
"system_executable": "/usr/bin/pypy3", | ||
"has_venv": True, | ||
"path": [ | ||
"/home/stefanor/git/upstream/virtualenv", | ||
"/usr/lib/pypy3.8", | ||
"/usr/local/lib/pypy3.8/dist-packages", | ||
"/usr/lib/python3/dist-packages", | ||
], | ||
"file_system_encoding": "utf-8", | ||
"stdout_encoding": "UTF-8", | ||
"sysconfig_scheme": None, | ||
"sysconfig_paths": { | ||
"stdlib": "{installed_base}/lib/{implementation_lower}{py_version_short}", | ||
"platstdlib": "{platbase}/lib/{implementation_lower}{py_version_short}", | ||
"purelib": "{base}/local/lib/{implementation_lower}{py_version_short}/dist-packages", | ||
"platlib": "{platbase}/local/lib/{implementation_lower}{py_version_short}/dist-packages", | ||
"include": "{installed_base}/local/include/{implementation_lower}{py_version_short}{abiflags}", | ||
"scripts": "{base}/local/bin", | ||
"data": "{base}", | ||
}, | ||
"distutils_install": { | ||
"purelib": "lib/pypy3.8/site-packages", | ||
"platlib": "lib/pypy3.8/site-packages", | ||
"headers": "include/pypy3.8/UNKNOWN", | ||
"scripts": "bin", | ||
"data": "", | ||
}, | ||
"sysconfig": { | ||
"makefile_filename": "/usr/lib/pypy3.8/config-3.8-x86_64-linux-gnu/Makefile", | ||
}, | ||
"sysconfig_vars": { | ||
"installed_base": "/usr", | ||
"implementation_lower": "pypy", | ||
"py_version_short": "3.8", | ||
"platbase": "/usr", | ||
"base": "/usr", | ||
"abiflags": "", | ||
"PYTHONFRAMEWORK": "", | ||
}, | ||
"system_stdlib": "/usr/lib/pypy3.8", | ||
"system_stdlib_platform": "/usr/lib/pypy3.8", | ||
"max_size": 9223372036854775807, | ||
"_creators": None, | ||
} | ||
|
||
|
||
def assert_contains_exe(sources, src): | ||
"""Assert that the one and only executeable in sources is src""" | ||
exes = [source for source in sources if isinstance(source, ExePathRefToDest)] | ||
assert len(exes) == 1 | ||
exe = exes[0] | ||
assert str(exe.src) == src | ||
|
||
|
||
def assert_contains_ref(sources, src): | ||
"""Assert that src appears in sources""" | ||
assert any(source for source in sources if isinstance(source, PathRefToDest) and str(source.src) == src) | ||
|
||
|
||
class FakePath(Path): | ||
""" | ||
A Path() fake that only knows about files in existing_paths and the | ||
directories that contain them. | ||
""" | ||
|
||
_flavour = Path('/')._flavour | ||
existing_paths = [] | ||
|
||
def exists(self): | ||
return str(self) in self.existing_paths or self.is_dir() | ||
|
||
def is_dir(self): | ||
prefix = str(self) + "/" | ||
return any(True for path in self.existing_paths if path.startswith(prefix)) | ||
|
||
def iterdir(self): | ||
prefix = str(self) + "/" | ||
for path in self.existing_paths: | ||
if path.startswith(prefix) and "/" not in path[len(prefix) :]: | ||
yield FakePath(path) | ||
|
||
def __truediv__(self, key): | ||
return FakePath(super().__truediv__(key)) | ||
|
||
|
||
def test_portable_pypy3_virtualenvs_get_their_libs(mocker): | ||
portable_pypy3 = PythonInfo._from_dict(PORTABLE_PYPY38) | ||
|
||
FakePath.existing_paths = [ | ||
"/tmp/pypy3.8-v7.3.8-linux64/lib/libgdbm.so.4", | ||
] | ||
mocker.patch("virtualenv.create.via_global_ref.builtin.pypy.pypy3.Path", FakePath) | ||
mocker.patch.object( | ||
PyPy3Posix, "_shared_libs", return_value=[Path("/tmp/pypy3.8-v7.3.8-linux64/bin/libpypy3-c.so")] | ||
) | ||
|
||
sources = list(PyPy3Posix.sources(interpreter=portable_pypy3)) | ||
assert_contains_exe(sources, "/tmp/pypy3.8-v7.3.8-linux64/bin/pypy") | ||
assert len(sources) > 2 | ||
assert_contains_ref(sources, "/tmp/pypy3.8-v7.3.8-linux64/bin/libpypy3-c.so") | ||
assert_contains_ref(sources, "/tmp/pypy3.8-v7.3.8-linux64/lib/libgdbm.so.4") | ||
|
||
|
||
def test_debian_pypy37_virtualenvs(mocker): | ||
deb_pypy3 = PythonInfo._from_dict(DEB_PYPY37) | ||
|
||
FakePath.existing_paths = [ | ||
"/usr/bin/pypy3", | ||
] | ||
mocker.patch("virtualenv.create.via_global_ref.builtin.pypy.pypy3.Path", FakePath) | ||
mocker.patch.object(PyPy3Posix, "_shared_libs", return_value=[Path("/usr/lib/pypy3/bin/libpypy3-c.so")]) | ||
|
||
sources = list(PyPy3Posix.sources(interpreter=deb_pypy3)) | ||
assert_contains_exe(sources, "/usr/bin/pypy3") | ||
assert_contains_ref(sources, "/usr/lib/pypy3/bin/libpypy3-c.so") | ||
assert len(sources) == 2 | ||
|
||
|
||
def test_debian_pypy38_virtualenvs_exclude_usr(mocker): | ||
deb_pypy3 = PythonInfo._from_dict(DEB_PYPY38) | ||
|
||
FakePath.existing_paths = [ | ||
"/usr/bin/pypy3", | ||
"/usr/lib/foo", | ||
] | ||
mocker.patch("virtualenv.create.via_global_ref.builtin.pypy.pypy3.Path", FakePath) | ||
# libpypy3-c.so lives on the ld search path | ||
mocker.patch.object(PyPy3Posix, "_shared_libs", return_value=[]) | ||
|
||
sources = list(PyPy3Posix.sources(interpreter=deb_pypy3)) | ||
assert_contains_exe(sources, "/usr/bin/pypy3") | ||
assert len(sources) == 1 |