Skip to content

Commit

Permalink
Add types for all Widget and Pane class variables
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Jun 10, 2022
1 parent 0749371 commit c24f3f9
Show file tree
Hide file tree
Showing 43 changed files with 862 additions and 438 deletions.
8 changes: 7 additions & 1 deletion panel/interact.py
Expand Up @@ -8,11 +8,14 @@
Copyright (c) Jupyter Development Team and PyViz Development Team.
Distributed under the terms of the Modified BSD License.
"""
from __future__ import annotations

import types

from collections import OrderedDict
from inspect import getcallargs
from numbers import Integral, Real
from typing import TYPE_CHECKING

try: # Python >= 3.3
from collections.abc import Iterable, Mapping
Expand Down Expand Up @@ -42,6 +45,9 @@
TextInput, Widget,
)

if TYPE_CHECKING:
from bokeh.model import Model


def _get_min_max_value(min, max, value=None, step=None):
"""Return min, max, value given input values with possible None."""
Expand Down Expand Up @@ -208,7 +214,7 @@ def update_pane(change):
watcher = widget.param.watch(update_pane, pname)
self._callbacks.append(watcher)

def _cleanup(self, root):
def _cleanup(self, root: Model | None = None) -> None:
self._inner_layout._cleanup(root)
super()._cleanup(root)

Expand Down
5 changes: 3 additions & 2 deletions panel/io/location.py
Expand Up @@ -79,7 +79,8 @@ def _get_model(
return model

def get_root(
self, doc: Optional[Document] = None, comm: Optional[Comm] = None, preprocess: bool = True
self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
preprocess: bool = True
) -> 'Model':
doc = init_doc(doc)
root = self._get_model(doc, comm=comm)
Expand All @@ -88,7 +89,7 @@ def get_root(
self._documents[doc] = root
return root

def _cleanup(self, root: Optional['Model']) -> None:
def _cleanup(self, root: Model | None = None) -> None:
if root:
if root.document in self._documents:
del self._documents[root.document]
Expand Down
3 changes: 2 additions & 1 deletion panel/io/notifications.py
Expand Up @@ -64,7 +64,8 @@ def __init__(self, **params):
self._notification_watchers = {}

def get_root(
self, doc: Optional['Document'] = None, comm: Optional['Comm'] = None, preprocess: bool = True
self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
preprocess: bool = True
) -> 'Model':
root = super().get_root(doc, comm, preprocess)
self._documents[doc] = root
Expand Down
7 changes: 5 additions & 2 deletions panel/layout/accordion.py
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import ClassVar, Mapping
from typing import TYPE_CHECKING, ClassVar, Mapping

import param

Expand All @@ -9,6 +9,9 @@
from .base import NamedListPanel
from .card import Card

if TYPE_CHECKING:
from bokeh.model import Model


class Accordion(NamedListPanel):
"""
Expand Down Expand Up @@ -126,7 +129,7 @@ def _get_objects(self, model, old_objects, doc, root, comm=None):
self._update_active()
return new_models

def _cleanup(self, root):
def _cleanup(self, root: Model | None = None) -> None:
for panel in self._panels.values():
panel._cleanup(root)
super()._cleanup(root)
Expand Down
68 changes: 36 additions & 32 deletions panel/layout/base.py
Expand Up @@ -36,19 +36,19 @@ class Panel(Reactive):
"""

# Used internally to optimize updates
_batch_update: bool = False
_batch_update: ClassVar[bool] = False

# Bokeh model used to render this Panel
_bokeh_model: Type['Model'] | None = None
_bokeh_model: ClassVar[Type[Model]]

# Properties that should sync JS -> Python
_linked_props: List[str] = []
_linked_props: ClassVar[List[str]] = []

# Parameters which require the preprocessors to be re-run
_preprocess_params: List[str] = []
_preprocess_params: ClassVar[List[str]] = []

# Parameter -> Bokeh property renaming
_rename: Dict[str, str | None] = {'objects': 'children'}
_rename: ClassVar[Mapping[str, str | None]] = {'objects': 'children'}

__abstract = True

Expand Down Expand Up @@ -77,7 +77,7 @@ def __repr__(self, depth: int = 0, max_depth: int = 10) -> str:

def _update_model(
self, events: Dict[str, param.parameterized.Event], msg: Dict[str, Any],
root: 'Model', model: 'Model', doc: 'Document', comm: Optional['Comm']
root: Model, model: Model, doc: Document, comm: Optional[Comm]
) -> None:
msg = dict(msg)
inverse = {v: k for k, v in self._rename.items() if v is not None}
Expand Down Expand Up @@ -105,8 +105,8 @@ def _update_model(
#----------------------------------------------------------------

def _get_objects(
self, model: 'Model', old_objects: List['Viewable'], doc: 'Document',
root: 'Model', comm: Optional['Comm'] = None
self, model: Model, old_objects: List[Viewable], doc: Document,
root: Model, comm: Optional[Comm] = None
):
"""
Returns new child models for the layout while reusing unchanged
Expand Down Expand Up @@ -135,9 +135,9 @@ def _get_objects(
return new_models

def _get_model(
self, doc: Document, root: Optional['Model'] = None,
parent: Optional['Model'] = None, comm: Optional[Comm] = None
) -> 'Model':
self, doc: Document, root: Optional[Model] = None,
parent: Optional[Model] = None, comm: Optional[Comm] = None
) -> Model:
if self._bokeh_model is None:
raise ValueError(f'{type(self).__name__} did not define a _bokeh_model.')
model = self._bokeh_model()
Expand Down Expand Up @@ -180,15 +180,15 @@ class ListLike(param.Parameterized):
objects = param.List(default=[], doc="""
The list of child objects that make up the layout.""")

