chore: import upstream snapshot with attribution
Test / Code Quality (push) Has been cancelled
Test / Test (macos-latest, Python 3.10) (push) Has been cancelled
Test / Test (macos-latest, Python 3.11) (push) Has been cancelled
Test / Test (macos-latest, Python 3.12) (push) Has been cancelled
Test / Test (macos-latest, Python 3.13) (push) Has been cancelled
Test / Test (macos-latest, Python 3.14) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.10) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.11) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.12) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.13) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.14) (push) Has been cancelled
Test / Test (windows-latest, Python 3.10) (push) Has been cancelled
Test / Test (windows-latest, Python 3.11) (push) Has been cancelled
Test / Test (windows-latest, Python 3.12) (push) Has been cancelled
Test / Test (windows-latest, Python 3.13) (push) Has been cancelled
Test / Test (windows-latest, Python 3.14) (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
dependency-audit / pip-audit (push) Has been cancelled
Test / Code Quality (push) Has been cancelled
Test / Test (macos-latest, Python 3.10) (push) Has been cancelled
Test / Test (macos-latest, Python 3.11) (push) Has been cancelled
Test / Test (macos-latest, Python 3.12) (push) Has been cancelled
Test / Test (macos-latest, Python 3.13) (push) Has been cancelled
Test / Test (macos-latest, Python 3.14) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.10) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.11) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.12) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.13) (push) Has been cancelled
Test / Test (ubuntu-latest, Python 3.14) (push) Has been cancelled
Test / Test (windows-latest, Python 3.10) (push) Has been cancelled
Test / Test (windows-latest, Python 3.11) (push) Has been cancelled
Test / Test (windows-latest, Python 3.12) (push) Has been cancelled
Test / Test (windows-latest, Python 3.13) (push) Has been cancelled
Test / Test (windows-latest, Python 3.14) (push) Has been cancelled
CodeQL / Analyze (push) Has been cancelled
dependency-audit / pip-audit (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
"""Tests for encoding-safe CLI output helpers."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
import notebooklm.cli._encoding as encoding_module
|
||||
from notebooklm.cli._encoding import replace_unencodable, safe_echo
|
||||
|
||||
|
||||
class DummyStream:
|
||||
def __init__(self, encoding):
|
||||
self.encoding = encoding
|
||||
|
||||
|
||||
class TestReplaceUnencodable:
|
||||
def test_preserves_text_encodable_by_stream(self):
|
||||
assert replace_unencodable("plain text", DummyStream("cp950")) == "plain text"
|
||||
|
||||
def test_replaces_text_not_encodable_by_stream(self):
|
||||
assert replace_unencodable("web 🌐", DummyStream("cp950")) == "web ?"
|
||||
|
||||
def test_uses_utf8_when_stream_encoding_is_missing(self):
|
||||
assert replace_unencodable("web 🌐", DummyStream(None)) == "web 🌐"
|
||||
|
||||
def test_uses_utf8_when_stream_is_none(self):
|
||||
assert replace_unencodable("web 🌐", None) == "web 🌐"
|
||||
|
||||
def test_unknown_encoding_falls_back_to_ascii_replacement(self):
|
||||
assert replace_unencodable("web 🌐", DummyStream("not-a-codec")) == "web ?"
|
||||
|
||||
|
||||
class TestSafeEcho:
|
||||
def test_echoes_original_message_when_first_write_succeeds(self):
|
||||
with patch.object(encoding_module.click, "echo") as mock_echo:
|
||||
safe_echo("web 🌐")
|
||||
|
||||
mock_echo.assert_called_once_with("web 🌐", err=False)
|
||||
|
||||
def test_replaces_stdout_text_when_first_write_cannot_encode(self):
|
||||
class DummyStdout:
|
||||
encoding = "cp950"
|
||||
|
||||
calls = []
|
||||
|
||||
def flaky_echo(message=None, **kwargs):
|
||||
if not calls:
|
||||
calls.append((message, kwargs.get("err", False)))
|
||||
raise UnicodeEncodeError(
|
||||
"cp950",
|
||||
str(message),
|
||||
4,
|
||||
5,
|
||||
"illegal multibyte sequence",
|
||||
)
|
||||
calls.append((message, kwargs.get("err", False)))
|
||||
|
||||
with (
|
||||
patch.object(encoding_module.click, "echo", side_effect=flaky_echo),
|
||||
patch.object(encoding_module.sys, "stdout", DummyStdout()),
|
||||
):
|
||||
safe_echo("web 🌐")
|
||||
|
||||
assert calls == [("web 🌐", False), ("web ?", False)]
|
||||
|
||||
def test_replaces_stderr_text_when_first_write_cannot_encode(self):
|
||||
class DummyStderr:
|
||||
encoding = "cp950"
|
||||
|
||||
calls = []
|
||||
|
||||
def flaky_echo(message=None, **kwargs):
|
||||
if not calls:
|
||||
calls.append((message, kwargs.get("err", False)))
|
||||
raise UnicodeEncodeError(
|
||||
"cp950",
|
||||
str(message),
|
||||
4,
|
||||
5,
|
||||
"illegal multibyte sequence",
|
||||
)
|
||||
calls.append((message, kwargs.get("err", False)))
|
||||
|
||||
with (
|
||||
patch.object(encoding_module.click, "echo", side_effect=flaky_echo),
|
||||
patch.object(encoding_module.sys, "stderr", DummyStderr()),
|
||||
):
|
||||
safe_echo("web 🌐", err=True)
|
||||
|
||||
assert calls == [("web 🌐", True), ("web ?", True)]
|
||||
Reference in New Issue
Block a user