Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adapt virtualenv 20 API #7718

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 54 additions & 94 deletions tests/lib/venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import compileall
import shutil
import sys
import sysconfig
import textwrap

import six
Expand Down Expand Up @@ -32,16 +32,15 @@ def __init__(self, location, template=None, venv_type=None):
self._create()

def _update_paths(self):
home, lib, inc, bin = _virtualenv.path_locations(self.location)
self.bin = Path(bin)
self.site = Path(lib) / 'site-packages'
# Workaround for https://github.com/pypa/virtualenv/issues/306
if hasattr(sys, "pypy_version_info"):
version_fmt = '{0}' if six.PY3 else '{0}.{1}'
version_dir = version_fmt.format(*sys.version_info)
self.lib = Path(home, 'lib-python', version_dir)
else:
self.lib = Path(lib)
paths = sysconfig.get_paths(vars={
"installed_base": self.location,
"installed_platbase": self.location,
"base": self.location,
"platbase": self.location,
})
self.bin = Path(paths["scripts"])
self.site = Path(paths["purelib"])
self.lib = Path(paths["stdlib"])

def __repr__(self):
return "<VirtualEnvironment {}>".format(self.location)
Expand All @@ -50,10 +49,6 @@ def _create(self, clear=False):
if clear:
shutil.rmtree(self.location)
if self._template:
# On Windows, calling `_virtualenv.path_locations(target)`
# will have created the `target` directory...
if sys.platform == 'win32' and self.location.exists():
self.location.rmdir()
# Clone virtual environment from template.
shutil.copytree(
self._template.location, self.location, symlinks=True
Expand All @@ -63,88 +58,51 @@ def _create(self, clear=False):
else:
# Create a new virtual environment.
if self._venv_type == 'virtualenv':
_virtualenv.create_environment(
_virtualenv.cli_run([
self.location,
no_pip=True,
no_wheel=True,
no_setuptools=True,
)
self._fix_virtualenv_site_module()
"--no-pip",
"--no-wheel",
"--no-setuptools",
])
elif self._venv_type == 'venv':
builder = _venv.EnvBuilder()
context = builder.ensure_directories(self.location)
builder.create_configuration(context)
builder.setup_python(context)
self.site.mkdir(parents=True, exist_ok=True)
else:
raise ValueError("venv type must be 'virtualenv' or 'venv'")
self.sitecustomize = self._sitecustomize
self.user_site_packages = self._user_site_packages

def _fix_virtualenv_site_module(self):
# Patch `site.py` so user site work as expected.
site_py = self.lib / 'site.py'
with open(site_py) as fp:
site_contents = fp.read()
for pattern, replace in (
(
# Ensure enabling user site does not result in adding
# the real site-packages' directory to `sys.path`.
(
'\ndef virtual_addsitepackages(known_paths):\n'
),
(
'\ndef virtual_addsitepackages(known_paths):\n'
' return known_paths\n'
),
),
(
# Fix sites ordering: user site must be added before system.
(
'\n paths_in_sys = addsitepackages(paths_in_sys)'
'\n paths_in_sys = addusersitepackages(paths_in_sys)\n'
),
(
'\n paths_in_sys = addusersitepackages(paths_in_sys)'
'\n paths_in_sys = addsitepackages(paths_in_sys)\n'
),
),
):
assert pattern in site_contents
site_contents = site_contents.replace(pattern, replace)
with open(site_py, 'w') as fp:
fp.write(site_contents)
# Make sure bytecode is up-to-date too.
assert compileall.compile_file(str(site_py), quiet=1, force=True)

def _customize_site(self):
contents = ''
if self._venv_type == 'venv':
# Enable user site (before system).
contents += textwrap.dedent(
'''
import os, site, sys

if not os.environ.get('PYTHONNOUSERSITE', False):

site.ENABLE_USER_SITE = True

# First, drop system-sites related paths.
original_sys_path = sys.path[:]
known_paths = set()
for path in site.getsitepackages():
site.addsitedir(path, known_paths=known_paths)
system_paths = sys.path[len(original_sys_path):]
for path in system_paths:
if path in original_sys_path:
original_sys_path.remove(path)
sys.path = original_sys_path

# Second, add user-site.
site.addsitedir(site.getusersitepackages())

# Third, add back system-sites related paths.
for path in site.getsitepackages():
site.addsitedir(path)
''').strip()
# Enable user site (before system).
contents = textwrap.dedent(
'''
import os, site, sys

if not os.environ.get('PYTHONNOUSERSITE', False):

site.ENABLE_USER_SITE = True

# First, drop system-sites related paths.
original_sys_path = sys.path[:]
known_paths = set()
for path in site.getsitepackages():
site.addsitedir(path, known_paths=known_paths)
system_paths = sys.path[len(original_sys_path):]
for path in system_paths:
if path in original_sys_path:
original_sys_path.remove(path)
sys.path = original_sys_path

# Second, add user-site.
site.addsitedir(site.getusersitepackages())

# Third, add back system-sites related paths.
for path in site.getsitepackages():
site.addsitedir(path)
''').strip()
if self._sitecustomize is not None:
contents += '\n' + self._sitecustomize
sitecustomize = self.site / "sitecustomize.py"
Expand Down Expand Up @@ -176,11 +134,13 @@ def user_site_packages(self):
@user_site_packages.setter
def user_site_packages(self, value):
self._user_site_packages = value
if self._venv_type == 'virtualenv':
marker = self.lib / "no-global-site-packages.txt"
if self._user_site_packages:
marker.unlink()
else:
marker.touch()
elif self._venv_type == 'venv':
self._customize_site()
self._customize_site()

pyvenv_cfg = self.location.joinpath("pyvenv.cfg")
modified_lines = []
for line in pyvenv_cfg.read_text().splitlines():
k, v = line.split("=", 1)
if k.strip() == "include-system-site-packages":
line = "{}= {}".format(k, "true" if value else "false")
modified_lines.append(line)
pyvenv_cfg.write_text("\n".join(modified_lines))
2 changes: 1 addition & 1 deletion tools/requirements/tests.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ pytest-xdist<1.28.0
pyyaml
setuptools>=39.2.0 # Needed for `setuptools.wheel.Wheel` support.
scripttest
https://github.com/pypa/virtualenv/archive/legacy.zip#egg=virtualenv
git+https://github.com/pypa/virtualenv.git@master#egg=virtualenv
werkzeug==0.16.0
wheel