You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`markdown_renderer.py`| Markdown → tkinter Text widget renderer |
43
44
|`_generate_version.py`| Build-time script: bakes git commit, date, and version tag into `_version.py`|
@@ -54,6 +55,7 @@ A Python desktop app (tkinter/ttkbootstrap GUI) that batch-fills PDF forms from
54
55
-**Cross-platform scrolling**: Mousewheel handlers branch by `sys.platform` — Windows (`delta/120`), macOS (`delta`), Linux (`Button-4`/`Button-5`).
55
56
-**Backward-compatible persistence**: `from_json()` filters unknown keys so newer configs load in older versions.
56
57
-**Field mapping**: `PDFField.excel_column` stores the explicit Excel column name per field. `TemplateConfig.field_excel_columns` persists these as `{field_name: col_name}`. Generation checks `field.excel_column` first, then falls back to auto-match by field name (case-insensitive). Tab 2 is the UI for viewing and editing these mappings.
58
+
-**Non-text field filling (CRITICAL)**: checkboxes/radios fill ONLY when written as a pypdf `NameObject("/OnState")` with `auto_regenerate=True` — a plain string never ticks a box. `pdf_analyzer` captures `on_states` (`widget.button_states()`) and `options` (`widget.choice_values`); `field_values.py` maps cells to values (truthy→on-state, choice validated vs options). `_generate_single_pdf` returns a list of per-field warnings (surfaced separately from row failures); signature fields can't be auto-filled.
57
59
-**Tab lifecycle**: Tab 2 starts disabled; enabled by `analyze_pdf_fields()` after successful analysis. `_refresh_tab2_mappings()` is the single rebuild point — called after analysis, after Excel load, and after template load.
58
60
-**Tab 2 in-place updates**: `self._mapping_rows` (list of dicts, one per field) tracks widget references for `_refresh_tab2_mappings()` in-place updates. Rebuild only when field names or count change; otherwise update comboboxes/labels in-place to avoid widget churn.
59
61
-**Data directory resilience**: `_resolve_data_dir()` tries `~/Documents/BulkPDFGenerator` first; falls back to `%LOCALAPPDATA%/BulkPDFGenerator` if `makedirs` fails (common on school networks with GPO-redirected Documents folders). Both `settings_file` and `templates_directory` derive from this resolved path.
@@ -137,6 +139,10 @@ Excel serial date range validation: only serials 1–2958465 are converted (1900
-**Run the app from source**: `venv/bin/python pdf_generator.py` (launches the GUI on macOS from the shell).
139
141
-**Verify GUI logic without clicking**: instantiate `BulkPDFGenerator(tk.Tk())` with `root.withdraw()`, call the handler directly, and assert widget state (`w['text']`, `w.winfo_manager()` for packed/hidden). Proves behaviour and that no modal blocks.
142
+
-**Headless method tests**: call generation/dialog methods without the GUI via `BulkPDFGenerator.__new__(BulkPDFGenerator)` (skips `__init__`). `_generate_single_pdf` only needs the `ctx` snapshot + `format_value_tab3` (staticmethod) — no `self.*`.
143
+
-**Don't instantiate Tk in automated tests** — headless CI (Linux) has no display. Guard GUI logic with `inspect.getsource` structural tests (see `test_performance.py`), e.g. assert the startup update path contains no `messagebox`.
144
+
-**PyMuPDF can't author radio-button groups** in fixtures (`add_widget` → `bad xref`); unit-test radio logic via `field_values.normalize_button_value`, verify end-to-end on a real PDF.
145
+
-**Gotcha — `test_data_fidelity.py` asserts `format_value_tab3(...)` and `data_type` sit on the SAME source line** (via `inspect.getsource`); don't split that call across lines.
140
146
-**Reviewing a session's work**: this repo is committed+pushed to `test` continuously, so by review time `HEAD == origin/test` and `/security-review` (or any diff-vs-upstream) sees an empty diff. Review against the session's starting commit instead: `git diff <base>..HEAD`.
141
147
-**Performance tests**: `tests/test_performance.py` uses `inspect.getsource()` to verify structural patterns (anti-patterns absent from source) rather than flaky timing assertions. 21 tests covering threading, debounce, batch updates, throttling, dialog geometry.
142
148
-**Main class**: `BulkPDFGenerator` (not `BulkPDFApp` or similar)
0 commit comments