"""Serve a refused GPU booking from Inference Providers instead. ZeroGPU refuses a booking *before* it runs the callback: the scheduler checks the requested duration against the visitor's remaining quota and raises, so nothing has happened yet and the same call can simply be made somewhere else. That is the whole reason this is safe to retry - a failure raised from inside a running callback must not be retried, because half the work is already done and `accept` writes files and opens a pull request. So the test is deliberately narrow: only the messages ZeroGPU produces at admission, and only when the operator has set a spending ceiling, which is what turns the fallback on. Everything else is re-raised untouched. """ import functools # All raised by spaces.zero.client.schedule() before the callback is invoked. ADMISSION_REFUSALS = ( "is larger than the maximum allowed", "exceeded your zerogpu", "exceeded your pro zerogpu", "exceeded your free zerogpu", "exceeded your zerogpu runs limit", "has reached its gpu limit", "no gpu was available", "too many zerogpu credits allocated", ) def is_admission_refusal(exc): """True only for a refusal raised before the callback body ran.""" text = str(exc).lower() return any(phrase in text for phrase in ADMISSION_REFUSALS) def guarded(plain, booked, enabled, enter, leave, log): """`booked` first; on an admission refusal, `plain` between enter/leave. functools.wraps is load-bearing rather than tidy: Gradio decides whether to inject a gr.OAuthProfile by reading the callback's annotations and signature, and an unwrapped *args/**kwargs shim would hide both and quietly sign every visitor out - the failure this app has already had once. """ @functools.wraps(plain) def run(*args, **kwargs): try: return booked(*args, **kwargs) except Exception as exc: # noqa: BLE001 if not (enabled() and is_admission_refusal(exc)): raise log(exc) enter() try: return plain(*args, **kwargs) finally: leave() return run