Skip to content

Commit

Permalink
fix --index-url handling for Poetry 1.8 - second try (#270)
Browse files Browse the repository at this point in the history
- if PyPI is disabled the highest prio source get `--index-url`, others get `--extra-index-url`
- if PyPI is enabled we just do not use `--index-url`, all other source get `--extra-index-url`
- put `--index-url` before `--extra-index-url` to work around a pip bug
  • Loading branch information
radoering committed Mar 19, 2024
1 parent bce7f70 commit 07f8981
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 19 deletions.
36 changes: 18 additions & 18 deletions src/poetry_plugin_export/exporter.py
Expand Up @@ -143,7 +143,7 @@ def _export_generic_txt(
and not is_direct_local_reference
and package.source_url
):
indexes.add(package.source_url)
indexes.add(package.source_url.rstrip("/"))

if package.files and self._with_hashes:
hashes = []
Expand Down Expand Up @@ -171,22 +171,16 @@ def _export_generic_txt(
if indexes and self._with_urls:
# If we have extra indexes, we add them to the beginning of the output
indexes_header = ""
for index in sorted(indexes):
repositories = [
r
for r in self._poetry.pool.all_repositories
if isinstance(r, HTTPRepository) and r.url == index.rstrip("/")
]
if not repositories:
continue
repository = repositories[0]
if repository is self._poetry.pool.repositories[0]:
url = (
repository.authenticated_url
if self._with_credentials
else repository.url
)
indexes_header += f"--index-url {url}\n"
has_pypi_repository = any(
r.name.lower() == "pypi" for r in self._poetry.pool.all_repositories
)
# Iterate over repositories so that we get the repository with the highest
# priority first so that --index-url comes before --extra-index-url
for repository in self._poetry.pool.all_repositories:
if (
not isinstance(repository, HTTPRepository)
or repository.url not in indexes
):
continue

url = (
Expand All @@ -197,7 +191,13 @@ def _export_generic_txt(
parsed_url = urllib.parse.urlsplit(url)
if parsed_url.scheme == "http":
indexes_header += f"--trusted-host {parsed_url.netloc}\n"
indexes_header += f"--extra-index-url {url}\n"
if (
not has_pypi_repository
and repository is self._poetry.pool.repositories[0]
):
indexes_header += f"--index-url {url}\n"
else:
indexes_header += f"--extra-index-url {url}\n"

content = indexes_header + "\n" + content

Expand Down
121 changes: 120 additions & 1 deletion tests/test_exporter.py
Expand Up @@ -1878,8 +1878,8 @@ def test_exporter_exports_requirements_txt_with_two_primary_sources(
content = f.read()

expected = f"""\
--extra-index-url https://foo:bar@a.example.com/simple
--index-url https://baz:qux@b.example.com/simple
--extra-index-url https://foo:bar@a.example.com/simple
bar==4.5.6 ; {MARKER_PY} \\
--hash=sha256:67890
Expand Down Expand Up @@ -2795,3 +2795,122 @@ def test_exporter_not_confused_by_extras_in_sub_dependencies(
typer[all]==0.9.0 ; python_version >= "3.11" and python_version < "4.0"
"""
assert io.fetch_output() == expected


@pytest.mark.parametrize(
("priorities", "expected"),
[
([("custom-a", Priority.PRIMARY), ("custom-b", Priority.PRIMARY)], ("a", "b")),
([("custom-b", Priority.PRIMARY), ("custom-a", Priority.PRIMARY)], ("b", "a")),
(
[("custom-b", Priority.SUPPLEMENTAL), ("custom-a", Priority.PRIMARY)],
("a", "b"),
),
([("custom-b", Priority.EXPLICIT), ("custom-a", Priority.PRIMARY)], ("a", "b")),
(
[
("PyPI", Priority.PRIMARY),
("custom-a", Priority.PRIMARY),
("custom-b", Priority.PRIMARY),
],
("", "a", "b"),
),
(
[
("PyPI", Priority.EXPLICIT),
("custom-a", Priority.PRIMARY),
("custom-b", Priority.PRIMARY),
],
("", "a", "b"),
),
(
[
("custom-a", Priority.PRIMARY),
("custom-b", Priority.PRIMARY),
("PyPI", Priority.SUPPLEMENTAL),
],
("", "a", "b"),
),
],
)
def test_exporter_index_urls(
tmp_path: Path,
poetry: Poetry,
priorities: list[tuple[str, Priority]],
expected: tuple[str, ...],
) -> None:
pypi = poetry.pool.repository("PyPI")
poetry.pool.remove_repository("PyPI")
for name, prio in priorities:
if name.lower() == "pypi":
repo = pypi
else:
repo = LegacyRepository(name, f"https://{name[-1]}.example.com/simple")
poetry.pool.add_repository(repo, priority=prio)

poetry.locker.mock_lock_data( # type: ignore[attr-defined]
{
"package": [
{
"name": "foo",
"version": "1.2.3",
"optional": False,
"python-versions": "*",
"source": {
"type": "legacy",
"url": "https://a.example.com/simple",
"reference": "",
},
},
{
"name": "bar",
"version": "4.5.6",
"optional": False,
"python-versions": "*",
"source": {
"type": "legacy",
"url": "https://b.example.com/simple",
"reference": "",
},
},
],
"metadata": {
"python-versions": "*",
"content-hash": "123456789",
"files": {
"foo": [{"name": "foo.whl", "hash": "12345"}],
"bar": [{"name": "bar.whl", "hash": "67890"}],
},
},
}
)
set_package_requires(poetry, dev={"bar"})

exporter = Exporter(poetry, NullIO())
exporter.only_groups([MAIN_GROUP, "dev"])
exporter.export("requirements.txt", tmp_path, "requirements.txt")

with (tmp_path / "requirements.txt").open(encoding="utf-8") as f:
content = f.read()

expected_urls = [
f"--extra-index-url https://{name[-1]}.example.com/simple"
for name in expected[1:]
]
if expected[0]:
expected_urls = [
f"--index-url https://{expected[0]}.example.com/simple",
*expected_urls,
]
url_string = "\n".join(expected_urls)

expected_content = f"""\
{url_string}
bar==4.5.6 ; {MARKER_PY} \\
--hash=sha256:67890
foo==1.2.3 ; {MARKER_PY} \\
--hash=sha256:12345
"""

assert content == expected_content

0 comments on commit 07f8981

Please sign in to comment.