fix(tests): strip ANSI from Typer --help output + patch os.environ for null-byte test (v0.29.0)

CI failures on macOS/Windows:

1. `test_endpoint_rejects_null_byte` — ``monkeypatch.setenv("HF_ENDPOINT",
   "...\x00")`` raises ``ValueError: embedded null byte`` at the C-level
   setenv call on macOS/Windows before ``resolve_endpoint`` can reject it.
   Linux's setenv swallows it. Replace with ``monkeypatch.setattr`` on
   ``os.environ`` dict so the null-byte string reaches ``resolve_endpoint``
   on every platform.

2. Help-text substring tests (``test_train_shows_push_as_flag_in_help``,
   ``test_push_shows_collection_flag_in_help``, ``test_push_subcommand_exists``,
   ``test_hf_space_help_shows_flags``, ``test_train_help_shows_hf_resume``,
   ``test_hf_space_command_registered``) — Typer injects ANSI escape codes
   on macOS/Windows pytest runs, splitting tokens like ``--push-as`` into
   ``-`` + ``-push-as`` across escape groups. Add ``_plain()`` helper that
   strips ANSI via regex and use it in every help-text assertion.

   Same pattern as 899ad8e (test_eval_gate.py) did after the v0.26.0 CI
   Windows failure.

Full suite still passes locally: 100 HF integration tests in 3.25s.
This commit is contained in:
Alpamys 2026-04-24 11:06:45 +05:00
parent 03ddc05573
commit 9aff44ac5f
1 changed files with 25 additions and 10 deletions

View File

@ -3,6 +3,7 @@
from __future__ import annotations
import json
import re
import sys
import types
from unittest.mock import MagicMock
@ -14,6 +15,16 @@ from soup_cli.cli import app
runner = CliRunner()
# Strip ANSI colour / style escape sequences before substring assertions —
# macOS/Windows Typer runs inject them even under pytest, and they split
# tokens like ``--push-as`` into ``-`` + ``-push-as`` across escape groups.
# Same pattern as ``test_eval_gate.py`` after the 899ad8e fix.
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*m")
def _plain(text: str) -> str:
return _ANSI_RE.sub("", text or "")
# ---------------------------------------------------------------------------
# Part A: utils/hf.py — token / endpoint / repo_id resolution
@ -106,7 +117,12 @@ class TestResolveEndpoint:
assert resolve_endpoint() == "http://localhost:8080"
def test_endpoint_rejects_null_byte(self, monkeypatch):
monkeypatch.setenv("HF_ENDPOINT", "https://hf.example.com\x00")
# OS-level setenv rejects null bytes on macOS/Windows before
# ``resolve_endpoint`` ever runs, so patch the dict directly.
monkeypatch.setattr(
"soup_cli.utils.hf.os.environ",
{"HF_ENDPOINT": "https://hf.example.com\x00"},
)
from soup_cli.utils.hf import resolve_endpoint
with pytest.raises(ValueError):
@ -214,8 +230,7 @@ class TestGetHfApi:
class TestPushAsCLIFlag:
def test_train_shows_push_as_flag_in_help(self):
result = runner.invoke(app, ["train", "--help"])
out = result.output
assert "--push-as" in out
assert "--push-as" in _plain(result.output)
def test_push_as_rejects_invalid_repo(self, tmp_path, monkeypatch):
cfg = tmp_path / "soup.yaml"
@ -443,7 +458,7 @@ class TestModelCardV2:
class TestCollections:
def test_push_shows_collection_flag_in_help(self):
result = runner.invoke(app, ["push", "--help"])
assert "--collection" in result.output
assert "--collection" in _plain(result.output)
def test_add_to_collection_calls_api(self, monkeypatch):
from soup_cli.utils.hf import add_to_collection
@ -496,7 +511,7 @@ class TestDataPush:
def test_push_subcommand_exists(self):
result = runner.invoke(app, ["data", "push", "--help"])
assert result.exit_code == 0, (result.output, repr(result.exception))
assert "--hf-dataset" in result.output
assert "--hf-dataset" in _plain(result.output)
def test_push_rejects_missing_file(self, tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
@ -604,13 +619,14 @@ class TestDataPush:
class TestDeployHfSpace:
def test_hf_space_command_registered(self):
result = runner.invoke(app, ["deploy", "--help"])
assert "hf-space" in result.output
assert "hf-space" in _plain(result.output)
def test_hf_space_help_shows_flags(self):
result = runner.invoke(app, ["deploy", "hf-space", "--help"])
assert result.exit_code == 0, (result.output, repr(result.exception))
assert "--model" in result.output
assert "--template" in result.output
plain = _plain(result.output)
assert "--model" in plain
assert "--template" in plain
def test_hf_space_rejects_invalid_repo(self, tmp_path, monkeypatch):
monkeypatch.chdir(tmp_path)
@ -740,8 +756,7 @@ class TestDeployHfSpace:
class TestAutoResume:
def test_train_help_shows_hf_resume(self):
result = runner.invoke(app, ["train", "--help"])
out = result.output
assert "--hf-resume" in out or "hf-resume" in out.lower().replace("-", "")
assert "--hf-resume" in _plain(result.output)
def test_prepare_hf_resume_downloads_latest(self, tmp_path, monkeypatch):
from soup_cli.monitoring.hf_push import prepare_hf_resume