We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Discrepancy between setuptools and distutils in sdist without MANIFEST.in
Originally reported by: **ikelos (Bitbucket: [ikelos](http://bitbucket.org/ikelos), GitHub: [ikelos](http://github.com/ikelos))**

---

[This upstream bug](http://bugs.python.org/issue2279) (fixed in to 2010) resolved the need to create a MANIFEST.in file as well as list data_files in the setup.py.  This does not appear to have been fixed in setuptools, and as such sdist and similar functions fail to include the appropriate files on machines that have setuptools, but not those that don't, when a fallback import system is used...

Would it be possible to align the two again so that setuptools is again a drop-in replacement for distutils?

---
- Bitbucket: https://bitbucket.org/pypa/setuptools/issue/274

Setuptools' sdist doesn't use data_files while distutils does
Originally reported by: **ionelmc (Bitbucket: [ionelmc](http://bitbucket.org/ionelmc), GitHub: [ionelmc](http://github.com/ionelmc))**

---

Distutils has this: https://github.com/python/cpython/blob/master/Lib/distutils/command/sdist.py#L270-L282

However that code is not copies in the sdist provided by setuptools. 

This can be problematic if you don't inlcude a file in MANIFEST.in but you have it in data_files - python's docs will most certainly mislead you as they say that sdist uses data_files: https://docs.python.org/3/distutils/sourcedist.html?highlight=data_files#specifying-the-files-to-distribute (last bullet)

---
- Bitbucket: https://bitbucket.org/pypa/setuptools/issue/521


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `setuptools/command/sdist.py`
Content:
```
1 from distutils import log
2 import distutils.command.sdist as orig
3 import os
4 import sys
5 import io
6 import contextlib
7 
8 from setuptools.extern import six
9 
10 from .py36compat import sdist_add_defaults
11 
12 import pkg_resources
13 
14 _default_revctrl = list
15 
16 
17 def walk_revctrl(dirname=''):
18     """Find all files under revision control"""
19     for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):
20         for item in ep.load()(dirname):
21             yield item
22 
23 
24 class sdist(sdist_add_defaults, orig.sdist):
25     """Smart sdist that finds anything supported by revision control"""
26 
27     user_options = [
28         ('formats=', None,
29          "formats for source distribution (comma-separated list)"),
30         ('keep-temp', 'k',
31          "keep the distribution tree around after creating " +
32          "archive file(s)"),
33         ('dist-dir=', 'd',
34          "directory to put the source distribution archive(s) in "
35          "[default: dist]"),
36     ]
37 
38     negative_opt = {}
39 
40     READMES = 'README', 'README.rst', 'README.txt'
41 
42     def run(self):
43         self.run_command('egg_info')
44         ei_cmd = self.get_finalized_command('egg_info')
45         self.filelist = ei_cmd.filelist
46         self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt'))
47         self.check_readme()
48 
49         # Run sub commands
50         for cmd_name in self.get_sub_commands():
51             self.run_command(cmd_name)
52 
53         # Call check_metadata only if no 'check' command
54         # (distutils <= 2.6)
55         import distutils.command
56 
57         if 'check' not in distutils.command.__all__:
58             self.check_metadata()
59 
60         self.make_distribution()
61 
62         dist_files = getattr(self.distribution, 'dist_files', [])
63         for file in self.archive_files:
64             data = ('sdist', '', file)
65             if data not in dist_files:
66                 dist_files.append(data)
67 
68     def initialize_options(self):
69         orig.sdist.initialize_options(self)
70 
71         self._default_to_gztar()
72 
73     def _default_to_gztar(self):
74         # only needed on Python prior to 3.6.
75         if sys.version_info >= (3, 6, 0, 'beta', 1):
76             return
77         self.formats = ['gztar']
78 
79     def make_distribution(self):
80         """
81         Workaround for #516
82         """
83         with self._remove_os_link():
84             orig.sdist.make_distribution(self)
85 
86     @staticmethod
87     @contextlib.contextmanager
88     def _remove_os_link():
89         """
90         In a context, remove and restore os.link if it exists
91         """
92 
93         class NoValue:
94             pass
95 
96         orig_val = getattr(os, 'link', NoValue)
97         try:
98             del os.link
99         except Exception:
100             pass
101         try:
102             yield
103         finally:
104             if orig_val is not NoValue:
105                 setattr(os, 'link', orig_val)
106 
107     def __read_template_hack(self):
108         # This grody hack closes the template file (MANIFEST.in) if an
109         #  exception occurs during read_template.
110         # Doing so prevents an error when easy_install attempts to delete the
111         #  file.
112         try:
113             orig.sdist.read_template(self)
114         except Exception:
115             _, _, tb = sys.exc_info()
116             tb.tb_next.tb_frame.f_locals['template'].close()
117             raise
118 
119     # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle
120     #  has been fixed, so only override the method if we're using an earlier
121     #  Python.
122     has_leaky_handle = (
123         sys.version_info < (2, 7, 2)
124         or (3, 0) <= sys.version_info < (3, 1, 4)
125         or (3, 2) <= sys.version_info < (3, 2, 1)
126     )
127     if has_leaky_handle:
128         read_template = __read_template_hack
129 
130     def _add_defaults_python(self):
131         """getting python files"""
132         if self.distribution.has_pure_modules():
133             build_py = self.get_finalized_command('build_py')
134             self.filelist.extend(build_py.get_source_files())
135             # This functionality is incompatible with include_package_data, and
136             # will in fact create an infinite recursion if include_package_data
137             # is True.  Use of include_package_data will imply that
138             # distutils-style automatic handling of package_data is disabled
139             if not self.distribution.include_package_data:
140                 for _, src_dir, _, filenames in build_py.data_files:
141                     self.filelist.extend([os.path.join(src_dir, filename)
142                                           for filename in filenames])
143 
144     def _add_defaults_data_files(self):
145         """
146         Don't add any data files, but why?
147         """
148 
149     def check_readme(self):
150         for f in self.READMES:
151             if os.path.exists(f):
152                 return
153         else:
154             self.warn(
155                 "standard file not found: should have one of " +
156                 ', '.join(self.READMES)
157             )
158 
159     def make_release_tree(self, base_dir, files):
160         orig.sdist.make_release_tree(self, base_dir, files)
161 
162         # Save any egg_info command line options used to create this sdist
163         dest = os.path.join(base_dir, 'setup.cfg')
164         if hasattr(os, 'link') and os.path.exists(dest):
165             # unlink and re-copy, since it might be hard-linked, and
166             # we don't want to change the source version
167             os.unlink(dest)
168             self.copy_file('setup.cfg', dest)
169 
170         self.get_finalized_command('egg_info').save_version_info(dest)
171 
172     def _manifest_is_not_generated(self):
173         # check for special comment used in 2.7.1 and higher
174         if not os.path.isfile(self.manifest):
175             return False
176 
177         with io.open(self.manifest, 'rb') as fp:
178             first_line = fp.readline()
179         return (first_line !=
180                 '# file GENERATED by distutils, do NOT edit\n'.encode())
181 
182     def read_manifest(self):
183         """Read the manifest file (named by 'self.manifest') and use it to
184         fill in 'self.filelist', the list of files to include in the source
185         distribution.
186         """
187         log.info("reading manifest file '%s'", self.manifest)
188         manifest = open(self.manifest, 'rb')
189         for line in manifest:
190             # The manifest must contain UTF-8. See #303.
191             if six.PY3:
192                 try:
193                     line = line.decode('UTF-8')
194                 except UnicodeDecodeError:
195                     log.warn("%r not UTF-8 decodable -- skipping" % line)
196                     continue
197             # ignore comments and blank lines
198             line = line.strip()
199             if line.startswith('#') or not line:
200                 continue
201             self.filelist.append(line)
202         manifest.close()
203
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
--- a/setuptools/command/sdist.py
+++ b/setuptools/command/sdist.py
@@ -141,11 +141,6 @@
                     self.filelist.extend([os.path.join(src_dir, filename)
                                           for filename in filenames])
 
-    def _add_defaults_data_files(self):
-        """
-        Don't add any data files, but why?
-        """
-
     def check_readme(self):
         for f in self.READMES:
             if os.path.exists(f):

{"golden_diff": "diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py\n--- a/setuptools/command/sdist.py\n+++ b/setuptools/command/sdist.py\n@@ -141,11 +141,6 @@\n                     self.filelist.extend([os.path.join(src_dir, filename)\n                                           for filename in filenames])\n \n-    def _add_defaults_data_files(self):\n-        \"\"\"\n-        Don't add any data files, but why?\n-        \"\"\"\n-\n     def check_readme(self):\n         for f in self.READMES:\n             if os.path.exists(f):\n", "issue": "Discrepancy between setuptools and distutils in sdist without MANIFEST.in\nOriginally reported by: **ikelos (Bitbucket: [ikelos](http://bitbucket.org/ikelos), GitHub: [ikelos](http://github.com/ikelos))**\n\n---\n\n[This upstream bug](http://bugs.python.org/issue2279) (fixed in to 2010) resolved the need to create a MANIFEST.in file as well as list data_files in the setup.py.  This does not appear to have been fixed in setuptools, and as such sdist and similar functions fail to include the appropriate files on machines that have setuptools, but not those that don't, when a fallback import system is used...\n\nWould it be possible to align the two again so that setuptools is again a drop-in replacement for distutils?\n\n---\n- Bitbucket: https://bitbucket.org/pypa/setuptools/issue/274\n\nSetuptools' sdist doesn't use data_files while distutils does\nOriginally reported by: **ionelmc (Bitbucket: [ionelmc](http://bitbucket.org/ionelmc), GitHub: [ionelmc](http://github.com/ionelmc))**\n\n---\n\nDistutils has this: https://github.com/python/cpython/blob/master/Lib/distutils/command/sdist.py#L270-L282\n\nHowever that code is not copies in the sdist provided by setuptools. \n\nThis can be problematic if you don't inlcude a file in MANIFEST.in but you have it in data_files - python's docs will most certainly mislead you as they say that sdist uses data_files: https://docs.python.org/3/distutils/sourcedist.html?highlight=data_files#specifying-the-files-to-distribute (last bullet)\n\n---\n- Bitbucket: https://bitbucket.org/pypa/setuptools/issue/521\n\n", "before_files": [{"content": "from distutils import log\nimport distutils.command.sdist as orig\nimport os\nimport sys\nimport io\nimport contextlib\n\nfrom setuptools.extern import six\n\nfrom .py36compat import sdist_add_defaults\n\nimport pkg_resources\n\n_default_revctrl = list\n\n\ndef walk_revctrl(dirname=''):\n    \"\"\"Find all files under revision control\"\"\"\n    for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):\n        for item in ep.load()(dirname):\n            yield item\n\n\nclass sdist(sdist_add_defaults, orig.sdist):\n    \"\"\"Smart sdist that finds anything supported by revision control\"\"\"\n\n    user_options = [\n        ('formats=', None,\n         \"formats for source distribution (comma-separated list)\"),\n        ('keep-temp', 'k',\n         \"keep the distribution tree around after creating \" +\n         \"archive file(s)\"),\n        ('dist-dir=', 'd',\n         \"directory to put the source distribution archive(s) in \"\n         \"[default: dist]\"),\n    ]\n\n    negative_opt = {}\n\n    READMES = 'README', 'README.rst', 'README.txt'\n\n    def run(self):\n        self.run_command('egg_info')\n        ei_cmd = self.get_finalized_command('egg_info')\n        self.filelist = ei_cmd.filelist\n        self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt'))\n        self.check_readme()\n\n        # Run sub commands\n        for cmd_name in self.get_sub_commands():\n            self.run_command(cmd_name)\n\n        # Call check_metadata only if no 'check' command\n        # (distutils <= 2.6)\n        import distutils.command\n\n        if 'check' not in distutils.command.__all__:\n            self.check_metadata()\n\n        self.make_distribution()\n\n        dist_files = getattr(self.distribution, 'dist_files', [])\n        for file in self.archive_files:\n            data = ('sdist', '', file)\n            if data not in dist_files:\n                dist_files.append(data)\n\n    def initialize_options(self):\n        orig.sdist.initialize_options(self)\n\n        self._default_to_gztar()\n\n    def _default_to_gztar(self):\n        # only needed on Python prior to 3.6.\n        if sys.version_info >= (3, 6, 0, 'beta', 1):\n            return\n        self.formats = ['gztar']\n\n    def make_distribution(self):\n        \"\"\"\n        Workaround for #516\n        \"\"\"\n        with self._remove_os_link():\n            orig.sdist.make_distribution(self)\n\n    @staticmethod\n    @contextlib.contextmanager\n    def _remove_os_link():\n        \"\"\"\n        In a context, remove and restore os.link if it exists\n        \"\"\"\n\n        class NoValue:\n            pass\n\n        orig_val = getattr(os, 'link', NoValue)\n        try:\n            del os.link\n        except Exception:\n            pass\n        try:\n            yield\n        finally:\n            if orig_val is not NoValue:\n                setattr(os, 'link', orig_val)\n\n    def __read_template_hack(self):\n        # This grody hack closes the template file (MANIFEST.in) if an\n        #  exception occurs during read_template.\n        # Doing so prevents an error when easy_install attempts to delete the\n        #  file.\n        try:\n            orig.sdist.read_template(self)\n        except Exception:\n            _, _, tb = sys.exc_info()\n            tb.tb_next.tb_frame.f_locals['template'].close()\n            raise\n\n    # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle\n    #  has been fixed, so only override the method if we're using an earlier\n    #  Python.\n    has_leaky_handle = (\n        sys.version_info < (2, 7, 2)\n        or (3, 0) <= sys.version_info < (3, 1, 4)\n        or (3, 2) <= sys.version_info < (3, 2, 1)\n    )\n    if has_leaky_handle:\n        read_template = __read_template_hack\n\n    def _add_defaults_python(self):\n        \"\"\"getting python files\"\"\"\n        if self.distribution.has_pure_modules():\n            build_py = self.get_finalized_command('build_py')\n            self.filelist.extend(build_py.get_source_files())\n            # This functionality is incompatible with include_package_data, and\n            # will in fact create an infinite recursion if include_package_data\n            # is True.  Use of include_package_data will imply that\n            # distutils-style automatic handling of package_data is disabled\n            if not self.distribution.include_package_data:\n                for _, src_dir, _, filenames in build_py.data_files:\n                    self.filelist.extend([os.path.join(src_dir, filename)\n                                          for filename in filenames])\n\n    def _add_defaults_data_files(self):\n        \"\"\"\n        Don't add any data files, but why?\n        \"\"\"\n\n    def check_readme(self):\n        for f in self.READMES:\n            if os.path.exists(f):\n                return\n        else:\n            self.warn(\n                \"standard file not found: should have one of \" +\n                ', '.join(self.READMES)\n            )\n\n    def make_release_tree(self, base_dir, files):\n        orig.sdist.make_release_tree(self, base_dir, files)\n\n        # Save any egg_info command line options used to create this sdist\n        dest = os.path.join(base_dir, 'setup.cfg')\n        if hasattr(os, 'link') and os.path.exists(dest):\n            # unlink and re-copy, since it might be hard-linked, and\n            # we don't want to change the source version\n            os.unlink(dest)\n            self.copy_file('setup.cfg', dest)\n\n        self.get_finalized_command('egg_info').save_version_info(dest)\n\n    def _manifest_is_not_generated(self):\n        # check for special comment used in 2.7.1 and higher\n        if not os.path.isfile(self.manifest):\n            return False\n\n        with io.open(self.manifest, 'rb') as fp:\n            first_line = fp.readline()\n        return (first_line !=\n                '# file GENERATED by distutils, do NOT edit\\n'.encode())\n\n    def read_manifest(self):\n        \"\"\"Read the manifest file (named by 'self.manifest') and use it to\n        fill in 'self.filelist', the list of files to include in the source\n        distribution.\n        \"\"\"\n        log.info(\"reading manifest file '%s'\", self.manifest)\n        manifest = open(self.manifest, 'rb')\n        for line in manifest:\n            # The manifest must contain UTF-8. See #303.\n            if six.PY3:\n                try:\n                    line = line.decode('UTF-8')\n                except UnicodeDecodeError:\n                    log.warn(\"%r not UTF-8 decodable -- skipping\" % line)\n                    continue\n            # ignore comments and blank lines\n            line = line.strip()\n            if line.startswith('#') or not line:\n                continue\n            self.filelist.append(line)\n        manifest.close()\n", "path": "setuptools/command/sdist.py"}], "after_files": [{"content": "from distutils import log\nimport distutils.command.sdist as orig\nimport os\nimport sys\nimport io\nimport contextlib\n\nfrom setuptools.extern import six\n\nfrom .py36compat import sdist_add_defaults\n\nimport pkg_resources\n\n_default_revctrl = list\n\n\ndef walk_revctrl(dirname=''):\n    \"\"\"Find all files under revision control\"\"\"\n    for ep in pkg_resources.iter_entry_points('setuptools.file_finders'):\n        for item in ep.load()(dirname):\n            yield item\n\n\nclass sdist(sdist_add_defaults, orig.sdist):\n    \"\"\"Smart sdist that finds anything supported by revision control\"\"\"\n\n    user_options = [\n        ('formats=', None,\n         \"formats for source distribution (comma-separated list)\"),\n        ('keep-temp', 'k',\n         \"keep the distribution tree around after creating \" +\n         \"archive file(s)\"),\n        ('dist-dir=', 'd',\n         \"directory to put the source distribution archive(s) in \"\n         \"[default: dist]\"),\n    ]\n\n    negative_opt = {}\n\n    READMES = 'README', 'README.rst', 'README.txt'\n\n    def run(self):\n        self.run_command('egg_info')\n        ei_cmd = self.get_finalized_command('egg_info')\n        self.filelist = ei_cmd.filelist\n        self.filelist.append(os.path.join(ei_cmd.egg_info, 'SOURCES.txt'))\n        self.check_readme()\n\n        # Run sub commands\n        for cmd_name in self.get_sub_commands():\n            self.run_command(cmd_name)\n\n        # Call check_metadata only if no 'check' command\n        # (distutils <= 2.6)\n        import distutils.command\n\n        if 'check' not in distutils.command.__all__:\n            self.check_metadata()\n\n        self.make_distribution()\n\n        dist_files = getattr(self.distribution, 'dist_files', [])\n        for file in self.archive_files:\n            data = ('sdist', '', file)\n            if data not in dist_files:\n                dist_files.append(data)\n\n    def initialize_options(self):\n        orig.sdist.initialize_options(self)\n\n        self._default_to_gztar()\n\n    def _default_to_gztar(self):\n        # only needed on Python prior to 3.6.\n        if sys.version_info >= (3, 6, 0, 'beta', 1):\n            return\n        self.formats = ['gztar']\n\n    def make_distribution(self):\n        \"\"\"\n        Workaround for #516\n        \"\"\"\n        with self._remove_os_link():\n            orig.sdist.make_distribution(self)\n\n    @staticmethod\n    @contextlib.contextmanager\n    def _remove_os_link():\n        \"\"\"\n        In a context, remove and restore os.link if it exists\n        \"\"\"\n\n        class NoValue:\n            pass\n\n        orig_val = getattr(os, 'link', NoValue)\n        try:\n            del os.link\n        except Exception:\n            pass\n        try:\n            yield\n        finally:\n            if orig_val is not NoValue:\n                setattr(os, 'link', orig_val)\n\n    def __read_template_hack(self):\n        # This grody hack closes the template file (MANIFEST.in) if an\n        #  exception occurs during read_template.\n        # Doing so prevents an error when easy_install attempts to delete the\n        #  file.\n        try:\n            orig.sdist.read_template(self)\n        except Exception:\n            _, _, tb = sys.exc_info()\n            tb.tb_next.tb_frame.f_locals['template'].close()\n            raise\n\n    # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle\n    #  has been fixed, so only override the method if we're using an earlier\n    #  Python.\n    has_leaky_handle = (\n        sys.version_info < (2, 7, 2)\n        or (3, 0) <= sys.version_info < (3, 1, 4)\n        or (3, 2) <= sys.version_info < (3, 2, 1)\n    )\n    if has_leaky_handle:\n        read_template = __read_template_hack\n\n    def _add_defaults_python(self):\n        \"\"\"getting python files\"\"\"\n        if self.distribution.has_pure_modules():\n            build_py = self.get_finalized_command('build_py')\n            self.filelist.extend(build_py.get_source_files())\n            # This functionality is incompatible with include_package_data, and\n            # will in fact create an infinite recursion if include_package_data\n            # is True.  Use of include_package_data will imply that\n            # distutils-style automatic handling of package_data is disabled\n            if not self.distribution.include_package_data:\n                for _, src_dir, _, filenames in build_py.data_files:\n                    self.filelist.extend([os.path.join(src_dir, filename)\n                                          for filename in filenames])\n\n    def check_readme(self):\n        for f in self.READMES:\n            if os.path.exists(f):\n                return\n        else:\n            self.warn(\n                \"standard file not found: should have one of \" +\n                ', '.join(self.READMES)\n            )\n\n    def make_release_tree(self, base_dir, files):\n        orig.sdist.make_release_tree(self, base_dir, files)\n\n        # Save any egg_info command line options used to create this sdist\n        dest = os.path.join(base_dir, 'setup.cfg')\n        if hasattr(os, 'link') and os.path.exists(dest):\n            # unlink and re-copy, since it might be hard-linked, and\n            # we don't want to change the source version\n            os.unlink(dest)\n            self.copy_file('setup.cfg', dest)\n\n        self.get_finalized_command('egg_info').save_version_info(dest)\n\n    def _manifest_is_not_generated(self):\n        # check for special comment used in 2.7.1 and higher\n        if not os.path.isfile(self.manifest):\n            return False\n\n        with io.open(self.manifest, 'rb') as fp:\n            first_line = fp.readline()\n        return (first_line !=\n                '# file GENERATED by distutils, do NOT edit\\n'.encode())\n\n    def read_manifest(self):\n        \"\"\"Read the manifest file (named by 'self.manifest') and use it to\n        fill in 'self.filelist', the list of files to include in the source\n        distribution.\n        \"\"\"\n        log.info(\"reading manifest file '%s'\", self.manifest)\n        manifest = open(self.manifest, 'rb')\n        for line in manifest:\n            # The manifest must contain UTF-8. See #303.\n            if six.PY3:\n                try:\n                    line = line.decode('UTF-8')\n                except UnicodeDecodeError:\n                    log.warn(\"%r not UTF-8 decodable -- skipping\" % line)\n                    continue\n            # ignore comments and blank lines\n            line = line.strip()\n            if line.startswith('#') or not line:\n                continue\n            self.filelist.append(line)\n        manifest.close()\n", "path": "setuptools/command/sdist.py"}]}