Skip to content

feature: better pip crossplatform resolves#2322

Merged
saikonen merged 8 commits intomasterfrom
feature/better-pip-crossplatform-resolves
Nov 4, 2025
Merged

feature: better pip crossplatform resolves#2322
saikonen merged 8 commits intomasterfrom
feature/better-pip-crossplatform-resolves

Conversation

@saikonen
Copy link
Copy Markdown
Collaborator

@saikonen saikonen commented Mar 3, 2025

for correctly resolving transient dependencies for cross-platform package resolves, where dependencies are conditional on platform/os such as

"nvidia-cuda-runtime-cu12 (==12.4.127) ; platform_system == \"Linux\" and platform_machine == \"x86_64\"",

This intends to solve an issue with packages such as the default torch where resolving on a mac, but deploying onto a linux-64 machine will result in a broken environment due to the conditional dependencies not getting bundled up.

@saikonen
Copy link
Copy Markdown
Collaborator Author

saikonen commented Mar 3, 2025

note that for testing this, both .pip/metadata and conda.manifest local files for the involved flow need to most likely be cleared

@saikonen saikonen force-pushed the feature/better-pip-crossplatform-resolves branch from d787ea8 to 7a340ff Compare October 30, 2025 22:52
@saikonen saikonen marked this pull request as ready for review October 30, 2025 23:40
@saikonen saikonen changed the title wip: better pip crossplatform resolves feat: better pip crossplatform resolves Oct 30, 2025
@saikonen saikonen changed the title feat: better pip crossplatform resolves feature: better pip crossplatform resolves Oct 30, 2025
@saikonen saikonen requested a review from romain-intel October 31, 2025 21:25
@saikonen saikonen merged commit 1f1b0b5 into master Nov 4, 2025
33 checks passed
@saikonen saikonen deleted the feature/better-pip-crossplatform-resolves branch November 4, 2025 16:38
import platform

platform.system = lambda: os.environ.get("PIP_PATCH_SYSTEM", os.uname().sysname)
platform.machine = lambda: os.environ.get("PIP_PATCH_MACHINE", os.uname().machine)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure this is sufficient in all cases. Here is the default_environment that is used:

    return {
        "implementation_name": implementation_name,
        "implementation_version": iver,
        "os_name": os.name,
        "platform_machine": platform.machine(),
        "platform_release": platform.release(),
        "platform_system": platform.system(),
        "platform_version": platform.version(),
        "python_full_version": platform.python_version(),
        "platform_python_implementation": platform.python_implementation(),
        "python_version": ".".join(platform.python_version_tuple()[:2]),
        "sys_platform": sys.platform,
    }

I think we need to override:

  • sys.platform
  • platform.version()

as well. The others relate to posix versus non posix (and I think we are always posix) and cpython or not (and I think we also only do cpython)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and platform.release()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not tested yet (working on it) but maybe something like this:

import json
import os
import platform
import sys

_override_mappings = {
    "platform_machine": platform.machine,
    "platform_release": platform.release,
    "platform_system": platform.system,
    "platform_version": platform.version,
    "sys_platform": sys.platform,
}

overrides = os.environ.get("PIP_CUSTOMIZE_OVERRIDES")
if overrides:
    overrides_dict = json.loads(overrides)
    for key, override_value in overrides_dict.items():
        if key in _override_mappings:
            if callable(_override_mappings[key]):
                _override_mappings[key] = lambda _v=override_value: _v
            else:
                _override_mappings[key] = override_value

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that didn't work and then I realized that if I override sys.platform, bad things happen. I still think we need to override it to handle as many markers as possible.

I ended up going with the other approach. Something like this:

import json
import os
import pip._vendor.packaging.markers as _markers


_overrides = os.environ.get("PIP_CUSTOMIZE_OVERRIDES")
if _overrides:
    _orig_default_environment = _markers.default_environment
    _overrides_dict = json.loads(_overrides)

    def _wrap_default_environment():
        result = _orig_default_environment()
        result.update(_overrides_dict)
        return result

    _markers.default_environment = _wrap_default_environment

and that seems to work. Just FYI.

Copy link
Copy Markdown
Collaborator Author

@saikonen saikonen Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opened #2675 to address this, along with resolving an issue cross-platform resolving on a mac when using metaflow-dev

what are you using as a source of info for platform.version/platform.release/sys.platform when it comes to the target system? I'm not sure if any/all of these are available currently at least on the OSS side

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants