From 74b1758bb138355d5036631d8c92e7b0871339b2 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Wed, 26 Apr 2023 21:51:28 -0400 Subject: test: refactor and add a test of terminal link text --- coverage/html.py | 12 +++--------- coverage/misc.py | 12 ++++++++++++ tests/test_misc.py | 14 +++++++++++++- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/coverage/html.py b/coverage/html.py index 4e594343..f11d85e1 100644 --- a/coverage/html.py +++ b/coverage/html.py @@ -13,7 +13,6 @@ import os import re import shutil import string # pylint: disable=deprecated-module -import sys from dataclasses import dataclass from typing import Any, Dict, Iterable, List, Optional, Tuple, TYPE_CHECKING, cast @@ -23,7 +22,7 @@ from coverage.data import CoverageData, add_data_to_hash from coverage.exceptions import NoDataError from coverage.files import flat_rootname from coverage.misc import ensure_dir, file_be_gone, Hasher, isolate_module, format_local_datetime -from coverage.misc import human_sorted, plural +from coverage.misc import human_sorted, plural, stdout_link from coverage.report import get_analysis_to_report from coverage.results import Analysis, Numbers from coverage.templite import Templite @@ -495,13 +494,8 @@ class HtmlReporter: index_file = os.path.join(self.directory, "index.html") write_html(index_file, html) - if sys.stdout.isatty(): - file_path = f"file://{os.path.abspath(index_file)}" - print_path = f"\033]8;;{file_path}\a{index_file}\033]8;;\a" - else: - print_path = index_file - - self.coverage._message(f"Wrote HTML report to {print_path}") + print_href = stdout_link(index_file, f"file://{os.path.abspath(index_file)}") + self.coverage._message(f"Wrote HTML report to {print_href}") # Write the latest hashes for next time. self.incr.write() diff --git a/coverage/misc.py b/coverage/misc.py index 8cefa12e..061682ee 100644 --- a/coverage/misc.py +++ b/coverage/misc.py @@ -386,3 +386,15 @@ def plural(n: int, thing: str = "", things: str = "") -> str: return thing else: return things or (thing + "s") + + +def stdout_link(text: str, url: str) -> str: + """Format text+url as a clickable link for stdout. + + If attached to a terminal, use escape sequences. Otherwise, just return + the text. + """ + if 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 ba465cbd..455a3bc1 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -6,13 +6,14 @@ from __future__ import annotations import sys +from unittest import mock import pytest from coverage.exceptions import CoverageException from coverage.misc import file_be_gone from coverage.misc import Hasher, substitute_variables, import_third_party -from coverage.misc import human_sorted, human_sorted_items +from coverage.misc import human_sorted, human_sorted_items, stdout_link from tests.coveragetest import CoverageTest @@ -153,3 +154,14 @@ def test_human_sorted_items(words: str, ordered: str) -> None: oitems = [(k, v) for k in okeys for v in [1, 2]] assert human_sorted_items(items) == oitems assert human_sorted_items(items, reverse=True) == oitems[::-1] + + +def test_stdout_link_tty() -> None: + with mock.patch.object(sys.stdout, "isatty", lambda:True): + link = stdout_link("some text", "some url") + assert link == "\033]8;;some url\asome text\033]8;;\a" + + +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" -- cgit v1.2.1