Bug 1845017 - Disable the TestPHCExhaustion test r=glandium
[gecko.git] / python / docs / index.rst
blob68b16ab649e942d85f387517f2e9b6114306bf28
1 =================================
2 Using third-party Python packages
3 =================================
5 Mach and its associated commands have a variety of 3rd-party Python dependencies. Many of these
6 are vendored in ``third_party/python``, while others are installed at runtime via ``pip``.
8 The dependencies of Mach itself can be found at ``python/sites/mach.txt``. Mach commands
9 may have additional dependencies which are specified at ``python/sites/<site>.txt``.
11 For example, the following Mach command would have its 3rd-party dependencies declared at
12 ``python/sites/foo.txt``.
14 .. code:: python
16     @Command(
17         "foo-it",
18         virtualenv_name="foo",
19     )
20     # ...
21     def foo_it_command():
22         import specific_dependency
24 The format of ``<site>.txt`` files are documented further in the
25 :py:class:`~mach.requirements.MachEnvRequirements` class.
27 Adding a Python package
28 =======================
30 There's two ways of using 3rd-party Python dependencies:
32 * :ref:`pip install the packages <python-pip-install>`. Python dependencies with native code must
33   be installed using ``pip``. This is the recommended technique for adding new Python dependencies.
34 * :ref:`Vendor the source of the Python package in-tree <python-vendor>`. Dependencies of the Mach
35   core logic or of building Firefox itself must be vendored.
37 .. note::
39     For dependencies that meet both restrictions (dependency of Mach/build, *and* has
40     native code), see the :ref:`mach-and-build-native-dependencies` section below.
42 .. _python-pip-install:
44 ``pip install`` the package
45 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
47 To add a ``pip install``-d package dependency, add it to your site's
48 ``python/sites/<site>.txt`` manifest file:
50 .. code::
52     ...
53     pypi:new-package==<version>
54     ...
56 .. note::
58     Some tasks are not permitted to use external resources, and for those we can
59     publish packages to an internal PyPI mirror.
60     See `how to upload to internal PyPI <https://wiki.mozilla.org/ReleaseEngineering/How_To/Upload_to_internal_Pypi>`_
61     for more details.
63 .. _python-vendor:
65 Vendoring Python packages
66 ~~~~~~~~~~~~~~~~~~~~~~~~~
68 To vendor a Python package, add it to ``third_party/python/requirements.in``
69 and then run ``mach vendor python``. This will update the tree of pinned
70 dependencies in ``third_party/python/requirements.txt`` and download them all
71 into the ``third_party/python`` directory.
73 Next, add that package and any new transitive dependencies (you'll see them added in
74 ``third_party/python/requirements.txt``) to the associated site's dependency manifest in
75 ``python/sites/<site>.txt``:
77 .. code::
79     ...
80     vendored:third_party/python/new-package
81     vendored:third_party/python/new-package-dependency-foo
82     vendored:third_party/python/new-package-dependency-bar
83     ...
85 .. note::
87     The following policy applies to **ALL** vendored packages:
89     * Vendored PyPI libraries **MUST NOT** be modified
90     * Vendored libraries **SHOULD** be released copies of libraries available on
91       PyPI.
93       * When considering manually vendoring a package, discuss the situation with
94         the ``#build`` team to ensure that other, more maintainable options are exhausted.
96 .. note::
98     We require that it is possible to build Firefox using only a checkout of the source,
99     without depending on a package index. This ensures that building Firefox is
100     deterministic and dependable, avoids packages from changing out from under us,
101     and means we’re not affected when 3rd party services are offline. We don't want a
102     DoS against PyPI or a random package maintainer removing an old tarball to delay
103     a Firefox chemspill. Therefore, packages required by Mach core logic or for building
104     Firefox itself must be vendored.
106 .. _mach-and-build-native-dependencies:
108 Mach/Build Native 3rd-party Dependencies
109 ========================================
111 There are cases where Firefox is built without being able to ``pip install``, but where
112 native 3rd party Python dependencies enable optional functionality. This can't be solved
113 by vendoring the platform-specific libraries, as then each one would have to be stored
114 multiple times in-tree according to how many platforms we wish to support.
116 Instead, this is solved by pre-installing such native packages onto the host system
117 in advance, then having Mach attempt to use such packages directly from the system.
118 This feature is only viable in very specific environments, as the system Python packages
119 have to be compatible with Mach's vendored packages.
121 .. note:
123     All of these native build-specific dependencies **MUST** be optional requirements
124     as to support the "no strings attached" builds that only use vendored packages.
126 To control this behaviour, the ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE`` environment
127 variable can be used:
129 .. list-table:: ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE``
130     :header-rows: 1
132     * - ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE``
133       - Behaviour
134     * - ``"pip"``
135       - Mach will ``pip install`` all needed dependencies from PyPI at runtime into a Python
136         virtual environment that's reused in future Mach invocations.
137     * - ``"none"``
138       - Mach will perform the build using only vendored packages. No Python virtual environment
139         will be created for Mach.
140     * - ``"system"``
141       - Mach will use the host system's Python packages as part of doing the build. This option
142         allows the usage of native Python packages without leaning on a ``pip install`` at
143         build-time. This is generally slower because the system Python packages have to
144         be asserted to be compatible with Mach. Additionally, dependency lockfiles are ignored,
145         so there's higher risk of breakage. Finally, as with ``"none"``, no Python virtualenv
146         environment is created for Mach.
147     * - ``<unset>``
148       - Same behaviour as ``"pip"`` if ``MOZ_AUTOMATION`` isn't set. Otherwise, uses
149         the same behaviour as ``"none"``.
151 There's a couple restrictions here:
153 * ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE`` only applies to the top-level ``"mach"`` site,
154    the ``"common"`` site and the ``"build"`` site. All other sites will use ``pip install`` at
155    run-time as needed.
157 * ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="system"`` is not allowed when using any site other
158   than ``"mach"``, ``"common"`` or ``"build"``, because:
160   * As described in :ref:`package-compatibility` below, packages used by Mach are still
161     in scope when commands are run, and
162   * The host system is practically guaranteed to be incompatible with commands' dependency
163     lockfiles.
165 The ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE`` environment variable fits into the following use
166 cases:
168 Mozilla CI Builds
169 ~~~~~~~~~~~~~~~~~
171 We need access to the native packages of ``zstandard`` and ``psutil`` to extract archives and
172 get OS information respectively. Use ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="system"``.
174 Mozilla CI non-Build Tasks
175 ~~~~~~~~~~~~~~~~~~~~~~~~~~
177 We generally don't want to create a Mach virtual environment to avoid redundant processing,
178 but it's ok to ``pip install`` for specific command sites as needed, so leave
179 ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE`` unset (``MOZ_AUTOMATION`` implies the default
180 behaviour of ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="none"``).
182 In cases where native packages *are* needed by Mach, use
183 ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="pip"``.
185 Downstream CI Builds
186 ~~~~~~~~~~~~~~~~~~~~
188 Sometimes these builds happen in sandboxed, network-less environments, and usually these builds
189 don't need any of the behaviour enabled by installing native Python dependencies.
190 Use ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="none"``.
192 Gentoo Builds
193 ~~~~~~~~~~~~~
195 When installing Firefox via the package manager, Gentoo generally builds it from source rather than
196 distributing a compiled binary artifact. Accordingly, users doing a build of Firefox in this
197 context don't want stray files created in ``~/.mozbuild`` or unnecessary ``pip install`` calls.
198 Use ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE="none"``.
200 Firefox Developers
201 ~~~~~~~~~~~~~~~~~~
203 Leave ``MACH_BUILD_PYTHON_NATIVE_PACKAGE_SOURCE`` unset so that all Mach commands can be run,
204 Python dependency lockfiles are respected, and optional behaviour is enabled by installing
205 native packages.
207 .. _package-compatibility:
209 Package compatibility
210 =====================
212 Mach requires that all commands' package requirements be compatible with those of Mach itself.
213 (This is because functions and state created by Mach are still usable from within the commands, and
214 they may still need access to their associated 3rd-party modules).
216 However, it is OK for Mach commands to have package requirements which are incompatible with each
217 other. This allows the flexibility for some Mach commands to depend on modern dependencies while
218 other, more mature commands may still only be compatible with a much older version.
220 .. note::
222     Only one version of a package may be vendored at any given time. If two Mach commands need to
223     have conflicting packages, then at least one of them must ``pip install`` the package instead
224     of vendoring.
226     If a Mach command's dependency conflicts with a vendored package, and that vendored package
227     isn't needed by Mach itself, then that vendored dependency should be moved from
228     ``python/sites/mach.txt`` to its associated environment.