Commit 5acf8fa6 by Sébastien Eustace Committed by GitHub

Merge pull request #2887 from python-poetry/fix-transitive-extras

Fix and improve handling of extras while resolving dependencies
parents b32051f1 55ebb9cd
......@@ -461,7 +461,7 @@ six = ">=1.0.0,<2.0.0"
[[package]]
name = "more-itertools"
version = "8.3.0"
version = "8.4.0"
description = "More routines for operating on iterables, beyond itertools"
category = "dev"
optional = false
......@@ -469,7 +469,7 @@ python-versions = ">=3.5"
[[package]]
name = "more-itertools"
version = "8.4.0"
version = "8.5.0"
description = "More routines for operating on iterables, beyond itertools"
category = "dev"
optional = false
......@@ -561,8 +561,8 @@ importlib-metadata = {version = ">=0.12", markers = "python_version < \"3.8\""}
[[package]]
name = "poetry-core"
version = "1.0.0a9"
description = "Core utilities for Poetry"
version = "1.0.0b1"
description = "Poetry PEP 517 Build Backend"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
......@@ -984,7 +984,7 @@ contextlib2 = {version = "*", markers = "python_version < \"3.4\""}
[metadata]
lock-version = "1.1"
python-versions = "~2.7 || ^3.5"
content-hash = "9528141e0eb24000c6f245065820732b3977d1c7d14c14fbcedf77e91c4a3e68"
content-hash = "062aef66c1c37dce14fcb2a66841afe97937ce9150136ff8dfa45e43d796821f"
[metadata.files]
appdirs = [
......@@ -1217,10 +1217,10 @@ more-itertools = [
{file = "more-itertools-5.0.0.tar.gz", hash = "sha256:38a936c0a6d98a38bcc2d03fdaaedaba9f412879461dd2ceff8d37564d6522e4"},
{file = "more_itertools-5.0.0-py2-none-any.whl", hash = "sha256:c0a5785b1109a6bd7fac76d6837fd1feca158e54e521ccd2ae8bfe393cc9d4fc"},
{file = "more_itertools-5.0.0-py3-none-any.whl", hash = "sha256:fe7a7cae1ccb57d33952113ff4fa1bc5f879963600ed74918f1236e212ee50b9"},
{file = "more-itertools-8.3.0.tar.gz", hash = "sha256:558bb897a2232f5e4f8e2399089e35aecb746e1f9191b6584a151647e89267be"},
{file = "more_itertools-8.3.0-py3-none-any.whl", hash = "sha256:7818f596b1e87be009031c7653d01acc46ed422e6656b394b0f765ce66ed4982"},
{file = "more-itertools-8.4.0.tar.gz", hash = "sha256:68c70cc7167bdf5c7c9d8f6954a7837089c6a36bf565383919bb595efb8a17e5"},
{file = "more_itertools-8.4.0-py3-none-any.whl", hash = "sha256:b78134b2063dd214000685165d81c154522c3ee0a1c0d4d113c80361c234c5a2"},
{file = "more-itertools-8.5.0.tar.gz", hash = "sha256:6f83822ae94818eae2612063a5101a7311e68ae8002005b5e05f03fd74a86a20"},
{file = "more_itertools-8.5.0-py3-none-any.whl", hash = "sha256:9b30f12df9393f0d28af9210ff8efe48d10c94f73e5daf886f10c4b0b0b4f03c"},
]
msgpack = [
{file = "msgpack-1.0.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:cec8bf10981ed70998d98431cd814db0ecf3384e6b113366e7f36af71a0fca08"},
......@@ -1270,8 +1270,8 @@ pluggy = [
{file = "pluggy-0.13.1.tar.gz", hash = "sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0"},
]
poetry-core = [
{file = "poetry-core-1.0.0a9.tar.gz", hash = "sha256:f08e9829fd06609ca5615faa91739b589eb71e025a6aaf7ddffb698676eb7c8c"},
{file = "poetry_core-1.0.0a9-py2.py3-none-any.whl", hash = "sha256:79a63629ae44533ba9aa828e0eff0002c61b3af5fc9bec212e006cc643f4eb19"},
{file = "poetry-core-1.0.0b1.tar.gz", hash = "sha256:c7a64770780f6a4998eee1e260fc3b7e22fa1c9b94b05c0faa13aa512f95eaa1"},
{file = "poetry_core-1.0.0b1-py2.py3-none-any.whl", hash = "sha256:92d2a33c27c733e746425c6506fdf583909e3ce5de4591deb23a4efb13f1a72c"},
]
pre-commit = [
{file = "pre_commit-2.6.0-py2.py3-none-any.whl", hash = "sha256:e8b1315c585052e729ab7e99dcca5698266bedce9067d21dc909c23e3ceed626"},
......@@ -1371,6 +1371,7 @@ six = [
]
subprocess32 = [
{file = "subprocess32-3.5.4-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:88e37c1aac5388df41cc8a8456bb49ebffd321a3ad4d70358e3518176de3a56b"},
{file = "subprocess32-3.5.4-cp27-cp27mu-manylinux2014_x86_64.whl", hash = "sha256:e45d985aef903c5b7444d34350b05da91a9e0ea015415ab45a21212786c649d0"},
{file = "subprocess32-3.5.4.tar.gz", hash = "sha256:eb2937c80497978d181efa1b839ec2d9622cf9600a039a79d0e108d1f9aec79d"},
]
termcolor = [
......
......@@ -29,6 +29,7 @@ class DebugResolveCommand(InitCommand):
def handle(self):
from poetry.core.packages.project_package import ProjectPackage
from poetry.factory import Factory
from poetry.io.null_io import NullIO
from poetry.puzzle import Solver
from poetry.repositories.pool import Pool
......@@ -59,7 +60,6 @@ class DebugResolveCommand(InitCommand):
for constraint in requirements:
name = constraint.pop("name")
dep = package.add_dependency(name, constraint)
extras = []
for extra in self.option("extras"):
if " " in extra:
......@@ -67,8 +67,9 @@ class DebugResolveCommand(InitCommand):
else:
extras.append(extra)
for ex in extras:
dep.extras.append(ex)
constraint["extras"] = extras
package.add_dependency(Factory.create_dependency(name, constraint))
package.python_versions = self.option("python") or (
self.poetry.package.python_versions
......@@ -122,7 +123,7 @@ class DebugResolveCommand(InitCommand):
pkg = op.package
row = [
"<c1>{}</c1>".format(pkg.name),
"<c1>{}</c1>".format(pkg.complete_name),
"<b>{}</b>".format(pkg.version),
"",
]
......
......@@ -388,7 +388,7 @@ The <c1>init</c1> command creates a basic <comment>pyproject.toml</> file in the
pair["extras"] = extras
package = Provider.get_package_from_vcs(
"git", url.url, reference=pair.get("rev")
"git", url.url, rev=pair.get("rev")
)
pair["name"] = package.name
result.append(pair)
......
......@@ -37,6 +37,7 @@ lists all packages available."""
from poetry.core.semver import Version
from poetry.repositories.installed_repository import InstalledRepository
from poetry.utils.helpers import get_package_version_display_string
package = self.argument("package")
......@@ -144,12 +145,31 @@ lists all packages available."""
if not self.option("outdated") or update_status != "up-to-date":
name_length = max(name_length, current_length)
version_length = max(
version_length, len(locked.full_pretty_version)
version_length,
len(
get_package_version_display_string(
locked, root=self.poetry.file.parent
)
),
)
latest_length = max(
latest_length,
len(
get_package_version_display_string(
latest, root=self.poetry.file.parent
)
),
)
latest_length = max(latest_length, len(latest.full_pretty_version))
else:
name_length = max(name_length, current_length)
version_length = max(version_length, len(locked.full_pretty_version))
version_length = max(
version_length,
len(
get_package_version_display_string(
locked, root=self.poetry.file.parent
)
),
)
write_version = name_length + version_length + 3 <= width
write_latest = name_length + version_length + latest_length + 3 <= width
......@@ -185,7 +205,10 @@ lists all packages available."""
)
if write_version:
line += " <b>{:{}}</b>".format(
locked.full_pretty_version, version_length
get_package_version_display_string(
locked, root=self.poetry.file.parent
),
version_length,
)
if show_latest:
latest = latest_packages[locked.pretty_name]
......@@ -199,7 +222,11 @@ lists all packages available."""
color = "yellow"
line += " <fg={}>{:{}}</>".format(
color, latest.full_pretty_version, latest_length
color,
get_package_version_display_string(
latest, root=self.poetry.file.parent
),
latest_length,
)
if write_description:
......
File mode changed from 100644 to 100755
......@@ -69,6 +69,9 @@ class PackageInfo:
self.requires_python = requires_python
self.files = files or []
self._cache_version = cache_version
self._source_type = None
self._source_url = None
self._source_reference = None
@property
def cache_version(self): # type: () -> Optional[str]
......@@ -136,7 +139,13 @@ class PackageInfo:
"Unable to retrieve the package version for {}".format(name)
)
package = Package(name=name, version=self.version)
package = Package(
name=name,
version=self.version,
source_type=self._source_type,
source_url=self._source_url,
source_reference=self._source_reference,
)
package.description = self.summary
package.root_dir = root_dir
package.python_versions = self.requires_python or "*"
......@@ -166,14 +175,9 @@ class PackageInfo:
# this is the first time we encounter this extra for this package
package.extras[extra] = []
# Activate extra dependencies if specified
if extras and extra in extras:
dependency.activate()
package.extras[extra].append(dependency)
if not dependency.is_optional() or dependency.is_activated():
# we skip add only if the dependency is option and was not activated as part of an extra
if dependency not in package.requires:
package.requires.append(dependency)
return package
......@@ -197,7 +201,7 @@ class PackageInfo:
with requires.open(encoding="utf-8") as f:
requirements = parse_requires(f.read())
return cls(
info = cls(
name=dist.name,
version=dist.version,
summary=dist.summary,
......@@ -206,6 +210,11 @@ class PackageInfo:
requires_python=dist.requires_python,
)
info._source_type = "file"
info._source_url = Path(dist.filename).resolve().as_posix()
return info
@classmethod
def _from_sdist_file(cls, path): # type: (Path) -> PackageInfo
"""
......@@ -501,23 +510,26 @@ class PackageInfo:
"""
project_package = cls._get_poetry_package(path)
if project_package:
return cls.from_package(project_package)
info = cls.from_package(project_package)
else:
info = cls.from_metadata(path)
info = cls.from_metadata(path)
if not info or info.requires_dist is None:
try:
if disable_build:
info = cls.from_setup_files(path)
else:
info = cls._pep517_metadata(path)
except PackageInfoError:
if not info:
raise
if info and info.requires_dist is not None:
# return only if requirements are discovered
return info
# we discovered PkgInfo but no requirements were listed
try:
if disable_build:
return cls.from_setup_files(path)
return cls._pep517_metadata(path)
except PackageInfoError as e:
if info:
# we discovered PkgInfo but no requirements were listed
return info
raise e
info._source_type = "directory"
info._source_url = path.as_posix()
return info
@classmethod
def from_sdist(cls, path): # type: (Path) -> PackageInfo
......
......@@ -556,7 +556,7 @@ class Executor(object):
git.checkout(package.source_reference, src_dir)
# Now we just need to install from the source directory
package.source_url = str(src_dir)
package._source_url = str(src_dir)
return self._install_directory(operation)
......@@ -599,7 +599,7 @@ class Executor(object):
def _download_archive(self, operation, link): # type: (Operation, Link) -> Path
response = self._authenticator.request(
"get", link.url, stream=True, io=self._sections.get(id(operation))
"get", link.url, stream=True, io=self._sections.get(id(operation), self._io)
)
wheel_size = response.headers.get("content-length")
operation_message = self.get_operation_message(operation)
......
......@@ -261,8 +261,8 @@ class PipInstaller(BaseInstaller):
# Now we just need to install from the source directory
pkg = Package(package.name, package.version)
pkg.source_type = "directory"
pkg.source_url = str(src_dir)
pkg._source_type = "directory"
pkg._source_url = str(src_dir)
pkg.develop = package.develop
self.install_directory(pkg)
......@@ -36,18 +36,18 @@ class Incompatibility:
# Short-circuit in the common case of a two-term incompatibility with
# two different packages (for example, a dependency).
or len(terms) == 2
and terms[0].dependency.name != terms[-1].dependency.name
and terms[0].dependency.complete_name != terms[-1].dependency.complete_name
):
pass
else:
# Coalesce multiple terms about the same package if possible.
by_name = {} # type: Dict[str, Dict[str, Term]]
for term in terms:
if term.dependency.name not in by_name:
by_name[term.dependency.name] = {}
if term.dependency.complete_name not in by_name:
by_name[term.dependency.complete_name] = {}
by_ref = by_name[term.dependency.name]
ref = term.dependency.name
by_ref = by_name[term.dependency.complete_name]
ref = term.dependency.complete_name
if ref in by_ref:
by_ref[ref] = by_ref[ref].intersect(term)
......@@ -432,7 +432,7 @@ class Incompatibility:
def _terse(self, term, allow_every=False):
if allow_every and term.constraint.is_any():
return "every version of {}".format(term.dependency.name)
return "every version of {}".format(term.dependency.complete_name)
return str(term.dependency)
......
......@@ -65,7 +65,7 @@ class PartialSolution:
return [
term.dependency
for term in self._positive.values()
if term.dependency.name not in self._decisions
if term.dependency.complete_name not in self._decisions
]
def decide(self, package): # type: (Package) -> None
......@@ -81,7 +81,7 @@ class PartialSolution:
self._attempted_solutions += 1
self._backtracking = False
self._decisions[package.name] = package
self._decisions[package.complete_name] = package
self._assign(
Assignment.decision(package, self.decision_level, len(self._assignments))
......@@ -120,9 +120,9 @@ class PartialSolution:
packages = set()
while self._assignments[-1].decision_level > decision_level:
removed = self._assignments.pop(-1)
packages.add(removed.dependency.name)
packages.add(removed.dependency.complete_name)
if removed.is_decision():
del self._decisions[removed.dependency.name]
del self._decisions[removed.dependency.complete_name]
# Re-compute _positive and _negative for the packages that were removed.
for package in packages:
......@@ -133,21 +133,21 @@ class PartialSolution:
del self._negative[package]
for assignment in self._assignments:
if assignment.dependency.name in packages:
if assignment.dependency.complete_name in packages:
self._register(assignment)
def _register(self, assignment): # type: (Assignment) -> None
"""
Registers an Assignment in _positive or _negative.
"""
name = assignment.dependency.name
name = assignment.dependency.complete_name
old_positive = self._positive.get(name)
if old_positive is not None:
self._positive[name] = old_positive.intersect(assignment)
return
ref = assignment.dependency.name
ref = assignment.dependency.complete_name
negative_by_ref = self._negative.get(name)
old_negative = None if negative_by_ref is None else negative_by_ref.get(ref)
if old_negative is None:
......@@ -174,12 +174,12 @@ class PartialSolution:
assigned_term = None # type: Term
for assignment in self._assignments:
if assignment.dependency.name != term.dependency.name:
if assignment.dependency.complete_name != term.dependency.complete_name:
continue
if (
not assignment.dependency.is_root
and not assignment.dependency.name == term.dependency.name
and not assignment.dependency.is_same_package_as(term.dependency)
):
if not assignment.is_positive():
continue
......@@ -203,15 +203,15 @@ class PartialSolution:
return self.relation(term) == SetRelation.SUBSET
def relation(self, term): # type: (Term) -> int
positive = self._positive.get(term.dependency.name)
positive = self._positive.get(term.dependency.complete_name)
if positive is not None:
return positive.relation(term)
by_ref = self._negative.get(term.dependency.name)
by_ref = self._negative.get(term.dependency.complete_name)
if by_ref is None:
return SetRelation.OVERLAPPING
negative = by_ref[term.dependency.name]
negative = by_ref[term.dependency.complete_name]
if negative is None:
return SetRelation.OVERLAPPING
......
......@@ -38,7 +38,7 @@ class Term(object):
Returns whether this term satisfies another.
"""
return (
self.dependency.name == other.dependency.name
self.dependency.complete_name == other.dependency.complete_name
and self.relation(other) == SetRelation.SUBSET
)
......@@ -47,9 +47,9 @@ class Term(object):
Returns the relationship between the package versions
allowed by this term and another.
"""
if self.dependency.name != other.dependency.name:
if self.dependency.complete_name != other.dependency.complete_name:
raise ValueError(
"{} should refer to {}".format(other, self.dependency.name)
"{} should refer to {}".format(other, self.dependency.complete_name)
)
other_constraint = other.constraint
......@@ -111,9 +111,9 @@ class Term(object):
Returns a Term that represents the packages
allowed by both this term and another
"""
if self.dependency.name != other.dependency.name:
if self.dependency.complete_name != other.dependency.complete_name:
raise ValueError(
"{} should refer to {}".format(other, self.dependency.name)
"{} should refer to {}".format(other, self.dependency.complete_name)
)
if self._compatible_dependency(other.dependency):
......@@ -151,17 +151,14 @@ class Term(object):
return (
self.dependency.is_root
or other.is_root
or other.name == self.dependency.name
or other.is_same_package_as(self.dependency)
)
def _non_empty_term(self, constraint, is_positive):
if constraint.is_empty():
return
dep = Dependency(self.dependency.name, constraint)
dep.python_versions = str(self.dependency.python_versions)
return Term(dep, is_positive)
return Term(self.dependency.with_constraint(constraint), is_positive)
def __str__(self):
return "{}{}".format("not " if not self.is_positive() else "", self._dependency)
......
......@@ -183,7 +183,7 @@ class VersionSolver:
unsatisfied.dependency, not unsatisfied.is_positive(), incompatibility
)
return unsatisfied.dependency.name
return unsatisfied.dependency.complete_name
def _resolve_conflict(
self, incompatibility
......@@ -371,7 +371,7 @@ class VersionSolver:
self._add_incompatibility(
Incompatibility([Term(dependency, True)], PackageNotFoundCause(e))
)
return dependency.name
return dependency.complete_name
try:
version = packages[0]
......@@ -387,7 +387,7 @@ class VersionSolver:
Incompatibility([Term(dependency, True)], NoVersionsCause())
)
return dependency.name
return dependency.complete_name
version = self._provider.complete_package(version)
......@@ -402,7 +402,7 @@ class VersionSolver:
# unit propagation which will guide us to choose a better version.
conflict = conflict or all(
[
term.dependency.name == dependency.name
term.dependency.complete_name == dependency.complete_name
or self._solution.satisfies(term)
for term in incompatibility.terms
]
......@@ -411,10 +411,12 @@ class VersionSolver:
if not conflict:
self._solution.decide(version)
self._log(
"selecting {} ({})".format(version.name, version.full_pretty_version)
"selecting {} ({})".format(
version.complete_name, version.full_pretty_version
)
)
return dependency.name
return dependency.complete_name
def _excludes_single_version(self, constraint): # type: (Any) -> bool
return isinstance(VersionRange().difference(constraint), Version)
......@@ -435,31 +437,29 @@ class VersionSolver:
self._log("fact: {}".format(incompatibility))
for term in incompatibility.terms:
if term.dependency.name not in self._incompatibilities:
self._incompatibilities[term.dependency.name] = []
if term.dependency.complete_name not in self._incompatibilities:
self._incompatibilities[term.dependency.complete_name] = []
if incompatibility in self._incompatibilities[term.dependency.name]:
if (
incompatibility
in self._incompatibilities[term.dependency.complete_name]
):
continue
self._incompatibilities[term.dependency.name].append(incompatibility)
self._incompatibilities[term.dependency.complete_name].append(
incompatibility
)
def _get_locked(self, dependency): # type: (Dependency) -> Union[Package, None]
if dependency.name in self._use_latest:
if dependency.complete_name in self._use_latest:
return
locked = self._locked.get(dependency.name)
locked = self._locked.get(dependency.complete_name)
if not locked:
return
if dependency.extras:
locked.requires_extras = dependency.extras
if not dependency.transitive_marker.without_extras().is_any():
marker_intersection = dependency.transitive_marker.without_extras().intersect(
locked.dependency.marker.without_extras()
)
if not marker_intersection.is_empty():
locked.dependency.transitive_marker = marker_intersection
if not dependency.is_same_package_as(locked):
return
return locked
......
from typing import List
from poetry.core.packages.dependency import Dependency
from poetry.core.packages.package import Package
class DependencyPackage(object):
def __init__(self, dependency, package):
def __init__(self, dependency, package): # type: (Dependency, Package) -> None
self._dependency = dependency
self._package = package
@property
def dependency(self):
def dependency(self): # type: () -> Dependency
return self._dependency
@property
def package(self):
def package(self): # type: () -> Package
return self._package
def clone(self): # type: () -> DependencyPackage
return self.__class__(self._dependency, self._package.clone())
def with_features(self, features): # type: (List[str]) -> "DependencyPackage"
return self.__class__(self._dependency, self._package.with_features(features))
def without_features(self): # type: () -> "DependencyPackage"
return self.with_features([])
def __getattr__(self, name):
return getattr(self._package, name)
......
import json
import logging
import os
import re
from hashlib import sha256
from typing import List
from tomlkit import array
from tomlkit import document
from tomlkit import inline_table
from tomlkit import item
......@@ -18,6 +20,7 @@ from poetry.core.packages.package import Package
from poetry.core.semver import parse_constraint
from poetry.core.semver.version import Version
from poetry.core.version.markers import parse_marker
from poetry.utils._compat import OrderedDict
from poetry.utils._compat import Path
from poetry.utils.toml_file import TomlFile
......@@ -75,6 +78,8 @@ class Locker(object):
"""
Searches and returns a repository of locked packages.
"""
from poetry.factory import Factory
if not self.is_locked():
return poetry.repositories.Repository()
......@@ -92,7 +97,21 @@ class Locker(object):
return packages
for info in locked_packages:
package = Package(info["name"], info["version"], info["version"])
source = info.get("source", {})
source_type = source.get("type")
url = source.get("url")
if source_type in ["directory", "file"]:
url = self._lock.path.parent.joinpath(url).resolve().as_posix()
package = Package(
info["name"],
info["version"],
info["version"],
source_type=source_type,
source_url=url,
source_reference=source.get("reference"),
source_resolved_reference=source.get("resolved_reference"),
)
package.description = info.get("description", "")
package.category = info["category"]
package.optional = info["optional"]
......@@ -137,20 +156,23 @@ class Locker(object):
for dep_name, constraint in info.get("dependencies", {}).items():
if isinstance(constraint, list):
for c in constraint:
package.add_dependency(dep_name, c)
package.add_dependency(
Factory.create_dependency(
dep_name, c, root_dir=self._lock.path.parent
)
)
continue
package.add_dependency(dep_name, constraint)
package.add_dependency(
Factory.create_dependency(
dep_name, constraint, root_dir=self._lock.path.parent
)
)
if "develop" in info:
package.develop = info["develop"]
if "source" in info:
package.source_type = info["source"].get("type", "")
package.source_url = info["source"]["url"]
package.source_reference = info["source"]["reference"]
packages.add_package(package)
return packages
......@@ -181,15 +203,17 @@ class Locker(object):
if root.extras:
lock["extras"] = {
extra: [dep.pretty_name for dep in deps]
for extra, deps in root.extras.items()
for extra, deps in sorted(root.extras.items())
}
lock["metadata"] = {
"lock-version": self._VERSION,
"python-versions": root.python_versions,
"content-hash": self._content_hash,
"files": files,
}
lock["metadata"] = OrderedDict(
[
("lock-version", self._VERSION),
("python-versions", root.python_versions),
("content-hash", self._content_hash),
("files", files),
]
)
if not self.is_locked() or lock != self.lock_data:
self._write_lock_data(lock)
......@@ -270,9 +294,6 @@ class Locker(object):
def _dump_package(self, package): # type: (Package) -> dict
dependencies = {}
for dependency in sorted(package.requires, key=lambda d: d.name):
if dependency.is_optional() and not dependency.is_activated():
continue
if dependency.pretty_name not in dependencies:
dependencies[dependency.pretty_name] = []
......@@ -298,15 +319,27 @@ class Locker(object):
constraint["version"] for constraint in constraints
]
data = {
"name": package.pretty_name,
"version": package.pretty_version,
"description": package.description or "",
"category": package.category,
"optional": package.optional,
"python-versions": package.python_versions,
"files": sorted(package.files, key=lambda x: x["file"]),
}
data = OrderedDict(
[
("name", package.pretty_name),
("version", package.pretty_version),
("description", package.description or ""),
("category", package.category),
("optional", package.optional),
("python-versions", package.python_versions),
("files", sorted(package.files, key=lambda x: x["file"])),
]
)
if dependencies:
data["dependencies"] = table()
for k, constraints in dependencies.items():
if len(constraints) == 1:
data["dependencies"][k] = constraints[0]
else:
data["dependencies"][k] = array().multiline(True)
for constraint in constraints:
data["dependencies"][k].append(constraint)
if package.extras:
extras = {}
......@@ -318,20 +351,29 @@ class Locker(object):
data["extras"] = extras
if dependencies:
for k, constraints in dependencies.items():
if len(constraints) == 1:
dependencies[k] = constraints[0]
if package.source_url:
url = package.source_url
if package.source_type in ["file", "directory"]:
# The lock file should only store paths relative to the root project
url = Path(
os.path.relpath(
Path(url).as_posix(), self._lock.path.parent.as_posix()
)
).as_posix()
data["dependencies"] = dependencies
data["source"] = OrderedDict()
if package.source_url:
data["source"] = {
"url": package.source_url,
"reference": package.source_reference,
}
if package.source_type:
data["source"]["type"] = package.source_type
data["source"]["url"] = url
if package.source_reference:
data["source"]["reference"] = package.source_reference
if package.source_resolved_reference:
data["source"]["resolved_reference"] = package.source_resolved_reference
if package.source_type == "directory":
data["develop"] = package.develop
......
......@@ -14,7 +14,9 @@ class PackageCollection(list):
self.append(package)
def append(self, package):
if not isinstance(package, DependencyPackage):
package = DependencyPackage(self._dependency, package)
if isinstance(package, DependencyPackage):
package = package.package
package = DependencyPackage(self._dependency, package)
return super(PackageCollection, self).append(package)
......@@ -103,7 +103,7 @@ class Provider:
for constraint in self._search_for.keys():
if (
constraint.name == dependency.name
constraint.is_same_package_as(dependency)
and constraint.constraint.intersect(dependency.constraint)
== dependency.constraint
):
......@@ -132,15 +132,7 @@ class Provider:
elif dependency.is_url():
packages = self.search_for_url(dependency)
else:
constraint = dependency.constraint
packages = self._pool.find_packages(
dependency.name,
constraint,
extras=dependency.extras,
allow_prereleases=dependency.allows_prereleases(),
repository=dependency.source_name,
)
packages = self._pool.find_packages(dependency)
packages.sort(
key=lambda p: (
......@@ -167,17 +159,12 @@ class Provider:
package = self.get_package_from_vcs(
dependency.vcs,
dependency.source,
dependency.reference,
branch=dependency.branch,
tag=dependency.tag,
rev=dependency.rev,
name=dependency.name,
)
for extra in dependency.extras:
if extra in package.extras:
for dep in package.extras[extra]:
dep.activate()
package.requires += package.extras[extra]
dependency._constraint = package.version
dependency._pretty_constraint = package.version.text
......@@ -187,7 +174,7 @@ class Provider:
@classmethod
def get_package_from_vcs(
cls, vcs, url, reference=None, name=None
cls, vcs, url, branch=None, tag=None, rev=None, name=None
): # type: (str, str, Optional[str], Optional[str]) -> Package
if vcs != "git":
raise ValueError("Unsupported VCS dependency {}".format(vcs))
......@@ -199,6 +186,7 @@ class Provider:
try:
git = Git()
git.clone(url, tmp_dir)
reference = branch or tag or rev
if reference is not None:
git.checkout(reference, tmp_dir)
else:
......@@ -207,10 +195,10 @@ class Provider:
revision = git.rev_parse(reference, tmp_dir).strip()
package = cls.get_package_from_directory(tmp_dir, name=name)
package.source_type = "git"
package.source_url = url
package.source_reference = revision
package._source_type = "git"
package._source_url = url
package._source_reference = reference
package._source_resolved_reference = revision
except Exception:
raise
finally:
......@@ -242,18 +230,10 @@ class Provider:
if dependency.base is not None:
package.root_dir = dependency.base
package.source_url = dependency.path.as_posix()
package.files = [
{"file": dependency.path.name, "hash": "sha256:" + dependency.hash()}
]
for extra in dependency.extras:
if extra in package.extras:
for dep in package.extras[extra]:
dep.activate()
package.requires += package.extras[extra]
return [package]
@classmethod
......@@ -267,9 +247,6 @@ class Provider:
"Unable to determine package info from path: {}".format(file_path)
)
package.source_type = "file"
package.source_url = file_path.as_posix()
return package
def search_for_directory(
......@@ -289,19 +266,11 @@ class Provider:
self._deferred_cache[dependency] = (dependency, package)
package.source_url = dependency.path.as_posix()
package.develop = dependency.develop
if dependency.base is not None:
package.root_dir = dependency.base
for extra in dependency.extras:
if extra in package.extras:
for dep in package.extras[extra]:
dep.activate()
package.requires += package.extras[extra]
return [package]
@classmethod
......@@ -320,9 +289,6 @@ class Provider:
)
)
package.source_type = "directory"
package.source_url = directory.as_posix()
return package
def search_for_url(self, dependency): # type: (URLDependency) -> List[Package]
......@@ -362,8 +328,8 @@ class Provider:
package = cls.get_package_from_file(temp_dir / file_name)
package.source_type = "url"
package.source_url = url
package._source_type = "url"
package._source_url = url
return package
......@@ -447,6 +413,7 @@ class Provider:
def complete_package(
self, package
): # type: (DependencyPackage) -> DependencyPackage
if package.is_root():
package = package.clone()
requires = package.all_requires
......@@ -461,7 +428,7 @@ class Provider:
self._pool.package(
package.name,
package.version.text,
extras=package.requires_extras,
extras=package.dependency.extras,
repository=package.dependency.source_name,
),
)
......@@ -480,13 +447,44 @@ class Provider:
elif r.is_url():
self.search_for_url(r)
_dependencies = [
r
for r in requires
if self._python_constraint.allows_any(r.python_constraint)
and r.name not in self.UNSAFE_PACKAGES
and (not self._env or r.marker.validate(self._env.marker_env))
]
optional_dependencies = []
activated_extras = []
for extra in package.dependency.extras:
if extra not in package.extras:
continue
activated_extras.append(extra)
optional_dependencies += [d.name for d in package.extras[extra]]
_dependencies = []
# If some extras/features were required, we need to
# add a special dependency representing the base package
# to the current package
if package.dependency.extras:
if activated_extras:
package = package.with_features(activated_extras)
_dependencies.append(package.without_features().to_dependency())
for dep in requires:
if not self._python_constraint.allows_any(dep.python_constraint):
continue
if dep.name in self.UNSAFE_PACKAGES:
continue
if self._env and not dep.marker.validate(self._env.marker_env):
continue
if (
dep.is_optional()
and dep.name not in optional_dependencies
and not package.is_root()
):
continue
_dependencies.append(dep)
overrides = self._overrides.get(package, {})
dependencies = []
......@@ -683,18 +681,6 @@ class Provider:
continue
dep.transitive_python_versions = str(python_constraint_intersection)
if (package.dependency.is_directory() or package.dependency.is_file()) and (
dep.is_directory() or dep.is_file()
):
relative_path = Path(
os.path.relpath(
dep.full_path.as_posix(), package.root_dir.as_posix()
)
)
# TODO: Improve the way we set the correct relative path for dependencies
dep._path = relative_path
clean_dependencies.append(dep)
package.requires = clean_dependencies
......
......@@ -34,7 +34,7 @@ class Solver:
installed, # type: Repository
locked, # type: Repository
io, # type: ConsoleIO
remove_untracked=False, # type: bool,
remove_untracked=False, # type: bool
provider=None, # type: Optional[Provider]
):
self._package = package
......@@ -100,18 +100,37 @@ class Solver:
and locked.source_type == pkg.source_type
and locked_source_url == pkg_source_url
and locked.source_reference == pkg.source_reference
and locked.source_resolved_reference
== pkg.source_resolved_reference
):
pkg = Package(pkg.name, locked.version)
pkg.source_type = "git"
pkg.source_url = locked.source_url
pkg.source_reference = locked.source_reference
pkg = Package(
pkg.name,
locked.version,
source_type="git",
source_url=locked.source_url,
source_reference=locked.source_reference,
source_resolved_reference=locked.source_resolved_reference,
)
break
if pkg_source_url != package_source_url or (
pkg.source_reference != package.source_reference
(
not pkg.source_resolved_reference
or not package.source_resolved_reference
)
and pkg.source_reference != package.source_reference
and not pkg.source_reference.startswith(
package.source_reference
)
or (
pkg.source_resolved_reference
and package.source_resolved_reference
and pkg.source_resolved_reference
!= package.source_resolved_reference
and not pkg.source_resolved_reference.startswith(
package.source_resolved_reference
)
)
):
operations.append(Update(pkg, package, priority=depths[i]))
else:
......@@ -226,17 +245,39 @@ class Solver:
PackageNode(self._package, packages), aggregate_package_nodes
)
)
# Return the packages in their original order with associated depths
final_packages = packages
depths = [results[package] for package in packages]
# Merging feature packages with base packages
final_packages = []
depths = []
for package in packages:
if package.features:
for _package in packages:
if (
_package.name == package.name
and not _package.is_same_package_as(package)
and _package.version == package.version
):
for dep in package.requires:
if dep.is_same_package_as(_package):
continue
if dep not in _package.requires:
_package.requires.append(dep)
continue
final_packages.append(package)
depths.append(results[package])
# Return the packages in their original order with associated depths
return final_packages, depths
class DFSNode(object):
def __init__(self, id, name):
def __init__(self, id, name, base_name):
self.id = id
self.name = name
self.base_name = base_name
def reachable(self):
return []
......@@ -302,13 +343,7 @@ def dfs_visit(node, back_edges, visited, sorted_nodes):
class PackageNode(DFSNode):
def __init__(
self,
package,
packages,
previous=None,
previous_dep=None,
dep=None,
is_activated=True,
self, package, packages, previous=None, previous_dep=None, dep=None,
):
self.package = package
self.packages = packages
......@@ -323,11 +358,12 @@ class PackageNode(DFSNode):
self.optional = True
else:
self.category = dep.category
self.optional = dep.is_optional() and not dep.is_activated()
if not is_activated:
self.optional = True
self.optional = dep.is_optional()
super(PackageNode, self).__init__(
(package.name, self.category, self.optional), package.name
(package.complete_name, self.category, self.optional),
package.complete_name,
package.name,
)
def reachable(self):
......@@ -341,29 +377,7 @@ class PackageNode(DFSNode):
return []
for dependency in self.package.all_requires:
is_activated = True
if dependency.is_optional():
if not self.package.is_root() and (
not self.previous_dep or not self.previous_dep.extras
):
continue
is_activated = False
for group, extra_deps in self.package.extras.items():
if self.dep:
extras = self.previous_dep.extras
elif self.package.is_root():
extras = self.package.extras
else:
extras = []
if group in extras and dependency.name in (
d.name for d in self.package.extras[group]
):
is_activated = True
break
if self.previous and self.previous.package.name == dependency.name:
if self.previous and self.previous.name == dependency.name:
# We have a circular dependency.
# Since the dependencies are resolved we can
# simply skip it because we already have it
......@@ -372,8 +386,9 @@ class PackageNode(DFSNode):
continue
for pkg in self.packages:
if pkg.name == dependency.name and dependency.constraint.allows(
pkg.version
if (
pkg.complete_name == dependency.complete_name
and dependency.constraint.allows(pkg.version)
):
# If there is already a child with this name
# we merge the requirements
......@@ -383,6 +398,7 @@ class PackageNode(DFSNode):
for child in children
):
continue
children.append(
PackageNode(
pkg,
......@@ -390,15 +406,21 @@ class PackageNode(DFSNode):
self,
dependency,
self.dep or dependency,
is_activated=is_activated,
)
)
return children
def visit(self, parents):
# The root package, which has no parents, is defined as having depth -1
# So that the root package's top-level dependencies have depth 0.
self.depth = 1 + max([parent.depth for parent in parents] + [-2])
self.depth = 1 + max(
[
parent.depth if parent.base_name != self.base_name else parent.depth - 1
for parent in parents
]
+ [-2]
)
def aggregate_package_nodes(nodes, children):
......
......@@ -12,9 +12,7 @@ class BaseRepository(object):
def package(self, name, version, extras=None):
raise NotImplementedError()
def find_packages(
self, name, constraint=None, extras=None, allow_prereleases=False
):
def find_packages(self, dependency):
raise NotImplementedError()
def search(self, query):
......
......@@ -76,9 +76,9 @@ class InstalledRepository(Repository):
revision = git.rev_parse("HEAD", src).strip()
url = git.remote_url(src)
package.source_type = "git"
package.source_url = url
package.source_reference = revision
package._source_type = "git"
package._source_url = url
package._source_reference = revision
@classmethod
def set_package_vcs_properties(cls, package, env): # type: (Package, Env) -> None
......@@ -144,15 +144,15 @@ class InstalledRepository(Repository):
break
else:
# TODO: handle multiple source directories?
package.source_type = "directory"
package.source_url = paths.pop().as_posix()
package._source_type = "directory"
package._source_url = paths.pop().as_posix()
continue
if cls.is_vcs_package(path, env):
cls.set_package_vcs_properties(package, env)
else:
# If not, it's a path dependency
package.source_type = "directory"
package.source_url = str(path.parent)
package._source_type = "directory"
package._source_url = str(path.parent)
return repo
......@@ -222,17 +222,17 @@ class LegacyRepository(PyPiRepository):
path=parsed.path,
)
def find_packages(
self, name, constraint=None, extras=None, allow_prereleases=False
):
def find_packages(self, dependency):
packages = []
constraint = dependency.constraint
if constraint is None:
constraint = "*"
if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint)
allow_prereleases = dependency.allows_prereleases()
if isinstance(constraint, VersionRange):
if (
constraint.max is not None
......@@ -242,7 +242,7 @@ class LegacyRepository(PyPiRepository):
):
allow_prereleases = True
key = name
key = dependency.name
if not constraint.is_any():
key = "{}:{}".format(key, str(constraint))
......@@ -251,7 +251,7 @@ class LegacyRepository(PyPiRepository):
if self._cache.store("matches").has(key):
versions = self._cache.store("matches").get(key)
else:
page = self._get("/{}/".format(canonicalize_name(name).replace(".", "-")))
page = self._get("/{}/".format(dependency.name.replace(".", "-")))
if page is None:
return []
......@@ -270,19 +270,19 @@ class LegacyRepository(PyPiRepository):
for package_versions in (versions, ignored_pre_release_versions):
for version in package_versions:
package = Package(name, version)
package.source_type = "legacy"
package.source_reference = self.name
package.source_url = self._url
if extras is not None:
package.requires_extras = extras
package = Package(
dependency.name,
version,
source_type="legacy",
source_reference=self.name,
source_url=self._url,
)
packages.append(package)
self._log(
"{} packages found for {} {}".format(
len(packages), name, str(constraint)
len(packages), dependency.name, str(constraint)
),
level="debug",
)
......@@ -302,7 +302,7 @@ class LegacyRepository(PyPiRepository):
We also need to download every file matching this release
to get the various hashes.
Note that, this will be cached so the subsequent operations
Note that this will be cached so the subsequent operations
should be much faster.
"""
try:
......@@ -311,9 +311,9 @@ class LegacyRepository(PyPiRepository):
return self._packages[index]
except ValueError:
package = super(LegacyRepository, self).package(name, version, extras)
package.source_type = "legacy"
package.source_url = self._url
package.source_reference = self.name
package._source_type = "legacy"
package._source_url = self._url
package._source_reference = self.name
return package
......
......@@ -144,13 +144,9 @@ class Pool(BaseRepository):
raise PackageNotFound("Package {} ({}) not found.".format(name, version))
def find_packages(
self,
name,
constraint=None,
extras=None,
allow_prereleases=False,
repository=None,
self, dependency,
):
repository = dependency.source_name
if repository is not None:
repository = repository.lower()
......@@ -162,15 +158,11 @@ class Pool(BaseRepository):
raise ValueError('Repository "{}" does not exist.'.format(repository))
if repository is not None and not self._ignore_repository_names:
return self.repository(repository).find_packages(
name, constraint, extras=extras, allow_prereleases=allow_prereleases
)
return self.repository(repository).find_packages(dependency)
packages = []
for idx, repo in enumerate(self._repositories):
packages += repo.find_packages(
name, constraint, extras=extras, allow_prereleases=allow_prereleases
)
for repo in self._repositories:
packages += repo.find_packages(dependency)
return packages
......
......@@ -14,6 +14,7 @@ from cachecontrol.controller import logger as cache_control_logger
from cachy import CacheManager
from html5lib.html5parser import parse
from poetry.core.packages import Dependency
from poetry.core.packages import Package
from poetry.core.packages import dependency_from_pep_508
from poetry.core.packages.utils.link import Link
......@@ -79,22 +80,18 @@ class PyPiRepository(RemoteRepository):
def session(self):
return self._session
def find_packages(
self,
name, # type: str
constraint=None, # type: Union[VersionConstraint, str, None]
extras=None, # type: Union[list, None]
allow_prereleases=False, # type: bool
): # type: (...) -> List[Package]
def find_packages(self, dependency): # type: (Dependency) -> List[Package]
"""
Find packages on the remote server.
"""
constraint = dependency.constraint
if constraint is None:
constraint = "*"
if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint)
allow_prereleases = dependency.allows_prereleases()
if isinstance(constraint, VersionRange):
if (
constraint.max is not None
......@@ -105,10 +102,10 @@ class PyPiRepository(RemoteRepository):
allow_prereleases = True
try:
info = self.get_package_info(name)
info = self.get_package_info(dependency.name)
except PackageNotFound:
self._log(
"No packages found for {} {}".format(name, str(constraint)),
"No packages found for {} {}".format(dependency.name, str(constraint)),
level="debug",
)
return []
......@@ -121,7 +118,7 @@ class PyPiRepository(RemoteRepository):
# Bad release
self._log(
"No release information found for {}-{}, skipping".format(
name, version
dependency.name, version
),
level="debug",
)
......@@ -132,7 +129,7 @@ class PyPiRepository(RemoteRepository):
except ParseVersionError:
self._log(
'Unable to parse version "{}" for the {} package, skipping'.format(
version, name
version, dependency.name
),
level="debug",
)
......@@ -145,13 +142,12 @@ class PyPiRepository(RemoteRepository):
continue
if not constraint or (constraint and constraint.allows(package.version)):
if extras is not None:
package.requires_extras = extras
packages.append(package)
self._log(
"{} packages found for {} {}".format(len(packages), name, str(constraint)),
"{} packages found for {} {}".format(
len(packages), dependency.name, str(constraint)
),
level="debug",
)
......
......@@ -29,32 +29,22 @@ class Repository(BaseRepository):
for package in self.packages:
if name == package.name and package.version.text == version:
# Activate extra dependencies
for extra in extras:
if extra in package.extras:
for extra_dep in package.extras[extra]:
for dep in package.requires:
if dep.name == extra_dep.name:
dep.activate()
return package.clone()
def find_packages(
self, name, constraint=None, extras=None, allow_prereleases=False
):
name = name.lower()
package = package.with_features(extras)
return package
def find_packages(self, dependency):
constraint = dependency.constraint
packages = []
ignored_pre_release_packages = []
if extras is None:
extras = []
if constraint is None:
constraint = "*"
if not isinstance(constraint, VersionConstraint):
constraint = parse_constraint(constraint)
allow_prereleases = dependency.allows_prereleases
if isinstance(constraint, VersionRange):
if (
constraint.max is not None
......@@ -65,7 +55,7 @@ class Repository(BaseRepository):
allow_prereleases = True
for package in self.packages:
if name == package.name:
if dependency.name == package.name:
if (
package.is_prerelease()
and not allow_prereleases
......@@ -79,19 +69,6 @@ class Repository(BaseRepository):
continue
if constraint.allows(package.version):
for dep in package.requires:
for extra in extras:
if extra not in package.extras:
continue
reqs = package.extras[extra]
for req in reqs:
if req.name == dep.name:
dep.activate()
if extras:
package.requires_extras = extras
packages.append(package)
return packages or ignored_pre_release_packages
......
import os
from typing import Union
from clikit.api.io import IO
......@@ -84,18 +86,35 @@ class Exporter(object):
package.source_url, package.source_reference, package.name
)
elif package.source_type in ["directory", "file", "url"]:
url = package.source_url
if package.source_type == "file":
dependency = FileDependency(package.name, Path(package.source_url))
dependency = FileDependency(
package.name,
Path(package.source_url),
base=self._poetry.locker.lock.path.parent,
)
url = Path(
os.path.relpath(
url, self._poetry.locker.lock.path.parent.as_posix()
)
).as_posix()
elif package.source_type == "directory":
dependency = DirectoryDependency(
package.name, Path(package.source_url)
package.name,
Path(package.source_url),
base=self._poetry.locker.lock.path.parent,
)
url = Path(
os.path.relpath(
url, self._poetry.locker.lock.path.parent.as_posix()
)
).as_posix()
else:
dependency = URLDependency(package.name, package.source_url)
dependency.marker = package.marker
line = "{}".format(package.source_url)
line = "{}".format(url)
if package.develop and package.source_type == "directory":
line = "-e " + line
else:
......
......@@ -10,6 +10,7 @@ from typing import Optional
import requests
from poetry.config.config import Config
from poetry.core.packages.package import Package
from poetry.core.version import Version
from poetry.utils._compat import Path
......@@ -100,3 +101,15 @@ def download_file(
for chunk in response.iter_content(chunk_size=chunk_size):
if chunk:
f.write(chunk)
def get_package_version_display_string(
package, root=None
): # type: (Package, Optional[Path]) -> str
if package.source_type in ["file", "directory"] and root:
return "{} {}".format(
package.version,
Path(os.path.relpath(package.source_url, root.as_posix())).as_posix(),
)
return package.full_pretty_version
from typing import Union
from poetry.core.packages import Dependency
from poetry.core.packages import Package
from poetry.core.semver import Version
from poetry.core.semver import parse_constraint
class VersionSelector(object):
......@@ -21,27 +19,27 @@ class VersionSelector(object):
Given a package name and optional version,
returns the latest Package that matches
"""
if target_package_version:
constraint = parse_constraint(target_package_version)
else:
constraint = parse_constraint("*")
candidates = self._pool.find_packages(
package_name, constraint, allow_prereleases=True, repository=source
from poetry.factory import Factory
dependency = Factory.create_dependency(
package_name,
{
"version": target_package_version or "*",
"allow_prereleases": allow_prereleases,
"source": source,
},
)
candidates = self._pool.find_packages(dependency)
only_prereleases = all([c.version.is_prerelease() for c in candidates])
if not candidates:
return False
dependency = Dependency(package_name, constraint)
package = None
for candidate in candidates:
if (
candidate.is_prerelease()
and not dependency.allows_prereleases()
and not allow_prereleases
and not only_prereleases
):
continue
......
......@@ -24,7 +24,7 @@ classifiers = [
[tool.poetry.dependencies]
python = "~2.7 || ^3.5"
poetry-core = "^1.0.0a9"
poetry-core = "^1.0.0b1"
cleo = "^0.8.1"
clikit = "^0.6.2"
crashtest = { version = "^0.3.0", python = "^3.6" }
......
from cleo.testers import CommandTester
from poetry.factory import Factory
from tests.helpers import get_package
......@@ -8,7 +9,7 @@ def test_debug_resolve_gives_resolution_results(app, repo):
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
cachy2.add_dependency(Factory.create_dependency("msgpack-python", ">=0.5 <0.6"))
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2)
......@@ -33,7 +34,7 @@ def test_debug_resolve_tree_option_gives_the_dependency_tree(app, repo):
tester = CommandTester(command)
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
cachy2.add_dependency(Factory.create_dependency("msgpack-python", ">=0.5 <0.6"))
repo.add_package(get_package("cachy", "0.1.0"))
repo.add_package(cachy2)
......
......@@ -300,12 +300,13 @@ Package operations: 2 installs, 0 updates, 0 removals
def test_add_directory_constraint(app, repo, tester, mocker):
p = mocker.patch("poetry.utils._compat.Path.cwd")
p.return_value = Path(__file__) / ".."
p.return_value = Path(__file__).parent
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))
tester.execute("../git/github.com/demo/demo")
path = "../git/github.com/demo/demo"
tester.execute("{}".format(path))
expected = """\
......@@ -317,8 +318,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4)
• Installing demo (0.1.2 ../git/github.com/demo/demo)
"""
• Installing demo (0.1.2 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == tester.io.fetch_output()
assert 2 == tester._command.installer.executor.installations_count
......@@ -335,7 +338,8 @@ def test_add_directory_with_poetry(app, repo, tester, mocker):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute("../git/github.com/demo/pyproject-demo")
path = "../git/github.com/demo/pyproject-demo"
tester.execute("{}".format(path))
expected = """\
......@@ -347,8 +351,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4)
• Installing demo (0.1.2 ../git/github.com/demo/pyproject-demo)
"""
• Installing demo (0.1.2 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == tester.io.fetch_output()
assert 2 == tester._command.installer.executor.installations_count
......@@ -360,7 +366,8 @@ def test_add_file_constraint_wheel(app, repo, tester, mocker, poetry):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute("../distributions/demo-0.1.0-py2.py3-none-any.whl")
path = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
tester.execute("{}".format(path))
expected = """\
......@@ -372,8 +379,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4)
• Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl)
"""
• Installing demo (0.1.0 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == tester.io.fetch_output()
assert 2 == tester._command.installer.executor.installations_count
......@@ -392,7 +401,8 @@ def test_add_file_constraint_sdist(app, repo, tester, mocker):
repo.add_package(get_package("pendulum", "1.4.4"))
tester.execute("../distributions/demo-0.1.0.tar.gz")
path = "../distributions/demo-0.1.0.tar.gz"
tester.execute("{}".format(path))
expected = """\
......@@ -404,8 +414,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
• Installing pendulum (1.4.4)
• Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz)
"""
• Installing demo (0.1.0 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == tester.io.fetch_output()
assert 2 == tester._command.installer.executor.installations_count
......@@ -1076,7 +1088,8 @@ def test_add_directory_constraint_old_installer(
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cleo", "0.6.5"))
old_tester.execute("../git/github.com/demo/demo")
path = "../git/github.com/demo/demo"
old_tester.execute("{}".format(path))
expected = """\
......@@ -1088,8 +1101,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4)
- Installing demo (0.1.2 ../git/github.com/demo/demo)
"""
- Installing demo (0.1.2 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == old_tester.io.fetch_output()
......@@ -1109,7 +1124,8 @@ def test_add_directory_with_poetry_old_installer(
repo.add_package(get_package("pendulum", "1.4.4"))
old_tester.execute("../git/github.com/demo/pyproject-demo")
path = "../git/github.com/demo/pyproject-demo"
old_tester.execute("{}".format(path))
expected = """\
......@@ -1121,8 +1137,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4)
- Installing demo (0.1.2 ../git/github.com/demo/pyproject-demo)
"""
- Installing demo (0.1.2 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == old_tester.io.fetch_output()
......@@ -1137,7 +1155,8 @@ def test_add_file_constraint_wheel_old_installer(
repo.add_package(get_package("pendulum", "1.4.4"))
old_tester.execute("../distributions/demo-0.1.0-py2.py3-none-any.whl")
path = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
old_tester.execute("{}".format(path))
expected = """\
......@@ -1149,8 +1168,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4)
- Installing demo (0.1.0 ../distributions/demo-0.1.0-py2.py3-none-any.whl)
"""
- Installing demo (0.1.0 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == old_tester.io.fetch_output()
......@@ -1172,7 +1193,8 @@ def test_add_file_constraint_sdist_old_installer(
repo.add_package(get_package("pendulum", "1.4.4"))
old_tester.execute("../distributions/demo-0.1.0.tar.gz")
path = "../distributions/demo-0.1.0.tar.gz"
old_tester.execute("{}".format(path))
expected = """\
......@@ -1184,8 +1206,10 @@ Writing lock file
Package operations: 2 installs, 0 updates, 0 removals
- Installing pendulum (1.4.4)
- Installing demo (0.1.0 ../distributions/demo-0.1.0.tar.gz)
"""
- Installing demo (0.1.0 {})
""".format(
app.poetry.file.parent.joinpath(path).resolve().as_posix()
)
assert expected == old_tester.io.fetch_output()
......
......@@ -3,6 +3,7 @@ import pytest
from cleo.testers import CommandTester
from clikit.formatter.ansi_formatter import AnsiFormatter
from poetry.factory import Factory
from tests.helpers import get_package
......@@ -1067,10 +1068,10 @@ def test_show_tree(app, poetry, installed):
command = app.find("show")
tester = CommandTester(command)
poetry.package.add_dependency("cachy", "^0.2.0")
poetry.package.add_dependency(Factory.create_dependency("cachy", "^0.2.0"))
cachy2 = get_package("cachy", "0.2.0")
cachy2.add_dependency("msgpack-python", ">=0.5 <0.6")
cachy2.add_dependency(Factory.create_dependency("msgpack-python", ">=0.5 <0.6"))
installed.add_package(cachy2)
......
......@@ -181,14 +181,11 @@ class Poetry(BasePoetry):
class Repository(BaseRepository):
def find_packages(
self, name, constraint=None, extras=None, allow_prereleases=False
):
packages = super(Repository, self).find_packages(
name, constraint, extras, allow_prereleases
)
def find_packages(self, dependency):
packages = super(Repository, self).find_packages(dependency)
if len(packages) == 0:
raise PackageNotFound("Package [{}] not found.".format(name))
raise PackageNotFound("Package [{}] not found.".format(dependency.name))
return packages
def find_links_for_package(self, package):
......
......@@ -14,23 +14,21 @@ bar = ["tomlkit"]
foo = ["cleo"]
[package.source]
reference = ""
type = "file"
url = "../../distributions/demo-0.1.0-py2.py3-none-any.whl"
url = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "inner-directory-project"
optional = false
python-versions = "*"
version = "1.2.4"
[package.source]
reference = ""
type = "directory"
url = "../project_with_transitive_file_dependencies/inner-directory-project"
url = "project_with_transitive_file_dependencies/inner-directory-project"
[[package]]
category = "main"
......@@ -43,7 +41,7 @@ version = "1.4.4"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "project-with-extras"
optional = false
python-versions = "*"
......@@ -54,14 +52,13 @@ extras_a = ["pendulum (>=1.4.4)"]
extras_b = ["cachy (>=0.2.0)"]
[package.source]
reference = ""
type = "directory"
url = "../project_with_extras"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "project-with-transitive-directory-dependencies"
optional = false
python-versions = "*"
......@@ -72,14 +69,13 @@ project-with-extras = "1.2.3"
project-with-transitive-file-dependencies = "1.2.3"
[package.source]
reference = ""
type = "directory"
url = "project_with_transitive_directory_dependencies"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "project-with-transitive-file-dependencies"
optional = false
python-versions = "*"
......@@ -90,7 +86,6 @@ demo = "0.1.0"
inner-directory-project = "1.2.4"
[package.source]
reference = ""
type = "directory"
url = "project_with_transitive_file_dependencies"
......
......@@ -9,7 +9,7 @@ version = "1.4.4"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "project-with-extras"
optional = false
python-versions = "*"
......@@ -23,7 +23,6 @@ extras_a = ["pendulum (>=1.4.4)"]
extras_b = ["cachy (>=0.2.0)"]
[package.source]
reference = ""
type = "directory"
url = "tests/fixtures/project_with_extras"
......
......@@ -9,7 +9,7 @@ python-versions = "*"
[[package]]
name = "my-package"
version = "0.1.2"
develop = true
develop = false
description = "Demo project."
category = "main"
optional = false
......@@ -17,7 +17,6 @@ python-versions = "*"
[package.source]
type = "directory"
reference = ""
url = "tests/fixtures/project_with_setup"
[package.dependencies]
......
......@@ -14,21 +14,19 @@ bar = ["tomlkit"]
foo = ["cleo"]
[package.source]
reference = ""
type = "file"
url = "../distributions/demo-0.1.0-py2.py3-none-any.whl"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "inner-directory-project"
optional = false
python-versions = "*"
version = "1.2.4"
[package.source]
reference = ""
type = "directory"
url = "project_with_transitive_file_dependencies/inner-directory-project"
......@@ -43,7 +41,7 @@ version = "1.4.4"
[[package]]
category = "main"
description = "This is a description"
develop = true
develop = false
name = "project-with-transitive-file-dependencies"
optional = false
python-versions = "*"
......@@ -54,7 +52,6 @@ demo = "0.1.0"
inner-directory-project = "1.2.4"
[package.source]
reference = ""
type = "directory"
url = "project_with_transitive_file_dependencies"
......
......@@ -8,7 +8,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.source]
type = "file"
reference = ""
url = "tests/fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl"
[package.dependencies]
......
......@@ -8,7 +8,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.source]
type = "url"
reference = ""
url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
[package.dependencies]
......
......@@ -8,7 +8,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.source]
type = "file"
reference = ""
url = "tests/fixtures/wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
[metadata]
......
......@@ -89,9 +89,13 @@ def test_chooser_chooses_universal_wheel_link_if_available(
package = Package("pytest", "3.5.0")
if source_type == "legacy":
package.source_type = "legacy"
package.source_reference = "foo"
package.source_url = "https://foo.bar/simple/"
package = Package(
package.name,
package.version.text,
source_type="legacy",
source_reference="foo",
source_url="https://foo.bar/simple/",
)
link = chooser.choose_for(package)
......@@ -106,9 +110,13 @@ def test_chooser_chooses_specific_python_universal_wheel_link_if_available(
package = Package("isort", "4.3.4")
if source_type == "legacy":
package.source_type = "legacy"
package.source_reference = "foo"
package.source_url = "https://foo.bar/simple/"
package = Package(
package.name,
package.version.text,
source_type="legacy",
source_reference="foo",
source_url="https://foo.bar/simple/",
)
link = chooser.choose_for(package)
......@@ -126,9 +134,13 @@ def test_chooser_chooses_system_specific_wheel_link_if_available(
package = Package("pyyaml", "3.13.0")
if source_type == "legacy":
package.source_type = "legacy"
package.source_reference = "foo"
package.source_url = "https://foo.bar/simple/"
package = Package(
package.name,
package.version.text,
source_type="legacy",
source_reference="foo",
source_url="https://foo.bar/simple/",
)
link = chooser.choose_for(package)
......@@ -143,9 +155,13 @@ def test_chooser_chooses_sdist_if_no_compatible_wheel_link_is_available(
package = Package("pyyaml", "3.13.0")
if source_type == "legacy":
package.source_type = "legacy"
package.source_reference = "foo"
package.source_url = "https://foo.bar/simple/"
package = Package(
package.name,
package.version.text,
source_type="legacy",
source_reference="foo",
source_url="https://foo.bar/simple/",
)
link = chooser.choose_for(package)
......@@ -159,16 +175,22 @@ def test_chooser_chooses_distributions_that_match_the_package_hashes(
chooser = Chooser(pool, env)
package = Package("isort", "4.3.4")
package.files = [
files = [
{
"hash": "sha256:b9c40e9750f3d77e6e4d441d8b0266cf555e7cdabdcff33c4fd06366ca761ef8",
"filename": "isort-4.3.4.tar.gz",
}
]
if source_type == "legacy":
package.source_type = "legacy"
package.source_reference = "foo"
package.source_url = "https://foo.bar/simple/"
package = Package(
package.name,
package.version.text,
source_type="legacy",
source_reference="foo",
source_url="https://foo.bar/simple/",
)
package.files = files
link = chooser.choose_for(package)
......
......@@ -65,26 +65,35 @@ def test_execute_executes_a_batch_of_operations(
env = MockEnv(path=Path(tmp_dir))
executor = Executor(env, pool, config, io)
file_package = Package("demo", "0.1.0")
file_package.source_type = "file"
file_package.source_url = str(
Path(__file__)
file_package = Package(
"demo",
"0.1.0",
source_type="file",
source_url=Path(__file__)
.parent.parent.joinpath(
"fixtures/distributions/demo-0.1.0-py2.py3-none-any.whl"
)
.resolve()
.as_posix(),
)
directory_package = Package("simple-project", "1.2.3")
directory_package.source_type = "directory"
directory_package.source_url = str(
Path(__file__).parent.parent.joinpath("fixtures/simple_project").resolve()
directory_package = Package(
"simple-project",
"1.2.3",
source_type="directory",
source_url=Path(__file__)
.parent.parent.joinpath("fixtures/simple_project")
.resolve()
.as_posix(),
)
git_package = Package("demo", "0.1.0")
git_package.source_type = "git"
git_package.source_reference = "master"
git_package.source_url = "https://github.com/demo/demo.git"
git_package = Package(
"demo",
"0.1.0",
source_type="git",
source_reference="master",
source_url="https://github.com/demo/demo.git",
)
assert 0 == executor.execute(
[
......
from __future__ import unicode_literals
import json
import sys
import pytest
......@@ -7,6 +8,7 @@ import pytest
from clikit.io import NullIO
from poetry.core.packages import ProjectPackage
from poetry.factory import Factory
from poetry.installation import Installer as BaseInstaller
from poetry.installation.executor import Executor as BaseExecutor
from poetry.installation.noop_installer import NoopInstaller
......@@ -79,6 +81,7 @@ class CustomInstalledRepository(InstalledRepository):
class Locker(BaseLocker):
def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock"))
self._written_data = None
self._locked = False
self._content_hash = self._get_content_hash()
......@@ -87,6 +90,11 @@ class Locker(BaseLocker):
def written_data(self):
return self._written_data
def set_lock_path(self, lock):
self._lock = TomlFile(Path(lock).joinpath("poetry.lock"))
return self
def locked(self, is_locked=True):
self._locked = is_locked
......@@ -118,7 +126,7 @@ class Locker(BaseLocker):
package["python-versions"] = python_versions
self._written_data = data
self._written_data = json.loads(json.dumps(data))
self._lock_data = data
......@@ -178,7 +186,7 @@ def installer(package, pool, locker, env, installed, config):
def fixture(name):
file = TomlFile(Path(__file__).parent / "fixtures" / "{}.test".format(name))
return file.read()
return json.loads(json.dumps(file.read()))
def test_run_no_dependencies(installer, locker):
......@@ -194,8 +202,8 @@ def test_run_with_dependencies(installer, locker, repo, package):
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
installer.run()
expected = fixture("with-dependencies")
......@@ -257,8 +265,8 @@ def test_run_update_after_removing_dependencies(
installed.add_package(package_b)
installed.add_package(package_c)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "~1.1")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "~1.1"))
installer.update(True)
installer.run()
......@@ -323,9 +331,9 @@ def test_run_install_no_dev(installer, locker, repo, package, installed):
installed.add_package(package_b)
installed.add_package(package_c)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "~1.1")
package.add_dependency("C", "~1.2", category="dev")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "~1.1"))
package.add_dependency(Factory.create_dependency("C", "~1.2", category="dev"))
installer.dev_mode(False)
installer.run()
......@@ -373,7 +381,7 @@ def test_run_install_remove_untracked(installer, locker, repo, package, installe
installed.add_package(package_pip) # Always required and never removed.
installed.add_package(package) # Root package never removed.
package.add_dependency("A", "~1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.dev_mode(True).remove_untracked(True)
installer.run()
......@@ -414,8 +422,8 @@ def test_run_whitelist_add(installer, locker, repo, package):
repo.add_package(package_a_new)
repo.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
installer.update(True)
installer.whitelist(["B"])
......@@ -464,7 +472,7 @@ def test_run_whitelist_remove(installer, locker, repo, package, installed):
repo.add_package(package_b)
installed.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.update(True)
installer.whitelist(["B"])
......@@ -488,11 +496,11 @@ def test_add_with_sub_dependencies(installer, locker, repo, package):
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a.add_dependency("D", "^1.0")
package_b.add_dependency("C", "~1.2")
package_a.add_dependency(Factory.create_dependency("D", "^1.0"))
package_b.add_dependency(Factory.create_dependency("C", "~1.2"))
installer.run()
expected = fixture("with-sub-dependencies")
......@@ -515,9 +523,9 @@ def test_run_with_python_versions(installer, locker, repo, package):
repo.add_package(package_c12)
repo.add_package(package_c13)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
installer.run()
expected = fixture("with-python-versions")
......@@ -535,7 +543,7 @@ def test_run_with_optional_and_python_restricted_dependencies(
package_c12 = get_package("C", "1.2")
package_c13 = get_package("C", "1.3")
package_d = get_package("D", "1.4")
package_c13.add_dependency("D", "^1.2")
package_c13.add_dependency(Factory.create_dependency("D", "^1.2"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -544,9 +552,15 @@ def test_run_with_optional_and_python_restricted_dependencies(
repo.add_package(package_d)
package.extras = {"foo": [get_dependency("A", "~1.0")]}
package.add_dependency("A", {"version": "~1.0", "optional": True})
package.add_dependency("B", {"version": "^1.0", "python": "~2.4"})
package.add_dependency("C", {"version": "^1.0", "python": "~2.7 || ^3.4"})
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.0", "optional": True})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "~2.4"})
)
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7 || ^3.4"})
)
installer.run()
expected = fixture("with-optional-dependencies")
......@@ -571,7 +585,7 @@ def test_run_with_optional_and_platform_restricted_dependencies(
package_c12 = get_package("C", "1.2")
package_c13 = get_package("C", "1.3")
package_d = get_package("D", "1.4")
package_c13.add_dependency("D", "^1.2")
package_c13.add_dependency(Factory.create_dependency("D", "^1.2"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -580,9 +594,15 @@ def test_run_with_optional_and_platform_restricted_dependencies(
repo.add_package(package_d)
package.extras = {"foo": [get_dependency("A", "~1.0")]}
package.add_dependency("A", {"version": "~1.0", "optional": True})
package.add_dependency("B", {"version": "^1.0", "platform": "custom"})
package.add_dependency("C", {"version": "^1.0", "platform": "darwin"})
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.0", "optional": True})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "platform": "custom"})
)
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "platform": "darwin"})
)
installer.run()
expected = fixture("with-platform-dependencies")
......@@ -603,14 +623,18 @@ def test_run_with_dependencies_extras(installer, locker, repo, package):
package_c = get_package("C", "1.0")
package_b.extras = {"foo": [get_dependency("C", "^1.0")]}
package_b.add_dependency("C", {"version": "^1.0", "optional": True})
package_b.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
repo.add_package(package_a)
repo.add_package(package_b)
repo.add_package(package_c)
package.add_dependency("A", "^1.0")
package.add_dependency("B", {"version": "^1.0", "extras": ["foo"]})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]})
)
installer.run()
expected = fixture("with-dependencies-extras")
......@@ -630,10 +654,12 @@ def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, p
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency("D", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
package.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True})
)
installer.run()
expected = fixture("extras")
......@@ -657,10 +683,12 @@ def test_run_installs_extras_if_requested(installer, locker, repo, package):
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency("D", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
package.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True})
)
installer.extras(["foo"])
installer.run()
......@@ -685,11 +713,13 @@ def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, pac
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.extras(["foo"])
installer.run()
......@@ -718,11 +748,13 @@ def test_run_installs_extras_with_deps_if_requested_locked(
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.extras(["foo"])
installer.run()
......@@ -739,7 +771,7 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
NullIO(), NullEnv(), package, locker, pool, config, installed=installed
)
package.add_dependency("pytest", "^3.5", category="dev")
package.add_dependency(Factory.create_dependency("pytest", "^3.5", category="dev"))
installer.run()
expected = fixture("with-pypi-repository")
......@@ -749,7 +781,7 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
def test_run_installs_with_local_file(installer, locker, repo, package):
file_path = fixtures_dir / "distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency("demo", {"file": str(file_path)})
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -758,7 +790,6 @@ def test_run_installs_with_local_file(installer, locker, repo, package):
expected = fixture("with-file-dependency")
assert locker.written_data == expected
assert 2 == installer.executor.installations_count
......@@ -766,7 +797,7 @@ def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, packa
file_path = (
fixtures_dir / "wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
)
package.add_dependency("demo", {"file": str(file_path)})
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
installer.run()
......@@ -782,8 +813,11 @@ def test_run_installs_with_local_poetry_directory_and_extras(
):
file_path = fixtures_dir / "project_with_extras"
package.add_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
Factory.create_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
)
)
print(package.requires[0].develop)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -799,13 +833,16 @@ def test_run_installs_with_local_poetry_directory_and_extras(
def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir
):
package.root_dir = fixtures_dir.joinpath("directory")
directory = fixtures_dir.joinpath("directory").joinpath(
"project_with_transitive_directory_dependencies"
)
root_dir = fixtures_dir.joinpath("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_directory_dependencies")
package.add_dependency(
"project-with-transitive-directory-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
Factory.create_dependency(
"project-with-transitive-directory-dependencies",
{"path": str(directory.relative_to(root_dir))},
root_dir=root_dir,
)
)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -823,13 +860,18 @@ def test_run_installs_with_local_poetry_directory_transitive(
def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir
):
package.root_dir = fixtures_dir.joinpath("directory")
root_dir = fixtures_dir.joinpath("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = fixtures_dir.joinpath("directory").joinpath(
"project_with_transitive_file_dependencies"
)
package.add_dependency(
"project-with-transitive-file-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
Factory.create_dependency(
"project-with-transitive-file-dependencies",
{"path": str(directory.relative_to(root_dir))},
root_dir=root_dir,
)
)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -848,7 +890,9 @@ def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir
):
file_path = fixtures_dir / "project_with_setup/"
package.add_dependency("my-package", {"path": str(file_path)})
package.add_dependency(
Factory.create_dependency("my-package", {"path": str(file_path)})
)
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cachy", "0.2.0"))
......@@ -858,7 +902,6 @@ def test_run_installs_with_local_setuptools_directory(
expected = fixture("with-directory-dependency-setuptools")
assert locker.written_data == expected
assert 3 == installer.executor.installations_count
......@@ -890,8 +933,10 @@ def test_run_with_prereleases(installer, locker, repo, package):
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", {"version": "*", "allow-prereleases": True})
package.add_dependency("B", "^1.1")
package.add_dependency(
Factory.create_dependency("A", {"version": "*", "allow-prereleases": True})
)
package.add_dependency(Factory.create_dependency("B", "^1.1"))
installer.update(True)
installer.whitelist({"B": "^1.1"})
......@@ -927,12 +972,16 @@ def test_run_changes_category_if_needed(installer, locker, repo, package):
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
package_b.add_dependency("A", "^1.0")
package_b.add_dependency(Factory.create_dependency("A", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", {"version": "^1.0", "optional": True}, category="dev")
package.add_dependency("B", "^1.1")
package.add_dependency(
Factory.create_dependency(
"A", {"version": "^1.0", "optional": True}, category="dev"
)
)
package.add_dependency(Factory.create_dependency("B", "^1.1"))
installer.update(True)
installer.whitelist(["B"])
......@@ -970,7 +1019,7 @@ def test_run_update_all_with_lock(installer, locker, repo, package):
repo.add_package(get_package("A", "1.0"))
repo.add_package(package_a)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
installer.update(True)
......@@ -1037,8 +1086,10 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
repo.add_package(get_package("C", "1.1"))
repo.add_package(get_package("D", "1.1"))
package.add_dependency("A", {"version": "^1.0", "extras": ["foo"]})
package.add_dependency("D", "^1.0")
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo"]})
)
package.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.update(True)
installer.whitelist("D")
......@@ -1052,16 +1103,20 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_install_duplicate_dependencies_different_constraints(
installer, locker, repo, package
):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=4.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1159,16 +1214,20 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock(
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=4.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1226,10 +1285,12 @@ def test_run_update_uninstalls_after_removal_transient_dependency(
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<2.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"})
)
package_b10 = get_package("B", "1.0")
......@@ -1318,15 +1379,15 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock_upda
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.1")
package_a.add_dependency("B", "^2.0")
package_a.add_dependency(Factory.create_dependency("B", "^2.0"))
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1359,7 +1420,9 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
installer, locker, repo, package, installed
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency("A", {"version": "^1.0", "python": "^3.5"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"})
)
package_a101 = get_package("A", "1.0.1")
package_a101.python_versions = ">=3.6"
......@@ -1384,13 +1447,17 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency(
installer, locker, repo, package, installed, env, pool, config
):
package.add_dependency("A", {"version": "^1.0"})
package.add_dependency(Factory.create_dependency("A", {"version": "^1.0"}))
package_a = get_package("A", "1.0.0")
package_a.add_dependency("B", {"version": "^1.0", "extras": ["foo"]})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]})
)
package_b = get_package("B", "1.0.0")
package_b.add_dependency("C", {"version": "^1.0", "optional": True})
package_b.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_b.extras = {"foo": [get_dependency("C")]}
package_c = get_package("C", "1.0.0")
......@@ -1408,7 +1475,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
assert 0 == installer.executor.updates_count
assert 0 == installer.executor.removals_count
package.add_dependency("D", "^1.0")
package.add_dependency(Factory.create_dependency("D", "^1.0"))
locker.locked(True)
locker.mock_lock_data(locker.written_data)
......@@ -1457,7 +1524,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
)
installer.use_executor()
package.add_dependency("poetry", {"version": "^0.12.0"})
package.add_dependency(Factory.create_dependency("poetry", {"version": "^0.12.0"}))
installer.update(True)
installer.run()
......@@ -1466,7 +1533,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
assert 0 == installer.executor.updates_count
assert 0 == installer.executor.removals_count
package.add_dependency("pytest", "^3.5")
package.add_dependency(Factory.create_dependency("pytest", "^3.5"))
locker.locked(True)
locker.mock_lock_data(locker.written_data)
......@@ -1514,7 +1581,9 @@ def test_installer_required_extras_should_be_installed(
installer.use_executor()
package.add_dependency(
"cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]}
Factory.create_dependency(
"cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]}
)
)
installer.update(True)
......@@ -1585,13 +1654,17 @@ def test_update_multiple_times_with_split_dependencies_is_idempotent(
)
package.python_versions = "~2.7 || ^3.4"
package.add_dependency("A", "^1.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
a10 = get_package("A", "1.0")
a11 = get_package("A", "1.1")
a11.add_dependency("B", ">=1.0.1")
a11.add_dependency("C", {"version": "^1.0", "python": "~2.7"})
a11.add_dependency("C", {"version": "^2.0", "python": "^3.4"})
a11.add_dependency(Factory.create_dependency("B", ">=1.0.1"))
a11.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7"})
)
a11.add_dependency(
Factory.create_dependency("C", {"version": "^2.0", "python": "^3.4"})
)
b101 = get_package("B", "1.0.1")
b110 = get_package("B", "1.1.0")
repo.add_package(a10)
......@@ -1626,7 +1699,9 @@ def test_installer_can_install_dependencies_from_forced_source(
locker, package, installed, env, config
):
package.python_versions = "^3.7"
package.add_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
package.add_dependency(
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
)
pool = Pool()
pool.add_repository(MockLegacyRepository())
......@@ -1654,7 +1729,7 @@ def test_installer_can_install_dependencies_from_forced_source(
def test_run_installs_with_url_file(installer, locker, repo, package):
url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency("demo", {"url": url})
package.add_dependency(Factory.create_dependency("demo", {"url": url}))
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -1672,11 +1747,13 @@ def test_installer_uses_prereleases_if_they_are_compatible(
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
"prerelease", {"git": "https://github.com/demo/prerelease.git"}
Factory.create_dependency(
"prerelease", {"git": "https://github.com/demo/prerelease.git"}
)
)
package_b = get_package("b", "2.0.0")
package_b.add_dependency("prerelease", ">=0.19")
package_b.add_dependency(Factory.create_dependency("prerelease", ">=0.19"))
repo.add_package(package_b)
......@@ -1686,7 +1763,7 @@ def test_installer_uses_prereleases_if_they_are_compatible(
locker.locked(True)
locker.mock_lock_data(locker.written_data)
package.add_dependency("b", "^2.0.0")
package.add_dependency(Factory.create_dependency("b", "^2.0.0"))
installer.whitelist(["b"])
installer.update(True)
......@@ -1701,7 +1778,7 @@ def test_installer_can_handle_old_lock_files(
pool = Pool()
pool.add_repository(MockRepository())
package.add_dependency("pytest", "^3.5", category="dev")
package.add_dependency(Factory.create_dependency("pytest", "^3.5", category="dev"))
locker.locked()
locker.mock_lock_data(fixture("old-lock"))
......@@ -1714,7 +1791,7 @@ def test_installer_can_handle_old_lock_files(
pool,
config,
installed=installed,
executor=Executor(MockEnv(), pool, config, NullIO(),),
executor=Executor(MockEnv(), pool, config, NullIO()),
)
installer.use_executor()
......
......@@ -7,6 +7,7 @@ import pytest
from clikit.io import NullIO
from poetry.core.packages import ProjectPackage
from poetry.factory import Factory
from poetry.installation import Installer as BaseInstaller
from poetry.installation.noop_installer import NoopInstaller
from poetry.packages import Locker as BaseLocker
......@@ -42,6 +43,7 @@ class CustomInstalledRepository(InstalledRepository):
class Locker(BaseLocker):
def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock"))
self._written_data = None
self._locked = False
self._content_hash = self._get_content_hash()
......@@ -50,6 +52,11 @@ class Locker(BaseLocker):
def written_data(self):
return self._written_data
def set_lock_path(self, lock):
self._lock = TomlFile(Path(lock).joinpath("poetry.lock"))
return self
def locked(self, is_locked=True):
self._locked = is_locked
......@@ -145,8 +152,8 @@ def test_run_with_dependencies(installer, locker, repo, package):
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
installer.run()
expected = fixture("with-dependencies")
......@@ -208,8 +215,8 @@ def test_run_update_after_removing_dependencies(
installed.add_package(package_b)
installed.add_package(package_c)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "~1.1")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "~1.1"))
installer.update(True)
installer.run()
......@@ -279,9 +286,9 @@ def test_run_install_no_dev(installer, locker, repo, package, installed):
installed.add_package(package_b)
installed.add_package(package_c)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "~1.1")
package.add_dependency("C", "~1.2", category="dev")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "~1.1"))
package.add_dependency(Factory.create_dependency("C", "~1.2", category="dev"))
installer.dev_mode(False)
installer.run()
......@@ -334,7 +341,7 @@ def test_run_install_remove_untracked(installer, locker, repo, package, installe
installed.add_package(package_pip) # Always required and never removed.
installed.add_package(package) # Root package never removed.
package.add_dependency("A", "~1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.dev_mode(True).remove_untracked(True)
installer.run()
......@@ -379,8 +386,8 @@ def test_run_whitelist_add(installer, locker, repo, package):
repo.add_package(package_a_new)
repo.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
installer.update(True)
installer.whitelist(["B"])
......@@ -429,7 +436,7 @@ def test_run_whitelist_remove(installer, locker, repo, package, installed):
repo.add_package(package_b)
installed.add_package(package_b)
package.add_dependency("A", "~1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
installer.update(True)
installer.whitelist(["B"])
......@@ -453,11 +460,11 @@ def test_add_with_sub_dependencies(installer, locker, repo, package):
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a.add_dependency("D", "^1.0")
package_b.add_dependency("C", "~1.2")
package_a.add_dependency(Factory.create_dependency("D", "^1.0"))
package_b.add_dependency(Factory.create_dependency("C", "~1.2"))
installer.run()
expected = fixture("with-sub-dependencies")
......@@ -480,9 +487,9 @@ def test_run_with_python_versions(installer, locker, repo, package):
repo.add_package(package_c12)
repo.add_package(package_c13)
package.add_dependency("A", "~1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency(Factory.create_dependency("A", "~1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
installer.run()
expected = fixture("with-python-versions")
......@@ -500,7 +507,7 @@ def test_run_with_optional_and_python_restricted_dependencies(
package_c12 = get_package("C", "1.2")
package_c13 = get_package("C", "1.3")
package_d = get_package("D", "1.4")
package_c13.add_dependency("D", "^1.2")
package_c13.add_dependency(Factory.create_dependency("D", "^1.2"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -509,9 +516,15 @@ def test_run_with_optional_and_python_restricted_dependencies(
repo.add_package(package_d)
package.extras = {"foo": [get_dependency("A", "~1.0")]}
package.add_dependency("A", {"version": "~1.0", "optional": True})
package.add_dependency("B", {"version": "^1.0", "python": "~2.4"})
package.add_dependency("C", {"version": "^1.0", "python": "~2.7 || ^3.4"})
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.0", "optional": True})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "~2.4"})
)
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7 || ^3.4"})
)
installer.run()
expected = fixture("with-optional-dependencies")
......@@ -537,7 +550,7 @@ def test_run_with_optional_and_platform_restricted_dependencies(
package_c12 = get_package("C", "1.2")
package_c13 = get_package("C", "1.3")
package_d = get_package("D", "1.4")
package_c13.add_dependency("D", "^1.2")
package_c13.add_dependency(Factory.create_dependency("D", "^1.2"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -546,9 +559,15 @@ def test_run_with_optional_and_platform_restricted_dependencies(
repo.add_package(package_d)
package.extras = {"foo": [get_dependency("A", "~1.0")]}
package.add_dependency("A", {"version": "~1.0", "optional": True})
package.add_dependency("B", {"version": "^1.0", "platform": "custom"})
package.add_dependency("C", {"version": "^1.0", "platform": "darwin"})
package.add_dependency(
Factory.create_dependency("A", {"version": "~1.0", "optional": True})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "platform": "custom"})
)
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "platform": "darwin"})
)
installer.run()
expected = fixture("with-platform-dependencies")
......@@ -570,14 +589,18 @@ def test_run_with_dependencies_extras(installer, locker, repo, package):
package_c = get_package("C", "1.0")
package_b.extras = {"foo": [get_dependency("C", "^1.0")]}
package_b.add_dependency("C", {"version": "^1.0", "optional": True})
package_b.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
repo.add_package(package_a)
repo.add_package(package_b)
repo.add_package(package_c)
package.add_dependency("A", "^1.0")
package.add_dependency("B", {"version": "^1.0", "extras": ["foo"]})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]})
)
installer.run()
expected = fixture("with-dependencies-extras")
......@@ -597,10 +620,12 @@ def test_run_does_not_install_extras_if_not_requested(installer, locker, repo, p
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency("D", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
package.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True})
)
installer.run()
expected = fixture("extras")
......@@ -625,10 +650,12 @@ def test_run_installs_extras_if_requested(installer, locker, repo, package):
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", "^1.0")
package.add_dependency("D", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(Factory.create_dependency("C", "^1.0"))
package.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True})
)
installer.extras(["foo"])
installer.run()
......@@ -654,11 +681,13 @@ def test_run_installs_extras_with_deps_if_requested(installer, locker, repo, pac
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.extras(["foo"])
installer.run()
......@@ -688,11 +717,13 @@ def test_run_installs_extras_with_deps_if_requested_locked(
repo.add_package(package_c)
repo.add_package(package_d)
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^1.0")
package.add_dependency("C", {"version": "^1.0", "optional": True})
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.extras(["foo"])
installer.run()
......@@ -710,7 +741,7 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
NullIO(), NullEnv(), package, locker, pool, config, installed=installed
)
package.add_dependency("pytest", "^3.5", category="dev")
package.add_dependency(Factory.create_dependency("pytest", "^3.5", category="dev"))
installer.run()
expected = fixture("with-pypi-repository")
......@@ -720,7 +751,7 @@ def test_installer_with_pypi_repository(package, locker, installed, config):
def test_run_installs_with_local_file(installer, locker, repo, package):
file_path = fixtures_dir / "distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency("demo", {"file": str(file_path)})
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -737,7 +768,7 @@ def test_run_installs_wheel_with_no_requires_dist(installer, locker, repo, packa
file_path = (
fixtures_dir / "wheel_with_no_requires_dist/demo-0.1.0-py2.py3-none-any.whl"
)
package.add_dependency("demo", {"file": str(file_path)})
package.add_dependency(Factory.create_dependency("demo", {"file": str(file_path)}))
installer.run()
......@@ -753,7 +784,9 @@ def test_run_installs_with_local_poetry_directory_and_extras(
):
file_path = fixtures_dir / "project_with_extras"
package.add_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
Factory.create_dependency(
"project-with-extras", {"path": str(file_path), "extras": ["extras_a"]}
)
)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -770,13 +803,16 @@ def test_run_installs_with_local_poetry_directory_and_extras(
def test_run_installs_with_local_poetry_directory_transitive(
installer, locker, repo, package, tmpdir
):
package.root_dir = fixtures_dir.joinpath("directory")
directory = fixtures_dir.joinpath("directory").joinpath(
"project_with_transitive_directory_dependencies"
)
root_dir = fixtures_dir.joinpath("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_directory_dependencies")
package.add_dependency(
"project-with-transitive-directory-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
Factory.create_dependency(
"project-with-transitive-directory-dependencies",
{"path": str(directory.relative_to(root_dir))},
root_dir=root_dir,
)
)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -794,13 +830,16 @@ def test_run_installs_with_local_poetry_directory_transitive(
def test_run_installs_with_local_poetry_file_transitive(
installer, locker, repo, package, tmpdir
):
package.root_dir = fixtures_dir.joinpath("directory")
directory = fixtures_dir.joinpath("directory").joinpath(
"project_with_transitive_file_dependencies"
)
root_dir = fixtures_dir.joinpath("directory")
package.root_dir = root_dir
locker.set_lock_path(root_dir)
directory = root_dir.joinpath("project_with_transitive_file_dependencies")
package.add_dependency(
"project-with-transitive-file-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
Factory.create_dependency(
"project-with-transitive-file-dependencies",
{"path": str(directory.relative_to(fixtures_dir.joinpath("directory")))},
root_dir=root_dir,
)
)
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -819,7 +858,9 @@ def test_run_installs_with_local_setuptools_directory(
installer, locker, repo, package, tmpdir
):
file_path = fixtures_dir / "project_with_setup/"
package.add_dependency("my-package", {"path": str(file_path)})
package.add_dependency(
Factory.create_dependency("my-package", {"path": str(file_path)})
)
repo.add_package(get_package("pendulum", "1.4.4"))
repo.add_package(get_package("cachy", "0.2.0"))
......@@ -861,8 +902,10 @@ def test_run_with_prereleases(installer, locker, repo, package):
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", {"version": "*", "allow-prereleases": True})
package.add_dependency("B", "^1.1")
package.add_dependency(
Factory.create_dependency("A", {"version": "*", "allow-prereleases": True})
)
package.add_dependency(Factory.create_dependency("B", "^1.1"))
installer.update(True)
installer.whitelist({"B": "^1.1"})
......@@ -898,12 +941,16 @@ def test_run_changes_category_if_needed(installer, locker, repo, package):
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.1")
package_b.add_dependency("A", "^1.0")
package_b.add_dependency(Factory.create_dependency("A", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
package.add_dependency("A", {"version": "^1.0", "optional": True}, category="dev")
package.add_dependency("B", "^1.1")
package.add_dependency(
Factory.create_dependency(
"A", {"version": "^1.0", "optional": True}, category="dev"
)
)
package.add_dependency(Factory.create_dependency("B", "^1.1"))
installer.update(True)
installer.whitelist(["B"])
......@@ -941,7 +988,7 @@ def test_run_update_all_with_lock(installer, locker, repo, package):
repo.add_package(get_package("A", "1.0"))
repo.add_package(package_a)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
installer.update(True)
......@@ -1008,8 +1055,10 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
repo.add_package(get_package("C", "1.1"))
repo.add_package(get_package("D", "1.1"))
package.add_dependency("A", {"version": "^1.0", "extras": ["foo"]})
package.add_dependency("D", "^1.0")
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo"]})
)
package.add_dependency(Factory.create_dependency("D", "^1.0"))
installer.update(True)
installer.whitelist("D")
......@@ -1023,16 +1072,20 @@ def test_run_update_with_locked_extras(installer, locker, repo, package):
def test_run_install_duplicate_dependencies_different_constraints(
installer, locker, repo, package
):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=4.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1132,16 +1185,20 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock(
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=4.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=4.0"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1202,10 +1259,12 @@ def test_run_update_uninstalls_after_removal_transient_dependency(
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<2.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"})
)
package_b10 = get_package("B", "1.0")
......@@ -1297,15 +1356,15 @@ def test_run_install_duplicate_dependencies_different_constraints_with_lock_upda
},
}
)
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.1")
package_a.add_dependency("B", "^2.0")
package_a.add_dependency(Factory.create_dependency("B", "^2.0"))
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -1341,7 +1400,9 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
installer, locker, repo, package, installed
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency("A", {"version": "^1.0", "python": "^3.5"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"})
)
package_a101 = get_package("A", "1.0.1")
package_a101.python_versions = ">=3.6"
......@@ -1368,13 +1429,17 @@ def test_installer_test_solver_finds_compatible_package_for_dependency_python_no
def test_installer_required_extras_should_not_be_removed_when_updating_single_dependency(
installer, locker, repo, package, installed, env, pool, config
):
package.add_dependency("A", {"version": "^1.0"})
package.add_dependency(Factory.create_dependency("A", {"version": "^1.0"}))
package_a = get_package("A", "1.0.0")
package_a.add_dependency("B", {"version": "^1.0", "extras": ["foo"]})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "extras": ["foo"]})
)
package_b = get_package("B", "1.0.0")
package_b.add_dependency("C", {"version": "^1.0", "optional": True})
package_b.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_b.extras = {"foo": [get_dependency("C")]}
package_c = get_package("C", "1.0.0")
......@@ -1392,7 +1457,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
assert len(installer.installer.updates) == 0
assert len(installer.installer.removals) == 0
package.add_dependency("D", "^1.0")
package.add_dependency(Factory.create_dependency("D", "^1.0"))
locker.locked(True)
locker.mock_lock_data(locker.written_data)
......@@ -1425,7 +1490,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
NullIO(), env, package, locker, pool, config, installed=installed
)
package.add_dependency("poetry", {"version": "^0.12.0"})
package.add_dependency(Factory.create_dependency("poetry", {"version": "^0.12.0"}))
installer.update(True)
installer.run()
......@@ -1434,7 +1499,7 @@ def test_installer_required_extras_should_not_be_removed_when_updating_single_de
assert len(installer.installer.updates) == 0
assert len(installer.installer.removals) == 0
package.add_dependency("pytest", "^3.5")
package.add_dependency(Factory.create_dependency("pytest", "^3.5"))
locker.locked(True)
locker.mock_lock_data(locker.written_data)
......@@ -1466,7 +1531,9 @@ def test_installer_required_extras_should_be_installed(
)
package.add_dependency(
"cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]}
Factory.create_dependency(
"cachecontrol", {"version": "^0.12.5", "extras": ["filecache"]}
)
)
installer.update(True)
......@@ -1529,13 +1596,17 @@ def test_update_multiple_times_with_split_dependencies_is_idempotent(
)
package.python_versions = "~2.7 || ^3.4"
package.add_dependency("A", "^1.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
a10 = get_package("A", "1.0")
a11 = get_package("A", "1.1")
a11.add_dependency("B", ">=1.0.1")
a11.add_dependency("C", {"version": "^1.0", "python": "~2.7"})
a11.add_dependency("C", {"version": "^2.0", "python": "^3.4"})
a11.add_dependency(Factory.create_dependency("B", ">=1.0.1"))
a11.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "python": "~2.7"})
)
a11.add_dependency(
Factory.create_dependency("C", {"version": "^2.0", "python": "^3.4"})
)
b101 = get_package("B", "1.0.1")
b110 = get_package("B", "1.1.0")
repo.add_package(a10)
......@@ -1570,7 +1641,9 @@ def test_installer_can_install_dependencies_from_forced_source(
locker, package, installed, env, config
):
package.python_versions = "^3.7"
package.add_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
package.add_dependency(
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
)
pool = Pool()
pool.add_repository(MockLegacyRepository())
......@@ -1590,7 +1663,7 @@ def test_installer_can_install_dependencies_from_forced_source(
def test_run_installs_with_url_file(installer, locker, repo, package):
url = "https://python-poetry.org/distributions/demo-0.1.0-py2.py3-none-any.whl"
package.add_dependency("demo", {"url": url})
package.add_dependency(Factory.create_dependency("demo", {"url": url}))
repo.add_package(get_package("pendulum", "1.4.4"))
......@@ -1608,11 +1681,13 @@ def test_installer_uses_prereleases_if_they_are_compatible(
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
"prerelease", {"git": "https://github.com/demo/prerelease.git"}
Factory.create_dependency(
"prerelease", {"git": "https://github.com/demo/prerelease.git"}
)
)
package_b = get_package("b", "2.0.0")
package_b.add_dependency("prerelease", ">=0.19")
package_b.add_dependency(Factory.create_dependency("prerelease", ">=0.19"))
repo.add_package(package_b)
......@@ -1622,7 +1697,7 @@ def test_installer_uses_prereleases_if_they_are_compatible(
locker.locked(True)
locker.mock_lock_data(locker.written_data)
package.add_dependency("b", "^2.0.0")
package.add_dependency(Factory.create_dependency("b", "^2.0.0"))
installer.whitelist(["b"])
installer.update(True)
......@@ -1637,7 +1712,7 @@ def test_installer_can_handle_old_lock_files(
pool = Pool()
pool.add_repository(MockRepository())
package.add_dependency("pytest", "^3.5", category="dev")
package.add_dependency(Factory.create_dependency("pytest", "^3.5", category="dev"))
locker.locked()
locker.mock_lock_data(fixture("old-lock"))
......
......@@ -13,10 +13,14 @@ from poetry.utils.env import NullEnv
@pytest.fixture
def package_git():
package = Package("demo", "1.0.0")
package.source_type = "git"
package.source_url = "git@github.com:demo/demo.git"
package.source_reference = "master"
package = Package(
"demo",
"1.0.0",
source_type="git",
source_url="git@github.com:demo/demo.git",
source_reference="master",
)
return package
......@@ -54,9 +58,12 @@ def test_requirement(installer):
def test_requirement_source_type_url():
installer = PipInstaller(NullEnv(), NullIO(), Pool())
foo = Package("foo", "0.0.0")
foo.source_type = "url"
foo.source_url = "https://somehwere.com/releases/foo-1.0.0.tar.gz"
foo = Package(
"foo",
"0.0.0",
source_type="url",
source_url="https://somehwere.com/releases/foo-1.0.0.tar.gz",
)
result = installer.requirement(foo, formatted=True)
expected = "{}#egg={}".format(foo.source_url, foo.name)
......@@ -79,14 +86,20 @@ def test_install_with_non_pypi_default_repository(pool, installer):
pool.add_repository(default, default=True)
pool.add_repository(another)
foo = Package("foo", "0.0.0")
foo.source_type = "legacy"
foo.source_reference = default._name
foo.source_url = default._url
bar = Package("bar", "0.1.0")
bar.source_type = "legacy"
bar.source_reference = another._name
bar.source_url = another._url
foo = Package(
"foo",
"0.0.0",
source_type="legacy",
source_reference=default.name,
source_url=default.url,
)
bar = Package(
"bar",
"0.1.0",
source_type="legacy",
source_reference=another.name,
source_url=another.url,
)
installer.install(foo)
installer.install(bar)
......@@ -104,10 +117,13 @@ def test_install_with_cert():
installer = PipInstaller(null_env, NullIO(), pool)
foo = Package("foo", "0.0.0")
foo.source_type = "legacy"
foo.source_reference = default._name
foo.source_url = default._url
foo = Package(
"foo",
"0.0.0",
source_type="legacy",
source_reference=default.name,
source_url=default.url,
)
installer.install(foo)
......@@ -133,10 +149,13 @@ def test_install_with_client_cert():
installer = PipInstaller(null_env, NullIO(), pool)
foo = Package("foo", "0.0.0")
foo.source_type = "legacy"
foo.source_reference = default._name
foo.source_url = default._url
foo = Package(
"foo",
"0.0.0",
source_type="legacy",
source_reference=default.name,
source_url=default.url,
)
installer.install(foo)
......@@ -161,11 +180,13 @@ def test_uninstall_git_package_nspkg_pth_cleanup(mocker, tmp_venv, pool):
installer = PipInstaller(tmp_venv, NullIO(), pool)
# use a namepspace package
package = Package("namespace-package-one", "1.0.0")
package.source_type = "git"
package.source_url = "https://github.com/demo/namespace-package-one.git"
package.source_reference = "master"
package.develop = True
package = Package(
"namespace-package-one",
"1.0.0",
source_type="git",
source_url="https://github.com/demo/namespace-package-one.git",
source_reference="master",
)
# we do this here because the virtual env might not be usable if failure case is triggered
pth_file_candidate = tmp_venv.site_packages / "{}-nspkg.pth".format(package.name)
......
from poetry.core.packages import Package
from poetry.factory import Factory
from poetry.mixology.failure import SolveFailure
from poetry.mixology.version_solver import VersionSolver
from poetry.packages import DependencyPackage
......@@ -11,7 +12,7 @@ def add_to_repo(repository, name, version, deps=None, python=None):
if deps:
for dep_name, dep_constraint in deps.items():
package.add_dependency(dep_name, dep_constraint)
package.add_dependency(Factory.create_dependency(dep_name, dep_constraint))
repository.add_package(package)
......
from poetry.factory import Factory
from ..helpers import add_to_repo
from ..helpers import check_solver_result
def test_circular_dependency_on_older_version(root, provider, repo):
root.add_dependency("a", ">=1.0.0")
root.add_dependency(Factory.create_dependency("a", ">=1.0.0"))
add_to_repo(repo, "a", "1.0.0")
add_to_repo(repo, "a", "2.0.0", deps={"b": "1.0.0"})
......@@ -13,8 +15,8 @@ def test_circular_dependency_on_older_version(root, provider, repo):
def test_diamond_dependency_graph(root, provider, repo):
root.add_dependency("a", "*")
root.add_dependency("b", "*")
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
add_to_repo(repo, "a", "2.0.0", deps={"c": "^1.0.0"})
add_to_repo(repo, "a", "1.0.0")
......@@ -33,8 +35,8 @@ def test_backjumps_after_partial_satisfier(root, provider, repo):
# c 2.0.0 is incompatible with y 2.0.0 because it requires x 1.0.0, but that
# requirement only exists because of both a and b. The solver should be able
# to deduce c 2.0.0's incompatibility and select c 1.0.0 instead.
root.add_dependency("c", "*")
root.add_dependency("y", "^2.0.0")
root.add_dependency(Factory.create_dependency("c", "*"))
root.add_dependency(Factory.create_dependency("y", "^2.0.0"))
add_to_repo(repo, "a", "1.0.0", deps={"x": ">=1.0.0"})
add_to_repo(repo, "b", "1.0.0", deps={"x": "<2.0.0"})
......@@ -56,7 +58,7 @@ def test_rolls_back_leaf_versions_first(root, provider, repo):
# The latest versions of a and b disagree on c. An older version of either
# will resolve the problem. This test validates that b, which is farther
# in the dependency graph from myapp is downgraded first.
root.add_dependency("a", "*")
root.add_dependency(Factory.create_dependency("a", "*"))
add_to_repo(repo, "a", "1.0.0", deps={"b": "*"})
add_to_repo(repo, "a", "2.0.0", deps={"b": "*", "c": "2.0.0"})
......@@ -71,7 +73,7 @@ def test_rolls_back_leaf_versions_first(root, provider, repo):
def test_simple_transitive(root, provider, repo):
# Only one version of baz, so foo and bar will have to downgrade
# until they reach it
root.add_dependency("foo", "*")
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "foo", "2.0.0", deps={"bar": "2.0.0"})
......@@ -93,8 +95,8 @@ def test_backjump_to_nearer_unsatisfied_package(root, provider, repo):
# a-2.0.0 whose dependency on c-2.0.0-nonexistent led to the problem. We
# make sure b has more versions than a so that the solver tries a first
# since it sorts sibling dependencies by number of versions.
root.add_dependency("a", "*")
root.add_dependency("b", "*")
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
add_to_repo(repo, "a", "1.0.0", deps={"c": "1.0.0"})
add_to_repo(repo, "a", "2.0.0", deps={"c": "2.0.0-nonexistent"})
......@@ -114,8 +116,8 @@ def test_traverse_into_package_with_fewer_versions_first(root, provider, repo):
# downgraded once). The chosen one depends on which dep is traversed first.
# Since b has fewer versions, it will be traversed first, which means a will
# come later. Since later selections are revised first, a gets downgraded.
root.add_dependency("a", "*")
root.add_dependency("b", "*")
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
add_to_repo(repo, "a", "1.0.0", deps={"c": "*"})
add_to_repo(repo, "a", "2.0.0", deps={"c": "*"})
......@@ -133,8 +135,8 @@ def test_traverse_into_package_with_fewer_versions_first(root, provider, repo):
def test_backjump_past_failed_package_on_disjoint_constraint(root, provider, repo):
root.add_dependency("a", "*")
root.add_dependency("foo", ">2.0.0")
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("foo", ">2.0.0"))
add_to_repo(repo, "a", "1.0.0", deps={"foo": "*"}) # ok
add_to_repo(
......
from poetry.factory import Factory
from ..helpers import add_to_repo
from ..helpers import check_solver_result
def test_simple_dependencies(root, provider, repo):
root.add_dependency("a", "1.0.0")
root.add_dependency("b", "1.0.0")
root.add_dependency(Factory.create_dependency("a", "1.0.0"))
root.add_dependency(Factory.create_dependency("b", "1.0.0"))
add_to_repo(repo, "a", "1.0.0", deps={"aa": "1.0.0", "ab": "1.0.0"})
add_to_repo(repo, "b", "1.0.0", deps={"ba": "1.0.0", "bb": "1.0.0"})
......@@ -28,8 +30,8 @@ def test_simple_dependencies(root, provider, repo):
def test_shared_dependencies_with_overlapping_constraints(root, provider, repo):
root.add_dependency("a", "1.0.0")
root.add_dependency("b", "1.0.0")
root.add_dependency(Factory.create_dependency("a", "1.0.0"))
root.add_dependency(Factory.create_dependency("b", "1.0.0"))
add_to_repo(repo, "a", "1.0.0", deps={"shared": ">=2.0.0 <4.0.0"})
add_to_repo(repo, "b", "1.0.0", deps={"shared": ">=3.0.0 <5.0.0"})
......@@ -45,8 +47,8 @@ def test_shared_dependencies_with_overlapping_constraints(root, provider, repo):
def test_shared_dependency_where_dependent_version_affects_other_dependencies(
root, provider, repo
):
root.add_dependency("foo", "<=1.0.2")
root.add_dependency("bar", "1.0.0")
root.add_dependency(Factory.create_dependency("foo", "<=1.0.2"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
add_to_repo(repo, "foo", "1.0.0")
add_to_repo(repo, "foo", "1.0.1", deps={"bang": "1.0.0"})
......@@ -63,7 +65,7 @@ def test_shared_dependency_where_dependent_version_affects_other_dependencies(
def test_circular_dependency(root, provider, repo):
root.add_dependency("foo", "1.0.0")
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "bar", "1.0.0", deps={"foo": "1.0.0"})
......
from poetry.factory import Factory
from ..helpers import add_to_repo
from ..helpers import check_solver_result
def test_dependency_does_not_match_root_python_constraint(root, provider, repo):
provider.set_package_python_versions("^3.6")
root.add_dependency("foo", "*")
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", python="<3.5")
......
from poetry.factory import Factory
from ..helpers import add_to_repo
from ..helpers import check_solver_result
def test_no_version_matching_constraint(root, provider, repo):
root.add_dependency("foo", "^1.0")
root.add_dependency(Factory.create_dependency("foo", "^1.0"))
add_to_repo(repo, "foo", "2.0.0")
add_to_repo(repo, "foo", "2.1.3")
......@@ -19,8 +21,8 @@ def test_no_version_matching_constraint(root, provider, repo):
def test_no_version_that_matches_combined_constraints(root, provider, repo):
root.add_dependency("foo", "1.0.0")
root.add_dependency("bar", "1.0.0")
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
add_to_repo(repo, "foo", "1.0.0", deps={"shared": ">=2.0.0 <3.0.0"})
add_to_repo(repo, "bar", "1.0.0", deps={"shared": ">=2.9.0 <4.0.0"})
......@@ -37,8 +39,8 @@ So, because myapp depends on both foo (1.0.0) and bar (1.0.0), version solving f
def test_disjoint_constraints(root, provider, repo):
root.add_dependency("foo", "1.0.0")
root.add_dependency("bar", "1.0.0")
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("bar", "1.0.0"))
add_to_repo(repo, "foo", "1.0.0", deps={"shared": "<=2.0.0"})
add_to_repo(repo, "bar", "1.0.0", deps={"shared": ">3.0.0"})
......@@ -55,8 +57,8 @@ So, because myapp depends on both foo (1.0.0) and bar (1.0.0), version solving f
def test_disjoint_root_constraints(root, provider, repo):
root.add_dependency("foo", "1.0.0")
root.add_dependency("foo", "2.0.0")
root.add_dependency(Factory.create_dependency("foo", "1.0.0"))
root.add_dependency(Factory.create_dependency("foo", "2.0.0"))
add_to_repo(repo, "foo", "1.0.0")
add_to_repo(repo, "foo", "2.0.0")
......@@ -68,8 +70,8 @@ Because myapp depends on both foo (1.0.0) and foo (2.0.0), version solving faile
def test_no_valid_solution(root, provider, repo):
root.add_dependency("a")
root.add_dependency("b")
root.add_dependency(Factory.create_dependency("a", "*"))
root.add_dependency(Factory.create_dependency("b", "*"))
add_to_repo(repo, "a", "1.0.0", deps={"b": "1.0.0"})
add_to_repo(repo, "a", "2.0.0", deps={"b": "2.0.0"})
......
from poetry.factory import Factory
from ...helpers import get_package
from ..helpers import add_to_repo
from ..helpers import check_solver_result
def test_with_compatible_locked_dependencies(root, provider, repo):
root.add_dependency("foo", "*")
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "foo", "1.0.1", deps={"bar": "1.0.1"})
......@@ -22,7 +24,7 @@ def test_with_compatible_locked_dependencies(root, provider, repo):
def test_with_incompatible_locked_dependencies(root, provider, repo):
root.add_dependency("foo", ">1.0.1")
root.add_dependency(Factory.create_dependency("foo", ">1.0.1"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "foo", "1.0.1", deps={"bar": "1.0.1"})
......@@ -40,7 +42,7 @@ def test_with_incompatible_locked_dependencies(root, provider, repo):
def test_with_unrelated_locked_dependencies(root, provider, repo):
root.add_dependency("foo", "*")
root.add_dependency(Factory.create_dependency("foo", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "foo", "1.0.1", deps={"bar": "1.0.1"})
......@@ -61,8 +63,8 @@ def test_with_unrelated_locked_dependencies(root, provider, repo):
def test_unlocks_dependencies_if_necessary_to_ensure_that_a_new_dependency_is_statisfied(
root, provider, repo
):
root.add_dependency("foo")
root.add_dependency("newdep", "2.0.0")
root.add_dependency(Factory.create_dependency("foo", "*"))
root.add_dependency(Factory.create_dependency("newdep", "2.0.0"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "<2.0.0"})
add_to_repo(repo, "bar", "1.0.0", deps={"baz": "<2.0.0"})
......@@ -94,8 +96,8 @@ def test_unlocks_dependencies_if_necessary_to_ensure_that_a_new_dependency_is_st
def test_with_compatible_locked_dependencies_use_latest(root, provider, repo):
root.add_dependency("foo", "*")
root.add_dependency("baz", "*")
root.add_dependency(Factory.create_dependency("foo", "*"))
root.add_dependency(Factory.create_dependency("baz", "*"))
add_to_repo(repo, "foo", "1.0.0", deps={"bar": "1.0.0"})
add_to_repo(repo, "foo", "1.0.1", deps={"bar": "1.0.1"})
......
......@@ -4,8 +4,10 @@ import tempfile
import pytest
import tomlkit
from poetry.core.packages.package import Package
from poetry.core.packages.project_package import ProjectPackage
from poetry.core.semver.version import Version
from poetry.factory import Factory
from poetry.packages.locker import Locker
from ..helpers import get_dependency
......@@ -28,9 +30,17 @@ def root():
def test_lock_file_data_is_ordered(locker, root):
package_a = get_package("A", "1.0.0")
package_a.add_dependency("B", "^1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a.files = [{"file": "foo", "hash": "456"}, {"file": "bar", "hash": "123"}]
packages = [package_a, get_package("B", "1.2")]
package_git = Package(
"git-package",
"1.2.3",
source_type="git",
source_url="https://github.com/python-poetry/poetry.git",
source_reference="develop",
source_resolved_reference="123456",
)
packages = [package_a, get_package("B", "1.2"), package_git]
locker.set_lock_data(root, packages)
......@@ -38,28 +48,42 @@ def test_lock_file_data_is_ordered(locker, root):
content = f.read()
expected = """[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[package.dependencies]
B = "^1.0"
[[package]]
name = "B"
version = "1.2"
description = ""
category = "main"
optional = false
python-versions = "*"
[[package]]
name = "git-package"
version = "1.2.3"
description = ""
name = "B"
category = "main"
optional = false
python-versions = "*"
version = "1.2"
[package.source]
type = "git"
url = "https://github.com/python-poetry/poetry.git"
reference = "develop"
resolved_reference = "123456"
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = [
......@@ -67,6 +91,7 @@ A = [
{file = "foo", hash = "456"},
]
B = []
git-package = []
"""
assert expected == content
......@@ -75,12 +100,12 @@ B = []
def test_locker_properly_loads_extras(locker):
content = """\
[[package]]
category = "main"
description = "httplib2 caching for requests"
name = "cachecontrol"
version = "0.12.5"
description = "httplib2 caching for requests"
category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
version = "0.12.5"
[package.dependencies]
msgpack = "*"
......@@ -95,9 +120,9 @@ filecache = ["lockfile (>=0.9)"]
redis = ["redis (>=2.10.5)"]
[metadata]
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
lock-version = "1.1"
python-versions = "~2.7 || ^3.4"
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
[metadata.files]
cachecontrol = []
......@@ -127,17 +152,17 @@ def test_lock_packages_with_null_description(locker, root):
content = f.read()
expected = """[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = []
......@@ -148,36 +173,36 @@ A = []
def test_lock_file_should_not_have_mixed_types(locker, root):
package_a = get_package("A", "1.0.0")
package_a.add_dependency("B", "^1.0.0")
package_a.add_dependency("B", {"version": ">=1.0.0", "optional": True})
package_a.add_dependency(Factory.create_dependency("B", "^1.0.0"))
package_a.add_dependency(
Factory.create_dependency("B", {"version": ">=1.0.0", "optional": True})
)
package_a.requires[-1].activate()
package_a.extras["foo"] = [get_dependency("B", ">=1.0.0")]
locker.set_lock_data(root, [package_a])
expected = """[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[package.dependencies]
[[package.dependencies.B]]
version = "^1.0.0"
[[package.dependencies.B]]
optional = true
version = ">=1.0.0"
B = [
{version = "^1.0.0"},
{version = ">=1.0.0", optional = true},
]
[package.extras]
foo = ["B (>=1.0.0)"]
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = []
......@@ -191,12 +216,12 @@ A = []
def test_reading_lock_file_should_raise_an_error_on_invalid_data(locker):
content = u"""[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[package.extras]
foo = ["bar"]
......@@ -205,9 +230,9 @@ foo = ["bar"]
foo = ["bar"]
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = []
......@@ -222,9 +247,13 @@ A = []
def test_locking_legacy_repository_package_should_include_source_section(root, locker):
package_a = get_package("A", "1.0.0")
package_a.source_url = "https://foo.bar"
package_a.source_reference = "legacy"
package_a = Package(
"A",
"1.0.0",
source_type="legacy",
source_url="https://foo.bar",
source_reference="legacy",
)
packages = [package_a]
locker.set_lock_data(root, packages)
......@@ -233,21 +262,22 @@ def test_locking_legacy_repository_package_should_include_source_section(root, l
content = f.read()
expected = """[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[package.source]
reference = "legacy"
type = "legacy"
url = "https://foo.bar"
reference = "legacy"
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = []
......@@ -261,9 +291,9 @@ def test_locker_should_emit_warnings_if_lock_version_is_newer_but_allowed(
):
content = """\
[metadata]
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
lock-version = "{version}"
python-versions = "~2.7 || ^3.4"
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
[metadata.files]
""".format(
......@@ -293,9 +323,9 @@ def test_locker_should_raise_an_error_if_lock_version_is_newer_and_not_allowed(
):
content = """\
[metadata]
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
lock-version = "2.0"
python-versions = "~2.7 || ^3.4"
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
[metadata.files]
"""
......@@ -310,27 +340,29 @@ python-versions = "~2.7 || ^3.4"
def test_extras_dependencies_are_ordered(locker, root):
package_a = get_package("A", "1.0.0")
package_a.add_dependency(
"B", {"version": "^1.0.0", "optional": True, "extras": ["c", "a", "b"]}
Factory.create_dependency(
"B", {"version": "^1.0.0", "optional": True, "extras": ["c", "a", "b"]}
)
)
package_a.requires[-1].activate()
locker.set_lock_data(root, [package_a])
expected = """[[package]]
category = "main"
description = ""
name = "A"
version = "1.0.0"
description = ""
category = "main"
optional = false
python-versions = "*"
version = "1.0.0"
[package.dependencies]
B = {version = "^1.0.0", extras = ["a", "b", "c"], optional = true}
[metadata]
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
lock-version = "1.1"
python-versions = "*"
content-hash = "115cf985d932e9bf5f540555bbdd75decbb62cac81e399375fc19f6277f8c1d8"
[metadata.files]
A = []
......@@ -351,9 +383,9 @@ def test_locker_should_neither_emit_warnings_nor_raise_error_for_lower_compatibl
)
content = """\
[metadata]
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
lock-version = "{version}"
python-versions = "~2.7 || ^3.4"
content-hash = "c3d07fca33fba542ef2b2a4d75bf5b48d892d21a830e2ad9c952ba5123a52f77"
[metadata.files]
""".format(
......
......@@ -54,7 +54,11 @@ def test_search_for_vcs_setup_egg_info(provider):
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -62,17 +66,19 @@ def test_search_for_vcs_setup_egg_info(provider):
def test_search_for_vcs_setup_egg_info_with_extras(provider):
dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git")
dependency.extras.append("foo")
dependency = VCSDependency(
"demo", "git", "https://github.com/demo/demo.git", extras=["foo"]
)
package = provider.search_for_vcs(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -89,7 +95,11 @@ def test_search_for_vcs_read_setup(provider, mocker):
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -100,21 +110,19 @@ def test_search_for_vcs_read_setup(provider, mocker):
def test_search_for_vcs_read_setup_with_extras(provider, mocker):
mocker.patch("poetry.utils.env.EnvManager.get", return_value=MockEnv())
dependency = VCSDependency("demo", "git", "https://github.com/demo/demo.git")
dependency.extras.append("foo")
dependency = VCSDependency(
"demo", "git", "https://github.com/demo/demo.git", extras=["foo"]
)
package = provider.search_for_vcs(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
}
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
def test_search_for_vcs_read_setup_raises_error_if_no_version(provider, mocker):
......@@ -145,7 +153,11 @@ def test_search_for_directory_setup_egg_info(provider, directory):
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -161,17 +173,18 @@ def test_search_for_directory_setup_egg_info_with_extras(provider):
/ "github.com"
/ "demo"
/ "demo",
extras=["foo"],
)
dependency.extras.append("foo")
package = provider.search_for_directory(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -200,7 +213,11 @@ def test_search_for_directory_setup_with_base(provider, directory):
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -233,7 +250,11 @@ def test_search_for_directory_setup_read_setup(provider, mocker):
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -252,17 +273,18 @@ def test_search_for_directory_setup_read_setup_with_extras(provider, mocker):
/ "github.com"
/ "demo"
/ "demo",
extras=["foo"],
)
dependency.extras.append("foo")
package = provider.search_for_directory(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.2"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
]
required = [r for r in package.requires if not r.is_optional()]
optional = [r for r in package.requires if r.is_optional()]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [get_dependency("tomlkit"), get_dependency("cleo")]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -299,7 +321,18 @@ def test_search_for_directory_poetry(provider):
assert package.name == "project-with-extras"
assert package.version.text == "1.2.3"
assert package.requires == []
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == []
assert optional == [
get_dependency("cachy", ">=0.2.0"),
get_dependency("pendulum", ">=1.4.4"),
]
assert package.extras == {
"extras_a": [get_dependency("pendulum", ">=1.4.4")],
"extras_b": [get_dependency("cachy", ">=0.2.0")],
......@@ -310,14 +343,25 @@ def test_search_for_directory_poetry_with_extras(provider):
dependency = DirectoryDependency(
"project-with-extras",
Path(__file__).parent.parent / "fixtures" / "project_with_extras",
extras=["extras_a"],
)
dependency.extras.append("extras_a")
package = provider.search_for_directory(dependency)[0]
assert package.name == "project-with-extras"
assert package.version.text == "1.2.3"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == []
assert optional == [
get_dependency("cachy", ">=0.2.0"),
get_dependency("pendulum", ">=1.4.4"),
]
assert package.extras == {
"extras_a": [get_dependency("pendulum", ">=1.4.4")],
"extras_b": [get_dependency("cachy", ">=0.2.0")],
......@@ -337,7 +381,18 @@ def test_search_for_file_sdist(provider):
assert package.name == "demo"
assert package.version.text == "0.1.0"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [
get_dependency("cleo"),
get_dependency("tomlkit"),
]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -351,16 +406,24 @@ def test_search_for_file_sdist_with_extras(provider):
/ "fixtures"
/ "distributions"
/ "demo-0.1.0.tar.gz",
extras=["foo"],
)
dependency.extras.append("foo")
package = provider.search_for_file(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.0"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [
get_dependency("cleo"),
get_dependency("tomlkit"),
]
assert package.extras == {
"foo": [get_dependency("cleo")],
......@@ -381,7 +444,18 @@ def test_search_for_file_wheel(provider):
assert package.name == "demo"
assert package.version.text == "0.1.0"
assert package.requires == [get_dependency("pendulum", ">=1.4.4")]
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [
get_dependency("cleo"),
get_dependency("tomlkit"),
]
assert package.extras == {
"foo": [get_dependency("cleo")],
"bar": [get_dependency("tomlkit")],
......@@ -395,16 +469,24 @@ def test_search_for_file_wheel_with_extras(provider):
/ "fixtures"
/ "distributions"
/ "demo-0.1.0-py2.py3-none-any.whl",
extras=["foo"],
)
dependency.extras.append("foo")
package = provider.search_for_file(dependency)[0]
assert package.name == "demo"
assert package.version.text == "0.1.0"
assert package.requires == [
get_dependency("pendulum", ">=1.4.4"),
get_dependency("cleo", optional=True),
required = [
r for r in sorted(package.requires, key=lambda r: r.name) if not r.is_optional()
]
optional = [
r for r in sorted(package.requires, key=lambda r: r.name) if r.is_optional()
]
assert required == [get_dependency("pendulum", ">=1.4.4")]
assert optional == [
get_dependency("cleo"),
get_dependency("tomlkit"),
]
assert package.extras == {
"foo": [get_dependency("cleo")],
......
......@@ -2,9 +2,11 @@ import pytest
from clikit.io import NullIO
from poetry.core.packages import Package
from poetry.core.packages import ProjectPackage
from poetry.core.packages import dependency_from_pep_508
from poetry.core.version.markers import parse_marker
from poetry.factory import Factory
from poetry.puzzle import Solver
from poetry.puzzle.exceptions import SolverProblemError
from poetry.puzzle.provider import Provider as BaseProvider
......@@ -87,11 +89,11 @@ def check_solver_result(ops, expected):
result.append({"job": job, "package": op.package, "skipped": op.skipped})
assert result == expected
assert expected == result
def test_solver_install_single(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
repo.add_package(package_a)
......@@ -125,7 +127,7 @@ def test_remove_non_installed(solver, repo, locked):
def test_install_non_existing_package_fail(solver, repo, package):
package.add_dependency("B", "1")
package.add_dependency(Factory.create_dependency("B", "1"))
package_a = get_package("A", "1.0")
repo.add_package(package_a)
......@@ -135,7 +137,7 @@ def test_install_non_existing_package_fail(solver, repo, package):
def test_solver_with_deps(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -159,7 +161,7 @@ def test_solver_with_deps(solver, repo, package):
def test_install_honours_not_equal(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -187,9 +189,9 @@ def test_install_honours_not_equal(solver, repo, package):
def test_install_with_deps_in_order(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency("C")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(Factory.create_dependency("C", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -216,7 +218,7 @@ def test_install_with_deps_in_order(solver, repo, package):
def test_install_installed(solver, repo, installed, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
installed.add_package(package_a)
......@@ -230,7 +232,7 @@ def test_install_installed(solver, repo, installed, package):
def test_update_installed(solver, repo, installed, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
installed.add_package(get_package("A", "1.0"))
......@@ -247,8 +249,8 @@ def test_update_installed(solver, repo, installed, package):
def test_update_with_use_latest(solver, repo, installed, package, locked):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
installed.add_package(get_package("A", "1.0"))
......@@ -276,13 +278,13 @@ def test_update_with_use_latest(solver, repo, installed, package, locked):
def test_solver_sets_categories(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B", category="dev")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*", category="dev"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
package_b.add_dependency("C", "~1.0")
package_b.add_dependency(Factory.create_dependency("C", "~1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -306,8 +308,8 @@ def test_solver_sets_categories(solver, repo, package):
def test_solver_respects_root_package_python_versions(solver, repo, package):
solver.provider.set_package_python_versions("~3.4")
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -316,7 +318,7 @@ def test_solver_respects_root_package_python_versions(solver, repo, package):
package_c.python_versions = "^3.4"
package_c11 = get_package("C", "1.1")
package_c11.python_versions = "^3.6"
package_b.add_dependency("C", "^1.0")
package_b.add_dependency(Factory.create_dependency("C", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -337,15 +339,15 @@ def test_solver_respects_root_package_python_versions(solver, repo, package):
def test_solver_fails_if_mismatch_root_python_versions(solver, repo, package):
solver.provider.set_package_python_versions("^3.4")
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_b.python_versions = "^3.6"
package_c = get_package("C", "1.0")
package_c.python_versions = "~3.3"
package_b.add_dependency("C", "~1.0")
package_b.add_dependency(Factory.create_dependency("C", "~1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -358,15 +360,19 @@ def test_solver_fails_if_mismatch_root_python_versions(solver, repo, package):
def test_solver_solves_optional_and_compatible_packages(solver, repo, package):
solver.provider.set_package_python_versions("~3.4")
package.extras["foo"] = [get_dependency("B")]
package.add_dependency("A", {"version": "*", "python": "^3.4"})
package.add_dependency("B", {"version": "*", "optional": True})
package.add_dependency(
Factory.create_dependency("A", {"version": "*", "python": "^3.4"})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "*", "optional": True})
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_b.python_versions = "^3.3"
package_c = get_package("C", "1.0")
package_c.python_versions = "^3.4"
package_b.add_dependency("C", "^1.0")
package_b.add_dependency(Factory.create_dependency("C", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -385,8 +391,8 @@ def test_solver_solves_optional_and_compatible_packages(solver, repo, package):
def test_solver_does_not_return_extras_if_not_requested(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -410,8 +416,10 @@ def test_solver_does_not_return_extras_if_not_requested(solver, repo, package):
def test_solver_returns_extras_if_requested(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B", {"version": "*", "extras": ["foo"]})
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(
Factory.create_dependency("B", {"version": "*", "extras": ["foo"]})
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -442,9 +450,11 @@ def test_solver_returns_extras_if_requested(solver, repo, package):
def test_solver_returns_prereleases_if_requested(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency("C", {"version": "*", "allow-prereleases": True})
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(
Factory.create_dependency("C", {"version": "*", "allow-prereleases": True})
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -469,9 +479,9 @@ def test_solver_returns_prereleases_if_requested(solver, repo, package):
def test_solver_does_not_return_prereleases_if_not_requested(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency("C")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(Factory.create_dependency("C", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -496,17 +506,19 @@ def test_solver_does_not_return_prereleases_if_not_requested(solver, repo, packa
def test_solver_sub_dependencies_with_requirements(solver, repo, package):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
package_d = get_package("D", "1.0")
package_c.add_dependency("D", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("C")
package_b.add_dependency("D", "^1.0")
package_c.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(Factory.create_dependency("C", "*"))
package_b.add_dependency(Factory.create_dependency("D", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -530,9 +542,15 @@ def test_solver_sub_dependencies_with_requirements(solver, repo, package):
def test_solver_sub_dependencies_with_requirements_complex(solver, repo, package):
package.add_dependency("A", {"version": "^1.0", "python": "<5.0"})
package.add_dependency("B", {"version": "^1.0", "python": "<5.0"})
package.add_dependency("C", {"version": "^1.0", "python": "<4.0"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "<5.0"})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<5.0"})
)
package.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "python": "<4.0"})
)
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
......@@ -541,12 +559,22 @@ def test_solver_sub_dependencies_with_requirements_complex(solver, repo, package
package_e = get_package("E", "1.0")
package_f = get_package("F", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<4.0"})
package_a.add_dependency("D", {"version": "^1.0", "python": "<4.0"})
package_b.add_dependency("E", {"version": "^1.0", "platform": "win32"})
package_b.add_dependency("F", {"version": "^1.0", "python": "<5.0"})
package_c.add_dependency("F", {"version": "^1.0", "python": "<4.0"})
package_d.add_dependency("F")
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<4.0"})
)
package_a.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "python": "<4.0"})
)
package_b.add_dependency(
Factory.create_dependency("E", {"version": "^1.0", "platform": "win32"})
)
package_b.add_dependency(
Factory.create_dependency("F", {"version": "^1.0", "python": "<5.0"})
)
package_c.add_dependency(
Factory.create_dependency("F", {"version": "^1.0", "python": "<4.0"})
)
package_d.add_dependency(Factory.create_dependency("F", "*"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -574,13 +602,15 @@ def test_solver_sub_dependencies_with_not_supported_python_version(
solver, repo, package
):
solver.provider.set_package_python_versions("^3.5")
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_b.python_versions = "<2.0"
package_a.add_dependency("B", {"version": "^1.0", "python": "<2.0"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<2.0"})
)
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -594,18 +624,24 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies(
solver, repo, package
):
solver.provider.set_package_python_versions("^3.5")
package.add_dependency("A")
package.add_dependency("A", {"version": "*", "extras": ["foo"]}, category="dev")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(
Factory.create_dependency(
"A", {"version": "*", "extras": ["foo"]}, category="dev"
)
)
package_a = get_package("A", "1.0")
package_a.extras["foo"] = [get_dependency("C")]
package_a.add_dependency("C", {"version": "^1.0", "optional": True})
package_a.add_dependency("B", {"version": "^1.0"})
package_a.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}))
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
package_d = get_package("D", "1.0")
......@@ -640,24 +676,30 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies(
def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_dependent(
solver, repo, package
):
package.add_dependency("A")
package.add_dependency("E")
package.add_dependency("A", {"version": "*", "extras": ["foo"]}, category="dev")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("E", "*"))
package.add_dependency(
Factory.create_dependency(
"A", {"version": "*", "extras": ["foo"]}, category="dev"
)
)
package_a = get_package("A", "1.0")
package_a.extras["foo"] = [get_dependency("C")]
package_a.add_dependency("C", {"version": "^1.0", "optional": True})
package_a.add_dependency("B", {"version": "^1.0"})
package_a.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "optional": True})
)
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}))
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
package_d = get_package("D", "1.0")
package_e = get_package("E", "1.0")
package_e.add_dependency("A", "^1.0")
package_e.add_dependency(Factory.create_dependency("A", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -692,10 +734,10 @@ def test_solver_with_dependency_in_both_main_and_dev_dependencies_with_one_more_
def test_solver_with_dependency_and_prerelease_sub_dependencies(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", ">=1.0.0.dev2")
package_a.add_dependency(Factory.create_dependency("B", ">=1.0.0.dev2"))
repo.add_package(package_a)
repo.add_package(get_package("B", "0.9.0"))
......@@ -717,14 +759,14 @@ def test_solver_with_dependency_and_prerelease_sub_dependencies(solver, repo, pa
def test_solver_circular_dependency(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", "^1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_b = get_package("B", "1.0")
package_b.add_dependency("A", "^1.0")
package_b.add_dependency("C", "^1.0")
package_b.add_dependency(Factory.create_dependency("A", "^1.0"))
package_b.add_dependency(Factory.create_dependency("C", "^1.0"))
package_c = get_package("C", "1.0")
......@@ -747,19 +789,19 @@ def test_solver_circular_dependency(solver, repo, package):
def test_solver_circular_dependency_chain(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", "^1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_b = get_package("B", "1.0")
package_b.add_dependency("C", "^1.0")
package_b.add_dependency(Factory.create_dependency("C", "^1.0"))
package_c = get_package("C", "1.0")
package_c.add_dependency("D", "^1.0")
package_c.add_dependency(Factory.create_dependency("D", "^1.0"))
package_d = get_package("D", "1.0")
package_d.add_dependency("B", "^1.0")
package_d.add_dependency(Factory.create_dependency("B", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -791,9 +833,9 @@ def test_solver_dense_dependencies(solver, repo, package):
package_ai = get_package("a" + str(i), "1.0")
repo.add_package(package_ai)
packages.append(package_ai)
package.add_dependency("a" + str(i), "^1.0")
package.add_dependency(Factory.create_dependency("a" + str(i), "^1.0"))
for j in range(i):
package_ai.add_dependency("a" + str(j), "^1.0")
package_ai.add_dependency(Factory.create_dependency("a" + str(j), "^1.0"))
ops = solver.solve()
......@@ -803,11 +845,15 @@ def test_solver_dense_dependencies(solver, repo, package):
def test_solver_duplicate_dependencies_same_constraint(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "2.7"})
package_a.add_dependency("B", {"version": "^1.0", "python": ">=3.4"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "2.7"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": ">=3.4"})
)
package_b = get_package("B", "1.0")
......@@ -826,11 +872,15 @@ def test_solver_duplicate_dependencies_same_constraint(solver, repo, package):
def test_solver_duplicate_dependencies_different_constraints(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<3.4"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=3.4"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
......@@ -854,11 +904,11 @@ def test_solver_duplicate_dependencies_different_constraints(solver, repo, packa
def test_solver_duplicate_dependencies_different_constraints_same_requirements(
solver, repo, package
):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0"})
package_a.add_dependency("B", {"version": "^2.0"})
package_a.add_dependency(Factory.create_dependency("B", {"version": "^1.0"}))
package_a.add_dependency(Factory.create_dependency("B", {"version": "^2.0"}))
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
......@@ -879,16 +929,20 @@ So, because no versions of a match !=1.0
def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package):
package.add_dependency("A")
package.add_dependency(Factory.create_dependency("A", "*"))
package_a = get_package("A", "1.0")
package_a.add_dependency("B", {"version": "^1.0", "python": "<3.4"})
package_a.add_dependency("B", {"version": "^2.0", "python": ">=3.4"})
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "<3.4"})
)
package_a.add_dependency(
Factory.create_dependency("B", {"version": "^2.0", "python": ">=3.4"})
)
package_b10 = get_package("B", "1.0")
package_b20 = get_package("B", "2.0")
package_b10.add_dependency("C", "1.2")
package_b20.add_dependency("C", "1.5")
package_b10.add_dependency(Factory.create_dependency("C", "1.2"))
package_b20.add_dependency(Factory.create_dependency("C", "1.5"))
package_c12 = get_package("C", "1.2")
package_c15 = get_package("C", "1.5")
......@@ -914,7 +968,11 @@ def test_solver_duplicate_dependencies_sub_dependencies(solver, repo, package):
def test_solver_fails_if_dependency_name_does_not_match_package(solver, repo, package):
package.add_dependency("my-demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency(
Factory.create_dependency(
"my-demo", {"git": "https://github.com/demo/demo.git"}
)
)
with pytest.raises(RuntimeError):
solver.solve()
......@@ -924,17 +982,17 @@ def test_solver_does_not_get_stuck_in_recursion_on_circular_dependency(
solver, repo, package
):
package_a = get_package("A", "1.0")
package_a.add_dependency("B", "^1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_b = get_package("B", "1.0")
package_b.add_dependency("C", "^1.0")
package_b.add_dependency(Factory.create_dependency("C", "^1.0"))
package_c = get_package("C", "1.0")
package_c.add_dependency("B", "^1.0")
package_c.add_dependency(Factory.create_dependency("B", "^1.0"))
repo.add_package(package_a)
repo.add_package(package_b)
repo.add_package(package_c)
package.add_dependency("A", "^1.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
ops = solver.solve()
......@@ -954,14 +1012,20 @@ def test_solver_can_resolve_git_dependencies(solver, repo, package):
repo.add_package(pendulum)
repo.add_package(cleo)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
)
ops = solver.solve()
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
check_solver_result(
ops,
......@@ -971,7 +1035,8 @@ def test_solver_can_resolve_git_dependencies(solver, repo, package):
op = ops[1]
assert op.package.source_type == "git"
assert op.package.source_reference.startswith("9cf87a2")
assert op.package.source_reference == "master"
assert op.package.source_resolved_reference.startswith("9cf87a2")
def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package):
......@@ -981,15 +1046,21 @@ def test_solver_can_resolve_git_dependencies_with_extras(solver, repo, package):
repo.add_package(cleo)
package.add_dependency(
"demo", {"git": "https://github.com/demo/demo.git", "extras": ["foo"]}
Factory.create_dependency(
"demo", {"git": "https://github.com/demo/demo.git", "extras": ["foo"]}
)
)
ops = solver.solve()
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
check_solver_result(
ops,
......@@ -1012,14 +1083,18 @@ def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref
repo.add_package(pendulum)
repo.add_package(cleo)
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference=ref[list(ref.keys())[0]],
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
git_config = {demo.source_type: demo.source_url}
git_config.update(ref)
package.add_dependency("demo", git_config)
package.add_dependency(Factory.create_dependency("demo", git_config))
ops = solver.solve()
......@@ -1031,14 +1106,17 @@ def test_solver_can_resolve_git_dependencies_with_ref(solver, repo, package, ref
op = ops[1]
assert op.package.source_type == "git"
assert op.package.source_reference.startswith("9cf87a2")
assert op.package.source_reference == ref[list(ref.keys())[0]]
assert op.package.source_resolved_reference.startswith("9cf87a2")
def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requirement_is_compatible(
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency("A", {"version": "^1.0", "python": "^3.6"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"})
)
package_a = get_package("A", "1.0.0")
package_a.python_versions = ">=3.6"
......@@ -1054,12 +1132,16 @@ def test_solver_does_not_trigger_conflict_for_python_constraint_if_python_requir
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency("A", {"version": "^1.0", "python": "^3.6"})
package.add_dependency("B", {"version": "^1.0", "python": "^3.5.3"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"})
)
package.add_dependency(
Factory.create_dependency("B", {"version": "^1.0", "python": "^3.5.3"})
)
package_a = get_package("A", "1.0.0")
package_a.python_versions = ">=3.6"
package_a.add_dependency("B", "^1.0")
package_a.add_dependency(Factory.create_dependency("B", "^1.0"))
package_b = get_package("B", "1.0.0")
package_b.python_versions = ">=3.5.3"
......@@ -1082,7 +1164,9 @@ def test_solver_triggers_conflict_for_dependency_python_not_fully_compatible_wit
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency("A", {"version": "^1.0", "python": "^3.5"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"})
)
package_a = get_package("A", "1.0.0")
package_a.python_versions = ">=3.6"
......@@ -1097,7 +1181,9 @@ def test_solver_finds_compatible_package_for_dependency_python_not_fully_compati
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency("A", {"version": "^1.0", "python": "^3.5"})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.5"})
)
package_a101 = get_package("A", "1.0.1")
package_a101.python_versions = ">=3.6"
......@@ -1121,7 +1207,9 @@ def test_solver_does_not_trigger_new_resolution_on_duplicate_dependencies_if_onl
dep2 = dependency_from_pep_508('B (>=2.0); extra == "bar"')
dep2.activate()
package.add_dependency("A", {"version": "^1.0", "extras": ["foo", "bar"]})
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "extras": ["foo", "bar"]})
)
package_a = get_package("A", "1.0.0")
package_a.extras = {"foo": [dep1], "bar": [dep2]}
......@@ -1153,8 +1241,10 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.4")
package.add_dependency("A", {"version": "^1.0", "python": "^3.6"})
package.add_dependency("B", "^1.0")
package.add_dependency(
Factory.create_dependency("A", {"version": "^1.0", "python": "^3.6"})
)
package.add_dependency(Factory.create_dependency("B", "^1.0"))
package_a = get_package("A", "1.0.0")
package_a.python_versions = ">=3.6"
......@@ -1182,19 +1272,23 @@ def test_solver_does_not_raise_conflict_for_locked_conditional_dependencies(
def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_package(
solver, repo, package
):
package.add_dependency("A")
package.add_dependency("B")
package.add_dependency("C")
package.add_dependency(Factory.create_dependency("A", "*"))
package.add_dependency(Factory.create_dependency("B", "*"))
package.add_dependency(Factory.create_dependency("C", "*"))
package_a = get_package("A", "1.0")
package_b = get_package("B", "1.0")
package_c = get_package("C", "1.0")
package_d = get_package("D", "1.0")
package_b.add_dependency("C", {"version": "^1.0", "extras": ["foo"]})
package_b.add_dependency(
Factory.create_dependency("C", {"version": "^1.0", "extras": ["foo"]})
)
package_c.add_dependency("D", {"version": "^1.0", "optional": True})
package_c.extras = {"foo": [get_dependency("D", "^1.0")]}
package_c.add_dependency(
Factory.create_dependency("D", {"version": "^1.0", "optional": True})
)
package_c.extras = {"foo": [Factory.create_dependency("D", "^1.0")]}
repo.add_package(package_a)
repo.add_package(package_b)
......@@ -1217,13 +1311,13 @@ def test_solver_returns_extras_if_requested_in_dependencies_and_not_in_root_pack
def test_solver_should_not_resolve_prerelease_version_if_not_requested(
solver, repo, package
):
package.add_dependency("A", "~1.8.0")
package.add_dependency("B", "^0.5.0")
package.add_dependency(Factory.create_dependency("A", "~1.8.0"))
package.add_dependency(Factory.create_dependency("B", "^0.5.0"))
package_a185 = get_package("A", "1.8.5")
package_a19b1 = get_package("A", "1.9b1")
package_b = get_package("B", "0.5.0")
package_b.add_dependency("A", ">=1.9b1")
package_b.add_dependency(Factory.create_dependency("A", ">=1.9b1"))
repo.add_package(package_a185)
repo.add_package(package_a19b1)
......@@ -1237,8 +1331,8 @@ def test_solver_ignores_dependencies_with_incompatible_python_full_version_marke
solver, repo, package
):
solver.provider.set_package_python_versions("^3.6")
package.add_dependency("A", "^1.0")
package.add_dependency("B", "^2.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package.add_dependency(Factory.create_dependency("B", "^2.0"))
package_a = get_package("A", "1.0.0")
package_a.requires.append(
......@@ -1271,21 +1365,30 @@ def test_solver_git_dependencies_update(solver, repo, package, installed):
repo.add_package(pendulum)
repo.add_package(cleo)
demo_installed = get_package("demo", "0.1.2")
demo_installed.source_type = "git"
demo_installed.source_url = "https://github.com/demo/demo.git"
demo_installed.source_reference = "123456"
demo_installed = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="123456",
)
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
installed.add_package(demo_installed)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
)
ops = solver.solve()
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
check_solver_result(
ops,
[
......@@ -1298,8 +1401,9 @@ def test_solver_git_dependencies_update(solver, repo, package, installed):
assert op.job_type == "update"
assert op.package.source_type == "git"
assert op.package.source_reference.startswith("9cf87a2")
assert op.initial_package.source_reference == "123456"
assert op.package.source_reference == "master"
assert op.package.source_resolved_reference.startswith("9cf87a2")
assert op.initial_package.source_resolved_reference == "123456"
def test_solver_git_dependencies_update_skipped(solver, repo, package, installed):
......@@ -1308,13 +1412,19 @@ def test_solver_git_dependencies_update_skipped(solver, repo, package, installed
repo.add_package(pendulum)
repo.add_package(cleo)
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
installed.add_package(demo)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
)
ops = solver.solve()
......@@ -1335,14 +1445,20 @@ def test_solver_git_dependencies_short_hash_update_skipped(
repo.add_package(pendulum)
repo.add_package(cleo)
demo = get_package("demo", "0.1.2")
demo.source_type = "git"
demo.source_url = "https://github.com/demo/demo.git"
demo.source_reference = "9cf87a285a2d3fbb0b9fa621997b3acc3631ed24"
demo = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
)
installed.add_package(demo)
package.add_dependency(
"demo", {"git": "https://github.com/demo/demo.git", "rev": "9cf87a2"}
Factory.create_dependency(
"demo", {"git": "https://github.com/demo/demo.git", "rev": "9cf87a2"}
)
)
ops = solver.solve()
......@@ -1351,7 +1467,18 @@ def test_solver_git_dependencies_short_hash_update_skipped(
ops,
[
{"job": "install", "package": pendulum},
{"job": "install", "package": demo, "skipped": True},
{
"job": "install",
"package": Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
source_resolved_reference="9cf87a285a2d3fbb0b9fa621997b3acc3631ed24",
),
"skipped": True,
},
],
)
......@@ -1369,13 +1496,11 @@ def test_solver_can_resolve_directory_dependencies(solver, repo, package):
/ "demo"
).as_posix()
package.add_dependency("demo", {"path": path})
package.add_dependency(Factory.create_dependency("demo", {"path": path}))
ops = solver.solve()
demo = get_package("demo", "0.1.2")
demo.source_type = "directory"
demo.source_url = path
demo = Package("demo", "0.1.2", source_type="directory", source_url=path)
check_solver_result(
ops,
......@@ -1405,13 +1530,13 @@ def test_solver_can_resolve_directory_dependencies_with_extras(solver, repo, pac
/ "demo"
).as_posix()
package.add_dependency("demo", {"path": path, "extras": ["foo"]})
package.add_dependency(
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]})
)
ops = solver.solve()
demo = get_package("demo", "0.1.2")
demo.source_type = "directory"
demo.source_url = path
demo = Package("demo", "0.1.2", source_type="directory", source_url=path)
check_solver_result(
ops,
......@@ -1441,13 +1566,11 @@ def test_solver_can_resolve_sdist_dependencies(solver, repo, package):
/ "demo-0.1.0.tar.gz"
).as_posix()
package.add_dependency("demo", {"path": path})
package.add_dependency(Factory.create_dependency("demo", {"path": path}))
ops = solver.solve()
demo = get_package("demo", "0.1.0")
demo.source_type = "file"
demo.source_url = path
demo = Package("demo", "0.1.0", source_type="file", source_url=path)
check_solver_result(
ops,
......@@ -1475,13 +1598,13 @@ def test_solver_can_resolve_sdist_dependencies_with_extras(solver, repo, package
/ "demo-0.1.0.tar.gz"
).as_posix()
package.add_dependency("demo", {"path": path, "extras": ["foo"]})
package.add_dependency(
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]})
)
ops = solver.solve()
demo = get_package("demo", "0.1.0")
demo.source_type = "file"
demo.source_url = path
demo = Package("demo", "0.1.0", source_type="file", source_url=path)
check_solver_result(
ops,
......@@ -1511,13 +1634,11 @@ def test_solver_can_resolve_wheel_dependencies(solver, repo, package):
/ "demo-0.1.0-py2.py3-none-any.whl"
).as_posix()
package.add_dependency("demo", {"path": path})
package.add_dependency(Factory.create_dependency("demo", {"path": path}))
ops = solver.solve()
demo = get_package("demo", "0.1.0")
demo.source_type = "file"
demo.source_url = path
demo = Package("demo", "0.1.0", source_type="file", source_url=path)
check_solver_result(
ops,
......@@ -1545,13 +1666,13 @@ def test_solver_can_resolve_wheel_dependencies_with_extras(solver, repo, package
/ "demo-0.1.0-py2.py3-none-any.whl"
).as_posix()
package.add_dependency("demo", {"path": path, "extras": ["foo"]})
package.add_dependency(
Factory.create_dependency("demo", {"path": path, "extras": ["foo"]})
)
ops = solver.solve()
demo = get_package("demo", "0.1.0")
demo.source_type = "file"
demo.source_url = path
demo = Package("demo", "0.1.0", source_type="file", source_url=path)
check_solver_result(
ops,
......@@ -1578,15 +1699,33 @@ def test_solver_can_solve_with_legacy_repository_using_proper_dists(
solver = Solver(package, pool, installed, locked, io)
package.add_dependency("isort", "4.3.4")
package.add_dependency(Factory.create_dependency("isort", "4.3.4"))
ops = solver.solve()
check_solver_result(
ops,
[
{"job": "install", "package": get_package("futures", "3.2.0")},
{"job": "install", "package": get_package("isort", "4.3.4")},
{
"job": "install",
"package": Package(
"futures",
"3.2.0",
source_type="legacy",
source_url=repo.url,
source_reference=repo.name,
),
},
{
"job": "install",
"package": Package(
"isort",
"4.3.4",
source_type="legacy",
source_url=repo.url,
source_reference=repo.name,
),
},
],
)
......@@ -1604,12 +1743,24 @@ def test_solver_can_solve_with_legacy_repository_using_proper_python_compatible_
solver = Solver(package, pool, installed, locked, io)
package.add_dependency("isort", "4.3.4")
package.add_dependency(Factory.create_dependency("isort", "4.3.4"))
ops = solver.solve()
check_solver_result(
ops, [{"job": "install", "package": get_package("isort", "4.3.4")}]
ops,
[
{
"job": "install",
"package": Package(
"isort",
"4.3.4",
source_type="legacy",
source_url=repo.url,
source_reference=repo.name,
),
}
],
)
......@@ -1621,7 +1772,7 @@ def test_solver_skips_invalid_versions(package, installed, locked, io):
solver = Solver(package, pool, installed, locked, io)
package.add_dependency("trackpy", "^0.4")
package.add_dependency(Factory.create_dependency("trackpy", "^0.4"))
ops = solver.solve()
......@@ -1631,8 +1782,12 @@ def test_solver_skips_invalid_versions(package, installed, locked, io):
def test_multiple_constraints_on_root(package, solver, repo):
package.add_dependency("foo", {"version": "^1.0", "python": "^2.7"})
package.add_dependency("foo", {"version": "^2.0", "python": "^3.7"})
package.add_dependency(
Factory.create_dependency("foo", {"version": "^1.0", "python": "^2.7"})
)
package.add_dependency(
Factory.create_dependency("foo", {"version": "^2.0", "python": "^3.7"})
)
foo15 = get_package("foo", "1.5.0")
foo25 = get_package("foo", "2.5.0")
......@@ -1652,7 +1807,7 @@ def test_solver_chooses_most_recent_version_amongst_repositories(
package, installed, locked, io
):
package.python_versions = "^3.7"
package.add_dependency("tomlkit", {"version": "^0.5"})
package.add_dependency(Factory.create_dependency("tomlkit", {"version": "^0.5"}))
repo = MockLegacyRepository()
pool = Pool([repo, MockPyPIRepository()])
......@@ -1665,15 +1820,17 @@ def test_solver_chooses_most_recent_version_amongst_repositories(
ops, [{"job": "install", "package": get_package("tomlkit", "0.5.3")}]
)
assert "" == ops[0].package.source_type
assert "" == ops[0].package.source_url
assert ops[0].package.source_type is None
assert ops[0].package.source_url is None
def test_solver_chooses_from_correct_repository_if_forced(
package, installed, locked, io
):
package.python_versions = "^3.7"
package.add_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
package.add_dependency(
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
)
repo = MockLegacyRepository()
pool = Pool([repo, MockPyPIRepository()])
......@@ -1683,7 +1840,19 @@ def test_solver_chooses_from_correct_repository_if_forced(
ops = solver.solve()
check_solver_result(
ops, [{"job": "install", "package": get_package("tomlkit", "0.5.2")}]
ops,
[
{
"job": "install",
"package": Package(
"tomlkit",
"0.5.2",
source_type="legacy",
source_url=repo.url,
source_reference=repo.name,
),
}
],
)
assert "http://legacy.foo.bar" == ops[0].package.source_url
......@@ -1693,12 +1862,14 @@ def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende
package, installed, locked, io
):
package.python_versions = "^3.7"
package.add_dependency("foo", "^1.0")
package.add_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
package.add_dependency(Factory.create_dependency("foo", "^1.0"))
package.add_dependency(
Factory.create_dependency("tomlkit", {"version": "^0.5", "source": "legacy"})
)
repo = Repository()
foo = get_package("foo", "1.0.0")
foo.add_dependency("tomlkit", "^0.5.0")
foo.add_dependency(Factory.create_dependency("tomlkit", "^0.5.0"))
repo.add_package(foo)
pool = Pool([MockLegacyRepository(), repo, MockPyPIRepository()])
......@@ -1709,22 +1880,31 @@ def test_solver_chooses_from_correct_repository_if_forced_and_transitive_depende
check_solver_result(
ops,
[
{"job": "install", "package": get_package("tomlkit", "0.5.2")},
{
"job": "install",
"package": Package(
"tomlkit",
"0.5.2",
source_type="legacy",
source_url="http://legacy.foo.bar",
source_reference="legacy",
),
},
{"job": "install", "package": foo},
],
)
assert "http://legacy.foo.bar" == ops[0].package.source_url
assert "" == ops[1].package.source_type
assert "" == ops[1].package.source_url
assert ops[1].package.source_type is None
assert ops[1].package.source_url is None
def test_solver_does_not_choose_from_secondary_repository_by_default(
package, installed, locked, io
):
package.python_versions = "^3.7"
package.add_dependency("clikit", {"version": "^0.2.0"})
package.add_dependency(Factory.create_dependency("clikit", {"version": "^0.2.0"}))
pool = Pool()
pool.add_repository(MockPyPIRepository(), secondary=True)
......@@ -1737,21 +1917,41 @@ def test_solver_does_not_choose_from_secondary_repository_by_default(
check_solver_result(
ops,
[
{"job": "install", "package": get_package("pastel", "0.1.0")},
{
"job": "install",
"package": Package(
"pastel",
"0.1.0",
source_type="legacy",
source_url="http://legacy.foo.bar",
source_reference="legacy",
),
},
{"job": "install", "package": get_package("pylev", "1.3.0")},
{"job": "install", "package": get_package("clikit", "0.2.4")},
{
"job": "install",
"package": Package(
"clikit",
"0.2.4",
source_type="legacy",
source_url="http://legacy.foo.bar",
source_reference="legacy",
),
},
],
)
assert "http://legacy.foo.bar" == ops[0].package.source_url
assert "" == ops[1].package.source_type
assert "" == ops[1].package.source_url
assert ops[1].package.source_type is None
assert ops[1].package.source_url is None
assert "http://legacy.foo.bar" == ops[2].package.source_url
def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, io):
package.python_versions = "^3.7"
package.add_dependency("clikit", {"version": "^0.2.0", "source": "PyPI"})
package.add_dependency(
Factory.create_dependency("clikit", {"version": "^0.2.0", "source": "PyPI"})
)
pool = Pool()
pool.add_repository(MockPyPIRepository(), secondary=True)
......@@ -1764,17 +1964,26 @@ def test_solver_chooses_from_secondary_if_explicit(package, installed, locked, i
check_solver_result(
ops,
[
{"job": "install", "package": get_package("pastel", "0.1.0")},
{
"job": "install",
"package": Package(
"pastel",
"0.1.0",
source_type="legacy",
source_url="http://legacy.foo.bar",
source_reference="legacy",
),
},
{"job": "install", "package": get_package("pylev", "1.3.0")},
{"job": "install", "package": get_package("clikit", "0.2.4")},
],
)
assert "http://legacy.foo.bar" == ops[0].package.source_url
assert "" == ops[1].package.source_type
assert "" == ops[1].package.source_url
assert "" == ops[2].package.source_type
assert "" == ops[2].package.source_url
assert ops[1].package.source_type is None
assert ops[1].package.source_url is None
assert ops[2].package.source_type is None
assert ops[2].package.source_url is None
def test_solver_discards_packages_with_empty_markers(
......@@ -1782,14 +1991,18 @@ def test_solver_discards_packages_with_empty_markers(
):
package.python_versions = "~2.7 || ^3.4"
package.add_dependency(
"a", {"version": "^0.1.0", "markers": "python_version >= '3.4'"}
Factory.create_dependency(
"a", {"version": "^0.1.0", "markers": "python_version >= '3.4'"}
)
)
package_a = get_package("a", "0.1.0")
package_a.add_dependency(
"b", {"version": "^0.1.0", "markers": "python_version < '3.2'"}
Factory.create_dependency(
"b", {"version": "^0.1.0", "markers": "python_version < '3.2'"}
)
)
package_a.add_dependency("c", "^0.2.0")
package_a.add_dependency(Factory.create_dependency("c", "^0.2.0"))
package_b = get_package("b", "0.1.0")
package_c = get_package("c", "0.2.0")
repo.add_package(package_a)
......@@ -1813,8 +2026,16 @@ def test_solver_does_not_raise_conflict_for_conditional_dev_dependencies(
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency("A", {"version": "^1.0", "python": "~2.7"}, category="dev")
package.add_dependency("A", {"version": "^2.0", "python": "^3.5"}, category="dev")
package.add_dependency(
Factory.create_dependency(
"A", {"version": "^1.0", "python": "~2.7"}, category="dev"
)
)
package.add_dependency(
Factory.create_dependency(
"A", {"version": "^2.0", "python": "^3.5"}, category="dev"
)
)
package_a100 = get_package("A", "1.0.0")
package_a200 = get_package("A", "2.0.0")
......@@ -1837,12 +2058,18 @@ def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras(
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency("requests", {"version": "^2.22.0", "extras": ["security"]})
package.add_dependency(
Factory.create_dependency(
"requests", {"version": "^2.22.0", "extras": ["security"]}
)
)
requests = get_package("requests", "2.22.0")
requests.add_dependency("idna", ">=2.5,<2.9")
requests.add_dependency(Factory.create_dependency("idna", ">=2.5,<2.9"))
requests.add_dependency(
"idna", {"version": ">=2.0.0", "markers": "extra == 'security'"}
Factory.create_dependency(
"idna", {"version": ">=2.0.0", "markers": "extra == 'security'"}
)
)
requests.extras["security"] = [get_dependency("idna", ">=2.0.0")]
idna = get_package("idna", "2.8")
......@@ -1861,13 +2088,19 @@ def test_solver_does_not_loop_indefinitely_on_duplicate_constraints_with_extras(
def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies(
solver, repo, package, locked, pool, installed, io
):
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency("a", "^1.2.3")
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
)
package.add_dependency(Factory.create_dependency("a", "^1.2.3"))
git_package = get_package("demo", "0.1.2")
git_package.source_type = "git"
git_package.source_url = "https://github.com/demo/demo.git"
git_package.source_reference = "commit"
git_package = Package(
"demo",
"0.1.2",
source_type="git",
source_url="https://github.com/demo/demo.git",
source_reference="master",
source_resolved_reference="commit",
)
installed.add_package(git_package)
......@@ -1875,6 +2108,7 @@ def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies(
locked.add_package(git_package)
repo.add_package(get_package("a", "1.2.3"))
repo.add_package(Package("pendulum", "2.1.2"))
solver = Solver(package, pool, installed, locked, io)
......@@ -1891,9 +2125,15 @@ def test_solver_does_not_fail_with_locked_git_and_non_git_dependencies(
def test_ignore_python_constraint_no_overlap_dependencies(solver, repo, package):
pytest = get_package("demo", "1.0.0")
pytest.add_dependency("configparser", {"version": "^1.2.3", "python": "<3.2"})
pytest.add_dependency(
Factory.create_dependency(
"configparser", {"version": "^1.2.3", "python": "<3.2"}
)
)
package.add_dependency("demo", {"version": "^1.0.0", "python": "^3.6"})
package.add_dependency(
Factory.create_dependency("demo", {"version": "^1.0.0", "python": "^3.6"})
)
repo.add_package(pytest)
repo.add_package(get_package("configparser", "1.2.3"))
......@@ -1909,12 +2149,14 @@ def test_solver_should_not_go_into_an_infinite_loop_on_duplicate_dependencies(
solver, repo, package
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency("A", "^1.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
package_a = get_package("A", "1.0.0")
package_a.add_dependency("B")
package_a.add_dependency(Factory.create_dependency("B", "*"))
package_a.add_dependency(
"B", {"version": "^1.0", "markers": "implementation_name == 'pypy'"}
Factory.create_dependency(
"B", {"version": "^1.0", "markers": "implementation_name == 'pypy'"}
)
)
package_b20 = get_package("B", "2.0.0")
......@@ -1964,7 +2206,7 @@ def test_solver_cannot_choose_another_version_for_directory_dependencies(
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.1.0")
foo = get_package("foo", "1.2.3")
foo.add_dependency("demo", "<0.1.2")
foo.add_dependency(Factory.create_dependency("demo", "<0.1.2"))
repo.add_package(foo)
repo.add_package(demo)
repo.add_package(pendulum)
......@@ -1978,8 +2220,8 @@ def test_solver_cannot_choose_another_version_for_directory_dependencies(
/ "demo"
).as_posix()
package.add_dependency("demo", {"path": path})
package.add_dependency("foo", "^1.2.3")
package.add_dependency(Factory.create_dependency("demo", {"path": path}))
package.add_dependency(Factory.create_dependency("foo", "^1.2.3"))
# This is not solvable since the demo version is pinned
# via the directory dependency
......@@ -1993,7 +2235,7 @@ def test_solver_cannot_choose_another_version_for_file_dependencies(
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.0.8")
foo = get_package("foo", "1.2.3")
foo.add_dependency("demo", "<0.1.0")
foo.add_dependency(Factory.create_dependency("demo", "<0.1.0"))
repo.add_package(foo)
repo.add_package(demo)
repo.add_package(pendulum)
......@@ -2005,8 +2247,8 @@ def test_solver_cannot_choose_another_version_for_file_dependencies(
/ "demo-0.1.0-py2.py3-none-any.whl"
).as_posix()
package.add_dependency("demo", {"path": path})
package.add_dependency("foo", "^1.2.3")
package.add_dependency(Factory.create_dependency("demo", {"path": path}))
package.add_dependency(Factory.create_dependency("foo", "^1.2.3"))
# This is not solvable since the demo version is pinned
# via the file dependency
......@@ -2020,13 +2262,15 @@ def test_solver_cannot_choose_another_version_for_git_dependencies(
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.0.8")
foo = get_package("foo", "1.2.3")
foo.add_dependency("demo", "<0.1.0")
foo.add_dependency(Factory.create_dependency("demo", "<0.1.0"))
repo.add_package(foo)
repo.add_package(demo)
repo.add_package(pendulum)
package.add_dependency("demo", {"git": "https://github.com/demo/demo.git"})
package.add_dependency("foo", "^1.2.3")
package.add_dependency(
Factory.create_dependency("demo", {"git": "https://github.com/demo/demo.git"})
)
package.add_dependency(Factory.create_dependency("foo", "^1.2.3"))
# This is not solvable since the demo version is pinned
# via the file dependency
......@@ -2053,15 +2297,18 @@ def test_solver_cannot_choose_another_version_for_url_dependencies(
pendulum = get_package("pendulum", "2.0.3")
demo = get_package("demo", "0.0.8")
foo = get_package("foo", "1.2.3")
foo.add_dependency("demo", "<0.1.0")
foo.add_dependency(Factory.create_dependency("demo", "<0.1.0"))
repo.add_package(foo)
repo.add_package(demo)
repo.add_package(pendulum)
package.add_dependency(
"demo", {"url": "https://foo.bar/distributions/demo-0.1.0-py2.py3-none-any.whl"}
Factory.create_dependency(
"demo",
{"url": "https://foo.bar/distributions/demo-0.1.0-py2.py3-none-any.whl"},
)
)
package.add_dependency("foo", "^1.2.3")
package.add_dependency(Factory.create_dependency("foo", "^1.2.3"))
# This is not solvable since the demo version is pinned
# via the git dependency
......@@ -2072,12 +2319,15 @@ def test_solver_cannot_choose_another_version_for_url_dependencies(
def test_solver_should_not_update_same_version_packages_if_installed_has_no_source_type(
solver, repo, package, installed
):
package.add_dependency("foo", "1.0.0")
package.add_dependency(Factory.create_dependency("foo", "1.0.0"))
foo = get_package("foo", "1.0.0")
foo.source_type = "legacy"
foo.source_reference = "custom"
foo.source_url = "https://foo.bar"
foo = Package(
"foo",
"1.0.0",
source_type="legacy",
source_url="https://foo.bar",
source_reference="custom",
)
repo.add_package(foo)
installed.add_package(get_package("foo", "1.0.0"))
......@@ -2090,10 +2340,14 @@ def test_solver_should_use_the_python_constraint_from_the_environment_if_availab
solver, repo, package, installed
):
solver.provider.set_package_python_versions("~2.7 || ^3.5")
package.add_dependency("A", "^1.0")
package.add_dependency(Factory.create_dependency("A", "^1.0"))
a = get_package("A", "1.0.0")
a.add_dependency("B", {"version": "^1.0.0", "markers": 'python_version < "3.2"'})
a.add_dependency(
Factory.create_dependency(
"B", {"version": "^1.0.0", "markers": 'python_version < "3.2"'}
)
)
b = get_package("B", "1.0.0")
b.python_versions = ">=2.6, <3"
......@@ -2113,16 +2367,24 @@ def test_solver_should_resolve_all_versions_for_multiple_duplicate_dependencies(
):
package.python_versions = "~2.7 || ^3.5"
package.add_dependency(
"A", {"version": "^1.0", "markers": "python_version < '3.5'"}
Factory.create_dependency(
"A", {"version": "^1.0", "markers": "python_version < '3.5'"}
)
)
package.add_dependency(
"A", {"version": "^2.0", "markers": "python_version >= '3.5'"}
Factory.create_dependency(
"A", {"version": "^2.0", "markers": "python_version >= '3.5'"}
)
)
package.add_dependency(
"B", {"version": "^3.0", "markers": "python_version < '3.5'"}
Factory.create_dependency(
"B", {"version": "^3.0", "markers": "python_version < '3.5'"}
)
)
package.add_dependency(
"B", {"version": "^4.0", "markers": "python_version >= '3.5'"}
Factory.create_dependency(
"B", {"version": "^4.0", "markers": "python_version >= '3.5'"}
)
)
package_a10 = get_package("A", "1.0.0")
......@@ -2153,7 +2415,9 @@ def test_solver_should_not_raise_errors_for_irrelevant_python_constraints(
):
package.python_versions = "^3.6"
solver.provider.set_package_python_versions("^3.6")
package.add_dependency("dataclasses", {"version": "^0.7", "python": "<3.7"})
package.add_dependency(
Factory.create_dependency("dataclasses", {"version": "^0.7", "python": "<3.7"})
)
dataclasses = get_package("dataclasses", "0.7")
dataclasses.python_versions = ">=3.6, <3.7"
......@@ -2162,3 +2426,40 @@ def test_solver_should_not_raise_errors_for_irrelevant_python_constraints(
ops = solver.solve()
check_solver_result(ops, [{"job": "install", "package": dataclasses}])
def test_solver_can_resolve_transitive_extras(solver, repo, package):
package.add_dependency(Factory.create_dependency("requests", "^2.24.0"))
package.add_dependency(Factory.create_dependency("PyOTA", "^2.1.0"))
requests = get_package("requests", "2.24.0")
requests.add_dependency(Factory.create_dependency("certifi", ">=2017.4.17"))
dep = get_dependency("PyOpenSSL", ">=0.14")
dep.in_extras.append("security")
requests.add_dependency(
Factory.create_dependency("PyOpenSSL", {"version": ">=0.14", "optional": True})
)
requests.extras["security"] = [dep]
pyota = get_package("PyOTA", "2.1.0")
pyota.add_dependency(
Factory.create_dependency(
"requests", {"version": ">=2.24.0", "extras": ["security"]}
)
)
repo.add_package(requests)
repo.add_package(pyota)
repo.add_package(get_package("certifi", "2017.4.17"))
repo.add_package(get_package("pyopenssl", "0.14"))
ops = solver.solve()
check_solver_result(
ops,
[
{"job": "install", "package": get_package("certifi", "2017.4.17")},
{"job": "install", "package": get_package("pyopenssl", "0.14")},
{"job": "install", "package": requests},
{"job": "install", "package": pyota},
],
)
......@@ -156,5 +156,5 @@ def test_load_editable_with_import_package(repository):
assert editable is not None
assert editable.name == "editable-with-import"
assert editable.version.text == "2.3.4"
assert editable.source_type == ""
assert editable.source_url == ""
assert editable.source_type is None
assert editable.source_url is None
......@@ -3,6 +3,7 @@ import shutil
import pytest
from poetry.core.packages import Dependency
from poetry.factory import Factory
from poetry.repositories.auth import Auth
from poetry.repositories.exceptions import PackageNotFound
from poetry.repositories.exceptions import RepositoryError
......@@ -117,7 +118,10 @@ def test_get_package_information_skips_dependencies_with_invalid_constraints():
package.description == "Python Language Server for the Language Server Protocol"
)
assert sorted(package.requires, key=lambda r: r.name) == [
assert 19 == len(package.requires)
assert sorted(
[r for r in package.requires if not r.is_optional()], key=lambda r: r.name
) == [
Dependency("configparser", "*"),
Dependency("future", ">=0.14.0"),
Dependency("futures", "*"),
......@@ -142,7 +146,7 @@ def test_get_package_information_skips_dependencies_with_invalid_constraints():
def test_find_packages_no_prereleases():
repo = MockRepository()
packages = repo.find_packages("pyyaml")
packages = repo.find_packages(Factory.create_dependency("pyyaml", "*"))
assert len(packages) == 1
......@@ -154,7 +158,7 @@ def test_find_packages_no_prereleases():
@pytest.mark.parametrize("constraint,count", [("*", 1), (">=1", 0), (">=19.0.0a0", 1)])
def test_find_packages_only_prereleases(constraint, count):
repo = MockRepository()
packages = repo.find_packages("black", constraint=constraint)
packages = repo.find_packages(Factory.create_dependency("black", constraint))
assert len(packages) == count
......@@ -167,7 +171,7 @@ def test_find_packages_only_prereleases(constraint, count):
def test_find_packages_only_prereleases_empty_when_not_any():
repo = MockRepository()
packages = repo.find_packages("black", constraint=">=1")
packages = repo.find_packages(Factory.create_dependency("black", ">=1"))
assert len(packages) == 0
......@@ -213,6 +217,7 @@ def test_get_package_from_both_py2_and_py3_specific_wheels():
assert "ipython" == package.name
assert "5.7.0" == package.version.text
assert "*" == package.python_versions
assert 26 == len(package.requires)
expected = [
Dependency("appnope", "*"),
......@@ -229,16 +234,17 @@ def test_get_package_from_both_py2_and_py3_specific_wheels():
Dependency("traitlets", ">=4.2"),
Dependency("win-unicode-console", ">=0.5"),
]
assert expected == package.requires
required = [r for r in package.requires if not r.is_optional()]
assert expected == required
assert 'python_version == "2.7"' == str(package.requires[1].marker)
assert 'python_version == "2.7"' == str(required[1].marker)
assert 'sys_platform == "win32" and python_version < "3.6"' == str(
package.requires[12].marker
required[12].marker
)
assert 'python_version == "2.7" or python_version == "3.3"' == str(
package.requires[4].marker
required[4].marker
)
assert 'sys_platform != "win32"' == str(package.requires[5].marker)
assert 'sys_platform != "win32"' == str(required[5].marker)
def test_get_package_with_dist_and_universal_py3_wheel():
......@@ -265,7 +271,8 @@ def test_get_package_with_dist_and_universal_py3_wheel():
Dependency("typing", "*"),
Dependency("win-unicode-console", ">=0.5"),
]
assert expected == sorted(package.requires, key=lambda dep: dep.name)
required = [r for r in package.requires if not r.is_optional()]
assert expected == sorted(required, key=lambda dep: dep.name)
def test_get_package_retrieves_non_sha256_hashes():
......
......@@ -9,6 +9,7 @@ from requests.exceptions import TooManyRedirects
from requests.models import Response
from poetry.core.packages import Dependency
from poetry.factory import Factory
from poetry.repositories.pypi_repository import PyPiRepository
from poetry.utils._compat import PY35
from poetry.utils._compat import Path
......@@ -56,21 +57,21 @@ class MockRepository(PyPiRepository):
def test_find_packages():
repo = MockRepository()
packages = repo.find_packages("requests", "^2.18")
packages = repo.find_packages(Factory.create_dependency("requests", "^2.18"))
assert len(packages) == 5
def test_find_packages_with_prereleases():
repo = MockRepository()
packages = repo.find_packages("toga", ">=0.3.0.dev2")
packages = repo.find_packages(Factory.create_dependency("toga", ">=0.3.0.dev2"))
assert len(packages) == 7
def test_find_packages_does_not_select_prereleases_if_not_allowed():
repo = MockRepository()
packages = repo.find_packages("pyyaml")
packages = repo.find_packages(Factory.create_dependency("pyyaml", "*"))
assert len(packages) == 1
......@@ -78,7 +79,7 @@ def test_find_packages_does_not_select_prereleases_if_not_allowed():
@pytest.mark.parametrize("constraint,count", [("*", 1), (">=1", 0), (">=19.0.0a0", 1)])
def test_find_packages_only_prereleases(constraint, count):
repo = MockRepository()
packages = repo.find_packages("black", constraint=constraint)
packages = repo.find_packages(Factory.create_dependency("black", constraint))
assert len(packages) == count
......@@ -89,7 +90,8 @@ def test_package():
package = repo.package("requests", "2.18.4")
assert package.name == "requests"
assert len(package.requires) == 4
assert len(package.requires) == 9
assert len([r for r in package.requires if r.is_optional()]) == 5
assert len(package.extras["security"]) == 3
assert len(package.extras["socks"]) == 2
......@@ -141,7 +143,8 @@ def test_fallback_can_read_setup_to_get_dependencies():
package = repo.package("sqlalchemy", "1.2.12")
assert package.name == "sqlalchemy"
assert len(package.requires) == 0
assert len(package.requires) == 9
assert len([r for r in package.requires if r.is_optional()]) == 9
assert package.extras == {
"mssql_pymssql": [Dependency("pymssql", "*")],
......@@ -162,7 +165,10 @@ def test_pypi_repository_supports_reading_bz2_files():
package = repo.package("twisted", "18.9.0")
assert package.name == "twisted"
assert sorted(package.requires, key=lambda r: r.name) == [
assert 28 == len(package.requires)
assert sorted(
[r for r in package.requires if not r.is_optional()], key=lambda r: r.name
) == [
Dependency("attrs", ">=17.4.0"),
Dependency("Automat", ">=0.3.0"),
Dependency("constantly", ">=15.1"),
......@@ -198,7 +204,7 @@ def test_invalid_versions_ignored():
# the json metadata for this package contains one malformed version
# and a correct one.
packages = repo.find_packages("pygame-music-grid")
packages = repo.find_packages(Factory.create_dependency("pygame-music-grid", "*"))
assert len(packages) == 1
......@@ -228,6 +234,6 @@ def test_urls():
def test_use_pypi_pretty_name():
repo = MockRepository(fallback=True)
package = repo.find_packages("twisted")
package = repo.find_packages(Factory.create_dependency("twisted", "*"))
assert len(package) == 1
assert package[0].pretty_name == "Twisted"
......@@ -55,7 +55,7 @@ def test_create_poetry():
assert not requests.is_vcs()
assert not requests.allows_prereleases()
assert requests.is_optional()
assert requests.extras == ["security"]
assert requests.extras == frozenset(["security"])
pathlib2 = dependencies["pathlib2"]
assert pathlib2.pretty_constraint == "^2.2"
......
......@@ -559,7 +559,6 @@ def test_remove_keeps_dir_if_not_deleteable(tmp_dir, manager, poetry, config, mo
original_rmtree = shutil.rmtree
def err_on_rm_venv_only(path, *args, **kwargs):
print(path)
if path == str(venv_path):
raise OSError(16, "Test error") # ERRNO 16: Device or resource busy
else:
......
......@@ -8,10 +8,12 @@ from poetry.repositories.auth import Auth
from poetry.repositories.legacy_repository import LegacyRepository
from poetry.utils._compat import Path
from poetry.utils.exporter import Exporter
from poetry.utils.toml_file import TomlFile
class Locker(BaseLocker):
def __init__(self):
self._lock = TomlFile(Path.cwd().joinpath("poetry.lock"))
self._locked = True
self._content_hash = self._get_content_hash()
......
import pytest
from poetry.core.packages import Package
from poetry.factory import Factory
from poetry.utils.extras import get_extra_package_names
_PACKAGE_FOO = Package("foo", "0.1.0")
_PACKAGE_SPAM = Package("spam", "0.2.0")
_PACKAGE_BAR = Package("bar", "0.3.0")
_PACKAGE_BAR.add_dependency("foo")
_PACKAGE_BAR.add_dependency(Factory.create_dependency("foo", "*"))
# recursive dependency
_PACKAGE_BAZ = Package("baz", "0.4.0")
_PACKAGE_BAZ.add_dependency("quix")
_PACKAGE_BAZ.add_dependency(Factory.create_dependency("quix", "*"))
_PACKAGE_QUIX = Package("quix", "0.5.0")
_PACKAGE_QUIX.add_dependency("baz")
_PACKAGE_QUIX.add_dependency(Factory.create_dependency("baz", "*"))
@pytest.mark.parametrize(
......
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