diff --git a/cncf-landscape/scripts/landscape_query.py b/cncf-landscape/scripts/landscape_query.py index 8054ba5..1c61bf1 100755 --- a/cncf-landscape/scripts/landscape_query.py +++ b/cncf-landscape/scripts/landscape_query.py @@ -205,13 +205,16 @@ def fetch_records( timeout: float, opener: Callable[..., Any] | None = None, ) -> tuple[list[Mapping[str, Any]], Mapping[str, Any]]: - request = Request( - url, - headers={ - "Accept": "application/json", - "User-Agent": "cncf-landscape-agent-skill/1.0", - }, - ) + try: + request = Request( + url, + headers={ + "Accept": "application/json", + "User-Agent": "cncf-landscape-agent-skill/1.0", + }, + ) + except ValueError as exc: + raise LandscapeError(f"Invalid Landscape API URL {url}: {exc}") from exc open_url = opener or urlopen try: with open_url(request, timeout=timeout) as response: diff --git a/cncf-landscape/tests/test_landscape_query.py b/cncf-landscape/tests/test_landscape_query.py index 412ddc0..3f9d242 100644 --- a/cncf-landscape/tests/test_landscape_query.py +++ b/cncf-landscape/tests/test_landscape_query.py @@ -2,8 +2,10 @@ """Offline tests for the CNCF Landscape query client.""" import importlib.util +import io import json import unittest +from contextlib import redirect_stderr from pathlib import Path SCRIPT = Path(__file__).resolve().parents[1] / "scripts" / "landscape_query.py" @@ -142,6 +144,15 @@ class LandscapeQueryTests(unittest.TestCase): with self.assertRaisesRegex(MODULE.LandscapeError, "Expected JSON"): MODULE.fetch_records("https://example.test/api/projects/all.json", 4.0, fake_opener(response)) + def test_malformed_base_url_uses_cli_error_path(self): + stderr = io.StringIO() + with redirect_stderr(stderr): + exit_code = MODULE.main(["--base-url", "not-a-url", "--timeout", "1"]) + + self.assertEqual(exit_code, 2) + self.assertIn("Error: Invalid Landscape API URL", stderr.getvalue()) + self.assertNotIn("Traceback", stderr.getvalue()) + def test_non_object_records_fail_closed(self): response = FakeResponse(b"[{}\n,\"not an object\"]") with self.assertRaisesRegex(MODULE.LandscapeError, "non-object record"):