diff --git a/MANIFEST.in b/MANIFEST.in index cb6ce2300e..0643e7ee2d 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -19,4 +19,3 @@ include tox.ini include setuptools/tests/config/setupcfg_examples.txt include setuptools/config/*.schema.json global-exclude *.py[cod] __pycache__ -prune .tox diff --git a/setuptools/command/egg_info.py b/setuptools/command/egg_info.py index 09255a3240..280eb5e807 100644 --- a/setuptools/command/egg_info.py +++ b/setuptools/command/egg_info.py @@ -606,16 +606,6 @@ def _add_referenced_files(self): log.debug("adding file referenced by config '%s'", rf) self.filelist.extend(referenced) - def prune_file_list(self): - build = self.get_finalized_command('build') - base_dir = self.distribution.get_fullname() - self.filelist.prune(build.build_base) - self.filelist.prune(base_dir) - sep = re.escape(os.sep) - self.filelist.exclude_pattern( - r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep, is_regex=True - ) - def _safe_data_files(self, build_py): """ The parent class implementation of this method diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 68afab89b4..fa9a2c4d81 100644 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -2,6 +2,7 @@ import contextlib import os +import re from itertools import chain from .._importlib import metadata @@ -156,6 +157,12 @@ def _add_defaults_data_files(self): except TypeError: log.warn("data_files contains unexpected objects") + def prune_file_list(self): + super().prune_file_list() + # Prevent accidental inclusion of test-related cache dirs at the project root + sep = re.escape(os.sep) + self.filelist.exclude_pattern(r"^(\.tox|\.nox|\.venv)" + sep, is_regex=True) + def check_readme(self): for f in self.READMES: if os.path.exists(f): diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py index 7fc9dae872..f628f3eb4a 100644 --- a/setuptools/tests/test_sdist.py +++ b/setuptools/tests/test_sdist.py @@ -9,6 +9,7 @@ import tempfile import unicodedata from inspect import cleandoc +from pathlib import Path from unittest import mock import jaraco.path @@ -425,6 +426,46 @@ def test_defaults_case_sensitivity(self, source_dir): assert 'setup.py' not in manifest, manifest assert 'setup.cfg' not in manifest, manifest + def test_exclude_dev_only_cache_folders(self, source_dir): + included = { + # Emulate problem in https://github.com/pypa/setuptools/issues/4601 + "MANIFEST.in": ( + "global-include LICEN[CS]E* COPYING* NOTICE* AUTHORS*\n" + "global-include *.txt\n" + ), + # For the sake of being conservative and limiting unforeseen side-effects + # we just exclude dev-only cache folders at the root of the repository: + "test/.venv/lib/python3.9/site-packages/bar-2.dist-info/AUTHORS.rst": "", + "src/.nox/py/lib/python3.12/site-packages/bar-2.dist-info/COPYING.txt": "", + "doc/.tox/default/lib/python3.11/site-packages/foo-4.dist-info/LICENSE": "", + # Let's test against false positives with similarly named files: + ".venv-requirements.txt": "", + ".tox-coveragerc.txt": "", + ".noxy/coveragerc.txt": "", + } + + excluded = { + # .tox/.nox/.venv are well-know folders present at the root of Python repos + # and therefore should be excluded + ".tox/release/lib/python3.11/site-packages/foo-4.dist-info/LICENSE": "", + ".nox/py/lib/python3.12/site-packages/bar-2.dist-info/COPYING.txt": "", + ".venv/lib/python3.9/site-packages/bar-2.dist-info/AUTHORS.rst": "", + } + + for file, content in {**excluded, **included}.items(): + Path(source_dir, file).parent.mkdir(parents=True, exist_ok=True) + Path(source_dir, file).write_text(content, encoding="utf-8") + + cmd = self.setup_with_extension() + self.assert_package_data_in_manifest(cmd) + manifest = {f.replace(os.sep, '/') for f in cmd.filelist.files} + for path in excluded: + assert os.path.exists(path) + assert path not in manifest, (path, manifest) + for path in included: + assert os.path.exists(path) + assert path in manifest, (path, manifest) + @fail_on_ascii def test_manifest_is_written_with_utf8_encoding(self): # Test for #303. @@ -915,4 +956,4 @@ def test_sanity_check_setuptools_own_sdist(setuptools_sdist): # setuptools sdist should not include the .tox folder tox_files = [name for name in files if ".tox" in name] - assert len(tox_files) == 0 + assert len(tox_files) == 0, f"not empty {tox_files}"