Commit 519ed36a authored by Reinout van Rees's avatar Reinout van Rees

Merged master

parents 50cadd78 fcc442e5
Change History Change History
************** **************
Unreleased
==========
- Undo breakage on Windows machines where ``sys.prefix`` can also be a
``site-packages`` directory: don't remove it from ``sys.path``. See
https://github.com/buildout/buildout/issues/217
- Remove assumption that ``pkg_resources`` is a module (untrue since
release of `setuptools 8.3``). See
https://github.com/buildout/buildout/issues/227
- Fix for #212. For certain kinds of conflict errors you'd get an UnpackError
when rendering the error message. Instead of a nicely formatted version
conflict message.
[reinout]
- Making sure we use the correct easy_install when setuptools is installed
globally. See https://github.com/buildout/buildout/pull/232 and
https://github.com/buildout/buildout/pull/222
[lrowe]
- Fixed: In ``zc.recipe.egg#custom`` recipe's ``rpath`` support, don't - Fixed: In ``zc.recipe.egg#custom`` recipe's ``rpath`` support, don't
assume path elements are buildout-relative if they start with one of the assume path elements are buildout-relative if they start with one of the
"special" tokens (e.g., ``$ORIGIN``). See: "special" tokens (e.g., ``$ORIGIN``). See:
https://github.com/buildout/buildout/issues/225. https://github.com/buildout/buildout/issues/225.
[tseaver]
2.3.1 (2014-12-16)
==================
- Fixed: Buildout merged single-version requirements with - Fixed: Buildout merged single-version requirements with
version-range requirements in a way that caused it to think there version-range requirements in a way that caused it to think there
wasn't a single-version requirement. IOW, buildout throught that wasn't a single-version requirement. IOW, buildout throught that
versions were being picked when they weren't. versions were being picked when they weren't.
- Suppress spurios (and possibly non-spurious) version-parsing warnings.
2.3.0 (2014-12-14) 2.3.0 (2014-12-14)
================== ==================
......
...@@ -61,7 +61,9 @@ parser.add_option("--allow-site-packages", ...@@ -61,7 +61,9 @@ parser.add_option("--allow-site-packages",
help=("Let bootstrap.py use existing site packages")) help=("Let bootstrap.py use existing site packages"))
parser.add_option("--setuptools-version", parser.add_option("--setuptools-version",
help="use a specific setuptools version") help="use a specific setuptools version")
parser.add_option("--setuptools-to-dir",
help=("allow for re-use of existing directory of "
"setuptools versions"))
options, args = parser.parse_args() options, args = parser.parse_args()
...@@ -77,7 +79,10 @@ except ImportError: ...@@ -77,7 +79,10 @@ except ImportError:
from urllib2 import urlopen from urllib2 import urlopen
ez = {} ez = {}
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez) if os.path.exists('ez_setup.py'):
exec(open('ez_setup.py').read(), ez)
else:
exec(urlopen('https://bootstrap.pypa.io/ez_setup.py').read(), ez)
if not options.allow_site_packages: if not options.allow_site_packages:
# ez_setup imports site, which adds site packages # ez_setup imports site, which adds site packages
...@@ -88,12 +93,18 @@ if not options.allow_site_packages: ...@@ -88,12 +93,18 @@ if not options.allow_site_packages:
# We can't remove these reliably # We can't remove these reliably
if hasattr(site, 'getsitepackages'): if hasattr(site, 'getsitepackages'):
for sitepackage_path in site.getsitepackages(): for sitepackage_path in site.getsitepackages():
# Strip all site-packages directories from sys.path that
# are not sys.prefix; this is because on Windows
# sys.prefix is a site-package directory.
if sitepackage_path != sys.prefix:
sys.path[:] = [x for x in sys.path if sitepackage_path not in x] sys.path[:] = [x for x in sys.path if sitepackage_path not in x]
setup_args = dict(to_dir=tmpeggs, download_delay=0) setup_args = dict(to_dir=tmpeggs, download_delay=0)
if options.setuptools_version is not None: if options.setuptools_version is not None:
setup_args['version'] = options.setuptools_version setup_args['version'] = options.setuptools_version
if options.setuptools_to_dir is not None:
setup_args['to_dir'] = options.setuptools_to_dir
ez['use_setuptools'](**setup_args) ez['use_setuptools'](**setup_args)
import setuptools import setuptools
...@@ -110,7 +121,12 @@ for path in sys.path: ...@@ -110,7 +121,12 @@ for path in sys.path:
ws = pkg_resources.working_set ws = pkg_resources.working_set
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
# Fix sys.path here as easy_install.pth added before PYTHONPATH
cmd = [sys.executable, '-c', cmd = [sys.executable, '-c',
'import sys; sys.path[0:0] = [%r]; ' % setuptools_path +
'from setuptools.command.easy_install import main; main()', 'from setuptools.command.easy_install import main; main()',
'-mZqNxd', tmpeggs] '-mZqNxd', tmpeggs]
...@@ -123,9 +139,6 @@ find_links = os.environ.get( ...@@ -123,9 +139,6 @@ find_links = os.environ.get(
if find_links: if find_links:
cmd.extend(['-f', find_links]) cmd.extend(['-f', find_links])
setuptools_path = ws.find(
pkg_resources.Requirement.parse('setuptools')).location
requirement = 'zc.buildout' requirement = 'zc.buildout'
version = options.version version = options.version
if version is None and not options.accept_buildout_test_releases: if version is None and not options.accept_buildout_test_releases:
...@@ -167,7 +180,7 @@ if version: ...@@ -167,7 +180,7 @@ if version:
cmd.append(requirement) cmd.append(requirement)
import subprocess import subprocess
if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=setuptools_path)) != 0: if subprocess.call(cmd) != 0:
raise Exception( raise Exception(
"Failed to execute command:\n%s" % repr(cmd)[1:-1]) "Failed to execute command:\n%s" % repr(cmd)[1:-1])
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
# #
############################################################################## ##############################################################################
name = "zc.buildout" name = "zc.buildout"
version = "2.3.0" version = "2.3.1"
import os import os
from setuptools import setup from setuptools import setup
......
...@@ -127,3 +127,35 @@ Let's make sure the generated `buildout` script uses it:: ...@@ -127,3 +127,35 @@ Let's make sure the generated `buildout` script uses it::
'/sample/eggs/setuptools-8.0...egg', '/sample/eggs/setuptools-8.0...egg',
'/sample/eggs/zc.buildout-2.0.0...egg', '/sample/eggs/zc.buildout-2.0.0...egg',
]... ]...
For a completely offline install we want to avoid downloading ez_setup.py,
specify the setuptools version, and to reuse the setuptools zipfile.
>>> try:
... from urllib.request import urlopen
... except ImportError:
... from urllib2 import urlopen
>>> ez_setup = urlopen('https://bootstrap.pypa.io/ez_setup.py').read()
>>> write('ez_setup.py',
... '''print("Using local ez_setup.py")
... ''' + ez_setup.decode('ascii'))
>>> os.path.exists('setuptools-14.3.zip')
False
>>> print_('X'); print_(system(
... zc.buildout.easy_install._safe_arg(sys.executable)+' '+
... 'bootstrap.py --setuptools-version 14.3 --version 2.0.0 '+
... '--setuptools-to-dir .')); print_('X')
... # doctest: +ELLIPSIS
X...Using local ez_setup.py...Generated script '/sample/bin/buildout'...X
>>> os.path.exists('setuptools-14.3.zip')
True
>>> print_(open(buildout_script).read()) # doctest: +ELLIPSIS
#...
sys.path[0:0] = [
'/sample/eggs/setuptools-14.3...egg',
'/sample/eggs/zc.buildout-2.0.0...egg',
]...
...@@ -37,10 +37,10 @@ download: ...@@ -37,10 +37,10 @@ download:
<a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
<a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
<a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br>
<a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> <a href="demo-0.4rc1-py2.4.egg">demo-0.4rc1-py2.4.egg</a><br>
<a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
<a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
<a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> <a href="demoneeded-1.2rc1.zip">demoneeded-1.2rc1.zip</a><br>
<a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br> <a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br>
<a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
<a href="index/">index/</a><br> <a href="index/">index/</a><br>
......
...@@ -322,7 +322,9 @@ class Installer: ...@@ -322,7 +322,9 @@ class Installer:
try: try:
path = setuptools_loc path = setuptools_loc
args = [sys.executable, '-c', _easy_install_cmd, '-mZUNxd', tmp] args = [sys.executable, '-c',
('import sys; sys.path[0:0] = [%r]; ' % path) +
_easy_install_cmd, '-mZUNxd', tmp]
level = logger.getEffectiveLevel() level = logger.getEffectiveLevel()
if level > 0: if level > 0:
args.append('-q') args.append('-q')
...@@ -337,9 +339,7 @@ class Installer: ...@@ -337,9 +339,7 @@ class Installer:
sys.stdout.flush() # We want any pending output first sys.stdout.flush() # We want any pending output first
exit_code = subprocess.call( exit_code = subprocess.call(list(args))
list(args),
env=dict(os.environ, PYTHONPATH=path))
dists = [] dists = []
env = pkg_resources.Environment([tmp]) env = pkg_resources.Environment([tmp])
...@@ -503,7 +503,7 @@ class Installer: ...@@ -503,7 +503,7 @@ class Installer:
if dist is None: if dist is None:
raise zc.buildout.UserError( raise zc.buildout.UserError(
"Couln't download distribution %s." % avail) "Couldn't download distribution %s." % avail)
if dist.precedence == pkg_resources.EGG_DIST: if dist.precedence == pkg_resources.EGG_DIST:
# It's already an egg, just fetch it into the dest # It's already an egg, just fetch it into the dest
...@@ -1350,17 +1350,16 @@ class VersionConflict(zc.buildout.UserError): ...@@ -1350,17 +1350,16 @@ class VersionConflict(zc.buildout.UserError):
self.err, self.ws = err, ws self.err, self.ws = err, ws
def __str__(self): def __str__(self):
result = ["There is a version conflict."]
if len(self.err.args) == 2:
existing_dist, req = self.err.args existing_dist, req = self.err.args
result = ["There is a version conflict.", result.append("We already have: %s" % existing_dist)
"We already have: %s" % existing_dist,
]
stated = False
for dist in self.ws: for dist in self.ws:
if req in dist.requires(): if req in dist.requires():
result.append("but %s requires %r." % (dist, str(req))) result.append("but %s requires %r." % (dist, str(req)))
stated = True else:
if not stated: # The error argument is already a nice error string.
result.append("We require %s" % req) result.append(self.err.args[0])
return '\n'.join(result) return '\n'.join(result)
......
...@@ -97,10 +97,10 @@ We have a link server that has a number of eggs: ...@@ -97,10 +97,10 @@ We have a link server that has a number of eggs:
<a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
<a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
<a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br>
<a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> <a href="demo-0.4rc1-py2.4.egg">demo-0.4rc1-py2.4.egg</a><br>
<a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
<a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
<a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> <a href="demoneeded-1.2rc1.zip">demoneeded-1.2rc1.zip</a><br>
<a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br> <a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br>
<a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
<a href="index/">index/</a><br> <a href="index/">index/</a><br>
...@@ -168,15 +168,15 @@ The old setting is returned. ...@@ -168,15 +168,15 @@ The old setting is returned.
... ['demo'], dest, links=[link_server], index=link_server+'index/') ... ['demo'], dest, links=[link_server], index=link_server+'index/')
>>> for dist in ws: >>> for dist in ws:
... print_(dist) ... print_(dist)
demo 0.4c1 demo 0.4rc1
demoneeded 1.2c1 demoneeded 1.2rc1
>>> ls(dest) >>> ls(dest)
d demo-0.2-py2.4.egg d demo-0.2-py2.4.egg
d demo-0.3-py2.4.egg d demo-0.3-py2.4.egg
d demo-0.4c1-py2.4.egg d demo-0.4rc1-py2.4.egg
d demoneeded-1.1-py2.4.egg d demoneeded-1.1-py2.4.egg
d demoneeded-1.2c1-py2.4.egg d demoneeded-1.2rc1-py2.4.egg
Let's put the setting back to the default. Let's put the setting back to the default.
...@@ -200,10 +200,10 @@ dependencies. We might do this to specify a specific version. ...@@ -200,10 +200,10 @@ dependencies. We might do this to specify a specific version.
>>> ls(dest) >>> ls(dest)
d demo-0.2-py2.4.egg d demo-0.2-py2.4.egg
d demo-0.3-py2.4.egg d demo-0.3-py2.4.egg
d demo-0.4c1-py2.4.egg d demo-0.4rc1-py2.4.egg
d demoneeded-1.0-py2.4.egg d demoneeded-1.0-py2.4.egg
d demoneeded-1.1-py2.4.egg d demoneeded-1.1-py2.4.egg
d demoneeded-1.2c1-py2.4.egg d demoneeded-1.2rc1-py2.4.egg
d other-1.0-py2.4.egg d other-1.0-py2.4.egg
>>> rmdir(dest) >>> rmdir(dest)
...@@ -1117,10 +1117,10 @@ Let's update our link server with a new version of extdemo: ...@@ -1117,10 +1117,10 @@ Let's update our link server with a new version of extdemo:
<a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br>
<a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br>
<a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br>
<a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> <a href="demo-0.4rc1-py2.4.egg">demo-0.4rc1-py2.4.egg</a><br>
<a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
<a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
<a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> <a href="demoneeded-1.2rc1.zip">demoneeded-1.2rc1.zip</a><br>
<a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br> <a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br>
<a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
<a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br> <a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br>
......
...@@ -453,7 +453,7 @@ def wait(port, up): ...@@ -453,7 +453,7 @@ def wait(port, up):
if up: if up:
raise raise
else: else:
raise SystemError("Couln't stop server") raise SystemError("Couldn't stop server")
def install(project, destination): def install(project, destination):
if not isinstance(destination, str): if not isinstance(destination, str):
......
...@@ -361,6 +361,30 @@ If we use the verbose switch, we can see where requirements are coming from: ...@@ -361,6 +361,30 @@ If we use the verbose switch, we can see where requirements are coming from:
but sampley 1 requires 'demoneeded==1.0'. but sampley 1 requires 'demoneeded==1.0'.
""" """
def version_conflict_rendering():
"""
We use the arguments passed by pkg_resources.VersionConflict to construct a
nice error message:
>>> error = pkg_resources.VersionConflict('pkg1 2.1', 'pkg1 1.0')
>>> ws = [] # Not relevant for this test
>>> print_(zc.buildout.easy_install.VersionConflict(
... error, ws)) # doctest: +ELLIPSIS
There is a version conflict...
But sometimes pkg_resources passes a nicely formatted string itself already.
Extracting the original arguments fails in that case, so we just show the string.
>>> error = pkg_resources.VersionConflict('pkg1 2.1 is simply wrong')
>>> ws = [] # Not relevant for this test
>>> print_(zc.buildout.easy_install.VersionConflict(
... error, ws)) # doctest: +ELLIPSIS
There is a version conflict.
pkg1 2.1 is simply wrong
"""
def show_who_requires_missing_distributions(): def show_who_requires_missing_distributions():
""" """
...@@ -2320,9 +2344,9 @@ distributions: ...@@ -2320,9 +2344,9 @@ distributions:
>>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS >>> print_(system(buildout+' -v'), end='') # doctest: +ELLIPSIS
Installing 'zc.buildout', 'setuptools'. Installing 'zc.buildout', 'setuptools'.
... ...
Picked: demo = 0.4c1 Picked: demo = 0.4rc1
... ...
Picked: demoneeded = 1.2c1 Picked: demoneeded = 1.2rc1
We get an error if we specify anything but true or false: We get an error if we specify anything but true or false:
...@@ -2981,14 +3005,14 @@ def create_sample_eggs(test, executable=sys.executable): ...@@ -2981,14 +3005,14 @@ def create_sample_eggs(test, executable=sys.executable):
for i in (0, 1, 2): for i in (0, 1, 2):
write(tmp, 'eggrecipedemoneeded.py', 'y=%s\ndef f():\n pass' % i) write(tmp, 'eggrecipedemoneeded.py', 'y=%s\ndef f():\n pass' % i)
c1 = i==2 and 'c1' or '' rc1 = i==2 and 'rc1' or ''
write( write(
tmp, 'setup.py', tmp, 'setup.py',
"from setuptools import setup\n" "from setuptools import setup\n"
"setup(name='demoneeded', py_modules=['eggrecipedemoneeded']," "setup(name='demoneeded', py_modules=['eggrecipedemoneeded'],"
" zip_safe=True, version='1.%s%s', author='bob', url='bob', " " zip_safe=True, version='1.%s%s', author='bob', url='bob', "
"author_email='bob')\n" "author_email='bob')\n"
% (i, c1) % (i, rc1)
) )
zc.buildout.testing.sdist(tmp, dest) zc.buildout.testing.sdist(tmp, dest)
...@@ -3032,7 +3056,7 @@ def create_sample_eggs(test, executable=sys.executable): ...@@ -3032,7 +3056,7 @@ def create_sample_eggs(test, executable=sys.executable):
'def main():\n' 'def main():\n'
' print_(x, eggrecipedemoneeded.y)\n' ' print_(x, eggrecipedemoneeded.y)\n'
% i) % i)
c1 = i==4 and 'c1' or '' rc1 = i==4 and 'rc1' or ''
write( write(
tmp, 'setup.py', tmp, 'setup.py',
"from setuptools import setup\n" "from setuptools import setup\n"
...@@ -3040,7 +3064,7 @@ def create_sample_eggs(test, executable=sys.executable): ...@@ -3040,7 +3064,7 @@ def create_sample_eggs(test, executable=sys.executable):
" install_requires = 'demoneeded'," " install_requires = 'demoneeded',"
" entry_points={'console_scripts': " " entry_points={'console_scripts': "
"['demo = eggrecipedemo:main']}," "['demo = eggrecipedemo:main']},"
" zip_safe=True, version='0.%s%s')\n" % (i, c1) " zip_safe=True, version='0.%s%s')\n" % (i, rc1)
) )
zc.buildout.testing.bdist_egg(tmp, dest) zc.buildout.testing.bdist_egg(tmp, dest)
......
...@@ -31,10 +31,10 @@ We have a link server that has a number of distributions: ...@@ -31,10 +31,10 @@ We have a link server that has a number of distributions:
<a href="demo-0.1-py2.3.egg">demo-0.1-py2.3.egg</a><br> <a href="demo-0.1-py2.3.egg">demo-0.1-py2.3.egg</a><br>
<a href="demo-0.2-py2.3.egg">demo-0.2-py2.3.egg</a><br> <a href="demo-0.2-py2.3.egg">demo-0.2-py2.3.egg</a><br>
<a href="demo-0.3-py2.3.egg">demo-0.3-py2.3.egg</a><br> <a href="demo-0.3-py2.3.egg">demo-0.3-py2.3.egg</a><br>
<a href="demo-0.4c1-py2.3.egg">demo-0.4c1-py2.3.egg</a><br> <a href="demo-0.4rc1-py2.3.egg">demo-0.4rc1-py2.3.egg</a><br>
<a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br>
<a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br>
<a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> <a href="demoneeded-1.2rc1.zip">demoneeded-1.2rc1.zip</a><br>
<a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br> <a href="du_zipped-1.0-pyN.N.egg">du_zipped-1.0-pyN.N.egg</a><br>
<a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br>
<a href="index/">index/</a><br> <a href="index/">index/</a><br>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment