function with_lock
A decorator that wraps callback functions (both sync and async) to mark them for execution with a Bokeh document lock, allowing safe modification of Bokeh models.
/tf/active/vicechatdev/patches/server.py
399 - 423
simple
Purpose
This decorator is used in Bokeh/Panel applications to ensure that callback functions can safely modify Bokeh models by executing with the appropriate document lock. It preserves the original function's signature and async nature while adding a 'lock' attribute set to True, which signals to the framework that this function requires lock acquisition before execution. This is critical for thread-safe operations in Bokeh server applications where multiple callbacks might attempt to modify the document simultaneously.
Source Code
def with_lock(func):
"""
Wrap a callback function to execute with a lock allowing the
function to modify bokeh models directly.
Arguments
---------
func: callable
The callable to wrap
Returns
-------
wrapper: callable
Function wrapped to execute without a Document lock.
"""
if inspect.iscoroutinefunction(func):
@wraps(func)
async def wrapper(*args, **kw):
return await func(*args, **kw)
else:
@wraps(func)
def wrapper(*args, **kw):
return func(*args, **kw)
wrapper.lock = True
return wrapper
Parameters
| Name | Type | Default | Kind |
|---|---|---|---|
func |
- | - | positional_or_keyword |
Parameter Details
func: A callable (function or coroutine function) that needs to be wrapped for lock-protected execution. Can be either a synchronous function or an async coroutine function. The function will be wrapped while preserving its original behavior and signature.
Return Value
Returns a wrapper function that has the same signature and behavior as the input function, but with an additional 'lock' attribute set to True. If the input is a coroutine function, returns an async wrapper; otherwise returns a synchronous wrapper. The wrapper preserves the original function's metadata through functools.wraps.
Dependencies
inspectfunctools
Required Imports
import inspect
from functools import wraps
Usage Example
import inspect
from functools import wraps
def with_lock(func):
if inspect.iscoroutinefunction(func):
@wraps(func)
async def wrapper(*args, **kw):
return await func(*args, **kw)
else:
@wraps(func)
def wrapper(*args, **kw):
return func(*args, **kw)
wrapper.lock = True
return wrapper
# Example 1: Synchronous callback
@with_lock
def update_plot(event):
# Safely modify Bokeh models
plot.title.text = 'Updated Title'
return 'Updated'
# Example 2: Async callback
@with_lock
async def async_update(event):
# Safely modify Bokeh models in async context
await some_async_operation()
plot.title.text = 'Async Updated'
return 'Done'
# Check that lock attribute is set
print(update_plot.lock) # True
print(async_update.lock) # True
Best Practices
- Use this decorator on any callback function that modifies Bokeh models to ensure thread-safe execution
- The decorator automatically detects whether the function is async or sync and wraps it appropriately
- The 'lock' attribute on the wrapper is used by the framework to determine lock acquisition strategy - do not modify it manually
- This decorator should be applied to callbacks used in Bokeh server applications, particularly when using Panel or custom Bokeh applications
- The decorator preserves the original function's metadata (name, docstring, etc.) through functools.wraps
- For async functions, ensure your execution environment supports async/await syntax
Tags
Similar Components
AI-powered semantic similarity - components with related functionality:
-
function async_execute 63.3% similar
-
function unlocked 56.9% similar
-
function guard_execution 50.0% similar
-
function run_with_timeout 49.9% similar
-
function modify_document 45.7% similar