From a4a7d3b3b3c8c5d1950bb15b591fc1a4874da849 Mon Sep 17 00:00:00 2001 From: Eugene Toder Date: Mon, 4 Nov 2024 18:41:00 -0500 Subject: [PATCH] Fix sorting of proxy_map in PDMPyPIClient Sort proxy_map after constructing URLPatterns. URLPattern has logic to make more specific patterns sort first. Current code instead sorts URLs as strings, which orders them lexicographically. This means that URLs from `no_proxy` usually sort *after* URLs from `all_proxy` and so `no_proxy` settings have no effect. Fixes #3254 --- news/3254.bugfix.md | 1 + src/pdm/models/session.py | 3 ++- tests/models/test_session.py | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 news/3254.bugfix.md create mode 100644 tests/models/test_session.py diff --git a/news/3254.bugfix.md b/news/3254.bugfix.md new file mode 100644 index 0000000000..2fdfba6802 --- /dev/null +++ b/news/3254.bugfix.md @@ -0,0 +1 @@ +Fix using `no_proxy` when `all_proxy` is set. diff --git a/src/pdm/models/session.py b/src/pdm/models/session.py index b9a6c5516f..3cdd60cb0d 100644 --- a/src/pdm/models/session.py +++ b/src/pdm/models/session.py @@ -152,8 +152,9 @@ def cache_transport(transport: httpx.BaseTransport) -> httpx.BaseTransport: mounts: dict[str, httpx.BaseTransport] = {"file://": LocalFSTransport()} self._trusted_host_ports: set[tuple[str, int | None]] = set() self._proxy_map = { - URLPattern(key): proxy for key, proxy in sorted(self._get_proxy_map(None, allow_env_proxies=True).items()) + URLPattern(key): proxy for key, proxy in self._get_proxy_map(None, allow_env_proxies=True).items() } + self._proxy_map = dict(sorted(self._proxy_map.items())) for s in sources: assert s.url is not None url = httpx.URL(s.url) diff --git a/tests/models/test_session.py b/tests/models/test_session.py new file mode 100644 index 0000000000..908cd565f4 --- /dev/null +++ b/tests/models/test_session.py @@ -0,0 +1,24 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from pdm.project.core import Project + + +def test_session_sources_all_proxy(project: Project, mocker, monkeypatch): + monkeypatch.setenv("all_proxy", "http://localhost:8888") + mock_get_transport = mocker.patch("pdm.models.session._get_transport") + + assert project.environment.session is not None + transport_args = mock_get_transport.call_args + assert transport_args is not None + assert transport_args.kwargs["proxy"].url == "http://localhost:8888" + + monkeypatch.setenv("no_proxy", "pypi.org") + mock_get_transport.reset_mock() + del project.environment.session + assert project.environment.session is not None + transport_args = mock_get_transport.call_args + assert transport_args is not None + assert transport_args.kwargs["proxy"] is None