fix(nspd): list_layers parse flat layers[] response, not children-tree #1077

Merged
bot-reviewer merged 1 commit from fix/nspd-list-layers-flat-parse into main 2026-06-06 17:51:15 +00:00
Owner

Баг

NSPDClient.list_layers() парсил _walk_layer_tree по id/children, но НСПД /api/geoportal/v1/layers-theme-tree?themeId=N отдаёт {"layers": [...flat...], "tree": ...} — слои лежат в плоском layers[] с ключом layerId (не id), не в children-дереве. → list_layers() молча возвращал [] для любой темы.

Найдено при ИРД-разведке НСПД 2026-06-06 (vault research/NSPD_IRD_Layers_Automation_Recon_Jun06). Не было замечено раньше, т.к. overlay layer-ID зашиты в LAYERS вручную — list_layers() нигде на горячем пути не использовался.

Фикс

list_layers(): сначала пробует плоский data["layers"] (актуальная форма, layerId), иначе fallback на _walk_layer_tree (старое nested-дерево id/children) + сохранён {"data": ...}-unwrap. Defensive на missing id (layerIdid → skip).

Тесты

  • test_list_layers_parses_flat_layers_response (новая форма). Старые тесты (nested-tree / data-wrapper / garbage) проходят без изменений — backward-compat сохранён.
    pytest tests/test_nspd_client.py32 passed. ruff check clean.

Refs #1067 (ИРД — discovery слоёв НСПД).

## Баг `NSPDClient.list_layers()` парсил `_walk_layer_tree` по `id`/`children`, но НСПД `/api/geoportal/v1/layers-theme-tree?themeId=N` отдаёт `{"layers": [...flat...], "tree": ...}` — слои лежат в **плоском `layers[]`** с ключом `layerId` (не `id`), не в children-дереве. → `list_layers()` молча возвращал `[]` для **любой** темы. Найдено при ИРД-разведке НСПД 2026-06-06 (vault `research/NSPD_IRD_Layers_Automation_Recon_Jun06`). Не было замечено раньше, т.к. overlay layer-ID зашиты в `LAYERS` вручную — `list_layers()` нигде на горячем пути не использовался. ## Фикс `list_layers()`: сначала пробует плоский `data["layers"]` (актуальная форма, `layerId`), иначе fallback на `_walk_layer_tree` (старое nested-дерево `id`/`children`) + сохранён `{"data": ...}`-unwrap. Defensive на missing id (`layerId` → `id` → skip). ## Тесты + `test_list_layers_parses_flat_layers_response` (новая форма). Старые тесты (nested-tree / data-wrapper / garbage) проходят без изменений — backward-compat сохранён. `pytest tests/test_nspd_client.py` → **32 passed**. `ruff check` clean. Refs #1067 (ИРД — discovery слоёв НСПД).
lekss361 added 1 commit 2026-06-06 17:45:20 +00:00
fix(nspd): list_layers parse flat layers[] response, not children-tree
All checks were successful
CI / changes (push) Successful in 7s
CI / changes (pull_request) Successful in 5s
CI / backend-tests (push) Successful in 5m46s
CI / backend-tests (pull_request) Successful in 5m45s
a609bcf741
НСПД /layers-theme-tree отдаёт {"layers":[...flat...], "tree":...} с ключом
layerId, а list_layers() ходил _walk_layer_tree по id/children → молча возвращал
[] для любой темы (слои не в children-дереве). Добавлен flat-layers путь с
fallback на nested-tree (id/children) + data-wrapper; defensive на missing id.

Refs #1067 (ИРД — discovery слоёв НСПД).
lekss361 added the
status/review
label 2026-06-06 17:46:09 +00:00
bot-reviewer reviewed 2026-06-06 17:50:49 +00:00
bot-reviewer left a comment
Collaborator

APPROVE

Логика корректна: приоритет data["layers"] (актуальный flat-формат, layerId) → fallback _walk_layer_tree (старое nested id/children) → [] при garbage. Все три пути покрыты тестами; backward-compat (nested-tree / data-wrapper / garbage) сохранён без изменений старых тестов. entry.get("layerId", entry.get("id")) + None-guard корректнее прежнего int(entry["id"]). Расширение data-unwrap guard на "layers" not in data верное.

Anti-regression проверена против HEAD ветки и vault (NSPD_IRD_Layers_Automation_Recon_Jun06) — diff применяется чисто, callers list_layers( не ломаются (раньше всегда [], downstream к пустому уже устойчив).

Минорные (advisory, не блок): пустой layers[] молча → [] без warning-лога — диагностический gap, не регрессия. В очередь не выношу.

Merge → деплой-verify.

<!-- gendesign-review-bot: sha=a609bcf verdict=approve --> ✅ **APPROVE** Логика корректна: приоритет `data["layers"]` (актуальный flat-формат, `layerId`) → fallback `_walk_layer_tree` (старое nested `id`/`children`) → `[]` при garbage. Все три пути покрыты тестами; backward-compat (nested-tree / data-wrapper / garbage) сохранён без изменений старых тестов. `entry.get("layerId", entry.get("id"))` + `None`-guard корректнее прежнего `int(entry["id"])`. Расширение data-unwrap guard на `"layers" not in data` верное. Anti-regression проверена против HEAD ветки и vault (`NSPD_IRD_Layers_Automation_Recon_Jun06`) — diff применяется чисто, callers `list_layers(` не ломаются (раньше всегда `[]`, downstream к пустому уже устойчив). Минорные (advisory, не блок): пустой `layers[]` молча → `[]` без warning-лога — диагностический gap, не регрессия. В очередь не выношу. Merge → деплой-verify.
bot-reviewer merged commit 38d948f078 into main 2026-06-06 17:51:15 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1077
No description provided.