Skip to content

Commit 936dae2

Browse files
committed
fix construction of python version marker
1 parent e8cb613 commit 936dae2

File tree

3 files changed

+44
-37
lines changed

3 files changed

+44
-37
lines changed

src/poetry/core/packages/package.py

+2-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
from poetry.core.packages.dependency_group import MAIN_GROUP
1616
from poetry.core.packages.specification import PackageSpecification
1717
from poetry.core.packages.utils.utils import create_nested_marker
18-
from poetry.core.packages.utils.utils import get_python_constraint_from_marker
1918
from poetry.core.semver.helpers import parse_constraint
2019
from poetry.core.version.markers import parse_marker
2120

@@ -263,11 +262,10 @@ def python_versions(self) -> str:
263262
@python_versions.setter
264263
def python_versions(self, value: str) -> None:
265264
self._python_versions = value
266-
constraint = parse_constraint(value)
265+
self._python_constraint = parse_constraint(value)
267266
self._python_marker = parse_marker(
268-
create_nested_marker("python_version", constraint)
267+
create_nested_marker("python_version", self._python_constraint)
269268
)
270-
self._python_constraint = get_python_constraint_from_marker(self._python_marker)
271269

272270
@property
273271
def python_constraint(self) -> VersionConstraint:

src/poetry/core/packages/utils/utils.py

+39-30
Original file line numberDiff line numberDiff line change
@@ -240,44 +240,53 @@ def create_nested_marker(
240240
marker = f'{name} == "{constraint.text}"'
241241
else:
242242
assert isinstance(constraint, VersionRange)
243+
min_name = max_name = name
244+
245+
parts = []
246+
247+
# `python_version` is a special case: to keep the constructed marker equivalent
248+
# to the constraint we need to be careful with the precision.
249+
#
250+
# PEP 440 tells us that that when we come to make the comparison the release
251+
# segment will be zero padded: eg "<= 3.10" is equivalent to "<= 3.10.0".
252+
#
253+
# But "python_version <= 3.10" is _not_ equivalent to "python_version <= 3.10.0" -
254+
# see normalize_python_version_markers.
255+
#
256+
# A similar issue arises for a constraint like "> 3.6".
243257
if constraint.min is not None:
244-
op = ">="
245-
if not constraint.include_min:
246-
op = ">"
247-
258+
op = ">=" if constraint.include_min else ">"
248259
version = constraint.min
249-
if constraint.max is not None:
250-
min_name = max_name = name
251-
if min_name == "python_version" and constraint.min.precision >= 3:
252-
min_name = "python_full_version"
253-
254-
if max_name == "python_version" and constraint.max.precision >= 3:
255-
max_name = "python_full_version"
256-
257-
text = f'{min_name} {op} "{version}"'
258-
259-
op = "<="
260-
if not constraint.include_max:
261-
op = "<"
260+
if min_name == "python_version" and version.precision >= 3:
261+
min_name = "python_full_version"
262262

263-
version = constraint.max
263+
if min_name == "python_version" and not constraint.include_min:
264+
padding = (
265+
".0" * (3 - version.precision) if version.precision < 3 else ""
266+
)
267+
part = f'python_full_version > "{version}{padding}"'
268+
else:
269+
part = f'{min_name} {op} "{version}"'
264270

265-
text += f' and {max_name} {op} "{version}"'
266-
267-
return text
268-
elif constraint.max is not None:
269-
op = "<="
270-
if not constraint.include_max:
271-
op = "<"
271+
parts.append(part)
272272

273+
if constraint.max is not None:
274+
op = "<=" if constraint.include_max else "<"
273275
version = constraint.max
274-
else:
275-
return ""
276+
if max_name == "python_version" and version.precision >= 3:
277+
max_name = "python_full_version"
276278

277-
if name == "python_version" and version.precision >= 3:
278-
name = "python_full_version"
279+
if name == "python_version" and constraint.include_max:
280+
padding = (
281+
".0" * (3 - version.precision) if version.precision < 3 else ""
282+
)
283+
part = f'python_full_version <= "{version}{padding}"'
284+
else:
285+
part = f'{max_name} {op} "{version}"'
286+
287+
parts.append(part)
279288

280-
marker = f'{name} {op} "{version}"'
289+
marker = " and ".join(parts)
281290

282291
return marker
283292

tests/packages/test_package.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -533,15 +533,15 @@ def test_package_pep592_yanked(
533533
assert package.yanked_reason == expected_yanked_reason
534534

535535

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

540540
assert (
541541
str(package.python_marker)
542-
== 'python_version > "3.6" and python_version <= "3.10"'
542+
== 'python_full_version > "3.6.0" and python_full_version <= "3.10.0"'
543543
)
544-
assert str(package.python_constraint) == ">=3.7,<3.11"
544+
assert str(package.python_constraint) == ">3.6,<=3.10"
545545

546546

547547
def test_cannot_update_package_version() -> None:

0 commit comments

Comments
 (0)