Skip to content

Commit 51eb5a1

Browse files
authored
Merge pull request #2855 from abravalheri/fix-2849
Fix 2849: Problem with custom commands inheriting directly from `distutils`
2 parents cc80157 + 748d00e commit 51eb5a1

File tree

3 files changed

+73
-11
lines changed

3 files changed

+73
-11
lines changed

changelog.d/2849.misc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add fallback for custom ``build_py`` commands inheriting directly from
2+
:mod:`distutils`, while still handling ``include_package_data=True`` for
3+
``sdist``.

setuptools/command/egg_info.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,15 @@ def _safe_data_files(self, build_py):
618618
Therefore, avoid triggering any attempt of
619619
analyzing/building the manifest again.
620620
"""
621-
return build_py.get_data_files_without_manifest()
621+
if hasattr(build_py, 'get_data_files_without_manifest'):
622+
return build_py.get_data_files_without_manifest()
623+
624+
log.warn(
625+
"Custom 'build_py' does not implement "
626+
"'get_data_files_without_manifest'.\nPlease extend command classes"
627+
" from setuptools instead of distutils."
628+
)
629+
return build_py.get_data_files()
622630

623631

624632
def write_file(filename, contents):

setuptools/tests/test_sdist.py

Lines changed: 61 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import unicodedata
77
import contextlib
88
import io
9+
from unittest import mock
910

1011
import pytest
1112

@@ -106,6 +107,13 @@ def source_dir(self, tmpdir):
106107
with tmpdir.as_cwd():
107108
yield
108109

110+
def assert_package_data_in_manifest(self, cmd):
111+
manifest = cmd.filelist.files
112+
assert os.path.join('sdist_test', 'a.txt') in manifest
113+
assert os.path.join('sdist_test', 'b.txt') in manifest
114+
assert os.path.join('sdist_test', 'c.rst') not in manifest
115+
assert os.path.join('d', 'e.dat') in manifest
116+
109117
def test_package_data_in_sdist(self):
110118
"""Regression test for pull request #4: ensures that files listed in
111119
package_data are included in the manifest even if they're not added to
@@ -120,11 +128,7 @@ def test_package_data_in_sdist(self):
120128
with quiet():
121129
cmd.run()
122130

123-
manifest = cmd.filelist.files
124-
assert os.path.join('sdist_test', 'a.txt') in manifest
125-
assert os.path.join('sdist_test', 'b.txt') in manifest
126-
assert os.path.join('sdist_test', 'c.rst') not in manifest
127-
assert os.path.join('d', 'e.dat') in manifest
131+
self.assert_package_data_in_manifest(cmd)
128132

129133
def test_package_data_and_include_package_data_in_sdist(self):
130134
"""
@@ -142,11 +146,58 @@ def test_package_data_and_include_package_data_in_sdist(self):
142146
with quiet():
143147
cmd.run()
144148

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
149+
self.assert_package_data_in_manifest(cmd)
150+
151+
@mock.patch('setuptools.command.egg_info.log')
152+
def test_custom_build_py(self, log_stub):
153+
"""
154+
Ensure projects defining custom build_py don't break
155+
when creating sdists (issue #2849)
156+
"""
157+
from distutils.command.build_py import build_py as OrigBuildPy
158+
159+
using_custom_command_guard = mock.Mock()
160+
161+
class CustomBuildPy(OrigBuildPy):
162+
"""
163+
Some projects have custom commands inheriting from `distutils`
164+
"""
165+
166+
def get_data_files(self):
167+
using_custom_command_guard()
168+
return super().get_data_files()
169+
170+
setup_attrs = {**SETUP_ATTRS, 'include_package_data': True}
171+
assert setup_attrs['package_data']
172+
173+
dist = Distribution(setup_attrs)
174+
dist.script_name = 'setup.py'
175+
cmd = sdist(dist)
176+
cmd.ensure_finalized()
177+
178+
# Make sure we use the custom command
179+
cmd.cmdclass = {'build_py': CustomBuildPy}
180+
cmd.distribution.cmdclass = {'build_py': CustomBuildPy}
181+
assert cmd.distribution.get_command_class('build_py') == CustomBuildPy
182+
183+
with quiet():
184+
cmd.run()
185+
186+
using_custom_command_guard.assert_called()
187+
self.assert_package_data_in_manifest(cmd)
188+
189+
warn_stub = log_stub.warn
190+
warn_stub.assert_called()
191+
for call in warn_stub.call_args_list:
192+
args, _kw = call
193+
if "setuptools instead of distutils" in args[0]:
194+
return
195+
else:
196+
raise AssertionError(
197+
"The user should have been warned to extend setuptools command"
198+
" classes instead of distutils",
199+
warn_stub.call_args_list
200+
)
150201

151202
def test_setup_py_exists(self):
152203
dist = Distribution(SETUP_ATTRS)

0 commit comments

Comments
 (0)