Commit
…s data when include_package_data=True (#3308)
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
Relying on ``include_package_data`` to ensure sub-packages are automatically | ||
added to the build wheel distribution (as "data") is now considered a | ||
deprecated practice. | ||
|
||
This behaviour was controversial and caused inconsistencies (#3260). | ||
|
||
Instead, projects are encouraged to properly configure ``packages`` or use | ||
discovery tools. General information can be found in :doc:`userguide/package_discovery`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,9 @@ | |
import distutils.errors | ||
import itertools | ||
import stat | ||
import warnings | ||
from pathlib import Path | ||
from setuptools._deprecation_warning import SetuptoolsDeprecationWarning | ||
from setuptools.extern.more_itertools import unique_everseen | ||
|
||
|
||
|
@@ -130,6 +133,7 @@ def analyze_manifest(self): | |
src_dirs[assert_relative(self.get_package_dir(package))] = package | ||
|
||
self.run_command('egg_info') | ||
check = _IncludePackageDataAbuse() | ||
ei_cmd = self.get_finalized_command('egg_info') | ||
for path in ei_cmd.filelist.files: | ||
d, f = os.path.split(assert_relative(path)) | ||
|
@@ -140,8 +144,13 @@ def analyze_manifest(self): | |
d, df = os.path.split(d) | ||
f = os.path.join(df, f) | ||
if d in src_dirs: | ||
if path.endswith('.py') and f == oldf: | ||
continue # it's a module, not data | ||
if f == oldf: | ||
if check.is_module(f): | ||
continue # it's a module, not data | ||
else: | ||
importable = check.importable_subpackage(src_dirs[d], f) | ||
if importable: | ||
check.warn(importable) | ||
mf.setdefault(src_dirs[d], []).append(path) | ||
|
||
def get_data_files(self): | ||
|
@@ -241,3 +250,44 @@ def assert_relative(path): | |
% path | ||
) | ||
raise DistutilsSetupError(msg) | ||
|
||
|
||
class _IncludePackageDataAbuse: | ||
"""Inform users that package or module is included as 'data file'""" | ||
|
||
MESSAGE = """\ | ||
!!\n\n | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
abravalheri
Author
Contributor
|
||
############################ | ||
# Package would be ignored # | ||
############################ | ||
Python recognizes {importable!r} as an importable package, however it is | ||
included in the distribution as "data". | ||
This behavior is likely to change in future versions of setuptools (and | ||
therefore is considered deprecated). | ||
Please make sure that {importable!r} is included as a package by using | ||
setuptools' `packages` configuration field or the proper discovery methods. | ||
You can read more about "package discovery" and "data files" on setuptools | ||
documentation page. | ||
\n\n!! | ||
""" | ||
|
||
def __init__(self): | ||
self._already_warned = set() | ||
|
||
def is_module(self, file): | ||
return file.endswith(".py") and file[:-len(".py")].isidentifier() | ||
|
||
def importable_subpackage(self, parent, file): | ||
pkg = Path(file).parent | ||
parts = list(itertools.takewhile(str.isidentifier, pkg.parts)) | ||
if parts: | ||
return ".".join([parent, *parts]) | ||
return None | ||
|
||
def warn(self, importable): | ||
if importable not in self._already_warned: | ||
msg = textwrap.dedent(self.MESSAGE).format(importable=importable) | ||
warnings.warn(msg, SetuptoolsDeprecationWarning, stacklevel=2) | ||
self._already_warned.add(importable) |
Could you please add a one-line short summary here? @gentoo is trying to capture warning messages from setuptools and right now we just get
!!
here. I don't think we can cleanly capture multi-line warnings, so at least grabbing a meaningful summary would be good.