updated scan.py to help us error handle the weird searches and alos build an ignore list

This commit is contained in:
2026-07-09 16:21:20 -05:00
parent 041ffd1c3f
commit 60cc36893e
6 changed files with 60 additions and 4 deletions

View File

@@ -34,7 +34,12 @@ Extracts and organizes documents from FileCabinet CS (Thomson Reuters) using GUI
python fccs_scan.py
```
Reads the restored FCCS backup directory and writes all drawer IDs (subfolder names) to `drawer_ids.txt`.
Reads the restored FCCS backup directory and writes all drawer IDs (subfolder names) to `drawer_ids.txt`. It also:
- **Flags prefix clashes** — if one drawer ID is a prefix of another (e.g. `02218` and `02218A`), searching the shorter ID in FCCS pops up a selection box that breaks automated navigation. These are reported so you can export them manually or ignore the shorter ID.
- **Reports ignored drawers** — any IDs listed in `ignore.txt` that exist in this backup are shown as ones the export will skip.
**Ignoring drawers:** To exclude specific drawers from export (e.g. password-protected folders that would stall the automation), add their IDs to the file at `ignore_file` (default `C:\Migration\ignore.txt`), one per line. `drawer_ids.txt` stays a full inventory; the export skips anything in the ignore list. Lines starting with `#` are treated as comments.
### Step 2: Export Documents
@@ -88,6 +93,6 @@ Exported filenames follow the format `{drawer_id}_{client_name}_{folder_name}_{c
All scripts read from `config.ini` (or specify `--config path\to\config.ini`).
- **`[paths]`** -- backup_dir, export_dir, output_dir, drawer_id_file, completed_file, log_file, screenshot_dir, folder_list
- **`[paths]`** -- backup_dir, export_dir, output_dir, drawer_id_file, completed_file, ignore_file, log_file, screenshot_dir, manifest_dir, folder_list
- **`[timeouts]`** -- nav_timeout, dialog_timeout, progress_appear, progress_finish, settle, confirm_timeout
- **`[controls]`** -- FCCS window class names and button titles (rarely need changing)

View File

@@ -5,6 +5,7 @@ export_dir = C:\Migration\Export
output_dir = C:\Migration\Output
drawer_id_file = C:\Migration\drawer_ids.txt
completed_file = C:\Migration\completed.txt
ignore_file = C:\Migration\ignore.txt
log_file = C:\Migration\run_log.txt
screenshot_dir = C:\Migration\screenshots
manifest_dir = C:\Migration\manifests

View File

@@ -137,3 +137,23 @@ def load_lines(path):
return []
with open(path, "r", encoding="utf-8") as f:
return [line.strip() for line in f if line.strip() and not line.strip().startswith("#")]
def check_for_clashes(drawer_ids):
"""Find drawer IDs that are a prefix of another drawer ID.
FCCS searches by prefix, so searching the shorter ID (e.g. '02218')
pops up a selection box when a longer ID exists (e.g. '02218A'),
which breaks the automated navigation.
Returns a list of (short_id, [longer_ids...]) tuples, sorted by short_id.
Empty list means no clashes.
"""
ids = sorted(set(drawer_ids))
clashes = []
for short in ids:
matches = [other for other in ids
if other != short and other.startswith(short)]
if matches:
clashes.append((short, matches))
return clashes

View File

@@ -354,6 +354,7 @@ def main():
paths = {
"drawer_id_file": cfg.get("paths", "drawer_id_file"),
"completed_file": cfg.get("paths", "completed_file"),
"ignore_file": cfg.get("paths", "ignore_file"),
"screenshot_dir": cfg.get("paths", "screenshot_dir"),
"manifest_dir": cfg.get("paths", "manifest_dir"),
}
@@ -391,10 +392,12 @@ def main():
sys.exit(1)
completed = load_completed(paths["completed_file"])
ignored = set(load_lines(paths["ignore_file"]))
pending = [d for d in all_ids if d not in completed]
pending = [d for d in all_ids if d not in completed and d not in ignored]
log(f"Total drawers in list : {len(all_ids)}")
log(f"Already completed : {len(completed)}")
log(f"Ignored (skipped) : {len(ignored & set(all_ids))}")
log(f"Remaining to process : {len(pending)}")
if not pending:

View File

@@ -8,7 +8,9 @@ Writes the sorted list of drawer IDs to the configured drawer_id_file.
import os
import sys
from fccs_config import parse_args, load_config, make_logger
from fccs_config import (
parse_args, load_config, make_logger, load_lines, check_for_clashes,
)
def main():
@@ -18,6 +20,7 @@ def main():
backup_dir = cfg.get("paths", "backup_dir")
output_file = cfg.get("paths", "drawer_id_file")
ignore_file = cfg.get("paths", "ignore_file")
if not os.path.isdir(backup_dir):
log(f"ERROR: backup directory not found: {backup_dir}")
@@ -34,6 +37,30 @@ def main():
log(f"Found {len(drawer_ids)} drawers, written to {output_file}")
# Report which drawers are set to be ignored (skipped by the export).
ignored = set(load_lines(ignore_file))
if ignored:
present = sorted(ignored & set(drawer_ids))
log(f"Ignore list ({ignore_file}): {len(ignored)} IDs, "
f"{len(present)} present in this backup — these will be SKIPPED "
f"by fccs_export.py: {', '.join(present) if present else '(none present)'}")
# Flag prefix clashes: FCCS search on the shorter ID pops a selection box.
clashes = check_for_clashes(drawer_ids)
if clashes:
log("-" * 60)
log(f"WARNING: {len(clashes)} potential drawer ID clash(es) found.")
log("Searching the shorter ID in FCCS may show a selection box "
"instead of navigating directly, which breaks the export.")
log("Consider exporting these manually, or add the shorter ID to "
f"the ignore list ({ignore_file}).")
for short, matches in clashes:
flag = " [ignored]" if short in ignored else ""
log(f" {short}{flag} -> also matches: {', '.join(matches)}")
log("-" * 60)
else:
log("No drawer ID prefix clashes found.")
if __name__ == "__main__":
main()