Skip to content

Commit

Permalink
Handle Django compatibility (#3835)
Browse files Browse the repository at this point in the history
* Handle Django compatibility

* Improve exception handling for django
  • Loading branch information
philippjfr authored Sep 14, 2022
1 parent 3a7a791 commit 0911b29
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 17 deletions.
5 changes: 4 additions & 1 deletion panel/io/django.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from contextlib import contextmanager
from urllib.parse import urljoin, urlparse

from bokeh.server.django.consumers import AutoloadJsConsumer, DocConsumer
try:
from bokeh_django.consumers import AutoloadJsConsumer, DocConsumer
except Exception:
from bokeh.server.django.consumers import AutoloadJsConsumer, DocConsumer

from ..util import edit_readonly
from .resources import Resources
Expand Down
57 changes: 41 additions & 16 deletions panel/io/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,40 @@ def wrapper(*args, **kw):
wrapper.lock = True # type: ignore
return wrapper

def dispatch_tornado(conn, event):
from tornado.websocket import WebSocketHandler
socket = conn._socket
ws_conn = socket.ws_connection
if not ws_conn or ws_conn.is_closing(): # type: ignore
return
msg = conn.protocol.create('PATCH-DOC', [event])
futures = [
WebSocketHandler.write_message(socket, msg.header_json),
WebSocketHandler.write_message(socket, msg.metadata_json),
WebSocketHandler.write_message(socket, msg.content_json)
]
for header, payload in msg._buffers:
futures.extend([
WebSocketHandler.write_message(socket, header),
WebSocketHandler.write_message(socket, payload, binary=True)
])
return futures

def dispatch_django(conn, event):
socket = conn._socket
msg = conn.protocol.create('PATCH-DOC', [event])
futures = [
socket.send(text_data=msg.header_json),
socket.send(text_data=msg.metadata_json),
socket.send(text_data=msg.content_json)
]
for header, payload in msg._buffers:
futures.extend([
socket.send(text_data=header),
socket.send(binary_data=payload)
])
return futures

@contextmanager
def unlocked() -> Iterator:
"""
Expand Down Expand Up @@ -160,22 +194,10 @@ def unlocked() -> Iterator:
remaining_events.append(event)
continue
for conn in connections:
socket = conn._socket
ws_conn = getattr(socket, 'ws_connection', False)
if (not hasattr(socket, 'write_message') or
ws_conn is None or (ws_conn and ws_conn.is_closing())): # type: ignore
continue
msg = conn.protocol.create('PATCH-DOC', [event])
futures.extend([
WebSocketHandler.write_message(socket, msg.header_json),
WebSocketHandler.write_message(socket, msg.metadata_json),
WebSocketHandler.write_message(socket, msg.content_json)
])
for header, payload in msg._buffers:
futures.extend([
WebSocketHandler.write_message(socket, header),
WebSocketHandler.write_message(socket, payload, binary=True)
])
if isinstance(conn._socket, WebSocketHandler):
futures += dispatch_tornado(conn, event)
else:
futures += dispatch_django(conn, event)

# Ensure that all write_message calls are awaited and handled
async def handle_write_errors():
Expand All @@ -184,6 +206,9 @@ async def handle_write_errors():
await future
except WebSocketClosedError:
logger.warning("Failed sending message as connection was closed")
except Exception as e:
logger.warning(f"Failed sending message due to following error: {e}")

asyncio.ensure_future(handle_write_errors())

curdoc.callbacks._held_events = remaining_events
Expand Down

0 comments on commit 0911b29

Please sign in to comment.