Skip to content

Commit

Permalink
Fix complicated export case
Browse files Browse the repository at this point in the history
By treating different python version ranges independently, we buy the
flexibility needed to make better decisions.
  • Loading branch information
dimbleby committed May 30, 2022
1 parent 27034d6 commit 5f421b1
Showing 1 changed file with 47 additions and 4 deletions.
51 changes: 47 additions & 4 deletions src/poetry/packages/locker.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@
from poetry.core.packages.url_dependency import URLDependency
from poetry.core.packages.vcs_dependency import VCSDependency
from poetry.core.semver.helpers import parse_constraint
from poetry.core.semver.util import constraint_regions
from poetry.core.semver.version import Version
from poetry.core.toml.file import TOMLFile
from poetry.core.version.markers import AnyMarker
from poetry.core.version.markers import SingleMarker
from poetry.core.version.markers import parse_marker
from poetry.core.version.requirements import InvalidRequirement
from tomlkit import array
Expand Down Expand Up @@ -49,6 +52,33 @@
logger = logging.getLogger(__name__)


def get_python_version_region_markers(packages: list[Package]) -> list[BaseMarker]:
markers = []

regions = constraint_regions([package.python_constraint for package in packages])
for region in regions:
marker: BaseMarker = AnyMarker()
if region.min is not None:
min_operator = ">=" if region.include_min else ">"
marker_name = (
"python_full_version" if region.min.precision > 2 else "python_version"
)
lo = SingleMarker(marker_name, f"{min_operator} {region.min}")
marker = marker.intersect(lo)

if region.max is not None:
max_operator = "<=" if region.include_max else "<"
marker_name = (
"python_full_version" if region.max.precision > 2 else "python_version"
)
hi = SingleMarker(marker_name, f"{max_operator} {region.max}")
marker = marker.intersect(hi)

markers.append(marker)

return markers


class Locker:

_VERSION = "1.1"
Expand Down Expand Up @@ -279,12 +309,25 @@ def __walk_dependencies(
):
continue

require = deepcopy(require)
require.marker = require.marker.intersect(
base_marker = require.marker.intersect(
requirement.marker.without_extras()
)
if not require.marker.is_empty():
dependencies.append(require)

if not base_marker.is_empty():
# So as to give ourselves enough flexibility in choosing a solution,
# we need to split the world up into the python version ranges that
# this package might care about.
#
# We create a marker for all of the possible regions, and add a
# requirement for each separately.
candidates = packages_by_name.get(require.name, [])
region_markers = get_python_version_region_markers(candidates)
for region_marker in region_markers:
marker = region_marker.intersect(base_marker)
if not marker.is_empty():
require2 = deepcopy(require)
require2.marker = marker
dependencies.append(require2)

key = locked_package
if key not in nested_dependencies:
Expand Down

0 comments on commit 5f421b1

Please sign in to comment.