Commit 09b61214 authored by Reinout van Rees's avatar Reinout van Rees

Merge pull request #282 from buildout/reinout-constraint-logging

Nicer version constraint logging + better requirement conflict info logging
parents cc0c0d4f caff88e3
......@@ -2,9 +2,9 @@ language: python
env:
- PYTHON_VER=2.6
- PYTHON_VER=2.7
- PYTHON_VER=3.2
- PYTHON_VER=3.3
- PYTHON_VER=3.4
- PYTHON_VER=3.5
sudo: false
cache:
......
......@@ -4,7 +4,17 @@ Change History
2.4.8 (unreleased)
==================
- Nothing changed yet.
- Added more elaborate version and requirement information when there's a
version conflict. Previously, you could get a report of a version conflict
without information about which dependency requested the conflicing
requirement.
Now all this information is logged and displayed in case of an error.
[reinout]
- Dropped 3.2 support (at least in the automatic tests) as setuptools will
soon stop supporting it. Added python 3.5 to the automatic tests.
[reinout]
2.4.7 (2015-10-29)
......
......@@ -19,6 +19,10 @@ ifeq ($(PYTHON_VER),3.4)
PYTHON_MINOR ?= 3.4.2
PYTHON_CONFIGURE_ARGS ?= --without-ensurepip
endif
ifeq ($(PYTHON_VER),3.5)
PYTHON_MINOR ?= 3.5.0
PYTHON_CONFIGURE_ARGS ?= --without-ensurepip
endif
ifndef PYTHON_MINOR
$(error Please specify desired PYTHON_MINOR for Python $(PYTHON_VER))
......
......@@ -102,9 +102,9 @@ setup(
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.2',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Topic :: Software Development :: Build Tools',
'Topic :: Software Development :: Libraries :: Python Modules',
],
......
......@@ -222,10 +222,28 @@ class Installer:
self._newest = newest
self._env = pkg_resources.Environment(path)
self._index = _get_index(index, links, self._allow_hosts)
self._requirements_and_constraints = []
if versions is not None:
self._versions = normalize_versions(versions)
def _version_conflict_information(self, name):
"""Return textual requirements/constraint information for debug purposes
We do a very simple textual search, as that filters out most
extraneous information witout missing anything.
"""
output = [
"Version and requirements information containing %s:" % name]
version_constraint = self._versions.get(name)
if version_constraint:
output.append(
"[versions] constraint on %s: %s" % (name, version_constraint))
output += [line for line in self._requirements_and_constraints
if name.lower() in line.lower()]
return '\n '.join(output)
def _satisfied(self, req, source=None):
dists = [dist for dist in self._env[req.project_name] if dist in req]
if not dists:
......@@ -608,14 +626,24 @@ class Installer:
def _constrain(self, requirement):
"""Return requirement with optional [versions] constraint added."""
constraint = self._versions.get(requirement.project_name.lower())
if constraint:
requirement = _constrained_requirement(constraint, requirement)
try:
requirement = _constrained_requirement(constraint,
requirement)
except IncompatibleConstraintError:
logger.info(self._version_conflict_information(
requirement.project_name.lower()))
raise
return requirement
def install(self, specs, working_set=None):
logger.debug('Installing %s.', repr(specs)[1:-1])
self._requirements_and_constraints.append(
"Base installation request: %s" % repr(specs)[1:-1])
for_buildout_run = bool(working_set)
path = self._path
......@@ -688,11 +716,17 @@ class Installer:
self._maybe_add_setuptools(ws, dist)
if dist not in req:
# Oops, the "best" so far conflicts with a dependency.
logger.info(self._version_conflict_information(req.key))
raise VersionConflict(
pkg_resources.VersionConflict(dist, req), ws)
best[req.key] = dist
requirements.extend(dist.requires(req.extras)[::-1])
extra_requirements = dist.requires(req.extras)[::-1]
for extra_requirement in extra_requirements:
self._requirements_and_constraints.append(
"Requirement of %s: %s" % (current_requirement, extra_requirement))
requirements.extend(extra_requirements)
processed[req] = True
return ws
......@@ -1505,7 +1539,9 @@ def _constrained_requirement(constraint, requirement):
assert constraint.startswith('==')
constraint = constraint[2:]
if constraint not in requirement:
bad_constraint(constraint, requirement)
msg = ("The requirement (%r) is not allowed by your [versions] "
"constraint (%s)" % (str(requirement), constraint))
raise IncompatibleConstraintError(msg)
# Sigh, copied from Requirement.__str__
extras = ','.join(requirement.extras)
......@@ -1528,8 +1564,3 @@ class IncompatibleConstraintError(zc.buildout.UserError):
"""
IncompatibleVersionError = IncompatibleConstraintError # Backward compatibility
def bad_constraint(constraint, requirement):
logger.error("The constraint, %s, is not consistent with the "
"requirement, %r.", constraint, str(requirement))
raise IncompatibleConstraintError("Bad constraint", constraint, requirement)
......@@ -242,13 +242,15 @@ we'll get an error:
... versions = dict(demo='0.2', demoneeded='1.0'))
Traceback (most recent call last):
...
IncompatibleConstraintError: Bad constraint 0.2 demo>0.2
IncompatibleConstraintError: The requirement ('demo>0.2') is not allowed by your [versions] constraint (0.2)
>>> print_(handler)
zc.buildout.easy_install DEBUG
Installing 'demo >0.2'.
zc.buildout.easy_install ERROR
The constraint, 0.2, is not consistent with the requirement, 'demo>0.2'.
zc.buildout.easy_install INFO
Version and requirements information containing demo:
[versions] constraint on demo: 0.2
Base installation request: 'demo >0.2'
>>> handler.clear()
......
......@@ -306,6 +306,9 @@ Now, let's create a buildout that requires y and z:
Installing eggs.
Getting distribution for 'demoneeded==1.1'.
Got demoneeded 1.1.
Version and requirements information containing demoneeded:
Requirement of samplez: demoneeded==1.1
Requirement of sampley: demoneeded==1.0
While:
Installing eggs.
Error: There is a version conflict.
......@@ -355,6 +358,9 @@ If we use the verbose switch, we can see where requirements are coming from:
Getting required 'sampley'
required by sampleb 1.
We have a develop egg: sampley 1
Version and requirements information containing demoneeded:
Requirement of samplez: demoneeded==1.1
Requirement of sampley: demoneeded==1.0
While:
Installing eggs.
Error: There is a version conflict.
......
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