Spaces:
Sleeping
Sleeping
File size: 6,309 Bytes
34b69bb 822af44 7d6e5a5 34b69bb 822af44 34b69bb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | """
Error Tester: a PyHARP app for exercising HARP's Gradio error handling.
The app performs no model inference. Its process endpoint deliberately raises
or returns selected failure shapes so HARP can be checked against the user-facing
messages in src/utils/Errors.h.
"""
import spaces
from pyharp import *
from typing import Optional, Tuple
import gradio as gr
import os
import tempfile
import time
import wave
model_card = ModelCard(
name="Error Tester",
description=(
"Raises controlled Gradio errors, runtime errors, quota messages, "
"Space-status messages, and malformed output payloads for testing "
"HARP's error handling."
),
author="TEAMuP",
tags=["example", "test", "error handling", "v3"],
)
ERROR_FAMILIES = [
"Success",
"Gradio runtime error",
"Python runtime error",
"ZeroGPU quota error",
"Space status error",
"Output payload error",
]
ERROR_VARIANTS = [
"Default message",
"Empty detail",
"Long detail",
"Custom detail",
]
OUTPUT_PAYLOADS = [
"Valid empty labels",
"Malformed label JSON",
"Missing audio file",
"Unsupported audio extension",
]
DEFAULT_DETAIL = (
"Synthetic failure from the PyHARP Error Tester. This is expected and is "
"intended to test HARP's error popup."
)
def write_silent_wav(duration_seconds: float = 0.25, sample_rate: int = 44100) -> str:
"""Create a small WAV file using only the Python standard library."""
fd, path = tempfile.mkstemp(prefix="harp_error_tester_", suffix=".wav")
os.close(fd)
frame_count = int(duration_seconds * sample_rate)
with wave.open(path, "wb") as wav:
wav.setnchannels(1)
wav.setsampwidth(2)
wav.setframerate(sample_rate)
wav.writeframes(b"\x00\x00" * frame_count)
return path
def build_detail(variant: str, custom_detail: str) -> str:
if variant == "Empty detail":
return ""
if variant == "Long detail":
return (
DEFAULT_DETAIL
+ " "
+ "This deliberately long diagnostic text should be shortened in "
+ "HARP's transient status area while remaining available in the "
+ "final error dialog. "
+ "x" * 260
)
if variant == "Custom detail" and custom_detail.strip():
return custom_detail.strip()
return DEFAULT_DETAIL
def build_labels(message: str) -> LabelList:
labels = LabelList()
labels.labels.append(
AudioLabel(
t=0.0,
label="success",
duration=0.25,
description=message,
color=OutputLabel.rgb_color_to_int(20, 120, 80),
amplitude=0.5,
)
)
return labels
@spaces.GPU
def process_fn(
input_audio_path: Optional[str],
error_family: str,
error_variant: str,
output_payload: str,
delay_seconds: float,
custom_detail: str,
) -> Tuple[str, LabelList]:
if delay_seconds > 0:
time.sleep(float(delay_seconds))
detail = build_detail(error_variant, custom_detail)
if error_family == "Gradio runtime error":
raise gr.Error(detail or "The Gradio server reported a runtime error.")
if error_family == "Python runtime error":
raise RuntimeError(detail or "Python RuntimeError without additional detail.")
if error_family == "ZeroGPU quota error":
quota_detail = detail or "GPU quota has been exceeded for this Space."
raise gr.Error(f"ZeroGPU quota exceeded: {quota_detail}")
if error_family == "Space status error":
status_detail = detail or "Check its status on HF."
raise gr.Error(f"Your Space is in error. {status_detail}")
if error_family == "Output payload error":
audio_path = write_silent_wav()
if output_payload == "Malformed label JSON":
return audio_path, {"labels": "this should be a list"}
if output_payload == "Missing audio file":
return "/tmp/harp_error_tester_missing_output.wav", LabelList()
if output_payload == "Unsupported audio extension":
fd, path = tempfile.mkstemp(prefix="harp_error_tester_", suffix=".txt")
with os.fdopen(fd, "w") as f:
f.write("This is not an audio file.\n")
return path, LabelList()
audio_path = input_audio_path or write_silent_wav()
labels = build_labels(f"Selected family: {error_family}. No error was raised.")
return audio_path, labels
with gr.Blocks() as demo:
input_components = [
gr.Audio(
type="filepath",
label="Optional Input Audio",
)
.harp_required(False)
.set_info("Passed through on success. A silent WAV is generated if empty."),
gr.Dropdown(
choices=ERROR_FAMILIES,
value="Gradio runtime error",
label="Error Family",
info="The broad error path to exercise."
),
gr.Dropdown(
choices=ERROR_VARIANTS,
value="Default message",
label="Error Detail",
info="Controls the detail text carried by raised errors."
),
gr.Dropdown(
choices=OUTPUT_PAYLOADS,
value="Valid empty labels",
label="Output Payload",
info="Used only when Error Family is Output payload error."
),
gr.Slider(
minimum=0,
maximum=30,
step=1,
value=0,
label="Delay (s)",
info="Stalls before producing the selected response."
),
gr.Textbox(
value="",
label="Custom Detail",
info="Used when Error Detail is Custom detail."
),
]
output_components = [
gr.Audio(
type="filepath",
label="Output Audio",
).set_info("Silent or pass-through audio for successful responses."),
gr.JSON(
label="Output Labels",
).set_info("Labels returned on successful responses."),
]
app = build_endpoint(
model_card=model_card,
input_components=input_components,
output_components=output_components,
process_fn=process_fn,
)
demo.queue().launch(share=True, show_error=True, pwa=True)
|