summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNed Batchelder <ned@nedbatchelder.com>2023-04-30 06:28:24 -0400
committerNed Batchelder <ned@nedbatchelder.com>2023-04-30 06:28:24 -0400
commit731e9a776539dde46ca4c626ed67a5a09e0fe76a (patch)
tree0bff422471183aafd12c6da0135642c1ecf10765
parent31c216b67ffb21c589fd39b55fe1bbd26d5bf705 (diff)
downloadpython-coveragepy-git-731e9a776539dde46ca4c626ed67a5a09e0fe76a.tar.gz
fix: a fake stdout might not have isatty
-rw-r--r--CHANGES.rst4
-rw-r--r--coverage/misc.py2
-rw-r--r--tests/test_misc.py17
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"