fix(pypi): support properly installing sdists via pypi without index (#3115)

This fixes the subtle bug introduced in #2871, where we were dropping
the URL from the requirement, because we can download the sdist
directly. We cannot add --no-index because sdists in general may
require extra build dependencies and we had already issues previously
(see 0.36 release notes).

Fixes #2363
Fixes #3131

---------

Co-authored-by: Richard Levasseur <richardlev@gmail.com>
(cherry picked from commit f6dd386697fa1302dcb089c46c565a05146c0b68)

Cherry-pick notes: adapted the changelog to mention 1.5.2
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6c4da84..2d99346 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -47,6 +47,16 @@
 END_UNRELEASED_TEMPLATE
 -->
 
+{#1-5-2}
+## [1.5.2] - 2025-08-11
+
+[1.5.2]: https://github.com/bazel-contrib/rules_python/releases/tag/1.5.2
+
+{#v1-5-2-fixed}
+### Fixed
+* (pypi) Correctly pull `sdist` distributions using `pip`
+  ([#3131](https://github.com/bazel-contrib/rules_python/pull/3131)).
+
 {#1-5-1}
 ## [1.5.1] - 2025-07-06
 
diff --git a/python/private/pypi/index_sources.bzl b/python/private/pypi/index_sources.bzl
index 803670c..1998e4f 100644
--- a/python/private/pypi/index_sources.bzl
+++ b/python/private/pypi/index_sources.bzl
@@ -93,12 +93,12 @@
                 is_known_ext = True
                 break
 
-        if is_known_ext:
+        requirement = requirement_line
+        if filename.endswith(".whl"):
             requirement = maybe_requirement.strip()
-        else:
+        elif not is_known_ext:
             # could not detect filename from the URL
             filename = ""
-            requirement = requirement_line
 
     return struct(
         requirement = requirement,
diff --git a/tests/pypi/extension/extension_tests.bzl b/tests/pypi/extension/extension_tests.bzl
index 8e32572..69dcfae 100644
--- a/tests/pypi/extension/extension_tests.bzl
+++ b/tests/pypi/extension/extension_tests.bzl
@@ -811,7 +811,7 @@
             "extra_pip_args": ["--extra-args-for-sdist-building"],
             "filename": "any-name.tar.gz",
             "python_interpreter_target": "unit_test_interpreter_target",
-            "requirement": "direct_sdist_without_sha",
+            "requirement": "direct_sdist_without_sha @ some-archive/any-name.tar.gz",
             "sha256": "",
             "urls": ["some-archive/any-name.tar.gz"],
         },
diff --git a/tests/pypi/index_sources/index_sources_tests.bzl b/tests/pypi/index_sources/index_sources_tests.bzl
index d4062b4..7aa22d1 100644
--- a/tests/pypi/index_sources/index_sources_tests.bzl
+++ b/tests/pypi/index_sources/index_sources_tests.bzl
@@ -73,7 +73,10 @@
             filename = "package.whl",
         ),
         "foo[extra] @ https://example.org/foo-1.0.tar.gz --hash=sha256:deadbe0f": struct(
-            requirement = "foo[extra]",
+            # NOTE @aignas 2025-08-03: we need to ensure that sdists continue working
+            # when we are using pip to install them even if the experimental_index_url
+            # code path is used.
+            requirement = "foo[extra] @ https://example.org/foo-1.0.tar.gz --hash=sha256:deadbe0f",
             requirement_line = "foo[extra] @ https://example.org/foo-1.0.tar.gz --hash=sha256:deadbe0f",
             marker = "",
             url = "https://example.org/foo-1.0.tar.gz",
diff --git a/tests/pypi/parse_requirements/parse_requirements_tests.bzl b/tests/pypi/parse_requirements/parse_requirements_tests.bzl
index 82fdd0a..b14467b 100644
--- a/tests/pypi/parse_requirements/parse_requirements_tests.bzl
+++ b/tests/pypi/parse_requirements/parse_requirements_tests.bzl
@@ -28,6 +28,9 @@
         "requirements_direct": """\
 foo[extra] @ https://some-url/package.whl
 """,
+        "requirements_direct_sdist": """
+foo @ https://github.com/org/foo/downloads/foo-1.1.tar.gz
+""",
         "requirements_extra_args": """\
 --index-url=example.org
 
@@ -131,22 +134,33 @@
         ctx = _mock_ctx(),
         requirements_by_platform = {
             "requirements_direct": ["linux_x86_64"],
+            "requirements_direct_sdist": ["osx_x86_64"],
         },
     )
     env.expect.that_collection(got).contains_exactly([
         struct(
             name = "foo",
             is_exposed = True,
-            is_multiple_versions = False,
+            is_multiple_versions = True,
             srcs = [
                 struct(
                     distribution = "foo",
                     extra_pip_args = [],
+                    filename = "foo-1.1.tar.gz",
+                    requirement_line = "foo @ https://github.com/org/foo/downloads/foo-1.1.tar.gz",
+                    sha256 = "",
+                    target_platforms = ["osx_x86_64"],
+                    url = "https://github.com/org/foo/downloads/foo-1.1.tar.gz",
+                    yanked = False,
+                ),
+                struct(
+                    distribution = "foo",
+                    extra_pip_args = [],
+                    filename = "package.whl",
                     requirement_line = "foo[extra]",
+                    sha256 = "",
                     target_platforms = ["linux_x86_64"],
                     url = "https://some-url/package.whl",
-                    filename = "package.whl",
-                    sha256 = "",
                     yanked = False,
                 ),
             ],