From 501be971e790c9c00e2010fcf38ef1a67fda5442 Mon Sep 17 00:00:00 2001 From: Andrey Epifancev Date: Wed, 28 Oct 2026 21:58:39 +0400 Subject: [PATCH] =?UTF-8?q?perf(gen):=20grow=20=D0=BD=D0=B5=20=D0=BF=D0=B0?= =?UTF-8?q?=D0=B4=D0=B0=D0=B5=D1=82=20=D0=BD=D0=B0=20=D0=BE=D1=82=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=D1=85=20=D0=BB=D0=B8=D1=81=D1=82=D0=B0=20?= =?UTF-8?q?=D0=B1=D0=B5=D0=B7=20null-=D0=BF=D0=BE=D0=BB=D0=B5=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit form4_ids вычисляет vsp_ids и project_ids из строк FORM_4 через .get с пропуском отсутствующих ключей, grow_form4_sheet использует её. Co-Authored-By: Claude Opus 5.5 --- perf/perfkit/gen/grow.py | 20 ++++++++++++++++++-- perf/tests/test_gen_grow.py | 14 +++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/perf/perfkit/gen/grow.py b/perf/perfkit/gen/grow.py index 005cd0b..0675a3f 100644 --- a/perf/perfkit/gen/grow.py +++ b/perf/perfkit/gen/grow.py @@ -60,11 +60,27 @@ async def grow_vsp_sheet(api: Api, form_id: int, sheet: str, need: int, org_inde return need +def form4_ids(rows: list[dict]) -> tuple[list[int], list[int]]: + """(vsp_ids, project_ids) из строк листа FORM_4; отсутствующие ключи (data/header/vsp_id/project_id) пропускаются.""" + vsp_ids: set[int] = set() + project_ids: set[int] = set() + for r in rows: + header = (r.get("data") or {}).get("header") or {} + if r.get("row_type") == "INPUT": + vid = header.get("vsp_id") + if vid is not None: + vsp_ids.add(vid) + elif r.get("row_type") == "ITEM": + pid = header.get("project_id") + if pid is not None: + project_ids.add(pid) + return sorted(vsp_ids), sorted(project_ids) + + async def grow_form4_sheet(api: Api, form_id: int, sheet: str, need: int) -> int: path = f"/form/{form_id}/sheet/{sheet}" rows = (await api.get(path))["result"] - vsp_ids = sorted({r["data"]["header"]["vsp_id"] for r in rows if r.get("row_type") == "INPUT" and r["data"]["header"].get("vsp_id")}) - project_ids = sorted({r["data"]["header"]["project_id"] for r in rows if r.get("row_type") == "ITEM"}) + vsp_ids, project_ids = form4_ids(rows) if not project_ids: raise RuntimeError(f"{sheet}: нет проектов") leaves = await leaf_items(api, "FORM_4", sheet) diff --git a/perf/tests/test_gen_grow.py b/perf/tests/test_gen_grow.py index 1b4aa4e..70e7d6e 100644 --- a/perf/tests/test_gen_grow.py +++ b/perf/tests/test_gen_grow.py @@ -1,6 +1,6 @@ import pytest -from perfkit.gen.grow import rows_to_add, TARGETS +from perfkit.gen.grow import form4_ids, rows_to_add, TARGETS @pytest.mark.parametrize("cur,target,exp", [(31, 500, 469), (110, 300, 190), (500, 500, 0), (700, 500, 0), (0, 5, 5)]) @@ -12,3 +12,15 @@ def test_targets_do_not_touch_small_pair_sheets(): # AHR_RENT и FORM_4/AHR остаются малыми (пара для @big) assert ("FORM_2", "AHR_RENT") not in [(f, s) for f, s, _ in TARGETS] assert ("FORM_4", "AHR") not in [(f, s) for f, s, _ in TARGETS] + + +def test_form4_ids_tolerates_absent_keys(): + rows = [ + {"row_type": "INPUT", "data": {"header": {"vsp_id": 3}}}, + {"row_type": "INPUT", "data": {"header": {}}}, + {"row_type": "INPUT", "data": {}}, + {"row_type": "ITEM", "data": {"header": {"project_id": 11}}}, + {"row_type": "ITEM", "data": {"header": {}}}, + {"row_type": "ITEM", "data": {}}, + ] + assert form4_ids(rows) == ([3], [11])