diff options
Diffstat (limited to 'setuptools')
| -rwxr-xr-x | setuptools/archive_util.py | 29 | ||||
| -rw-r--r-- | setuptools/command/bdist_egg.py | 6 | ||||
| -rw-r--r-- | setuptools/command/build_py.py | 4 | ||||
| -rwxr-xr-x | setuptools/command/develop.py | 36 | ||||
| -rwxr-xr-x | setuptools/command/easy_install.py | 46 | ||||
| -rwxr-xr-x | setuptools/command/install_scripts.py | 5 | ||||
| -rwxr-xr-x | setuptools/command/sdist.py | 23 | ||||
| -rw-r--r-- | setuptools/command/test.py | 5 | ||||
| -rwxr-xr-x | setuptools/command/upload.py | 2 | ||||
| -rw-r--r-- | setuptools/extension.py | 56 | ||||
| -rwxr-xr-x | setuptools/sandbox.py | 10 | ||||
| -rw-r--r-- | setuptools/tests/__init__.py | 161 | ||||
| -rw-r--r-- | setuptools/tests/py26compat.py | 14 | ||||
| -rw-r--r-- | setuptools/tests/server.py | 56 | ||||
| -rw-r--r-- | setuptools/tests/test_bdist_egg.py | 69 | ||||
| -rw-r--r-- | setuptools/tests/test_develop.py | 62 | ||||
| -rw-r--r-- | setuptools/tests/test_dist_info.py | 76 | ||||
| -rw-r--r-- | setuptools/tests/test_easy_install.py | 175 | ||||
| -rw-r--r-- | setuptools/tests/test_markerlib.py | 98 | ||||
| -rw-r--r-- | setuptools/tests/test_packageindex.py | 58 | ||||
| -rw-r--r-- | setuptools/tests/test_resources.py | 42 | ||||
| -rw-r--r-- | setuptools/tests/test_test.py | 124 |
22 files changed, 924 insertions, 233 deletions
diff --git a/setuptools/archive_util.py b/setuptools/archive_util.py index ab786f3d..5787753f 100755 --- a/setuptools/archive_util.py +++ b/setuptools/archive_util.py @@ -180,19 +180,22 @@ def unpack_tarfile(filename, extract_dir, progress_filter=default_filter): try: tarobj.chown = lambda *args: None # don't do any chowning! for member in tarobj: - if member.isfile() or member.isdir(): - name = member.name - # don't extract absolute paths or ones with .. in them - if not name.startswith('/') and '..' not in name: - dst = os.path.join(extract_dir, *name.split('/')) - dst = progress_filter(name, dst) - if dst: - if dst.endswith(os.sep): - dst = dst[:-1] - try: - tarobj._extract_member(member,dst) # XXX Ugh - except tarfile.ExtractError: - pass # chown/chmod/mkfifo/mknode/makedev failed + name = member.name + # don't extract absolute paths or ones with .. in them + if not name.startswith('/') and '..' not in name: + prelim_dst = os.path.join(extract_dir, *name.split('/')) + final_dst = progress_filter(name, prelim_dst) + # If progress_filter returns None, then we do not extract + # this file + # TODO: Do we really need to limit to just these file types? + # tarobj.extract() will handle all files on all platforms, + # turning file types that aren't allowed on that platform into + # regular files. + if final_dst and (member.isfile() or member.isdir() or + member.islnk() or member.issym()): + tarobj.extract(member, extract_dir) + if final_dst != prelim_dst: + shutil.move(prelim_dst, final_dst) return True finally: tarobj.close() diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py index 68ca15c7..0ee9c55b 100644 --- a/setuptools/command/bdist_egg.py +++ b/setuptools/command/bdist_egg.py @@ -426,7 +426,11 @@ def scan_module(egg_dir, base, name, stubs): pkg = base[len(egg_dir)+1:].replace(os.sep,'.') module = pkg+(pkg and '.' or '')+os.path.splitext(name)[0] f = open(filename,'rb'); f.read(8) # skip magic & date - code = marshal.load(f); f.close() + try: + code = marshal.load(f); f.close() + except ValueError: + f.seek(0); f.read(12) # skip magic & date & file size; file size added in Python 3.3 + code = marshal.load(f); f.close() safe = True symbols = dict.fromkeys(iter_symbols(code)) for bad in ['__file__', '__path__']: diff --git a/setuptools/command/build_py.py b/setuptools/command/build_py.py index d53960fe..505dd4f3 100644 --- a/setuptools/command/build_py.py +++ b/setuptools/command/build_py.py @@ -215,8 +215,8 @@ class build_py(_build_py, Mixin2to3): else: return init_py - f = open(init_py,'rU') - if 'declare_namespace' not in f.read(): + f = open(init_py,'rbU') + if 'declare_namespace'.encode() not in f.read(): from distutils import log log.warn( "WARNING: %s is a namespace package, but its __init__.py does\n" diff --git a/setuptools/command/develop.py b/setuptools/command/develop.py index 93b7773c..709e349c 100755 --- a/setuptools/command/develop.py +++ b/setuptools/command/develop.py @@ -3,7 +3,7 @@ from distutils.util import convert_path, subst_vars from pkg_resources import Distribution, PathMetadata, normalize_path from distutils import log from distutils.errors import DistutilsError, DistutilsOptionError -import os, setuptools, glob +import os, sys, setuptools, glob class develop(easy_install): """Set up package for development""" @@ -84,11 +84,35 @@ class develop(easy_install): " installation directory", p, normalize_path(os.curdir)) def install_for_development(self): - # Ensure metadata is up-to-date - self.run_command('egg_info') - # Build extensions in-place - self.reinitialize_command('build_ext', inplace=1) - self.run_command('build_ext') + if sys.version_info >= (3,) and getattr(self.distribution, 'use_2to3', False): + # If we run 2to3 we can not do this inplace: + + # Ensure metadata is up-to-date + self.reinitialize_command('build_py', inplace=0) + self.run_command('build_py') + bpy_cmd = self.get_finalized_command("build_py") + build_path = normalize_path(bpy_cmd.build_lib) + + # Build extensions + self.reinitialize_command('egg_info', egg_base=build_path) + self.run_command('egg_info') + + self.reinitialize_command('build_ext', inplace=0) + self.run_command('build_ext') + + # Fixup egg-link and easy-install.pth + ei_cmd = self.get_finalized_command("egg_info") + self.egg_path = build_path + self.dist.location = build_path + self.dist._provider = PathMetadata(build_path, ei_cmd.egg_info) # XXX + else: + # Without 2to3 inplace works fine: + self.run_command('egg_info') + + # Build extensions in-place + self.reinitialize_command('build_ext', inplace=1) + self.run_command('build_ext') + self.install_site_py() # ensure that target dir is site-safe if setuptools.bootstrap_install_from: self.easy_install(setuptools.bootstrap_install_from) diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index a51d88f5..f2260236 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -10,7 +10,15 @@ file, or visit the `EasyInstall home page`__. __ http://packages.python.org/distribute/easy_install.html """ -import sys, os.path, zipimport, shutil, tempfile, zipfile, re, stat, random +import sys +import os +import zipimport +import shutil +import tempfile +import zipfile +import re +import stat +import random from glob import glob from setuptools import Command, _dont_write_bytecode from setuptools.sandbox import run_setup @@ -21,6 +29,7 @@ from distutils.sysconfig import get_python_lib, get_config_vars from distutils.errors import DistutilsArgError, DistutilsOptionError, \ DistutilsError, DistutilsPlatformError from distutils.command.install import INSTALL_SCHEMES, SCHEME_KEYS +from setuptools.command import setopt from setuptools.archive_util import unpack_archive from setuptools.package_index import PackageIndex from setuptools.package_index import URL_SCHEME @@ -761,12 +770,13 @@ Please make the appropriate changes for your system and try again. target = os.path.join(self.script_dir, script_name) self.add_output(target) + mask = current_umask() if not self.dry_run: ensure_directory(target) f = open(target,"w"+mode) f.write(contents) f.close() - chmod(target,0755) + chmod(target, 0777-mask) @@ -1082,11 +1092,14 @@ See the setuptools documentation for the "develop" command for more info. def build_and_install(self, setup_script, setup_base): args = ['bdist_egg', '--dist-dir'] + dist_dir = tempfile.mkdtemp( prefix='egg-dist-tmp-', dir=os.path.dirname(setup_script) ) try: + self._set_fetcher_options(os.path.dirname(setup_script)) args.append(dist_dir) + self.run_setup(setup_script, setup_base, args) all_eggs = Environment([dist_dir]) eggs = [] @@ -1101,6 +1114,30 @@ See the setuptools documentation for the "develop" command for more info. rmtree(dist_dir) log.set_verbosity(self.verbose) # restore our log verbosity + def _set_fetcher_options(self, base): + """ + When easy_install is about to run bdist_egg on a source dist, that + source dist might have 'setup_requires' directives, requiring + additional fetching. Ensure the fetcher options given to easy_install + are available to that command as well. + """ + # find the fetch options from easy_install and write them out + # to the setup.cfg file. + ei_opts = self.distribution.get_option_dict('easy_install').copy() + fetch_directives = ( + 'find_links', 'site_dirs', 'index_url', 'optimize', + 'site_dirs', 'allow_hosts', + ) + fetch_options = {} + for key, val in ei_opts.iteritems(): + if key not in fetch_directives: continue + fetch_options[key.replace('_', '-')] = val[1] + # create a settings dictionary suitable for `edit_config` + settings = dict(easy_install=fetch_options) + cfg_filename = os.path.join(base, 'setup.cfg') + setopt.edit_config(cfg_filename, settings) + + def update_pth(self,dist): if self.pth_file is None: return @@ -1842,6 +1879,11 @@ def rmtree(path, ignore_errors=False, onerror=auto_chmod): except os.error: onerror(os.rmdir, path, sys.exc_info()) +def current_umask(): + tmp = os.umask(022) + os.umask(tmp) + return tmp + def bootstrap(): # This function is called when setuptools*.egg is run using /bin/sh import setuptools; argv0 = os.path.dirname(setuptools.__path__[0]) diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py index 6ce1b993..82456035 100755 --- a/setuptools/command/install_scripts.py +++ b/setuptools/command/install_scripts.py @@ -39,15 +39,16 @@ class install_scripts(_install_scripts): def write_script(self, script_name, contents, mode="t", *ignored): """Write an executable file to the scripts directory""" - from setuptools.command.easy_install import chmod + from setuptools.command.easy_install import chmod, current_umask log.info("Installing %s script to %s", script_name, self.install_dir) target = os.path.join(self.install_dir, script_name) self.outfiles.append(target) + mask = current_umask() if not self.dry_run: ensure_directory(target) f = open(target,"w"+mode) f.write(contents) f.close() - chmod(target,0755) + chmod(target, 0777-mask) diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py index 484f8276..a176f635 100755 --- a/setuptools/command/sdist.py +++ b/setuptools/command/sdist.py @@ -4,6 +4,8 @@ from distutils import log import os, re, sys, pkg_resources from glob import glob +READMES = ('README', 'README.rst', 'README.txt') + entities = [ ("<","<"), (">", ">"), (""", '"'), ("'", "'"), ("&", "&") @@ -97,7 +99,7 @@ def entries_finder(dirname, filename): for match in entries_pattern.finditer(data): yield joinpath(dirname,unescape(match.group(1))) else: - log.warn("unrecognized .svn/entries format in %s", dirname) + log.warn("unrecognized .svn/entries format in %s", os.path.abspath(dirname)) finders = [ @@ -145,7 +147,17 @@ class sdist(_sdist): self.filelist = ei_cmd.filelist self.filelist.append(os.path.join(ei_cmd.egg_info,'SOURCES.txt')) self.check_readme() - self.check_metadata() + + # Run sub commands + for cmd_name in self.get_sub_commands(): + self.run_command(cmd_name) + + # Call check_metadata only if no 'check' command + # (distutils <= 2.6) + import distutils.command + if 'check' not in distutils.command.__all__: + self.check_metadata() + self.make_distribution() dist_files = getattr(self.distribution,'dist_files',[]) @@ -155,7 +167,7 @@ class sdist(_sdist): dist_files.append(data) def add_defaults(self): - standards = [('README', 'README.txt'), + standards = [READMES, self.distribution.script_name] for fn in standards: if isinstance(fn, tuple): @@ -228,13 +240,12 @@ class sdist(_sdist): read_template = __read_template_hack def check_readme(self): - alts = ("README", "README.txt") - for f in alts: + for f in READMES: if os.path.exists(f): return else: self.warn( - "standard file not found: should have one of " +', '.join(alts) + "standard file not found: should have one of " +', '.join(READMES) ) diff --git a/setuptools/command/test.py b/setuptools/command/test.py index b7aef969..e5cb9bb5 100644 --- a/setuptools/command/test.py +++ b/setuptools/command/test.py @@ -81,7 +81,7 @@ class test(Command): def with_project_on_sys_path(self, func): - if getattr(self.distribution, 'use_2to3', False): + if sys.version_info >= (3,) and getattr(self.distribution, 'use_2to3', False): # If we run 2to3 we can not do this inplace: # Ensure metadata is up-to-date @@ -141,9 +141,10 @@ class test(Command): import unittest loader_ep = EntryPoint.parse("x="+self.test_loader) loader_class = loader_ep.load(require=False) + cks = loader_class() unittest.main( None, None, [unittest.__file__]+self.test_args, - testLoader = loader_class() + testLoader = cks ) diff --git a/setuptools/command/upload.py b/setuptools/command/upload.py index 4bd6021d..9f9366b5 100755 --- a/setuptools/command/upload.py +++ b/setuptools/command/upload.py @@ -92,7 +92,7 @@ class upload(Command): comment = "built on %s" % platform.platform(terse=1) data = { ':action':'file_upload', - 'protcol_version':'1', + 'protocol_version':'1', 'name':self.distribution.get_name(), 'version':self.distribution.get_version(), 'content':(basename,content), diff --git a/setuptools/extension.py b/setuptools/extension.py index 980ee0a7..eb8b836c 100644 --- a/setuptools/extension.py +++ b/setuptools/extension.py @@ -1,40 +1,46 @@ -from distutils.core import Extension as _Extension +import sys +import distutils.core +import distutils.extension + from setuptools.dist import _get_unpatched -_Extension = _get_unpatched(_Extension) -# Prefer Cython to Pyrex -pyrex_impls = 'Cython.Distutils.build_ext', 'Pyrex.Distutils.build_ext' -for pyrex_impl in pyrex_impls: - try: - # from (pyrex_impl) import build_ext - build_ext = __import__(pyrex_impl, fromlist=['build_ext']).build_ext - break - except: - pass -have_pyrex = 'build_ext' in globals() +_Extension = _get_unpatched(distutils.core.Extension) + +def have_pyrex(): + """ + Return True if Cython or Pyrex can be imported. + """ + pyrex_impls = 'Cython.Distutils.build_ext', 'Pyrex.Distutils.build_ext' + for pyrex_impl in pyrex_impls: + try: + # from (pyrex_impl) import build_ext + __import__(pyrex_impl, fromlist=['build_ext']).build_ext + return True + except Exception: + pass + return False class Extension(_Extension): """Extension that uses '.c' files in place of '.pyx' files""" - if not have_pyrex: - # convert .pyx extensions to .c - def __init__(self,*args,**kw): - _Extension.__init__(self,*args,**kw) - sources = [] - for s in self.sources: - if s.endswith('.pyx'): - sources.append(s[:-3]+'c') - else: - sources.append(s) - self.sources = sources + def __init__(self, *args, **kw): + _Extension.__init__(self, *args, **kw) + if not have_pyrex(): + self._convert_pyx_sources_to_c() + + def _convert_pyx_sources_to_c(self): + "convert .pyx extensions to .c" + def pyx_to_c(source): + if source.endswith('.pyx'): + source = source[:-4] + '.c' + return source + self.sources = map(pyx_to_c, self.sources) class Library(Extension): """Just like a regular Extension, but built as a library instead""" -import sys, distutils.core, distutils.extension distutils.core.Extension = Extension distutils.extension.Extension = Extension if 'distutils.command.build_ext' in sys.modules: sys.modules['distutils.command.build_ext'].Extension = Extension - diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py index 8e0c09b5..ab2543d9 100755 --- a/setuptools/sandbox.py +++ b/setuptools/sandbox.py @@ -39,8 +39,14 @@ def run_setup(setup_script, args): finally: pkg_resources.__setstate__(pr_state) sys.modules.update(save_modules) - for key in list(sys.modules): - if key not in save_modules: del sys.modules[key] + # remove any modules imported within the sandbox + del_modules = [ + mod_name for mod_name in sys.modules + if mod_name not in save_modules + # exclude any encodings modules. See #285 + and not mod_name.startswith('encodings.') + ] + map(sys.modules.__delitem__, del_modules) os.chdir(old_dir) sys.path[:] = save_path sys.argv[:] = save_argv diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py index 9af44a88..eec76efd 100644 --- a/setuptools/tests/__init__.py +++ b/setuptools/tests/__init__.py @@ -1,16 +1,19 @@ """Tests for the 'setuptools' package""" -from unittest import TestSuite, TestCase, makeSuite, defaultTestLoader -import distutils.core, distutils.cmd +import sys +import os +import unittest +import doctest +import distutils.core +import distutils.cmd from distutils.errors import DistutilsOptionError, DistutilsPlatformError from distutils.errors import DistutilsSetupError -import setuptools, setuptools.dist -from setuptools import Feature from distutils.core import Extension -extract_constant, get_module_constant = None, None -from setuptools.depends import * -from distutils.version import StrictVersion, LooseVersion -from distutils.util import convert_path -import sys, os.path +from distutils.version import LooseVersion + +import setuptools.dist +import setuptools.depends as dep +from setuptools import Feature +from setuptools.depends import Require def additional_tests(): import doctest, unittest @@ -38,51 +41,56 @@ def makeSetup(**args): distutils.core_setup_stop_after = None - - -class DependsTests(TestCase): +class DependsTests(unittest.TestCase): def testExtractConst(self): - if not extract_constant: return # skip on non-bytecode platforms + if not hasattr(dep, 'extract_constant'): + # skip on non-bytecode platforms + return def f1(): - global x,y,z + global x, y, z x = "test" y = z # unrecognized name - self.assertEqual(extract_constant(f1.func_code,'q', -1), None) + self.assertEqual(dep.extract_constant(f1.func_code,'q', -1), None) # constant assigned - self.assertEqual(extract_constant(f1.func_code,'x', -1), "test") + self.assertEqual(dep.extract_constant(f1.func_code,'x', -1), "test") # expression assigned - self.assertEqual(extract_constant(f1.func_code,'y', -1), -1) + self.assertEqual(dep.extract_constant(f1.func_code,'y', -1), -1) # recognized name, not assigned - self.assertEqual(extract_constant(f1.func_code,'z', -1), None) - + self.assertEqual(dep.extract_constant(f1.func_code,'z', -1), None) def testFindModule(self): - self.assertRaises(ImportError, find_module, 'no-such.-thing') - self.assertRaises(ImportError, find_module, 'setuptools.non-existent') - f,p,i = find_module('setuptools.tests'); f.close() + self.assertRaises(ImportError, dep.find_module, 'no-such.-thing') + self.assertRaises(ImportError, dep.find_module, 'setuptools.non-existent') + f,p,i = dep.find_module('setuptools.tests') + f.close() def testModuleExtract(self): - if not get_module_constant: return # skip on non-bytecode platforms + if not hasattr(dep, 'get_module_constant'): + # skip on non-bytecode platforms + return + from email import __version__ self.assertEqual( - get_module_constant('email','__version__'), __version__ + dep.get_module_constant('email','__version__'), __version__ ) self.assertEqual( - get_module_constant('sys','version'), sys.version + dep.get_module_constant('sys','version'), sys.version ) self.assertEqual( - get_module_constant('setuptools.tests','__doc__'),__doc__ + dep.get_module_constant('setuptools.tests','__doc__'),__doc__ ) def testRequire(self): - if not extract_constant: return # skip on non-bytecode platforms + if not hasattr(dep, 'extract_constant'): + # skip on non-bytecode platformsh + return req = Require('Email','1.0.3','email') @@ -94,21 +102,21 @@ class DependsTests(TestCase): from email import __version__ self.assertEqual(req.get_version(), __version__) - self.assert_(req.version_ok('1.0.9')) - self.assert_(not req.version_ok('0.9.1')) - self.assert_(not req.version_ok('unknown')) + self.assertTrue(req.version_ok('1.0.9')) + self.assertTrue(not req.version_ok('0.9.1')) + self.assertTrue(not req.version_ok('unknown')) - self.assert_(req.is_present()) - self.assert_(req.is_current()) + self.assertTrue(req.is_present()) + self.assertTrue(req.is_current()) req = Require('Email 3000','03000','email',format=LooseVersion) - self.assert_(req.is_present()) - self.assert_(not req.is_current()) - self.assert_(not req.version_ok('unknown')) + self.assertTrue(req.is_present()) + self.assertTrue(not req.is_current()) + self.assertTrue(not req.version_ok('unknown')) req = Require('Do-what-I-mean','1.0','d-w-i-m') - self.assert_(not req.is_present()) - self.assert_(not req.is_current()) + self.assertTrue(not req.is_present()) + self.assertTrue(not req.is_current()) req = Require('Tests', None, 'tests', homepage="http://example.com") self.assertEqual(req.format, None) @@ -118,11 +126,11 @@ class DependsTests(TestCase): self.assertEqual(req.homepage, 'http://example.com') paths = [os.path.dirname(p) for p in __path__] - self.assert_(req.is_present(paths)) - self.assert_(req.is_current(paths)) + self.assertTrue(req.is_present(paths)) + self.assertTrue(req.is_current(paths)) -class DistroTests(TestCase): +class DistroTests(unittest.TestCase): def setUp(self): self.e1 = Extension('bar.ext',['bar.c']) @@ -135,10 +143,8 @@ class DistroTests(TestCase): package_dir = {}, ) - def testDistroType(self): - self.assert_(isinstance(self.dist,setuptools.dist.Distribution)) - + self.assertTrue(isinstance(self.dist,setuptools.dist.Distribution)) def testExcludePackage(self): self.dist.exclude_package('a') @@ -157,12 +163,6 @@ class DistroTests(TestCase): # test removals from unspecified options makeSetup().exclude_package('x') - - - - - - def testIncludeExclude(self): # remove an extension self.dist.exclude(ext_modules=[self.e1]) @@ -189,20 +189,17 @@ class DistroTests(TestCase): dist.exclude(packages=['a'], py_modules=['b'], ext_modules=[self.e2]) def testContents(self): - self.assert_(self.dist.has_contents_for('a')) + self.assertTrue(self.dist.has_contents_for('a')) self.dist.exclude_package('a') - self.assert_(not self.dist.has_contents_for('a')) + self.assertTrue(not self.dist.has_contents_for('a')) - self.assert_(self.dist.has_contents_for('b')) + self.assertTrue(self.dist.has_contents_for('b')) self.dist.exclude_package('b') - self.assert_(not self.dist.has_contents_for('b')) + self.assertTrue(not self.dist.has_contents_for('b')) - self.assert_(self.dist.has_contents_for('c')) + self.assertTrue(self.dist.has_contents_for('c')) self.dist.exclude_package('c') - self.assert_(not self.dist.has_contents_for('c')) - - - + self.assertTrue(not self.dist.has_contents_for('c')) def testInvalidIncludeExclude(self): self.assertRaises(DistutilsSetupError, @@ -232,20 +229,7 @@ class DistroTests(TestCase): ) - - - - - - - - - - - - - -class FeatureTests(TestCase): +class FeatureTests(unittest.TestCase): def setUp(self): self.req = Require('Distutils','1.0.3','distutils') @@ -269,12 +253,12 @@ class FeatureTests(TestCase): ) def testDefaults(self): - self.assert_(not + self.assertTrue(not Feature( "test",standard=True,remove='x',available=False ).include_by_default() ) - self.assert_( + self.assertTrue( Feature("test",standard=True,remove='x').include_by_default() ) # Feature must have either kwargs, removes, or require_features @@ -288,33 +272,33 @@ class FeatureTests(TestCase): def testFeatureOptions(self): dist = self.dist - self.assert_( + self.assertTrue( ('with-dwim',None,'include DWIM') in dist.feature_options ) - self.assert_( + self.assertTrue( ('without-dwim',None,'exclude DWIM (default)') in dist.feature_options ) - self.assert_( + self.assertTrue( ('with-bar',None,'include bar (default)') in dist.feature_options ) - self.assert_( + self.assertTrue( ('without-bar',None,'exclude bar') in dist.feature_options ) self.assertEqual(dist.feature_negopt['without-foo'],'with-foo') self.assertEqual(dist.feature_negopt['without-bar'],'with-bar') self.assertEqual(dist.feature_negopt['without-dwim'],'with-dwim') - self.assert_(not 'without-baz' in dist.feature_negopt) + self.assertTrue(not 'without-baz' in dist.feature_negopt) def testUseFeatures(self): dist = self.dist self.assertEqual(dist.with_foo,1) self.assertEqual(dist.with_bar,0) self.assertEqual(dist.with_baz,1) - self.assert_(not 'bar_et' in dist.py_modules) - self.assert_(not 'pkg.bar' in dist.packages) - self.assert_('pkg.baz' in dist.packages) - self.assert_('scripts/baz_it' in dist.scripts) - self.assert_(('libfoo','foo/foofoo.c') in dist.libraries) + self.assertTrue(not 'bar_et' in dist.py_modules) + self.assertTrue(not 'pkg.bar' in dist.packages) + self.assertTrue('pkg.baz' in dist.packages) + self.assertTrue('scripts/baz_it' in dist.scripts) + self.assertTrue(('libfoo','foo/foofoo.c') in dist.libraries) self.assertEqual(dist.ext_modules,[]) self.assertEqual(dist.require_features, [self.req]) @@ -327,11 +311,11 @@ class FeatureTests(TestCase): SystemExit, makeSetup, features = {'x':Feature('x', remove='y')} ) -class TestCommandTests(TestCase): +class TestCommandTests(unittest.TestCase): def testTestIsCommand(self): test_cmd = makeSetup().get_command_obj('test') - self.assert_(isinstance(test_cmd, distutils.cmd.Command)) + self.assertTrue(isinstance(test_cmd, distutils.cmd.Command)) def testLongOptSuiteWNoDefault(self): ts1 = makeSetup(script_args=['test','--test-suite=foo.tests.suite']) @@ -363,8 +347,3 @@ class TestCommandTests(TestCase): ts5 = makeSetup().get_command_obj('test') ts5.ensure_finalized() self.assertEqual(ts5.test_suite, None) - - - - - diff --git a/setuptools/tests/py26compat.py b/setuptools/tests/py26compat.py new file mode 100644 index 00000000..d4fb891a --- /dev/null +++ b/setuptools/tests/py26compat.py @@ -0,0 +1,14 @@ +import unittest + +try: + # provide skipIf for Python 2.4-2.6 + skipIf = unittest.skipIf +except AttributeError: + def skipIf(condition, reason): + def skipper(func): + def skip(*args, **kwargs): + return + if condition: + return skip + return func + return skipper diff --git a/setuptools/tests/server.py b/setuptools/tests/server.py index f4aaaa1c..b2ab7acc 100644 --- a/setuptools/tests/server.py +++ b/setuptools/tests/server.py @@ -2,7 +2,9 @@ """ import urllib2 import sys -from threading import Thread +import time +import threading +import BaseHTTPServer from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler @@ -17,32 +19,64 @@ class IndexServer(HTTPServer): # The index files should be located in setuptools/tests/indexes s.stop() """ - def __init__(self): - HTTPServer.__init__(self, ('', 0), SimpleHTTPRequestHandler) + def __init__(self, server_address=('', 0), + RequestHandlerClass=SimpleHTTPRequestHandler): + HTTPServer.__init__(self, server_address, RequestHandlerClass) self._run = True def serve(self): - while True: + while self._run: self.handle_request() - if not self._run: break def start(self): - self.thread = Thread(target=self.serve) + self.thread = threading.Thread(target=self.serve) self.thread.start() def stop(self): - """self.shutdown is not supported on python < 2.6""" + "Stop the server" + + # Let the server finish the last request and wait for a new one. + time.sleep(0.1) + + # self.shutdown is not supported on python < 2.6, so just + # set _run to false, and make a request, causing it to + # terminate. self._run = False + url = 'http://127.0.0.1:%(server_port)s/' % vars(self) try: - if sys.version > '2.6': - urllib2.urlopen('http://127.0.0.1:%s/' % self.server_port, - None, 5) + if sys.version_info >= (2, 6): + urllib2.urlopen(url, timeout=5) else: - urllib2.urlopen('http://127.0.0.1:%s/' % self.server_port) + urllib2.urlopen(url) except urllib2.URLError: + # ignore any errors; all that's important is the request pass self.thread.join() def base_url(self): port = self.server_port return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port + +class RequestRecorder(BaseHTTPServer.BaseHTTPRequestHandler): + def do_GET(self): + requests = vars(self.server).setdefault('requests', []) + requests.append(self) + self.send_response(200, 'OK') + +class MockServer(HTTPServer, threading.Thread): + """ + A simple HTTP Server that records the requests made to it. + """ + def __init__(self, server_address=('', 0), + RequestHandlerClass=RequestRecorder): + HTTPServer.__init__(self, server_address, RequestHandlerClass) + threading.Thread.__init__(self) + self.setDaemon(True) + self.requests = [] + + def run(self): + self.serve_forever() + + def url(self): + return 'http://localhost:%(server_port)s/' % vars(self) + url = property(url) diff --git a/setuptools/tests/test_bdist_egg.py b/setuptools/tests/test_bdist_egg.py new file mode 100644 index 00000000..7da122cc --- /dev/null +++ b/setuptools/tests/test_bdist_egg.py @@ -0,0 +1,69 @@ +"""develop tests +""" +import sys +import os, re, shutil, tempfile, unittest +import tempfile +import site +from StringIO import StringIO + +from distutils.errors import DistutilsError +from setuptools.command.bdist_egg import bdist_egg +from setuptools.command import easy_install as easy_install_pkg +from setuptools.dist import Distribution + +SETUP_PY = """\ +from setuptools import setup + +setup(name='foo', py_modules=['hi']) +""" + +class TestDevelopTest(unittest.TestCase): + + def setUp(self): + self.dir = tempfile.mkdtemp() + self.old_cwd = os.getcwd() + os.chdir(self.dir) + f = open('setup.py', 'w') + f.write(SETUP_PY) + f.close() + f = open('hi.py', 'w') + f.write('1\n') + f.close() + if sys.version >= "2.6": + self.old_base = site.USER_BASE + site.USER_BASE = tempfile.mkdtemp() + self.old_site = site.USER_SITE + site.USER_SITE = tempfile.mkdtemp() + + def tearDown(self): + os.chdir(self.old_cwd) + shutil.rmtree(self.dir) + if sys.version >= "2.6": + shutil.rmtree(site.USER_BASE) + shutil.rmtree(site.USER_SITE) + site.USER_BASE = self.old_base + site.USER_SITE = self.old_site + + def test_bdist_egg(self): + dist = Distribution(dict( + script_name='setup.py', + script_args=['bdist_egg'], + name='foo', + py_modules=['hi'] + )) + os.makedirs(os.path.join('build', 'src')) + old_stdout = sys.stdout + sys.stdout = o = StringIO() + try: + dist.parse_command_line() + dist.run_commands() + finally: + sys.stdout = old_stdout + + # let's see if we got our egg link at the right place + [content] = os.listdir('dist') + self.assertTrue(re.match('foo-0.0.0-py[23].\d.egg$', content)) + +def test_suite(): + return unittest.makeSuite(TestDevelopTest) + diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py index 5576d5e5..3e071dad 100644 --- a/setuptools/tests/test_develop.py +++ b/setuptools/tests/test_develop.py @@ -14,38 +14,62 @@ from setuptools.dist import Distribution SETUP_PY = """\ from setuptools import setup -setup(name='foo') +setup(name='foo', + packages=['foo'], + use_2to3=True, +) +""" + +INIT_PY = """print "foo" """ class TestDevelopTest(unittest.TestCase): def setUp(self): + if sys.version < "2.6" or hasattr(sys, 'real_prefix'): + return + + # Directory structure self.dir = tempfile.mkdtemp() + os.mkdir(os.path.join(self.dir, 'foo')) + # setup.py setup = os.path.join(self.dir, 'setup.py') f = open(setup, 'w') f.write(SETUP_PY) f.close() self.old_cwd = os.getcwd() + # foo/__init__.py + init = os.path.join(self.dir, 'foo', '__init__.py') + f = open(init, 'w') + f.write(INIT_PY) + f.close() + os.chdir(self.dir) - if sys.version >= "2.6": - self.old_base = site.USER_BASE - site.USER_BASE = tempfile.mkdtemp() - self.old_site = site.USER_SITE - site.USER_SITE = tempfile.mkdtemp() + self.old_base = site.USER_BASE + site.USER_BASE = tempfile.mkdtemp() + self.old_site = site.USER_SITE + site.USER_SITE = tempfile.mkdtemp() def tearDown(self): + if sys.version < "2.6" or hasattr(sys, 'real_prefix'): + return + os.chdir(self.old_cwd) shutil.rmtree(self.dir) - if sys.version >= "2.6": - shutil.rmtree(site.USER_BASE) - shutil.rmtree(site.USER_SITE) - site.USER_BASE = self.old_base - site.USER_SITE = self.old_site + shutil.rmtree(site.USER_BASE) + shutil.rmtree(site.USER_SITE) + site.USER_BASE = self.old_base + site.USER_SITE = self.old_site def test_develop(self): if sys.version < "2.6" or hasattr(sys, 'real_prefix'): return - dist = Distribution() + dist = Distribution( + dict(name='foo', + packages=['foo'], + use_2to3=True, + version='0.0', + )) dist.script_name = 'setup.py' cmd = develop(dist) cmd.user = 1 @@ -53,7 +77,7 @@ class TestDevelopTest(unittest.TestCase): cmd.install_dir = site.USER_SITE cmd.user = 1 old_stdout = sys.stdout - sys.stdout = StringIO() + #sys.stdout = StringIO() try: cmd.run() finally: @@ -62,9 +86,17 @@ class TestDevelopTest(unittest.TestCase): # let's see if we got our egg link at the right place content = os.listdir(site.USER_SITE) content.sort() - self.assertEquals(content, ['UNKNOWN.egg-link', 'easy-install.pth']) + self.assertEqual(content, ['easy-install.pth', 'foo.egg-link']) + + # Check that we are using the right code. + path = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt').read().split()[0].strip() + init = open(os.path.join(path, 'foo', '__init__.py'), 'rt').read().strip() + if sys.version < "3": + self.assertEqual(init, 'print "foo"') + else: + self.assertEqual(init, 'print("foo")') - def test_develop_with_setup_requires(self): + def notest_develop_with_setup_requires(self): wanted = ("Could not find suitable distribution for " "Requirement.parse('I-DONT-EXIST')") diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py new file mode 100644 index 00000000..70dce2d4 --- /dev/null +++ b/setuptools/tests/test_dist_info.py @@ -0,0 +1,76 @@ +"""Test .dist-info style distributions. +""" +import os +import shutil +import tempfile +import unittest +import textwrap + +try: + import _markerlib +except: + pass + +import pkg_resources + +from setuptools.tests.py26compat import skipIf + +def DALS(s): + "dedent and left-strip" + return textwrap.dedent(s).lstrip() + +class TestDistInfo(unittest.TestCase): + + def test_distinfo(self): + dists = {} + for d in pkg_resources.find_distributions(self.tmpdir): + dists[d.project_name] = d + + assert len(dists) == 2, dists + + unversioned = dists['UnversionedDistribution'] + versioned = dists['VersionedDistribution'] + + assert versioned.version == '2.718' # from filename + assert unversioned.version == '0.3' # from METADATA + + @skipIf('_markerlib' not in globals(), + "_markerlib is used to test conditional dependencies (Python >= 2.5)") + def test_conditional_dependencies(self): + requires = [pkg_resources.Requirement.parse('splort==4'), + pkg_resources.Requirement.parse('quux>=1.1')] + + for d in pkg_resources.find_distributions(self.tmpdir): + self.assertEqual(d.requires(), requires[:1]) + self.assertEqual(d.requires(extras=('baz',)), requires) + self.assertEqual(d.extras, ['baz']) + + def setUp(self): + self.tmpdir = tempfile.mkdtemp() + versioned = os.path.join(self.tmpdir, + 'VersionedDistribution-2.718.dist-info') + os.mkdir(versioned) + open(os.path.join(versioned, 'METADATA'), 'w+').write(DALS( + """ + Metadata-Version: 1.2 + Name: VersionedDistribution + Requires-Dist: splort (4) + Provides-Extra: baz + Requires-Dist: quux (>=1.1); extra == 'baz' + """)) + + unversioned = os.path.join(self.tmpdir, + 'UnversionedDistribution.dist-info') + os.mkdir(unversioned) + open(os.path.join(unversioned, 'METADATA'), 'w+').write(DALS( + """ + Metadata-Version: 1.2 + Name: UnversionedDistribution + Version: 0.3 + Requires-Dist: splort (==4) + Provides-Extra: baz + Requires-Dist: quux (>=1.1); extra == 'baz' + """)) + + def tearDown(self): + shutil.rmtree(self.tmpdir) diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 4150ad10..13f668d0 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -1,17 +1,27 @@ """Easy install Tests """ import sys -import os, shutil, tempfile, unittest +import os +import shutil +import tempfile +import unittest import site -from StringIO import StringIO +import textwrap +import tarfile +import urlparse +import StringIO +import distutils.core + 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 +68,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) @@ -71,7 +81,7 @@ class TestEasyInstallTest(unittest.TestCase): 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 +102,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 @@ -104,30 +114,31 @@ class TestEasyInstallTest(unittest.TestCase): 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 = cmd.package_index.scanned_urls.keys() keys.sort() - self.assertEquals(keys, ['link1', 'link2']) + self.assertEqual(keys, ['link1', 'link2']) class TestPTHFileWriter(unittest.TestCase): @@ -136,9 +147,9 @@ 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): if os.name != 'nt': @@ -146,9 +157,9 @@ class TestPTHFileWriter(unittest.TestCase): else: location = 'c:\\does_not_exist' pth = PthDistributions('does-not_exist', [location, ]) - self.assert_(not pth.dirty) + self.assertTrue(not pth.dirty) pth.add(PRDistribution(location)) - self.assert_(not pth.dirty) + self.assertTrue(not pth.dirty) class TestUserInstallTest(unittest.TestCase): @@ -173,7 +184,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 @@ -235,7 +246,8 @@ 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) for basedir in [new_location, target, ]: @@ -250,3 +262,134 @@ class TestUserInstallTest(unittest.TestCase): else: del os.environ['PYTHONPATH'] + +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.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): + 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() + installer(dist_path) + tempdir_context(build_sdist) + +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 diff --git a/setuptools/tests/test_markerlib.py b/setuptools/tests/test_markerlib.py new file mode 100644 index 00000000..4cce0430 --- /dev/null +++ b/setuptools/tests/test_markerlib.py @@ -0,0 +1,98 @@ +import os +import unittest +from setuptools.tests.py26compat import skipIf + +try: + import _ast +except ImportError: + pass + +class TestMarkerlib(unittest.TestCase): + + @skipIf('_ast' not in globals(), + "ast not available (Python < 2.5?)") + def test_markers(self): + from _markerlib import interpret, default_environment, compile + + os_name = os.name + + self.assert_(interpret("")) + + self.assert_(interpret("os.name != 'buuuu'")) + self.assert_(interpret("python_version > '1.0'")) + self.assert_(interpret("python_version < '5.0'")) + self.assert_(interpret("python_version <= '5.0'")) + self.assert_(interpret("python_version >= '1.0'")) + self.assert_(interpret("'%s' in os.name" % os_name)) + self.assert_(interpret("'buuuu' not in os.name")) + + self.assertFalse(interpret("os.name == 'buuuu'")) + self.assertFalse(interpret("python_version < '1.0'")) + self.assertFalse(interpret("python_version > '5.0'")) + self.assertFalse(interpret("python_version >= '5.0'")) + self.assertFalse(interpret("python_version <= '1.0'")) + self.assertFalse(interpret("'%s' not in os.name" % os_name)) + self.assertFalse(interpret("'buuuu' in os.name and python_version >= '5.0'")) + + environment = default_environment() + environment['extra'] = 'test' + self.assert_(interpret("extra == 'test'", environment)) + self.assertFalse(interpret("extra == 'doc'", environment)) + + def raises_nameError(): + try: + interpret("python.version == '42'") + except NameError: + pass + else: + raise Exception("Expected NameError") + + raises_nameError() + + def raises_syntaxError(): + try: + interpret("(x for x in (4,))") + except SyntaxError: + pass + else: + raise Exception("Expected SyntaxError") + + raises_syntaxError() + + statement = "python_version == '5'" + self.assertEqual(compile(statement).__doc__, statement) + + @skipIf('_ast' not in globals(), + "ast not available (Python < 2.5?)") + def test_ast(self): + try: + import ast, nose + raise nose.SkipTest() + except ImportError: + pass + + # Nonsensical code coverage tests. + import _markerlib._markers_ast as _markers_ast + + class Node(_ast.AST): + _fields = ('bogus') + list(_markers_ast.iter_fields(Node())) + + class Node2(_ast.AST): + def __init__(self): + self._fields = ('bogus',) + self.bogus = [Node()] + + class NoneTransformer(_markers_ast.NodeTransformer): + def visit_Attribute(self, node): + return None + + def visit_Str(self, node): + return None + + def visit_Node(self, node): + return [] + + NoneTransformer().visit(_markers_ast.parse('a.b = "c"')) + NoneTransformer().visit(Node2()) + diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 00d44ca6..3e446b54 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -1,24 +1,27 @@ """Package Index Tests """ -# More would be better! import sys -import os, shutil, tempfile, unittest, urllib2 +import unittest +import urllib2 import pkg_resources +import httplib +import distutils.errors import setuptools.package_index from server import IndexServer class TestPackageIndex(unittest.TestCase): - def test_bad_urls(self): + def test_bad_url_bad_port(self): index = setuptools.package_index.PackageIndex() url = 'http://127.0.0.1:0/nonesuch/test_package_index' try: v = index.open_url(url) except Exception, v: - self.assert_(url in str(v)) + self.assertTrue(url in str(v)) else: - self.assert_(isinstance(v,urllib2.HTTPError)) + self.assertTrue(isinstance(v,urllib2.HTTPError)) + def test_bad_url_typo(self): # issue 16 # easy_install inquant.contentmirror.plone breaks because of a typo # in its home URL @@ -30,9 +33,14 @@ class TestPackageIndex(unittest.TestCase): try: v = index.open_url(url) except Exception, v: - self.assert_(url in str(v)) + self.assertTrue(url in str(v)) else: - self.assert_(isinstance(v, urllib2.HTTPError)) + self.assertTrue(isinstance(v, urllib2.HTTPError)) + + def test_bad_url_bad_status_line(self): + index = setuptools.package_index.PackageIndex( + hosts=('www.example.com',) + ) def _urlopen(*args): import httplib @@ -45,19 +53,34 @@ class TestPackageIndex(unittest.TestCase): try: v = index.open_url(url) except Exception, v: - self.assert_('line' in str(v)) + self.assertTrue('line' in str(v)) else: raise AssertionError('Should have raise here!') finally: urllib2.urlopen = old_urlopen + def test_bad_url_double_scheme(self): + """ + A bad URL with a double scheme should raise a DistutilsError. + """ + index = setuptools.package_index.PackageIndex( + hosts=('www.example.com',) + ) + # issue 20 url = 'http://http://svn.pythonpaste.org/Paste/wphp/trunk' try: index.open_url(url) - except Exception, v: - self.assert_('nonnumeric port' in str(v)) + except distutils.errors.DistutilsError, error: + msg = unicode(error) + assert 'nonnumeric port' in msg or 'getaddrinfo failed' in msg or 'Name or service not known' in msg + return + raise RuntimeError("Did not raise") + def test_bad_url_screwy_href(self): + index = setuptools.package_index.PackageIndex( + hosts=('www.example.com',) + ) # issue #160 if sys.version_info[0] == 2 and sys.version_info[1] == 7: @@ -67,13 +90,12 @@ class TestPackageIndex(unittest.TestCase): 'http://www.famfamfam.com/">') index.process_index(url, page) - def test_url_ok(self): index = setuptools.package_index.PackageIndex( hosts=('www.example.com',) ) url = 'file:///tmp/test_package_index' - self.assert_(index.url_ok(url, True)) + self.assertTrue(index.url_ok(url, True)) def test_links_priority(self): """ @@ -90,6 +112,10 @@ class TestPackageIndex(unittest.TestCase): is used -> Distribute should use the link from pypi, not the external one. """ + if sys.platform.startswith('java'): + # Skip this test on jython because binding to :0 fails + return + # start an index server server = IndexServer() server.start() @@ -102,11 +128,11 @@ class TestPackageIndex(unittest.TestCase): server.stop() # the distribution has been found - self.assert_('foobar' in pi) + self.assertTrue('foobar' in pi) # we have only one link, because links are compared without md5 - self.assert_(len(pi['foobar'])==1) + self.assertTrue(len(pi['foobar'])==1) # the link should be from the index - self.assert_('correct_md5' in pi['foobar'][0].location) + self.assertTrue('correct_md5' in pi['foobar'][0].location) def test_parse_bdist_wininst(self): self.assertEqual(setuptools.package_index.parse_bdist_wininst( @@ -117,5 +143,3 @@ class TestPackageIndex(unittest.TestCase): 'reportlab-2.5.win-amd64-py2.7.exe'), ('reportlab-2.5', '2.7', 'win-amd64')) self.assertEqual(setuptools.package_index.parse_bdist_wininst( 'reportlab-2.5.win-amd64.exe'), ('reportlab-2.5', None, 'win-amd64')) - - diff --git a/setuptools/tests/test_resources.py b/setuptools/tests/test_resources.py index 3e0309f1..d08fa325 100644 --- a/setuptools/tests/test_resources.py +++ b/setuptools/tests/test_resources.py @@ -45,7 +45,7 @@ class DistroTests(TestCase): ad.add(Distribution.from_filename("FooPkg-1.2-py2.4.egg")) # Name is in there now - self.assert_(ad['FooPkg']) + self.assertTrue(ad['FooPkg']) # But only 1 package self.assertEqual(list(ad), ['foopkg']) @@ -228,7 +228,7 @@ class EntryPointTests(TestCase): self.assertEqual(ep.module_name,"setuptools.tests.test_resources") self.assertEqual(ep.attrs, ("EntryPointTests",)) self.assertEqual(ep.extras, ("x",)) - self.assert_(ep.load() is EntryPointTests) + self.assertTrue(ep.load() is EntryPointTests) self.assertEqual( str(ep), "foo = setuptools.tests.test_resources:EntryPointTests [x]" @@ -328,20 +328,20 @@ class RequirementsTests(TestCase): foo_dist = Distribution.from_filename("FooPkg-1.3_1.egg") twist11 = Distribution.from_filename("Twisted-1.1.egg") twist12 = Distribution.from_filename("Twisted-1.2.egg") - self.assert_(parse_version('1.2') in r) - self.assert_(parse_version('1.1') not in r) - self.assert_('1.2' in r) - self.assert_('1.1' not in r) - self.assert_(foo_dist not in r) - self.assert_(twist11 not in r) - self.assert_(twist12 in r) + self.assertTrue(parse_version('1.2') in r) + self.assertTrue(parse_version('1.1') not in r) + self.assertTrue('1.2' in r) + self.assertTrue('1.1' not in r) + self.assertTrue(foo_dist not in r) + self.assertTrue(twist11 not in r) + self.assertTrue(twist12 in r) def testAdvancedContains(self): r, = parse_requirements("Foo>=1.2,<=1.3,==1.9,>2.0,!=2.5,<3.0,==4.5") for v in ('1.2','1.2.2','1.3','1.9','2.0.1','2.3','2.6','3.0c1','4.5'): - self.assert_(v in r, (v,r)) + self.assertTrue(v in r, (v,r)) for v in ('1.2c1','1.3.1','1.5','1.9.1','2.0','2.5','3.0','4.0'): - self.assert_(v not in r, (v,r)) + self.assertTrue(v not in r, (v,r)) def testOptionsAndHashing(self): @@ -363,14 +363,14 @@ class RequirementsTests(TestCase): r2 = Requirement.parse("foo!=0.3a4") d = Distribution.from_filename - self.assert_(d("foo-0.3a4.egg") not in r1) - self.assert_(d("foo-0.3a1.egg") not in r1) - self.assert_(d("foo-0.3a4.egg") not in r2) + self.assertTrue(d("foo-0.3a4.egg") not in r1) + self.assertTrue(d("foo-0.3a1.egg") not in r1) + self.assertTrue(d("foo-0.3a4.egg") not in r2) - self.assert_(d("foo-0.3a2.egg") in r1) - self.assert_(d("foo-0.3a2.egg") in r2) - self.assert_(d("foo-0.3a3.egg") in r2) - self.assert_(d("foo-0.3a5.egg") in r2) + self.assertTrue(d("foo-0.3a2.egg") in r1) + self.assertTrue(d("foo-0.3a2.egg") in r2) + self.assertTrue(d("foo-0.3a3.egg") in r2) + self.assertTrue(d("foo-0.3a5.egg") in r2) def testDistributeSetuptoolsOverride(self): # Plain setuptools or distribute mean we return distribute. @@ -489,7 +489,7 @@ class ParseTests(TestCase): def testVersionOrdering(self): def c(s1,s2): p1, p2 = parse_version(s1),parse_version(s2) - self.assert_(p1<p2, (s1,s2,p1,p2)) + self.assertTrue(p1<p2, (s1,s2,p1,p2)) c('2.1','2.1.1') c('2.1.0','2.10') @@ -577,12 +577,12 @@ class ScriptHeaderTests(TestCase): self.assertEqual(get_script_header('#!/usr/bin/python -x', executable=exe), '#!%s -x\n' % exe) - self.assert_('Unable to adapt shebang line' in sys.stdout.getvalue()) + self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue()) sys.stdout = sys.stderr = StringIO.StringIO() self.assertEqual(get_script_header('#!/usr/bin/python', executable=self.non_ascii_exe), '#!%s -x\n' % self.non_ascii_exe) - self.assert_('Unable to adapt shebang line' in sys.stdout.getvalue()) + self.assertTrue('Unable to adapt shebang line' in sys.stdout.getvalue()) finally: sys.platform = platform sys.stdout = stdout diff --git a/setuptools/tests/test_test.py b/setuptools/tests/test_test.py new file mode 100644 index 00000000..ad7cbd0f --- /dev/null +++ b/setuptools/tests/test_test.py @@ -0,0 +1,124 @@ +# -*- coding: UTF-8 -*- + +"""develop tests +""" +import sys +import os, shutil, tempfile, unittest +import tempfile +import site +from StringIO import StringIO + +from distutils.errors import DistutilsError +from setuptools.command.test import test +from setuptools.command import easy_install as easy_install_pkg +from setuptools.dist import Distribution + +SETUP_PY = """\ +from setuptools import setup + +setup(name='foo', + packages=['name', 'name.space', 'name.space.tests'], + namespace_packages=['name'], + test_suite='name.space.tests.test_suite', +) +""" + +NS_INIT = """# -*- coding: Latin-1 -*- +# Söme Arbiträry Ünicode to test Issüé 310 +try: + __import__('pkg_resources').declare_namespace(__name__) +except ImportError: + from pkgutil import extend_path + __path__ = extend_path(__path__, __name__) +""" +# Make sure this is Latin-1 binary, before writing: +if sys.version_info < (3,): + NS_INIT = NS_INIT.decode('UTF-8') +NS_INIT = NS_INIT.encode('Latin-1') + +TEST_PY = """import unittest + +class TestTest(unittest.TestCase): + def test_test(self): + print "Foo" # Should fail under Python 3 unless 2to3 is used + +test_suite = unittest.makeSuite(TestTest) +""" + +class TestTestTest(unittest.TestCase): + + def setUp(self): + if sys.version < "2.6" or hasattr(sys, 'real_prefix'): + return + + # Directory structure + self.dir = tempfile.mkdtemp() + os.mkdir(os.path.join(self.dir, 'name')) + os.mkdir(os.path.join(self.dir, 'name', 'space')) + os.mkdir(os.path.join(self.dir, 'name', 'space', 'tests')) + # setup.py + setup = os.path.join(self.dir, 'setup.py') + f = open(setup, 'wt') + f.write(SETUP_PY) + f.close() + self.old_cwd = os.getcwd() + # name/__init__.py + init = os.path.join(self.dir, 'name', '__init__.py') + f = open(init, 'wb') + f.write(NS_INIT) + f.close() + # name/space/__init__.py + init = os.path.join(self.dir, 'name', 'space', '__init__.py') + f = open(init, 'wt') + f.write('#empty\n') + f.close() + # name/space/tests/__init__.py + init = os.path.join(self.dir, 'name', 'space', 'tests', '__init__.py') + f = open(init, 'wt') + f.write(TEST_PY) + f.close() + + os.chdir(self.dir) + self.old_base = site.USER_BASE + site.USER_BASE = tempfile.mkdtemp() + self.old_site = site.USER_SITE + site.USER_SITE = tempfile.mkdtemp() + + def tearDown(self): + if sys.version < "2.6" or hasattr(sys, 'real_prefix'): + return + + os.chdir(self.old_cwd) + shutil.rmtree(self.dir) + shutil.rmtree(site.USER_BASE) + shutil.rmtree(site.USER_SITE) + site.USER_BASE = self.old_base + site.USER_SITE = self.old_site + + def test_test(self): + if sys.version < "2.6" or hasattr(sys, 'real_prefix'): + return + + dist = Distribution(dict( + name='foo', + packages=['name', 'name.space', 'name.space.tests'], + namespace_packages=['name'], + test_suite='name.space.tests.test_suite', + use_2to3=True, + )) + dist.script_name = 'setup.py' + cmd = test(dist) + cmd.user = 1 + cmd.ensure_finalized() + cmd.install_dir = site.USER_SITE + cmd.user = 1 + old_stdout = sys.stdout + sys.stdout = StringIO() + try: + try: # try/except/finally doesn't work in Python 2.4, so we need nested try-statements. + cmd.run() + except SystemExit: # The test runner calls sys.exit, stop that making an error. + pass + finally: + sys.stdout = old_stdout +
\ No newline at end of file |
