[tradein] scraper_kit F4 follow-up: mock-target artifact блокирует миграцию avito/imv.py на _base #2386

Open
opened 2026-07-04 06:44:17 +00:00 by lekss361 · 0 comments
Owner

Родительский: #2352 (Group F4). Follow-up от F4a (#2361) — этот PR смигрировал avito serp/detail на build_*_session(), но НЕ трогал avito/imv.py's own-session curl_cffi construction.

Почему отложено (реальная находка, не оверсайт)

avito/imv.py строит own-session curl_cffi AsyncSession(headers=_DOC_HEADERS) — технически подходит под build_document_session(). НО тесты test_avito_imv_kit_parity.py::test_kit_evaluate_via_imv_{with,without}_config_uses_proxy патчат:

unittest.mock.patch("curl_cffi.requests.AsyncSession", _fake_session)

Это подменяет атрибут на module-объекте curl_cffi.requests, что работает только если код делает свежий lookup имени в момент вызова (как старый локальный from curl_cffi.requests import AsyncSession внутри функции). А _base.py делает from curl_cffi.requests import AsyncSession на module-level (один раз при импорте _base, до того как тест патчит) → вызов внутри build_curl_cffi_session резолвится через имя в namespace _base.py, а не через live-атрибут curl_cffi.requests.AsyncSession → patch не долетает, calls пуст, тесты падают.

Прод-поведение идентично (сеть не отличает откуда взят класс) — это чисто mock-target артефакт, НЕ реальная разница.

Класс проблемы (важно)

Тот же паттерн теста сломает миграцию ЛЮБОГО provider'а на own-session helper, если там есть тесты с patch("curl_cffi.requests.AsyncSession", ...). Два варианта фикса (выбрать один системно):

  • Вариант A (фикс в _base.py): резолвить AsyncSession через curl_cffi.requests.AsyncSession(...) (полный путь, live-lookup) вместо from ... import AsyncSession module-level — тогда patch на curl_cffi.requests.AsyncSession снова долетает. Симметрично тому, как BrowserFetcher уже патчится через _base.BrowserFetcher. Минимальный, покрывает все будущие own-session миграции.
  • Вариант B (фикс в тестах): переписать эти конкретные тесты на patch("scraper_kit.providers._base.AsyncSession", ...). Работает, но каждый новый own-session тест придётся писать с оглядкой на это.

Рекомендация: Вариант A (системный, one-time). После фикса — домигрировать avito/imv.py's own-session construction на build_document_session().

Scope

  1. Реализовать Вариант A в _base.py (или обосновать B).
  2. Домигрировать avito/imv.py own-session на build_document_session().
  3. Проверить test_avito_imv_kit_parity.py зелёный без ослабления assertions.

Refs #2352, #2358, #2361

Родительский: #2352 (Group F4). Follow-up от F4a (#2361) — этот PR смигрировал avito serp/detail на `build_*_session()`, но НЕ трогал `avito/imv.py`'s own-session curl_cffi construction. ## Почему отложено (реальная находка, не оверсайт) `avito/imv.py` строит own-session curl_cffi `AsyncSession(headers=_DOC_HEADERS)` — технически подходит под `build_document_session()`. НО тесты `test_avito_imv_kit_parity.py::test_kit_evaluate_via_imv_{with,without}_config_uses_proxy` патчат: ```python unittest.mock.patch("curl_cffi.requests.AsyncSession", _fake_session) ``` Это подменяет атрибут на module-объекте `curl_cffi.requests`, что работает только если код делает **свежий lookup имени в момент вызова** (как старый локальный `from curl_cffi.requests import AsyncSession` внутри функции). А `_base.py` делает `from curl_cffi.requests import AsyncSession` на **module-level** (один раз при импорте `_base`, до того как тест патчит) → вызов внутри `build_curl_cffi_session` резолвится через имя в namespace `_base.py`, а не через live-атрибут `curl_cffi.requests.AsyncSession` → patch не долетает, `calls` пуст, тесты падают. **Прод-поведение идентично** (сеть не отличает откуда взят класс) — это чисто mock-target артефакт, НЕ реальная разница. ## Класс проблемы (важно) Тот же паттерн теста сломает миграцию ЛЮБОГО provider'а на own-session helper, если там есть тесты с `patch("curl_cffi.requests.AsyncSession", ...)`. Два варианта фикса (выбрать один системно): - **Вариант A (фикс в _base.py):** резолвить `AsyncSession` через `curl_cffi.requests.AsyncSession(...)` (полный путь, live-lookup) вместо `from ... import AsyncSession` module-level — тогда patch на `curl_cffi.requests.AsyncSession` снова долетает. Симметрично тому, как BrowserFetcher уже патчится через `_base.BrowserFetcher`. Минимальный, покрывает все будущие own-session миграции. - **Вариант B (фикс в тестах):** переписать эти конкретные тесты на `patch("scraper_kit.providers._base.AsyncSession", ...)`. Работает, но каждый новый own-session тест придётся писать с оглядкой на это. Рекомендация: Вариант A (системный, one-time). После фикса — домигрировать `avito/imv.py`'s own-session construction на `build_document_session()`. ## Scope 1. Реализовать Вариант A в `_base.py` (или обосновать B). 2. Домигрировать `avito/imv.py` own-session на `build_document_session()`. 3. Проверить `test_avito_imv_kit_parity.py` зелёный без ослабления assertions. Refs #2352, #2358, #2361
lekss361 added the
scope/backend
scrapers
tech-debt
tradein
labels 2026-07-04 10:23:49 +00:00
Sign in to join this conversation.
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#2386
No description provided.