Coverage for tests / unit / parsers / base_parser / test_safe_parse.py: 98%
47 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2026-04-03 18:53 +0000
1"""Tests for safe_parse_items function."""
3from __future__ import annotations
5from dataclasses import dataclass
6from unittest.mock import patch
8from assertpy import assert_that
10from lintro.parsers.base_issue import BaseIssue
11from lintro.parsers.base_parser import safe_parse_items
14@dataclass
15class TestIssue(BaseIssue):
16 """Simple test issue for safe_parse_items tests."""
18 pass
21def test_safe_parse_items_success() -> None:
22 """Parse all valid items successfully."""
23 items: list[object] = [{"file": "a.py", "line": 1}, {"file": "b.py", "line": 2}]
25 def parse_func(item: dict[str, object]) -> TestIssue:
26 # Values are validated at runtime; use explicit type checks for mypy
27 line_val = item["line"]
28 line = line_val if isinstance(line_val, int) else 0
29 return TestIssue(file=str(item["file"]), line=line)
31 results: list[TestIssue] = safe_parse_items(items, parse_func, "test_tool")
32 assert_that(results).is_length(2)
33 assert_that(results[0].file).is_equal_to("a.py")
36def test_safe_parse_items_skips_non_dict() -> None:
37 """Skip non-dictionary items."""
38 items: list[object] = [{"file": "a.py"}, "not_a_dict", 123]
40 def parse_func(item: dict[str, object]) -> TestIssue:
41 return TestIssue(file=str(item.get("file", "")))
43 with patch("lintro.parsers.base_parser.logger"):
44 results: list[TestIssue] = safe_parse_items(items, parse_func, "test_tool")
45 assert_that(results).is_length(1)
48def test_safe_parse_items_handles_parse_errors() -> None:
49 """Continue parsing after encountering errors."""
50 items: list[object] = [{"file": "a.py"}, {"bad": "data"}, {"file": "c.py"}]
52 def parse_func(item: dict[str, object]) -> TestIssue | None:
53 if "file" not in item:
54 raise KeyError("file")
55 return TestIssue(file=str(item["file"]))
57 with patch("lintro.parsers.base_parser.logger"):
58 results: list[TestIssue] = safe_parse_items(items, parse_func, "test_tool")
59 assert_that(results).is_length(2)
62def test_safe_parse_items_skips_none_results() -> None:
63 """Skip items where parse function returns None."""
64 items: list[object] = [{"file": "a.py"}, {"skip": True}, {"file": "c.py"}]
66 def parse_func(item: dict[str, object]) -> TestIssue | None:
67 if item.get("skip"):
68 return None
69 return TestIssue(file=str(item.get("file", "")))
71 results: list[TestIssue] = safe_parse_items(items, parse_func, "test_tool")
72 assert_that(results).is_length(2)
75def test_safe_parse_items_empty_list() -> None:
76 """Handle empty items list."""
78 def parse_func(item: dict[str, object]) -> TestIssue:
79 return TestIssue(file=str(item.get("file", "")))
81 results: list[TestIssue] = safe_parse_items([], parse_func, "test_tool")
82 assert_that(results).is_empty()