Skip to content

Commit

Permalink
More types
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Nov 15, 2024
1 parent 750a217 commit 9e602c9
Show file tree
Hide file tree
Showing 10 changed files with 46 additions and 35 deletions.
4 changes: 2 additions & 2 deletions panel/chat/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ class ChatInterface(ChatFeed):
>>> yield contents
>>> chat_interface = ChatInterface(
callback=repeat_contents, widgets=[TextInput(), FileInput()]
)
... callback=repeat_contents, widgets=[TextInput(), FileInput()]
... )
"""

auto_send_types = param.List(doc="""
Expand Down
2 changes: 1 addition & 1 deletion panel/io/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,7 +562,7 @@ def server_clear(session_context, clear=clear):
except AttributeError:
pass

return wrapped_func
return wrapped_func # type: ignore

def is_equal(value, other)->bool:
"""Returns True if value and other are equal
Expand Down
2 changes: 1 addition & 1 deletion panel/io/django.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
try:
from bokeh_django.consumers import AutoloadJsConsumer, DocConsumer
except Exception:
from bokeh.server.django.consumers import AutoloadJsConsumer, DocConsumer
from bokeh.server.django.consumers import AutoloadJsConsumer, DocConsumer # type: ignore

from ..util import edit_readonly
from .resources import Resources
Expand Down
8 changes: 4 additions & 4 deletions panel/io/ipywidget.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from ipywidgets.widgets.widget import _remove_buffers

# Stop ipywidgets_bokeh from patching the kernel
ipykernel.kernelbase.Kernel._instance = ''
ipykernel.kernelbase.Kernel._instance = '' # type: ignore

from ipywidgets_bokeh.kernel import (
BokehKernel, SessionWebsocket, WebsocketStream,
Expand All @@ -33,7 +33,7 @@
try:
from ipykernel.comm.comm import BaseComm as _IPyComm
except Exception:
from ipykernel.comm.comm import Comm as _IPyComm
from ipykernel.comm.comm import Comm as _IPyComm # type: ignore

try:
# Support for ipywidgets>=8.0.5
Expand All @@ -46,7 +46,7 @@ def publish_msg(self, *args, **kwargs): pass

comm.create_comm = lambda *args, **kwargs: TempComm(target_name='panel-temp-comm', primary=False)
except Exception:
comm = None
comm = None # type: ignore

def _get_kernel(cls=None, doc=None):
doc = doc or state.curdoc
Expand Down Expand Up @@ -233,5 +233,5 @@ def wrapper(*args, **kwargs):
# Patch kernel and widget objects
_ORIG_KERNEL = ipykernel.kernelbase.Kernel._instance
if isinstance(ipykernel.kernelbase.Kernel._instance, (BokehKernel, str)):
ipykernel.kernelbase.Kernel._instance = classproperty(_get_kernel)
ipykernel.kernelbase.Kernel._instance = classproperty(_get_kernel) # type: ignore
Widget.on_widget_constructed(_on_widget_constructed)
7 changes: 4 additions & 3 deletions panel/io/notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,8 @@ def render_model(
# ALERT: Replace with better approach before Bokeh 3.x compatible release
dist_url = '/panel-preview/static/extensions/panel/'
patch_model_css(model, dist_url=dist_url)
model.document._template_variables['dist_url'] = dist_url
if model.document:
model.document._template_variables['dist_url'] = dist_url

(docs_json, [render_item]) = standalone_docs_json_and_render_items([model], suppress_callback_warning=True)
div = div_for_render_item(render_item)
Expand Down Expand Up @@ -479,7 +480,7 @@ def show_server(panel: Any, notebook_url: str, port: int = 0) -> 'Server':
if callable(notebook_url):
url = notebook_url(server.port)
else:
url = _server_url(notebook_url, server.port)
url = _server_url(notebook_url, server.port or port)

script = server_document(url, resources=None)

Expand All @@ -495,7 +496,7 @@ def render_embed(
panel, max_states: int = 1000, max_opts: int = 3, json: bool = False,
json_prefix: str = '', save_path: str = './', load_path: Optional[str] = None,
progress: bool = True, states: dict[Widget, list[Any]] = {}
) -> None:
) -> Mimebundle:
"""
Renders a static version of a panel in a notebook by evaluating
the set of states defined by the widgets in the model. Note
Expand Down
15 changes: 7 additions & 8 deletions panel/io/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,6 @@ class ResourceComponent:
'raw_css': [],
}


