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 files

The 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>

Files changed (1) hide show
  1. app.py +55 -9
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 gradio 4.44.0 bugs ─────────────────────────────────────────
15
- # Bug 1: gradio_client/utils.py get_type() crashes with TypeError when
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 any residual TypeError
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