Skip to content

fix(convert,import): ask before replacing an existing output file - #212

Merged
nelsonduarte merged 1 commit into
mainfrom
fix/no-silent-overwrite
Oct 17, 2026
Merged

nelsonduarte merged 1 commit into
mainfrom
fix/no-silent-overwrite

Conversation

@nelsonduarte

Copy link
Copy Markdown
Owner

Summary

Converter and Import pre-fill the output next to the input, so _resolve_output_file never reached the Save dialog and an existing file with that name was replaced without a question (for example TIC.pdf to XLSX replacing the user's own TIC.xlsx). Both tools now ask before replacing an existing output.

Changes

BasePage gains an opt-in guard. _resolve_output_file and _resolve_output_dir are unchanged, so the tools that still call them behave as before.

  • _ask_overwrite: a warning box with Replace, Choose another name (Choose another folder for folder outputs) and Cancel. Cancel is the default and the Escape button; closing the box, or a box that returns with no button clicked, counts as Cancel.
  • _resolve_output_file_guarded: asks when the resolved path already exists, unless a Save dialog asked about it for this run: the one it opens itself (empty field or Choose another name), or the field's own Save as since the previous run. Pipeline temp outputs never ask.
  • _guard_folder_outputs: checks the files a run will write into a folder, and checks again when the user picks another folder.

DropFileEdit gains mark_confirmed, is_confirmed and take_confirmed:

  • its Save as button marks the path as confirmed only when the picked file already existed at that moment;
  • any change of path (set_path to another path, clear) revokes the mark;
  • the guard consumes the mark on every run, so the run after it asks again.

Converter uses the guard for DOCX, TXT, PPTX, XLSX, HTML and EPUB, and _guard_folder_outputs for the page_NNN PNG/JPG export, before the output folder is created or the starting status is shown. A new _image_name helper keeps the check and the writer on the same file names. Import uses the guard for its output PDF.

app/translations.json adds 6 overwrite.* keys in all 8 languages.

Tests

  • tests/test_no_silent_overwrite.py (new, 48 tests) drives the real _run flow with the real _ask_overwrite box and a stubbed exec.
  • tests/test_encrypted_pdf_tools.py: the image export test fails fast on any unexpected modal instead of hanging offscreen.
  • Full suite at verification time: 1076 passed, 2 skipped.

Known limitations (follow-ups)

  • Dropping a file onto the field does not explicitly revoke an earlier confirmation, and there is no test for the drop.
  • The other 10 tools with an output suffix still replace without asking.
  • Loading A and then B can write B's result over A_<suffix>.pdf.
  • Converter's Save as filter is always PDF, so TXT saves as .pdf.

🤖 Generated with Claude Code

Converter and Import pre-fill the output next to the input, so
_resolve_output_file never reached the Save dialog and an existing file
with that name was replaced without a question (for example TIC.pdf to
XLSX replacing the user's own TIC.xlsx).

BasePage gains an opt-in guard; _resolve_output_file and
_resolve_output_dir are unchanged, so the tools that still call them
behave as before:
- _ask_overwrite shows a warning box with Replace, Choose another name
  (Choose another folder for folder outputs) and Cancel. Cancel is the
  default and the Escape button; closing the box, or a box that returns
  with no button clicked, counts as Cancel.
- _resolve_output_file_guarded asks when the resolved path already
  exists, unless a Save dialog asked about it for this run: the one it
  opens itself (empty field or Choose another name) or the field's own
  Save as since the previous run. Pipeline temp outputs never ask.
- _guard_folder_outputs checks the files a run will write into a folder
  and checks again when the user picks another folder.

DropFileEdit gains mark_confirmed, is_confirmed and take_confirmed. Its
Save as button marks the path as confirmed only when the picked file
already existed at that moment. Any change of path (set_path to another
path, clear) revokes the mark, and the guard consumes it on every run,
so the run after it asks again.

Converter uses the guard for DOCX, TXT, PPTX, XLSX, HTML and EPUB, and
_guard_folder_outputs for the page_NNN PNG/JPG export, before the output
folder is created or the starting status is shown. A new _image_name
helper keeps the check and the writer on the same file names. Import
uses the guard for its output PDF.

translations.json adds 6 overwrite.* keys in all 8 languages.

Tests: tests/test_no_silent_overwrite.py adds 48 tests that drive the
real _run flow with the real _ask_overwrite box and a stubbed exec;
tests/test_encrypted_pdf_tools.py fails fast on any unexpected modal in
the image export test instead of hanging offscreen. Full suite at
verification time: 1076 passed, 2 skipped.

Known limitations, left for follow-ups:
- dropping a file onto the field does not explicitly revoke an earlier
  confirmation, and there is no test for the drop;
- the other 10 tools with an output suffix still replace without asking;
- loading A and then B can write B's result over A_<suffix>.pdf;
- Converter's Save as filter is always PDF, so TXT saves as .pdf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nelsonduarte
nelsonduarte merged commit b1f1fa1 into main Oct 17, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant