Spaces:
Sleeping
Sleeping
Pointf5ive commited on
Commit ·
55f755c
1
Parent(s): b9de0c7
Make rights/page-scope updates resilient and auto-resolve latest book
Browse files- smoke_signal_tab.py +64 -17
smoke_signal_tab.py
CHANGED
|
@@ -998,6 +998,42 @@ def _safe_title_slug(title: str) -> str:
|
|
| 998 |
return slug[:120]
|
| 999 |
|
| 1000 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1001 |
def _clean_page_spec(spec: str) -> str:
|
| 1002 |
raw = (spec or "").strip().lower()
|
| 1003 |
if raw in ("", "all", "*", "none", "-"):
|
|
@@ -1033,16 +1069,12 @@ def _default_ocr_scope_values() -> tuple[str, str]:
|
|
| 1033 |
|
| 1034 |
def save_book_scope(book_id: str, include_spec: str, exclude_spec: str, safe_title: str) -> tuple:
|
| 1035 |
df = load_manifest_df()
|
| 1036 |
-
bid = (book_id or "").strip()
|
| 1037 |
if df.empty:
|
| 1038 |
return _ingest_status_html("idle"), df, "No books in manifest yet."
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
bid = str(df.iloc[-1]["book_id"])
|
| 1044 |
-
if bid not in df["book_id"].astype(str).values:
|
| 1045 |
-
return _ingest_status_html("idle"), df, f"Book ID {bid} not found."
|
| 1046 |
|
| 1047 |
try:
|
| 1048 |
include_clean = _clean_page_spec(include_spec)
|
|
@@ -1058,7 +1090,7 @@ def save_book_scope(book_id: str, include_spec: str, exclude_spec: str, safe_tit
|
|
| 1058 |
if title_raw:
|
| 1059 |
safe = _safe_title_slug(title_raw)
|
| 1060 |
else:
|
| 1061 |
-
filename = str(
|
| 1062 |
stem = Path(filename).stem if filename else bid
|
| 1063 |
safe = _safe_title_slug(stem)
|
| 1064 |
|
|
@@ -1201,14 +1233,19 @@ def _ingest_status_html(state: str, new=0, dups=0) -> str:
|
|
| 1201 |
def update_rights(book_id: str, new_rights: str) -> tuple:
|
| 1202 |
"""Update rights class for an existing book."""
|
| 1203 |
df = load_manifest_df()
|
| 1204 |
-
if df.empty
|
| 1205 |
-
return _ingest_status_html("idle"), df,
|
| 1206 |
-
|
| 1207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1208 |
save_manifest_df(df)
|
| 1209 |
-
msg = f"[{datetime.utcnow().strftime('%H:%M:%S')}] ✓ Updated {
|
| 1210 |
if prev_status == "pending" and new_rights not in ("unknown", "excluded"):
|
| 1211 |
-
_, profile_log = run_profile(book_ids=[
|
| 1212 |
if profile_log:
|
| 1213 |
msg = msg + "\n" + str(profile_log)
|
| 1214 |
return _ingest_status_html("done"), load_manifest_df(), msg
|
|
@@ -1737,6 +1774,16 @@ def run_ocr(page_selection: str = "", page_exclusion: str = "", replace_book_que
|
|
| 1737 |
debug = f"[DEBUG] SS_ROOT={SS_ROOT}\nMANIFEST_CSV={MANIFEST_CSV}\nCSV exists={MANIFEST_CSV.exists()}\n"
|
| 1738 |
if not df.empty:
|
| 1739 |
debug += f"Manifest rows={len(df)}\nStatuses={df['status'].value_counts().to_dict()}\n"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1740 |
else:
|
| 1741 |
debug += "Manifest is EMPTY\n"
|
| 1742 |
|
|
@@ -2614,7 +2661,7 @@ def smoke_signal_tab():
|
|
| 2614 |
|
| 2615 |
gr.Markdown("**Update rights class for existing book:**")
|
| 2616 |
with gr.Row():
|
| 2617 |
-
update_book_id = gr.Textbox(label="Book ID", placeholder="grf1999", scale=1)
|
| 2618 |
update_rights_dd = gr.Dropdown(
|
| 2619 |
label="New Rights Class",
|
| 2620 |
choices=["public-domain","licensed-owned","controlled-internal","unknown"],
|
|
@@ -2630,7 +2677,7 @@ def smoke_signal_tab():
|
|
| 2630 |
|
| 2631 |
gr.Markdown("**Save Book Pages + Safe Title (persisted):**")
|
| 2632 |
with gr.Row():
|
| 2633 |
-
scope_book_id = gr.Textbox(label="Book ID", placeholder="grf1999", scale=1)
|
| 2634 |
scope_include = gr.Textbox(label="Story Pages Include", placeholder="all or 7-27 or 7,8,9,11-27", scale=1)
|
| 2635 |
scope_exclude = gr.Textbox(label="Story Pages Exclude", placeholder="e.g. 1,2,3,17,25", scale=1)
|
| 2636 |
scope_title = gr.Textbox(label="Safe Book Title", placeholder="e.g. the-gruffalo", scale=1)
|
|
|
|
| 998 |
return slug[:120]
|
| 999 |
|
| 1000 |
|
| 1001 |
+
def _resolve_book_row(df: pd.DataFrame, selector: str) -> Optional[pd.Series]:
|
| 1002 |
+
if df.empty:
|
| 1003 |
+
return None
|
| 1004 |
+
raw = str(selector or "").strip()
|
| 1005 |
+
if not raw:
|
| 1006 |
+
return df.iloc[-1]
|
| 1007 |
+
|
| 1008 |
+
# Exact book_id
|
| 1009 |
+
exact = df[df["book_id"].astype(str) == raw]
|
| 1010 |
+
if not exact.empty:
|
| 1011 |
+
return exact.iloc[0]
|
| 1012 |
+
|
| 1013 |
+
low = raw.lower()
|
| 1014 |
+
|
| 1015 |
+
# Case-insensitive book_id
|
| 1016 |
+
bid_match = df[df["book_id"].astype(str).str.lower() == low]
|
| 1017 |
+
if not bid_match.empty:
|
| 1018 |
+
return bid_match.iloc[0]
|
| 1019 |
+
|
| 1020 |
+
# Safe title match
|
| 1021 |
+
if "safe_title" in df.columns:
|
| 1022 |
+
st_match = df[df["safe_title"].astype(str).str.lower() == low]
|
| 1023 |
+
if not st_match.empty:
|
| 1024 |
+
return st_match.iloc[0]
|
| 1025 |
+
|
| 1026 |
+
# Filename / stem match
|
| 1027 |
+
name_match = df[df["filename"].astype(str).str.lower() == low]
|
| 1028 |
+
if not name_match.empty:
|
| 1029 |
+
return name_match.iloc[0]
|
| 1030 |
+
stem_match = df[df["filename"].astype(str).str.lower().str.replace(".pdf", "", regex=False) == low]
|
| 1031 |
+
if not stem_match.empty:
|
| 1032 |
+
return stem_match.iloc[0]
|
| 1033 |
+
|
| 1034 |
+
return None
|
| 1035 |
+
|
| 1036 |
+
|
| 1037 |
def _clean_page_spec(spec: str) -> str:
|
| 1038 |
raw = (spec or "").strip().lower()
|
| 1039 |
if raw in ("", "all", "*", "none", "-"):
|
|
|
|
| 1069 |
|
| 1070 |
def save_book_scope(book_id: str, include_spec: str, exclude_spec: str, safe_title: str) -> tuple:
|
| 1071 |
df = load_manifest_df()
|
|
|
|
| 1072 |
if df.empty:
|
| 1073 |
return _ingest_status_html("idle"), df, "No books in manifest yet."
|
| 1074 |
+
row = _resolve_book_row(df, book_id)
|
| 1075 |
+
if row is None:
|
| 1076 |
+
return _ingest_status_html("idle"), df, f"Book ID or title '{book_id}' not found."
|
| 1077 |
+
bid = str(row["book_id"])
|
|
|
|
|
|
|
|
|
|
| 1078 |
|
| 1079 |
try:
|
| 1080 |
include_clean = _clean_page_spec(include_spec)
|
|
|
|
| 1090 |
if title_raw:
|
| 1091 |
safe = _safe_title_slug(title_raw)
|
| 1092 |
else:
|
| 1093 |
+
filename = str(row.get("filename", "") or "")
|
| 1094 |
stem = Path(filename).stem if filename else bid
|
| 1095 |
safe = _safe_title_slug(stem)
|
| 1096 |
|
|
|
|
| 1233 |
def update_rights(book_id: str, new_rights: str) -> tuple:
|
| 1234 |
"""Update rights class for an existing book."""
|
| 1235 |
df = load_manifest_df()
|
| 1236 |
+
if df.empty:
|
| 1237 |
+
return _ingest_status_html("idle"), df, "No books in manifest yet."
|
| 1238 |
+
row = _resolve_book_row(df, book_id)
|
| 1239 |
+
if row is None:
|
| 1240 |
+
return _ingest_status_html("idle"), df, f"Book ID or title '{book_id}' not found."
|
| 1241 |
+
resolved_book_id = str(row["book_id"])
|
| 1242 |
+
|
| 1243 |
+
prev_status = df.loc[df["book_id"] == resolved_book_id, "status"].values[0]
|
| 1244 |
+
df.loc[df["book_id"] == resolved_book_id, "rights_class"] = new_rights
|
| 1245 |
save_manifest_df(df)
|
| 1246 |
+
msg = f"[{datetime.utcnow().strftime('%H:%M:%S')}] ✓ Updated {resolved_book_id} rights → {new_rights}"
|
| 1247 |
if prev_status == "pending" and new_rights not in ("unknown", "excluded"):
|
| 1248 |
+
_, profile_log = run_profile(book_ids=[resolved_book_id])
|
| 1249 |
if profile_log:
|
| 1250 |
msg = msg + "\n" + str(profile_log)
|
| 1251 |
return _ingest_status_html("done"), load_manifest_df(), msg
|
|
|
|
| 1774 |
debug = f"[DEBUG] SS_ROOT={SS_ROOT}\nMANIFEST_CSV={MANIFEST_CSV}\nCSV exists={MANIFEST_CSV.exists()}\n"
|
| 1775 |
if not df.empty:
|
| 1776 |
debug += f"Manifest rows={len(df)}\nStatuses={df['status'].value_counts().to_dict()}\n"
|
| 1777 |
+
try:
|
| 1778 |
+
row_summaries = []
|
| 1779 |
+
for _, r in df.iterrows():
|
| 1780 |
+
row_summaries.append(
|
| 1781 |
+
f"{r.get('book_id','?')} rights={r.get('rights_class','?')} status={r.get('status','?')}"
|
| 1782 |
+
)
|
| 1783 |
+
if row_summaries:
|
| 1784 |
+
debug += "Rows:\n- " + "\n- ".join(row_summaries) + "\n"
|
| 1785 |
+
except Exception:
|
| 1786 |
+
pass
|
| 1787 |
else:
|
| 1788 |
debug += "Manifest is EMPTY\n"
|
| 1789 |
|
|
|
|
| 2661 |
|
| 2662 |
gr.Markdown("**Update rights class for existing book:**")
|
| 2663 |
with gr.Row():
|
| 2664 |
+
update_book_id = gr.Textbox(label="Book ID (optional)", placeholder="grf1999 or leave blank to use latest", scale=1)
|
| 2665 |
update_rights_dd = gr.Dropdown(
|
| 2666 |
label="New Rights Class",
|
| 2667 |
choices=["public-domain","licensed-owned","controlled-internal","unknown"],
|
|
|
|
| 2677 |
|
| 2678 |
gr.Markdown("**Save Book Pages + Safe Title (persisted):**")
|
| 2679 |
with gr.Row():
|
| 2680 |
+
scope_book_id = gr.Textbox(label="Book ID (optional)", placeholder="grf1999 or leave blank to use latest", scale=1)
|
| 2681 |
scope_include = gr.Textbox(label="Story Pages Include", placeholder="all or 7-27 or 7,8,9,11-27", scale=1)
|
| 2682 |
scope_exclude = gr.Textbox(label="Story Pages Exclude", placeholder="e.g. 1,2,3,17,25", scale=1)
|
| 2683 |
scope_title = gr.Textbox(label="Safe Book Title", placeholder="e.g. the-gruffalo", scale=1)
|