Skip to content

Commit

Permalink
fix construction of python version marker
Browse files Browse the repository at this point in the history
  • Loading branch information
dimbleby committed Aug 29, 2022
1 parent e8cb613 commit 6d6d2bd
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 37 deletions.
6 changes: 2 additions & 4 deletions src/poetry/core/packages/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
from poetry.core.packages.dependency_group import MAIN_GROUP
from poetry.core.packages.specification import PackageSpecification
from poetry.core.packages.utils.utils import create_nested_marker
from poetry.core.packages.utils.utils import get_python_constraint_from_marker
from poetry.core.semver.helpers import parse_constraint
from poetry.core.version.markers import parse_marker

Expand Down Expand Up @@ -263,11 +262,10 @@ def python_versions(self) -> str:
@python_versions.setter
def python_versions(self, value: str) -> None:
self._python_versions = value
constraint = parse_constraint(value)
self._python_constraint = parse_constraint(value)
self._python_marker = parse_marker(
create_nested_marker("python_version", constraint)
create_nested_marker("python_version", self._python_constraint)
)
self._python_constraint = get_python_constraint_from_marker(self._python_marker)

@property
def python_constraint(self) -> VersionConstraint:
Expand Down
69 changes: 39 additions & 30 deletions src/poetry/core/packages/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,44 +240,53 @@ def create_nested_marker(
marker = f'{name} == "{constraint.text}"'
else:
assert isinstance(constraint, VersionRange)
min_name = max_name = name

parts = []

# `python_version` is a special case: to keep the constructed marker equivalent
# to the constraint we need to be careful with the precision.
#
# PEP 440 tells us that that when we come to make the comparison the release
# segment will be zero padded: eg "<= 3.10" is equivalent to "<= 3.10.0".
#
# But "python_version <= 3.6" is _not_ equivalent to "python_version <= 3.10.0" -
# see normalize_python_version_markers.
#
# A similar issue arises for a constraint like "> 3.6".
if constraint.min is not None:
op = ">="
if not constraint.include_min:
op = ">"

op = ">=" if constraint.include_min else ">"
version = constraint.min
if constraint.max is not None:
min_name = max_name = name
if min_name == "python_version" and constraint.min.precision >= 3:
min_name = "python_full_version"

if max_name == "python_version" and constraint.max.precision >= 3:
max_name = "python_full_version"

text = f'{min_name} {op} "{version}"'

op = "<="
if not constraint.include_max:
op = "<"
if min_name == "python_version" and version.precision >= 3:
min_name = "python_full_version"

version = constraint.max
if min_name == "python_version" and not constraint.include_min:
padding = (
".0" * (3 - version.precision) if version.precision < 3 else ""
)
part = f'python_full_version > "{version}{padding}"'
else:
part = f'{min_name} {op} "{version}"'

text += f' and {max_name} {op} "{version}"'

return text
elif constraint.max is not None:
op = "<="
if not constraint.include_max:
op = "<"
parts.append(part)

if constraint.max is not None:
op = "<=" if constraint.include_max else "<"
version = constraint.max
else:
return ""
if max_name == "python_version" and version.precision >= 3:
max_name = "python_full_version"

if name == "python_version" and version.precision >= 3:
name = "python_full_version"
if name == "python_version" and constraint.include_max:
padding = (
".0" * (3 - version.precision) if version.precision < 3 else ""
)
part = f'python_full_version <= "{version}{padding}"'
else:
part = f'{max_name} {op} "{version}"'

parts.append(part)

marker = f'{name} {op} "{version}"'
marker = " and ".join(parts)

return marker

Expand Down
6 changes: 3 additions & 3 deletions tests/packages/test_package.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,15 +533,15 @@ def test_package_pep592_yanked(
assert package.yanked_reason == expected_yanked_reason


def test_python_versions_are_normalized() -> None:
def test_python_versions_are_made_precise() -> None:
package = Package("foo", "1.2.3")
package.python_versions = ">3.6,<=3.10"

assert (
str(package.python_marker)
== 'python_version > "3.6" and python_version <= "3.10"'
== 'python_full_version > "3.6.0" and python_full_version <= "3.10.0"'
)
assert str(package.python_constraint) == ">=3.7,<3.11"
assert str(package.python_constraint) == ">3.6,<=3.10"


def test_cannot_update_package_version() -> None:
Expand Down

0 comments on commit 6d6d2bd

Please sign in to comment.