Coverage for src\genesis\parsers\sheet_nature.py: 100%

29 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-26 14:20 +0800

1from __future__ import annotations 

2 

3from enum import Enum 

4from typing import Any 

5 

6 

7class SheetNature(Enum): 

8 TABLE = "table" 

9 FREE_TEXT = "free_text" 

10 MIXED = "mixed" 

11 

12 

13def _non_empty(row: list[Any]) -> list[Any]: 

14 return [c for c in row if c is not None and str(c).strip() != ""] 

15 

16 

17def find_header_row(matrix: list[list[Any]]) -> int: 

18 for i, row in enumerate(matrix): 

19 if len(_non_empty(row)) >= 2: 

20 return i 

21 return -1 

22 

23 

24def _free_text_like(matrix: list[list[Any]]) -> bool: 

25 if not matrix: 

26 return True 

27 max_cols = max((len(row) for row in matrix), default=0) 

28 if max_cols <= 1: 

29 return True 

30 non_empty_rows = [r for r in matrix if _non_empty(r)] 

31 if len(non_empty_rows) / len(matrix) < 0.7: 

32 return True 

33 return find_header_row(matrix) == -1 

34 

35 

36def classify_sheet(matrix: list[list[Any]]) -> SheetNature: 

37 if _free_text_like(matrix): 

38 return SheetNature.FREE_TEXT 

39 header_row = find_header_row(matrix) 

40 if header_row >= 0: # pragma: no cover — _free_text_like()==False 时 find_header_row 恒 ≥0 

41 for row in matrix[header_row + 1:]: 

42 if any(str(c).strip().startswith(("・", "■")) for c in _non_empty(row)): 

43 return SheetNature.MIXED 

44 return SheetNature.TABLE