Daniel Holth avatar Daniel Holth committed 7e95e44 Merge

merge

Comments (0)

Files changed (10)

 * Issue #313: Support for sdist subcommands (Python 2.7)
 * Issue #314: test_local_index() would fail an OS X.
 * Issue #310: Non-ascii characters in a namespace __init__.py causes errors.
+* Issue #218: Improved documentation on behavior of `package_data` and
+  `include_package_data`. Files indicated by `package_data` are now included
+  in the manifest.
+* `distribute_setup.py` now allows a `--download-base` argument for retrieving
+  distribute from a specified location.
 
 ------
 0.6.28

File contents unchanged.

distribute_setup.py

 import fnmatch
 import tempfile
 import tarfile
+import optparse
+
 from distutils import log
 
 try:
                 self._dbg(1, "tarfile: %s" % e)
 
 
-def _build_install_args(argv):
+def _build_install_args(options):
+    """
+    Build the arguments to 'python setup.py install' on the distribute package
+    """
     install_args = []
-    user_install = '--user' in argv
-    if user_install and sys.version_info < (2, 6):
-        log.warn("--user requires Python 2.6 or later")
-        raise SystemExit(1)
-    if user_install:
+    if options.user_install:
+        if sys.version_info < (2, 6):
+            log.warn("--user requires Python 2.6 or later")
+            raise SystemExit(1)
         install_args.append('--user')
     return install_args
 
+def _parse_args():
+    """
+    Parse the command line for options
+    """
+    parser = optparse.OptionParser()
+    parser.add_option(
+        '--user', dest='user_install', action='store_true', default=False,
+        help='install in user site package (requires Python 2.6 or later)')
+    parser.add_option(
+        '--download-base', dest='download_base', metavar="URL",
+        default=DEFAULT_URL,
+        help='alternative URL from where to download the distribute package')
+    options, args = parser.parse_args()
+    # positional arguments are ignored
+    return options
 
-def main(argv, version=DEFAULT_VERSION):
+def main(version=DEFAULT_VERSION):
     """Install or upgrade setuptools and EasyInstall"""
-    tarball = download_setuptools()
-    _install(tarball, _build_install_args(argv))
-
+    options = _parse_args()
+    tarball = download_setuptools(download_base=options.download_base)
+    _install(tarball, _build_install_args(options))
 
 if __name__ == '__main__':
-    main(sys.argv[1:])
+    main()

docs/setuptools.txt

         include_package_data = True
     )
 
-This tells setuptools to install any data files it finds in your packages.  The
-data files must be under CVS or Subversion control, or else they must be
+This tells setuptools to install any data files it finds in your packages.
+The data files must be under CVS or Subversion control, or else they must be
 specified via the distutils' ``MANIFEST.in`` file.  (They can also be tracked
 by another revision control system, using an appropriate plugin.  See the
 section below on `Adding Support for Other Revision Control Systems`_ for
 information on how to write such plugins.)
 
-If you want finer-grained control over what files are included (for example, if
-you have documentation files in your package directories and want to exclude
-them from installation), then you can also use the ``package_data`` keyword,
-e.g.::
+If the data files are not under version control, or are not in a supported
+version control system, or if you want finer-grained control over what files
+are included (for example, if you have documentation files in your package
+directories and want to exclude them from installation), then you can also use
+the ``package_data`` keyword, e.g.::
 
     from setuptools import setup, find_packages
     setup(
 (Note: although the ``package_data`` argument was previously only available in
 ``setuptools``, it was also added to the Python ``distutils`` package as of
 Python 2.4; there is `some documentation for the feature`__ available on the
-python.org website.)
+python.org website.  If using the setuptools-specific ``include_package_data``
+argument, files specified by ``package_data`` will *not* be automatically
+added to the manifest unless they are tracked by a supported version control
+system, or are listed in the MANIFEST.in file.)
 
 __ http://docs.python.org/dist/node11.html
 

setuptools/command/sdist.py

         if self.distribution.has_pure_modules():
             build_py = self.get_finalized_command('build_py')
             self.filelist.extend(build_py.get_source_files())
+            # This functionality is incompatible with include_package_data, and
+            # will in fact create an infinite recursion if include_package_data
+            # is True.  Use of include_package_data will imply that
+            # distutils-style automatic handling of package_data is disabled
+            if not self.distribution.include_package_data:
+                for _, src_dir, _, filenames in build_py.data_files:
+                    self.filelist.extend([os.path.join(src_dir, filename)
+                                          for filename in filenames])
 
         if self.distribution.has_ext_modules():
             build_ext = self.get_finalized_command('build_ext')

