Commit 20c14661 authored by Daniel Holth's avatar Daniel Holth

merge

--HG--
branch : distribute
extra : rebase_source : e10714ab6506fa313a8bfb3f88f0620d3ab1707d
parents fb321a77 cada83b2
......@@ -16,6 +16,11 @@ CHANGES
* 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
......
......@@ -19,6 +19,8 @@ import time
import fnmatch
import tempfile
import tarfile
import optparse
from distutils import log
try:
......@@ -495,22 +497,39 @@ def _extractall(self, path=".", members=None):
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 main(argv, version=DEFAULT_VERSION):
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(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()
......@@ -756,17 +756,18 @@ e.g.::
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(
......@@ -822,7 +823,10 @@ converts slashes to appropriate platform-specific separators at build time.
(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
......
......@@ -198,6 +198,14 @@ class sdist(_sdist):
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')
......
......@@ -264,6 +264,7 @@ class Distribution(_Distribution):
def fetch_build_egg(self, req):
"""Fetch an egg needed for building"""
try:
cmd = self._egg_fetcher
cmd.package_index.to_scan = []
......@@ -287,7 +288,7 @@ class Distribution(_Distribution):
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
......
......@@ -166,12 +166,12 @@ else:
_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"""
......
......@@ -38,7 +38,7 @@ def makeSetup(**args):
try:
return setuptools.setup(**args)
finally:
distutils.core_setup_stop_after = None
distutils.core._setup_stop_after = None
class DependsTests(unittest.TestCase):
......
......@@ -12,6 +12,7 @@ import urlparse
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
......@@ -110,7 +111,9 @@ class TestEasyInstallTest(unittest.TestCase):
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)
......@@ -247,7 +250,7 @@ class TestUserInstallTest(unittest.TestCase):
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, ]:
......@@ -262,6 +265,57 @@ class TestUserInstallTest(unittest.TestCase):
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):
......@@ -319,30 +373,41 @@ 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
......
"""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)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment