Commit 1c195b36 by Sébastien Eustace Committed by GitHub

debug:resolve command improvements (#402)

* Add a —tree option to debug:resolve

* Add support for git dependencies in debug:resolve

* Add tests for debug:resolve
parent bc3b7344
...@@ -13,6 +13,7 @@ class DebugResolveCommand(Command): ...@@ -13,6 +13,7 @@ class DebugResolveCommand(Command):
{ package?* : packages to resolve. } { package?* : packages to resolve. }
{ --E|extras=* : Extras to activate for the dependency. } { --E|extras=* : Extras to activate for the dependency. }
{ --python= : Python version(s) to use for resolution. } { --python= : Python version(s) to use for resolution. }
{ --tree : Displays the dependency tree. }
""" """
_loggers = ["poetry.repositories.pypi_repository"] _loggers = ["poetry.repositories.pypi_repository"]
...@@ -29,16 +30,14 @@ class DebugResolveCommand(Command): ...@@ -29,16 +30,14 @@ class DebugResolveCommand(Command):
if not packages: if not packages:
package = self.poetry.package package = self.poetry.package
else: else:
requirements = self._determine_requirements(packages) package = ProjectPackage(
requirements = self._format_requirements(requirements) self.poetry.package.name, self.poetry.package.version
)
# validate requirements format requirements = self._format_requirements(packages)
for constraint in requirements.values():
parse_constraint(constraint)
dependencies = [] dependencies = []
for name, constraint in requirements.items(): for name, constraint in requirements.items():
dep = Dependency(name, constraint) dep = package.add_dependency(name, constraint)
extras = [] extras = []
for extra in self.option("extras"): for extra in self.option("extras"):
if " " in extra: if " " in extra:
...@@ -49,17 +48,9 @@ class DebugResolveCommand(Command): ...@@ -49,17 +48,9 @@ class DebugResolveCommand(Command):
for ex in extras: for ex in extras:
dep.extras.append(ex) dep.extras.append(ex)
dependencies.append(dep)
package = ProjectPackage(
self.poetry.package.name, self.poetry.package.version
)
package.python_versions = ( package.python_versions = (
self.option("python") or self.poetry.package.python_versions self.option("python") or self.poetry.package.python_versions
) )
for dep in dependencies:
package.requires.append(dep)
solver = Solver( solver = Solver(
package, self.poetry.pool, Repository(), Repository(), self.output package, self.poetry.pool, Repository(), Repository(), self.output
...@@ -71,6 +62,23 @@ class DebugResolveCommand(Command): ...@@ -71,6 +62,23 @@ class DebugResolveCommand(Command):
self.line("Resolution results:") self.line("Resolution results:")
self.line("") self.line("")
if self.option("tree"):
show_command = self.get_application().find("show")
show_command.output = self.output
show_command.init_styles()
packages = [op.package for op in ops]
repo = Repository(packages)
requires = package.requires + package.dev_requires
for pkg in repo.packages:
for require in requires:
if pkg.name == require.name:
show_command.display_package_tree(pkg, repo)
break
return 0
for op in ops: for op in ops:
package = op.package package = op.package
self.line( self.line(
...@@ -83,23 +91,37 @@ class DebugResolveCommand(Command): ...@@ -83,23 +91,37 @@ class DebugResolveCommand(Command):
self.line(" - {}: {}".format(req_name, req_value)) self.line(" - {}: {}".format(req_name, req_value))
def _determine_requirements(self, requires): # type: (List[str]) -> List[str] def _determine_requirements(self, requires): # type: (List[str]) -> List[str]
from poetry.semver import parse_constraint
if not requires: if not requires:
return [] return []
requires = self._parse_name_version_pairs(requires) requires = self._parse_name_version_pairs(requires)
result = [] result = []
for requirement in requires: for requirement in requires:
if "version" not in requirement: if "version" in requirement:
requirement["version"] = "*" parse_constraint(requirement["version"])
result.append("{} {}".format(requirement["name"], requirement["version"])) return requires
return result
def _parse_name_version_pairs(self, pairs): # type: (list) -> list def _parse_name_version_pairs(self, pairs): # type: (list) -> list
result = [] result = []
for i in range(len(pairs)): for i in range(len(pairs)):
if pairs[i].startswith("git+https://"):
url = pairs[i].lstrip("git+")
rev = None
if "@" in url:
url, rev = url.split("@")
pair = {"name": url.split("/")[-1].rstrip(".git"), "git": url}
if rev:
pair["rev"] = rev
result.append(pair)
continue
pair = re.sub("^([^=: ]+)[=: ](.*)$", "\\1 \\2", pairs[i].strip()) pair = re.sub("^([^=: ]+)[=: ](.*)$", "\\1 \\2", pairs[i].strip())
pair = pair.strip() pair = pair.strip()
...@@ -107,14 +129,16 @@ class DebugResolveCommand(Command): ...@@ -107,14 +129,16 @@ class DebugResolveCommand(Command):
name, version = pair.split(" ", 2) name, version = pair.split(" ", 2)
result.append({"name": name, "version": version}) result.append({"name": name, "version": version})
else: else:
result.append({"name": pair}) result.append({"name": pair, "version": "*"})
return result return result
def _format_requirements(self, requirements): # type: (List[str]) -> dict def _format_requirements(self, requirements): # type: (List[str]) -> dict
requires = {} requires = {}
requirements = self._parse_name_version_pairs(requirements) requirements = self._determine_requirements(requirements)
for requirement in requirements: for requirement in requirements:
requires[requirement["name"]] = requirement["version"] name = requirement.pop("name")
requires[name] = requirement
return requires return requires
...@@ -193,7 +193,11 @@ lists all packages available.""" ...@@ -193,7 +193,11 @@ lists all packages available."""
def display_package_tree(self, package, installed_repo): def display_package_tree(self, package, installed_repo):
self.write("<info>{}</info>".format(package.pretty_name)) self.write("<info>{}</info>".format(package.pretty_name))
self.line(" {} {}".format(package.pretty_version, package.description)) description = ""
if package.description:
description = " " + package.description
self.line(" {}{}".format(package.pretty_version, description))
dependencies = package.requires dependencies = package.requires
dependencies = sorted(dependencies, key=lambda x: x.name) dependencies = sorted(dependencies, key=lambda x: x.name)
......
import sys
from cleo.testers import CommandTester
from tests.helpers import get_dependency
from tests.helpers import get_package
def test_debug_resolve_gives_resolution_results(app, repo):
command = app.find("debug:resolve")
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute([("command", command.get_name()), ("package", ["cachy"])])
expected = """\
Resolving dependencies...
Resolution results:
- msgpack-python (0.5.3)
- cachy (0.2.0)
"""
assert tester.get_display(True) == expected
def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo):
command = app.find("debug:resolve")
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2)
repo.add_package(get_package("msgpack-python", "0.5.3"))
tester.execute(
[("command", command.get_name()), ("package", ["cachy"]), ("--tree", True)]
)
expected = """\
Resolving dependencies...
Resolution results:
cachy 0.2.0
`-- msgpack-python >=0.5 <0.6
"""
assert tester.get_display(True) == expected
def test_debug_resolve_git_dependency(app, repo):
repo.add_package(get_package("pendulum", "2.0.3"))
command = app.find("debug:resolve")
tester = CommandTester(command)
tester.execute(
[
("command", command.get_name()),
("package", ["git+https://github.com/demo/demo.git"]),
]
)
expected = """\
Resolving dependencies...
Resolution results:
- pendulum (2.0.3)
- demo (0.1.2)
"""
assert tester.get_display(True) == expected
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