Skip to content

Commit

Permalink
Merge pull request #10495 from sbidoul/out-of-tree-build-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
pradyunsg committed Oct 2, 2021
2 parents 9c474d4 + 040cc39 commit a07bfb3
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 33 deletions.
26 changes: 14 additions & 12 deletions docs/html/cli/pip_install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -490,18 +490,20 @@ You can install local projects by specifying the project path to pip:
py -m pip install path/to/SomeProject
During regular installation, pip will copy the entire project directory to a
temporary location and install from there. The exception is that pip will
exclude .tox and .nox directories present in the top level of the project from
being copied. This approach is the cause of several performance and correctness
issues, so it is planned that pip 21.3 will change to install directly from the
local project directory. Depending on the build backend used by the project,
this may generate secondary build artifacts in the project directory, such as
the ``.egg-info`` and ``build`` directories in the case of the setuptools
backend.

To opt in to the future behavior, specify the ``--use-feature=in-tree-build``
option in pip's command line.
.. note::

Depending on the build backend used by the project, this may generate
secondary build artifacts in the project directory, such as the
``.egg-info`` and ``build`` directories in the case of the setuptools
backend.

Pip has a legacy behaviour that copies the entire project directory to a
temporary location and installs from there. This approach was the cause of
several performance and correctness issues, so it is now disabled by
default, and it is planned that pip 22.1 will remove it.

To opt in to the legacy behavior, specify the
``--use-deprecated=out-of-tree-build`` option in pip's command line.


.. _`editable-installs`:
Expand Down
3 changes: 3 additions & 0 deletions news/10495.removal.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
In-tree builds are now the default. ``--use-feature=in-tree-build`` is now
ignored. ``--use-deprecated=out-of-tree-build`` may be used temporarily to ease
the transition.
2 changes: 1 addition & 1 deletion src/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -973,7 +973,7 @@ def check_list_path_option(options: Values) -> None:
metavar="feature",
action="append",
default=[],
choices=["legacy-resolver"],
choices=["legacy-resolver", "out-of-tree-build"],
help=("Enable deprecated functionality, that will be removed in the future."),
)

