feat: Sheet 性质判定(table/free_text/mixed)
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from enum import Enum
|
||||
from typing import Any
|
||||
|
||||
|
||||
class SheetNature(Enum):
|
||||
TABLE = "table"
|
||||
FREE_TEXT = "free_text"
|
||||
MIXED = "mixed"
|
||||
|
||||
|
||||
def _non_empty(row: list[Any]) -> list[Any]:
|
||||
return [c for c in row if c is not None and str(c).strip() != ""]
|
||||
|
||||
|
||||
def find_header_row(matrix: list[list[Any]]) -> int:
|
||||
for i, row in enumerate(matrix):
|
||||
if len(_non_empty(row)) >= 2:
|
||||
return i
|
||||
return -1
|
||||
|
||||
|
||||
def _free_text_like(matrix: list[list[Any]]) -> bool:
|
||||
if not matrix:
|
||||
return True
|
||||
max_cols = max((len(row) for row in matrix), default=0)
|
||||
if max_cols <= 1:
|
||||
return True
|
||||
non_empty_rows = [r for r in matrix if _non_empty(r)]
|
||||
if len(non_empty_rows) / len(matrix) < 0.7:
|
||||
return True
|
||||
return find_header_row(matrix) == -1
|
||||
|
||||
|
||||
def classify_sheet(matrix: list[list[Any]]) -> SheetNature:
|
||||
if _free_text_like(matrix):
|
||||
return SheetNature.FREE_TEXT
|
||||
header_row = find_header_row(matrix)
|
||||
if header_row >= 0:
|
||||
for row in matrix[header_row + 1:]:
|
||||
if any(str(c).strip().startswith(("・", "■")) for c in _non_empty(row)):
|
||||
return SheetNature.MIXED
|
||||
return SheetNature.TABLE
|
||||
@@ -0,0 +1,22 @@
|
||||
from genesis.parsers.sheet_nature import SheetNature, classify_sheet, find_header_row
|
||||
|
||||
|
||||
def test_table_detection():
|
||||
m = [["機能ID", "機能名"], ["A001", "社員登録"], ["A002", "退職処理"]]
|
||||
assert classify_sheet(m) == SheetNature.TABLE
|
||||
|
||||
|
||||
def test_free_text_single_col():
|
||||
m = [["新入社員を登録できる。"], ["氏名・所属・入社日を入力する。"]]
|
||||
assert classify_sheet(m) == SheetNature.FREE_TEXT
|
||||
|
||||
|
||||
def test_free_text_many_empty_rows():
|
||||
m = [["要求A"], [], [], [], ["要求B"]]
|
||||
assert classify_sheet(m) == SheetNature.FREE_TEXT
|
||||
|
||||
|
||||
def test_header_row_index():
|
||||
m = [["機能ID", "名前"], ["1", "田中"]]
|
||||
assert find_header_row(m) == 0
|
||||
assert find_header_row([["自由テキスト"]]) == -1
|
||||
Reference in New Issue
Block a user