|
19 | 19 | from poetry.core.packages.url_dependency import URLDependency
|
20 | 20 | from poetry.core.packages.vcs_dependency import VCSDependency
|
21 | 21 | from poetry.core.semver.helpers import parse_constraint
|
| 22 | +from poetry.core.semver.util import constraint_regions |
22 | 23 | from poetry.core.semver.version import Version
|
23 | 24 | from poetry.core.toml.file import TOMLFile
|
| 25 | +from poetry.core.version.markers import AnyMarker |
| 26 | +from poetry.core.version.markers import SingleMarker |
24 | 27 | from poetry.core.version.markers import parse_marker
|
25 | 28 | from poetry.core.version.requirements import InvalidRequirement
|
26 | 29 | from tomlkit import array
|
|
49 | 52 | logger = logging.getLogger(__name__)
|
50 | 53 |
|
51 | 54 |
|
| 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 | + |
52 | 79 | class Locker:
|
53 | 80 |
|
54 | 81 | _VERSION = "1.1"
|
@@ -279,12 +306,25 @@ def __walk_dependencies(
|
279 | 306 | ):
|
280 | 307 | continue
|
281 | 308 |
|
282 |
| - require = deepcopy(require) |
283 |
| - require.marker = require.marker.intersect( |
| 309 | + base_marker = require.marker.intersect( |
284 | 310 | requirement.marker.without_extras()
|
285 | 311 | )
|
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) |
288 | 328 |
|
289 | 329 | key = locked_package
|
290 | 330 | if key not in nested_dependencies:
|
|
0 commit comments