Repository: pypa/build
Pull request #195 (2020-12-02 15:31:25)

build: install backend specified dependencies when building with isolation
PEP 517 says that we should use the get_requires_for_* hooks to fetch
extra build dependencies the backend might specify. Currently, we are
not installing these dependencies into the isolted environment, this
patch addresses that.

It also slightly changes the isolation build logic to create a isolated
environment for each distribution we want to build. Since we are now
calling the get_requires_for_{sdist,wheel} hooks to install extra
dependencies, the might change between a sdist and wheel. Since we do
not want sdist dependencies leaking into the environment where the wheel
is built, or vice-versa, we need to separate the environments.

Perhaps in the future we could try to optimize this to see if the sdist
and wheel dependencies are the same and avoid creating a new isolated
environment if they aren't?

Addresses #194

Signed-off-by: Filipe Laíns <lains@riseup.net>

FFY00: Adjusted the comment to clarify layday's question.

Patch:
diff --git a/src/build/__main__.py b/src/build/__main__.py
index 517aab9..8091d00 100644
--- a/src/build/__main__.py
+++ b/src/build/__main__.py
@@ -48,10 +48,13 @@ def _format_dep_chain(dep_chain):  # type: (Sequence[str]) -> str
 
 def _build_in_isolated_env(builder, outdir, distributions):
     # type: (ProjectBuilder, str, List[str]) -> None
-    with IsolatedEnvBuilder() as env:
-        builder.python_executable = env.executable
-        env.install(builder.build_dependencies)
-        for distribution in distributions:
+    for distribution in distributions:
+        with IsolatedEnvBuilder() as env:
+            builder.python_executable = env.executable
+            # first install the build dependencies
+            env.install(builder.build_dependencies)
+            # then get the extra required dependencies from the backend (which was installed in the call above :P)
+            env.install(builder.get_dependencies(distribution))
             builder.build(distribution, outdir)
 
 


Test patch:
diff --git a/tests/test_main.py b/tests/test_main.py
index 54e6ac0..445a2aa 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -102,13 +102,23 @@ def test_version(capsys):
 @pytest.mark.isolated
 def test_build_isolated(mocker, test_flit_path):
     build_cmd = mocker.patch('build.ProjectBuilder.build')
+    required_cmd = mocker.patch(
+        'build.ProjectBuilder.get_dependencies',
+        side_effect=[
+            ['dep1', 'dep2'],
+        ],
+    )
     mocker.patch('build.__main__._error')
     install = mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
     build.__main__.build_package(test_flit_path, '.', ['sdist'])
 
+    install.assert_any_call({'flit_core >=2,<3'})
+
+    required_cmd.assert_called_with('sdist')
+    install.assert_any_call(['dep1', 'dep2'])
+
     build_cmd.assert_called_with('sdist', '.')
-    install.assert_called_with({'flit_core >=2,<3'})
 
 
 def test_build_no_isolation_check_deps_empty(mocker, test_flit_path):
@@ -142,7 +152,7 @@ def test_build_no_isolation_with_check_deps(mocker, test_flit_path, missing_deps
 @pytest.mark.isolated
 def test_build_raises_build_exception(mocker, test_flit_path):
     error = mocker.patch('build.__main__._error')
-    mocker.patch('build.ProjectBuilder.build', side_effect=build.BuildException)
+    mocker.patch('build.ProjectBuilder.get_dependencies', side_effect=build.BuildException)
     mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
     build.__main__.build_package(test_flit_path, '.', ['sdist'])
@@ -153,7 +163,7 @@ def test_build_raises_build_exception(mocker, test_flit_path):
 @pytest.mark.isolated
 def test_build_raises_build_backend_exception(mocker, test_flit_path):
     error = mocker.patch('build.__main__._error')
-    mocker.patch('build.ProjectBuilder.build', side_effect=build.BuildBackendException)
+    mocker.patch('build.ProjectBuilder.get_dependencies', side_effect=build.BuildBackendException)
     mocker.patch('build.env._IsolatedEnvVenvPip.install')
 
     build.__main__.build_package(test_flit_path, '.', ['sdist'])