Skip to content

fix: include legacy manylinux aliases in --platform tags - #170

Open
BrandonLWhite wants to merge 3 commits into
python-poetry:mainfrom
BrandonLWhite:fix/platform-legacy-manylinux-aliases
Open

BrandonLWhite wants to merge 3 commits into
python-poetry:mainfrom
BrandonLWhite:fix/platform-legacy-manylinux-aliases

Conversation

@BrandonLWhite

@BrandonLWhite BrandonLWhite commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Hello, this PR is to resolve a problem I recently encountered where packages that only provide wheels for really old "manylinux" versions, specifically the old aliased ones, fail to install with the plugin for a specified --platform that is more modern but technically compatible.

This is not a regression issue, but rather a gap from my original implementation of the --platform feature.

This PR and the details that follow were generated by Claude Opus 5.5. But I have examined everything personally and confirmed the fix works in my use case. I will also respond, as a human, to any follow-up questions you may have.


Problem

poetry bundle venv --platform manylinux_2_34_aarch64 cannot install a wheel whose only Linux tag is a legacy manylinux alias, even though PEP 600 defines manylinux2014_aarch64 as an alias for manylinux_2_17_aarch64, which a glibc 2.34 target satisfies.

For example, duckdb-extension-httpfs 1.5.5 ships its aarch64 build only as py3-none-manylinux2014_aarch64, so bundling a project that depends on it fails:

Unable to find installation candidates for duckdb-extension-httpfs (1.5.5)

Asking for the legacy platform explicitly fails the same way: --platform manylinux2014_aarch64 also rejects a manylinux2014_aarch64 wheel.

When the package also publishes an sdist, the failure is silent instead. Poetry skips the wheels it considers unsupported and installs the sdist, so any extension is built on the host rather than for the target, as the README's Limitations section describes. For example, cmake 3.18.4.post1 tags its Linux wheels only with legacy aliases (manylinux1_x86_64, manylinux1_i686 and manylinux2014_aarch64), so for --platform manylinux_2_34_aarch64 Poetry chooses cmake-3.18.4.post1.tar.gz.

Root cause

create_supported_manylinux_platforms normalizes the --platform value through LEGACY_MANYLINUX_ALIASES, then emits only PEP 600 spellings: manylinux_2_{N}_{arch} for every N from the requested glibc minor down to 0. Poetry's chooser matches wheel tags against env.supported_tags by exact string, so a wheel tagged only with an alias never matches.

PEP 600's reference code applies its alias table to the wheel's tag before comparing. The plugin applied it only to the requested platform.

This went unnoticed because most wheels carry both spellings, for example manylinux_2_17_x86_64.manylinux2014_x86_64. None of the wheels in the existing project_with_binary_wheel fixture is tagged only with a legacy alias, so test_bundler_platform_override never exercised this case.

Fix

Emit each legacy alias right after the PEP 600 tag for the same glibc version:

  • manylinux_2_17 → manylinux2014
  • manylinux_2_12 → manylinux2010
  • manylinux_2_5 → manylinux1

The alias lookup is the existing LEGACY_MANYLINUX_ALIASES map, inverted.

The order matters. Among compatible wheels with the same version and build tag, Poetry's chooser prefers the one whose tags appear earliest in supported_tags. A wheel built for a newer glibc still wins, and at the same glibc version the alias ranks just below the PEP 600 spelling.

Aliases are emitted for every architecture, matching how the existing input normalization treats them. An alias that PEP 600 does not define for an architecture, such as manylinux1_aarch64, matches no wheel, just as the existing manylinux_2_0_aarch64 tag matches none today.

This also changes which file some existing bundles install. A package that was silently built from its sdist, like cmake above, now gets its wheel. And a wheel tagged only with a legacy alias for a newer glibc now outranks a wheel with a PEP 600 tag for an older glibc, as PEP 600 says installers should prefer the highest compatible glibc version.

The README's --platform section gains a "Compatible wheels" subsection that says which wheels a platform value accepts, including the legacy aliases.

Precedent

  • packaging, which Poetry uses for the host's own tags: packaging._manylinux.platform_tags yields each legacy alias immediately after the PEP 600 tag for the same glibc version. On an aarch64 host with glibc 2.34, its list ends manylinux_2_18_aarch64, manylinux_2_17_aarch64, manylinux2014_aarch64. So Poetry running on the target host itself would install the httpfs wheel above, and this change makes --platform agree with it.
  • uv: uv pip install --python-platform aarch64-manylinux_2_34 duckdb-extension-httpfs==1.5.5 installs the manylinux2014_aarch64 wheel (tested with uv 0.12.17). Its tag generator (crates/uv-platform-tags/src/tags.rs) pushes manylinux2014 right after manylinux_2_17, commented "Support legacy manylinux tags with lower priority" and citing PEP 600.
  • pip: for a PEP 600 value, pip download --platform (26.2.1) matches only that exact tag, with no downward glibc expansion and no aliases, so it cannot fetch even a manylinux_2_28 wheel for --platform manylinux_2_34_aarch64. Its only expansion goes from a legacy x86_64 or i686 value to older legacy tags: manylinux2014_x86_64 also accepts manylinux2010_x86_64 and manylinux1_x86_64. The missing PEP 600 handling is tracked as a bug in pip doesn't handle PEP600 compatible manylinux wheels when --platform is specified. pypa/pip#10760 (open since 2022; maintainers said they would accept a fix), not as intended behavior.

