summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnderson Bravalheri <andersonbravalheri@gmail.com>2022-06-25 20:04:49 +0100
committerGitHub <noreply@github.com>2022-06-25 20:04:49 +0100
commit2ee94e7e40379d348cdadbb747fbbcf5a6f228c6 (patch)
tree9df2f7a96c125520c4fbc8478019aebbd5a4782e
parent700237e252e45cb465c1013fe41ad43092fccf1a (diff)
parent54795137d0c3febaf553df15d0b0e2e8c894150a (diff)
downloadpython-setuptools-git-2ee94e7e40379d348cdadbb747fbbcf5a6f228c6.tar.gz
sdist: Add files from build subcommands - get_source_files (#3412)
-rw-r--r--changelog.d/3412.change.rst3
-rw-r--r--setuptools/command/build.py16
-rw-r--r--setuptools/command/sdist.py14
-rw-r--r--setuptools/tests/test_sdist.py41
4 files changed, 74 insertions, 0 deletions
diff --git a/changelog.d/3412.change.rst b/changelog.d/3412.change.rst
new file mode 100644
index 00000000..69f02bc8
--- /dev/null
+++ b/changelog.d/3412.change.rst
@@ -0,0 +1,3 @@
+Added ability of collecting source files from custom build sub-commands to
+``sdist``. This allows plugins and customization scripts to automatically
+add required source files in the source distribution.
diff --git a/setuptools/command/build.py b/setuptools/command/build.py
index bf4f71a7..c35dc3fc 100644
--- a/setuptools/command/build.py
+++ b/setuptools/command/build.py
@@ -65,6 +65,11 @@ class SubCommand(Protocol):
of ``get_output_mapping()``. Alternatively, ``setuptools`` **MAY** attempt to use
:doc:`import hooks <python:reference/import>` to redirect any attempt to import
to the directory with the original source code and other files built in place.
+
+ Please note that custom sub-commands **SHOULD NOT** rely on ``run()`` being
+ executed (or not) to provide correct return values for ``get_outputs()``,
+ ``get_output_mapping()`` or ``get_source_files()``. The ``get_*`` methods should
+ work independently of ``run()``.
"""
editable_mode: bool = False
@@ -106,6 +111,17 @@ class SubCommand(Protocol):
def run(self):
"""(Required by the original :class:`setuptools.Command` interface)"""
+ def get_source_files(self) -> List[str]:
+ """
+ Return a list of all files that are used by the command to create the expected
+ outputs.
+ For example, if your build command transpiles Java files into Python, you should
+ list here all the Java files.
+ The primary purpose of this function is to help populating the ``sdist``
+ with all the files necessary to build the distribution.
+ All files should be strings relative to the project root directory.
+ """
+
def get_outputs(self) -> List[str]:
"""
Return a list of files intended for distribution as they would have been
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index 0ffeacf3..4a8cde7e 100644
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -4,10 +4,12 @@ import os
import sys
import io
import contextlib
+from itertools import chain
from .py36compat import sdist_add_defaults
from .._importlib import metadata
+from .build import _ORIGINAL_SUBCOMMANDS
_default_revctrl = list
@@ -100,6 +102,10 @@ class sdist(sdist_add_defaults, orig.sdist):
if orig_val is not NoValue:
setattr(os, 'link', orig_val)
+ def add_defaults(self):
+ super().add_defaults()
+ self._add_defaults_build_sub_commands()
+
def _add_defaults_optional(self):
super()._add_defaults_optional()
if os.path.isfile('pyproject.toml'):
@@ -112,6 +118,14 @@ class sdist(sdist_add_defaults, orig.sdist):
self.filelist.extend(build_py.get_source_files())
self._add_data_files(self._safe_data_files(build_py))
+ def _add_defaults_build_sub_commands(self):
+ build = self.get_finalized_command("build")
+ missing_cmds = set(build.get_sub_commands()) - _ORIGINAL_SUBCOMMANDS
+ # ^-- the original built-in sub-commands are already handled by default.
+ cmds = (self.get_finalized_command(c) for c in missing_cmds)
+ files = (c.get_source_files() for c in cmds if hasattr(c, "get_source_files"))
+ self.filelist.extend(chain.from_iterable(files))
+
def _safe_data_files(self, build_py):
"""
Since the ``sdist`` class is also used to compute the MANIFEST
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index 302cff73..4b0d2e17 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -10,6 +10,7 @@ from unittest import mock
import pytest
+from setuptools import Command
from setuptools._importlib import metadata
from setuptools import SetuptoolsDeprecationWarning
from setuptools.command.sdist import sdist
@@ -517,6 +518,46 @@ class TestSdistTest:
manifest = cmd.filelist.files
assert 'pyproject.toml' not in manifest
+ def test_build_subcommand_source_files(self, tmpdir):
+ touch(tmpdir / '.myfile~')
+
+ # Sanity check: without custom commands file list should not be affected
+ dist = Distribution({**SETUP_ATTRS, "script_name": "setup.py"})
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+ with quiet():
+ cmd.run()
+ manifest = cmd.filelist.files
+ assert '.myfile~' not in manifest
+
+ # Test: custom command should be able to augment file list
+ dist = Distribution({**SETUP_ATTRS, "script_name": "setup.py"})
+ build = dist.get_command_obj("build")
+ build.sub_commands = [*build.sub_commands, ("build_custom", None)]
+
+ class build_custom(Command):
+ def initialize_options(self):
+ ...
+
+ def finalize_options(self):
+ ...
+
+ def run(self):
+ ...
+
+ def get_source_files(self):
+ return ['.myfile~']
+
+ dist.cmdclass.update(build_custom=build_custom)
+
+ cmd = sdist(dist)
+ cmd.use_defaults = True
+ cmd.ensure_finalized()
+ with quiet():
+ cmd.run()
+ manifest = cmd.filelist.files
+ assert '.myfile~' in manifest
+
def test_default_revctrl():
"""