Skip to content

Commit 57ad7fa

Browse files
patchback[bot]bdracowebknjazpre-commit-ci[bot]
authored
[PR #11714/0d77d0d6 backport][3.14] Fix loading netrc when NETRC env var is not set (#11728)
Co-authored-by: J. Nick Koston <[email protected]> Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> fixes #11713
1 parent 6d22d3a commit 57ad7fa

File tree

6 files changed

+50
-12
lines changed

6 files changed

+50
-12
lines changed

CHANGES/11713.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed loading netrc credentials from the default :file:`~/.netrc` (:file:`~/_netrc` on Windows) location when the :envvar:`NETRC` environment variable is not set -- by :user:`bdraco`.

CHANGES/11714.bugfix.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
11713.bugfix.rst

aiohttp/client.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -645,14 +645,7 @@ async def _request(
645645
auth = self._default_auth
646646

647647
# Try netrc if auth is still None and trust_env is enabled.
648-
# Only check if NETRC environment variable is set to avoid
649-
# creating an expensive executor job unnecessarily.
650-
if (
651-
auth is None
652-
and self._trust_env
653-
and url.host is not None
654-
and os.environ.get("NETRC")
655-
):
648+
if auth is None and self._trust_env and url.host is not None:
656649
auth = await self._loop.run_in_executor(
657650
None, self._get_netrc_auth, url.host
658651
)

tests/conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncio
22
import base64
33
import os
4+
import platform
45
import socket
56
import ssl
67
import sys
@@ -309,6 +310,23 @@ def netrc_other_host(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
309310
return netrc_file
310311

311312

313+
@pytest.fixture
314+
def netrc_home_directory(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
315+
"""Create a netrc file in a mocked home directory without setting NETRC env var."""
316+
home_dir = tmp_path / "home"
317+
home_dir.mkdir()
318+
netrc_filename = "_netrc" if platform.system() == "Windows" else ".netrc"
319+
netrc_file = home_dir / netrc_filename
320+
netrc_file.write_text("default login netrc_user password netrc_pass\n")
321+
322+
home_env_var = "USERPROFILE" if platform.system() == "Windows" else "HOME"
323+
monkeypatch.setenv(home_env_var, str(home_dir))
324+
# Ensure NETRC env var is not set
325+
monkeypatch.delenv("NETRC", raising=False)
326+
327+
return netrc_file
328+
329+
312330
@pytest.fixture
313331
def start_connection() -> Iterator[mock.Mock]:
314332
with mock.patch(

tests/test_client_functional.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3777,12 +3777,12 @@ async def test_netrc_auth_from_env( # type: ignore[misc]
37773777

37783778

37793779
@pytest.mark.usefixtures("no_netrc")
3780-
async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
3780+
async def test_netrc_auth_skipped_without_netrc_file( # type: ignore[misc]
37813781
headers_echo_client: Callable[
37823782
..., Awaitable[TestClient[web.Request, web.Application]]
37833783
],
37843784
) -> None:
3785-
"""Test that netrc authentication is skipped when NETRC env var is not set."""
3785+
"""Test that netrc authentication is skipped when no netrc file exists."""
37863786
client = await headers_echo_client(trust_env=True)
37873787
async with client.get("/") as r:
37883788
assert r.status == 200
@@ -3791,6 +3791,20 @@ async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
37913791
assert "Authorization" not in content["headers"]
37923792

37933793

3794+
@pytest.mark.usefixtures("netrc_home_directory")
3795+
async def test_netrc_auth_from_home_directory( # type: ignore[misc]
3796+
headers_echo_client: Callable[
3797+
..., Awaitable[TestClient[web.Request, web.Application]]
3798+
],
3799+
) -> None:
3800+
"""Test that netrc authentication works from default ~/.netrc without NETRC env var."""
3801+
client = await headers_echo_client(trust_env=True)
3802+
async with client.get("/") as r:
3803+
assert r.status == 200
3804+
content = await r.json()
3805+
assert content["headers"]["Authorization"] == "Basic bmV0cmNfdXNlcjpuZXRyY19wYXNz"
3806+
3807+
37943808
@pytest.mark.usefixtures("netrc_default_contents")
37953809
async def test_netrc_auth_overridden_by_explicit_auth( # type: ignore[misc]
37963810
headers_echo_client: Callable[

tests/test_client_session.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,8 +1366,8 @@ async def test_netrc_auth_skipped_without_trust_env(auth_server: TestServer) ->
13661366

13671367

13681368
@pytest.mark.usefixtures("no_netrc")
1369-
async def test_netrc_auth_skipped_without_netrc_env(auth_server: TestServer) -> None:
1370-
"""Test that netrc authentication is skipped when NETRC env var is not set."""
1369+
async def test_netrc_auth_skipped_without_netrc_file(auth_server: TestServer) -> None:
1370+
"""Test that netrc authentication is skipped when no netrc file exists."""
13711371
async with (
13721372
ClientSession(trust_env=True) as session,
13731373
session.get(auth_server.make_url("/")) as resp,
@@ -1376,6 +1376,17 @@ async def test_netrc_auth_skipped_without_netrc_env(auth_server: TestServer) ->
13761376
assert text == "no_auth"
13771377

13781378

1379+
@pytest.mark.usefixtures("netrc_home_directory")
1380+
async def test_netrc_auth_from_home_directory(auth_server: TestServer) -> None:
1381+
"""Test that netrc authentication works from default ~/.netrc location without NETRC env var."""
1382+
async with (
1383+
ClientSession(trust_env=True) as session,
1384+
session.get(auth_server.make_url("/")) as resp,
1385+
):
1386+
text = await resp.text()
1387+
assert text == "auth:Basic bmV0cmNfdXNlcjpuZXRyY19wYXNz"
1388+
1389+
13791390
@pytest.mark.usefixtures("netrc_default_contents")
13801391
async def test_netrc_auth_overridden_by_explicit_auth(auth_server: TestServer) -> None:
13811392
"""Test that explicit auth parameter overrides netrc authentication."""

0 commit comments

Comments
 (0)