Skip to content

Commit 4416409

Browse files
authored
Merge pull request #2844 from abravalheri/fix-1461
Fix 1461: Better loop breaker for `manifest_maker`
2 parents 2ef757e + 6757e38 commit 4416409

File tree

6 files changed

+59
-5
lines changed

6 files changed

+59
-5
lines changed

bootstrap.egg-info/entry_points.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
[distutils.commands]
22
egg_info = setuptools.command.egg_info:egg_info
3+
build_py = setuptools.command.build_py:build_py
4+
sdist = setuptools.command.sdist:sdist
35

46
[distutils.setup_keywords]
57
include_package_data = setuptools.dist:assert_bool
68
install_requires = setuptools.dist:check_requirements
79
extras_require = setuptools.dist:check_extras
810
entry_points = setuptools.dist:check_entry_points
11+
exclude_package_data = setuptools.dist:check_package_data
12+
namespace_packages = setuptools.dist:check_nsp
913

1014
[egg_info.writers]
1115
PKG-INFO = setuptools.command.egg_info:write_pkg_info

changelog.d/1461.change.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix inconsistency with ``include_package_data`` and ``packages_data`` in sdist
2+
by replacing the loop breaking mechanism between the ``sdist`` and
3+
``egg_info`` commands -- by :user:`abravalheri`

setuptools/command/build_py.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,16 @@ def _get_data_files(self):
6767
self.analyze_manifest()
6868
return list(map(self._get_pkg_data_files, self.packages or ()))
6969

70+
def get_data_files_without_manifest(self):
71+
"""
72+
Generate list of ``(package,src_dir,build_dir,filenames)`` tuples,
73+
but without triggering any attempt to analyze or build the manifest.
74+
"""
75+
# Prevent eventual errors from unset `manifest_files`
76+
# (that would otherwise be set by `analyze_manifest`)
77+
self.__dict__.setdefault('manifest_files', {})
78+
return list(map(self._get_pkg_data_files, self.packages or ()))
79+
7080
def _get_pkg_data_files(self, package):
7181
# Locate package source directory
7282
src_dir = self.get_package_dir(package)

setuptools/command/egg_info.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,18 @@ def prune_file_list(self):
608608
self.filelist.exclude_pattern(r'(^|' + sep + r')(RCS|CVS|\.svn)' + sep,
609609
is_regex=1)
610610

611+
def _safe_data_files(self, build_py):
612+
"""
613+
The parent class implementation of this method
614+
(``sdist``) will try to include data files, which
615+
might cause recursion problems when
616+
``include_package_data=True``.
617+
618+
Therefore, avoid triggering any attempt of
619+
analyzing/building the manifest again.
620+
"""
621+
return build_py.get_data_files_without_manifest()
622+
611623

612624
def write_file(filename, contents):
613625
"""Create a file with the specified name and write 'contents' (a

setuptools/command/sdist.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,15 @@ def _add_defaults_python(self):
114114

115115
def _safe_data_files(self, build_py):
116116
"""
117-
Extracting data_files from build_py is known to cause
118-
infinite recursion errors when `include_package_data`
119-
is enabled, so suppress it in that case.
117+
Since the ``sdist`` class is also used to compute the MANIFEST
118+
(via :obj:`setuptools.command.egg_info.manifest_maker`),
119+
there might be recursion problems when trying to obtain the list of
120+
data_files and ``include_package_data=True`` (which in turn depends on
121+
the files included in the MANIFEST).
122+
123+
To avoid that, ``manifest_maker`` should be able to overwrite this
124+
method and avoid recursive attempts to build/analyze the MANIFEST.
120125
"""
121-
if self.distribution.include_package_data:
122-
return ()
123126
return build_py.data_files
124127

125128
def _add_data_files(self, data_files):

setuptools/tests/test_sdist.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,28 @@ def test_package_data_in_sdist(self):
126126
assert os.path.join('sdist_test', 'c.rst') not in manifest
127127
assert os.path.join('d', 'e.dat') in manifest
128128

129+
def test_package_data_and_include_package_data_in_sdist(self):
130+
"""
131+
Ensure package_data and include_package_data work
132+
together.
133+
"""
134+
setup_attrs = {**SETUP_ATTRS, 'include_package_data': True}
135+
assert setup_attrs['package_data']
136+
137+
dist = Distribution(setup_attrs)
138+
dist.script_name = 'setup.py'
139+
cmd = sdist(dist)
140+
cmd.ensure_finalized()
141+
142+
with quiet():
143+
cmd.run()
144+
145+
manifest = cmd.filelist.files
146+
assert os.path.join('sdist_test', 'a.txt') in manifest
147+
assert os.path.join('sdist_test', 'b.txt') in manifest
148+
assert os.path.join('sdist_test', 'c.rst') not in manifest
149+
assert os.path.join('d', 'e.dat') in manifest
150+
129151
def test_setup_py_exists(self):
130152
dist = Distribution(SETUP_ATTRS)
131153
dist.script_name = 'foo.py'

0 commit comments

Comments
 (0)