Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate legacy metadata in temporary directory #7978

Merged
merged 4 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 18 additions & 63 deletions src/pip/_internal/operations/build/metadata_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,84 +5,44 @@
import os

from pip._internal.exceptions import InstallationError
from pip._internal.utils.misc import ensure_dir
from pip._internal.utils.setuptools_build import make_setuptools_egg_info_args
from pip._internal.utils.subprocess import call_subprocess
from pip._internal.utils.temp_dir import TempDirectory
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
from pip._internal.vcs import vcs

if MYPY_CHECK_RUNNING:
from typing import List, Optional

from pip._internal.build_env import BuildEnvironment

logger = logging.getLogger(__name__)


def _find_egg_info(source_directory, is_editable):
# type: (str, bool) -> str
"""Find an .egg-info in `source_directory`, based on `is_editable`.
def _find_egg_info(directory):
# type: (str) -> str
"""Find an .egg-info subdirectory in `directory`.
"""

def looks_like_virtual_env(path):
# type: (str) -> bool
return (
os.path.lexists(os.path.join(path, 'bin', 'python')) or
os.path.exists(os.path.join(path, 'Scripts', 'Python.exe'))
)

def locate_editable_egg_info(base):
# type: (str) -> List[str]
candidates = [] # type: List[str]
for root, dirs, files in os.walk(base):
for dir_ in vcs.dirnames:
if dir_ in dirs:
dirs.remove(dir_)
# Iterate over a copy of ``dirs``, since mutating
# a list while iterating over it can cause trouble.
# (See https://github.com/pypa/pip/pull/462.)
for dir_ in list(dirs):
if looks_like_virtual_env(os.path.join(root, dir_)):
dirs.remove(dir_)
# Also don't search through tests
elif dir_ == 'test' or dir_ == 'tests':
dirs.remove(dir_)
candidates.extend(os.path.join(root, dir_) for dir_ in dirs)
return [f for f in candidates if f.endswith('.egg-info')]

def depth_of_directory(dir_):
# type: (str) -> int
return (
dir_.count(os.path.sep) +
(os.path.altsep and dir_.count(os.path.altsep) or 0)
)

base = source_directory
if is_editable:
filenames = locate_editable_egg_info(base)
else:
base = os.path.join(base, 'pip-egg-info')
filenames = os.listdir(base)
filenames = [
f for f in os.listdir(directory) if f.endswith(".egg-info")
]

if not filenames:
raise InstallationError(
"Files/directories not found in {}".format(base)
"No .egg-info directory found in {}".format(directory)
)

# If we have more than one match, we pick the toplevel one. This
# can easily be the case if there is a dist folder which contains
# an extracted tarball for testing purposes.
if len(filenames) > 1:
filenames.sort(key=depth_of_directory)
raise InstallationError(
"More than one .egg-info directory found in {}".format(
directory
)
)

return os.path.join(base, filenames[0])
return os.path.join(directory, filenames[0])


def generate_metadata(
build_env, # type: BuildEnvironment
setup_py_path, # type: str
source_dir, # type: str
editable, # type: bool
isolated, # type: bool
details, # type: str
):
Expand All @@ -96,14 +56,9 @@ def generate_metadata(
setup_py_path, details,
)

egg_info_dir = None # type: Optional[str]
# For non-editable installs, don't put the .egg-info files at the root,
# to avoid confusion due to the source code being considered an installed
# egg.
if not editable:
egg_info_dir = os.path.join(source_dir, 'pip-egg-info')
# setuptools complains if the target directory does not exist.
ensure_dir(egg_info_dir)
egg_info_dir = TempDirectory(
kind="pip-egg-info", globally_managed=True
).path

args = make_setuptools_egg_info_args(
setup_py_path,
Expand All @@ -119,4 +74,4 @@ def generate_metadata(
)

# Return the .egg-info directory.
return _find_egg_info(source_dir, editable)
return _find_egg_info(egg_info_dir)
3 changes: 0 additions & 3 deletions src/pip/_internal/req/req_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,6 @@ def _generate_metadata(self):
build_env=self.build_env,
setup_py_path=self.setup_py_path,
source_dir=self.unpacked_source_directory,
editable=self.editable,
isolated=self.isolated,
details=self.name or "from {}".format(self.link)
)
Expand Down Expand Up @@ -729,8 +728,6 @@ def archive(self, build_dir):
os.path.abspath(self.unpacked_source_directory)
)
for dirpath, dirnames, filenames in os.walk(dir):
if 'pip-egg-info' in dirnames:
dirnames.remove('pip-egg-info')
for dirname in dirnames:
dir_arcname = self._get_archive_name(
dirname, parentdir=dirpath, rootdir=dir,
Expand Down
6 changes: 3 additions & 3 deletions src/pip/_internal/utils/setuptools_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ def make_setuptools_egg_info_args(
no_user_config, # type: bool
):
# type: (...) -> List[str]
args = make_setuptools_shim_args(setup_py_path)
if no_user_config:
args += ["--no-user-cfg"]
args = make_setuptools_shim_args(
setup_py_path, no_user_config=no_user_config
)

args += ["egg_info"]

Expand Down