_preprocess_params: List[str] = ['objects']
_preprocess_params: ClassVar[List[str]] = ['objects']

def __getitem__(self, index: int | slice) -> 'Viewable' | List['Viewable']:
def __getitem__(self, index: int | slice) -> Viewable | List[Viewable]:
return self.objects[index]

def __len__(self) -> int:
return len(self.objects)

def __iter__(self) -> Iterator['Viewable']:
def __iter__(self) -> Iterator[Viewable]:
for obj in self.objects:
yield obj

Expand All @@ -210,7 +210,7 @@ def __radd__(self, other: Iterable[Any]) -> 'ListLike':
other = list(other)
return self.clone(*(other+self.objects))

def __contains__(self, obj: 'Viewable') -> bool:
def __contains__(self, obj: Viewable) -> bool:
return obj in self.objects

def __setitem__(self, index: int | slice, panes: Iterable[Any]) -> None:
Expand Down Expand Up @@ -322,7 +322,7 @@ def insert(self, index: int, obj: Any) -> None:
new_objects.insert(index, panel(obj))
self.objects = new_objects

def pop(self, index: int) -> 'Viewable':
def pop(self, index: int) -> Viewable:
"""
Pops an item from the layout by index.
Expand All @@ -335,7 +335,7 @@ def pop(self, index: int) -> 'Viewable':
self.objects = new_objects
return obj

def remove(self, obj: 'Viewable') -> None:
def remove(self, obj: Viewable) -> None:
"""
Removes an object from the layout.
Expand All @@ -361,9 +361,9 @@ class NamedListLike(param.Parameterized):
objects = param.List(default=[], doc="""
The list of child objects that make up the layout.""")

_preprocess_params = ['objects']
_preprocess_params: ClassVar[List[str]] = ['objects']

def __init__(self, *items: List[Any, Tuple[str, Any]], **params: Any):
def __init__(self, *items: List[Any | Tuple[str, Any]], **params: Any):
if 'objects' in params:
if items:
raise ValueError('%s objects should be supplied either '
Expand Down Expand Up @@ -416,13 +416,13 @@ def _update_active(self, *events: param.parameterized.Event) -> None:
# Public API
#----------------------------------------------------------------

def __getitem__(self, index) -> 'Viewable' | List['Viewable']:
def __getitem__(self, index) -> Viewable | List[Viewable]:
return self.objects[index]

def __len__(self) -> int:
return len(self.objects)

def __iter__(self) -> Iterator['Viewable']:
def __iter__(self) -> Iterator[Viewable]:
for obj in self.objects:
yield obj

Expand Down Expand Up @@ -563,7 +563,7 @@ def insert(self, index: int, pane: Any) -> None:
self._names.insert(index, new_name)
self.objects = new_objects

def pop(self, index: int) -> 'Viewable':
def pop(self, index: int) -> Viewable:
"""
Pops an item from the tabs by index.
Expand All @@ -577,7 +577,7 @@ def pop(self, index: int) -> 'Viewable':
self.objects = new_objects
return obj

def remove(self, pane: 'Viewable') -> None:
def remove(self, pane: Viewable) -> None:
"""
Removes an object from the tabs.
Expand Down Expand Up @@ -616,7 +616,7 @@ class ListPanel(ListLike, Panel):
Whether to add scrollbars if the content overflows the size
of the container.""")

_source_transforms: Mapping[str, str | None] = {'scroll': None}
_source_transforms: ClassVar[Mapping[str, str | None]] = {'scroll': None}

__abstract = True

Expand All @@ -641,7 +641,7 @@ def _process_param_change(self, params: Dict[str, Any]) -> Dict[str, Any]:
params['css_classes'] = css_classes
return super()._process_param_change(params)

def _cleanup(self, root: 'Model' | None):
def _cleanup(self, root: Model | None = None) -> None:
if root is not None and root.ref['id'] in state._fake_roots:
state._fake_roots.remove(root.ref['id'])
super()._cleanup(root)
Expand All @@ -663,7 +663,7 @@ class NamedListPanel(NamedListLike, Panel):
Whether to add scrollbars if the content overflows the size
of the container.""")

