build_fixed_row_by_index evaluated ~2 400 candidate paths per report row (7 million _pick_value calls per 13 800 rows). A reverse index "path -> (rule, candidate, probe)" is built once at import; per row we walk only the record's own fields and keep the best hit per rule, with the same candidate/probe ordering as _pick_value. Differential test compares the index with _pick_value on random and parsed payloads. Also: merged lookup reuses the operation lookup when the participant payload is empty, and index-free paths skip the regex normalisation. scripts/bench_report.py reproduces the measurement (0.42 -> 0.26 ms/row). Refs #1 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
52 lines
2.2 KiB
Python
52 lines
2.2 KiB
Python
"""Переиспользование lookup операции между строками одной операции.
|
||
|
||
Все строки одной операции (участники, continuation) приходят с одним и тем
|
||
же словарём operation_fields. Его lookup можно не пересобирать, но только
|
||
если результат не зависит от того, кешировался словарь или нет: изменение
|
||
содержимого словаря между вызовами обязано отражаться в строке.
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from app.pipeline.mapping import build_fixed_row
|
||
|
||
_OPERATION_CODE_COLUMN = "Код вида операции"
|
||
|
||
|
||
def _row(operation_fields: dict[str, str], participant_fields: dict[str, str]):
|
||
return build_fixed_row(
|
||
file_name="f.xml",
|
||
record_id="R1",
|
||
operation_index=1,
|
||
operation_fields=operation_fields,
|
||
participant_fields=participant_fields,
|
||
)
|
||
|
||
|
||
def test_same_operation_dict_across_rows_gives_same_values_as_fresh_dict() -> None:
|
||
shared = {"КодОперации": "5007", "СумОперации": "10.00"}
|
||
first = _row(shared, {"ИННФЛ": "111111111111", "Тип": "01"})
|
||
second = _row(shared, {"ИННФЛ": "222222222222", "Тип": "01"})
|
||
fresh = _row(dict(shared), {"ИННФЛ": "222222222222", "Тип": "01"})
|
||
|
||
assert first[_OPERATION_CODE_COLUMN] == "5007"
|
||
assert second == fresh
|
||
|
||
|
||
def test_mutating_operation_dict_between_rows_is_reflected() -> None:
|
||
operation = {"КодОперации": "5007"}
|
||
assert _row(operation, {})[_OPERATION_CODE_COLUMN] == "5007"
|
||
|
||
operation["КодОперации"] = "6001"
|
||
assert _row(operation, {})[_OPERATION_CODE_COLUMN] == "6001"
|
||
|
||
del operation["КодОперации"]
|
||
assert _row(operation, {})[_OPERATION_CODE_COLUMN] == ""
|
||
|
||
|
||
def test_empty_participant_row_equals_row_built_without_participant_data() -> None:
|
||
operation = {"КодОперации": "5007", "ИННФЛ": "333333333333"}
|
||
with_empty = _row(operation, {})
|
||
fresh = _row(dict(operation), dict())
|
||
assert with_empty == fresh
|