Repository navigation
Conversation
165e622 to
018418a
Compare
…ests Add `test_get_ui_html_cache_write_is_atomic` — interposes on `os.replace` to assert deterministically that the cache file only materializes complete via the atomic rename (the source already holds the full content), so a reader can never catch it existing-but-empty. Add an `isolated_ui_cache` fixture so `test_chat_app_index_endpoint` and `test_chat_app_index_caching` point `_get_cache_dir` at a temp dir and stub the CDN fetch, removing the live jsdelivr dependency and real `~/.cache` pollution from the suite.
The `isolated_ui_cache` fixture monkeypatches `_get_cache_dir`, which left its real body uncovered now that the index-route tests no longer exercise it. Add `test_get_cache_dir_uses_xdg_cache_home` to cover it via the public XDG path.
pydanty runtime failureRun Next step: maintainer attention needed; rerun after fixing the runtime failure. Failure detail (tail) |
|
David's AICA here: 🔍 Local review suite (automated, pre-merge)
Verdict: ✅ all 3 waves passed, 0 blocking, 0 required |
- _write_cached_file: wrap both the write and os.replace in try/except so the delete=False temp file is unlinked on any failure (incl. write error), not just os.replace failure; flush before the rename so the temp holds complete content at replace time. - Add docstrings to _read_cached_file / _write_cached_file. - Dedupe the MockAsyncClient/MockResponse doubles behind a shared _stub_cdn_fetch helper used by the cache tests.
…solation refactor
📝 WalkthroughWalkthroughThis change updates UI HTML caching to use atomic file writes. New helpers treat missing or empty cache files as misses and write via a same-directory temp file plus Related PRs: None specified. Suggested labels: area: ui, testing Suggested reviewers: None specified. 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
pydantic_ai_slim/pydantic_ai/ui/_web/app.py (1)
100-108: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDuplicated fetch-and-cache flow between the CDN and custom-URL branches.
Both branches now execute the same
_read_cached_file→httpxfetch →raise_for_status→_write_cached_filesequence. Since both paths were touched in this PR, consider extracting a small_fetch_and_cache(url, cache_file)helper to avoid future drift between the two copies.♻️ Proposed consolidation
+async def _fetch_and_cache(url: str, cache_file: Path) -> bytes: + if content := _read_cached_file(cache_file): + return content + + async with httpx.AsyncClient() as client: + response = await client.get(url) + response.raise_for_status() + content = response.content + + _write_cached_file(cache_file, content) + return contentThen call
await _fetch_and_cache(DEFAULT_HTML_URL, cache_file)andawait _fetch_and_cache(html_source, cache_file)from the two branches respectively.Also applies to: 124-132
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pydantic_ai_slim/pydantic_ai/ui/_web/app.py` around lines 100 - 108, Both the default HTML and custom HTML source branches in app.py duplicate the same cache-read, HTTP fetch, status check, and cache-write flow. Extract that logic into a shared helper such as _fetch_and_cache(url, cache_file) and update the existing branches in the HTML-loading function to call it with DEFAULT_HTML_URL or html_source so the behavior stays in one place and does not drift.tests/test_ui_web.py (1)
194-223: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMigration to
_stub_cdn_fetchis incomplete.Good shared-helper extraction, but per the PR discussion, older inline
MockResponse/MockAsyncClientsetups elsewhere in this file (still present per current graph evidence) haven't been migrated to this helper yet, leaving duplicated mocking logic. Worth finishing the migration (or explicitly deferring) to avoid the two patterns diverging over time.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_ui_web.py` around lines 194 - 223, The migration to the shared CDN fetch stub is only partially complete, and this file still has duplicated inline `MockResponse`/`MockAsyncClient` mocking logic alongside `_stub_cdn_fetch`. Update the remaining tests to use `_stub_cdn_fetch` instead of their local `httpx.AsyncClient` stubs, or clearly defer those cases, so `_get_ui_html` cache/CDN branch tests all share the same helper and stay consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pydantic_ai_slim/pydantic_ai/ui/_web/app.py`:
- Around line 64-79: Move the atomic rename in _write_cached_file outside the
NamedTemporaryFile context so the temp file is closed before os.replace runs;
the current flow keeps tmp_file open during the replace, which can fail on
Windows. Keep the existing cleanup behavior by still unlinking tmp_path on any
exception, but ensure the write/flush happens inside the with block and the
replace happens after the file handle is closed.
---
Nitpick comments:
In `@pydantic_ai_slim/pydantic_ai/ui/_web/app.py`:
- Around line 100-108: Both the default HTML and custom HTML source branches in
app.py duplicate the same cache-read, HTTP fetch, status check, and cache-write
flow. Extract that logic into a shared helper such as _fetch_and_cache(url,
cache_file) and update the existing branches in the HTML-loading function to
call it with DEFAULT_HTML_URL or html_source so the behavior stays in one place
and does not drift.
In `@tests/test_ui_web.py`:
- Around line 194-223: The migration to the shared CDN fetch stub is only
partially complete, and this file still has duplicated inline
`MockResponse`/`MockAsyncClient` mocking logic alongside `_stub_cdn_fetch`.
Update the remaining tests to use `_stub_cdn_fetch` instead of their local
`httpx.AsyncClient` stubs, or clearly defer those cases, so `_get_ui_html`
cache/CDN branch tests all share the same helper and stay consistent.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: d32b211b-b4db-4e08-a83d-6d41aa01e1cc
📒 Files selected for processing (2)
pydantic_ai_slim/pydantic_ai/ui/_web/app.pytests/test_ui_web.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
pydantic/logfire(auto-detected)pydantic/pydantic(auto-detected)
…gnyan/fix-ui-html-cache-atomic-5399
…cache write On Windows, `os.replace` on a `NamedTemporaryFile` whose handle is still open raises `PermissionError` (WinError 32), so the atomic web UI HTML cache write in `_write_cached_file` failed there. Close the handle before the rename, and add a regression test pinning the close-before-replace ordering.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@tests/test_ui_web.py`:
- Around line 337-370: The `capturing_named_temporary_file` helper uses a `dir`
keyword parameter to mirror the `tempfile.NamedTemporaryFile(dir=...)` call in
`_write_cached_file`, but that shadows the builtin and triggers Ruff A002. Keep
the parameter name unchanged so the monkeypatch still matches the production
call, and suppress the lint on that parameter or function with an explicit `#
noqa` annotation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: dcaf2f98-ee7a-4488-afb2-657093ca97b0
📒 Files selected for processing (2)
pydantic_ai_slim/pydantic_ai/ui/_web/app.pytests/test_ui_web.py
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
pydantic/logfire(auto-detected)pydantic/pydantic(auto-detected)
🚧 Files skipped from review as they are similar to previous changes (1)
- pydantic_ai_slim/pydantic_ai/ui/_web/app.py
Summary
Addresses #5399, cache race item.
Testing
Checklist