fix(ptica): scope=manual_list перестаёт создавать задание из пустоты (#2464) #2965

Merged
bot-backend merged 1 commit from fix/2464-manual-list-validation into main 2026-08-20 09:53:52 +00:00
Collaborator

Пункт эпика #2464: admin_cadastre.py:83.

Дефект

if scope == "manual_list":
    if not quarters:                     # ["  "] — непустой список, проходит
        raise HTTPException(400, ...)
    return [q.strip() for q in quarters if q.strip()]   # → []

Проверка непустоты стоит до очистки. Список из одних пробелов её проходит, а после strip оказывается пустым.

Что происходит дальше

_resolve_quarters возвращает [], и вызывающий без единой проверки:

  1. создаёт job-строку с нулём кварталов,
  2. ставит enqueue_cadastre_harvest в очередь Celery,
  3. возвращает targets_total: 0, estimate_minutes: 0.0.

Получается пустышка, неотличимая в списке заданий от настоящей.

Правка

Сначала чистим, потом проверяем. Прежние отказы (None, []) сохраняются.

Тест

Проверяет поведение: на пробельном вводе функция обязана отказать. Против origin/main падает по отсутствию отказа, а не по отсутствию символа:

["   "] · ["", "  ", "\t"] · ["\n"]   → DID NOT RAISE            → падает
None и []                             → контроль, зелёный обе стороны
годный список проходит и чистится     → контроль, зелёный обе стороны
смешанный список сохраняет живые      → контроль, зелёный обе стороны

Третий и четвёртый контроли не для симметрии: ловят «починку», которая отказывала бы на любом вводе с пробелами или отбрасывала бы смешанный список целиком.

Прогоны

tests/api/v1 -k cadastre   7 passed   rc=0
Пункт эпика #2464: `admin_cadastre.py:83`. ## Дефект ```python if scope == "manual_list": if not quarters: # [" "] — непустой список, проходит raise HTTPException(400, ...) return [q.strip() for q in quarters if q.strip()] # → [] ``` Проверка непустоты стоит **до** очистки. Список из одних пробелов её проходит, а после `strip` оказывается пустым. ## Что происходит дальше `_resolve_quarters` возвращает `[]`, и вызывающий без единой проверки: 1. создаёт job-строку с нулём кварталов, 2. ставит `enqueue_cadastre_harvest` в очередь Celery, 3. возвращает `targets_total: 0`, `estimate_minutes: 0.0`. Получается пустышка, неотличимая в списке заданий от настоящей. ## Правка Сначала чистим, потом проверяем. Прежние отказы (`None`, `[]`) сохраняются. ## Тест Проверяет **поведение**: на пробельном вводе функция обязана отказать. Против `origin/main` падает по **отсутствию отказа**, а не по отсутствию символа: ``` [" "] · ["", " ", "\t"] · ["\n"] → DID NOT RAISE → падает None и [] → контроль, зелёный обе стороны годный список проходит и чистится → контроль, зелёный обе стороны смешанный список сохраняет живые → контроль, зелёный обе стороны ``` Третий и четвёртый контроли не для симметрии: ловят «починку», которая отказывала бы на любом вводе с пробелами или отбрасывала бы смешанный список целиком. ## Прогоны ``` tests/api/v1 -k cadastre 7 passed rc=0 ```
bot-backend added 1 commit 2026-08-20 09:33:55 +00:00
fix(ptica): scope=manual_list перестаёт создавать задание из пустоты (#2464)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI / backend-tests (pull_request) Successful in 17m14s
d3d21b92f5
Проверка непустоты стояла ДО очистки:

    if not quarters:                       # ["  "] — непустой, проходит
        raise HTTPException(400, ...)
    return [q.strip() for q in quarters if q.strip()]   # → []

Список из одних пробелов проходил как непустой, а после strip оставался пустым.
Дальше по коду это молча создавало job с нулём кварталов, ставило его в очередь
Celery и возвращало targets_total=0 с estimate_minutes=0.0 — пустышку,
неотличимую в списке заданий от настоящей.

Правка: сначала чистим, потом проверяем. Прежние отказы (None, []) сохраняются.

Тест проверяет ПОВЕДЕНИЕ: на пробельном вводе функция обязана отказать. Против
origin/main три случая падают с «DID NOT RAISE» — то есть по отсутствию отказа,
а не по отсутствию символа.

  ["   "], ["", "  ", "\t"], ["\n"]   → DID NOT RAISE  → падает
  None и []                          — контроль, зелёный с обеих сторон
  годный список проходит и чистится  — контроль, зелёный с обеих сторон
  смешанный список сохраняет живые   — контроль, зелёный с обеих сторон

Третий и четвёртый контроли не для симметрии: они ловят «починку», которая
отказывала бы на любом вводе с пробелами или отбрасывала бы смешанный список
целиком.

Прогоны: tests/api/v1 -k cadastre — 7 passed rc=0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
bot-backend merged commit 497d2fa6ad into main 2026-08-20 09:53:52 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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#2965
No description provided.