Verification

  • Tests: 29/29 pass, mypy is clean, and all pre-commit hooks pass.
    • Each new or extended test fails without the fix: the three platform tests because the alias tags are missing, and the bundler test because the chooser picks the sdist.
      • test_create_supported_tags_manylinux_includes_legacy_aliases (new): for manylinux_2_34_aarch64, the manylinux2014_aarch64 alias is present for the cp314, abi3 and py3 tags.
      • test_create_supported_tags_ranks_legacy_alias_with_its_glibc_version (new): manylinux2014_aarch64 sits directly between manylinux_2_17_aarch64 and manylinux_2_16_aarch64.
      • test_create_supported_tags_legacy_manylinux_aliases (extended): the aliases at or below the requested glibc version are present, and newer ones are not. For example, manylinux2010_x86_64 does not yield manylinux2014_x86_64.
      • test_bundler_platform_override_selects_legacy_manylinux_wheel (new): bundles a new project_with_legacy_manylinux_wheel fixture, which depends on cmake 3.18.4.post1, through Poetry's chooser. The chooser must pick the manylinux2014_aarch64 wheel for manylinux_2_34_aarch64 and manylinux2014_aarch64, and the manylinux1_x86_64 wheel for manylinux_2_28_x86_64. Without the fix it picks cmake-3.18.4.post1.tar.gz.
    • The mocks in test_bundler_platform_override move into a _mock_platform_installs helper that the new bundler test shares. The existing test's assertions are unchanged.
  • End to end: I ran a real poetry bundle venv --without dev --platform manylinux_2_34_aarch64 on an x86_64 host, for a Python 3.14 project that depends on duckdb==1.5.5 and duckdb-extension-httpfs==1.5.5.
    • With this change (Poetry 2.5.0), the bundle succeeds. It installs duckdb's manylinux_2_26_aarch64.manylinux_2_28_aarch64 wheel and httpfs's manylinux2014_aarch64 wheel, whose extension binary is an aarch64 ELF.
    • With 1.8.0 (Poetry 2.5.1), the same command fails with Unable to find installation candidates for duckdb-extension-httpfs (1.5.5).

🤖 Generated with Claude Code

BrandonLWhite and others added 3 commits October 1, 2026 09:21
create_supported_manylinux_platforms normalized the --platform value
through LEGACY_MANYLINUX_ALIASES, then emitted only PEP 600 spellings
(manylinux_2_N_ARCH). Poetry's chooser matches wheel tags against
env.supported_tags by exact string, so a wheel tagged only with a
legacy alias never matched: duckdb-extension-httpfs 1.5.5, whose
aarch64 wheel is tagged only manylinux2014_aarch64, could not be
bundled for --platform manylinux_2_34_aarch64, nor even for
--platform manylinux2014_aarch64.

Emit each PEP 600 legacy alias (manylinux2014, manylinux2010,
manylinux1) right after the tag for the same glibc version, so a wheel
built for a newer glibc still ranks first, and at the same glibc
version the alias ranks just below the PEP 600 spelling.

ai-generated: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a project_with_legacy_manylinux_wheel fixture that depends on cmake
3.18.4.post1, whose Linux wheels are tagged only manylinux1_x86_64,
manylinux1_i686 and manylinux2014_aarch64, alongside an sdist. The new
bundler test checks that Poetry's chooser picks those wheels for
--platform manylinux_2_34_aarch64, manylinux2014_aarch64 and
manylinux_2_28_x86_64. Without the alias fix it silently picks the
sdist, which would be built on the host.

Move the mocks from test_bundler_platform_override into a shared
_mock_platform_installs helper; that test's assertions are unchanged.

ai-generated: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The README did not say that a platform value also accepts wheels built
for older versions of it, or, for manylinux, wheels tagged only with
the legacy manylinux2014, manylinux2010 or manylinux1 aliases.

ai-generated: true
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@BrandonLWhite
BrandonLWhite marked this pull request as ready for review October 9, 2026 21:40

This branch has not been deployed

No deployments
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.

1 participant