diff options
-rw-r--r-- | .hgignore | 1 | ||||
-rw-r--r-- | .hgtags | 1 | ||||
-rw-r--r-- | CHANGES.txt | 11 | ||||
-rw-r--r-- | CONTRIBUTORS.txt | 2 | ||||
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rwxr-xr-x | README.txt | 6 | ||||
-rw-r--r-- | distribute.egg-info/entry_points.txt | 2 | ||||
-rw-r--r-- | distribute_setup.py | 7 | ||||
-rw-r--r-- | docs/conf.py | 4 | ||||
-rw-r--r-- | pkg_resources.py | 18 | ||||
-rwxr-xr-x | release.sh | 2 | ||||
-rwxr-xr-x | setup.py | 36 | ||||
-rwxr-xr-x | setuptools/command/easy_install.py | 7 | ||||
-rwxr-xr-x | setuptools/package_index.py | 4 | ||||
-rw-r--r-- | setuptools/tests/indexes/test_links_priority/external.html | 3 | ||||
-rw-r--r-- | setuptools/tests/indexes/test_links_priority/simple/foobar/index.html | 4 | ||||
-rw-r--r-- | setuptools/tests/server.py | 48 | ||||
-rw-r--r-- | setuptools/tests/test_easy_install.py | 8 | ||||
-rw-r--r-- | setuptools/tests/test_packageindex.py | 36 | ||||
-rw-r--r-- | test.sh | 50 |
20 files changed, 221 insertions, 30 deletions
@@ -10,3 +10,4 @@ lib bin include \.Python +*.swp @@ -15,3 +15,4 @@ ac7d9b14ac43fecb8b65de548b25773553facaee 0.6.9 f18396c6e1875476279d8bbffd8e6dadcc695136 0.6.10 e00987890c0b386f09d0f6b73d8558b72f6367f1 0.6.11 48a97bc89e2f65fc9b78b358d7dc89ba9ec9524a 0.6.12 +dae247400d0ca1fdfaf38db275622c9bec550b08 0.6.13 diff --git a/CHANGES.txt b/CHANGES.txt index f7119ada..93381aad 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,11 +3,22 @@ CHANGES ======= ------ +0.6.14 +------ + +* Issue 170: Fixed unittest failure. Thanks to Toshio. +* Issue 171: Fixed race condition in unittests cause deadlocks in test suite. +* Issue 143: Fixed a lookup issue with easy_install. + Thanks to David and Zooko. + +------ 0.6.13 ------ * Issue 160: 2.7 gives ValueError("Invalid IPv6 URL") * Issue 150: Fixed using ~/.local even in a --no-site-packages virtualenv +* Issue 163: scan index links before external links, and don't use the md5 when + comparing two distributions ------ 0.6.12 diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index da9e0219..f0ec2ba4 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -5,6 +5,7 @@ Contributors * Alex Grönholm * Alice Bevan-McGregor * Arfrever Frehtes Taifersar Arahesis +* Christophe Combelles * Daniel Stutzbach * Hanno Schlichting * Jannis Leidel @@ -14,6 +15,7 @@ Contributors * Philip Jenvey * Reinout van Rees * Tarek Ziadé +* Toshio Kuratomi If you think you name is missing, please add it (alpha order by first name) diff --git a/MANIFEST.in b/MANIFEST.in index 97fef03a..461cfd4f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,6 @@ recursive-include setuptools *.py *.txt *.exe recursive-include tests *.py *.c *.pyx *.txt +recursive-include setuptools/tests *.html recursive-include docs *.py *.txt *.conf *.css *.css_t Makefile indexsidebar.html include *.py include *.txt @@ -99,9 +99,9 @@ Source installation Download the source tarball, uncompress it, then run the install command:: - $ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.13.tar.gz - $ tar -xzvf distribute-0.6.13.tar.gz - $ cd distribute-0.6.13 + $ curl -O http://pypi.python.org/packages/source/d/distribute/distribute-0.6.14.tar.gz + $ tar -xzvf distribute-0.6.14.tar.gz + $ cd distribute-0.6.14 $ python setup.py install --------------------------- diff --git a/distribute.egg-info/entry_points.txt b/distribute.egg-info/entry_points.txt index 0ee58646..1c9f123d 100644 --- a/distribute.egg-info/entry_points.txt +++ b/distribute.egg-info/entry_points.txt @@ -32,7 +32,7 @@ depends.txt = setuptools.command.egg_info:warn_depends_obsolete [console_scripts] easy_install = setuptools.command.easy_install:main -easy_install-2.5 = setuptools.command.easy_install:main +easy_install-2.6 = setuptools.command.easy_install:main [setuptools.file_finders] svn_cvs = setuptools.command.sdist:_default_revctrl diff --git a/distribute_setup.py b/distribute_setup.py index 194861b5..37117b34 100644 --- a/distribute_setup.py +++ b/distribute_setup.py @@ -361,8 +361,8 @@ def _under_prefix(location): if len(args) > index: top_dir = args[index+1] return location.startswith(top_dir) - elif option == '--user' and USER_SITE is not None: - return location.startswith(USER_SITE) + if arg == '--user' and USER_SITE is not None: + return location.startswith(USER_SITE) return True @@ -421,6 +421,9 @@ def _fake_setuptools(): def _relaunch(): log.warn('Relaunching...') # we have to relaunch the process + # pip marker to avoid a relaunch bug + if sys.argv[:3] == ['-c', 'install', '--single-version-externally-managed']: + sys.argv[0] = 'setup.py' args = [sys.executable] + sys.argv sys.exit(subprocess.call(args)) diff --git a/docs/conf.py b/docs/conf.py index 53614ed5..59443dd1 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -48,9 +48,9 @@ copyright = u'2009, The fellowship of the packaging' # built documents. # # The short X.Y version. -version = '0.6.13' +version = '0.6.14' # The full version, including alpha/beta/rc tags. -release = '0.6.4' +release = '0.6.14' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pkg_resources.py b/pkg_resources.py index 6ec51fa0..30dbc188 100644 --- a/pkg_resources.py +++ b/pkg_resources.py @@ -14,6 +14,7 @@ method. """ import sys, os, zipimport, time, re, imp, types +from urlparse import urlparse, urlunparse try: frozenset @@ -2044,8 +2045,13 @@ class EntryPoint(object): parse_map = classmethod(parse_map) - - +def _remove_md5_fragment(location): + if not location: + return '' + parsed = urlparse(location) + if parsed[-1].startswith('md5='): + return urlunparse(parsed[:-1] + ('',)) + return location class Distribution(object): @@ -2079,10 +2085,14 @@ class Distribution(object): ) from_location = classmethod(from_location) + hashcmp = property( lambda self: ( - getattr(self,'parsed_version',()), self.precedence, self.key, - -len(self.location or ''), self.location, self.py_version, + getattr(self,'parsed_version',()), + self.precedence, + self.key, + _remove_md5_fragment(self.location), + self.py_version, self.platform ) ) @@ -1,5 +1,5 @@ #!/bin/sh -export VERSION="0.6.12" +export VERSION="0.6.14" # tagging hg tag $VERSION @@ -37,10 +37,12 @@ init_path = convert_path('setuptools/command/__init__.py') exec(open(init_path).read(), d) SETUP_COMMANDS = d['__all__'] -VERSION = "0.6.13" +VERSION = "0.6.14" from setuptools import setup, find_packages from setuptools.command.build_py import build_py as _build_py +from setuptools.command.test import test as _test + scripts = [] # specific command that is used to generate windows .exe files @@ -64,6 +66,36 @@ class build_py(_build_py): if copied and srcfile in self.distribution.convert_2to3_doctests: self.__doctests_2to3.append(outf) +class test(_test): + """Specific test class to avoid rewriting the entry_points.txt""" + def run(self): + entry_points = os.path.join('distribute.egg-info', 'entry_points.txt') + + if not os.path.exists(entry_points): + try: + _test.run(self) + finally: + return + + f = open(entry_points) + + # running the test + try: + ep_content = f.read() + finally: + f.close() + + try: + _test.run(self) + finally: + # restoring the file + f = open(entry_points, 'w') + try: + f.write(ep_content) + finally: + f.close() + + # if we are installing Distribute using "python setup.py install" # we need to get setuptools out of the way def _easy_install_marker(): @@ -90,6 +122,7 @@ if _being_installed(): from distribute_setup import _before_install _before_install() + dist = setup( name="distribute", version=VERSION, @@ -110,6 +143,7 @@ dist = setup( zip_safe = (sys.version>="2.5"), # <2.5 needs unzipped for -m to work + cmdclass = {'test': test}, entry_points = { "distutils.commands" : [ diff --git a/setuptools/command/easy_install.py b/setuptools/command/easy_install.py index e13f676a..2a227196 100755 --- a/setuptools/command/easy_install.py +++ b/setuptools/command/easy_install.py @@ -39,7 +39,7 @@ __all__ = [ ] import site -HAS_USER_SITE = not sys.version < "2.6" +HAS_USER_SITE = not sys.version < "2.6" and site.ENABLE_USER_SITE def samefile(p1,p2): if hasattr(os.path,'samefile') and ( @@ -122,7 +122,7 @@ class easy_install(Command): create_index = PackageIndex def initialize_options(self): - if HAS_USER_SITE and site.ENABLE_USER_SITE: + if HAS_USER_SITE: whereami = os.path.abspath(__file__) self.user = whereami.startswith(site.USER_SITE) else: @@ -1348,8 +1348,7 @@ def get_site_dirs(): site_lib = get_python_lib(plat_specific) if site_lib not in sitedirs: sitedirs.append(site_lib) - if sys.version >= "2.6": - import site + if HAS_USER_SITE: sitedirs.append(site.USER_SITE) sitedirs = map(normalize_path, sitedirs) diff --git a/setuptools/package_index.py b/setuptools/package_index.py index 67e9f6ae..1d467f78 100755 --- a/setuptools/package_index.py +++ b/setuptools/package_index.py @@ -203,11 +203,11 @@ class PackageIndex(Environment): charset = f.headers.get_param('charset') or 'latin-1' page = page.decode(charset, "ignore") f.close() - if url.startswith(self.index_url) and getattr(f,'code',None)!=404: - page = self.process_index(url, page) for match in HREF.finditer(page): link = urlparse.urljoin(base, htmldecode(match.group(1))) self.process_url(link) + if url.startswith(self.index_url) and getattr(f,'code',None)!=404: + page = self.process_index(url, page) def process_filename(self, fn, nested=False): # process filenames or directories 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/server.py b/setuptools/tests/server.py new file mode 100644 index 00000000..f4aaaa1c --- /dev/null +++ b/setuptools/tests/server.py @@ -0,0 +1,48 @@ +"""Basic http server for tests to simulate PyPI or custom indexes +""" +import urllib2 +import sys +from threading import Thread +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): + HTTPServer.__init__(self, ('', 0), SimpleHTTPRequestHandler) + self._run = True + + def serve(self): + while True: + self.handle_request() + if not self._run: break + + def start(self): + self.thread = Thread(target=self.serve) + self.thread.start() + + def stop(self): + """self.shutdown is not supported on python < 2.6""" + self._run = False + try: + if sys.version > '2.6': + urllib2.urlopen('http://127.0.0.1:%s/' % self.server_port, + None, 5) + else: + urllib2.urlopen('http://127.0.0.1:%s/' % self.server_port) + except urllib2.URLError: + pass + self.thread.join() + + def base_url(self): + port = self.server_port + return 'http://127.0.0.1:%s/setuptools/tests/indexes/' % port diff --git a/setuptools/tests/test_easy_install.py b/setuptools/tests/test_easy_install.py index 4791e03c..8caaeb87 100644 --- a/setuptools/tests/test_easy_install.py +++ b/setuptools/tests/test_easy_install.py @@ -158,7 +158,7 @@ class TestUserInstallTest(unittest.TestCase): self.old_cwd = os.getcwd() os.chdir(self.dir) if sys.version >= "2.6": - self.old_enable = site.ENABLE_USER_SITE + 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() @@ -174,11 +174,11 @@ class TestUserInstallTest(unittest.TestCase): shutil.rmtree(site.USER_SITE) site.USER_BASE = self.old_base site.USER_SITE = self.old_site - site.ENABLE_USER_SITE = self.old_enable + easy_install_pkg.HAS_USER_SITE = self.old_has_site easy_install_pkg.__file__ = self.old_file def test_user_install_implied(self): - site.ENABLE_USER_SITE = True # disabled sometimes + easy_install_pkg.HAS_USER_SITE = True # disabled sometimes #XXX: replace with something meaningfull if sys.version < "2.6": return #SKIP @@ -195,7 +195,7 @@ class TestUserInstallTest(unittest.TestCase): _LOG.info('this should not break') def test_user_install_not_implied_without_usersite_enabled(self): - site.ENABLE_USER_SITE = False # disabled sometimes + easy_install_pkg.HAS_USER_SITE = False # usually enabled #XXX: replace with something meaningfull if sys.version < "2.6": return #SKIP diff --git a/setuptools/tests/test_packageindex.py b/setuptools/tests/test_packageindex.py index 8ae7a5b9..42cb8c1e 100644 --- a/setuptools/tests/test_packageindex.py +++ b/setuptools/tests/test_packageindex.py @@ -5,6 +5,7 @@ import sys import os, shutil, tempfile, unittest, urllib2 import pkg_resources import setuptools.package_index +from server import IndexServer class TestPackageIndex(unittest.TestCase): @@ -74,3 +75,38 @@ class TestPackageIndex(unittest.TestCase): url = 'file:///tmp/test_package_index' self.assert_(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 + -> Distribute should use the link from pypi, not the external one. + """ + # 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.assert_('foobar' in pi) + # we have only one link, because links are compared without md5 + self.assert_(len(pi['foobar'])==1) + # the link should be from the index + self.assert_('correct_md5' in pi['foobar'][0].location) + + + @@ -1,9 +1,47 @@ -python2.3 setup.py -q test -python2.4 setup.py -q test -python2.5 setup.py -q test -python2.6 setup.py -q test -python2.7 setup.py -q test +#!/bin/sh +echo -n "Running tests for Python 2.3..." +python2.3 setup.py -q test > /dev/null 2> /dev/null +if [ $? -ne 0 ];then + echo "Failed" + exit $1 +else + echo "Success" +fi + +echo -n "Running tests for Python 2.4..." +python2.4 setup.py -q test > /dev/null 2> /dev/null +if [ $? -ne 0 ];then + echo "Failed" + exit $1 +else + echo "Success" +fi + +echo -n "Running tests for Python 2.5..." +python2.5 setup.py -q test > /dev/null 2> /dev/null +if [ $? -ne 0 ];then + echo "Failed" + exit $1 +else + echo "Success" +fi + +echo -n "Running tests for Python 2.6..." +python2.6 setup.py -q test > /dev/null 2> /dev/null +if [ $? -ne 0 ];then + echo "Failed" + exit $1 +else + echo "Success" +fi rm -rf build -python3.1 setup.py -q test +echo -n "Running tests for Python 3.1..." +python3.1 setup.py -q test > /dev/null 2> /dev/null +if [ $? -ne 0 ];then + echo "Failed" + exit $1 +else + echo "Success" +fi |