fix: lazy-import playwright in screenshot_page, fix SQLite connection leak in collect_listings

This commit is contained in:
pyr0ball 2026-03-03 12:45:39 -08:00
parent 4b06b0e1a2
commit 063c777cf5
2 changed files with 15 additions and 12 deletions

View file

@ -13,7 +13,6 @@ from pathlib import Path
import requests import requests
import yaml import yaml
from playwright.sync_api import sync_playwright
_ROOT = Path(__file__).parent.parent _ROOT = Path(__file__).parent.parent
_EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}") _EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}")
@ -78,12 +77,11 @@ def collect_listings(db_path: Path | None = None, n: int = 5) -> list[dict]:
import sqlite3 import sqlite3
from scripts.db import DEFAULT_DB from scripts.db import DEFAULT_DB
path = db_path or DEFAULT_DB path = db_path or DEFAULT_DB
conn = sqlite3.connect(path) with sqlite3.connect(path) as conn:
conn.row_factory = sqlite3.Row conn.row_factory = sqlite3.Row
rows = conn.execute( rows = conn.execute(
"SELECT title, company, url FROM jobs ORDER BY id DESC LIMIT ?", (n,) "SELECT title, company, url FROM jobs ORDER BY id DESC LIMIT ?", (n,)
).fetchall() ).fetchall()
conn.close()
return [{"title": r["title"], "company": r["company"], "url": r["url"]} for r in rows] return [{"title": r["title"], "company": r["company"], "url": r["url"]} for r in rows]
@ -198,8 +196,13 @@ def upload_attachment(
def screenshot_page(port: int | None = None) -> bytes | None: def screenshot_page(port: int | None = None) -> bytes | None:
""" """
Capture a screenshot of the running Peregrine UI using Playwright. Capture a screenshot of the running Peregrine UI using Playwright.
Returns PNG bytes, or None if Playwright is not installed or if capture fails. Returns PNG bytes, or None if Playwright is not installed or capture fails.
""" """
try:
from playwright.sync_api import sync_playwright
except ImportError:
return None
if port is None: if port is None:
port = int(os.environ.get("STREAMLIT_PORT", os.environ.get("STREAMLIT_SERVER_PORT", "8502"))) port = int(os.environ.get("STREAMLIT_PORT", os.environ.get("STREAMLIT_SERVER_PORT", "8502")))

View file

@ -249,16 +249,16 @@ def test_upload_attachment_returns_url(mock_post, monkeypatch):
def test_screenshot_page_returns_none_on_failure(monkeypatch): def test_screenshot_page_returns_none_on_failure(monkeypatch):
"""screenshot_page returns None gracefully when capture fails.""" """screenshot_page returns None gracefully when capture fails."""
from scripts.feedback_api import screenshot_page from scripts.feedback_api import screenshot_page
# Patch sync_playwright to raise an exception (simulates any failure) import playwright.sync_api as pw_api
import scripts.feedback_api as fapi original = pw_api.sync_playwright
def bad_playwright(): def bad_playwright():
raise RuntimeError("browser unavailable") raise RuntimeError("browser unavailable")
monkeypatch.setattr(fapi, "sync_playwright", bad_playwright) monkeypatch.setattr(pw_api, "sync_playwright", bad_playwright)
result = screenshot_page(port=9999) result = screenshot_page(port=9999)
assert result is None assert result is None
@patch("scripts.feedback_api.sync_playwright") @patch("playwright.sync_api.sync_playwright")
def test_screenshot_page_returns_bytes(mock_pw): def test_screenshot_page_returns_bytes(mock_pw):
"""screenshot_page returns PNG bytes when playwright is available.""" """screenshot_page returns PNG bytes when playwright is available."""
from scripts.feedback_api import screenshot_page from scripts.feedback_api import screenshot_page