All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
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 1m56s
CI / backend-tests (pull_request) Successful in 17m12s
`_detect_kind` проверял «резервир» первым и возвращал «резервирование» безусловно. Постановление об изъятии, где резервирование упомянуто вскользь — типовая формулировка «ранее зарезервированных земель», ссылка на утративший силу акт, — классифицировалось как резервирование. Ошибка не единичная: `kind` в `extract_reservations` один на весь документ, поэтому неверный тип уходит в КАЖДУЮ строку land_reservation по этому акту. Побеждает то слово, что встретилось раньше. Тема документа стоит в заголовке, поэтому позиция — сигнал сильнее порядка проверок, и он симметричен: заголовок «О резервировании» так же выигрывает у «изъятия» в теле. Простая смена порядка проверок этой симметрии не даёт — на неё поставлен отдельный контроль. Текущих ошибок на проде нет, и это измерено: в land_reservation 27 строк, все из источника izyatie_ekb_ocr, все «изъятие», ни в одной выдержке слова «резервир» не встречается. Правка закрывает возможность, а не чинит существующую порчу. Двусторонне: против origin/main два теста красные с конкретным неверным значением (`assert 'резервирование' == 'изъятие'`). Контроли — симметрия заголовка, одиночные маркеры, откат к default_kind — зелёные с обеих сторон. Формулировки в тестах взяты с прода дословно (basis_act). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
83 lines
5.4 KiB
Python
83 lines
5.4 KiB
Python
"""Тип постановления определяется по первому упоминанию, а не по порядку проверок (#2464).
|
||
|
||
`_detect_kind` проверял «резервир» ПЕРВЫМ и возвращал «резервирование» безусловно.
|
||
Постановление об изъятии, где резервирование упомянуто вскользь — типовая
|
||
формулировка «ранее зарезервированных земель», ссылка на утративший силу акт, —
|
||
переклассифицировало **весь документ**: `kind` в `extract_reservations` один на
|
||
все участки, поэтому ошибка размножается на каждую строку `land_reservation`.
|
||
|
||
Побеждает то слово, что встретилось раньше. Тема документа стоит в заголовке,
|
||
поэтому позиция — сигнал сильнее порядка проверок, и он симметричен: заголовок
|
||
«О резервировании» так же выигрывает у «изъятия» в теле.
|
||
|
||
Формулировки взяты с прода: `basis_act` в `land_reservation` (источник
|
||
`izyatie_ekb_ocr`, 27 строк, все «изъятие») начинается со слов «Сообщение о
|
||
планируемом изъятии земельных участков…».
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
from app.services.scrapers.page_reservation_parser import (
|
||
_detect_kind,
|
||
extract_reservations,
|
||
)
|
||
|
||
# Заголовок — с прода, дословно.
|
||
_ЗАГОЛОВОК_ИЗЪЯТИЕ = (
|
||
"Сообщение о планируемом изъятии земельных участков и объектов недвижимого "
|
||
"имущества для муниципальных нужд в целях строительства улицы Энергостроителей"
|
||
)
|
||
|
||
|
||
def test_izyatie_in_title_wins_over_later_rezervirovanie() -> None:
|
||
"""Головной: упоминание резервирования в теле не переписывает тему заголовка.
|
||
|
||
На origin/main возвращается «резервирование» — неверное значение, а не отказ.
|
||
"""
|
||
text = (
|
||
f"{_ЗАГОЛОВОК_ИЗЪЯТИЕ}. Изъятию подлежат участки, ранее зарезервированные "
|
||
"постановлением о резервировании земель от 12.03.2019."
|
||
)
|
||
assert (
|
||
_detect_kind(text, "изъятие") == "изъятие"
|
||
), "документ об изъятии классифицирован по случайному упоминанию в теле"
|
||
|
||
|
||
def test_all_parcels_of_the_document_are_affected() -> None:
|
||
"""Ошибка типа размножается на КАЖДЫЙ участок — kind в документе один на всех."""
|
||
text = (
|
||
f"{_ЗАГОЛОВОК_ИЗЪЯТИЕ}. Изъять земельные участки с кадастровыми номерами "
|
||
"66:41:0303004:22, 66:41:0303004:23, 66:41:0206032:8499, ранее "
|
||
"зарезервированные постановлением о резервировании земель."
|
||
)
|
||
records = extract_reservations(text, default_kind="изъятие")
|
||
assert len(records) == 3, f"разобрано участков: {len(records)}"
|
||
kinds = {r.reservation_kind for r in records}
|
||
assert kinds == {"изъятие"}, f"типы участков: {kinds} — ошибка ушла бы во все строки"
|
||
|
||
|
||
def test_rezervirovanie_in_title_still_wins() -> None:
|
||
"""Контроль симметрии: заголовок о резервировании выигрывает у изъятия в теле.
|
||
|
||
Ловит «починку» через простую смену порядка проверок — она сломала бы этот случай.
|
||
"""
|
||
text = (
|
||
"Постановление о резервировании земель для муниципальных нужд. "
|
||
"Зарезервированные участки не подлежат изъятию до истечения срока."
|
||
)
|
||
assert _detect_kind(text, "изъятие") == "резервирование"
|
||
|
||
|
||
def test_single_keyword_documents_unchanged() -> None:
|
||
"""Контроль: документы с одним словом-маркером распознаются как раньше."""
|
||
assert _detect_kind("Об изъятии земельного участка", "резервирование") == "изъятие"
|
||
assert _detect_kind("О резервировании земель", "изъятие") == "резервирование"
|
||
|
||
|
||
def test_no_keyword_falls_back_to_default() -> None:
|
||
"""Контроль: без маркеров остаётся default_kind, а не выдуманный тип."""
|
||
assert _detect_kind("Об утверждении схемы расположения участка", "изъятие") == "изъятие"
|
||
assert (
|
||
_detect_kind("Об утверждении схемы расположения участка", "резервирование")
|
||
== "резервирование"
|
||
)
|