Skip to content

Commit d261745

Browse files
committed
Fix complicated export case
By treating different python version ranges independently, we buy the flexibility needed to make better decisions.
1 parent 27034d6 commit d261745

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

Diff for: src/poetry/packages/locker.py

+44-4
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,11 @@
1919
from poetry.core.packages.url_dependency import URLDependency
2020
from poetry.core.packages.vcs_dependency import VCSDependency
2121
from poetry.core.semver.helpers import parse_constraint
22+
from poetry.core.semver.util import constraint_regions
2223
from poetry.core.semver.version import Version
2324
from poetry.core.toml.file import TOMLFile
25+
from poetry.core.version.markers import AnyMarker
26+
from poetry.core.version.markers import SingleMarker
2427
from poetry.core.version.markers import parse_marker
2528
from poetry.core.version.requirements import InvalidRequirement
2629
from tomlkit import array
@@ -49,6 +52,30 @@
4952
logger = logging.getLogger(__name__)
5053

5154

55+
def get_python_version_region_markers(packages: list[Package]) -> list[BaseMarker]:
56+
regions = constraint_regions([package.python_constraint for package in packages])
57+
58+
markers = []
59+
for region in regions:
60+
min_operator = ">=" if region.include_min else ">"
61+
lo = (
62+
SingleMarker("python_full_version", f"{min_operator} {region.min}")
63+
if region.min is not None
64+
else AnyMarker()
65+
)
66+
67+
max_operator = "<=" if region.include_max else "<"
68+
hi = (
69+
SingleMarker("python_full_version", f"{max_operator} {region.max}")
70+
if region.max is not None
71+
else AnyMarker()
72+
)
73+
74+
markers.append(lo.intersect(hi))
75+
76+
return markers
77+
78+
5279
class Locker:
5380

5481
_VERSION = "1.1"
@@ -279,12 +306,25 @@ def __walk_dependencies(
279306
):
280307
continue
281308

282-
require = deepcopy(require)
283-
require.marker = require.marker.intersect(
309+
base_marker = require.marker.intersect(
284310
requirement.marker.without_extras()
285311
)
286-
if not require.marker.is_empty():
287-
dependencies.append(require)
312+
313+
if not base_marker.is_empty():
314+
# So as to give ourselves enough flexibility in choosing a solution,
315+
# we need to split the world up into the python version ranges that
316+
# this package might care about.
317+
#
318+
# We create a marker for all of the possible regions, and add a
319+
# requirement for each separately.
320+
candidates = packages_by_name.get(require.name, [])
321+
region_markers = get_python_version_region_markers(candidates)
322+
for region_marker in region_markers:
323+
marker = region_marker.intersect(base_marker)
324+
if not marker.is_empty():
325+
require2 = deepcopy(require)
326+
require2.marker = marker
327+
dependencies.append(require2)
288328

289329
key = locked_package
290330
if key not in nested_dependencies:

0 commit comments

Comments
 (0)