summaryrefslogtreecommitdiff
path: root/setuptools
diff options
context:
space:
mode:
authorAnderson Bravalheri <andersonbravalheri@gmail.com>2022-04-11 19:24:35 +0100
committerAnderson Bravalheri <andersonbravalheri@gmail.com>2022-06-15 16:43:54 +0100
commitf3786f3453e4c4d2dde05beb53a5090b4b449aa2 (patch)
tree4842f3d5f8890977d3c0ccab22b4c57cca151eea /setuptools
parent008a7186929c01d1a1f17619db645764629e52f6 (diff)
downloadpython-setuptools-git-f3786f3453e4c4d2dde05beb53a5090b4b449aa2.tar.gz
Allow egg-info directory to be ignored in manifest
Diffstat (limited to 'setuptools')
-rw-r--r--setuptools/command/editable_wheel.py12
-rw-r--r--setuptools/command/egg_info.py13
-rw-r--r--setuptools/tests/test_editable_install.py28
3 files changed, 39 insertions, 14 deletions
diff --git a/setuptools/command/editable_wheel.py b/setuptools/command/editable_wheel.py
index d5a7d530..354f6b9f 100644
--- a/setuptools/command/editable_wheel.py
+++ b/setuptools/command/editable_wheel.py
@@ -47,6 +47,7 @@ class editable_wheel(Command):
user_options = [
("dist-dir=", "d", "directory to put final built distributions in"),
("dist-info-dir=", "I", "path to a pre-build .dist-info directory"),
+ ("strict", None, "perform an strict installation"),
]
boolean_options = ["strict"]
@@ -211,6 +212,9 @@ class _LinkTree(_StaticPth):
self.tmp = tmp
def _build_py(self):
+ if not self.dist.has_pure_modules():
+ return
+
build_py = self.dist.get_command_obj("build_py")
build_py.ensure_finalized()
# Force build_py to use links instead of copying files
@@ -218,6 +222,9 @@ class _LinkTree(_StaticPth):
build_py.run()
def _build_ext(self):
+ if not self.dist.has_ext_modules():
+ return
+
build_ext = self.dist.get_command_obj("build_ext")
build_ext.ensure_finalized()
# Extensions are not editable, so we just have to build them in the right dir
@@ -257,6 +264,11 @@ def _configure_build(name: str, dist: Distribution, target_dir: _Path, tmp_dir:
headers = str(Path(target_dir, f"{name}.data", "include"))
scripts = str(Path(target_dir, f"{name}.data", "scripts"))
+ # egg-info will be generated again to create a manifest (used for package data)
+ egg_info = dist.reinitialize_command("egg_info", reinit_subcommands=True)
+ egg_info.egg_base = str(tmp_dir)
+ egg_info.ignore_egg_info_in_manifest = True
+
build = dist.reinitialize_command("build", reinit_subcommands=True)
install = dist.reinitialize_command("install", reinit_subcommands=True)
diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py
index c37ab81f..0c9d45ae 100644
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -182,6 +182,7 @@ class egg_info(InfoCommon, Command):
self.egg_info = None
self.egg_version = None
self.broken_egg_info = False
+ self.ignore_egg_info_in_manifest = False
####################################
# allow the 'tag_svn_revision' to be detected and
@@ -311,6 +312,7 @@ class egg_info(InfoCommon, Command):
"""Generate SOURCES.txt manifest file"""
manifest_filename = os.path.join(self.egg_info, "SOURCES.txt")
mm = manifest_maker(self.distribution)
+ mm.ignore_egg_info_dir = self.ignore_egg_info_in_manifest
mm.manifest = manifest_filename
mm.run()
self.filelist = mm.filelist
@@ -334,6 +336,10 @@ class egg_info(InfoCommon, Command):
class FileList(_FileList):
# Implementations of the various MANIFEST.in commands
+ def __init__(self, warn=None, debug_print=None, ignore_egg_info_dir=False):
+ super().__init__(warn, debug_print)
+ self.ignore_egg_info_dir = ignore_egg_info_dir
+
def process_template_line(self, line):
# Parse the line: split it up, make sure the right number of words
# is there, and return the relevant words. 'action' is always
@@ -523,6 +529,10 @@ class FileList(_FileList):
return False
try:
+ # ignore egg-info paths
+ is_egg_info = ".egg-info" in u_path or b".egg-info" in utf8_path
+ if self.ignore_egg_info_dir and is_egg_info:
+ return False
# accept is either way checks out
if os.path.exists(u_path) or os.path.exists(utf8_path):
return True
@@ -539,12 +549,13 @@ class manifest_maker(sdist):
self.prune = 1
self.manifest_only = 1
self.force_manifest = 1
+ self.ignore_egg_info_dir = False
def finalize_options(self):
pass
def run(self):
- self.filelist = FileList()
+ self.filelist = FileList(ignore_egg_info_dir=self.ignore_egg_info_dir)
if not os.path.exists(self.manifest):
self.write_manifest() # it must exist so it'll get in the list
self.add_defaults()
diff --git a/setuptools/tests/test_editable_install.py b/setuptools/tests/test_editable_install.py
index f27c2e71..eb8f18ac 100644
--- a/setuptools/tests/test_editable_install.py
+++ b/setuptools/tests/test_editable_install.py
@@ -65,6 +65,8 @@ EXAMPLE = {
"MANIFEST.in": dedent("""\
global-include *.py *.txt
global-exclude *.py[cod]
+ prune dist
+ prune build
""").strip(),
"README.rst": "This is a ``README``",
"LICENSE.txt": "---- placeholder MIT license ----",
@@ -413,14 +415,9 @@ class TestOverallBehaviour:
version = "3.14159"
"""
- MANIFEST = """\
- global-include *.py *.txt
- global-exclude *.py[cod]
- """
-
FLAT_LAYOUT = {
"pyproject.toml": dedent(PYPROJECT),
- "MANIFEST.in": dedent(MANIFEST),
+ "MANIFEST.in": EXAMPLE["MANIFEST.in"],
"otherfile.py": "",
"mypkg": {
"__init__.py": "",
@@ -437,7 +434,7 @@ class TestOverallBehaviour:
"flat-layout": FLAT_LAYOUT,
"src-layout": {
"pyproject.toml": dedent(PYPROJECT),
- "MANIFEST.in": dedent(MANIFEST),
+ "MANIFEST.in": EXAMPLE["MANIFEST.in"],
"otherfile.py": "",
"src": {"mypkg": FLAT_LAYOUT["mypkg"]},
},
@@ -449,7 +446,7 @@ class TestOverallBehaviour:
[tool.setuptools.package-dir]
"mypkg.subpackage" = "other"
"""),
- "MANIFEST.in": dedent(MANIFEST),
+ "MANIFEST.in": EXAMPLE["MANIFEST.in"],
"otherfile.py": "",
"mypkg": {
"__init__.py": "",
@@ -459,7 +456,7 @@ class TestOverallBehaviour:
},
"namespace": {
"pyproject.toml": dedent(PYPROJECT),
- "MANIFEST.in": dedent(MANIFEST),
+ "MANIFEST.in": EXAMPLE["MANIFEST.in"],
"otherfile.py": "",
"src": {
"mypkg": {
@@ -525,7 +522,7 @@ class TestLinkTree:
FILES["pyproject.toml"] += dedent("""\
[tool.setuptools.packages.find]
where = ["src"]
- exclude = ["*.subpackage.*"]
+ exclude = ["*.subpackage*"]
""")
FILES["src"]["mypkg"]["resource.not_in_manifest"] = "abc"
@@ -538,19 +535,24 @@ class TestLinkTree:
dist.parse_config_files()
build = tmp_path / ".build"
+ tmp = tmp_path / ".tmp"
+ tmp.mkdir()
unpacked = tmp_path / ".unpacked"
unpacked.mkdir()
- make_tree = _LinkTree(dist, name, build, tmp_path / ".tmp")
+ make_tree = _LinkTree(dist, name, build, tmp)
make_tree(unpacked)
mod1 = next(build.glob("**/mod1.py"))
- assert str(mod1.resolve()) == str((tmp_path / "mypkg/mod1.py").resolve())
+ expected = tmp_path / "src/mypkg/mod1.py"
+ assert str(mod1.resolve()) == str(expected.resolve())
with pytest.raises(AssertionError): # ignore problems caused by #3260
+ # Ensure excluded packages don't show up
assert next(build.glob("**/subpackage"), None) is None
assert next(build.glob("**/mod2.py"), None) is None
assert next(build.glob("**/resource_file.txt"), None) is None
+
assert next(build.glob("**/resource.not_in_manifest"), None) is None
def test_strict_install(self, tmp_path, venv, monkeypatch):
@@ -569,7 +571,7 @@ class TestLinkTree:
"""
out = venv.run(["python", "-c", dedent(cmd_import_error)])
with pytest.raises(AssertionError): # ignore problems caused by #3260
- assert b"No module named 'mypkg.subpackage'" in out
+ assert b"cannot import name 'subpackage'" in out
# Ensure resource files excluded from distribution are not reachable
cmd_get_resource = """\