76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
"""Числовой формат числовых ячеек в `Cell.number_format` (#42): xlsx синтетикой, xls — реальным файлом из fixtures."""
|
||
|
||
import datetime
|
||
import io
|
||
from pathlib import Path
|
||
|
||
import openpyxl
|
||
import pytest
|
||
|
||
from src.parser.readers import read_book
|
||
from src.parser.readers import xlsb as xlsb_reader
|
||
from src.parser.readers._common import make_cell
|
||
from tests.unit.parser.test_readers import _FakeXlsbBook, _zip_with
|
||
|
||
FILLED_CELLS = 6
|
||
UNAGRANDE_XLS = "statements-xlsx/unagrande-group/2025-Q3/ББ. Лист 2 3кв.25.xls"
|
||
|
||
|
||
def _xlsx() -> bytes:
|
||
book = openpyxl.Workbook()
|
||
ws = book.active
|
||
assert ws is not None
|
||
ws["A1"] = 10741981390
|
||
ws["A1"].number_format = "#,##0,"
|
||
ws["A2"] = 586260.26
|
||
ws["A2"].number_format = "0,"
|
||
ws["A3"] = 5
|
||
ws["A4"] = 7
|
||
ws["A4"].number_format = "General"
|
||
ws["A5"] = "текст"
|
||
ws["A5"].number_format = "0,"
|
||
ws["A6"] = datetime.datetime(2025, 9, 30)
|
||
ws["A6"].number_format = "dd.mm.yyyy"
|
||
out = io.BytesIO()
|
||
book.save(out)
|
||
return out.getvalue()
|
||
|
||
|
||
def test_xlsx_number_format_is_kept_for_numbers_only() -> None:
|
||
sheets, _ = read_book(_xlsx(), "XLSX")
|
||
sheet = sheets[0]
|
||
|
||
assert sheet.cell(1, 1).number_format == "#,##0,"
|
||
assert sheet.cell(2, 1).number_format == "0,"
|
||
assert sheet.cell(3, 1).number_format is None # General по умолчанию
|
||
assert sheet.cell(4, 1).number_format is None # явный General
|
||
assert sheet.cell(5, 1).number_format is None # текст
|
||
assert sheet.cell(6, 1).kind == "date"
|
||
assert sheet.cell(6, 1).number_format is None # дата
|
||
assert len(sheet.cells) == FILLED_CELLS # разреженность: Cell только у непустых
|
||
|
||
|
||
def test_make_cell_number_format_rules() -> None:
|
||
assert make_cell(1.5, number_format="GENERAL").number_format is None # type: ignore[union-attr]
|
||
assert make_cell(1.5, number_format="").number_format is None # type: ignore[union-attr]
|
||
assert make_cell(1.5, number_format="0,").number_format == "0," # type: ignore[union-attr]
|
||
assert make_cell("x", number_format="0,").number_format is None # type: ignore[union-attr]
|
||
assert make_cell(datetime.datetime(2025, 1, 1), number_format="0,").number_format is None # type: ignore[union-attr]
|
||
|
||
|
||
@pytest.mark.fixtures
|
||
def test_xls_number_format_is_read(fixtures_dir: Path) -> None:
|
||
sheets, _ = read_book((fixtures_dir / UNAGRANDE_XLS).read_bytes(), "XLS")
|
||
|
||
formats = {cell.number_format for sheet in sheets for cell in sheet.cells.values() if cell.kind == "number"}
|
||
assert {"#,##0,", "0,", '[=0]"-"'} <= formats
|
||
assert all(cell.number_format is None for sheet in sheets for cell in sheet.cells.values() if cell.kind != "number")
|
||
|
||
|
||
def test_xlsb_cells_have_no_number_format(monkeypatch: pytest.MonkeyPatch) -> None:
|
||
monkeypatch.setattr(xlsb_reader.pyxlsb, "open_workbook", lambda _stream: _FakeXlsbBook())
|
||
|
||
sheets, _ = read_book(_zip_with("xl/workbook.bin"), "XLSB")
|
||
|
||
assert all(cell.number_format is None for cell in sheets[0].cells.values())
|