fix(tradein): extract_street_name handles Nominatim reverse format #557
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#557
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/tradein-extract-street-name-reverse"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Live bug
На проде после deploy PR-C: секция «По вашей улице» не показывалась — endpoint возвращал
count=0для любого реального адреса.Real browser request (DevTools captured):
Root cause
extract_street_name()была спроектирована под FORWARD-формат ("ул. Космонавтов, 50"), ноgeo.full_addressот geocoder Nominatim — REVERSE-формат:Старая логика:
_extract_short_addrнаходит keyword"улица"→ возвращает остаток до конца строки_TRAILING_HOUSE_RE = r',\s*\d+.*$'→ matches последний postal-index (, 640144, Россия) — но.*$greedy → strip последние 2 элемента, оставив всю админ-кишку_STREET_PREFIX_REотрезает"улица ""8 Марта, Артек, Форум-Сити, Ленинский район, Екатеринбург, ..."⛔ILIKE '%<мусор>%'→ 0 matches вtradein.dealsVerified локально на production-адресе перед fix.
Fix
Новая логика без
_extract_short_addrпромежуточного шага:Алгоритм:
"Большая Конюшенная, 25"); фильтр admin-слов (Россия/область/район/...)Работает с обоими форматами:
"Екатеринбург, ул. Космонавтов, 50"→"Космонавтов""80, улица 8 Марта, Артек, ..."→"8 Марта"Changes
tradein-mvp/backend/app/services/estimator.py— replaced_TRAILING_HOUSE_RE+_STREET_PREFIX_RE+ oldextract_street_namewith new_STREET_KW_RE+_STREET_NAME_RE+ rewritten functiontradein-mvp/backend/tests/test_street_deals_endpoint.py—test_extract_street_name_parametrized(10 cases: 4 forward, 2 reverse Nominatim, 4 edge cases)Verification
ruff check— passpytest— 15/15 pass (5 pre-existing + 10 new parametrized)ул. 8 Марта→street="8 Марта",count > 30→ секция в UI рендеритсяRefs: финальный hotfix 4-PR roadmap. После deploy: hard reload в браузере (Ctrl+Shift+R) для очистки JS-кеша.
Deep Code Review #557 — verdict: APPROVE
Files: 2 (P1: services/estimator.py; P2: tests/test_street_deals_endpoint.py) · +83 / -29
Checked SHA:
8de8daef01(matches prompt).Live bug to fix mapping
Verified: PR body's
count=0symptom traces to_extract_short_addrreturning the entire admin tail of REVERSE-format Nominatim string. New_STREET_KW_RE+_STREET_NAME_REpair extracts the street name directly without the broken_TRAILING_HOUSE_REgreedy strip. Root-cause analysis is accurate.Correctness — regex traced on real data
Locally executed both regexes against 23 cases (5 pre-existing forward, 6 new parametrized incl. real
80, улица 8 Марта, ...from prod). All pass. Also probed:ул. Малышева, д. 1→Малышева— resolves PR #555 review concern (д.N form now stripped via the trailing-house lookahead).Космонавтов 12(no comma) →Космонавтов— resolves second PR #555 concern.ул. Тимофеева-Ресовского, 12→Тимофеева-Ресовского(hyphenated names OK).Большая Конюшенная), digit-prefix (8 Марта) — all OK.Security
street_pattern = "%" + street + "%"ILIKE bind (psycopg, not string-concat). No injection surface._STREET_KW_REand_STREET_NAME_REare anchored / bounded — no catastrophic backtracking risk (each alternative has fixed{0,2}quantifier).re.IGNORECASEonly on keyword regex — name regex relies on[А-Яа-яёЁ]character class which already accepts both cases. Fine.Cross-file impact
_extract_short_addris still used at estimator.py:1303 (different code path) — removal of its call fromextract_street_namedoes NOT orphan it. Verified.trade_in.py:1109(/street-dealsendpoint, PR #555). Output type/shape unchanged:str | None. Backward-compatible.Tests
test_extract_street_name_basicstill pass with new logic (traced manually).test_extract_street_name_parametrizedadds 11 cases incl. the live-bug reproduction string and edge-case None inputs. Good regression coverage.Minor remaining edge cases (non-blocking, leave as follow-up)
50, Космонавтов, Екатеринбург, Россия(Nominatim sometimes omitsулица) → returnsNone. Real Nominatim usually includesулица/пр./etc., so blast is small.badsubstring filter false positives:Россиянская, 5(fallback path, no keyword) —Россия in Россиянскаяblocks it. Use==or word-boundary match if this surfaces. Fallback path is rare.ул. Сакко и Ванцетти, 30→None(lowercaseиconnector breaks 3-word constraint requiring capital starts). Real corner case; PR scope is the live bug, not exhaustive RU street naming.ул. Чкалова/Большакова, 5→None. Out of scope.period_months/area_tolerance(raised in PR #555 review) remain unaddressed but PR is not the place for that.Project conventions
str | Nonepreserved.Complexity / blast radius
extract_street_nameis a leaf helper.Auto-merging (squash + branch delete).