spacr.qt.ai.issue_report¶
Error reports filed as issues on the public spaCR GitHub repository.
A failed run is reported in one of two ways, chosen by the “One-click issue
filing” preference (spacr.qt.preferences.get_issue_prompt_mode()):
'always', the default:file_without_review()files the report as soon as the run has failed. It sendspublic_report(), the same redaction the preview applies by default, and it never opens a browser. Filing needs a GitHub sign-in (theghCLI orGITHUB_TOKEN). Without one, nothing is sent.'ask': the report opens in an editable preview, andsubmit_report()sends it only after the Send click. Without a sign-in it opens a pre-filled GitHub form in the browser.
Both paths build the report with build_report(), and both look for an
open issue carrying the same traceback fingerprint before they open a new
one. spaCR never stores a durable GitHub token itself.
Functions¶
|
Build a |
|
Legacy end-to-end helper retained for API callers and tests. |
|
File a report automatically, for issue reporting set to 'always'. |
|
The fingerprint |
|
Build the |
|
Where a report's log copy is written. |
|
Return the last |
|
Open |
|
The report as it is sent when nobody reviews it first. |
|
Replace this computer's login and host names with placeholders. |
|
Strip anything that looks like an API key / access token. |
|
Replace absolute paths pointing inside |
|
Return a copy of |
|
Sanitise a full traceback string via |
|
Write the log tail to a file beside the report and return its path. |
|
Remove file/folder names from an already sanitised report. |
|
Submit one payload the user has already approved in the preview. |
Module Contents¶
- spacr.qt.ai.issue_report.build_report(traceback_text: str, active_app: str = '', settings: Dict[str, Any] | None = None, include_log_tail: bool = True, ai_response: str = '') Dict[str, str][source]¶
Build a
(title, body)pair for a pre-filled GitHub issue.- Parameters:
traceback_text – full traceback text (as caught by
traceback.format_exc()).active_app – id of the app the user was in when the error fired (
"mask"/"measure"/ …).settings – the pipeline settings dict in play, if any. Sanitised before inclusion.
include_log_tail – also attach the last N log lines.
ai_response – spaCR AI’s analysis of this same error, when the AI is switched on and has already answered. Sanitised and length-capped like everything else here, and clearly marked as machine-generated: it is a lead for whoever reads the report, not a finding.
- Returns:
dict with keys
title,bodyandfingerprint, ready to be URL-encoded ontoissues/new.
- spacr.qt.ai.issue_report.file_issue(traceback_text: str, active_app: str = '', settings: Dict[str, Any] | None = None, *, include_log_tail: bool = True, ai_response: str = '') str[source]¶
Legacy end-to-end helper retained for API callers and tests.
The GUI does not call this directly: it builds the payload, displays an editable preview, then passes the approved mapping to
submit_report(). Headless callers invoking this function are the report-specific affirmative action themselves.- Parameters:
traceback_text – full traceback text, passed to
build_report(), which sanitises it and derives the issue title and fingerprint from it.
- spacr.qt.ai.issue_report.file_without_review(report: Dict[str, str]) Dict[str, str][source]¶
File a report automatically, for issue reporting set to ‘always’.
Runs on a worker thread: resolving the sign-in can run
gh auth token, and posting waits on api.github.com.It never opens a browser. The browser form is a prompt the user answers, and ‘always’ is the choice not to be prompted. So without a GitHub sign-in it files nothing and says so.
- Parameters:
report – the payload to post, already passed through
public_report().- Returns:
{"status": ..., "url": ..., "detail": ...}with a status ofFILED,SEEN_AGAIN(a comment on the open issue with the same fingerprint),SIGNED_OUT,REFUSED(inside a test run) orFAILED. Never raises.
- spacr.qt.ai.issue_report.fingerprint_of(traceback_text: str) str[source]¶
The fingerprint
build_report()gives this traceback.- Parameters:
traceback_text – the raw traceback.
- Returns:
six hex characters, without building the report. The automatic filer checks this against what it has filed before, so a repeated crash costs no log copy and no network call.
- spacr.qt.ai.issue_report.issue_url(title: str, body: str, label: str = ISSUE_LABEL, repo: str = REPO) str[source]¶
Build the
https://github.com/<repo>/issues/new?…URL.The URL is truncated to ~7.5 KB so it fits GitHub’s parser limit; an ellipsis + note is appended to the body when we clip.
- Parameters:
title – URL-encodable issue title.
body – markdown body; may be truncated.
label – label to attach (created lazily by GitHub if it doesn’t already exist).
repo –
owner/nameslug.
- Returns:
fully-quoted
https://github.com/…URL.
- spacr.qt.ai.issue_report.log_bundle_dir() pathlib.Path[source]¶
Where a report’s log copy is written.
- spacr.qt.ai.issue_report.log_tail(n_lines: int = LOG_TAIL_LINES, log_path: pathlib.Path | None = None) str[source]¶
Return the last
n_linesof~/.spacr/logs/spacr.log(or a custom path), sanitized.- Parameters:
n_lines – how many trailing lines to include.
log_path – override for the log file path.
- Returns:
sanitised last-N-lines block or
""if the file is absent or unreadable.
- spacr.qt.ai.issue_report.open_issue_in_browser(url: str) bool[source]¶
Open
urlin the user’s default browser.- Parameters:
url – the address to open, typically from
issue_url(); it is opened in a new tab where the browser supports one.- Returns:
Trueif webbrowser accepted the request, else False.
- spacr.qt.ai.issue_report.public_report(report: Dict[str, str]) Dict[str, str][source]¶
The report as it is sent when nobody reviews it first.
The preview opens with “Remove file and folder names” switched on, so what a reviewer sends by default is the body after
strip_report_paths(). A report filed automatically gets that same body. The title is stripped as well: it quotes the exception line, and that line can carry a file name.- Parameters:
report – a report from
build_report().- Returns:
title,bodyandfingerprint, ready to post.
- spacr.qt.ai.issue_report.redact_identity(s: str) str[source]¶
Replace this computer’s login and host names with placeholders.
A home folder is already shortened to
~bysanitize_path(). The login name can still appear elsewhere: another folder named after the user, a permission error, anownersetting. The host name can appear in a network path or a connection error. Each is replaced wherever it stands as a whole word, in any letter case.- Parameters:
s – arbitrary text.
- Returns:
the text with
USER_PLACEHOLDERandHOST_PLACEHOLDERin place of those names.
- spacr.qt.ai.issue_report.redact_secrets(s: str) str[source]¶
Strip anything that looks like an API key / access token.
The issue body is posted to a PUBLIC GitHub repo, so a token that survived into a traceback, a settings value or a log line would be leaked to the world (and, for GitHub PATs, instantly revoked).
- Parameters:
s – arbitrary text.
- Returns:
the same text with credential-shaped substrings replaced by
REDACTED.
- spacr.qt.ai.issue_report.sanitize_path(s: str) str[source]¶
Replace absolute paths pointing inside
$HOMEwith~/.Also collapses any string that looks like an on-disk
*.dbpath down to<DB>so lab / patient / experiment identifiers embedded in a filename don’t leak, replaces this computer’s login and host names throughredact_identity(), and redacts credential-shaped substrings viaredact_secrets().- Parameters:
s – arbitrary text.
- Returns:
text with home-relative paths abbreviated and DB paths, login and host names and secrets redacted.
- spacr.qt.ai.issue_report.sanitize_settings(settings: Dict[str, Any]) Dict[str, Any][source]¶
Return a copy of
settingswith paths + DB names sanitized.Values whose key names a credential (
api_key,GITHUB_TOKEN,password, …) are dropped entirely — the key name is enough of a hint that the value must never reach a public issue.- Parameters:
settings – any pipeline settings dict.
- Returns:
sanitized copy safe to include in a public issue.
- spacr.qt.ai.issue_report.sanitize_traceback(tb: str) str[source]¶
Sanitise a full traceback string via
sanitize_path().- Parameters:
tb – the traceback text;
Noneor an empty string gives"".
- spacr.qt.ai.issue_report.save_log_bundle(fingerprint: str, log_path: pathlib.Path | None = None, n_lines: int = LOG_BUNDLE_LINES) pathlib.Path | None[source]¶
Write the log tail to a file beside the report and return its path.
The public issue names this path instead of carrying the log itself. More lines are kept here than would ever have gone in an issue – once the log is not being pasted into a URL there is no length to stay under, and whoever reads the report wants the whole run, not a keyhole.
- Parameters:
fingerprint – the traceback hash, so one report’s log is easy to match to the issue that names it.
log_path – override for the log file path.
n_lines – how many trailing lines to keep.
- Returns:
the path written, or
Noneif there was nothing to write or the write failed – a report must still be filable on a read-only home directory.
- spacr.qt.ai.issue_report.strip_report_paths(text: str) str[source]¶
Remove file/folder names from an already sanitised report.
The ordinary sanitizer abbreviates the home directory so a traceback is still useful. Public reports default to the stricter form: traceback file fields, quoted path values and remaining absolute path-like tokens become
<PATH>. The preview lets the user restore the useful names before sending; with issue reporting set to ‘always’ there is no preview, so what this leaves behind is what gets published.A PATH CAN CONTAIN A SPACE, and the rule that stopped one at the first whitespace published the rest of it.
/Volumes/Lab Drive/Patient 042came out as<PATH> Drive/Patient 042, andC:\Users\anna\OneDrive - Karolinska Institutet\Screenskept the institution and the screen — the two operating systems whose own folders have spaces in them. A UNC path was not a path at all: nothing here started at\\. The LAST component of an unquoted path has no separator after it to prove a space is inside the path rather than after it, so it runs on only over words shaped like a name – a number, a capitalised word, a file name – and\\LAB-NAS\screens\plate 1is replaced whole whileopening /mnt/data/x.tif failedkeeps itsfailed. A lower-case word ending such a component still survives it; a quoted path is taken whole, and the title and everyrepr-ed settings value are quoted.A slash straight after
<starts a closing tag, not a path. The report’s collapsible sections end in</summary>and</details>, and issue #121 was filed with both turned into<<PATH>, so every section after the first one stayed open.- Parameters:
text – a report title or body, already through
sanitize_path().- Returns:
the same text with path-shaped tokens replaced by
<PATH>.
- spacr.qt.ai.issue_report.submit_report(report: Dict[str, str]) str[source]¶
Submit one payload the user has already approved in the preview.
- Parameters:
report – the approved payload with
titleandbodykeys, plusfingerprintfor the duplicate search when a GitHub sign-in posts it through the API. Without a sign-in, or when posting fails, the title and body are put into a pre-filled issue URL that is opened in the browser.- Returns:
the filed issue’s URL, the pre-filled
issues/newURL, or the transport refusal message when network use is refused (inside a test run).