Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1102,10 +1102,16 @@ def _patch_ocr_with_textlayer(page_md: str, pdf_path: str, page_num: int) -> str
|
|
| 1102 |
key = (_norm(r["date"]), _norm(r["desc"]), _norm(r["amount"]))
|
| 1103 |
tl_freq[key] = tl_freq.get(key, 0) + 1
|
| 1104 |
|
| 1105 |
-
# Share with _dedupe_duplicate_rows_in_da3_table
|
| 1106 |
-
#
|
|
|
|
|
|
|
| 1107 |
global _tl_freq_context
|
| 1108 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1109 |
|
| 1110 |
table_pattern = re.compile(r"<table[^>]*>.*?</table>", re.DOTALL | re.IGNORECASE)
|
| 1111 |
result = page_md
|
|
@@ -1280,10 +1286,8 @@ def _patch_ocr_with_textlayer(page_md: str, pdf_path: str, page_num: int) -> str
|
|
| 1280 |
|
| 1281 |
except Exception as e:
|
| 1282 |
log.warning("_patch_ocr_with_textlayer failed (page %d): %s", page_num, e)
|
| 1283 |
-
return page_md
|
| 1284 |
-
finally:
|
| 1285 |
-
# Always clear so stale frequencies do not affect subsequent pages.
|
| 1286 |
_tl_freq_context.clear()
|
|
|
|
| 1287 |
|
| 1288 |
# --------------------------
|
| 1289 |
# Fix 5: Mid-table separator row reconstruction
|
|
@@ -2731,11 +2735,10 @@ _DA3_MONEY_TOKEN = re.compile(
|
|
| 2731 |
_MSFT_PIN_G_REF = re.compile(r"MICROSOFT#(G\d{6,16})", re.IGNORECASE)
|
| 2732 |
|
| 2733 |
# Module-level text-layer frequency context (Fix-20 override).
|
| 2734 |
-
# Set by _patch_ocr_with_textlayer
|
| 2735 |
-
#
|
| 2736 |
-
#
|
| 2737 |
-
#
|
| 2738 |
-
# as the cap instead of the default 2, preserving all text-layer-confirmed rows.
|
| 2739 |
_tl_freq_context: dict = {}
|
| 2740 |
|
| 2741 |
_DA3_LEADING_DATE = re.compile(r"^\d{1,2}/\d{1,2}(?:/\d{2,4})?$")
|
|
@@ -3714,6 +3717,10 @@ def stabilize_tables_and_text(page_md: str) -> str:
|
|
| 3714 |
if not page_md:
|
| 3715 |
return page_md
|
| 3716 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3717 |
page_md = normalize_money_glyphs(page_md)
|
| 3718 |
|
| 3719 |
blocks = re.split(r"\n\s*\n", page_md.strip())
|
|
@@ -3829,6 +3836,8 @@ def run_ocr(uploaded_file):
|
|
| 3829 |
|
| 3830 |
all_pages = []
|
| 3831 |
for page_num, page_result in enumerate(results):
|
|
|
|
|
|
|
| 3832 |
page_md, regions = get_page_md_and_regions(page_result)
|
| 3833 |
img_h = page_heights[page_num] if page_num < len(page_heights) else 1000
|
| 3834 |
header_end_frac, footer_start_frac = get_header_footer_zones(regions, img_h)
|
|
|
|
| 1102 |
key = (_norm(r["date"]), _norm(r["desc"]), _norm(r["amount"]))
|
| 1103 |
tl_freq[key] = tl_freq.get(key, 0) + 1
|
| 1104 |
|
| 1105 |
+
# Share with _dedupe_duplicate_rows_in_da3_table (Fix-20 override).
|
| 1106 |
+
# Keys MUST match _transaction_row_dedupe_key (date/desc/amount, no spaces in
|
| 1107 |
+
# date/desc; amount stripped of $/,/space). The injection map tl_freq uses
|
| 1108 |
+
# _norm() with spaces — different tuple shape — so we keep a parallel count.
|
| 1109 |
global _tl_freq_context
|
| 1110 |
+
tl_dedupe = {}
|
| 1111 |
+
for r in tl_rows:
|
| 1112 |
+
dk = _transaction_row_dedupe_key([r["date"], r["desc"], r["amount"]])
|
| 1113 |
+
tl_dedupe[dk] = tl_dedupe.get(dk, 0) + 1
|
| 1114 |
+
_tl_freq_context = tl_dedupe
|
| 1115 |
|
| 1116 |
table_pattern = re.compile(r"<table[^>]*>.*?</table>", re.DOTALL | re.IGNORECASE)
|
| 1117 |
result = page_md
|
|
|
|
| 1286 |
|
| 1287 |
except Exception as e:
|
| 1288 |
log.warning("_patch_ocr_with_textlayer failed (page %d): %s", page_num, e)
|
|
|
|
|
|
|
|
|
|
| 1289 |
_tl_freq_context.clear()
|
| 1290 |
+
return page_md
|
| 1291 |
|
| 1292 |
# --------------------------
|
| 1293 |
# Fix 5: Mid-table separator row reconstruction
|
|
|
|
| 2735 |
_MSFT_PIN_G_REF = re.compile(r"MICROSOFT#(G\d{6,16})", re.IGNORECASE)
|
| 2736 |
|
| 2737 |
# Module-level text-layer frequency context (Fix-20 override).
|
| 2738 |
+
# Set by _patch_ocr_with_textlayer; consumed by normalize_html_tables in run_ocr's
|
| 2739 |
+
# post-patch pass. Cleared at the start of stabilize_tables_and_text (new page)
|
| 2740 |
+
# and on patch failure so keys never bleed across pages.
|
| 2741 |
+
# Keys match _transaction_row_dedupe_key (not the _norm()-based tl_freq map).
|
|
|
|
| 2742 |
_tl_freq_context: dict = {}
|
| 2743 |
|
| 2744 |
_DA3_LEADING_DATE = re.compile(r"^\d{1,2}/\d{1,2}(?:/\d{2,4})?$")
|
|
|
|
| 3717 |
if not page_md:
|
| 3718 |
return page_md
|
| 3719 |
|
| 3720 |
+
# Fresh page: drop any text-layer dedupe caps so the first normalize pass
|
| 3721 |
+
# (before _patch_ocr_with_textlayer) does not see stale keys from a prior page.
|
| 3722 |
+
_tl_freq_context.clear()
|
| 3723 |
+
|
| 3724 |
page_md = normalize_money_glyphs(page_md)
|
| 3725 |
|
| 3726 |
blocks = re.split(r"\n\s*\n", page_md.strip())
|
|
|
|
| 3836 |
|
| 3837 |
all_pages = []
|
| 3838 |
for page_num, page_result in enumerate(results):
|
| 3839 |
+
# Header normalize runs before body patch; do not reuse prior page caps.
|
| 3840 |
+
_tl_freq_context.clear()
|
| 3841 |
page_md, regions = get_page_md_and_regions(page_result)
|
| 3842 |
img_h = page_heights[page_num] if page_num < len(page_heights) else 1000
|
| 3843 |
header_end_frac, footer_start_frac = get_header_footer_zones(regions, img_h)
|