Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit efc472b

Browse files
Bug 1886479 - Introduce the possibility to provide a fallback in python site r=mach-reviewers,ahal
pyyaml is already vendored but as a consequence we don't benefit from the faster native loader. Introduce the possibility to provide a vendored package as fallback to an optional pypi package. If the pypi package install fails, we can still use the vendored one without the speed benefit. This makes my `mach build export` step 8% faster. Differential Revision: https://phabricator.services.mozilla.com/D234652
1 parent 008a615 commit efc472b

File tree

4 files changed

+54
-1
lines changed

4 files changed

+54
-1
lines changed

python/docs/index.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,18 @@ By default ``./mach vendor python`` only fully runs if changes are detected in t
160160
want to force the full vendor to run, just add ``--force``.
161161

162162

163+
If the package contains optional native dependencies, they won't be compiled as
164+
part of the vendored package. It is however possible to prefer the pypi version
165+
which may contain the native bits, while allowing to fallback to the vendored
166+
version:
167+
168+
.. code:: text
169+
170+
...
171+
vendored-fallback:pypi-package-name:third_party/python/new-package:explanation
172+
...
173+
174+
163175
.. _mach-and-build-native-dependencies:
164176

165177
Mach/Build Native 3rd-party Dependencies

python/mach/mach/requirements.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# License, v. 2.0. If a copy of the MPL was not distributed with this
33
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
44
import os
5+
import re
56
from pathlib import Path
67

78
from packaging.requirements import Requirement
@@ -63,13 +64,20 @@ def __init__(self):
6364
self.pypi_requirements = []
6465
self.pypi_optional_requirements = []
6566
self.vendored_requirements = []
67+
self.vendored_fallback_requirements = []
6668

6769
def pths_as_absolute(self, topsrcdir: str):
6870
return [
6971
os.path.normcase(Path(topsrcdir) / pth.path)
7072
for pth in (self.pth_requirements + self.vendored_requirements)
7173
]
7274

75+
def pths_fallback_as_absolute(self, topsrcdir: str):
76+
return [
77+
os.path.normcase(Path(topsrcdir) / pth.path)
78+
for pth in self.vendored_fallback_requirements
79+
]
80+
7381
@classmethod
7482
def from_requirements_definition(
7583
cls,
@@ -124,6 +132,32 @@ def _parse_requirements_line(
124132
requirements_output.pth_requirements.append(PthSpecifier(params))
125133
elif action == "vendored":
126134
requirements_output.vendored_requirements.append(PthSpecifier(params))
135+
elif action == "vendored-fallback":
136+
if is_thunderbird_packages_txt:
137+
raise Exception(THUNDERBIRD_PYPI_ERROR)
138+
139+
pypi_pkg, vendored_path, repercussion = params.split(":")
140+
requirements = topsrcdir / "third_party" / "python" / "requirements.txt"
141+
with open(requirements) as req:
142+
content = req.read()
143+
pattern = re.compile(rf"^({pypi_pkg}==.*) \\$", re.MULTILINE)
144+
version_matches = pattern.findall(content, re.MULTILINE)
145+
if len(version_matches) != 1:
146+
raise Exception(
147+
f"vendored-fallback package {pypi_pkg} is not referenced in {requirements}"
148+
)
149+
(raw_requirement,) = version_matches
150+
151+
requirements_output.pypi_optional_requirements.append(
152+
PypiOptionalSpecifier(
153+
repercussion,
154+
_parse_package_specifier(raw_requirement, only_strict_requirements),
155+
)
156+
)
157+
158+
requirements_output.vendored_fallback_requirements.append(
159+
PthSpecifier(vendored_path)
160+
)
127161
elif action == "packages.txt":
128162
_parse_requirements_definition_file(
129163
topsrcdir / params,

python/mach/mach/site.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ def _sys_path(self):
412412
*stdlib_paths,
413413
*self._requirements.pths_as_absolute(self._topsrcdir),
414414
*system_site_paths,
415+
*self._requirements.pths_fallback_as_absolute(self._topsrcdir),
415416
]
416417
elif self._site_packages_source == SitePackagesSource.NONE:
417418
stdlib_paths = self._metadata.original_python.sys_path_stdlib()
@@ -795,6 +796,12 @@ def _pthfile_lines(self):
795796
lines.extend(
796797
_deprioritize_venv_packages(self._virtualenv, self._populate_virtualenv)
797798
)
799+
# Except for fallback that should come after the pip installed package.
800+
lines.extend(
801+
resolve_requirements(self._topsrcdir, "mach").pths_fallback_as_absolute(
802+
self._topsrcdir
803+
)
804+
)
798805

799806
# Note that an on-disk virtualenv is always created for commands, even if they
800807
# are using the system as their site-packages source. This is to support use

python/sites/mach.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ pth:xpcom/geckoprocesstypes_generator
5757
pth:xpcom/idl-parser
5858
vendored:third_party/python/Jinja2
5959
vendored:third_party/python/MarkupSafe/src
60-
vendored:third_party/python/PyYAML/lib/
60+
vendored-fallback:pyyaml:third_party/python/PyYAML/lib/:faster native loading is disabled
6161
vendored:third_party/python/ansicon
6262
vendored:third_party/python/appdirs
6363
vendored:third_party/python/attrs

0 commit comments

Comments
 (0)