Expand Down
17 changes: 16 additions & 1 deletion src/pip/_internal/cli/req_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.resolution.base import BaseResolver
from pip._internal.self_outdated_check import pip_self_version_check
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.temp_dir import (
TempDirectory,
TempDirectoryTypeRegistry,
Expand Down Expand Up @@ -260,6 +261,20 @@ def make_requirement_preparer(
"fast-deps has no effect when used with the legacy resolver."
)

in_tree_build = "out-of-tree-build" not in options.deprecated_features_enabled
if "in-tree-build" in options.features_enabled:
deprecated(
reason="In-tree builds are now the default.",
replacement="to remove the --use-feature=in-tree-build flag",
gone_in="22.1",
)
if "out-of-tree-build" in options.deprecated_features_enabled:
deprecated(
reason="Out-of-tree builds are deprecated.",
replacement=None,
gone_in="22.1",
)

return RequirementPreparer(
build_dir=temp_build_dir_path,
src_dir=options.src_dir,
Expand All @@ -272,7 +287,7 @@ def make_requirement_preparer(
require_hashes=options.require_hashes,
use_user_site=use_user_site,
lazy_wheel=lazy_wheel,
in_tree_build="in-tree-build" in options.features_enabled,
in_tree_build=in_tree_build,
)

@classmethod
Expand Down
15 changes: 2 additions & 13 deletions src/pip/_internal/operations/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
from pip._internal.network.session import PipSession
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.filesystem import copy2_fixed
from pip._internal.utils.hashes import Hashes, MissingHashes
from pip._internal.utils.logging import indent_log
Expand Down Expand Up @@ -197,19 +196,9 @@ def unpack_url(
#
# As further cleanup, _copy_source_tree and accompanying tests can
# be removed.
#
# TODO when use-deprecated=out-of-tree-build is removed
if link.is_existing_dir():
deprecated(
reason=(
"pip copied the source tree into a temporary directory "
"before building it. This is changing so that packages "
"are built in-place "
'within the original source tree ("in-tree build").'
),
replacement=None,
gone_in="21.3",
feature_flag="in-tree-build",
issue=7555,
)
if os.path.isdir(location):
rmtree(location)
_copy_source_tree(link.file_path, location)
Expand Down
3 changes: 2 additions & 1 deletion tests/functional/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def test_entrypoints_work(entrypoint, script):
)
)

script.pip("install", "-vvv", str(fake_pkg))
# expect_temp because pip install will generate fake_pkg.egg-info
script.pip("install", "-vvv", str(fake_pkg), expect_temp=True)
result = script.pip("-V")
result2 = script.run("fake_pip", "-V", allow_stderr_warning=True)
assert result.stdout == result2.stdout
Expand Down
21 changes: 17 additions & 4 deletions tests/functional/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,12 @@ def test_install_from_local_directory_with_symlinks_to_directories(script, data)
Test installing from a local directory containing symlinks to directories.
"""
to_install = data.packages.joinpath("symlinks")
result = script.pip("install", to_install)
result = script.pip(
"install",
"--use-deprecated=out-of-tree-build",
to_install,
allow_stderr_warning=True, # TODO: set to False when removing out-of-tree-build
)
pkg_folder = script.site_packages / "symlinks"
dist_info_folder = script.site_packages / "symlinks-0.1.dev0.dist-info"
result.did_create(pkg_folder)
Expand All @@ -597,10 +602,10 @@ def test_install_from_local_directory_with_symlinks_to_directories(script, data)
@pytest.mark.usefixtures("with_wheel")
def test_install_from_local_directory_with_in_tree_build(script, data):
"""
Test installing from a local directory with --use-feature=in-tree-build.
Test installing from a local directory with default in tree build.
"""
to_install = data.packages.joinpath("FSPkg")
args = ["install", "--use-feature=in-tree-build", to_install]
args = ["install", to_install]

in_tree_build_dir = to_install / "build"
assert not in_tree_build_dir.exists()
Expand All @@ -618,6 +623,8 @@ def test_install_from_local_directory_with_socket_file(script, data, tmpdir):
"""
Test installing from a local directory containing a socket file.
"""
# TODO: remove this test when removing out-of-tree-build support,
# it is only meant to test the copy of socket files
dist_info_folder = script.site_packages / "FSPkg-0.1.dev0.dist-info"
package_folder = script.site_packages / "fspkg"
to_copy = data.packages.joinpath("FSPkg")
Expand All @@ -628,7 +635,13 @@ def test_install_from_local_directory_with_socket_file(script, data, tmpdir):
socket_file_path = os.path.join(to_install, "example")
make_socket_file(socket_file_path)

result = script.pip("install", "--verbose", to_install)
result = script.pip(
"install",
"--use-deprecated=out-of-tree-build",
"--verbose",
to_install,
allow_stderr_warning=True, # because of the out-of-tree deprecation warning
)
result.did_create(package_folder)
result.did_create(dist_info_folder)
assert str(socket_file_path) in result.stderr
Expand Down
11 changes: 10 additions & 1 deletion tests/functional/test_uninstall.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from pip._internal.utils.misc import rmtree
from tests.lib import assert_all_changes, create_test_package_with_setup, need_svn
from tests.lib.local_repos import local_checkout, local_repo
from tests.lib.path import Path


@pytest.mark.network
Expand Down Expand Up @@ -279,7 +280,15 @@ def test_uninstall_console_scripts(script):
result = script.pip("install", pkg_path)
result.did_create(script.bin / "discover" + script.exe)
result2 = script.pip("uninstall", "discover", "-y")
assert_all_changes(result, result2, [script.venv / "build", "cache"])
assert_all_changes(
result,
result2,
[
script.venv / "build",
"cache",
Path("scratch") / "discover" / "discover.egg-info",
],
)


def test_uninstall_console_scripts_uppercase_name(script):
Expand Down

0 comments on commit a07bfb3

Please sign in to comment.