Repository: pdm-project/pdm

Issue:
PDM ignores no_proxy when all_proxy is set
- [x] I have searched the issue tracker and believe that this is not a duplicate.

## Steps to reproduce

```bash
$ export all_proxy=http://localhost:8888 # does not exist
$ export no_proxy=pypi.org
$ mkdir proj && cd proj
$ pdm init -n
Creating a pyproject.toml for PDM...
INFO: Using the first matched interpreter.
Virtualenv is created successfully at /home/elt/tmp/proj/.venv
Project is initialized successfully
WARNING: Failed to get latest version: [Errno 111] Connection refused
$ pdm add bitarray
Adding packages to default dependencies: bitarray
⠋ 0:00:00 Resolve for environment (==3.12.*) None
See /home/elt/.local/state/pdm/log/pdm-lock-h4xxhla8.log for detailed debug log.
[ConnectError]: [Errno 111] Connection refused
WARNING: Add '-v' to see the detailed traceback
```

## Actual behavior

PDM attempts to use proxy for pypi.org even though it is listed in `no_proxy`.

## Expected behavior

PDM should not use proxy for pypi.org when it is listed in `no_proxy`.

## Environment Information

```bash
$ pdm info
PDM version:
  2.20.0.post2.dev3+gacb40b07
Python Interpreter:
  /home/elt/tmp/proj/.venv/bin/python (3.12)
Project Root:
  /home/elt/tmp/proj
Local Packages:

$ pdm info --env
{
  "implementation_name": "cpython",
  "implementation_version": "3.12.3",
  "os_name": "posix",
  "platform_machine": "x86_64",
  "platform_release": "5.15.153.1-microsoft-standard-WSL2",
  "platform_system": "Linux",
  "platform_version": "#1 SMP Fri Mar 29 23:14:13 UTC 2024",
  "python_full_version": "3.12.3",
  "platform_python_implementation": "CPython",
  "python_version": "3.12",
  "sys_platform": "linux"
}
```


Discussion:
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/pdm-project/pdm/pull/3255?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 84.81%. Comparing base [(`acb40b0`)](https://app.codecov.io/gh/pdm-project/pdm/commit/acb40b0713c30466dcbab73e6b98d1add8e5dd98?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) to head [(`5e2dfe5`)](https://app.codecov.io/gh/pdm-project/pdm/commit/5e2dfe51ada81f3e2fc5e3a0a35b21d3b73daf05?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project).

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #3255      +/-   ##
==========================================
- Coverage   85.30%   84.81%   -0.50%     
==========================================
  Files         112      112              
  Lines       11351    11352       +1     
  Branches     2473     2473              
==========================================
- Hits         9683     9628      -55     
- Misses       1140     1187      +47     
- Partials      528      537       +9     
```

| [Flag](https://app.codecov.io/gh/pdm-project/pdm/pull/3255/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) | Coverage Δ | |
|---|---|---|
| [unittests](https://app.codecov.io/gh/pdm-project/pdm/pull/3255/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project) | `84.68% <100.00%> (-0.42%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project#carryforward-flags-in-the-pull-request-comment) to find out more.

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/pdm-project/pdm/pull/3255?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pdm-project).


Patch:
diff --git a/news/3254.bugfix.md b/news/3254.bugfix.md
new file mode 100644
index 00000000..2fdfba68
--- /dev/null
+++ b/news/3254.bugfix.md
@@ -0,0 +1,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 b9a6c551..3cdd60cb 100644
--- a/src/pdm/models/session.py
+++ b/src/pdm/models/session.py
@@ -152,8 +152,9 @@ class PDMPyPIClient(PyPIClient):
         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)


Test patch:
diff --git a/tests/models/test_session.py b/tests/models/test_session.py
new file mode 100644
index 00000000..908cd565
--- /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