arm-tabular-parser/api/tests/fixtures/test_readers_real.py
Andrey Epifancev b5a3b480b2 feat(parser): модель листа Sheet и читатели xlsx/xls/xlsb
grid.py: Cell, MergedRange, Sheet (1-based, только непустые ячейки, ленивые
индексы строк и merged; диапазоны больше 10 000 ячеек проверяются перебором),
column_letter для диагностики. errors.py: ParserError и коды контракта.
readers: read_book определяет формат по сигнатуре (zip → XLSX/XLSB по
xl/workbook.bin, OLE2 → XLS), предупреждает о несовпадении с file_type;
ошибки библиотек → UnreadableError одной строкой. Числа — Decimal(str(value)),
bool отдельно, даты как datetime; xlsb без outline/merged с предупреждением.
Тесты: синтетическая книга openpyxl, подмена file_type, мусор/обрезанные
файлы, xlsb через подменённый pyxlsb; 66 реальных ОСВ читаются < 5 с с
outline и merged; xls «62 за 3 квартал 2024»: строка 15 — outline 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
2026-10-05 12:11:16 +04:00

50 lines
2.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Читатели на реальных ОСВ из ../fixtures: все 66 файлов читаются быстро, outline и merged на месте."""
import time
from pathlib import Path
from typing import cast
import pytest
from src.contract import FileType
from src.parser.readers import read_book
READ_SECONDS_LIMIT = 5.0
NAMED_XLS = "osv/schastl/2024-Q3/Оборотносальдовая ведомость по счету 62 за 3 квартал 2024 г..xls"
# Строка 15 (1-based) — контрагент «МАЛЕЧКИНСКАЯ ПТИЦЕФАБРИКА ООО» под 62 → 62.01 → «БП Аренда»
NAMED_XLS_ROW = 15
NAMED_XLS_OUTLINE = 3
@pytest.mark.fixtures
def test_real_file_is_read_quickly_with_outline_and_merged(osv_file: Path) -> None:
data = osv_file.read_bytes()
started = time.perf_counter()
sheets, warnings = read_book(data, cast(FileType, osv_file.suffix.lstrip(".").upper()))
assert time.perf_counter() - started < READ_SECONDS_LIMIT
assert warnings == []
assert sheets
assert any(sheet.row_outline for sheet in sheets)
assert all(level >= 1 for sheet in sheets for level in sheet.row_outline.values())
assert any(sheet.merged for sheet in sheets)
assert any(sheet.cells for sheet in sheets)
@pytest.mark.fixtures
def test_named_xls_outline_level(fixtures_dir: Path) -> None:
sheets, _ = read_book((fixtures_dir / NAMED_XLS).read_bytes(), "XLS")
sheet = sheets[0]
assert sheet.cell(NAMED_XLS_ROW, 1).text == "МАЛЕЧКИНСКАЯ ПТИЦЕФАБРИКА ООО"
assert sheet.outline(NAMED_XLS_ROW) == NAMED_XLS_OUTLINE
@pytest.mark.fixtures
def test_biff8_content_with_xlsx_file_type_is_read_as_xls(fixtures_dir: Path) -> None:
sheets, warnings = read_book((fixtures_dir / NAMED_XLS).read_bytes(), "XLSX")
assert warnings == ["file_type=XLSX, но содержимое BIFF8: прочитано как XLS"]
assert sheets[0].outline(NAMED_XLS_ROW) == NAMED_XLS_OUTLINE