Skip to content

fix(publish): normalize legacy repository URL trailing slash (#6687)#10785

Merged
radoering merged 3 commits intopython-poetry:mainfrom
bibekmhj:fix/normalize-legacy-upload-url-6687
Mar 28, 2026
Merged

fix(publish): normalize legacy repository URL trailing slash (#6687)#10785
radoering merged 3 commits intopython-poetry:mainfrom
bibekmhj:fix/normalize-legacy-upload-url-6687

Conversation

@bibekmhj
Copy link
Copy Markdown
Contributor

@bibekmhj bibekmhj commented Mar 25, 2026

Fixes #6687

When a PEP 503 legacy repository is configured without a trailing slash
(e.g. https://test.pypi.org/legacy), uploads silently fail because the
server expects the /legacy/ path.

This PR normalizes the URL before publishing.

Changes:

  • Simplify _normalize_legacy_repository_url to a one-liner per
    @radoering's suggestion in fix(publish): normalize legacy repository URL trailing slash #10732 (removes urllib.parse import)
  • Fix broken call_args assertions in test — replaced with
    assert_called_once_with which actually validates the call
  • Parametrize the test to cover three cases:
    1. Missing trailing slash → slash appended ✓
    2. Already has trailing slash → no double slash ✓
    3. Non-legacy URL → unchanged ✓

Note: This supersedes #10732 which had reviewer feedback pending.

Summary by Sourcery

Normalize configured legacy repository URLs during publishing to ensure uploads target the correct endpoint.

Bug Fixes:

  • Ensure legacy repository URLs without a trailing slash are corrected so uploads no longer silently fail.

Tests:

  • Add a parametrized publishing test that verifies legacy URLs are normalized and other URLs remain unchanged.

…poetry#6687)

- Simplify _normalize_legacy_repository_url per maintainer suggestion
- Fix broken call_args assertions in test, use assert_called_once_with
- Add parametrized test cases: already-normalized URL and non-legacy URL
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 25, 2026

Reviewer's Guide

Normalizes legacy repository URLs before publishing so missing trailing slashes on /legacy endpoints are handled correctly, and adds focused tests that verify URL normalization and correct uploader calls.

Sequence diagram for publishing with normalized legacy repository URL

sequenceDiagram
    actor User
    participant Publisher
    participant PoetryConfig as Poetry_config
    participant Normalizer as _normalize_legacy_repository_url
    participant Uploader

    User->>Publisher: publish(repository_name, username, password, ...)
    Publisher->>PoetryConfig: get(repositories.{repository_name}.url)
    PoetryConfig-->>Publisher: url
    Publisher->>Normalizer: _normalize_legacy_repository_url(url)
    Normalizer-->>Publisher: normalized_url
    Publisher->>Uploader: upload(normalized_url, credentials, artifacts)
    Uploader-->>Publisher: result
    Publisher-->>User: publish_result
Loading

Updated class diagram for Publisher and legacy URL normalization

classDiagram
    class Publisher {
        - poetry
        - http_session
        + publish(repository_name, username, password, dry_run, cert, client_cert)
    }

    class _normalize_legacy_repository_url {
        + _normalize_legacy_repository_url(url str) str
    }

    class PoetryConfig {
        + get(key str) str
    }

    class Uploader {
        + upload(url str, username str, password str, artifacts list)
    }

    Publisher --> PoetryConfig : uses
    Publisher --> Uploader : uses
    Publisher --> _normalize_legacy_repository_url : calls
Loading

File-Level Changes

Change Details Files
Normalize legacy repository URLs used by Publisher.publish so /legacy endpoints always include a trailing slash when required.
  • Introduce a helper function that appends a trailing slash when the URL ends with the exact path segment '/legacy' without a slash.
  • Wire the normalization helper into Publisher.publish so configured repository URLs are normalized before being passed to the uploader.
src/poetry/publishing/publisher.py
Add and adjust tests to verify URL normalization behavior and correct interaction with the uploader.
  • Add a parametrized test that covers missing trailing slash, existing trailing slash, and non-legacy URLs to ensure normalization behaves as expected.
  • Patch uploader auth and upload methods and switch to assert_called_once_with to correctly validate arguments and call counts in the publishing flow.
tests/publishing/test_publisher.py

Assessment against linked issues

Issue Objective Addressed Explanation
#6687 Ensure publishing to PEP 503 legacy repositories succeeds when the configured repository URL omits the trailing slash (e.g. https://test.pypi.org/legacy), by normalizing it to the correct upload URL.
#6687 Ensure that poetry config pypi-token.<repository> correctly stores and applies API tokens for authenticated publishing, avoiding the need to specify username/password explicitly. The PR only introduces URL normalization for legacy repository URLs and associated tests. It does not modify token storage, configuration handling, or authentication logic related to pypi-token.<repository>.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 25, 2026

Documentation Updates

1 document(s) were updated by changes in this PR:

configuration
View Changes
@@ -564,6 +564,10 @@
 
 See [Publishable Repositories]({{< relref "repositories#publishable-repositories" >}}) for more information.
 
+{{% note %}}
+Poetry automatically normalizes legacy repository URLs by adding a trailing slash if one is missing. This means both `https://test.pypi.org/legacy` and `https://test.pypi.org/legacy/` will work correctly when publishing.
+{{% /note %}}
+
 ### `http-basic.<name>.[username|password]`
 
 **Type**: `string`

How did I do? Any feedback?  Join Discord

@bibekmhj
Copy link
Copy Markdown
Contributor Author

pre-commit.ci autofix

@radoering radoering added the impact/docs Contains or requires documentation changes label Mar 28, 2026
@github-actions
Copy link
Copy Markdown

Deploy preview for website ready!

✅ Preview
https://website-hoy50ou4k-python-poetry.vercel.app

Built with commit 941a9c2.
This pull request is being automatically deployed with vercel-action

@radoering radoering merged commit a35955f into python-poetry:main Mar 28, 2026
57 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

impact/docs Contains or requires documentation changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Omitting trailing slash on some PEP 503 repositories prevents inferring the correct upload URL

2 participants