From c08d4cc806897de687785c723ac7b767c1bc2711 Mon Sep 17 00:00:00 2001 From: Pradyun Gedam Date: Sun, 4 Mar 2018 17:10:09 +0530 Subject: [PATCH] Add --no-build-isolation for disabling build isolation --- src/pip/_internal/cmdoptions.py | 11 +++++++++++ src/pip/_internal/commands/download.py | 2 ++ src/pip/_internal/commands/install.py | 2 ++ src/pip/_internal/commands/wheel.py | 5 ++++- src/pip/_internal/operations/prepare.py | 19 +++++++++++-------- tests/functional/test_wheel.py | 14 ++++++++++++++ tests/unit/test_req.py | 3 ++- 7 files changed, 46 insertions(+), 10 deletions(-) diff --git a/src/pip/_internal/cmdoptions.py b/src/pip/_internal/cmdoptions.py index 8d01fab7282..17d9e0ac34d 100644 --- a/src/pip/_internal/cmdoptions.py +++ b/src/pip/_internal/cmdoptions.py @@ -451,6 +451,17 @@ def only_binary(): help='Ignore the Requires-Python information.' ) # type: Any +no_build_isolation = partial( + Option, + '--no-build-isolation', + dest='build_isolation', + action='store_false', + default=True, + help='Disable isolation when building a modern source distribution. ' + 'Build dependencies specified by PEP 518 must be already installed ' + 'if this option is used.' +) # type: Any + install_options = partial( Option, '--install-option', diff --git a/src/pip/_internal/commands/download.py b/src/pip/_internal/commands/download.py index f05f6447c2a..5713d07ce5d 100644 --- a/src/pip/_internal/commands/download.py +++ b/src/pip/_internal/commands/download.py @@ -57,6 +57,7 @@ def __init__(self, *args, **kw): cmd_opts.add_option(cmdoptions.no_clean()) cmd_opts.add_option(cmdoptions.require_hashes()) cmd_opts.add_option(cmdoptions.progress_bar()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) cmd_opts.add_option( '-d', '--dest', '--destination-dir', '--destination-directory', @@ -201,6 +202,7 @@ def run(self, options, args): download_dir=options.download_dir, wheel_download_dir=None, progress_bar=options.progress_bar, + build_isolation=options.build_isolation, ) resolver = Resolver( diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index e1513994b38..c7dfb833dc5 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -139,6 +139,7 @@ def __init__(self, *args, **kw): help='Ignore the installed packages (reinstalling instead).') cmd_opts.add_option(cmdoptions.ignore_requires_python()) + cmd_opts.add_option(cmdoptions.no_build_isolation()) cmd_opts.add_option(cmdoptions.install_options()) cmd_opts.add_option(cmdoptions.global_options()) @@ -260,6 +261,7 @@ def run(self, options, args): download_dir=None, wheel_download_dir=None, progress_bar=options.progress_bar, + build_isolation=options.build_isolation, ) resolver = Resolver( diff --git a/src/pip/_internal/commands/wheel.py b/src/pip/_internal/commands/wheel.py index 17c18796f8e..8a85d873001 100644 --- a/src/pip/_internal/commands/wheel.py +++ b/src/pip/_internal/commands/wheel.py @@ -63,7 +63,9 @@ def __init__(self, *args, **kw): dest='build_options', metavar='options', action='append', - help="Extra arguments to be supplied to 'setup.py bdist_wheel'.") + help="Extra arguments to be supplied to 'setup.py bdist_wheel'.", + ) + cmd_opts.add_option(cmdoptions.no_build_isolation()) cmd_opts.add_option(cmdoptions.constraints()) cmd_opts.add_option(cmdoptions.editable()) cmd_opts.add_option(cmdoptions.requirements()) @@ -158,6 +160,7 @@ def run(self, options, args): download_dir=None, wheel_download_dir=options.wheel_dir, progress_bar=options.progress_bar, + build_isolation=options.build_isolation, ) resolver = Resolver( diff --git a/src/pip/_internal/operations/prepare.py b/src/pip/_internal/operations/prepare.py index 86e2e7b9954..429b701724d 100644 --- a/src/pip/_internal/operations/prepare.py +++ b/src/pip/_internal/operations/prepare.py @@ -104,7 +104,7 @@ def dist(self, finder): return list(pkg_resources.find_distributions( self.req.source_dir))[0] - def prep_for_dist(self, finder): + def prep_for_dist(self, finder, build_isolation): # FIXME:https://github.com/pypa/pip/issues/1112 pass @@ -120,11 +120,11 @@ def dist(self, finder): ) return dist - def prep_for_dist(self, finder): + def prep_for_dist(self, finder, build_isolation): # Before calling "setup.py egg_info", we need to set-up the build # environment. - build_requirements, isolate = self.req.get_pep_518_info() + should_isolate = build_isolation and isolate if 'setuptools' not in build_requirements: logger.warning( @@ -132,11 +132,11 @@ def prep_for_dist(self, finder): "it cannot build a wheel without setuptools. You may need to " "upgrade to a newer version of pip.") - if not isolate: + if not should_isolate: self.req.build_env = NoOpBuildEnvironment(no_clean=False) with self.req.build_env as prefix: - if isolate: + if should_isolate: _install_build_reqs(finder, prefix, build_requirements) self.req.run_egg_info() @@ -157,7 +157,7 @@ class RequirementPreparer(object): """ def __init__(self, build_dir, download_dir, src_dir, wheel_download_dir, - progress_bar): + progress_bar, build_isolation): super(RequirementPreparer, self).__init__() self.src_dir = src_dir @@ -181,6 +181,9 @@ def __init__(self, build_dir, download_dir, src_dir, wheel_download_dir, self.progress_bar = progress_bar + # Is build isolation allowed? + self.build_isolation = build_isolation + @property def _download_should_save(self): # TODO: Modify to reduce indentation needed @@ -306,7 +309,7 @@ def prepare_linked_requirement(self, req, session, finder, (req, exc, req.link) ) abstract_dist = make_abstract_dist(req) - abstract_dist.prep_for_dist(finder) + abstract_dist.prep_for_dist(finder, self.build_isolation) if self._download_should_save: # Make a .zip of the source_dir we already created. if req.link.scheme in vcs.all_schemes: @@ -331,7 +334,7 @@ def prepare_editable_requirement(self, req, require_hashes, finder): req.update_editable(not self._download_should_save) abstract_dist = make_abstract_dist(req) - abstract_dist.prep_for_dist(finder) + abstract_dist.prep_for_dist(finder, self.build_isolation) if self._download_should_save: req.archive(self.download_dir) diff --git a/tests/functional/test_wheel.py b/tests/functional/test_wheel.py index 32d1df95e1c..a50811b115f 100644 --- a/tests/functional/test_wheel.py +++ b/tests/functional/test_wheel.py @@ -222,3 +222,17 @@ def test_pip_wheel_with_pep518_build_reqs(script, data): assert wheel_file_path in result.files_created, result.stdout assert "Successfully built pep518" in result.stdout, result.stdout assert "Installing build dependencies" in result.stdout, result.stdout + + +@pytest.mark.network +def test_pip_wheel_with_pep518_build_reqs_no_isolation(script, data): + script.pip('install', 'wheel') + result = script.pip( + 'wheel', '--no-index', '-f', data.find_links, '--no-build-isolation', + 'pep518==3.0', + ) + wheel_file_name = 'pep518-3.0-py%s-none-any.whl' % pyversion[0] + wheel_file_path = script.scratch / wheel_file_name + assert wheel_file_path in result.files_created, result.stdout + assert "Successfully built pep518" in result.stdout, result.stdout + assert "Installing build dependencies" not in result.stdout, result.stdout diff --git a/tests/unit/test_req.py b/tests/unit/test_req.py index dfecd4c8424..b04fb83a35c 100644 --- a/tests/unit/test_req.py +++ b/tests/unit/test_req.py @@ -39,7 +39,8 @@ def _basic_resolver(self, finder): src_dir=os.path.join(self.tempdir, 'src'), download_dir=None, wheel_download_dir=None, - progress_bar="on" + progress_bar="on", + build_isolation=True, ) return Resolver( preparer=preparer, wheel_cache=None,