From 731e9a776539dde46ca4c626ed67a5a09e0fe76a Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sun, 30 Apr 2023 06:28:24 -0400 Subject: fix: a fake stdout might not have isatty --- CHANGES.rst | 4 +++- coverage/misc.py | 2 +- tests/test_misc.py | 17 +++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 1d3364b5..987442e2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,7 +20,9 @@ development at the same time, such as 4.5.x and 5.0. Unreleased ---------- -Nothing yet. +- Fix: ``html_report()`` could fail with an AttributeError on ``isatty`` if run + in an unusual environment where sys.stdout had been replaced. This is now + fixed. .. scriv-start-here diff --git a/coverage/misc.py b/coverage/misc.py index 061682ee..908b0dd2 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -394,7 +394,7 @@ def stdout_link(text: str, url: str) -> str: If attached to a terminal, use escape sequences. Otherwise, just return the text. """ - if sys.stdout.isatty(): + if hasattr(sys.stdout, "isatty") and sys.stdout.isatty(): return f"\033]8;;{url}\a{text}\033]8;;\a" else: return text diff --git a/tests/test_misc.py b/tests/test_misc.py index 455a3bc1..d489f171 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -6,6 +6,7 @@ from __future__ import annotations import sys +from typing import Any from unittest import mock import pytest @@ -165,3 +166,19 @@ def test_stdout_link_tty() -> None: def test_stdout_link_not_tty() -> None: # Without mocking isatty, it reports False in a pytest suite. assert stdout_link("some text", "some url") == "some text" + + +def test_stdout_link_with_fake_stdout() -> None: + # If stdout is another object, we should still be ok. + class FakeStdout: + """New stdout, has .write(), but not .isatty().""" + def __init__(self, f: Any) -> None: + self.f = f + + def write(self, data: str) -> Any: + """Write through to the underlying file.""" + return self.f.write(data) + + with mock.patch.object(sys, "stdout", FakeStdout(sys.stdout)): + link = stdout_link("some text", "some url") + assert link == "some text" -- cgit v1.2.1