@classmethod
def _resolve_resource(
cls,
Expand Down Expand Up @@ -556,9 +555,9 @@ def resolve_resources(
for name, url in res.items()
}
if rt in resources:
resources[rt] = dict(resources[rt], **res)
resources[rt] = dict(resources[rt], **res) # type: ignore
else:
resources[rt] = res
resources[rt] = res # type: ignore

resource_types: ResourcesType = {
'js': {},
Expand All @@ -569,20 +568,20 @@ def resolve_resources(

cdn = use_cdn() if cdn == 'auto' else cdn
for resource_type in resource_types:
if resource_type not in resources or resource_type == 'raw_css':
if resource_type not in resources or resource_type == 'raw_css': # type: ignore
continue
resource_files = resource_types[resource_type]
for rname, resource in resources[resource_type].items():
resource_files = resource_types[resource_type] # type: ignore
for rname, resource in resources[resource_type].items(): # type: ignore
resolved_resource = self._resolve_resource(
resource_type, resource, cdn=cdn
)
if resolved_resource:
resource_files[rname] = resolved_resource
resource_files[rname] = resolved_resource # type: ignore

version_suffix = f'?v={JS_VERSION}'
dist_path = get_dist_path(cdn=cdn)
for resource_type, extra_resources in (extras or {}).items():
resource_files = resource_types[resource_type]
resource_files = resource_types[resource_type] # type: ignore
for name, res in extra_resources.items():
if not cdn:
res = res.replace(CDN_DIST, dist_path)
Expand Down
23 changes: 15 additions & 8 deletions panel/io/save.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
OutputDocumentFor, standalone_docs_json_and_render_items,
)
from bokeh.io.export import get_screenshot_as_png
from bokeh.model import Model
from bokeh.model import Model, UIElement
from bokeh.resources import CDN, INLINE, Resources as BkResources
from pyviz_comms import Comm

Expand Down Expand Up @@ -59,8 +59,12 @@
bokeh.io.export._WAIT_SCRIPT = _WAIT_SCRIPT

def save_png(
model: Model, filename: str, resources=CDN, template=None,
template_variables=None, timeout: int = 5
model: UIElement | Document,
filename: str | os.PathLike | IO,
resources: BkResources = CDN,
template=None,
template_variables: dict[str, Any] | None = None,
timeout: int = 5
) -> None:
"""
Saves a bokeh model to png
Expand Down Expand Up @@ -104,15 +108,15 @@ def save_png(
"""

try:
def get_layout_html(obj, resources, width, height, **kwargs):
def get_layout_html(obj: UIElement | Document, resources: Resources, width: int | None, height: int | None, **kwargs):
resources = Resources.from_bokeh(resources)
return file_html(
obj, resources, title="", template=template,
template_variables=template_variables or {},
_always_new=True
)
old_layout_fn = bokeh.io.export.get_layout_html
bokeh.io.export.get_layout_html = get_layout_html
bokeh.io.export.get_layout_html = get_layout_html # type: ignore
img = get_screenshot_as_png(model, driver=webdriver, timeout=timeout, resources=resources)

if img.width == 0 or img.height == 0:
Expand Down Expand Up @@ -140,7 +144,7 @@ def _title_from_models(models: Iterable[Model], title: str) -> str:
return DEFAULT_TITLE

def file_html(
models: Model | Document | list[Model], resources: Resources | None,
models: Model | Document | list[Model], resources: BkResources | None,
title: str | None = None, template: Template | str = BASE_TEMPLATE,
template_variables: dict[str, Any] = {}, theme: ThemeLike = None,
_always_new: bool = False
Expand All @@ -159,7 +163,7 @@ def file_html(
(docs_json, render_items) = standalone_docs_json_and_render_items(
models_seq, suppress_callback_warning=True
)
title = _title_from_models(models_seq, title)
title = _title_from_models(models_seq, title or 'Panel Application')
bundle = bundle_resources(models_seq, resources)
return html_page_for_render_items(
bundle, docs_json, render_items, title=title, template=template,
Expand Down Expand Up @@ -252,7 +256,7 @@ def save(
comm = Comm()
with config.set(embed=embed):
if isinstance(panel, Document):
model = panel
model: Document | Model = panel
elif isinstance(panel, BaseTemplate):
with set_resource_mode(mode):
panel._init_doc(doc, title=title)
Expand All @@ -268,6 +272,9 @@ def save(
else:
add_to_doc(model, doc, True)

if isinstance(model, Model) and not isinstance(model, UIElement):
raise ValueError("Cannot render non-UI components.")

if as_png:
return save_png(
model, resources=resources, filename=filename, template=template,
Expand Down
2 changes: 1 addition & 1 deletion panel/io/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class _state(param.Parameterized):
_curdoc: ContextVar[Document | None] = ContextVar('curdoc', default=None)

# Whether to hold comm events
_hold: ClassVar[bool] = False
_hold: bool = False

# Used to ensure that events are not scheduled from the wrong thread
_thread_id_: ClassVar[WeakKeyDictionary[Document, int]] = WeakKeyDictionary()
Expand Down
5 changes: 3 additions & 2 deletions panel/tests/ui/pane/test_ipywidget.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import pytest
import traitlets

pytest.importorskip("ipywidgets")
pytest.importorskip("playwright")

import traitlets

from bokeh.core.has_props import _default_resolver
from bokeh.model import Model

Expand Down
13 changes: 8 additions & 5 deletions panel/theme/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class Design(param.Parameterized, ResourceComponent):
modifiers: ClassVar[dict[type[Viewable], dict[str, Any]]] = {}

# Defines the resources required to render this theme
_resources: ClassVar[dict[str, dict[str, str]]] = {}
_resources = {}

# Declares valid themes for this Design
_themes: ClassVar[dict[str, type[Theme]]] = {
Expand Down Expand Up @@ -145,8 +145,11 @@ def _apply_hooks(self, viewable: Viewable, root: Model, changed: Viewable, old_m
cache = state._stylesheets[root.document]
else:
state._stylesheets[root.document] = cache = {}
with root.document.models.freeze():
self._reapply(changed, root, old_models, isolated=False, cache=cache, document=root.document)
if root.document:
with root.document.models.freeze():
self._reapply(changed, root, old_models, isolated=False, cache=cache, document=root.document)
else:
self._reapply(changed, root, old_models, isolated=False, cache=cache)

def _wrapper(self, viewable):
return viewable
Expand Down Expand Up @@ -195,7 +198,7 @@ def _get_modifiers(
)
theme_type = type(theme) if isinstance(theme, Theme) else theme
is_server = bool(state.curdoc.session_context) if not state._is_pyodide and state.curdoc else False
modifiers, child_modifiers = cls._resolve_modifiers(type(viewable), theme_type, is_server=is_server)
modifiers, child_modifiers = cls._resolve_modifiers(type(viewable), theme_type, is_server=is_server) # type: ignore
modifiers = dict(modifiers)
if 'stylesheets' in modifiers:
if isolated:
Expand All @@ -217,7 +220,7 @@ def _get_modifiers(
return modifiers, child_modifiers

@classmethod
def _patch_modifiers(cls, doc: Document, modifiers: dict[str, Any], cache: dict[str, ImportedStyleSheet]):
def _patch_modifiers(cls, doc: Document | None, modifiers: dict[str, Any], cache: dict[str, ImportedStyleSheet]):
if 'stylesheets' in modifiers:
stylesheets = []
for sts in modifiers['stylesheets']:
Expand Down

0 comments on commit 9e602c9

Please sign in to comment.