setuptools/dist.py

 
     def fetch_build_egg(self, req):
         """Fetch an egg needed for building"""
+
         try:
             cmd = self._egg_fetcher
             cmd.package_index.to_scan = []
             cmd = easy_install(
                 dist, args=["x"], install_dir=os.curdir, exclude_scripts=True,
                 always_copy=False, build_directory=None, editable=False,
-                upgrade=False, multi_version=True, no_report = True
+                upgrade=False, multi_version=True, no_report=True, user=False
             )
             cmd.ensure_finalized()
             self._egg_fetcher = cmd

setuptools/sandbox.py

     _EXCEPTIONS = []
 
 try:
-	from win32com.client.gencache import GetGeneratePath
-	_EXCEPTIONS.append(GetGeneratePath())
-	del GetGeneratePath
+    from win32com.client.gencache import GetGeneratePath
+    _EXCEPTIONS.append(GetGeneratePath())
+    del GetGeneratePath
 except ImportError:
-	# it appears pywin32 is not installed, so no need to exclude.
-	pass
+    # it appears pywin32 is not installed, so no need to exclude.
+    pass
 
 class DirectorySandbox(AbstractSandbox):
     """Restrict operations to a single subdirectory - pseudo-chroot"""

setuptools/tests/__init__.py

     try:
         return setuptools.setup(**args)
     finally:
-        distutils.core_setup_stop_after = None
+        distutils.core._setup_stop_after = None
 
 
 class DependsTests(unittest.TestCase):

setuptools/tests/test_easy_install.py

 import StringIO
 import distutils.core
 
+from setuptools.sandbox import run_setup, SandboxViolation
 from setuptools.command.easy_install import easy_install, get_script_args, main
 from setuptools.command.easy_install import  PthDistributions
 from setuptools.command import easy_install as easy_install_pkg
         old_wd = os.getcwd()
         try:
             os.chdir(dir)
-            main([])
+            reset_setup_stop_context(
+                lambda: self.assertRaises(SystemExit, main, [])
+            )
         finally:
             os.chdir(old_wd)
             shutil.rmtree(dir)
             cmd.local_index.scan([new_location])
             res = cmd.easy_install('foo')
             self.assertEqual(os.path.realpath(res.location),
-                             os.path.realpath(new_location))            
+                             os.path.realpath(new_location))
         finally:
             sys.path.remove(target)
             for basedir in [new_location, target, ]:
             else:
                 del os.environ['PYTHONPATH']
 
