Spaces:
Sleeping
Sleeping
ibcplateformes Claude Opus 4.6 commited on
Commit ·
80d0f11
1
Parent(s): c1ed66c
Patch jinja2 LRUCache to handle unhashable keys from gradio 4.44.0
Browse filesThe root cause is gradio 4.44.0 corrupting internal state with
additionalProperties:true schemas, which propagates unhashable dict/list
objects into jinja2's template cache keys. This patch makes jinja2's
LRUCache treat unhashable keys as cache misses instead of crashing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
app.py
CHANGED
|
@@ -9,15 +9,62 @@ import logging
|
|
| 9 |
import tempfile
|
| 10 |
import shutil
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
import gradio as gr
|
| 13 |
|
| 14 |
-
# ── Monkey-patch
|
| 15 |
-
#
|
| 16 |
-
# schema is a bool (additionalProperties: true in JSON schema).
|
| 17 |
-
# Bug 2: _json_schema_to_python_type() also crashes on bool schemas.
|
| 18 |
-
# Strategy: Wrap both functions to catch TypeError — do NOT modify any schema
|
| 19 |
-
# dicts, as that leaks into jinja2's LRU cache and causes
|
| 20 |
-
# "unhashable type: dict" errors in template rendering.
|
| 21 |
try:
|
| 22 |
import gradio_client.utils as _gc_utils
|
| 23 |
|
|
@@ -47,8 +94,7 @@ try:
|
|
| 47 |
except Exception:
|
| 48 |
pass
|
| 49 |
|
| 50 |
-
# Safety net: patch Blocks.get_api_info to prevent
|
| 51 |
-
# from crashing the entire app during health checks or page loads.
|
| 52 |
try:
|
| 53 |
_orig_get_api_info = gr.Blocks.get_api_info
|
| 54 |
|
|
|
|
| 9 |
import tempfile
|
| 10 |
import shutil
|
| 11 |
|
| 12 |
+
# ── Patch jinja2 LRU cache BEFORE importing gradio ──────────────────────────
|
| 13 |
+
# Gradio 4.44.0 has a bug where component JSON schemas with
|
| 14 |
+
# `additionalProperties: true` (a bool) corrupt gradio's internal state,
|
| 15 |
+
# causing jinja2's LRU cache to receive unhashable keys (dicts/lists).
|
| 16 |
+
# We patch jinja2's LRUCache to treat unhashable keys as cache misses
|
| 17 |
+
# instead of crashing the entire app.
|
| 18 |
+
try:
|
| 19 |
+
import jinja2.utils as _j2utils
|
| 20 |
+
|
| 21 |
+
_OrigLRUCache = _j2utils.LRUCache
|
| 22 |
+
|
| 23 |
+
class _SafeLRUCache(_OrigLRUCache):
|
| 24 |
+
def __getitem__(self, key):
|
| 25 |
+
try:
|
| 26 |
+
return super().__getitem__(key)
|
| 27 |
+
except TypeError:
|
| 28 |
+
raise KeyError(key)
|
| 29 |
+
|
| 30 |
+
def get(self, key, default=None):
|
| 31 |
+
try:
|
| 32 |
+
return super().get(key, default)
|
| 33 |
+
except TypeError:
|
| 34 |
+
return default
|
| 35 |
+
|
| 36 |
+
def __setitem__(self, key, value):
|
| 37 |
+
try:
|
| 38 |
+
super().__setitem__(key, value)
|
| 39 |
+
except TypeError:
|
| 40 |
+
pass # Skip caching for unhashable keys
|
| 41 |
+
|
| 42 |
+
def __contains__(self, key):
|
| 43 |
+
try:
|
| 44 |
+
return super().__contains__(key)
|
| 45 |
+
except TypeError:
|
| 46 |
+
return False
|
| 47 |
+
|
| 48 |
+
_j2utils.LRUCache = _SafeLRUCache
|
| 49 |
+
|
| 50 |
+
# Also patch any already-created Environment caches
|
| 51 |
+
import jinja2.environment
|
| 52 |
+
_OrigEnvInit = jinja2.environment.Environment.__init__
|
| 53 |
+
|
| 54 |
+
def _patched_env_init(self, *args, **kwargs):
|
| 55 |
+
_OrigEnvInit(self, *args, **kwargs)
|
| 56 |
+
if isinstance(self.cache, _OrigLRUCache) and not isinstance(self.cache, _SafeLRUCache):
|
| 57 |
+
old_cap = self.cache.capacity
|
| 58 |
+
self.cache = _SafeLRUCache(old_cap)
|
| 59 |
+
|
| 60 |
+
jinja2.environment.Environment.__init__ = _patched_env_init
|
| 61 |
+
except Exception:
|
| 62 |
+
pass
|
| 63 |
+
|
| 64 |
import gradio as gr
|
| 65 |
|
| 66 |
+
# ── Monkey-patch gradio_client schema parsing bugs ──────────────────────────
|
| 67 |
+
# get_type() and _json_schema_to_python_type() crash when schema is a bool.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
try:
|
| 69 |
import gradio_client.utils as _gc_utils
|
| 70 |
|
|
|
|
| 94 |
except Exception:
|
| 95 |
pass
|
| 96 |
|
| 97 |
+
# Safety net: patch Blocks.get_api_info to prevent TypeError propagation.
|
|
|
|
| 98 |
try:
|
| 99 |
_orig_get_api_info = gr.Blocks.get_api_info
|
| 100 |
|