Repository: pypa/setuptools (Python)

Issue:
pyproject.toml should be included in sdist by default
An issue came up at work recently where installing [python-daemon](https://pagure.io/python-daemon) with `pip` was hitting the `easy_install` path. I assumed it was because `python-daemon` didn't have a `pyproject.toml`, but it turns out they do - it's just not included in the `Manifest.in`, so it didn't get included in the `sdist`. To verify this I created a super basic example project and it does seem that the default is to exclude `pyproject.toml`.

Given that `pyproject.toml` is one of the most important files to have when executing a build, it should be included in the sdist unless explicitly excluded.


Discussion:
I think the same issue should be put into Python bugtracker for ``distutils`` to include ``pyproject.toml`` by default.
@daa I think at this point new changes like this are not likely to be accepted in `distutils`, but you are welcome to open an issue. Generally the guidance is to use `setuptools`.
From [PEP 517](https://www.python.org/dev/peps/pep-0517/):

> ### `build_sdist`
>
> […] A .tar.gz source distribution (sdist) contains a single top-level directory […]. This directory must also contain the pyproject.toml from the build directory, and a PKG-INFO file containing metadata in the format described in PEP 345.

So at least sdists built through `build_meta` must contain pyproject.toml. It is still debatable whether `setup.py sdist` (which is not restricted by PEP 517) should do this by default though.

Should I file a PR to special-case `build_meta.build_sdist`? As it stands Setuptools is not technically compliant to PEP 517. (Edit: I already did.)



Patch:
diff --git a/changelog.d/1634.breaking.rst b/changelog.d/1634.breaking.rst
new file mode 100644
index 0000000000..b65e5d9f40
--- /dev/null
+++ b/changelog.d/1634.breaking.rst
@@ -0,0 +1,1 @@
+Include ``pyproject.toml`` in source distribution by default. Projects relying on the previous behavior where ``pyproject.toml`` was excluded by default should stop relying on that behavior or add ``exclude pyproject.toml`` to their MANIFEST.in file.
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index eebdfd1975..a851453f9a 100644
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -121,6 +121,14 @@ def __read_template_hack(self):
     if has_leaky_handle:
         read_template = __read_template_hack
 
+    def _add_defaults_optional(self):
+        if six.PY2:
+            sdist_add_defaults._add_defaults_optional(self)
+        else:
+            super()._add_defaults_optional()
+        if os.path.isfile('pyproject.toml'):
+            self.filelist.append('pyproject.toml')
+
     def _add_defaults_python(self):
         """getting python files"""
         if self.distribution.has_pure_modules():


Test patch:
diff --git a/setuptools/tests/test_build_meta.py b/setuptools/tests/test_build_meta.py
index e1efe5617c..326b4f5dbd 100644
--- a/setuptools/tests/test_build_meta.py
+++ b/setuptools/tests/test_build_meta.py
@@ -262,6 +262,27 @@ def test_build_sdist_version_change(self, build_backend):
         assert os.path.isfile(
             os.path.join(os.path.abspath("out_sdist"), sdist_name))
 
+    def test_build_sdist_pyproject_toml_exists(self, tmpdir_cwd):
+        files = {
+            'setup.py': DALS("""
+                __import__('setuptools').setup(
+                    name='foo',
+                    version='0.0.0',
+                    py_modules=['hello']
+                )"""),
+            'hello.py': '',
+            'pyproject.toml': DALS("""
+                [build-system]
+                requires = ["setuptools", "wheel"]
+                build-backend = "setuptools.build_meta
+                """),
+        }
+        build_files(files)
+        build_backend = self.get_build_backend()
+        targz_path = build_backend.build_sdist("temp")
+        with tarfile.open(os.path.join("temp", targz_path)) as tar:
+            assert any('pyproject.toml' in name for name in tar.getnames())
+
     def test_build_sdist_setup_py_exists(self, tmpdir_cwd):
         # If build_sdist is called from a script other than setup.py,
         # ensure setup.py is included
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
index d2c4e0cf95..b27c4a8336 100644
--- a/setuptools/tests/test_sdist.py
+++ b/setuptools/tests/test_sdist.py
@@ -1,6 +1,8 @@
 # -*- coding: utf-8 -*-
 """sdist tests"""
 
+from __future__ import print_function
+
 import os
 import shutil
 import sys
@@ -449,6 +451,36 @@ def test_sdist_with_latin1_encoded_filename(self):
             except UnicodeDecodeError:
                 filename not in cmd.filelist.files
 
+    def test_pyproject_toml_in_sdist(self):
+        """
+        Check if pyproject.toml is included in source distribution if present
+        """
+        open(os.path.join(self.temp_dir, 'pyproject.toml'), 'w').close()
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        cmd = sdist(dist)
+        cmd.ensure_finalized()
+        with quiet():
+            cmd.run()
+        manifest = cmd.filelist.files
+        assert 'pyproject.toml' in manifest
+
+    def test_pyproject_toml_excluded(self):
+        """
+        Check that pyproject.toml can excluded even if present
+        """
+        open(os.path.join(self.temp_dir, 'pyproject.toml'), 'w').close()
+        with open('MANIFEST.in', 'w') as mts:
+            print('exclude pyproject.toml', file=mts)
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        cmd = sdist(dist)
+        cmd.ensure_finalized()
+        with quiet():
+            cmd.run()
+        manifest = cmd.filelist.files
+        assert 'pyproject.toml' not in manifest
+
 
 def test_default_revctrl():
     """