+    def test_setup_requires(self):
+        """Regression test for issue #318
+
+        Ensures that a package with setup_requires can be installed when
+        distribute is installed in the user site-packages without causing a
+        SandboxViolation.
+        """
+
+        test_setup_attrs = {
+            'name': 'test_pkg', 'version': '0.0',
+            'setup_requires': ['foobar'],
+            'dependency_links': [os.path.abspath(self.dir)]
+        }
+
+        test_pkg = os.path.join(self.dir, 'test_pkg')
+        test_setup_py = os.path.join(test_pkg, 'setup.py')
+        test_setup_cfg = os.path.join(test_pkg, 'setup.cfg')
+        os.mkdir(test_pkg)
+
+        f = open(test_setup_py, 'w')
+        f.write(textwrap.dedent("""\
+            import setuptools
+            setuptools.setup(**%r)
+        """ % test_setup_attrs))
+        f.close()
+
+        foobar_path = os.path.join(self.dir, 'foobar-0.1.tar.gz')
+        make_trivial_sdist(
+            foobar_path,
+            textwrap.dedent("""\
+                import setuptools
+                setuptools.setup(
+                    name='foobar',
+                    version='0.1'
+                )
+            """))
+
+        old_stdout = sys.stdout
+        old_stderr = sys.stderr
+        sys.stdout = StringIO.StringIO()
+        sys.stderr = StringIO.StringIO()
+        try:
+            reset_setup_stop_context(
+                lambda: run_setup(test_setup_py, ['install'])
+            )
+        except SandboxViolation:
+            self.fail('Installation caused SandboxViolation')
+        finally:
+            sys.stdout = old_stdout
+            sys.stderr = old_stderr
+
 
 class TestSetupRequires(unittest.TestCase):
 
         doesn't exist) and invoke installer on it.
         """
         def build_sdist(dir):
-            setup_py = tarfile.TarInfo(name="setup.py")
-            try:
-                # Python 3 (StringIO gets converted to io module)
-                MemFile = StringIO.BytesIO
-            except AttributeError:
-                MemFile = StringIO.StringIO
-            setup_py_bytes = MemFile(textwrap.dedent("""
-                import setuptools
-                setuptools.setup(
-                    name="distribute-test-fetcher",
-                    version="1.0",
-                    setup_requires = ['does-not-exist'],
-                )
-                """).lstrip().encode('utf-8'))
-            setup_py.size = len(setup_py_bytes.getvalue())
             dist_path = os.path.join(dir, 'distribute-test-fetcher-1.0.tar.gz')
-            dist = tarfile.open(dist_path, 'w:gz')
-            try:
-                dist.addfile(setup_py, fileobj=setup_py_bytes)
-            finally:
-                dist.close()
+            make_trivial_sdist(
+                dist_path,
+                textwrap.dedent("""
+                    import setuptools
+                    setuptools.setup(
+                        name="distribute-test-fetcher",
+                        version="1.0",
+                        setup_requires = ['does-not-exist'],
+                    )
+                """).lstrip())
             installer(dist_path)
         tempdir_context(build_sdist)
 
+
+def make_trivial_sdist(dist_path, setup_py):
+    """Create a simple sdist tarball at dist_path, containing just a
+    setup.py, the contents of which are provided by the setup_py string.
+    """
+
+    setup_py_file = tarfile.TarInfo(name='setup.py')
+    try:
+        # Python 3 (StringIO gets converted to io module)
+        MemFile = StringIO.BytesIO
+    except AttributeError:
+        MemFile = StringIO.StringIO
+    setup_py_bytes = MemFile(setup_py.encode('utf-8'))
+    setup_py_file.size = len(setup_py_bytes.getvalue())
+    dist = tarfile.open(dist_path, 'w:gz')
+    try:
+        dist.addfile(setup_py_file, fileobj=setup_py_bytes)
+    finally:
+        dist.close()
+
+
 def tempdir_context(f, cd=lambda dir:None):
     """
     Invoke f in the context

setuptools/tests/test_sdist.py

+"""sdist tests"""
+
+
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+from StringIO import StringIO
+
+
+from setuptools.command.sdist import sdist
+from setuptools.dist import Distribution
+
+
+SETUP_ATTRS = {
+    'name': 'sdist_test',
+    'version': '0.0',
+    'packages': ['sdist_test'],
+    'package_data': {'sdist_test': ['*.txt']}
+}
+
+
+SETUP_PY = """\
+from setuptools import setup
+
+setup(**%r)
+""" % SETUP_ATTRS
+
+
+class TestSdistTest(unittest.TestCase):
+    def setUp(self):
+        self.temp_dir = tempfile.mkdtemp()
+        f = open(os.path.join(self.temp_dir, 'setup.py'), 'w')
+        f.write(SETUP_PY)
+        f.close()
+        # Set up the rest of the test package
+        test_pkg = os.path.join(self.temp_dir, 'sdist_test')
+        os.mkdir(test_pkg)
+        # *.rst was not included in package_data, so c.rst should not be
+        # automatically added to the manifest when not under version control
+        for fname in ['__init__.py', 'a.txt', 'b.txt', 'c.rst']:
+            # Just touch the files; their contents are irrelevant
+            open(os.path.join(test_pkg, fname), 'w').close()
+
+        self.old_cwd = os.getcwd()
+        os.chdir(self.temp_dir)
+
+    def tearDown(self):
+        os.chdir(self.old_cwd)
+        shutil.rmtree(self.temp_dir)
+
+    def test_package_data_in_sdist(self):
+        """Regression test for pull request #4: ensures that files listed in
+        package_data are included in the manifest even if they're not added to
+        version control.
+        """
+
+        dist = Distribution(SETUP_ATTRS)
+        dist.script_name = 'setup.py'
+        cmd = sdist(dist)
+        cmd.ensure_finalized()
+
+        # squelch output
+        old_stdout = sys.stdout
+        old_stderr = sys.stderr
+        sys.stdout = StringIO()
+        sys.stderr = StringIO()
+        try:
+            cmd.run()
+        finally:
+            sys.stdout = old_stdout
+            sys.stderr = old_stderr
+
+        manifest = cmd.filelist.files
+
+        self.assert_(os.path.join('sdist_test', 'a.txt') in manifest)
+        self.assert_(os.path.join('sdist_test', 'b.txt') in manifest)
+        self.assert_(os.path.join('sdist_test', 'c.rst') not in manifest)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.