diff --git a/poetry/core/factory.py b/poetry/core/factory.py index 7dbc8ff2d..003a197ba 100644 --- a/poetry/core/factory.py +++ b/poetry/core/factory.py @@ -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 @@ -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) ) ) ) diff --git a/poetry/core/packages/dependency.py b/poetry/core/packages/dependency.py index 0ea6d127b..65d0090e0 100644 --- a/poetry/core/packages/dependency.py +++ b/poetry/core/packages/dependency.py @@ -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 @@ -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 @@ -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: @@ -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 @@ -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 @@ -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 diff --git a/tests/packages/test_dependency.py b/tests/packages/test_dependency.py index 0baa12700..a0e9d2524 100644 --- a/tests/packages/test_dependency.py +++ b/tests/packages/test_dependency.py @@ -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" diff --git a/tests/test_factory.py b/tests/test_factory.py index e4b3eb538..76836b60f 100644 --- a/tests/test_factory.py +++ b/tests/test_factory.py @@ -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"] @@ -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"'