diff options
author | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2022-06-21 11:09:22 +0100 |
---|---|---|
committer | Anderson Bravalheri <andersonbravalheri@gmail.com> | 2022-06-21 11:37:13 +0100 |
commit | fd5fcbb1ec200ba2b0c657628a591ce2255998e3 (patch) | |
tree | e4c20ee26e15647978b9f0102d8d27d11197840a | |
parent | fd891afb3020eceab6d8528dfbc0d844865361d4 (diff) | |
download | python-setuptools-git-fd5fcbb1ec200ba2b0c657628a591ce2255998e3.tar.gz |
build_meta: Allow dist-info and egg-info to coexist
PEP 517 does not care if other directories/files are left behind in the
`metadata_directory`, as long as a `.dist_info` directory is produced at
the root. We can leave the `.egg-info` directory behind, so this way
we don't have to run it again when listing files from `build_py`.
-rw-r--r-- | setuptools/_path.py | 22 | ||||
-rw-r--r-- | setuptools/build_meta.py | 47 | ||||
-rw-r--r-- | setuptools/config/expand.py | 21 |
3 files changed, 45 insertions, 45 deletions
diff --git a/setuptools/_path.py b/setuptools/_path.py index ede9cb00..3767523b 100644 --- a/setuptools/_path.py +++ b/setuptools/_path.py @@ -1,7 +1,29 @@ import os +from typing import Union + +_Path = Union[str, os.PathLike] def ensure_directory(path): """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) os.makedirs(dirname, exist_ok=True) + + +def same_path(p1: _Path, p2: _Path) -> bool: + """Differs from os.path.samefile because it does not require paths to exist. + Purely string based (no comparison between i-nodes). + >>> same_path("a/b", "./a/b") + True + >>> same_path("a/b", "a/./b") + True + >>> same_path("a/b", "././a/b") + True + >>> same_path("a/b", "./a/b/c/..") + True + >>> same_path("a/b", "../a/b/c") + False + >>> same_path("a", "a/b") + False + """ + return os.path.normpath(p1) == os.path.normpath(p2) diff --git a/setuptools/build_meta.py b/setuptools/build_meta.py index f39a5a62..8e2af261 100644 --- a/setuptools/build_meta.py +++ b/setuptools/build_meta.py @@ -40,6 +40,7 @@ from typing import Dict, Iterator, List, Optional, Union import setuptools import distutils +from ._path import same_path from ._reqs import parse_strings from ._deprecation_warning import SetuptoolsDeprecationWarning from distutils.util import strtobool @@ -341,6 +342,23 @@ class _BuildMetaBackend(_ConfigSettingsTranslator): def get_requires_for_build_sdist(self, config_settings=None): return self._get_build_requires(config_settings, requirements=[]) + def _bubble_up_info_directory(self, metadata_directory: str, suffix: str) -> str: + """ + PEP 517 requires that the .dist-info directory be placed in the + metadata_directory. To comply, we MUST copy the directory to the root. + + Returns the basename of the info directory, e.g. `proj-0.0.0.dist-info`. + """ + candidates = list(Path(metadata_directory).glob(f"**/*{suffix}/")) + assert len(candidates) == 1, f"Exactly one {suffix} should have been produced" + info_dir = candidates[0] + + if not same_path(info_dir.parent, metadata_directory): + shutil.move(str(info_dir), metadata_directory) + # PEP 517 allow other files and dirs to exist in metadata_directory + + return info_dir.name + def prepare_metadata_for_build_wheel(self, metadata_directory, config_settings=None): sys.argv = [ @@ -348,36 +366,13 @@ class _BuildMetaBackend(_ConfigSettingsTranslator): *self._global_args(config_settings), "dist_info", "--output-dir", metadata_directory, + "--keep-egg-info", ] with no_install_setup_requires(): self.run_setup() - dist_info_directory = metadata_directory - while True: - dist_infos = [f for f in os.listdir(dist_info_directory) - if f.endswith('.dist-info')] - - if ( - len(dist_infos) == 0 and - len(_get_immediate_subdirectories(dist_info_directory)) == 1 - ): - - dist_info_directory = os.path.join( - dist_info_directory, os.listdir(dist_info_directory)[0]) - continue - - assert len(dist_infos) == 1 - break - - # PEP 517 requires that the .dist-info directory be placed in the - # metadata_directory. To comply, we MUST copy the directory to the root - if dist_info_directory != metadata_directory: - shutil.move( - os.path.join(dist_info_directory, dist_infos[0]), - metadata_directory) - shutil.rmtree(dist_info_directory, ignore_errors=True) - - return dist_infos[0] + self._bubble_up_info_directory(metadata_directory, ".egg-info") + return self._bubble_up_info_directory(metadata_directory, ".dist-info") def _build_with_temp_dir(self, setup_command, result_extension, result_directory, config_settings): diff --git a/setuptools/config/expand.py b/setuptools/config/expand.py index da55d4ee..6ea54969 100644 --- a/setuptools/config/expand.py +++ b/setuptools/config/expand.py @@ -43,6 +43,8 @@ from types import ModuleType from distutils.errors import DistutilsOptionError +from .._path import same_path as _same_path + if TYPE_CHECKING: from setuptools.dist import Distribution # noqa from setuptools.discovery import ConfigDiscovery # noqa @@ -330,25 +332,6 @@ def find_packages( return packages -def _same_path(p1: _Path, p2: _Path) -> bool: - """Differs from os.path.samefile because it does not require paths to exist. - Purely string based (no comparison between i-nodes). - >>> _same_path("a/b", "./a/b") - True - >>> _same_path("a/b", "a/./b") - True - >>> _same_path("a/b", "././a/b") - True - >>> _same_path("a/b", "./a/b/c/..") - True - >>> _same_path("a/b", "../a/b/c") - False - >>> _same_path("a", "a/b") - False - """ - return os.path.normpath(p1) == os.path.normpath(p2) - - def _nest_path(parent: _Path, path: _Path) -> str: path = parent if path in {".", ""} else os.path.join(parent, path) return os.path.normpath(path) |