diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /testing/web-platform/tests/tools/wpt/virtualenv.py | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/tools/wpt/virtualenv.py')
-rw-r--r-- | testing/web-platform/tests/tools/wpt/virtualenv.py | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/testing/web-platform/tests/tools/wpt/virtualenv.py b/testing/web-platform/tests/tools/wpt/virtualenv.py new file mode 100644 index 0000000000..59f422a6ef --- /dev/null +++ b/testing/web-platform/tests/tools/wpt/virtualenv.py @@ -0,0 +1,142 @@ +# mypy: allow-untyped-defs + +import os +import shutil +import sys +import logging +from shutil import which + +# The `pkg_resources` module is provided by `setuptools`, which is itself a +# dependency of `virtualenv`. Tolerate its absence so that this module may be +# evaluated when that module is not available. Because users may not recognize +# the `pkg_resources` module by name, raise a more descriptive error if it is +# referenced during execution. +try: + import pkg_resources as _pkg_resources + get_pkg_resources = lambda: _pkg_resources +except ImportError: + def get_pkg_resources(): + raise ValueError("The Python module `virtualenv` is not installed.") + +from tools.wpt.utils import call + +logger = logging.getLogger(__name__) + +class Virtualenv: + def __init__(self, path, skip_virtualenv_setup): + self.path = path + self.skip_virtualenv_setup = skip_virtualenv_setup + if not skip_virtualenv_setup: + self.virtualenv = which("virtualenv") + if not self.virtualenv: + raise ValueError("virtualenv must be installed and on the PATH") + self._working_set = None + + @property + def exists(self): + # We need to check also for lib_path because different python versions + # create different library paths. + return os.path.isdir(self.path) and os.path.isdir(self.lib_path) + + @property + def broken_link(self): + python_link = os.path.join(self.path, ".Python") + return os.path.lexists(python_link) and not os.path.exists(python_link) + + def create(self): + if os.path.exists(self.path): + shutil.rmtree(self.path) + self._working_set = None + call(self.virtualenv, self.path, "-p", sys.executable) + + @property + def bin_path(self): + if sys.platform in ("win32", "cygwin"): + return os.path.join(self.path, "Scripts") + return os.path.join(self.path, "bin") + + @property + def pip_path(self): + path = which("pip3", path=self.bin_path) + if path is None: + raise ValueError("pip3 not found") + return path + + @property + def lib_path(self): + base = self.path + + # this block is literally taken from virtualenv 16.4.3 + IS_PYPY = hasattr(sys, "pypy_version_info") + IS_JYTHON = sys.platform.startswith("java") + if IS_JYTHON: + site_packages = os.path.join(base, "Lib", "site-packages") + elif IS_PYPY: + site_packages = os.path.join(base, "site-packages") + else: + IS_WIN = sys.platform == "win32" + if IS_WIN: + site_packages = os.path.join(base, "Lib", "site-packages") + else: + site_packages = os.path.join(base, "lib", f"python{sys.version[:3]}", "site-packages") + + return site_packages + + @property + def working_set(self): + if not self.exists: + raise ValueError("trying to read working_set when venv doesn't exist") + + if self._working_set is None: + self._working_set = get_pkg_resources().WorkingSet((self.lib_path,)) + + return self._working_set + + def activate(self): + if sys.platform == 'darwin': + # The default Python on macOS sets a __PYVENV_LAUNCHER__ environment + # variable which affects invocation of python (e.g. via pip) in a + # virtualenv. Unset it if present to avoid this. More background: + # https://github.com/web-platform-tests/wpt/issues/27377 + # https://github.com/python/cpython/pull/9516 + os.environ.pop('__PYVENV_LAUNCHER__', None) + path = os.path.join(self.bin_path, "activate_this.py") + with open(path) as f: + exec(f.read(), {"__file__": path}) + + def start(self): + if not self.exists or self.broken_link: + self.create() + self.activate() + + def install(self, *requirements): + try: + self.working_set.require(*requirements) + except Exception: + pass + else: + return + + # `--prefer-binary` guards against race conditions when installation + # occurs while packages are in the process of being published. + call(self.pip_path, "install", "--prefer-binary", *requirements) + + def install_requirements(self, *requirements_paths): + install = [] + # Check which requirements are already satisfied, to skip calling pip + # at all in the case that we've already installed everything, and to + # minimise the installs in other cases. + for requirements_path in requirements_paths: + with open(requirements_path) as f: + try: + self.working_set.require(f.read()) + except Exception: + install.append(requirements_path) + + if install: + # `--prefer-binary` guards against race conditions when installation + # occurs while packages are in the process of being published. + cmd = [self.pip_path, "install", "--prefer-binary"] + for path in install: + cmd.extend(["-r", path]) + call(*cmd) |