_source_transforms: Dict[str, str | None] = {'scroll': None}
_source_transforms: ClassVar[Mapping[str, str | None]] = {'scroll': None}

__abstract = True

Expand All @@ -676,7 +676,7 @@ def _process_param_change(self, params: Dict[str, Any]) -> Dict[str, Any]:
params['css_classes'] = css_classes
return super()._process_param_change(params)

def _cleanup(self, root: 'Model' | None) -> None:
def _cleanup(self, root: Model | None = None) -> None:
if root is not None and root.ref['id'] in state._fake_roots:
state._fake_roots.remove(root.ref['id'])
super()._cleanup(root)
Expand All @@ -702,7 +702,7 @@ class Row(ListPanel):

col_sizing = param.Parameter()

_bokeh_model: Type['Model'] = BkRow
_bokeh_model: ClassVar[Type[Model]] = BkRow

_rename: ClassVar[Mapping[str, str | None]] = dict(ListPanel._rename, col_sizing='cols')

Expand All @@ -725,7 +725,7 @@ class Column(ListPanel):

row_sizing = param.Parameter()

_bokeh_model: Type['Model'] = BkColumn
_bokeh_model: ClassVar[Type[Model]] = BkColumn

_rename: ClassVar[Mapping[str, str | None]] = dict(ListPanel._rename, row_sizing='rows')

Expand Down Expand Up @@ -764,12 +764,16 @@ class WidgetBox(ListPanel):
be specified as a two-tuple of the form (vertical, horizontal)
or a four-tuple (top, right, bottom, left).""")

_source_transforms = {'disabled': None, 'horizontal': None}
_source_transforms: ClassVar[Mapping[str, str | None]] = {
'disabled': None, 'horizontal': None
}

_rename: ClassVar[Mapping[str, str | None]] = {'objects': 'children', 'horizontal': None}
_rename: ClassVar[Mapping[str, str | None]] = {
'objects': 'children', 'horizontal': None
}

@property
def _bokeh_model(self) -> Type['Model']: # type: ignore
def _bokeh_model(self) -> Type[Model]: # type: ignore
return BkRow if self.horizontal else BkColumn

@param.depends('disabled', 'objects', watch=True)
Expand Down
17 changes: 12 additions & 5 deletions panel/layout/card.py
@@ -1,12 +1,17 @@
from __future__ import annotations

from typing import ClassVar, Mapping
from typing import (
TYPE_CHECKING, ClassVar, List, Mapping, Type,
)

import param

from ..models import Card as BkCard
from .base import Column, ListPanel, Row

if TYPE_CHECKING:
from bokeh.model import Model


class Card(Column):
"""
Expand Down Expand Up @@ -63,11 +68,13 @@ class Card(Column):
A title to be displayed in the Card header, will be overridden
by the header if defined.""")

_bokeh_model = BkCard
_bokeh_model: ClassVar[Type[Model]] = BkCard

_linked_props = ['collapsed']
_linked_props: ClassVar[List[str]] = ['collapsed']

_rename: ClassVar[Mapping[str, str | None]] = dict(Column._rename, title=None, header=None, title_css_classes=None)
_rename: ClassVar[Mapping[str, str | None]] = dict(
Column._rename, title=None, header=None, title_css_classes=None
)

def __init__(self, *objects, **params):
self._header_layout = Row(css_classes=['card-header-row'],
Expand All @@ -77,7 +84,7 @@ def __init__(self, *objects, **params):
self.param.watch(self._update_header, ['title', 'header', 'title_css_classes'])
self._update_header()

def _cleanup(self, root):
def _cleanup(self, root: Model | None = None) -> None:
super()._cleanup(root)
self._header_layout._cleanup(root)

Expand Down

0 comments on commit c24f3f9

Please sign in to comment.