Spaces:
Running
Running
Commit
·
f34ea8c
1
Parent(s):
40cdbbd
Fix: replace gr.JSON with gr.Code to fix API schema crash on HF Spaces
Browse filesgr.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 |
-
|
| 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.
|
| 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.
|
| 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"):
|