fix(findings): namespace per-tool button keys so multi-file render works
Reported: uploading multiple files on the home page and clicking Run
analysis blew up with
StreamlitDuplicateElementKey: key='_findings_open_02_text_cleaner'
when two uploaded files both had Clean Text findings.
Root cause: ``render_findings_panel`` is invoked once per uploaded
file from ``_home.py``, but the per-tool jump button used a
filename-agnostic key:
key=f"_findings_open_{tool_id}"
Two files both flagging Clean Text → two buttons with identical keys
→ Streamlit rejects the second one.
Fix:
- Add ``key_namespace: str = ""`` to ``render_findings_panel``. The
helper hashes it (sha1 truncated to 8 chars) and appends to every
button key, so different namespaces produce different keys but the
same namespace stays stable across reruns.
- The home page now passes the filename:
``render_findings_panel(findings, header=f"📄 {name}", key_namespace=name)``.
- The single-call site in ``upload_and_analyze_section`` (the legacy
helper, only used outside the new home-page path) keeps the default
empty namespace, which is fine because that path renders findings
for ONE file at a time.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1374,7 +1374,12 @@ def _tool_page_slug(tool_id: str) -> str:
|
||||
return _TOOL_PAGE_PATHS.get(tool_id, "")
|
||||
|
||||
|
||||
def render_findings_panel(findings, *, header: str | None = None) -> None:
|
||||
def render_findings_panel(
|
||||
findings,
|
||||
*,
|
||||
header: str | None = None,
|
||||
key_namespace: str = "",
|
||||
) -> None:
|
||||
"""Render a list of :class:`Finding` objects grouped by tool.
|
||||
|
||||
Each tool gets a header with the count, an open-tool button, and a list
|
||||
@@ -1427,9 +1432,20 @@ def render_findings_panel(findings, *, header: str | None = None) -> None:
|
||||
# rendering blended into the page, making the per-tool
|
||||
# jump non-obvious. The button triggers ``st.switch_page``
|
||||
# so navigation is still a soft switch (no full reload).
|
||||
#
|
||||
# ``key_namespace`` is hashed into the widget key so the
|
||||
# home page (which calls this once PER uploaded file)
|
||||
# doesn't collide on the shared tool_id — two files both
|
||||
# having Clean Text findings would otherwise produce two
|
||||
# buttons with the same key and Streamlit refuses.
|
||||
import hashlib as _hashlib
|
||||
ns = _hashlib.sha1(
|
||||
(key_namespace or "").encode("utf-8"),
|
||||
usedforsecurity=False,
|
||||
).hexdigest()[:8]
|
||||
if st.button(
|
||||
_t("findings.open_tool", tool=name),
|
||||
key=f"_findings_open_{tool_id}",
|
||||
key=f"_findings_open_{tool_id}_{ns}",
|
||||
type="primary",
|
||||
use_container_width=False,
|
||||
):
|
||||
|
||||
Reference in New Issue
Block a user