Skip to content

Commit

Permalink
Add always-install-via-wheel feature
Browse files Browse the repository at this point in the history
--no-binary does not disable wheel building anymore, so a wheel
is built during the install process and setup.py install is
not used anymore in this case

--build-option and --global-option are passed to setup.py bdist_wheel
in the pip install command, like it is done in the pip wheel command.
  • Loading branch information
sbidoul committed Apr 6, 2021
1 parent 2c805ef commit d8c4571
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 12 deletions.
9 changes: 7 additions & 2 deletions docs/html/cli/pip_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,9 @@ Per-requirement Overrides
-------------------------

Since version 7.0 pip supports controlling the command line options given to
``setup.py`` via requirements files. This disables the use of wheels (cached or
otherwise) for that package, as ``setup.py`` does not exist for wheels.
``setup.py`` via requirements files. Unless the ``always-install-via-wheel``
feature is enabled, this disables the use of wheels (cached or otherwise),
as ``setup.py`` does not exist for wheels.

The ``--global-option`` and ``--install-option`` options are used to pass
options to ``setup.py``. For example:
Expand All @@ -334,6 +335,10 @@ script as:

python setup.py --no-user-cfg install --prefix='/usr/local' --no-compile

When the ``always-install-via-wheel`` feature is enabled, ``--install-option``
is ignored, and ``--global-option`` is passed to the ``setup.py bdist_wheel``
command that is used to create a wheel that will be installed.

Note that the only way of giving more than one option to ``setup.py``
is through multiple ``--global-option`` and ``--install-option``
options, as shown in the example above. The value of each option is
Expand Down
11 changes: 11 additions & 0 deletions news/9778.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Add an experimental ``always-install-via-wheel`` feature flag. When enabled, it has the
following effects:

- Installation of source distributions is always done by first building a wheel
then installing from it (assuming the ``wheel`` package is installed).
- ``--no-binary`` now only means "do not download wheels" and
"do not use the wheel cache", whereas before it also
implied using the legacy ``setup.py install``.
- ``--build-option`` and ``--global-option`` are passed to ``setup.py bdist_wheel``
during installation, as it was already done when using ``pip wheel``.
- ``--install-option`` is ignored (because there is no ``setup.py install`` involved)
20 changes: 14 additions & 6 deletions src/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,15 @@ def no_binary():
callback=_handle_no_binary,
type="str",
default=format_control,
help="Do not use binary packages. Can be supplied multiple times, and "
help="Do not download binary packages nor use the wheel cache. "
"Can be supplied multiple times, and "
'each time adds to the existing value. Accepts either ":all:" to '
'disable all binary packages, ":none:" to empty the set (notice '
"the colons), or one or more package names with commas between "
"them (no colons). Note that some packages are tricky to compile "
"and may fail to install when this option is used on them.",
"and may fail to install when this option is used on them. "
"Additionally, this option forces the use of the legacy 'setup.py install' "
"path, unless the 'always-install-via-wheel' feature is enabled.",
)


Expand Down Expand Up @@ -821,7 +824,8 @@ def _handle_no_use_pep517(option, opt, value, parser):
'command (use like --install-option="--install-scripts=/usr/local/'
'bin"). Use multiple --install-option options to pass multiple '
"options to setup.py install. If you are using an option with a "
"directory path, be sure to use absolute path.",
"directory path, be sure to use absolute path. "
"This option implies '--no-binary :all:'.",
) # type: Callable[..., Option]

build_options = partial(
Expand All @@ -830,7 +834,10 @@ def _handle_no_use_pep517(option, opt, value, parser):
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'. "
"This option implies '--no-binary :all:'."
"This option is ignored by the 'pip install' command unless the "
"'always-install-via-wheel' feature is enabled.",
) # type: Callable[..., Option]

global_options = partial(
Expand All @@ -840,7 +847,8 @@ def _handle_no_use_pep517(option, opt, value, parser):
action="append",
metavar="options",
help="Extra global options to be supplied to the setup.py "
"call before the install or bdist_wheel command.",
"call before the install or bdist_wheel command. "
"This option implies '--no-binary :all:'.",
) # type: Callable[..., Option]

no_clean = partial(
Expand Down Expand Up @@ -965,7 +973,7 @@ def check_list_path_option(options):
metavar="feature",
action="append",
default=[],
choices=["2020-resolver", "fast-deps", "in-tree-build"],
choices=["2020-resolver", "fast-deps", "in-tree-build", "always-install-via-wheel"],
help="Enable new functionality, that may be backward incompatible.",
) # type: Callable[..., Option]

Expand Down
8 changes: 5 additions & 3 deletions src/pip/_internal/commands/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,12 @@
logger = logging.getLogger(__name__)


def get_check_binary_allowed(format_control):
# type: (FormatControl) -> BinaryAllowedPredicate
def get_check_binary_allowed(format_control, features_enabled):
# type: (FormatControl, List[str]) -> BinaryAllowedPredicate
def check_binary_allowed(req):
# type: (InstallRequirement) -> bool
if "always-install-via-wheel" in features_enabled:
return True
canonical_name = canonicalize_name(req.name or "")
allowed_formats = format_control.get_allowed_formats(canonical_name)
return "binary" in allowed_formats
Expand Down Expand Up @@ -330,7 +332,7 @@ def run(self, options, args):
)

check_binary_allowed = get_check_binary_allowed(
finder.format_control
finder.format_control, options.features_enabled
)

reqs_to_build = [
Expand Down
2 changes: 1 addition & 1 deletion src/pip/_internal/wheel_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def _should_build(

if not check_binary_allowed(req):
logger.info(
"Skipping wheel build for %s, due to binaries "
"Using legacy 'setup.py install' for %s, due to binaries "
"being disabled for it.", req.name,
)
return False
Expand Down
22 changes: 22 additions & 0 deletions tests/functional/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,17 @@ def test_install_global_option(script):
assert not result.files_created


def test_install_global_option_does_not_disable_wheel_building(
script, data, with_wheel
):
res = script.pip(
'install', '--no-index', '--global-option=-v', '-f', data.find_links,
'--use-feature=always-install-via-wheel',
'upper', expect_stderr=True)
assert "Successfully installed upper-2.0" in str(res), str(res)
assert "Building wheel for upper" in str(res), str(res)


def test_install_with_hacked_egg_info(script, data):
"""
test installing a package which defines its own egg_info class
Expand Down Expand Up @@ -1439,6 +1450,17 @@ def test_install_no_binary_disables_building_wheels(script, data, with_wheel):
assert "Running setup.py install for upper" in str(res), str(res)


def test_install_no_binary_does_not_disable_building_wheels(
script, data, with_wheel
):
res = script.pip(
'install', '--no-index', '--no-binary=upper', '-f', data.find_links,
'--use-feature=always-install-via-wheel',
'upper', expect_stderr=True)
assert "Successfully installed upper-2.0" in str(res), str(res)
assert "Building wheel for upper" in str(res), str(res)


@pytest.mark.network
def test_install_no_binary_builds_pep_517_wheel(script, data, with_wheel):
to_install = data.packages.joinpath('pep517_setup_and_pyproject')
Expand Down

0 comments on commit d8c4571

Please sign in to comment.