Bugfixes for set resolution

Signed-off-by: Dan Ryan <dan@danryan.co>
This commit is contained in:
Dan Ryan
2018-12-05 18:28:00 -05:00
parent 83f5791bc8
commit df712cc6db
2 changed files with 40 additions and 20 deletions
+6 -6
View File
@@ -410,6 +410,7 @@ class Environment(object):
rdeps = {}
for req in self.get_package_requirements():
for d in self.reverse_dependency(req):
parents = None
name = d["package_name"]
pkg = {
name: {
@@ -417,15 +418,14 @@ class Environment(object):
"required": d["required_version"]
}
}
if d.get("parent"):
pkg[name]["parents"] = list(d["parent"])
parents = set(d.get("parent", []))
pkg[name]["parents"] = parents
if rdeps.get(name):
if rdeps[name].get("parents"):
rdeps[name]["parents"].append(pkg[name]["parents"])
else:
if not (rdeps[name].get("required") or rdeps[name].get("installed")):
rdeps[name].update(pkg[name])
rdeps[name]["parents"] = rdeps[name].get("parents", set()) | parents
else:
rdeps.update(pkg)
rdeps[name] = pkg[name]
for k in list(rdeps.keys()):
entry = rdeps[k]
if entry.get("parents"):
+34 -14
View File
@@ -139,7 +139,7 @@ class Entry(object):
def pipfile_packages(self):
return self.project.pipfile_package_names["dev" if self.dev else "default"]
def create_parent(self, name, specifier):
def create_parent(self, name, specifier="*"):
parent = self.create(name, specifier, self.project, self.resolver,
self.reverse_deps, self.dev)
parent._deptree = self.deptree
@@ -159,6 +159,8 @@ class Entry(object):
def clean_specifier(specifier):
from pipenv.vendor.packaging.specifiers import Specifier
if not any(specifier.startswith(k) for k in Specifier._operators.keys()):
if specifier.strip().lower() in ["any", "*"]:
return "*"
specifier = "=={0}".format(specifier)
elif specifier.startswith("==") and specifier.count("=") > 2:
specifier = "=={0}".format(specifier.lstrip("="))
@@ -234,14 +236,24 @@ class Entry(object):
), {})
def get_parent_deps(self, unnest=False):
from pipenv.vendor.packaging.specifiers import Specifier
parents = []
for k, v in self.reverse_deps.get(self.normalized_name, {}).get("parents", {}).items():
specifier = self.clean_specifier(v)
parent = self.create_parent(k, specifier)
parents.append(parent)
for spec in self.reverse_deps.get(self.normalized_name, {}).get("parents", set()):
spec_index = next(iter(c for c in Specifier._operators if c in spec), None)
name = spec
parent = None
if spec_index is not None:
specifier = self.clean_specifier(spec[spec_index:])
name = spec[:spec_index]
parent = self.create_parent(name, specifier)
else:
name = spec
parent = self.create_parent(name)
if parent is not None:
parents.append(parent)
if not unnest or parent.pipfile_name is not None:
continue
if self.reverse_deps.get(parent.normalized_name, {}).get("parents", {}):
if self.reverse_deps.get(parent.normalized_name, {}).get("parents", set()):
parents.extend(parent.flattened_parents)
return parents
@@ -261,22 +273,30 @@ class Entry(object):
def constraint_from_parent_conflicts(self):
# ensure that we satisfy the parent dependencies of this dep
from pipenv.vendor.packaging.specifiers import Specifier
parent_dependencies = set()
has_mismatch = False
for p in self.parent_deps:
if parent.is_updated:
if p.is_updated:
continue
if not p.requirements:
continue
needed = p.requirements.get("dependencies", [])
entry_ref = p.get_dependency(self.name)
required = entry_ref.get("required_version", "")
self.clean_specifier(required)
parent_requires = self.make_requirement(name, required)
required = entry_ref.get("required_version", "*")
required = self.clean_specifier(required)
parent_requires = self.make_requirement(self.name, required)
parent_dependencies.add("{0} => {1} ({2})".format(p.name, self.name, required))
if not parent_requires.requirement.specifier.contains(self.updated_version):
from pipenv.exceptions import DependencyConflict
msg = "Cannot resolve {0} due to conflicting parent dependency: {1}".format(
entry.name, parent.name
has_mismatch = True
if has_mismatch:
from pipenv.exceptions import DependencyConflict
msg = (
"Cannot resolve {0} ({1}) due to conflicting parent dependencies: "
"\n\t{2}".format(
self.name, self.updated_version, "\n\t".join(parent_dependencies)
)
raise DependencyConflict(msg)
)
raise DependencyConflict(msg)
return self.entry.as_ireq()
def validate_constraint(self):