Source code

Revision control

Other Tools

Test Info: Warnings

  • This test gets skipped with pattern: os == "win" os == "mac"
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at
import shutil
import subprocess
import sys
from pathlib import Path
import mozunit
from buildconfig import topsrcdir
from mach.requirements import MachEnvRequirements
def _resolve_command_site_names():
virtualenv_names = []
for child in (Path(topsrcdir) / "build").iterdir():
if not"_virtualenv_packages.txt"):
if == "mach_virtualenv_packages.txt":
virtualenv_names.append([: -len("_virtualenv_packages.txt")])
return virtualenv_names
def _requirement_definition_to_pip_format(virtualenv_name, cache, is_mach_or_build_env):
"""Convert from parsed requirements object to pip-consumable format"""
requirements_path = (
Path(topsrcdir) / "build" / f"{virtualenv_name}_virtualenv_packages.txt"
requirements = MachEnvRequirements.from_requirements_definition(
topsrcdir, False, not is_mach_or_build_env, requirements_path
lines = []
for pypi in (
requirements.pypi_requirements + requirements.pypi_optional_requirements
for vendored in requirements.vendored_requirements:
for pth in requirements.pth_requirements:
path = Path(pth.path)
if "third_party" not in ( for p in path.parents):
for child in path.iterdir():
raise Exception(
f'In {requirements_path}, the "pth:" pointing to "{path}" has a '
'".dist-info" file.\n'
'Perhaps it should change to start with "vendored:" instead of '
raise Exception(
f'In {requirements_path}, the "pth:" pointing to "{path}" has an '
'".egg-info" file.\n'
'Perhaps it should change to start with "vendored:" instead of '
return "\n".join(lines)
class PackageCache:
def __init__(self, storage_dir: Path):
self._cache = {}
self._storage_dir = storage_dir
def package_for_vendor_dir(self, vendor_path: Path):
if vendor_path in self._cache:
return self._cache[vendor_path]
if not any((p for p in vendor_path.iterdir() if".dist-info"))):
# This vendored package is not a wheel. It may be a source package (with
# a, or just some Python code that was manually copied into the
# tree. If it's a source package, the file may be up a few levels
# from the referenced Python module path.
package_dir = vendor_path
while True:
if (package_dir / "").exists():
elif package_dir.parent == package_dir:
raise Exception(
f'Package "{vendor_path}" is not a wheel and does not have a '
' file. Perhaps it should be "pth:" instead of '
package_dir = package_dir.parent
self._cache[vendor_path] = package_dir
return package_dir
# Pip requires that wheels have a version number in their name, even if
# it ignores it. We should parse out the version and put it in here
# so that failure debugging is easier, but that's non-trivial work.
# So, this "0" satisfies pip's naming requirement while being relatively
# obvious that it's a placeholder.
output_path = self._storage_dir / f"{}-0-py3-none-any"
shutil.make_archive(str(output_path), "zip", vendor_path)
whl_path = output_path.parent / ( + ".whl")
(output_path.parent / ( + ".zip")).rename(whl_path)
self._cache[vendor_path] = whl_path
return whl_path
def test_sites_compatible(tmpdir: str):
command_site_names = _resolve_command_site_names()
work_dir = Path(tmpdir)
cache = PackageCache(work_dir)
mach_requirements = _requirement_definition_to_pip_format("mach", cache, True)
# Create virtualenv to try to install all dependencies into.
/ "third_party"
/ "python"
/ "virtualenv"
/ ""
str(work_dir / "env"),
for name in command_site_names:
print(f'Checking compatibility of "{name}" site')
command_requirements = _requirement_definition_to_pip_format(
name, cache, name == "build"
with open(work_dir / "requirements.txt", "w") as requirements_txt:
# Attempt to install combined set of dependencies (global Mach + current
# command)
str(work_dir / "env" / "bin" / "pip"),
str(work_dir / "requirements.txt"),
if __name__ == "__main__":