Skip to content

Commit 0d77d0d

Browse files
bdracowebknjazpre-commit-ci[bot]
authored
Fix loading netrc when NETRC env var is not set (#11714)
Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 1fbb1bb commit 0d77d0d

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
@@ -590,14 +590,7 @@ async def _request(
590590
auth = self._default_auth
591591

592592
# Try netrc if auth is still None and trust_env is enabled.
593-
# Only check if NETRC environment variable is set to avoid
594-
# creating an expensive executor job unnecessarily.
595-
if (
596-
auth is None
597-
and self._trust_env
598-
and url.host is not None
599-
and os.environ.get("NETRC")
600-
):
593+
if auth is None and self._trust_env and url.host is not None:
601594
auth = await self._loop.run_in_executor(
602595
None, self._get_netrc_auth, url.host
603596
)

tests/conftest.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import asyncio
44
import base64
55
import os
6+
import platform
67
import socket
78
import ssl
89
import sys
@@ -329,6 +330,23 @@ def netrc_other_host(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
329330
return netrc_file
330331

331332

333+
@pytest.fixture
334+
def netrc_home_directory(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Path:
335+
"""Create a netrc file in a mocked home directory without setting NETRC env var."""
336+
home_dir = tmp_path / "home"
337+
home_dir.mkdir()
338+
netrc_filename = "_netrc" if platform.system() == "Windows" else ".netrc"
339+
netrc_file = home_dir / netrc_filename
340+
netrc_file.write_text("default login netrc_user password netrc_pass\n")
341+
342+
home_env_var = "USERPROFILE" if platform.system() == "Windows" else "HOME"
343+
monkeypatch.setenv(home_env_var, str(home_dir))
344+
# Ensure NETRC env var is not set
345+
monkeypatch.delenv("NETRC", raising=False)
346+
347+
return netrc_file
348+
349+
332350
@pytest.fixture
333351
def start_connection() -> Iterator[mock.Mock]:
334352
with mock.patch(

tests/test_client_functional.py

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

37493749

37503750
@pytest.mark.usefixtures("no_netrc")
3751-
async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
3751+
async def test_netrc_auth_skipped_without_netrc_file( # type: ignore[misc]
37523752
headers_echo_client: Callable[
37533753
..., Awaitable[TestClient[web.Request, web.Application]]
37543754
],
37553755
) -> None:
3756-
"""Test that netrc authentication is skipped when NETRC env var is not set."""
3756+
"""Test that netrc authentication is skipped when no netrc file exists."""
37573757
client = await headers_echo_client(trust_env=True)
37583758
async with client.get("/") as r:
37593759
assert r.status == 200
@@ -3762,6 +3762,20 @@ async def test_netrc_auth_skipped_without_env_var( # type: ignore[misc]
37623762
assert "Authorization" not in content["headers"]
37633763

37643764

3765+
@pytest.mark.usefixtures("netrc_home_directory")
3766+
async def test_netrc_auth_from_home_directory( # type: ignore[misc]
3767+
headers_echo_client: Callable[
3768+
..., Awaitable[TestClient[web.Request, web.Application]]
3769+
],
3770+
) -> None:
3771+
"""Test that netrc authentication works from default ~/.netrc without NETRC env var."""
3772+
client = await headers_echo_client(trust_env=True)
3773+
async with client.get("/") as r:
3774+
assert r.status == 200
3775+
content = await r.json()
3776+
assert content["headers"]["Authorization"] == "Basic bmV0cmNfdXNlcjpuZXRyY19wYXNz"
3777+
3778+
37653779
@pytest.mark.usefixtures("netrc_default_contents")
37663780
async def test_netrc_auth_overridden_by_explicit_auth( # type: ignore[misc]
37673781
headers_echo_client: Callable[

tests/test_client_session.py

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

13691369

13701370
@pytest.mark.usefixtures("no_netrc")
1371-
async def test_netrc_auth_skipped_without_netrc_env(auth_server: TestServer) -> None:
1372-
"""Test that netrc authentication is skipped when NETRC env var is not set."""
1371+
async def test_netrc_auth_skipped_without_netrc_file(auth_server: TestServer) -> None:
1372+
"""Test that netrc authentication is skipped when no netrc file exists."""
13731373
async with (
13741374
ClientSession(trust_env=True) as session,
13751375
session.get(auth_server.make_url("/")) as resp,
@@ -1378,6 +1378,17 @@ async def test_netrc_auth_skipped_without_netrc_env(auth_server: TestServer) ->
13781378
assert text == "no_auth"
13791379

13801380

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

0 commit comments

Comments
 (0)