Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure setting dependency marker sets the python constraint #208

Merged
merged 1 commit into from
Sep 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions poetry/core/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ def create_dependency(
from .packages.url_dependency import URLDependency
from .packages.utils.utils import create_nested_marker
from .packages.vcs_dependency import VCSDependency
from .semver.helpers import parse_constraint
from .version.markers import AnyMarker
from .version.markers import parse_marker

Expand Down Expand Up @@ -340,11 +341,10 @@ def create_dependency(
if not markers:
marker = AnyMarker()
if python_versions:
dependency.python_versions = python_versions
marker = marker.intersect(
parse_marker(
create_nested_marker(
"python_version", dependency.python_constraint
"python_version", parse_constraint(python_versions)
)
)
)
Expand Down
116 changes: 65 additions & 51 deletions poetry/core/packages/dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def __init__(
self._activated = not self._optional

self.is_root = False
self.marker = AnyMarker()
self._marker = AnyMarker()
self.source_name = None

@property
Expand Down Expand Up @@ -131,7 +131,7 @@ def python_versions(self, value: str) -> None:
self._python_versions = value
self._python_constraint = parse_constraint(value)
if not self._python_constraint.is_any():
self.marker = self.marker.intersect(
self._marker = self._marker.intersect(
parse_marker(
self._create_nested_marker(
"python_version", self._python_constraint
Expand All @@ -151,6 +151,69 @@ def transitive_python_versions(self, value: str) -> None:
self._transitive_python_versions = value
self._transitive_python_constraint = parse_constraint(value)

@property
def marker(self) -> "BaseMarker":
return self._marker

@marker.setter
def marker(self, marker: Union[str, "BaseMarker"]) -> None:
from poetry.core.semver.helpers import parse_constraint
from poetry.core.version.markers import BaseMarker
from poetry.core.version.markers import parse_marker

from .utils.utils import convert_markers

if not isinstance(marker, BaseMarker):
marker = parse_marker(marker)

self._marker = marker

markers = convert_markers(marker)

if "extra" in markers:
# If we have extras, the dependency is optional
self.deactivate()

for or_ in markers["extra"]:
for _, extra in or_:
self.in_extras.append(extra)

if "python_version" in markers:
ors = []
for or_ in markers["python_version"]:
ands = []
for op, version in or_:
# Expand python version
if op == "==" and "*" not in version:
version = "~" + version
op = ""
elif op == "!=":
version += ".*"
elif op in ("in", "not in"):
versions = []
for v in re.split("[ ,]+", version):
split = v.split(".")
if len(split) in [1, 2]:
split.append("*")
op_ = "" if op == "in" else "!="
else:
op_ = "==" if op == "in" else "!="

versions.append(op_ + ".".join(split))

glue = " || " if op == "in" else ", "
if versions:
ands.append(glue.join(versions))

continue

ands.append("{}{}".format(op, version))

ors.append(" ".join(ands))

self._python_versions = " || ".join(ors)
self._python_constraint = parse_constraint(self._python_versions)

@property
def transitive_marker(self) -> "BaseMarker":
if self._transitive_marker is None:
Expand Down Expand Up @@ -427,7 +490,6 @@ def create_from_pep_508(

from .url_dependency import URLDependency
from .utils.link import Link
from .utils.utils import convert_markers
from .utils.utils import is_archive_file
from .utils.utils import is_installable_dir
from .utils.utils import is_url
Expand All @@ -446,11 +508,6 @@ def create_from_pep_508(

req = Requirement(name)

if req.marker:
markers = convert_markers(req.marker)
else:
markers = {}

name = req.name
path = os.path.normpath(os.path.abspath(name))
link = None
Expand Down Expand Up @@ -543,49 +600,6 @@ def create_from_pep_508(

dep = Dependency(name, constraint, extras=req.extras)

if "extra" in markers:
# If we have extras, the dependency is optional
dep.deactivate()

for or_ in markers["extra"]:
for _, extra in or_:
dep.in_extras.append(extra)

if "python_version" in markers:
ors = []
for or_ in markers["python_version"]:
ands = []
for op, version in or_:
# Expand python version
if op == "==" and "*" not in version:
version = "~" + version
op = ""
elif op == "!=":
version += ".*"
elif op in ("in", "not in"):
versions = []
for v in re.split("[ ,]+", version):
split = v.split(".")
if len(split) in [1, 2]:
split.append("*")
op_ = "" if op == "in" else "!="
else:
op_ = "==" if op == "in" else "!="

versions.append(op_ + ".".join(split))

glue = " || " if op == "in" else ", "
if versions:
ands.append(glue.join(versions))

continue

ands.append("{}{}".format(op, version))

ors.append(" ".join(ands))

dep.python_versions = " || ".join(ors)

if req.marker:
dep.marker = req.marker

Expand Down
8 changes: 8 additions & 0 deletions tests/packages/test_dependency.py
Original file line number Diff line number Diff line change
Expand Up @@ -275,3 +275,11 @@ def test_with_constraint():
assert new.transitive_marker == dependency.transitive_marker
assert new.python_constraint == dependency.python_constraint
assert new.transitive_python_constraint == dependency.transitive_python_constraint


def test_marker_properly_sets_python_constraint():
dependency = Dependency("foo", "^1.2.3")

dependency.marker = 'python_version >= "3.6" and python_version < "4.0"'

assert str(dependency.python_constraint) == ">=3.6,<4.0"
4 changes: 2 additions & 2 deletions tests/test_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def test_create_poetry():

pathlib2 = dependencies["pathlib2"]
assert pathlib2.pretty_constraint == "^2.2"
assert pathlib2.python_versions == "~2.7"
assert pathlib2.python_versions == ">=2.7 <2.8"
assert not pathlib2.is_optional()

demo = dependencies["demo"]
Expand Down Expand Up @@ -102,7 +102,7 @@ def test_create_poetry():
dataclasses = dependencies["dataclasses"]
assert dataclasses.name == "dataclasses"
assert dataclasses.pretty_constraint == "^0.7"
assert dataclasses.python_versions == ">=3.6.1,<3.7"
assert dataclasses.python_versions == ">=3.6.1 <3.7"
assert (
str(dataclasses.marker)
== 'python_full_version >= "3.6.1" and python_version < "3.7"'
Expand Down