diff options
Diffstat (limited to 'setuptools/tests/test_easy_install.py')
-rw-r--r-- | setuptools/tests/test_easy_install.py | 263 |
1 files changed, 240 insertions, 23 deletions
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index af5644c5..aab4b617 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -1,17 +1,28 @@ """Easy install Tests """ import sys -import os, shutil, tempfile, unittest +import os +import shutil +import tempfile +import unittest import site -from setuptools.compat import StringIO, next +from setuptools.compat import StringIO, BytesIO, next +from setuptools.compat import urlparse +import textwrap +import tarfile +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 from setuptools.dist import Distribution from pkg_resources import Distribution as PRDistribution +import setuptools.tests.server try: - import multiprocessing + # import multiprocessing solely for the purpose of testing its existence + __import__('multiprocessing') import logging _LOG = logging.getLogger('test_easy_install') logging.basicConfig(level=logging.INFO, stream=sys.stderr) @@ -58,7 +69,7 @@ class TestEasyInstallTest(unittest.TestCase): try: cmd.install_site_py() sitepy = os.path.join(cmd.install_dir, 'site.py') - self.assert_(os.path.exists(sitepy)) + self.assertTrue(os.path.exists(sitepy)) finally: shutil.rmtree(cmd.install_dir) @@ -67,11 +78,11 @@ class TestEasyInstallTest(unittest.TestCase): old_platform = sys.platform try: - name, script = next(get_script_args(dist)) + name, script = [i for i in next(get_script_args(dist))][0:2] finally: sys.platform = old_platform - self.assertEquals(script, WANTED) + self.assertEqual(script, WANTED) def test_no_setup_cfg(self): # makes sure easy_install as a command (main) @@ -92,7 +103,7 @@ class TestEasyInstallTest(unittest.TestCase): opts = self.command_options if 'easy_install' in opts: assert 'find_links' not in opts['easy_install'], msg - return self._old_parse_command_line + return self._old_parse_command_line() Distribution._old_parse_command_line = Distribution.parse_command_line Distribution.parse_command_line = _parse_command_line @@ -100,33 +111,36 @@ 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) + Distribution.parse_command_line = Distribution._old_parse_command_line def test_no_find_links(self): # new option '--no-find-links', that blocks find-links added at # the project level dist = Distribution() cmd = easy_install(dist) - cmd.check_pth_processing = lambda : True + cmd.check_pth_processing = lambda: True cmd.no_find_links = True cmd.find_links = ['link1', 'link2'] cmd.install_dir = os.path.join(tempfile.mkdtemp(), 'ok') cmd.args = ['ok'] cmd.ensure_finalized() - self.assertEquals(cmd.package_index.scanned_urls, {}) + self.assertEqual(cmd.package_index.scanned_urls, {}) # let's try without it (default behavior) cmd = easy_install(dist) - cmd.check_pth_processing = lambda : True + cmd.check_pth_processing = lambda: True cmd.find_links = ['link1', 'link2'] cmd.install_dir = os.path.join(tempfile.mkdtemp(), 'ok') cmd.args = ['ok'] cmd.ensure_finalized() keys = sorted(cmd.package_index.scanned_urls.keys()) - self.assertEquals(keys, ['link1', 'link2']) + self.assertEqual(keys, ['link1', 'link2']) class TestPTHFileWriter(unittest.TestCase): @@ -135,15 +149,19 @@ class TestPTHFileWriter(unittest.TestCase): if a distribution is in site but also the cwd ''' pth = PthDistributions('does-not_exist', [os.getcwd()]) - self.assert_(not pth.dirty) + self.assertTrue(not pth.dirty) pth.add(PRDistribution(os.getcwd())) - self.assert_(pth.dirty) + self.assertTrue(pth.dirty) def test_add_from_site_is_ignored(self): - pth = PthDistributions('does-not_exist', ['/test/location/does-not-have-to-exist']) - self.assert_(not pth.dirty) - pth.add(PRDistribution('/test/location/does-not-have-to-exist')) - self.assert_(not pth.dirty) + if os.name != 'nt': + location = '/test/location/does-not-have-to-exist' + else: + location = 'c:\\does_not_exist' + pth = PthDistributions('does-not_exist', [location, ]) + self.assertTrue(not pth.dirty) + pth.add(PRDistribution(location)) + self.assertTrue(not pth.dirty) class TestUserInstallTest(unittest.TestCase): @@ -168,7 +186,7 @@ class TestUserInstallTest(unittest.TestCase): def tearDown(self): os.chdir(self.old_cwd) shutil.rmtree(self.dir) - if sys.version >= "2.6": + if sys.version >= "2.6": shutil.rmtree(site.USER_BASE) shutil.rmtree(site.USER_SITE) site.USER_BASE = self.old_base @@ -220,7 +238,7 @@ class TestUserInstallTest(unittest.TestCase): sys.path.append(target) old_ppath = os.environ.get('PYTHONPATH') - os.environ['PYTHONPATH'] = ':'.join(sys.path) + os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path) try: dist = Distribution() dist.script_name = 'setup.py' @@ -230,13 +248,212 @@ class TestUserInstallTest(unittest.TestCase): cmd.ensure_finalized() cmd.local_index.scan([new_location]) res = cmd.easy_install('foo') - self.assertEquals(res.location, new_location) + self.assertEqual(os.path.realpath(res.location), + os.path.realpath(new_location)) finally: sys.path.remove(target) - shutil.rmtree(new_location) - shutil.rmtree(target) + for basedir in [new_location, target, ]: + if not os.path.exists(basedir) or not os.path.isdir(basedir): + continue + try: + shutil.rmtree(basedir) + except: + pass if old_ppath is not None: os.environ['PYTHONPATH'] = old_ppath 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() + sys.stderr = 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): + + def test_setup_requires_honors_fetch_params(self): + """ + When easy_install installs a source distribution which specifies + setup_requires, it should honor the fetch parameters (such as + allow-hosts, index-url, and find-links). + """ + # set up a server which will simulate an alternate package index. + p_index = setuptools.tests.server.MockServer() + p_index.start() + netloc = 1 + p_index_loc = urlparse(p_index.url)[netloc] + if p_index_loc.endswith(':0'): + # Some platforms (Jython) don't find a port to which to bind, + # so skip this test for them. + return + + # I realize this is all-but-impossible to read, because it was + # ported from some well-factored, safe code using 'with'. If you + # need to maintain this code, consider making the changes in + # the parent revision (of this comment) and then port the changes + # back for Python 2.4 (or deprecate Python 2.4). + + def install(dist_file): + def install_at(temp_install_dir): + def install_env(): + ei_params = ['--index-url', p_index.url, + '--allow-hosts', p_index_loc, + '--exclude-scripts', '--install-dir', temp_install_dir, + dist_file] + def install_clean_reset(): + def install_clean_argv(): + # attempt to install the dist. It should fail because + # it doesn't exist. + self.assertRaises(SystemExit, + easy_install_pkg.main, ei_params) + argv_context(install_clean_argv, ['easy_install']) + reset_setup_stop_context(install_clean_reset) + environment_context(install_env, PYTHONPATH=temp_install_dir) + tempdir_context(install_at) + + # create an sdist that has a build-time dependency. + self.create_sdist(install) + + # there should have been two or three requests to the server + # (three happens on Python 3.3a) + self.assertTrue(2 <= len(p_index.requests) <= 3) + self.assertEqual(p_index.requests[0].path, '/does-not-exist/') + + def create_sdist(self, installer): + """ + Create an sdist with a setup_requires dependency (of something that + doesn't exist) and invoke installer on it. + """ + def build_sdist(dir): + dist_path = os.path.join(dir, 'distribute-test-fetcher-1.0.tar.gz') + 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 = BytesIO + except AttributeError: + MemFile = 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 + """ + temp_dir = tempfile.mkdtemp() + orig_dir = os.getcwd() + try: + cd(temp_dir) + f(temp_dir) + finally: + cd(orig_dir) + shutil.rmtree(temp_dir) + +def environment_context(f, **updates): + """ + Invoke f in the context + """ + old_env = os.environ.copy() + os.environ.update(updates) + try: + f() + finally: + for key in updates: + del os.environ[key] + os.environ.update(old_env) + +def argv_context(f, repl): + """ + Invoke f in the context + """ + old_argv = sys.argv[:] + sys.argv[:] = repl + try: + f() + finally: + sys.argv[:] = old_argv + +def reset_setup_stop_context(f): + """ + When the distribute tests are run using setup.py test, and then + one wants to invoke another setup() command (such as easy_install) + within those tests, it's necessary to reset the global variable + in distutils.core so that the setup() command will run naturally. + """ + setup_stop_after = distutils.core._setup_stop_after + distutils.core._setup_stop_after = None + try: + f() + finally: + distutils.core._setup_stop_after = setup_stop_after |