LoocasGoose Claude Opus 4.6 commited on
Commit
f34ea8c
·
1 Parent(s): 40cdbbd

Fix: replace gr.JSON with gr.Code to fix API schema crash on HF Spaces

Browse files

gr.JSON generates a JSON Schema with additionalProperties: true (boolean),
which crashes gradio_client's json_schema_to_python_type on Python 3.13
with "TypeError: argument of type 'bool' is not iterable". This broke
the /gradio_api/api_info endpoint, causing all event handlers to fail
with "No API found".

Replace gr.JSON with gr.Code(language="json") and serialize dicts to
JSON strings, avoiding the problematic schema entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

protein_conformal/backend/gradio_interface.py CHANGED
@@ -7,6 +7,7 @@ and perform conformal prediction with statistical guarantees.
7
  """
8
 
9
  import gradio as gr
 
10
  import numpy as np
11
  import os
12
  import sys
@@ -544,7 +545,7 @@ def process_input(input_text: str,
544
  """Wrapper that instruments the main pipeline with timing information."""
545
  stage_timer = StageTimer()
546
  try:
547
- return _process_input_impl(
548
  stage_timer,
549
  input_text,
550
  fasta_text,
@@ -562,6 +563,7 @@ def process_input(input_text: str,
562
  match_type,
563
  progress,
564
  )
 
565
  finally:
566
  stage_timer.log_summary()
567
 
@@ -907,14 +909,14 @@ def export_current_results(format_type: str) -> Tuple[Dict[str, Any], Optional[s
907
  Tuple of (status dict, file path for download)
908
  """
909
  global CURRENT_SESSION
910
-
911
  if not CURRENT_SESSION or "results" not in CURRENT_SESSION:
912
- return {"error": "No results to export"}, None
913
-
914
  try:
915
  # Create a directory for exported reports if it doesn't exist
916
  os.makedirs("exported_reports", exist_ok=True)
917
-
918
  # Create a unique filename
919
  from datetime import datetime
920
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
@@ -927,36 +929,34 @@ def export_current_results(format_type: str) -> Tuple[Dict[str, Any], Optional[s
927
  "exported_reports",
928
  f"results_{timestamp}_{risk_type}_{threshold_tag}.{format_type}",
929
  )
930
-
931
  # Export the results
932
  if format_type == "csv":
933
  if "matches" in CURRENT_SESSION["results"]:
934
- import pandas as pd
935
  # Export ALL matches, not just the displayed ones
936
  df = pd.DataFrame(CURRENT_SESSION["results"]["matches"])
937
  df.to_csv(file_path, index=False)
938
  total_exported = len(df)
939
  else:
940
- return {"error": "No matches to export"}, None
941
  elif format_type == "json":
942
  with open(file_path, 'w') as f:
943
- import json
944
  # For JSON export, we include the full result structure
945
  json.dump(CURRENT_SESSION["results"], f, indent=2)
946
  total_exported = CURRENT_SESSION["results"]["num_matches"]
947
  else:
948
- return {"error": f"Unsupported format: {format_type}"}, None
949
-
950
- return {
951
  "success": True,
952
  "message": f"Results exported as {file_path} ({total_exported} records)",
953
  "file_path": file_path
954
- }, file_path
955
-
956
  except Exception as e:
957
- return {
958
  "error": f"Error exporting results: {str(e)}"
959
- }, None
960
 
961
  def create_interface():
962
  """
@@ -1148,7 +1148,7 @@ def create_interface():
1148
  )
1149
 
1150
  with gr.Column(scale=1):
1151
- results_summary = gr.JSON(label="Search Summary")
1152
 
1153
  with gr.Row():
1154
  export_format = gr.Radio(
@@ -1159,7 +1159,7 @@ def create_interface():
1159
  )
1160
  export_btn = gr.Button("Export", size="sm", scale=1)
1161
 
1162
- export_status = gr.JSON(label="Export Status", visible=True)
1163
  export_download = gr.File(label="Download", interactive=False)
1164
 
1165
  with gr.TabItem("About"):
 
7
  """
8
 
9
  import gradio as gr
10
+ import json
11
  import numpy as np
12
  import os
13
  import sys
 
545
  """Wrapper that instruments the main pipeline with timing information."""
546
  stage_timer = StageTimer()
547
  try:
548
+ summary, df = _process_input_impl(
549
  stage_timer,
550
  input_text,
551
  fasta_text,
 
563
  match_type,
564
  progress,
565
  )
566
+ return json.dumps(summary, indent=2, default=str), df
567
  finally:
568
  stage_timer.log_summary()
569
 
 
909
  Tuple of (status dict, file path for download)
910
  """
911
  global CURRENT_SESSION
912
+
913
  if not CURRENT_SESSION or "results" not in CURRENT_SESSION:
914
+ return json.dumps({"error": "No results to export"}, indent=2), None
915
+
916
  try:
917
  # Create a directory for exported reports if it doesn't exist
918
  os.makedirs("exported_reports", exist_ok=True)
919
+
920
  # Create a unique filename
921
  from datetime import datetime
922
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
 
929
  "exported_reports",
930
  f"results_{timestamp}_{risk_type}_{threshold_tag}.{format_type}",
931
  )
932
+
933
  # Export the results
934
  if format_type == "csv":
935
  if "matches" in CURRENT_SESSION["results"]:
 
936
  # Export ALL matches, not just the displayed ones
937
  df = pd.DataFrame(CURRENT_SESSION["results"]["matches"])
938
  df.to_csv(file_path, index=False)
939
  total_exported = len(df)
940
  else:
941
+ return json.dumps({"error": "No matches to export"}, indent=2), None
942
  elif format_type == "json":
943
  with open(file_path, 'w') as f:
 
944
  # For JSON export, we include the full result structure
945
  json.dump(CURRENT_SESSION["results"], f, indent=2)
946
  total_exported = CURRENT_SESSION["results"]["num_matches"]
947
  else:
948
+ return json.dumps({"error": f"Unsupported format: {format_type}"}, indent=2), None
949
+
950
+ return json.dumps({
951
  "success": True,
952
  "message": f"Results exported as {file_path} ({total_exported} records)",
953
  "file_path": file_path
954
+ }, indent=2), file_path
955
+
956
  except Exception as e:
957
+ return json.dumps({
958
  "error": f"Error exporting results: {str(e)}"
959
+ }, indent=2), None
960
 
961
  def create_interface():
962
  """
 
1148
  )
1149
 
1150
  with gr.Column(scale=1):
1151
+ results_summary = gr.Code(language="json", label="Search Summary", interactive=False)
1152
 
1153
  with gr.Row():
1154
  export_format = gr.Radio(
 
1159
  )
1160
  export_btn = gr.Button("Export", size="sm", scale=1)
1161
 
1162
+ export_status = gr.Code(language="json", label="Export Status", interactive=False)
1163
  export_download = gr.File(label="Download", interactive=False)
1164
 
1165
  with gr.TabItem("About"):