summaryrefslogtreecommitdiff
path: root/setuptools/tests
diff options
context:
space:
mode:
Diffstat (limited to 'setuptools/tests')
-rw-r--r--setuptools/tests/__init__.py179
-rw-r--r--setuptools/tests/doctest.py16
-rw-r--r--setuptools/tests/indexes/test_links_priority/external.html3
-rw-r--r--setuptools/tests/indexes/test_links_priority/simple/foobar/index.html4
-rw-r--r--setuptools/tests/py26compat.py14
-rw-r--r--setuptools/tests/server.py82
-rw-r--r--setuptools/tests/test_bdist_egg.py69
-rw-r--r--setuptools/tests/test_build_ext.py20
-rw-r--r--setuptools/tests/test_develop.py118
-rw-r--r--setuptools/tests/test_dist_info.py80
-rw-r--r--setuptools/tests/test_easy_install.py425
-rw-r--r--setuptools/tests/test_markerlib.py64
-rw-r--r--setuptools/tests/test_packageindex.py134
-rw-r--r--setuptools/tests/test_resources.py169
-rw-r--r--setuptools/tests/test_sandbox.py66
-rw-r--r--setuptools/tests/test_sdist.py383
-rw-r--r--setuptools/tests/test_test.py124
-rw-r--r--setuptools/tests/test_upload_docs.py72
-rw-r--r--setuptools/tests/win_script_wrapper.txt288
19 files changed, 2015 insertions, 295 deletions
diff --git a/setuptools/tests/__init__.py b/setuptools/tests/__init__.py
index 287bc240..b6988a08 100644
--- a/setuptools/tests/__init__.py
+++ b/setuptools/tests/__init__.py
@@ -1,22 +1,25 @@
"""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
suite = unittest.TestSuite((
doctest.DocFileSuite(
- 'api_tests.txt',
+ os.path.join('tests', 'api_tests.txt'),
optionflags=doctest.ELLIPSIS, package='pkg_resources',
),
))
@@ -35,80 +38,85 @@ 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
# 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
- from distutils import __version__
+ if not hasattr(dep, 'get_module_constant'):
+ # skip on non-bytecode platforms
+ return
+
+ from email import __version__
self.assertEqual(
- get_module_constant('distutils','__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('Distutils','1.0.3','distutils')
+ req = Require('Email','1.0.3','email')
- self.assertEqual(req.name, 'Distutils')
- self.assertEqual(req.module, 'distutils')
+ self.assertEqual(req.name, 'Email')
+ self.assertEqual(req.module, 'email')
self.assertEqual(req.requested_version, '1.0.3')
self.assertEqual(req.attribute, '__version__')
- self.assertEqual(req.full_name(), 'Distutils-1.0.3')
+ self.assertEqual(req.full_name(), 'Email-1.0.3')
- from distutils import __version__
+ from email import __version__
self.assertEqual(req.get_version(), __version__)
- self.failUnless(req.version_ok('1.0.9'))
- self.failIf(req.version_ok('0.9.1'))
- self.failIf(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.failUnless(req.is_present())
- self.failUnless(req.is_current())
+ self.assertTrue(req.is_present())
+ self.assertTrue(req.is_current())
- req = Require('Distutils 3000','03000','distutils',format=LooseVersion)
- self.failUnless(req.is_present())
- self.failIf(req.is_current())
- self.failIf(req.version_ok('unknown'))
+ req = Require('Email 3000','03000','email',format=LooseVersion)
+ 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.failIf(req.is_present())
- self.failIf(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.failUnless(req.is_present(paths))
- self.failUnless(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.failUnless(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.failUnless(self.dist.has_contents_for('a'))
+ self.assertTrue(self.dist.has_contents_for('a'))
self.dist.exclude_package('a')
- self.failIf(self.dist.has_contents_for('a'))
+ self.assertTrue(not self.dist.has_contents_for('a'))
- self.failUnless(self.dist.has_contents_for('b'))
+ self.assertTrue(self.dist.has_contents_for('b'))
self.dist.exclude_package('b')
- self.failIf(self.dist.has_contents_for('b'))
+ self.assertTrue(not self.dist.has_contents_for('b'))
- self.failUnless(self.dist.has_contents_for('c'))
+ self.assertTrue(self.dist.has_contents_for('c'))
self.dist.exclude_package('c')
- self.failIf(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.failIf(
+ self.assertTrue(not
Feature(
"test",standard=True,remove='x',available=False
).include_by_default()
)
- self.failUnless(
+ 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.failUnless(
+ self.assertTrue(
('with-dwim',None,'include DWIM') in dist.feature_options
)
- self.failUnless(
+ self.assertTrue(
('without-dwim',None,'exclude DWIM (default)') in dist.feature_options
)
- self.failUnless(
+ self.assertTrue(
('with-bar',None,'include bar (default)') in dist.feature_options
)
- self.failUnless(
+ 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.failIf('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.failIf('bar_et' in dist.py_modules)
- self.failIf('pkg.bar' in dist.packages)
- self.failUnless('pkg.baz' in dist.packages)
- self.failUnless('scripts/baz_it' in dist.scripts)
- self.failUnless(('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.failUnless(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/doctest.py b/setuptools/tests/doctest.py
index bffce58f..cc1e06c3 100644
--- a/setuptools/tests/doctest.py
+++ b/setuptools/tests/doctest.py
@@ -1968,7 +1968,9 @@ def testfile(filename, module_relative=True, name=None, package=None,
runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
# Read the file, convert it to a test, and run it.
- s = open(filename).read()
+ f = open(filename)
+ s = f.read()
+ f.close()
test = parser.get_doctest(s, globs, name, filename, 0)
runner.run(test)
@@ -2053,16 +2055,16 @@ class Tester:
return (f,t)
def rundict(self, d, name, module=None):
- import new
- m = new.module(name)
+ import types
+ m = types.ModuleType(name)
m.__dict__.update(d)
if module is None:
module = False
return self.rundoc(m, name, module)
def run__test__(self, d, name):
- import new
- m = new.module(name)
+ import types
+ m = types.ModuleType(name)
m.__test__ = d
return self.rundoc(m, name)
@@ -2353,7 +2355,9 @@ def DocFileTest(path, module_relative=True, package=None,
# Find the file and read it.
name = os.path.basename(path)
- doc = open(path).read()
+ f = open(path)
+ doc = f.read()
+ f.close()
# Convert it to a test, and wrap it in a DocFileCase.
test = parser.get_doctest(doc, globs, name, path, 0)
diff --git a/setuptools/tests/indexes/test_links_priority/external.html b/setuptools/tests/indexes/test_links_priority/external.html
new file mode 100644
index 00000000..92e4702f
--- /dev/null
+++ b/setuptools/tests/indexes/test_links_priority/external.html
@@ -0,0 +1,3 @@
+<html><body>
+<a href="/foobar-0.1.tar.gz#md5=1__bad_md5___">bad old link</a>
+</body></html>
diff --git a/setuptools/tests/indexes/test_links_priority/simple/foobar/index.html b/setuptools/tests/indexes/test_links_priority/simple/foobar/index.html
new file mode 100644
index 00000000..fefb028b
--- /dev/null
+++ b/setuptools/tests/indexes/test_links_priority/simple/foobar/index.html
@@ -0,0 +1,4 @@
+<html><body>
+<a href="/foobar-0.1.tar.gz#md5=0_correct_md5">foobar-0.1.tar.gz</a><br/>
+<a href="../../external.html" rel="homepage">external homepage</a><br/>
+</body></html>
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
new file mode 100644
index 00000000..b2ab7acc
--- /dev/null
+++ b/setuptools/tests/server.py
@@ -0,0 +1,82 @@
+"""Basic http server for tests to simulate PyPI or custom indexes
+"""
+import urllib2
+import sys
+import time
+import threading
+import BaseHTTPServer
+from BaseHTTPServer import HTTPServer
+from SimpleHTTPServer import SimpleHTTPRequestHandler
+
+class IndexServer(HTTPServer):
+ """Basic single-threaded http server simulating a package index
+
+ You can use this server in unittest like this::
+ s = IndexServer()
+ s.start()
+ index_url = s.base_url() + 'mytestindex'
+ # do some test requests to the index
+ # The index files should be located in setuptools/tests/indexes
+ s.stop()
+ """
+ def __init__(self, server_address=('', 0),
+ RequestHandlerClass=SimpleHTTPRequestHandler):
+ HTTPServer.__init__(self, server_address, RequestHandlerClass)
+ self._run = True
+
+ def serve(self):
+ while self._run:
+ self.handle_request()
+
+ def start(self):
+ self.thread = threading.Thread(target=self.serve)
+ self.thread.start()
+
+ def stop(self):
+ "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_info >= (2, 6):
+ urllib2.urlopen(url, timeout=5)
+ else:
+ 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_build_ext.py b/setuptools/tests/test_build_ext.py
new file mode 100644
index 00000000..a520ced9
--- /dev/null
+++ b/setuptools/tests/test_build_ext.py
@@ -0,0 +1,20 @@
+"""build_ext tests
+"""
+import os, shutil, tempfile, unittest
+from distutils.command.build_ext import build_ext as distutils_build_ext
+from setuptools.command.build_ext import build_ext
+from setuptools.dist import Distribution
+
+class TestBuildExtTest(unittest.TestCase):
+
+ def test_get_ext_filename(self):
+ # setuptools needs to give back the same
+ # result than distutils, even if the fullname
+ # is not in ext_map
+ dist = Distribution()
+ cmd = build_ext(dist)
+ cmd.ext_map['foo/bar'] = ''
+ res = cmd.get_ext_filename('foo')
+ wanted = distutils_build_ext.get_ext_filename(cmd, 'foo')
+ assert res == wanted
+
diff --git a/setuptools/tests/test_develop.py b/setuptools/tests/test_develop.py
new file mode 100644
index 00000000..315058c5
--- /dev/null
+++ b/setuptools/tests/test_develop.py
@@ -0,0 +1,118 @@
+"""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.develop import develop
+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=['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)
+ 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_develop(self):
+ if sys.version < "2.6" or hasattr(sys, 'real_prefix'):
+ return
+ dist = Distribution(
+ dict(name='foo',
+ packages=['foo'],
+ use_2to3=True,
+ version='0.0',
+ ))
+ dist.script_name = 'setup.py'
+ cmd = develop(dist)
+ cmd.user = 1
+ cmd.ensure_finalized()
+ cmd.install_dir = site.USER_SITE
+ cmd.user = 1
+ old_stdout = sys.stdout
+ #sys.stdout = StringIO()
+ try:
+ cmd.run()
+ finally:
+ sys.stdout = old_stdout
+
+ # let's see if we got our egg link at the right place
+ content = os.listdir(site.USER_SITE)
+ content.sort()
+ self.assertEqual(content, ['easy-install.pth', 'foo.egg-link'])
+
+ # Check that we are using the right code.
+ egg_link_file = open(os.path.join(site.USER_SITE, 'foo.egg-link'), 'rt')
+ path = egg_link_file.read().split()[0].strip()
+ egg_link_file.close()
+ init_file = open(os.path.join(path, 'foo', '__init__.py'), 'rt')
+ init = init_file.read().strip()
+ init_file.close()
+ if sys.version < "3":
+ self.assertEqual(init, 'print "foo"')
+ else:
+ self.assertEqual(init, 'print("foo")')
+
+ def notest_develop_with_setup_requires(self):
+
+ wanted = ("Could not find suitable distribution for "
+ "Requirement.parse('I-DONT-EXIST')")
+ old_dir = os.getcwd()
+ os.chdir(self.dir)
+ try:
+ try:
+ dist = Distribution({'setup_requires': ['I_DONT_EXIST']})
+ except DistutilsError, e:
+ error = str(e)
+ if error == wanted:
+ pass
+ finally:
+ os.chdir(old_dir)
+
diff --git a/setuptools/tests/test_dist_info.py b/setuptools/tests/test_dist_info.py
new file mode 100644
index 00000000..fcb78c36
--- /dev/null
+++ b/setuptools/tests/test_dist_info.py
@@ -0,0 +1,80 @@
+"""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)
+ metadata_file = open(os.path.join(versioned, 'METADATA'), 'w+')
+ metadata_file.write(DALS(
+ """
+ Metadata-Version: 1.2
+ Name: VersionedDistribution
+ Requires-Dist: splort (4)
+ Provides-Extra: baz
+ Requires-Dist: quux (>=1.1); extra == 'baz'
+ """))
+ metadata_file.close()
+
+ unversioned = os.path.join(self.tmpdir,
+ 'UnversionedDistribution.dist-info')
+ os.mkdir(unversioned)
+ metadata_file = open(os.path.join(unversioned, 'METADATA'), 'w+')
+ metadata_file.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'
+ """))
+ metadata_file.close()
+
+ def tearDown(self):
+ shutil.rmtree(self.tmpdir)
diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py
new file mode 100644
index 00000000..395056e7
--- /dev/null
+++ b/setuptools/tests/test_easy_install.py
@@ -0,0 +1,425 @@
+"""Easy install Tests
+"""
+import sys
+import os
+import shutil
+import tempfile
+import unittest
+import site
+import textwrap
+import tarfile
+import urlparse
+import StringIO
+import distutils.core
+
+from setuptools.sandbox import run_setup, SandboxViolation
+from setuptools.command.easy_install import easy_install, fix_jython_executable, get_script_args
+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 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)
+ _MULTIPROC = True
+except ImportError:
+ _MULTIPROC = False
+ _LOG = None
+
+class FakeDist(object):
+ def get_entry_map(self, group):
+ if group != 'console_scripts':
+ return {}
+ return {'name': 'ep'}
+
+ def as_requirement(self):
+ return 'spec'
+
+WANTED = """\
+#!%s
+# EASY-INSTALL-ENTRY-SCRIPT: 'spec','console_scripts','name'
+__requires__ = 'spec'
+import sys
+from pkg_resources import load_entry_point
+
+if __name__ == '__main__':
+ sys.exit(
+ load_entry_point('spec', 'console_scripts', 'name')()
+ )
+""" % fix_jython_executable(sys.executable, "")
+
+SETUP_PY = """\
+from setuptools import setup
+
+setup(name='foo')
+"""
+
+class TestEasyInstallTest(unittest.TestCase):
+
+ def test_install_site_py(self):
+ dist = Distribution()
+ cmd = easy_install(dist)
+ cmd.sitepy_installed = False
+ cmd.install_dir = tempfile.mkdtemp()
+ try:
+ cmd.install_site_py()
+ sitepy = os.path.join(cmd.install_dir, 'site.py')
+ self.assertTrue(os.path.exists(sitepy))
+ finally:
+ shutil.rmtree(cmd.install_dir)
+
+ def test_get_script_args(self):
+ dist = FakeDist()
+
+ old_platform = sys.platform
+ try:
+ name, script = [i for i in get_script_args(dist).next()][0:2]
+ finally:
+ sys.platform = old_platform
+
+ self.assertEqual(script, WANTED)
+
+ 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.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.assertEqual(cmd.package_index.scanned_urls, {})
+
+ # let's try without it (default behavior)
+ cmd = easy_install(dist)
+ 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.assertEqual(keys, ['link1', 'link2'])
+
+
+class TestPTHFileWriter(unittest.TestCase):
+ def test_add_from_cwd_site_sets_dirty(self):
+ '''a pth file manager should set dirty
+ if a distribution is in site but also the cwd
+ '''
+ pth = PthDistributions('does-not_exist', [os.getcwd()])
+ self.assertTrue(not pth.dirty)
+ pth.add(PRDistribution(os.getcwd()))
+ self.assertTrue(pth.dirty)
+
+ def test_add_from_site_is_ignored(self):
+ 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):
+
+ def setUp(self):
+ self.dir = tempfile.mkdtemp()
+ setup = os.path.join(self.dir, 'setup.py')
+ f = open(setup, 'w')
+ f.write(SETUP_PY)
+ f.close()
+ self.old_cwd = os.getcwd()
+ os.chdir(self.dir)
+ if sys.version >= "2.6":
+ self.old_has_site = easy_install_pkg.HAS_USER_SITE
+ self.old_file = easy_install_pkg.__file__
+ self.old_base = site.USER_BASE
+ site.USER_BASE = tempfile.mkdtemp()
+ self.old_site = site.USER_SITE
+ site.USER_SITE = tempfile.mkdtemp()
+ easy_install_pkg.__file__ = site.USER_SITE
+
+ 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
+ easy_install_pkg.HAS_USER_SITE = self.old_has_site
+ easy_install_pkg.__file__ = self.old_file
+
+ def test_user_install_implied(self):
+ easy_install_pkg.HAS_USER_SITE = True # disabled sometimes
+ #XXX: replace with something meaningfull
+ if sys.version < "2.6":
+ return #SKIP
+ dist = Distribution()
+ dist.script_name = 'setup.py'
+ cmd = easy_install(dist)
+ cmd.args = ['py']
+ cmd.ensure_finalized()
+ self.assertTrue(cmd.user, 'user should be implied')
+
+ def test_multiproc_atexit(self):
+ if not _MULTIPROC:
+ return
+ _LOG.info('this should not break')
+
+ def test_user_install_not_implied_without_usersite_enabled(self):
+ easy_install_pkg.HAS_USER_SITE = False # usually enabled
+ #XXX: replace with something meaningfull
+ if sys.version < "2.6":
+ return #SKIP
+ dist = Distribution()
+ dist.script_name = 'setup.py'
+ cmd = easy_install(dist)
+ cmd.args = ['py']
+ cmd.initialize_options()
+ self.assertFalse(cmd.user, 'NOT user should be implied')
+
+ def test_local_index(self):
+ # make sure the local index is used
+ # when easy_install looks for installed
+ # packages
+ new_location = tempfile.mkdtemp()
+ target = tempfile.mkdtemp()
+ egg_file = os.path.join(new_location, 'foo-1.0.egg-info')
+ f = open(egg_file, 'w')
+ try:
+ f.write('Name: foo\n')
+ finally:
+ f.close()
+
+ sys.path.append(target)
+ old_ppath = os.environ.get('PYTHONPATH')
+ os.environ['PYTHONPATH'] = os.path.pathsep.join(sys.path)
+ try:
+ dist = Distribution()
+ dist.script_name = 'setup.py'
+ cmd = easy_install(dist)
+ cmd.install_dir = target
+ cmd.args = ['foo']
+ cmd.ensure_finalized()
+ cmd.local_index.scan([new_location])
+ res = cmd.easy_install('foo')
+ self.assertEqual(os.path.realpath(res.location),
+ os.path.realpath(new_location))
+ finally:
+ sys.path.remove(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 Distribute issue #318
+
+ Ensure that a package with setup_requires can be installed when
+ setuptools is installed in the user site-packages without causing a
+ SandboxViolation.
+ """
+
+ test_setup_attrs = {
+ 'name': 'test_pkg', 'version': '0.0',
+ 'setup_requires': ['foobar'],
+ 'dependency_links': [os.path.abspath(self.dir)]
+ }
+
+ test_pkg = os.path.join(self.dir, 'test_pkg')
+ test_setup_py = os.path.join(test_pkg, 'setup.py')
+ test_setup_cfg = os.path.join(test_pkg, 'setup.cfg')
+ os.mkdir(test_pkg)
+
+ f = open(test_setup_py, 'w')
+ f.write(textwrap.dedent("""\
+ import setuptools
+ setuptools.setup(**%r)
+ """ % test_setup_attrs))
+ f.close()
+
+ foobar_path = os.path.join(self.dir, 'foobar-0.1.tar.gz')
+ make_trivial_sdist(
+ foobar_path,
+ textwrap.dedent("""\
+ import setuptools
+ setuptools.setup(
+ name='foobar',
+ version='0.1'
+ )
+ """))
+
+ old_stdout = sys.stdout
+ old_stderr = sys.stderr
+ sys.stdout = StringIO.StringIO()
+ sys.stderr = StringIO.StringIO()
+ try:
+ reset_setup_stop_context(
+ lambda: run_setup(test_setup_py, ['install'])
+ )
+ except SandboxViolation:
+ self.fail('Installation caused SandboxViolation')
+ finally:
+ sys.stdout = old_stdout
+ sys.stderr = old_stderr
+
+
+class TestSetupRequires(unittest.TestCase):
+
+ 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):
+ dist_path = os.path.join(dir, 'setuptools-test-fetcher-1.0.tar.gz')
+ make_trivial_sdist(
+ dist_path,
+ textwrap.dedent("""
+ import setuptools
+ setuptools.setup(
+ name="setuptools-test-fetcher",
+ version="1.0",
+ setup_requires = ['does-not-exist'],
+ )
+ """).lstrip())
+ installer(dist_path)
+ tempdir_context(build_sdist)
+
+
+def make_trivial_sdist(dist_path, setup_py):
+ """Create a simple sdist tarball at dist_path, containing just a
+ setup.py, the contents of which are provided by the setup_py string.
+ """
+
+ setup_py_file = tarfile.TarInfo(name='setup.py')
+ try:
+ # Python 3 (StringIO gets converted to io module)
+ MemFile = StringIO.BytesIO
+ except AttributeError:
+ MemFile = StringIO.StringIO
+ setup_py_bytes = MemFile(setup_py.encode('utf-8'))
+ setup_py_file.size = len(setup_py_bytes.getvalue())
+ dist = tarfile.open(dist_path, 'w:gz')
+ try:
+ dist.addfile(setup_py_file, fileobj=setup_py_bytes)
+ finally:
+ dist.close()
+
+
+def tempdir_context(f, cd=lambda dir:None):
+ """
+ Invoke f in the context
+ """
+ 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 setuptools 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..aa461846
--- /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.assertTrue(interpret(""))
+
+ self.assertTrue(interpret("os.name != 'buuuu'"))
+ self.assertTrue(interpret("python_version > '1.0'"))
+ self.assertTrue(interpret("python_version < '5.0'"))
+ self.assertTrue(interpret("python_version <= '5.0'"))
+ self.assertTrue(interpret("python_version >= '1.0'"))
+ self.assertTrue(interpret("'%s' in os.name" % os_name))
+ self.assertTrue(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.assertTrue(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 0231eda8..9c4bfadb 100644
--- a/setuptools/tests/test_packageindex.py
+++ b/setuptools/tests/test_packageindex.py
@@ -1,27 +1,145 @@
"""Package Index Tests
"""
-# More would be better!
-
-import os, shutil, tempfile, unittest, urllib2
+import sys
+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/nonesuch/test_package_index'
+ 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
+ index = setuptools.package_index.PackageIndex(
+ hosts=('www.example.com',)
+ )
+
+ url = 'url:%20https://svn.plone.org/svn/collective/inquant.contentmirror.plone/trunk'
+ try:
+ v = index.open_url(url)
+ except Exception, v:
+ self.assertTrue(url in str(v))
+ else:
+ 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
+ raise httplib.BadStatusLine('line')
+
+ old_urlopen = urllib2.urlopen
+ urllib2.urlopen = _urlopen
+ url = 'http://example.com'
+ try:
+ try:
+ v = index.open_url(url)
+ except Exception, 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 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:
+ # this should not fail
+ url = 'http://example.com'
+ page = ('<a href="http://www.famfamfam.com]('
+ '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):
+ """
+ Download links from the pypi simple index should be used before
+ external download links.
+ http://bitbucket.org/tarek/distribute/issue/163/md5-validation-error
+
+ Usecase :
+ - someone uploads a package on pypi, a md5 is generated
+ - someone manually copies this link (with the md5 in the url) onto an
+ external page accessible from the package page.
+ - someone reuploads the package (with a different md5)
+ - while easy_installing, an MD5 error occurs because the external link
+ is used
+ -> Setuptools 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()
+ index_url = server.base_url() + 'test_links_priority/simple/'
+
+ # scan a test index
+ pi = setuptools.package_index.PackageIndex(index_url)
+ requirement = pkg_resources.Requirement.parse('foobar')
+ pi.find_packages(requirement)
+ server.stop()
+
+ # the distribution has been found
+ self.assertTrue('foobar' in pi)
+ # we have only one link, because links are compared without md5
+ self.assertTrue(len(pi['foobar'])==1)
+ # the link should be from the index
+ self.assertTrue('correct_md5' in pi['foobar'][0].location)
+ def test_parse_bdist_wininst(self):
+ self.assertEqual(setuptools.package_index.parse_bdist_wininst(
+ 'reportlab-2.5.win32-py2.4.exe'), ('reportlab-2.5', '2.4', 'win32'))
+ self.assertEqual(setuptools.package_index.parse_bdist_wininst(
+ 'reportlab-2.5.win32.exe'), ('reportlab-2.5', None, 'win32'))
+ self.assertEqual(setuptools.package_index.parse_bdist_wininst(
+ '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 03e5d0f8..9c2ed9c9 100644
--- a/setuptools/tests/test_resources.py
+++ b/setuptools/tests/test_resources.py
@@ -3,11 +3,21 @@
# NOTE: the shebang and encoding lines are for ScriptHeaderTests; do not remove
from unittest import TestCase, makeSuite; from pkg_resources import *
from setuptools.command.easy_install import get_script_header, is_sh
-import os, pkg_resources, sys, StringIO
+import os, pkg_resources, sys, StringIO, tempfile, shutil
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"""
@@ -35,7 +45,7 @@ class DistroTests(TestCase):
ad.add(Distribution.from_filename("FooPkg-1.2-py2.4.egg"))
# Name is in there now
- self.failUnless(ad['FooPkg'])
+ self.assertTrue(ad['FooPkg'])
# But only 1 package
self.assertEqual(list(ad), ['foopkg'])
@@ -143,7 +153,7 @@ class DistroTests(TestCase):
self.assertRaises(VersionConflict, ws.resolve,
parse_requirements("Foo==0.9"), ad)
ws = WorkingSet([]) # reset
-
+
# Request an extra that causes an unresolved dependency for "Baz"
self.assertRaises(
DistributionNotFound, ws.resolve,parse_requirements("Foo[bar]"), ad
@@ -161,7 +171,7 @@ class DistroTests(TestCase):
self.assertRaises( VersionConflict,
ws.resolve, parse_requirements("Foo==1.2\nFoo!=1.2"), ad
)
-
+
def testDistroDependsOptions(self):
d = self.distRequires("""
Twisted>=1.5
@@ -188,21 +198,6 @@ class DistroTests(TestCase):
self.assertRaises(UnknownExtra, d.requires, ["foo"])
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
class EntryPointTests(TestCase):
def assertfields(self, ep):
@@ -210,7 +205,7 @@ class EntryPointTests(TestCase):
self.assertEqual(ep.module_name,"setuptools.tests.test_resources")
self.assertEqual(ep.attrs, ("EntryPointTests",))
self.assertEqual(ep.extras, ("x",))
- self.failUnless(ep.load() is EntryPointTests)
+ self.assertTrue(ep.load() is EntryPointTests)
self.assertEqual(
str(ep),
"foo = setuptools.tests.test_resources:EntryPointTests [x]"
@@ -310,20 +305,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.failUnless(parse_version('1.2') in r)
- self.failUnless(parse_version('1.1') not in r)
- self.failUnless('1.2' in r)
- self.failUnless('1.1' not in r)
- self.failUnless(foo_dist not in r)
- self.failUnless(twist11 not in r)
- self.failUnless(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.failUnless(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.failUnless(v not in r, (v,r))
+ self.assertTrue(v not in r, (v,r))
def testOptionsAndHashing(self):
@@ -341,21 +336,33 @@ class RequirementsTests(TestCase):
)
def testVersionEquality(self):
- r1 = Requirement.parse("setuptools==0.3a2")
- r2 = Requirement.parse("setuptools!=0.3a4")
+ r1 = Requirement.parse("foo==0.3a2")
+ r2 = Requirement.parse("foo!=0.3a4")
d = Distribution.from_filename
- self.failIf(d("setuptools-0.3a4.egg") in r1)
- self.failIf(d("setuptools-0.3a1.egg") in r1)
- self.failIf(d("setuptools-0.3a4.egg") in r2)
-
- self.failUnless(d("setuptools-0.3a2.egg") in r1)
- self.failUnless(d("setuptools-0.3a2.egg") in r2)
- self.failUnless(d("setuptools-0.3a3.egg") in r2)
- self.failUnless(d("setuptools-0.3a5.egg") 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.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 testSetuptoolsProjectName(self):
+ """
+ The setuptools project should implement the setuptools package.
+ """
+ self.assertEqual(
+ Requirement.parse('setuptools').project_name, 'setuptools')
+ # setuptools 0.7 and higher means setuptools.
+ self.assertEqual(
+ Requirement.parse('setuptools == 0.7').project_name, 'setuptools')
+ self.assertEqual(
+ Requirement.parse('setuptools == 0.7a1').project_name, 'setuptools')
+ self.assertEqual(
+ Requirement.parse('setuptools >= 0.7').project_name, 'setuptools')
@@ -452,7 +459,7 @@ class ParseTests(TestCase):
def testVersionOrdering(self):
def c(s1,s2):
p1, p2 = parse_version(s1),parse_version(s2)
- self.failUnless(p1<p2, (s1,s2,p1,p2))
+ self.assertTrue(p1<p2, (s1,s2,p1,p2))
c('2.1','2.1.1')
c('2a1','2b0')
@@ -505,6 +512,19 @@ class ScriptHeaderTests(TestCase):
'#!%s -x\n' % self.non_ascii_exe)
def test_get_script_header_jython_workaround(self):
+ # This test doesn't work with Python 3 in some locales
+ if (sys.version_info >= (3,) and os.environ.get("LC_CTYPE")
+ in (None, "C", "POSIX")):
+ return
+
+ class java:
+ class lang:
+ class System:
+ @staticmethod
+ def getProperty(property):
+ return ""
+ sys.modules["java"] = java
+
platform = sys.platform
sys.platform = 'java1.5.0_13'
stdout = sys.stdout
@@ -517,17 +537,78 @@ class ScriptHeaderTests(TestCase):
# Ensure we generate what is basically a broken shebang line
# when there's options, with a warning emitted
- sys.stdout = StringIO.StringIO()
+ sys.stdout = sys.stderr = StringIO.StringIO()
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())
- sys.stdout = StringIO.StringIO()
+ 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:
+ del sys.modules["java"]
sys.platform = platform
sys.stdout = stdout
+
+
+
+class NamespaceTests(TestCase):
+
+ def setUp(self):
+ self._ns_pkgs = pkg_resources._namespace_packages.copy()
+ self._tmpdir = tempfile.mkdtemp(prefix="tests-setuptools-")
+ os.makedirs(os.path.join(self._tmpdir, "site-pkgs"))
+ self._prev_sys_path = sys.path[:]
+ sys.path.append(os.path.join(self._tmpdir, "site-pkgs"))
+
+ def tearDown(self):
+ shutil.rmtree(self._tmpdir)
+ 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
+ Create namespace packages in the following tree :
+ site-packages-1/pkg1/pkg2
+ site-packages-2/pkg1/pkg2
+ Check both are in the _namespace_packages dict and that their __path__
+ is correct
+ """
+ sys.path.append(os.path.join(self._tmpdir, "site-pkgs2"))
+ os.makedirs(os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"))
+ os.makedirs(os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2"))
+ ns_str = "__import__('pkg_resources').declare_namespace(__name__)\n"
+ for site in ["site-pkgs", "site-pkgs2"]:
+ pkg1_init = open(os.path.join(self._tmpdir, site,
+ "pkg1", "__init__.py"), "w")
+ pkg1_init.write(ns_str)
+ pkg1_init.close()
+ pkg2_init = open(os.path.join(self._tmpdir, site,
+ "pkg1", "pkg2", "__init__.py"), "w")
+ pkg2_init.write(ns_str)
+ pkg2_init.close()
+ import pkg1
+ self._assertIn("pkg1", pkg_resources._namespace_packages.keys())
+ try:
+ import pkg1.pkg2
+ except ImportError, e:
+ self.fail("Setuptools tried to import the parent namespace package")
+ # check the _namespace_packages dict
+ 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__, [
+ os.path.join(self._tmpdir, "site-pkgs", "pkg1", "pkg2"),
+ os.path.join(self._tmpdir, "site-pkgs2", "pkg1", "pkg2") ])
+
diff --git a/setuptools/tests/test_sandbox.py b/setuptools/tests/test_sandbox.py
new file mode 100644
index 00000000..1609ee86
--- /dev/null
+++ b/setuptools/tests/test_sandbox.py
@@ -0,0 +1,66 @@
+"""develop tests
+"""
+import sys
+import os
+import shutil
+import unittest
+import tempfile
+
+from setuptools.sandbox import DirectorySandbox, SandboxViolation
+
+def has_win32com():
+ """
+ Run this to determine if the local machine has win32com, and if it
+ does, include additional tests.
+ """
+ if not sys.platform.startswith('win32'):
+ return False
+ try:
+ mod = __import__('win32com')
+ except ImportError:
+ return False
+ return True
+
+class TestSandbox(unittest.TestCase):
+
+ def setUp(self):
+ self.dir = tempfile.mkdtemp()
+
+ def tearDown(self):
+ shutil.rmtree(self.dir)
+
+ def test_devnull(self):
+ if sys.version < '2.4':
+ return
+ sandbox = DirectorySandbox(self.dir)
+ sandbox.run(self._file_writer(os.devnull))
+
+ def _file_writer(path):
+ def do_write():
+ f = open(path, 'w')
+ f.write('xxx')
+ f.close()
+ return do_write
+
+ _file_writer = staticmethod(_file_writer)
+
+ if has_win32com():
+ def test_win32com(self):
+ """
+ win32com should not be prevented from caching COM interfaces
+ in gen_py.
+ """
+ import win32com
+ gen_py = win32com.__gen_path__
+ target = os.path.join(gen_py, 'test_write')
+ sandbox = DirectorySandbox(self.dir)
+ try:
+ try:
+ sandbox.run(self._file_writer(target))
+ except SandboxViolation:
+ self.fail("Could not create gen_py file due to SandboxViolation")
+ finally:
+ if os.path.exists(target): os.remove(target)
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/setuptools/tests/test_sdist.py b/setuptools/tests/test_sdist.py
new file mode 100644
index 00000000..a9d5d6e5
--- /dev/null
+++ b/setuptools/tests/test_sdist.py
@@ -0,0 +1,383 @@
+# -*- coding: utf-8 -*-
+"""sdist tests"""
+
+
+import os
+import shutil
+import sys
+import tempfile
+import unittest
+import urllib
+import unicodedata
+from StringIO import StringIO
+
+
+from setuptools.command.sdist import sdist
+from setuptools.command.egg_info import manifest_maker
+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
+
+
+if sys.version_info >= (3,):
+ LATIN1_FILENAME = 'smörbröd.py'.encode('latin-1')
+else:
+ LATIN1_FILENAME = 'sm\xf6rbr\xf6d.py'
+
+
+# Cannot use context manager because of Python 2.4
+def quiet():
+ global old_stdout, old_stderr
+ old_stdout, old_stderr = sys.stdout, sys.stderr
+ sys.stdout, sys.stderr = StringIO(), StringIO()
+
+def unquiet():
+ sys.stdout, sys.stderr = old_stdout, old_stderr
+
+
+# Fake byte literals for Python <= 2.5
+def b(s, encoding='utf-8'):
+ if sys.version_info >= (3,):
+ return s.encode(encoding)
+ return s
+
+
+# Convert to POSIX path
+def posix(path):
+ if sys.version_info >= (3,) and not isinstance(path, unicode):
+ return path.replace(os.sep.encode('ascii'), b('/'))
+ else:
+ return path.replace(os.sep, '/')
+
+
+# HFS Plus uses decomposed UTF-8
+def decompose(path):
+ if isinstance(path, unicode):
+ return unicodedata.normalize('NFD', path)
+ try:
+ path = path.decode('utf-8')
+ path = unicodedata.normalize('NFD', path)
+ path = path.encode('utf-8')
+ except UnicodeError:
+ pass # Not UTF-8
+ return path
+
+
+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
+ quiet()
+ try:
+ cmd.run()
+ finally:
+ unquiet()
+
+ 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_manifest_is_written_with_utf8_encoding(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ mm = manifest_maker(dist)
+ mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ os.mkdir('sdist_test.egg-info')
+
+ # UTF-8 filename
+ filename = os.path.join('sdist_test', 'smörbröd.py')
+
+ # Add UTF-8 filename and write manifest
+ quiet()
+ try:
+ mm.run()
+ mm.filelist.files.append(filename)
+ mm.write_manifest()
+ finally:
+ unquiet()
+
+ manifest = open(mm.manifest, 'rbU')
+ contents = manifest.read()
+ manifest.close()
+
+ # The manifest should be UTF-8 encoded
+ try:
+ u_contents = contents.decode('UTF-8')
+ except UnicodeDecodeError, e:
+ self.fail(e)
+
+ # The manifest should contain the UTF-8 filename
+ if sys.version_info >= (3,):
+ self.assertTrue(posix(filename) in u_contents)
+ else:
+ self.assertTrue(posix(filename) in contents)
+
+ # Python 3 only
+ if sys.version_info >= (3,):
+
+ def test_write_manifest_allows_utf8_filenames(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ mm = manifest_maker(dist)
+ mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ os.mkdir('sdist_test.egg-info')
+
+ # UTF-8 filename
+ filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
+
+ # Add filename and write manifest
+ quiet()
+ try:
+ mm.run()
+ u_filename = filename.decode('utf-8')
+ mm.filelist.files.append(u_filename)
+ # Re-write manifest
+ mm.write_manifest()
+ finally:
+ unquiet()
+
+ manifest = open(mm.manifest, 'rbU')
+ contents = manifest.read()
+ manifest.close()
+
+ # The manifest should be UTF-8 encoded
+ try:
+ contents.decode('UTF-8')
+ except UnicodeDecodeError, e:
+ self.fail(e)
+
+ # The manifest should contain the UTF-8 filename
+ self.assertTrue(posix(filename) in contents)
+
+ # The filelist should have been updated as well
+ self.assertTrue(u_filename in mm.filelist.files)
+
+ def test_write_manifest_skips_non_utf8_filenames(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ mm = manifest_maker(dist)
+ mm.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ os.mkdir('sdist_test.egg-info')
+
+ # Latin-1 filename
+ filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+
+ # Add filename with surrogates and write manifest
+ quiet()
+ try:
+ mm.run()
+ u_filename = filename.decode('utf-8', 'surrogateescape')
+ mm.filelist.files.append(u_filename)
+ # Re-write manifest
+ mm.write_manifest()
+ finally:
+ unquiet()
+
+ manifest = open(mm.manifest, 'rbU')
+ contents = manifest.read()
+ manifest.close()
+
+ # The manifest should be UTF-8 encoded
+ try:
+ contents.decode('UTF-8')
+ except UnicodeDecodeError, e:
+ self.fail(e)
+
+ # The Latin-1 filename should have been skipped
+ self.assertFalse(posix(filename) in contents)
+
+ # The filelist should have been updated as well
+ self.assertFalse(u_filename in mm.filelist.files)
+
+ def test_manifest_is_read_with_utf8_encoding(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ # Create manifest
+ quiet()
+ try:
+ cmd.run()
+ finally:
+ unquiet()
+
+ # Add UTF-8 filename to manifest
+ filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
+ cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ manifest = open(cmd.manifest, 'ab')
+ manifest.write(b('\n')+filename)
+ manifest.close()
+
+ # The file must exist to be included in the filelist
+ open(filename, 'w').close()
+
+ # Re-read manifest
+ cmd.filelist.files = []
+ quiet()
+ try:
+ cmd.read_manifest()
+ finally:
+ unquiet()
+
+ # The filelist should contain the UTF-8 filename
+ if sys.version_info >= (3,):
+ filename = filename.decode('utf-8')
+ self.assertTrue(filename in cmd.filelist.files)
+
+ # Python 3 only
+ if sys.version_info >= (3,):
+
+ def test_read_manifest_skips_non_utf8_filenames(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ # Create manifest
+ quiet()
+ try:
+ cmd.run()
+ finally:
+ unquiet()
+
+ # Add Latin-1 filename to manifest
+ filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+ cmd.manifest = os.path.join('sdist_test.egg-info', 'SOURCES.txt')
+ manifest = open(cmd.manifest, 'ab')
+ manifest.write(b('\n')+filename)
+ manifest.close()
+
+ # The file must exist to be included in the filelist
+ open(filename, 'w').close()
+
+ # Re-read manifest
+ cmd.filelist.files = []
+ quiet()
+ try:
+ try:
+ cmd.read_manifest()
+ except UnicodeDecodeError, e:
+ self.fail(e)
+ finally:
+ unquiet()
+
+ # The Latin-1 filename should have been skipped
+ filename = filename.decode('latin-1')
+ self.assertFalse(filename in cmd.filelist.files)
+
+ def test_sdist_with_utf8_encoded_filename(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ # UTF-8 filename
+ filename = os.path.join(b('sdist_test'), b('smörbröd.py'))
+ open(filename, 'w').close()
+
+ quiet()
+ try:
+ cmd.run()
+ finally:
+ unquiet()
+
+ if sys.platform == 'darwin':
+ filename = decompose(filename)
+
+ if sys.version_info >= (3,):
+ if sys.platform == 'win32':
+ # Python 3 mangles the UTF-8 filename
+ filename = filename.decode('cp1252')
+ self.assertTrue(filename in cmd.filelist.files)
+ else:
+ filename = filename.decode('utf-8')
+ self.assertTrue(filename in cmd.filelist.files)
+ else:
+ self.assertTrue(filename in cmd.filelist.files)
+
+ def test_sdist_with_latin1_encoded_filename(self):
+ # Test for #303.
+ dist = Distribution(SETUP_ATTRS)
+ dist.script_name = 'setup.py'
+ cmd = sdist(dist)
+ cmd.ensure_finalized()
+
+ # Latin-1 filename
+ filename = os.path.join(b('sdist_test'), LATIN1_FILENAME)
+ open(filename, 'w').close()
+
+ quiet()
+ try:
+ cmd.run()
+ finally:
+ unquiet()
+
+ if sys.version_info >= (3,):
+ filename = filename.decode('latin-1')
+ if sys.platform == 'win32':
+ # Latin-1 is similar to Windows-1252
+ self.assertTrue(filename in cmd.filelist.files)
+ else:
+ # The Latin-1 filename should have been skipped
+ self.assertFalse(filename in cmd.filelist.files)
+ else:
+ # No conversion takes place under Python 2 and the file
+ # is included. We shall keep it that way for BBB.
+ 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
diff --git a/setuptools/tests/test_upload_docs.py b/setuptools/tests/test_upload_docs.py
new file mode 100644
index 00000000..769f16cc
--- /dev/null
+++ b/setuptools/tests/test_upload_docs.py
@@ -0,0 +1,72 @@
+"""build_ext tests
+"""
+import sys, os, shutil, tempfile, unittest, site, zipfile
+from setuptools.command.upload_docs import upload_docs
+from setuptools.dist import Distribution
+
+SETUP_PY = """\
+from setuptools import setup
+
+setup(name='foo')
+"""
+
+class TestUploadDocsTest(unittest.TestCase):
+ def setUp(self):
+ self.dir = tempfile.mkdtemp()
+ setup = os.path.join(self.dir, 'setup.py')
+ f = open(setup, 'w')
+ f.write(SETUP_PY)
+ f.close()
+ self.old_cwd = os.getcwd()
+ os.chdir(self.dir)
+
+ self.upload_dir = os.path.join(self.dir, 'build')
+ os.mkdir(self.upload_dir)
+
+ # A test document.
+ f = open(os.path.join(self.upload_dir, 'index.html'), 'w')
+ f.write("Hello world.")
+ f.close()
+
+ # An empty folder.
+ os.mkdir(os.path.join(self.upload_dir, 'empty'))
+
+ if sys.version >= "2.6":
+ self.old_base = site.USER_BASE
+ site.USER_BASE = upload_docs.USER_BASE = tempfile.mkdtemp()
+ self.old_site = site.USER_SITE
+ site.USER_SITE = upload_docs.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_create_zipfile(self):
+ # Test to make sure zipfile creation handles common cases.
+ # This explicitly includes a folder containing an empty folder.
+
+ dist = Distribution()
+
+ cmd = upload_docs(dist)
+ cmd.upload_dir = self.upload_dir
+ cmd.target_dir = self.upload_dir
+ tmp_dir = tempfile.mkdtemp()
+ tmp_file = os.path.join(tmp_dir, 'foo.zip')
+ try:
+ zip_file = cmd.create_zipfile(tmp_file)
+
+ assert zipfile.is_zipfile(tmp_file)
+
+ zip_file = zipfile.ZipFile(tmp_file) # woh...
+
+ assert zip_file.namelist() == ['index.html']
+
+ zip_file.close()
+ finally:
+ shutil.rmtree(tmp_dir)
+
diff --git a/setuptools/tests/win_script_wrapper.txt b/setuptools/tests/win_script_wrapper.txt
index 2d95502e..9f7c81d6 100644
--- a/setuptools/tests/win_script_wrapper.txt
+++ b/setuptools/tests/win_script_wrapper.txt
@@ -1,137 +1,151 @@
-Python Script Wrapper for Windows
-=================================
-
-setuptools includes wrappers for Python scripts that allows them to be
-executed like regular windows programs. There are 2 wrappers, once
-for command-line programs, cli.exe, and one for graphica programs,
-gui.exe. These programs are almost identical, function pretty much
-the same way, and are generated from the same source file. The
-wrapper programs are used by copying them to the directory containing
-the script they are to wrap and with the same name as the script they
-are to wrap. In the rest of this document, we'll give an example that
-will illustrate this.
-
-Let's create a simple script, foo-script.py:
-
- >>> import os, sys, tempfile
- >>> from setuptools.command.easy_install import nt_quote_arg
- >>> sample_directory = tempfile.mkdtemp()
- >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write(
- ... """#!%(python_exe)s
- ... import sys
- ... input = repr(sys.stdin.read())
- ... print sys.argv[0][-14:]
- ... print sys.argv[1:]
- ... print input
- ... if __debug__:
- ... print 'non-optimized'
- ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
-
-Note that the script starts with a Unix-style '#!' line saying which
-Python executable to run. The wrapper will use this to find the
-correct Python executable.
-
-We'll also copy cli.exe to the sample-directory with the name foo.exe:
-
- >>> import pkg_resources
- >>> open(os.path.join(sample_directory, 'foo.exe'), 'wb').write(
- ... pkg_resources.resource_string('setuptools', 'cli.exe')
- ... )
-
-When the copy of cli.exe, foo.exe in this example, runs, it examines
-the path name it was run with and computes a Python script path name
-by removing the '.exe' suffic and adding the '-script.py' suffix. (For
-GUI programs, the suffix '-script-pyw' is added.) This is why we
-named out script the way we did. Now we can run out script by running
-the wrapper:
-
- >>> import os
- >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))
- ... + r' arg1 "arg 2" "arg \"2\\\"" "arg 4\\" "arg5 a\\b"')
- >>> input.write('hello\nworld\n')
- >>> input.close()
- >>> print output.read(),
- \foo-script.py
- ['arg1', 'arg 2', 'arg "2\\"', 'arg 4\\', 'arg5 a\\\\b']
- 'hello\nworld\n'
- non-optimized
-
-This example was a little pathological in that it exercised windows
-(MS C runtime) quoting rules:
-
-- Strings containing spaces are surrounded by double quotes.
-
-- Double quotes in strings need to be escaped by preceding them with
- back slashes.
-
-- One or more backslashes preceding double quotes quotes need to be
- escaped by preceding each of them them with back slashes.
-
-
-Specifying Python Command-line Options
---------------------------------------
-
-You can specify a single argument on the '#!' line. This can be used
-to specify Python options like -O, to run in optimized mode or -i
-to start the interactive interpreter. You can combine multiple
-options as usual. For example, to run in optimized mode and
-enter the interpreter after running the script, you could use -Oi:
-
- >>> open(os.path.join(sample_directory, 'foo-script.py'), 'w').write(
- ... """#!%(python_exe)s -Oi
- ... import sys
- ... input = repr(sys.stdin.read())
- ... print sys.argv[0][-14:]
- ... print sys.argv[1:]
- ... print input
- ... if __debug__:
- ... print 'non-optimized'
- ... sys.ps1 = '---'
- ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
-
- >>> input, output = os.popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe')))
- >>> input.close()
- >>> print output.read(),
- \foo-script.py
- []
- ''
- ---
-
-Testing the GUI Version
------------------------
-
-Now let's test the GUI version with the simple scipt, bar-script.py:
-
- >>> import os, sys, tempfile
- >>> from setuptools.command.easy_install import nt_quote_arg
- >>> sample_directory = tempfile.mkdtemp()
- >>> open(os.path.join(sample_directory, 'bar-script.pyw'), 'w').write(
- ... """#!%(python_exe)s
- ... import sys
- ... open(sys.argv[1], 'wb').write(repr(sys.argv[2]))
- ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
-
-We'll also copy gui.exe to the sample-directory with the name bar.exe:
-
- >>> import pkg_resources
- >>> open(os.path.join(sample_directory, 'bar.exe'), 'wb').write(
- ... pkg_resources.resource_string('setuptools', 'gui.exe')
- ... )
-
-Finally, we'll run the script and check the result:
-
- >>> import os
- >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'bar.exe'))
- ... + r' "%s" "Test Argument"' % os.path.join(sample_directory, 'test_output.txt'))
- >>> input.close()
- >>> print output.read()
- <BLANKLINE>
- >>> print open(os.path.join(sample_directory, 'test_output.txt'), 'rb').read()
- 'Test Argument'
-
-
-We're done with the sample_directory:
-
- >>> import shutil
- >>> shutil.rmtree(sample_directory)
-
+Python Script Wrapper for Windows
+=================================
+
+setuptools includes wrappers for Python scripts that allows them to be
+executed like regular windows programs. There are 2 wrappers, once
+for command-line programs, cli.exe, and one for graphica programs,
+gui.exe. These programs are almost identical, function pretty much
+the same way, and are generated from the same source file. The
+wrapper programs are used by copying them to the directory containing
+the script they are to wrap and with the same name as the script they
+are to wrap. In the rest of this document, we'll give an example that
+will illustrate this.
+
+Let's create a simple script, foo-script.py:
+
+ >>> import os, sys, tempfile
+ >>> from setuptools.command.easy_install import nt_quote_arg
+ >>> sample_directory = tempfile.mkdtemp()
+ >>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
+ >>> f.write(
+ ... """#!%(python_exe)s
+ ... import sys
+ ... input = repr(sys.stdin.read())
+ ... print sys.argv[0][-14:]
+ ... print sys.argv[1:]
+ ... print input
+ ... if __debug__:
+ ... print 'non-optimized'
+ ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
+ >>> f.close()
+
+Note that the script starts with a Unix-style '#!' line saying which
+Python executable to run. The wrapper will use this to find the
+correct Python executable.
+
+We'll also copy cli.exe to the sample-directory with the name foo.exe:
+
+ >>> import pkg_resources
+ >>> f = open(os.path.join(sample_directory, 'foo.exe'), 'wb')
+ >>> f.write(
+ ... pkg_resources.resource_string('setuptools', 'cli.exe')
+ ... )
+ >>> f.close()
+
+When the copy of cli.exe, foo.exe in this example, runs, it examines
+the path name it was run with and computes a Python script path name
+by removing the '.exe' suffic and adding the '-script.py' suffix. (For
+GUI programs, the suffix '-script-pyw' is added.) This is why we
+named out script the way we did. Now we can run out script by running
+the wrapper:
+
+ >>> import os
+ >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'foo.exe'))
+ ... + r' arg1 "arg 2" "arg \"2\\\"" "arg 4\\" "arg5 a\\b"')
+ >>> input.write('hello\nworld\n')
+ >>> input.close()
+ >>> print output.read(),
+ \foo-script.py
+ ['arg1', 'arg 2', 'arg "2\\"', 'arg 4\\', 'arg5 a\\\\b']
+ 'hello\nworld\n'
+ non-optimized
+
+This example was a little pathological in that it exercised windows
+(MS C runtime) quoting rules:
+
+- Strings containing spaces are surrounded by double quotes.
+
+- Double quotes in strings need to be escaped by preceding them with
+ back slashes.
+
+- One or more backslashes preceding double quotes quotes need to be
+ escaped by preceding each of them them with back slashes.
+
+
+Specifying Python Command-line Options
+--------------------------------------
+
+You can specify a single argument on the '#!' line. This can be used
+to specify Python options like -O, to run in optimized mode or -i
+to start the interactive interpreter. You can combine multiple
+options as usual. For example, to run in optimized mode and
+enter the interpreter after running the script, you could use -Oi:
+
+ >>> f = open(os.path.join(sample_directory, 'foo-script.py'), 'w')
+ >>> f.write(
+ ... """#!%(python_exe)s -Oi
+ ... import sys
+ ... input = repr(sys.stdin.read())
+ ... print sys.argv[0][-14:]
+ ... print sys.argv[1:]
+ ... print input
+ ... if __debug__:
+ ... print 'non-optimized'
+ ... sys.ps1 = '---'
+ ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
+ >>> f.close()
+
+ >>> input, output = os.popen4(nt_quote_arg(os.path.join(sample_directory, 'foo.exe')))
+ >>> input.close()
+ >>> print output.read(),
+ \foo-script.py
+ []
+ ''
+ ---
+
+Testing the GUI Version
+-----------------------
+
+Now let's test the GUI version with the simple scipt, bar-script.py:
+
+ >>> import os, sys, tempfile
+ >>> from setuptools.command.easy_install import nt_quote_arg
+ >>> sample_directory = tempfile.mkdtemp()
+ >>> f = open(os.path.join(sample_directory, 'bar-script.pyw'), 'w')
+ >>> f.write(
+ ... """#!%(python_exe)s
+ ... import sys
+ ... f = open(sys.argv[1], 'wb')
+ ... f.write(repr(sys.argv[2]))
+ ... f.close()
+ ... """ % dict(python_exe=nt_quote_arg(sys.executable)))
+ >>> f.close()
+
+We'll also copy gui.exe to the sample-directory with the name bar.exe:
+
+ >>> import pkg_resources
+ >>> f = open(os.path.join(sample_directory, 'bar.exe'), 'wb')
+ >>> f.write(
+ ... pkg_resources.resource_string('setuptools', 'gui.exe')
+ ... )
+ >>> f.close()
+
+Finally, we'll run the script and check the result:
+
+ >>> import os
+ >>> input, output = os.popen4('"'+nt_quote_arg(os.path.join(sample_directory, 'bar.exe'))
+ ... + r' "%s" "Test Argument"' % os.path.join(sample_directory, 'test_output.txt'))
+ >>> input.close()
+ >>> print output.read()
+ <BLANKLINE>
+ >>> f = open(os.path.join(sample_directory, 'test_output.txt'), 'rb')
+ >>> print f.read()
+ 'Test Argument'
+ >>> f.close()
+
+
+We're done with the sample_directory:
+
+ >>> import shutil
+ >>> shutil.rmtree(sample_directory)
+