Pointf5ive commited on
Commit
55f755c
·
1 Parent(s): b9de0c7

Make rights/page-scope updates resilient and auto-resolve latest book

Browse files
Files changed (1) hide show
  1. 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
- if not bid:
1040
- if len(df) == 1:
1041
- bid = str(df.iloc[0]["book_id"])
1042
- else:
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(df.loc[df["book_id"] == bid, "filename"].values[0] or "")
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 or book_id not in df["book_id"].values:
1205
- return _ingest_status_html("idle"), df, f"Book ID {book_id} not found."
1206
- prev_status = df.loc[df["book_id"] == book_id, "status"].values[0]
1207
- df.loc[df["book_id"] == book_id, "rights_class"] = new_rights
 
 
 
 
 
1208
  save_manifest_df(df)
1209
- msg = f"[{datetime.utcnow().strftime('%H:%M:%S')}] ✓ Updated {book_id} rights → {new_rights}"
1210
  if prev_status == "pending" and new_rights not in ("unknown", "excluded"):
1211
- _, profile_log = run_profile(book_ids=[book_id])
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)