From b2f8930e558a0de69d2c9fbc4def64bc81c1e1af Mon Sep 17 00:00:00 2001 From: Thorsrud22 <229304553+Thorsrud22@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:56:31 +0200 Subject: [PATCH] fix: raise a clear TypeError when convert() is given a non-str Passing a list of lines to Ansi2HTMLConverter.convert() (or prepare()) used to fail deep inside the regex pass with "AttributeError: 'list' object has no attribute 'replace'", which gives no hint about what was wrong or how to fix it. Two users reported hitting this (#242). Check the input type once at the entry point and raise a TypeError that names the actual type and suggests joining the lines first. Fixes #242 --- src/ansi2html/converter.py | 6 ++++++ tests/test_ansi2html.py | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/src/ansi2html/converter.py b/src/ansi2html/converter.py index c9f29fd..774c820 100644 --- a/src/ansi2html/converter.py +++ b/src/ansi2html/converter.py @@ -607,6 +607,12 @@ def prepare( ) -> Attributes: """Load the contents of 'ansi' into this object""" + if not isinstance(ansi, str): + raise TypeError( + "ansi must be a str, not %s; join an iterable of lines first, " + "e.g. ''.join(lines)" % type(ansi).__name__ + ) + body, styles = self.apply_regex(ansi) if ensure_trailing_newline and _needs_extra_newline(body): diff --git a/tests/test_ansi2html.py b/tests/test_ansi2html.py index fedb954..e9e0d8b 100644 --- a/tests/test_ansi2html.py +++ b/tests/test_ansi2html.py @@ -29,6 +29,8 @@ from typing import List from unittest.mock import patch +import pytest + from ansi2html import Ansi2HTMLConverter from ansi2html.converter import ( ANSI_BLINK_FAST, @@ -57,6 +59,12 @@ def test_linkify(self) -> None: html = Ansi2HTMLConverter(linkify=True).convert(ansi) assert target in html + def test_convert_rejects_non_str_input(self) -> None: + # Passing a list of lines used to surface as an unhelpful + # AttributeError deep inside apply_regex (see #242). + with pytest.raises(TypeError, match="must be a str, not list"): + Ansi2HTMLConverter().convert(["a", "b"]) # type: ignore[arg-type] + def test_not_linkify(self) -> None: ansi = "http://threebean.org" target = 'http://threebean.org'