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