Skip to content

Commit b734e04

Browse files
patchback[bot]bdracowebknjazpre-commit-ci[bot]
authored
[PR #11714/0d77d0d6 backport][3.13] Fix loading netrc when NETRC env var is not set (#11727)
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 e6042d2 commit b734e04

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
@@ -661,14 +661,7 @@ async def _request(
661661
auth = self._default_auth
662662

663663
# Try netrc if auth is still None and trust_env is enabled.
664-
# Only check if NETRC environment variable is set to avoid
665-
# creating an expensive executor job unnecessarily.
666-
if (
667-
auth is None
668-
and self._trust_env
669-
and url.host is not None
670-
and os.environ.get("NETRC")
671-
):
664+
if auth is None and self._trust_env and url.host is not None:
672665
auth = await self._loop.run_in_executor(
673666
None, self._get_netrc_auth, url.host
674667
)

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
@@ -308,6 +309,23 @@ def netrc_other_host(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
308309
return netrc_file
309310

310311

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

tests/test_client_functional.py

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

37863786

37873787
@pytest.mark.usefixtures("no_netrc")
3788-
async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
3788+
async def test_netrc_auth_skipped_without_netrc_file( # type: ignore[misc]
37893789
headers_echo_client: Callable[
37903790
..., Awaitable[TestClient[web.Request, web.Application]]
37913791
],
37923792
) -> None:
3793-
"""Test that netrc authentication is skipped when NETRC env var is not set."""
3793+
"""Test that netrc authentication is skipped when no netrc file exists."""
37943794
client = await headers_echo_client(trust_env=True)
37953795
async with client.get("/") as r:
37963796
assert r.status == 200
@@ -3799,6 +3799,20 @@ async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
37993799
assert "Authorization" not in content["headers"]
38003800

38013801

3802+
@pytest.mark.usefixtures("netrc_home_directory")
3803+
async def test_netrc_auth_from_home_directory( # type: ignore[misc]
3804+
headers_echo_client: Callable[
3805+
..., Awaitable[TestClient[web.Request, web.Application]]
3806+
],
3807+
) -> None:
3808+
"""Test that netrc authentication works from default ~/.netrc without NETRC env var."""
3809+
client = await headers_echo_client(trust_env=True)
3810+
async with client.get("/") as r:
3811+
assert r.status == 200
3812+
content = await r.json()
3813+
assert content["headers"]["Authorization"] == "Basic bmV0cmNfdXNlcjpuZXRyY19wYXNz"
3814+
3815+
38023816
@pytest.mark.usefixtures("netrc_default_contents")
38033817
async def test_netrc_auth_overridden_by_explicit_auth( # type: ignore[misc]
38043818
headers_echo_client: Callable[

tests/test_client_session.py

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

13661366

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

13771377

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

0 commit comments

Comments
 (0)