aboutsummaryrefslogtreecommitdiffstats
path: root/setuptools
diff options
context:
space:
mode:
authorJason R. Coombs <jaraco@jaraco.com>2013-06-18 08:44:39 -0500
committerJason R. Coombs <jaraco@jaraco.com>2013-06-18 08:44:39 -0500
commitfb8c7cf0abc9ce58b8a6f0621c0a9909fb9b8eff (patch)
tree95cae06260f49e011fc045000fc1531dbc0e0cf5 /setuptools
parent32ba6930fa97bbeac9392cac3ed49aac87fd1018 (diff)
parentdb678072da41b75408680dab3e23c1b76573bf1d (diff)
downloadexternal_python_setuptools-fb8c7cf0abc9ce58b8a6f0621c0a9909fb9b8eff.tar.gz
external_python_setuptools-fb8c7cf0abc9ce58b8a6f0621c0a9909fb9b8eff.tar.bz2
external_python_setuptools-fb8c7cf0abc9ce58b8a6f0621c0a9909fb9b8eff.zip
Merge with upstream
--HG-- branch : distribute
Diffstat (limited to 'setuptools')
-rwxr-xr-xsetuptools/archive_util.py29
-rw-r--r--setuptools/cli-32.exebin0 -> 69632 bytes
-rw-r--r--setuptools/cli-64.exebin0 -> 75264 bytes
-rw-r--r--setuptools/cli.exebin7168 -> 69632 bytes
-rw-r--r--setuptools/command/__init__.py1
-rw-r--r--setuptools/command/bdist_egg.py8
-rw-r--r--setuptools/command/build_py.py30
-rwxr-xr-xsetuptools/command/develop.py36
-rwxr-xr-xsetuptools/command/easy_install.py105
-rwxr-xr-xsetuptools/command/egg_info.py21
-rwxr-xr-xsetuptools/command/install_egg_info.py2
-rwxr-xr-xsetuptools/command/install_scripts.py5
-rwxr-xr-xsetuptools/command/sdist.py76
-rw-r--r--setuptools/command/test.py22
-rwxr-xr-xsetuptools/command/upload.py2
-rw-r--r--setuptools/dist.py35
-rw-r--r--setuptools/extension.py56
-rw-r--r--setuptools/gui-32.exebin0 -> 65536 bytes
-rw-r--r--setuptools/gui-64.exebin0 -> 75264 bytes
-rw-r--r--setuptools/gui.exebin7168 -> 65536 bytes
-rwxr-xr-xsetuptools/package_index.py27
-rwxr-xr-xsetuptools/sandbox.py20
-rw-r--r--setuptools/script template (dev).py6
-rw-r--r--setuptools/script template.py4
-rw-r--r--setuptools/tests/__init__.py163
-rw-r--r--setuptools/tests/py26compat.py14
-rw-r--r--setuptools/tests/server.py56
-rw-r--r--setuptools/tests/test_bdist_egg.py69
-rw-r--r--setuptools/tests/test_develop.py62
-rw-r--r--setuptools/tests/test_dist_info.py76
-rw-r--r--setuptools/tests/test_easy_install.py263
-rw-r--r--setuptools/tests/test_markerlib.py64
-rw-r--r--setuptools/tests/test_packageindex.py60
-rw-r--r--setuptools/tests/test_resources.py83
-rw-r--r--setuptools/tests/test_sdist.py170
-rw-r--r--setuptools/tests/test_test.py124
36 files changed, 1401 insertions, 288 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/cli-32.exe b/setuptools/cli-32.exe
new file mode 100644
index 00000000..9b7717b7
--- /dev/null
+++ b/setuptools/cli-32.exe
Binary files differ
diff --git a/setuptools/cli-64.exe b/setuptools/cli-64.exe
new file mode 100644
index 00000000..265585af
--- /dev/null
+++ b/setuptools/cli-64.exe
Binary files differ
diff --git a/setuptools/cli.exe b/setuptools/cli.exe
index 8906ff77..9b7717b7 100644
--- a/setuptools/cli.exe
+++ b/setuptools/cli.exe
Binary files differ
diff --git a/setuptools/command/__init__.py b/setuptools/command/__init__.py
index 152406b3..b063fa19 100644
--- a/setuptools/command/__init__.py
+++ b/setuptools/command/__init__.py
@@ -14,7 +14,6 @@ if sys.version>='2.5':
from distutils.command.bdist import bdist
-
if 'egg' not in bdist.format_commands:
bdist.format_command['egg'] = ('bdist_egg', "Python .egg file")
bdist.format_commands.append('egg')
diff --git a/setuptools/command/bdist_egg.py b/setuptools/command/bdist_egg.py
index 007f3ba9..875971f0 100644
--- a/setuptools/command/bdist_egg.py
+++ b/setuptools/command/bdist_egg.py
@@ -426,8 +426,12 @@ def scan_module(egg_dir, base, name, stubs):
return True # Extension module
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()
+ if sys.version_info < (3, 3):
+ skip = 8 # skip magic & date
+ else:
+ skip = 12 # skip magic & date & file size
+ f = open(filename,'rb'); f.read(skip)
+ 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 a01e2843..8751acd4 100644
--- a/setuptools/command/build_py.py
+++ b/setuptools/command/build_py.py
@@ -28,13 +28,8 @@ try:
if not files:
return
log.info("Fixing "+" ".join(files))
- if not self.fixer_names:
- self.fixer_names = []
- for p in setuptools.lib2to3_fixer_packages:
- self.fixer_names.extend(get_fixers_from_package(p))
- if self.distribution.use_2to3_fixers is not None:
- for p in self.distribution.use_2to3_fixers:
- self.fixer_names.extend(get_fixers_from_package(p))
+ self.__build_fixer_names()
+ self.__exclude_fixers()
if doctests:
if setuptools.run_2to3_on_doctests:
r = DistutilsRefactoringTool(self.fixer_names)
@@ -42,6 +37,23 @@ try:
else:
_Mixin2to3.run_2to3(self, files)
+ def __build_fixer_names(self):
+ if self.fixer_names: return
+ self.fixer_names = []
+ for p in setuptools.lib2to3_fixer_packages:
+ self.fixer_names.extend(get_fixers_from_package(p))
+ if self.distribution.use_2to3_fixers is not None:
+ for p in self.distribution.use_2to3_fixers:
+ self.fixer_names.extend(get_fixers_from_package(p))
+
+ def __exclude_fixers(self):
+ excluded_fixers = getattr(self, 'exclude_fixers', [])
+ if self.distribution.use_2to3_exclude_fixers is not None:
+ excluded_fixers.extend(self.distribution.use_2to3_exclude_fixers)
+ for fixer_name in excluded_fixers:
+ if fixer_name in self.fixer_names:
+ self.fixer_names.remove(fixer_name)
+
except ImportError:
class Mixin2to3:
def run_2to3(self, files, doctests=True):
@@ -201,8 +213,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 b8a10346..75d7b24b 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
@@ -43,6 +52,10 @@ __all__ = [
import site
HAS_USER_SITE = not sys.version < "2.6" and site.ENABLE_USER_SITE
+import struct
+def is_64bit():
+ return struct.calcsize("P") == 8
+
def samefile(p1,p2):
if hasattr(os.path,'samefile') and (
os.path.exists(p1) and os.path.exists(p2)
@@ -730,22 +743,26 @@ Please make the appropriate changes for your system and try again.
spec = str(dist.as_requirement())
is_script = is_python_script(script_text, script_name)
- if is_script and dev_path:
- script_text = get_script_header(script_text) + (
- "# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r\n"
- "__requires__ = %(spec)r\n"
- "from pkg_resources import require; require(%(spec)r)\n"
- "del require\n"
- "__file__ = %(dev_path)r\n"
- "execfile(__file__)\n"
- ) % locals()
- elif is_script:
- script_text = get_script_header(script_text) + (
- "# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r\n"
- "__requires__ = %(spec)r\n"
- "import pkg_resources\n"
- "pkg_resources.run_script(%(spec)r, %(script_name)r)\n"
- ) % locals()
+ def get_template(filename):
+ """
+ There are a couple of template scripts in the package. This
+ function loads one of them and prepares it for use.
+
+ These templates use triple-quotes to escape variable
+ substitutions so the scripts get the 2to3 treatment when build
+ on Python 3. The templates cannot use triple-quotes naturally.
+ """
+ raw_bytes = resource_string('setuptools', template_name)
+ template_str = raw_bytes.decode('utf-8')
+ clean_template = template_str.replace('"""', '')
+ return clean_template
+
+ if is_script:
+ template_name = 'script template.py'
+ if dev_path:
+ template_name = template_name.replace('.py', ' (dev).py')
+ script_text = (get_script_header(script_text) +
+ get_template(template_name) % locals())
self.write_script(script_name, _to_ascii(script_text), 'b')
def write_script(self, script_name, contents, mode="t", blockers=()):
@@ -756,12 +773,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,0x1ED) # 0755
+ chmod(target, 0x1FF-mask) # 0777
@@ -1078,11 +1096,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 = []
@@ -1097,6 +1118,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
@@ -1431,7 +1476,19 @@ def extract_wininst_cfg(dist_filename):
f.seek(prepended-(12+cfglen))
cfg = ConfigParser.RawConfigParser({'version':'','target_version':''})
try:
- cfg.readfp(StringIO(f.read(cfglen).split(chr(0),1)[0]))
+ part = f.read(cfglen)
+ # part is in bytes, but we need to read up to the first null
+ # byte.
+ if sys.version_info >= (2,6):
+ null_byte = bytes([0])
+ else:
+ null_byte = chr(0)
+ config = part.split(null_byte, 1)[0]
+ # Now the config is in bytes, but on Python 3, it must be
+ # unicode for the RawConfigParser, so decode it. Is this the
+ # right encoding?
+ config = config.decode('ascii')
+ cfg.readfp(StringIO(config))
except ConfigParser.Error:
return None
if not cfg.has_section('metadata') or not cfg.has_section('Setup'):
@@ -1777,7 +1834,10 @@ def get_script_args(dist, executable=sys_executable, wininst=False):
ext, launcher = '-script.py', 'cli.exe'
old = ['.py','.pyc','.pyo']
new_header = re.sub('(?i)pythonw.exe','python.exe',header)
-
+ if is_64bit():
+ launcher = launcher.replace(".", "-64.")
+ else:
+ launcher = launcher.replace(".", "-32.")
if os.path.exists(new_header[2:-1]) or sys.platform!='win32':
hdr = new_header
else:
@@ -1827,6 +1887,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/egg_info.py b/setuptools/command/egg_info.py
index 9ccbe68f..124c410e 100755
--- a/setuptools/command/egg_info.py
+++ b/setuptools/command/egg_info.py
@@ -163,7 +163,12 @@ class egg_info(Command):
os.unlink(filename)
def tagged_version(self):
- return safe_version(self.distribution.get_version() + self.vtags)
+ version = self.distribution.get_version()
+ # egg_info may be called more than once for a distribution,
+ # in which case the version string already contains all tags.
+ if self.vtags and version.endswith(self.vtags):
+ return safe_version(version)
+ return safe_version(version + self.vtags)
def run(self):
self.mkpath(self.egg_info)
@@ -288,6 +293,19 @@ class FileList(FileList):
+def compose(path):
+ # Apple's HFS Plus returns decomposed UTF-8. Since just about
+ # everyone else chokes on it, we must make sure to return fully
+ # composed UTF-8 only.
+ if sys.getfilesystemencoding().lower() == 'utf-8':
+ from unicodedata import normalize
+ if sys.version_info >= (3,):
+ path = normalize('NFC', path)
+ else:
+ path = normalize('NFC', path.decode('utf-8')).encode('utf-8')
+ return path
+
+
class manifest_maker(sdist):
template = "MANIFEST.in"
@@ -312,6 +330,7 @@ class manifest_maker(sdist):
self.prune_file_list()
self.filelist.sort()
self.filelist.remove_duplicates()
+ self.filelist.files = [compose(path) for path in self.filelist.files]
self.write_manifest()
def write_manifest (self):
diff --git a/setuptools/command/install_egg_info.py b/setuptools/command/install_egg_info.py
index dd95552e..f44b34b5 100755
--- a/setuptools/command/install_egg_info.py
+++ b/setuptools/command/install_egg_info.py
@@ -89,6 +89,8 @@ class install_egg_info(Command):
if not self.dry_run:
f = open(filename,'wt')
for pkg in nsp:
+ # ensure pkg is not a unicode string under Python 2.7
+ pkg = str(pkg)
pth = tuple(pkg.split('.'))
trailer = '\n'
if '.' in pkg:
diff --git a/setuptools/command/install_scripts.py b/setuptools/command/install_scripts.py
index 251190ba..105dabca 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,0x1ED) # 0755
+ chmod(target, 0x1FF-mask) # 0777
diff --git a/setuptools/command/sdist.py b/setuptools/command/sdist.py
index 499a3fb9..56ef8a66 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 = [
("&lt;","<"), ("&gt;", ">"), ("&quot;", '"'), ("&apos;", "'"),
("&amp;", "&")
@@ -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):
@@ -186,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')
@@ -199,24 +219,33 @@ class sdist(_sdist):
build_scripts = self.get_finalized_command('build_scripts')
self.filelist.extend(build_scripts.get_source_files())
- def read_template(self):
+ def __read_template_hack(self):
+ # This grody hack closes the template file (MANIFEST.in) if an
+ # exception occurs during read_template.
+ # Doing so prevents an error when easy_install attempts to delete the
+ # file.
try:
_sdist.read_template(self)
except:
- # grody hack to close the template file (MANIFEST.in)
- # this prevents easy_install's attempt at deleting the file from
- # dying and thus masking the real error
sys.exc_info()[2].tb_next.tb_frame.f_locals['template'].close()
raise
+ # Beginning with Python 2.7.2, 3.1.4, and 3.2.1, this leaky file handle
+ # has been fixed, so only override the method if we're using an earlier
+ # Python.
+ if (
+ sys.version_info < (2,7,2)
+ or (3,0) <= sys.version_info < (3,1,4)
+ or (3,2) <= sys.version_info < (3,2,1)
+ ):
+ 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)
)
@@ -233,7 +262,34 @@ class sdist(_sdist):
self.get_finalized_command('egg_info').save_version_info(dest)
+ def _manifest_is_not_generated(self):
+ # check for special comment used in 2.7.1 and higher
+ if not os.path.isfile(self.manifest):
+ return False
+ fp = open(self.manifest, 'rbU')
+ try:
+ first_line = fp.readline()
+ finally:
+ fp.close()
+ return first_line != '# file GENERATED by distutils, do NOT edit\n'.encode()
+
+ def read_manifest(self):
+ """Read the manifest file (named by 'self.manifest') and use it to
+ fill in 'self.filelist', the list of files to include in the source
+ distribution.
+ """
+ log.info("reading manifest file '%s'", self.manifest)
+ manifest = open(self.manifest, 'rbU')
+ for line in manifest:
+ if sys.version_info >= (3,):
+ line = line.decode('UTF-8')
+ # ignore comments and blank lines
+ line = line.strip()
+ if line.startswith('#') or not line:
+ continue
+ self.filelist.append(line)
+ manifest.close()
diff --git a/setuptools/command/test.py b/setuptools/command/test.py
index b7aef969..a02ac142 100644
--- a/setuptools/command/test.py
+++ b/setuptools/command/test.py
@@ -2,6 +2,7 @@ from setuptools import Command
from distutils.errors import DistutilsOptionError
import sys
from pkg_resources import *
+from pkg_resources import _namespace_packages
from unittest import TestLoader, main
class ScanningLoader(TestLoader):
@@ -81,7 +82,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
@@ -139,11 +140,28 @@ class test(Command):
def run_tests(self):
import unittest
+
+ # Purge modules under test from sys.modules. The test loader will
+ # re-import them from the build location. Required when 2to3 is used
+ # with namespace packages.
+ if sys.version_info >= (3,) and getattr(self.distribution, 'use_2to3', False):
+ module = self.test_args[-1].split('.')[0]
+ if module in _namespace_packages:
+ del_modules = []
+ if module in sys.modules:
+ del_modules.append(module)
+ module += '.'
+ for name in sys.modules:
+ if name.startswith(module):
+ del_modules.append(name)
+ map(sys.modules.__delitem__, del_modules)
+
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 6b18d761..bf9c0668 100755
--- a/setuptools/command/upload.py
+++ b/setuptools/command/upload.py
@@ -91,7 +91,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/dist.py b/setuptools/dist.py
index ebe02065..d90acbec 100644
--- a/setuptools/dist.py
+++ b/setuptools/dist.py
@@ -267,6 +267,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 = []
@@ -290,7 +291,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
@@ -642,6 +643,38 @@ class Distribution(_Distribution):
name = name[:-6]
yield name
+
+ def handle_display_options(self, option_order):
+ """If there were any non-global "display-only" options
+ (--help-commands or the metadata display options) on the command
+ line, display the requested info and return true; else return
+ false.
+ """
+ import sys
+
+ if sys.version_info < (3,) or self.help_commands:
+ return _Distribution.handle_display_options(self, option_order)
+
+ # Stdout may be StringIO (e.g. in tests)
+ import io
+ if not isinstance(sys.stdout, io.TextIOWrapper):
+ return _Distribution.handle_display_options(self, option_order)
+
+ # Print metadata in UTF-8 no matter the platform
+ encoding = sys.stdout.encoding
+ errors = sys.stdout.errors
+ newline = sys.platform != 'win32' and '\n' or None
+ line_buffering = sys.stdout.line_buffering
+
+ sys.stdout = io.TextIOWrapper(
+ sys.stdout.detach(), 'utf-8', errors, newline, line_buffering)
+ try:
+ return _Distribution.handle_display_options(self, option_order)
+ finally:
+ sys.stdout = io.TextIOWrapper(
+ sys.stdout.detach(), encoding, errors, newline, line_buffering)
+
+
# Install it throughout the distutils
for module in distutils.dist, distutils.core, distutils.cmd:
module.Distribution = Distribution
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/gui-32.exe b/setuptools/gui-32.exe
new file mode 100644
index 00000000..3f64af7d
--- /dev/null
+++ b/setuptools/gui-32.exe
Binary files differ
diff --git a/setuptools/gui-64.exe b/setuptools/gui-64.exe
new file mode 100644
index 00000000..3ab4378e
--- /dev/null
+++ b/setuptools/gui-64.exe
Binary files differ
diff --git a/setuptools/gui.exe b/setuptools/gui.exe
index 474838d5..3f64af7d 100644
--- a/setuptools/gui.exe
+++ b/setuptools/gui.exe
Binary files differ
diff --git a/setuptools/package_index.py b/setuptools/package_index.py
index 589dade6..2cab63c1 100755
--- a/setuptools/package_index.py
+++ b/setuptools/package_index.py
@@ -1,5 +1,6 @@
"""PyPI and direct package downloading"""
import sys, os.path, re, shutil, random, socket
+import base64
from pkg_resources import *
from distutils import log
from distutils.errors import DistutilsError
@@ -201,7 +202,7 @@ class PackageIndex(Environment):
return
self.info("Reading %s", url)
- f = self.open_url(url, "Download error: %s -- Some packages may not be found!")
+ f = self.open_url(url, "Download error on %s: %%s -- Some packages may not be found!" % url)
if f is None: return
self.fetched_urls[url] = self.fetched_urls[f.url] = True
@@ -764,19 +765,41 @@ def socket_timeout(timeout=15):
return _socket_timeout
return _socket_timeout
+def _encode_auth(auth):
+ """
+ A function compatible with Python 2.3-3.3 that will encode
+ auth from a URL suitable for an HTTP header.
+ >>> _encode_auth('username%3Apassword')
+ u'dXNlcm5hbWU6cGFzc3dvcmQ='
+ """
+ auth_s = unquote(auth)
+ # convert to bytes
+ auth_bytes = auth_s.encode()
+ # use the legacy interface for Python 2.3 support
+ encoded_bytes = base64.encodestring(auth_bytes)
+ # convert back to a string
+ encoded = encoded_bytes.decode()
+ # strip the trailing carriage return
+ return encoded.rstrip()
def open_with_auth(url):
"""Open a urllib2 request, handling HTTP authentication"""
scheme, netloc, path, params, query, frag = urlparse(url)
+ # Double scheme does not raise on Mac OS X as revealed by a
+ # failing test. We would expect "nonnumeric port". Refs #20.
+ if sys.platform == 'darwin':
+ if netloc.endswith(':'):
+ raise httplib.InvalidURL("nonnumeric port: ''")
+
if scheme in ('http', 'https'):
auth, host = splituser(netloc)
else:
auth = None
if auth:
- auth = "Basic " + unquote(auth).encode('base64').strip()
+ auth = "Basic " + _encode_auth(auth)
new_url = urlunparse((scheme,host,path,params,query,frag))
request = urllib2.Request(new_url)
request.add_header("Authorization", auth)
diff --git a/setuptools/sandbox.py b/setuptools/sandbox.py
index 41f1119b..c49d1cfe 100755
--- a/setuptools/sandbox.py
+++ b/setuptools/sandbox.py
@@ -42,8 +42,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
@@ -163,12 +169,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"""
diff --git a/setuptools/script template (dev).py b/setuptools/script template (dev).py
new file mode 100644
index 00000000..6dd9dd45
--- /dev/null
+++ b/setuptools/script template (dev).py
@@ -0,0 +1,6 @@
+# EASY-INSTALL-DEV-SCRIPT: %(spec)r,%(script_name)r
+__requires__ = """%(spec)r"""
+from pkg_resources import require; require("""%(spec)r""")
+del require
+__file__ = """%(dev_path)r"""
+execfile(__file__)
diff --git a/setuptools/script template.py b/setuptools/script template.py
new file mode 100644
index 00000000..8dd5d510
--- /dev/null
+++ b/setuptools/script template.py
@@ -0,0 +1,4 @@
+# EASY-INSTALL-SCRIPT: %(spec)r,%(script_name)r
+__requires__ = """%(spec)r"""
+import pkg_resources
+pkg_resources.run_script("""%(spec)r""", """%(script_name)r""")
diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py
index 669bb826..298141a7 100644
--- a/setuptools/tests/__init__.py
+++ b/setuptools/tests/__init__.py
@@ -1,17 +1,20 @@
"""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 distutils.version import LooseVersion
from setuptools.compat import func_code
-from setuptools.depends import *
-from distutils.version import StrictVersion, LooseVersion
-from distutils.util import convert_path
-import sys, os.path
+
+import setuptools.dist
+import setuptools.depends as dep
+from setuptools import Feature
+from setuptools.depends import Require
def additional_tests():
import doctest, unittest
@@ -36,55 +39,60 @@ def makeSetup(**args):
try:
return setuptools.setup(**args)
finally:
- distutils.core_setup_stop_after = None
-
-
+ 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
fc = func_code(f1)
# unrecognized name
- self.assertEqual(extract_constant(fc,'q', -1), None)
+ self.assertEqual(dep.extract_constant(fc,'q', -1), None)
# constant assigned
- self.assertEqual(extract_constant(fc,'x', -1), "test")
+ self.assertEqual(dep.extract_constant(fc,'x', -1), "test")
# expression assigned
- self.assertEqual(extract_constant(fc,'y', -1), -1)
+ self.assertEqual(dep.extract_constant(fc,'y', -1), -1)
# recognized name, not assigned
- self.assertEqual(extract_constant(fc,'z', -1), None)
-
+ self.assertEqual(dep.extract_constant(fc,'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')
@@ -96,21 +104,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)
@@ -120,11 +128,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'])
@@ -137,10 +145,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')
@@ -159,12 +165,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])
@@ -191,20 +191,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,
@@ -234,20 +231,7 @@ class DistroTests(TestCase):
)
-
-
-
-
-
-
-
-
-
-
-
-
-
-class FeatureTests(TestCase):
+class FeatureTests(unittest.TestCase):
def setUp(self):
self.req = Require('Distutils','1.0.3','distutils')
@@ -271,12 +255,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
@@ -290,33 +274,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])
@@ -329,11 +313,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'])
@@ -365,8 +349,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 c70fab7b..c7343340 100644
--- a/setuptools/tests/server.py
+++ b/setuptools/tests/server.py
@@ -1,7 +1,9 @@
"""Basic http server for tests to simulate PyPI or custom indexes
"""
import sys
-from threading import Thread
+import time
+import threading
+import BaseHTTPServer
from setuptools.compat import (urllib2, URLError, HTTPServer,
SimpleHTTPRequestHandler)
@@ -16,32 +18,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 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 752a70e9..ecd2212d 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..623ccc47
--- /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 ast
+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('ast' not in globals(),
+ "ast is used to test conditional dependencies (Python >= 2.6)")
+ 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 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
diff --git a/setuptools/tests/test_markerlib.py b/setuptools/tests/test_markerlib.py
new file mode 100644
index 00000000..7ff2f584
--- /dev/null
+++ b/setuptools/tests/test_markerlib.py
@@ -0,0 +1,64 @@
+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.6?)")
+ 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)
+
diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py
index cabbb48c..d9e50224 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -1,26 +1,27 @@
"""Package Index Tests
"""
-# More would be better!
import sys
-import os, shutil, tempfile, unittest
+import unittest
import pkg_resources
from setuptools.compat import urllib2, httplib, HTTPError
+import distutils.errors
import setuptools.package_index
from setuptools.tests.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 = sys.exc_info()[1]
- self.assert_(url in str(v))
+ self.assertTrue(url in str(v))
else:
- self.assert_(isinstance(v, HTTPError))
+ self.assertTrue(isinstance(v, HTTPError))
+ def test_bad_url_typo(self):
# issue 16
# easy_install inquant.contentmirror.plone breaks because of a typo
# in its home URL
@@ -33,9 +34,14 @@ class TestPackageIndex(unittest.TestCase):
v = index.open_url(url)
except Exception:
v = sys.exc_info()[1]
- self.assert_(url in str(v))
+ self.assertTrue(url in str(v))
else:
- self.assert_(isinstance(v, HTTPError))
+ self.assertTrue(isinstance(v, HTTPError))
+
+ def test_bad_url_bad_status_line(self):
+ index = setuptools.package_index.PackageIndex(
+ hosts=('www.example.com',)
+ )
def _urlopen(*args):
raise httplib.BadStatusLine('line')
@@ -48,20 +54,35 @@ class TestPackageIndex(unittest.TestCase):
v = index.open_url(url)
except Exception:
v = sys.exc_info()[1]
- 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 = sys.exc_info()[1]
- self.assert_('nonnumeric port' in str(v))
-
+ except distutils.errors.DistutilsError:
+ error = sys.exc_info()[1]
+ 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:
@@ -71,13 +92,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):
"""
@@ -94,6 +114,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()
@@ -106,11 +130,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(
@@ -121,5 +145,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 57536221..4b3d50a8 100644
--- a/setuptools/tests/test_resources.py
+++ b/setuptools/tests/test_resources.py
@@ -9,6 +9,16 @@ try: frozenset
except NameError:
from sets import ImmutableSet as frozenset
+def safe_repr(obj, short=False):
+ """ copied from Python2.7"""
+ try:
+ result = repr(obj)
+ except Exception:
+ result = object.__repr__(obj)
+ if not short or len(result) < _MAX_LENGTH:
+ return result
+ return result[:_MAX_LENGTH] + ' [truncated]...'
+
class Metadata(EmptyProvider):
"""Mock object to return metadata as if from an on-disk distribution"""
@@ -36,7 +46,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'])
@@ -219,7 +229,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]"
@@ -319,20 +329,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):
@@ -354,14 +364,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.
@@ -468,27 +478,29 @@ class ParseTests(TestCase):
p1, p2 = parse_version(s1),parse_version(s2)
self.assertEqual(p1,p2, (s1,s2,p1,p2))
- c('1.2-rc1', '1.2rc1')
c('0.4', '0.4.0')
c('0.4.0.0', '0.4.0')
c('0.4.0-0', '0.4-0')
c('0pl1', '0.0pl1')
c('0pre1', '0.0c1')
c('0.0.0preview1', '0c1')
- c('0.0c1', '0-rc1')
+ c('0.0c1', '0rc1')
c('1.2a1', '1.2.a.1'); c('1.2...a', '1.2a')
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')
c('2a1','2b0')
+ c('2b1','2c0')
c('2a1','2.1')
c('2.3a1', '2.3')
c('2.1-1', '2.1-2')
c('2.1-1', '2.1.1')
+ c('2.1', '2.1.1-1')
c('2.1', '2.1pl4')
c('2.1a0-20040501', '2.1')
c('1.1', '02.1')
@@ -499,8 +511,20 @@ class ParseTests(TestCase):
c('0.4', '4.0')
c('0.0.4', '0.4.0')
c('0pl1', '0.4pl1')
- c('2.1.0-rc1','2.1.0')
c('2.1dev','2.1a0')
+ c('2.1.0rc1','2.1.0')
+ c('2.1.0','2.1.0-rc0')
+ c('2.1.0','2.1.0-a')
+ c('2.1.0','2.1.0-alpha')
+ c('2.1.0','2.1.0-foo')
+ c('1.0','1.0-1')
+ c('1.0-1','1.0.1')
+ c('1.0a','1.0b')
+ c('1.0dev','1.0rc1')
+ c('1.0pre','1.0')
+ c('1.0pre','1.0')
+ c('1.0a','1.0-a')
+ c('1.0rc1','1.0-rc1')
torture ="""
0.80.1-3 0.80.1-2 0.80.1-1 0.79.9999+0.80.0pre4-1
@@ -554,12 +578,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()
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
@@ -581,6 +605,13 @@ class NamespaceTests(TestCase):
pkg_resources._namespace_packages = self._ns_pkgs.copy()
sys.path = self._prev_sys_path[:]
+ def _assertIn(self, member, container):
+ """ assertIn and assertTrue does not exist in Python2.3"""
+ if member not in container:
+ standardMsg = '%s not found in %s' % (safe_repr(member),
+ safe_repr(container))
+ self.fail(self._formatMessage(msg, standardMsg))
+
def test_two_levels_deep(self):
"""
Test nested namespace packages
@@ -604,13 +635,13 @@ class NamespaceTests(TestCase):
pkg2_init.write(ns_str)
pkg2_init.close()
import pkg1
- self.assertTrue("pkg1" in pkg_resources._namespace_packages.keys())
+ self._assertIn("pkg1", pkg_resources._namespace_packages.keys())
try:
import pkg1.pkg2
except ImportError:
self.fail("Distribute tried to import the parent namespace package")
# check the _namespace_packages dict
- self.assertTrue("pkg1.pkg2" in pkg_resources._namespace_packages.keys())
+ self._assertIn("pkg1.pkg2", pkg_resources._namespace_packages.keys())
self.assertEqual(pkg_resources._namespace_packages["pkg1"], ["pkg1.pkg2"])
# check the __path__ attribute contains both paths
self.assertEqual(pkg1.pkg2.__path__, [
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
new file mode 100644
index 00000000..7e2f0a49
--- /dev/null
+++ b/setuptools/tests/test_sdist.py
@@ -0,0 +1,170 @@
+# -*- coding: utf-8 -*-
+"""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.assertTrue(os.path.join('sdist_test', 'a.txt') in manifest)
+ self.assertTrue(os.path.join('sdist_test', 'b.txt') in manifest)
+ self.assertTrue(os.path.join('sdist_test', 'c.rst') not in manifest)
+
+ def test_filelist_is_fully_composed(self):
+ # Test for #303. Requires HFS Plus to fail.
+
+ # Add file with non-ASCII filename
+ filename = os.path.join('sdist_test', 'smörbröd.py')
+ open(filename, 'w').close()
+
+ 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
+
+ self.assertTrue(filename in cmd.filelist.files)
+
+ def test_manifest_is_written_in_utf8(self):
+ # Test for #303.
+
+ # Add file with non-ASCII filename
+ filename = os.path.join('sdist_test', 'smörbröd.py')
+ open(filename, 'w').close()
+
+ 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 = open(os.path.join('sdist_test.egg-info', 'SOURCES.txt'), 'rbU')
+ contents = manifest.read()
+ manifest.close()
+ self.assertTrue(len(contents))
+
+ # This must not fail:
+ contents.decode('UTF-8')
+
+ def test_manifest_is_read_in_utf8(self):
+ # Test for #303.
+
+ # Add file with non-ASCII filename
+ filename = os.path.join('sdist_test', 'smörbröd.py')
+ open(filename, 'w').close()
+
+ 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
+
+ cmd.filelist.files = []
+ cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ cmd.read_manifest()
+
+ self.assertTrue(filename in cmd.filelist.files)
+
+
+def test_suite():
+ return unittest.defaultTestLoader.loadTestsFromName(__name__)
+
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