- I-1 (R-23): readers/_limits.py — сумма ZipInfo.file_size ≤ 10 × PARSE_MAX_BYTES (параметр read_book от OsvParser), потоковый скан <mergeCell ref> до openpyxl и площадь merged после чтения любого формата (MERGED_AREA_LIMIT = 200 000; реальный максимум 10 090) → UNSUPPORTED_FORMAT; дедлайн в циклах detect (поиск строки групп, дополнительные колонки); README «Лимиты» исправлен, «Известные ограничения» (defusedxml). - I-2: OsvParser логирует стек непредвиденной ошибки (loguru ERROR), UNREADABLE — WARNING без стека. - M-1: ACCOUNT_RE с re.ASCII | re.DOTALL (многострочное название после запятой, только цифры 0–9). - M-3 (R-24): правило детектора ИНН не дополняет 9/11 цифр нулём; дополнение — только при извлечении (numbers.inn_digits) из колонки, выбранной по заголовку или по строгому правилу. - T9.1: тесты R-21 (свёрнутый родитель на противоположной стороне; (0,0) при детях (X, X)). - T1.1: хелперы фикстур пропускают скрытые файлы/каталоги и lock-файлы Excel (~$…). - T12.3: golden-update не удаляет снимки части без исходного каталога (osv/synthetic или реальные файлы). Golden-снимки не изменились (82/82). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
104 lines
3.9 KiB
Python
104 lines
3.9 KiB
Python
"""Хелперы доступа к ../fixtures: каталог из ARM_KA_FIXTURES, список файлов ОСВ без синтетики, причина skip."""
|
||
|
||
from pathlib import Path
|
||
|
||
import pytest
|
||
from fixtures_helpers import (
|
||
FIXTURES_ENV,
|
||
fixtures_skip_reason,
|
||
osv_fixture_files,
|
||
resolve_fixtures_dir,
|
||
synthetic_files,
|
||
synthetic_skip_reason,
|
||
)
|
||
|
||
|
||
def test_env_overrides_fixtures_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
assert resolve_fixtures_dir() == tmp_path
|
||
|
||
|
||
def test_default_fixtures_dir_is_sibling_of_repository(monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.delenv(FIXTURES_ENV, raising=False)
|
||
assert resolve_fixtures_dir() == Path(__file__).resolve().parents[4] / "fixtures"
|
||
|
||
|
||
def test_no_osv_directory_gives_no_files(tmp_path: Path) -> None:
|
||
assert osv_fixture_files(tmp_path) == []
|
||
assert synthetic_files(tmp_path) == []
|
||
|
||
|
||
def test_synthetic_excluded_and_foreign_files_ignored(tmp_path: Path) -> None:
|
||
osv = tmp_path / "osv"
|
||
(osv / "rb").mkdir(parents=True)
|
||
(osv / "synthetic").mkdir()
|
||
(osv / "rb" / "b.xlsx").write_bytes(b"")
|
||
(osv / "a.xls").write_bytes(b"")
|
||
(osv / "c.xlsb").write_bytes(b"")
|
||
(osv / ".DS_Store").write_bytes(b"")
|
||
(osv / "notes.txt").write_bytes(b"")
|
||
(osv / "synthetic" / "s.xlsx").write_bytes(b"")
|
||
(osv / "synthetic" / ".gitkeep").write_bytes(b"")
|
||
(osv / "synthetic" / "README.md").write_bytes(b"")
|
||
|
||
assert osv_fixture_files(tmp_path) == [osv / "a.xls", osv / "c.xlsb", osv / "rb" / "b.xlsx"]
|
||
assert synthetic_files(tmp_path) == [osv / "synthetic" / "s.xlsx"]
|
||
|
||
|
||
def test_hidden_and_excel_lock_files_are_ignored(tmp_path: Path) -> None:
|
||
"""T1.1: скрытые файлы и каталоги и lock-файлы Excel (`~$…`, пока книга открыта) — не фикстуры."""
|
||
osv = tmp_path / "osv"
|
||
(osv / "rb" / ".cache").mkdir(parents=True)
|
||
(osv / "synthetic").mkdir()
|
||
for path in (
|
||
osv / "rb" / "b.xlsx",
|
||
osv / "rb" / "~$b.xlsx",
|
||
osv / "rb" / ".b.xlsx",
|
||
osv / "rb" / ".cache" / "c.xlsx",
|
||
osv / "synthetic" / "s.xlsx",
|
||
osv / "synthetic" / "~$s.xlsx",
|
||
osv / "synthetic" / ".s.xls",
|
||
):
|
||
path.write_bytes(b"")
|
||
|
||
assert osv_fixture_files(tmp_path) == [osv / "rb" / "b.xlsx"]
|
||
assert synthetic_files(tmp_path) == [osv / "synthetic" / "s.xlsx"]
|
||
|
||
|
||
def test_skip_reason_mentions_env_and_path(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
missing = tmp_path / "нет-такого"
|
||
monkeypatch.setenv(FIXTURES_ENV, str(missing))
|
||
reason = fixtures_skip_reason()
|
||
assert reason is not None
|
||
assert FIXTURES_ENV in reason
|
||
assert str(missing) in reason
|
||
|
||
|
||
def test_skip_reason_none_when_available(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
(tmp_path / "osv").mkdir()
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
assert fixtures_skip_reason() is None
|
||
|
||
|
||
def test_synthetic_skip_reason_when_fixtures_exist_but_synthetic_is_missing_or_empty(
|
||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||
) -> None:
|
||
(tmp_path / "osv").mkdir()
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path))
|
||
reason = synthetic_skip_reason()
|
||
assert reason is not None
|
||
assert "osv" in reason
|
||
assert "synthetic" in reason
|
||
|
||
(tmp_path / "osv" / "synthetic").mkdir()
|
||
(tmp_path / "osv" / "synthetic" / "README.md").write_bytes(b"")
|
||
assert synthetic_skip_reason() == reason
|
||
|
||
(tmp_path / "osv" / "synthetic" / "s01.xlsx").write_bytes(b"")
|
||
assert synthetic_skip_reason() is None
|
||
|
||
|
||
def test_synthetic_skip_reason_is_none_without_fixtures(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.setenv(FIXTURES_ENV, str(tmp_path / "нет"))
|
||
assert synthetic_skip_reason() is None # причину тогда даёт fixtures_skip_reason
|