mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Replace virtualenv with Python's built-in venv (#30377)
* Replace virtualenv with Python's built-in venv. * Apply Delan's suggestions and make a couple small fixes - Fix a tidy warning about directories that don't exist - Use shutil instead of the redundant get_exec_path - Miscellaneous cleanups * Fix typo in environment variable * fix bug where pip still tries to the wrong site-packages --------- Co-authored-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Delan Azabani <dazabani@igalia.com>
This commit is contained in:
parent
914fe64fc7
commit
117d59d393
15 changed files with 52 additions and 71 deletions
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
|
@ -17,7 +17,7 @@ jobs:
|
||||||
fetch-depth: 2
|
fetch-depth: 2
|
||||||
- name: Bootstrap
|
- name: Bootstrap
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
sudo apt update
|
sudo apt update
|
||||||
python3 ./mach bootstrap
|
python3 ./mach bootstrap
|
||||||
- name: Compile docs
|
- name: Compile docs
|
||||||
|
|
2
.github/workflows/linux-wpt.yml
vendored
2
.github/workflows/linux-wpt.yml
vendored
|
@ -57,7 +57,7 @@ jobs:
|
||||||
run: tar -xzf release-binary/target.tar.gz
|
run: tar -xzf release-binary/target.tar.gz
|
||||||
- name: Prep test environment
|
- name: Prep test environment
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install -qy --no-install-recommends libgl1 libssl1.1 libdbus-1-3 libxcb-xfixes0-dev libxcb-shape0-dev libunwind8 libgl1-mesa-dri mesa-vulkan-drivers libegl1-mesa
|
sudo apt install -qy --no-install-recommends libgl1 libssl1.1 libdbus-1-3 libxcb-xfixes0-dev libxcb-shape0-dev libunwind8 libgl1-mesa-dri mesa-vulkan-drivers libegl1-mesa
|
||||||
sudo apt install ./libffi6_3.2.1-8_amd64.deb
|
sudo apt install ./libffi6_3.2.1-8_amd64.deb
|
||||||
|
|
2
.github/workflows/linux.yml
vendored
2
.github/workflows/linux.yml
vendored
|
@ -87,7 +87,7 @@ jobs:
|
||||||
crate: taplo-cli
|
crate: taplo-cli
|
||||||
locked: true
|
locked: true
|
||||||
- name: Bootstrap Python
|
- name: Bootstrap Python
|
||||||
run: python3 -m pip install --upgrade pip virtualenv
|
run: python3 -m pip install --upgrade pip
|
||||||
- name: Bootstrap dependencies
|
- name: Bootstrap dependencies
|
||||||
run: sudo apt update && python3 ./mach bootstrap
|
run: sudo apt update && python3 ./mach bootstrap
|
||||||
- name: Tidy
|
- name: Tidy
|
||||||
|
|
2
.github/workflows/mac-wpt.yml
vendored
2
.github/workflows/mac-wpt.yml
vendored
|
@ -43,7 +43,7 @@ jobs:
|
||||||
- name: Prep test environment
|
- name: Prep test environment
|
||||||
run: |
|
run: |
|
||||||
gtar -xzf target.tar.gz
|
gtar -xzf target.tar.gz
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
python3 ./mach bootstrap
|
python3 ./mach bootstrap
|
||||||
- name: Smoketest
|
- name: Smoketest
|
||||||
run: python3 ./mach smoketest --${{ inputs.profile }}
|
run: python3 ./mach smoketest --${{ inputs.profile }}
|
||||||
|
|
2
.github/workflows/mac.yml
vendored
2
.github/workflows/mac.yml
vendored
|
@ -82,7 +82,7 @@ jobs:
|
||||||
locked: true
|
locked: true
|
||||||
- name: Bootstrap
|
- name: Bootstrap
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
python3 ./mach bootstrap
|
python3 ./mach bootstrap
|
||||||
brew install gnu-tar
|
brew install gnu-tar
|
||||||
- name: Build (${{ inputs.profile }})
|
- name: Build (${{ inputs.profile }})
|
||||||
|
|
2
.github/workflows/nightly-rust.yml
vendored
2
.github/workflows/nightly-rust.yml
vendored
|
@ -24,7 +24,7 @@ jobs:
|
||||||
run: echo nightly > rust-toolchain
|
run: echo nightly > rust-toolchain
|
||||||
- name: Bootstrap
|
- name: Bootstrap
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
sudo apt update
|
sudo apt update
|
||||||
python3 ./mach bootstrap
|
python3 ./mach bootstrap
|
||||||
- name: Release build
|
- name: Release build
|
||||||
|
|
2
.github/workflows/scheduled-wpt-import.yml
vendored
2
.github/workflows/scheduled-wpt-import.yml
vendored
|
@ -35,7 +35,7 @@ jobs:
|
||||||
- uses: actions/download-artifact@v3
|
- uses: actions/download-artifact@v3
|
||||||
- name: Prep environment
|
- name: Prep environment
|
||||||
run: |
|
run: |
|
||||||
python3 -m pip install --upgrade pip virtualenv
|
python3 -m pip install --upgrade pip
|
||||||
sudo apt update
|
sudo apt update
|
||||||
python3 ./mach bootstrap
|
python3 ./mach bootstrap
|
||||||
- name: Add upstream remote
|
- name: Add upstream remote
|
||||||
|
|
2
.github/workflows/windows.yml
vendored
2
.github/workflows/windows.yml
vendored
|
@ -78,7 +78,7 @@ jobs:
|
||||||
# this point crown is not installed yet.
|
# this point crown is not installed yet.
|
||||||
RUSTC: "rustc"
|
RUSTC: "rustc"
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip virtualenv
|
python -m pip install --upgrade pip
|
||||||
python mach fetch
|
python mach fetch
|
||||||
python mach bootstrap-gstreamer
|
python mach bootstrap-gstreamer
|
||||||
cargo install --path support/crown
|
cargo install --path support/crown
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,6 +12,7 @@
|
||||||
/ports/android/local.properties
|
/ports/android/local.properties
|
||||||
/ports/android/obj
|
/ports/android/obj
|
||||||
/python/_virtualenv*
|
/python/_virtualenv*
|
||||||
|
/python/_venv*
|
||||||
/python/tidy/servo_tidy.egg-info
|
/python/tidy/servo_tidy.egg-info
|
||||||
/tests/wpt/sync
|
/tests/wpt/sync
|
||||||
*.pkl
|
*.pkl
|
||||||
|
|
11
README.md
11
README.md
|
@ -25,18 +25,17 @@ manually, try the [manual build setup][manual-build].
|
||||||
- Install [Xcode](https://developer.apple.com/xcode/)
|
- Install [Xcode](https://developer.apple.com/xcode/)
|
||||||
- Install [Homebrew](https://brew.sh/)
|
- Install [Homebrew](https://brew.sh/)
|
||||||
- Run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
- Run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
||||||
- Run `pip3 install virtualenv`
|
|
||||||
- Run `./mach bootstrap`<br/>
|
- Run `./mach bootstrap`<br/>
|
||||||
*Note: This will install the recommended version of GStreamer globally on your system.*
|
*Note: This will install the recommended version of GStreamer globally on your system.*
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
- Run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
- Run `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`
|
||||||
- Install Python and virtualenv
|
- Install Python
|
||||||
- **Debian-like:** Run `sudo apt install python3-virtualenv python3-pip`
|
- **Debian-like:** Run `sudo apt install python3-pip`
|
||||||
- **Fedora:** Run `sudo dnf install python3 python3-virtualenv python3-pip python3-devel`
|
- **Fedora:** Run `sudo dnf install python3 python3-pip python3-devel`
|
||||||
- **Arch:** Run `sudo pacman -S --needed python python-virtualenv python-pip`
|
- **Arch:** Run `sudo pacman -S --needed python python-pip`
|
||||||
- **Gentoo:** Run `sudo emerge dev-python/virtualenv dev-python/pip`
|
- **Gentoo:** Run `sudo emerge dev-python/pip`
|
||||||
- Run `./mach bootstrap`
|
- Run `./mach bootstrap`
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
|
@ -113,13 +113,3 @@ If you want to test the data submission code in `submit_to_perfherder.py` withou
|
||||||
* `vagrant ssh`
|
* `vagrant ssh`
|
||||||
* `./manage.py create_credentials <username> <email> "description"`, the email has to match your logged in user. Remember to log-in through the Web UI once before you run this.
|
* `./manage.py create_credentials <username> <email> "description"`, the email has to match your logged in user. Remember to log-in through the Web UI once before you run this.
|
||||||
* Setup your Treeherder client ID and secret as environment variables `TREEHERDER_CLIENT_ID` and `TREEHERDER_CLIENT_SECRET`
|
* Setup your Treeherder client ID and secret as environment variables `TREEHERDER_CLIENT_ID` and `TREEHERDER_CLIENT_SECRET`
|
||||||
|
|
||||||
# Troubleshooting
|
|
||||||
|
|
||||||
If you saw this error message:
|
|
||||||
|
|
||||||
```
|
|
||||||
venv/bin/activate: line 8: _OLD_VIRTUAL_PATH: unbound variable
|
|
||||||
```
|
|
||||||
|
|
||||||
That means your `virtualenv` is too old, try run `pip install -U virtualenv` to upgrade (If you installed ubuntu's `python-virtualenv` package, uninstall it first then install it through `pip`)
|
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
import sys
|
import site
|
||||||
import shutil
|
import shutil
|
||||||
|
import sys
|
||||||
|
|
||||||
from subprocess import Popen
|
from subprocess import Popen
|
||||||
from tempfile import TemporaryFile
|
from tempfile import TemporaryFile
|
||||||
|
@ -80,27 +81,26 @@ CATEGORIES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Possible names of executables
|
|
||||||
# NOTE: Windows Python doesn't provide versioned executables, so we must use
|
|
||||||
# the plain names. On MSYS, we still use Windows Python.
|
|
||||||
PYTHON_NAMES = ["python-2.7", "python2.7", "python2", "python"]
|
|
||||||
|
|
||||||
|
|
||||||
def _get_exec_path(names, is_valid_path=lambda _path: True):
|
|
||||||
for name in names:
|
|
||||||
path = shutil.which(name)
|
|
||||||
if path and is_valid_path(path):
|
|
||||||
return path
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
|
# venv calls its scripts folder "bin" on non-Windows and "Scripts" on Windows.
|
||||||
def _get_virtualenv_script_dir():
|
def _get_virtualenv_script_dir():
|
||||||
# Virtualenv calls its scripts folder "bin" on linux/OSX/MSYS64 but "Scripts" on Windows
|
|
||||||
if os.name == "nt" and os.sep != "/":
|
if os.name == "nt" and os.sep != "/":
|
||||||
return "Scripts"
|
return "Scripts"
|
||||||
return "bin"
|
return "bin"
|
||||||
|
|
||||||
|
|
||||||
|
# venv names its lib folder something like "lib/python3.11/site-packages" on
|
||||||
|
# non-Windows and "Lib\site-packages" on Window.
|
||||||
|
def _get_virtualenv_lib_dir():
|
||||||
|
if os.name == "nt" and os.sep != "/":
|
||||||
|
return os.path.join("Lib", "site-packages")
|
||||||
|
return os.path.join(
|
||||||
|
"lib",
|
||||||
|
f"python{sys.version_info[0]}.{sys.version_info[1]}",
|
||||||
|
"site-packages"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _process_exec(args):
|
def _process_exec(args):
|
||||||
with TemporaryFile() as out:
|
with TemporaryFile() as out:
|
||||||
with TemporaryFile() as err:
|
with TemporaryFile() as err:
|
||||||
|
@ -130,32 +130,29 @@ def _process_exec(args):
|
||||||
|
|
||||||
|
|
||||||
def _activate_virtualenv(topdir):
|
def _activate_virtualenv(topdir):
|
||||||
virtualenv_path = os.path.join(topdir, "python", "_virtualenv%d.%d" % (sys.version_info[0], sys.version_info[1]))
|
virtualenv_path = os.path.join(topdir, "python", "_venv%d.%d" % (sys.version_info[0], sys.version_info[1]))
|
||||||
python = sys.executable # If there was no python, mach wouldn't have run at all!
|
python = sys.executable
|
||||||
if not python:
|
|
||||||
sys.exit('Failed to find python executable for starting virtualenv.')
|
|
||||||
|
|
||||||
script_dir = _get_virtualenv_script_dir()
|
if os.environ.get("VIRTUAL_ENV") != virtualenv_path:
|
||||||
activate_path = os.path.join(virtualenv_path, script_dir, "activate_this.py")
|
venv_script_path = os.path.join(virtualenv_path, _get_virtualenv_script_dir())
|
||||||
need_pip_upgrade = False
|
if not os.path.exists(virtualenv_path):
|
||||||
if not (os.path.exists(virtualenv_path) and os.path.exists(activate_path)):
|
_process_exec([python, "-m", "venv", "--system-site-packages", virtualenv_path])
|
||||||
import importlib
|
|
||||||
try:
|
|
||||||
importlib.import_module('virtualenv')
|
|
||||||
except ModuleNotFoundError:
|
|
||||||
sys.exit("Python virtualenv is not installed. Please install it prior to running mach.")
|
|
||||||
|
|
||||||
_process_exec([python, "-m", "virtualenv", "-p", python, "--system-site-packages", virtualenv_path])
|
# This general approach is taken from virtualenv's `activate_this.py`.
|
||||||
|
os.environ["PATH"] = os.pathsep.join([venv_script_path, *os.environ.get("PATH", "").split(os.pathsep)])
|
||||||
|
os.environ["VIRTUAL_ENV"] = virtualenv_path
|
||||||
|
|
||||||
# We want to upgrade pip when virtualenv created for the first time
|
prev_length = len(sys.path)
|
||||||
need_pip_upgrade = True
|
lib_path = os.path.realpath(os.path.join(virtualenv_path, _get_virtualenv_lib_dir()))
|
||||||
|
site.addsitedir(lib_path)
|
||||||
|
sys.path[:] = sys.path[prev_length:] + sys.path[0:prev_length]
|
||||||
|
|
||||||
exec(compile(open(activate_path).read(), activate_path, 'exec'), dict(__file__=activate_path))
|
sys.real_prefix = sys.prefix
|
||||||
|
sys.prefix = virtualenv_path
|
||||||
|
|
||||||
python = _get_exec_path(PYTHON_NAMES,
|
# Use the python in our venv for subprocesses, not the python we were originally run with.
|
||||||
is_valid_path=lambda path: path.startswith(virtualenv_path))
|
# Otherwise pip may still try to write to the wrong site-packages directory.
|
||||||
if not python:
|
python = os.path.join(venv_script_path, "python")
|
||||||
sys.exit("Python executable in virtualenv failed to activate.")
|
|
||||||
|
|
||||||
# TODO: Right now, we iteratively install all the requirements by invoking
|
# TODO: Right now, we iteratively install all the requirements by invoking
|
||||||
# `pip install` each time. If it were the case that there were conflicting
|
# `pip install` each time. If it were the case that there were conflicting
|
||||||
|
@ -168,11 +165,6 @@ def _activate_virtualenv(topdir):
|
||||||
os.path.join(WPT_RUNNER_PATH, "requirements.txt",),
|
os.path.join(WPT_RUNNER_PATH, "requirements.txt",),
|
||||||
]
|
]
|
||||||
|
|
||||||
if need_pip_upgrade:
|
|
||||||
# Upgrade pip when virtualenv is created to fix the issue
|
|
||||||
# https://github.com/servo/servo/issues/11074
|
|
||||||
_process_exec([python, "-m", "pip", "install", "-I", "-U", "pip"])
|
|
||||||
|
|
||||||
for req_rel_path in requirements_paths:
|
for req_rel_path in requirements_paths:
|
||||||
req_path = os.path.join(topdir, req_rel_path)
|
req_path = os.path.join(topdir, req_rel_path)
|
||||||
marker_file = req_rel_path.replace(os.path.sep, '-')
|
marker_file = req_rel_path.replace(os.path.sep, '-')
|
||||||
|
|
|
@ -252,7 +252,7 @@ class MachCommands(CommandBase):
|
||||||
subprocess.call(["perl", "-i", "-pe", expr, target_path])
|
subprocess.call(["perl", "-i", "-pe", expr, target_path])
|
||||||
|
|
||||||
@Command('clean',
|
@Command('clean',
|
||||||
description='Clean the target/ and python/_virtualenv[version]/ directories',
|
description='Clean the target/ and python/_venv[version]/ directories',
|
||||||
category='build')
|
category='build')
|
||||||
@CommandArgument('--manifest-path',
|
@CommandArgument('--manifest-path',
|
||||||
default=None,
|
default=None,
|
||||||
|
@ -265,7 +265,7 @@ class MachCommands(CommandBase):
|
||||||
def clean(self, manifest_path=None, params=[], verbose=False):
|
def clean(self, manifest_path=None, params=[], verbose=False):
|
||||||
self.ensure_bootstrapped()
|
self.ensure_bootstrapped()
|
||||||
|
|
||||||
virtualenv_fname = '_virtualenv%d.%d' % (sys.version_info[0], sys.version_info[1])
|
virtualenv_fname = '_venv%d.%d' % (sys.version_info[0], sys.version_info[1])
|
||||||
virtualenv_path = path.join(self.get_top_dir(), 'python', virtualenv_fname)
|
virtualenv_path = path.join(self.get_top_dir(), 'python', virtualenv_fname)
|
||||||
if path.exists(virtualenv_path):
|
if path.exists(virtualenv_path):
|
||||||
print('Removing virtualenv directory: %s' % virtualenv_path)
|
print('Removing virtualenv directory: %s' % virtualenv_path)
|
||||||
|
|
|
@ -36,7 +36,6 @@ from xml.etree.ElementTree import XML
|
||||||
|
|
||||||
import toml
|
import toml
|
||||||
|
|
||||||
from mach_bootstrap import _get_exec_path
|
|
||||||
from mach.decorators import CommandArgument, CommandArgumentGroup
|
from mach.decorators import CommandArgument, CommandArgumentGroup
|
||||||
from mach.registrar import Registrar
|
from mach.registrar import Registrar
|
||||||
|
|
||||||
|
@ -618,8 +617,8 @@ class CommandBase(object):
|
||||||
host_suffix = "x86_64"
|
host_suffix = "x86_64"
|
||||||
host = os_type + "-" + host_suffix
|
host = os_type + "-" + host_suffix
|
||||||
|
|
||||||
host_cc = env.get('HOST_CC') or _get_exec_path(["clang"]) or _get_exec_path(["gcc"])
|
host_cc = env.get('HOST_CC') or shutil.which(["clang"]) or util.whichget_exec_path(["gcc"])
|
||||||
host_cxx = env.get('HOST_CXX') or _get_exec_path(["clang++"]) or _get_exec_path(["g++"])
|
host_cxx = env.get('HOST_CXX') or util.whichget_exec_path(["clang++"]) or util.whichget_exec_path(["g++"])
|
||||||
|
|
||||||
llvm_toolchain = path.join(env['ANDROID_NDK'], "toolchains", "llvm", "prebuilt", host)
|
llvm_toolchain = path.join(env['ANDROID_NDK'], "toolchains", "llvm", "prebuilt", host)
|
||||||
gcc_toolchain = path.join(env['ANDROID_NDK'], "toolchains",
|
gcc_toolchain = path.join(env['ANDROID_NDK'], "toolchains",
|
||||||
|
|
|
@ -105,7 +105,7 @@ directories = [
|
||||||
"./tests/wpt/mozilla/tests/mozilla/referrer-policy",
|
"./tests/wpt/mozilla/tests/mozilla/referrer-policy",
|
||||||
"./tests/wpt/mozilla/tests/webgl",
|
"./tests/wpt/mozilla/tests/webgl",
|
||||||
"./python/tidy/tests",
|
"./python/tidy/tests",
|
||||||
"./python/_virtualenv*",
|
"./python/_v*",
|
||||||
"./python/mach",
|
"./python/mach",
|
||||||
# Generated and upstream code combined with our own. Could use cleanup
|
# Generated and upstream code combined with our own. Could use cleanup
|
||||||
"./target",
|
"./target",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue