Skip to content

Commit

Permalink
Add Children for Box (and subclasses) to support validation of any ty…
Browse files Browse the repository at this point in the history
…pe of iterable plus a configurable option to omit invalid items (including closed widgets) and log a warning or error.
  • Loading branch information
Alan Fleming committed May 26, 2024
1 parent 448c76d commit be31488
Showing 1 changed file with 43 additions and 9 deletions.
52 changes: 43 additions & 9 deletions python/ipywidgets/ipywidgets/widgets/widget_box.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

Expand All @@ -7,14 +8,16 @@
group other widgets together and control their
relative layouts.
"""
from __future__ import annotations

import typing

from traitlets import CaselessStrEnum, TraitError, TraitType, Unicode

from .widget import register, widget_serialization, Widget
from .docutils import doc_subst
from .domwidget import DOMWidget
from .widget import Widget, register, widget_serialization
from .widget_core import CoreWidget
from .docutils import doc_subst
from .trait_types import TypedTuple
from traitlets import Unicode, CaselessStrEnum, Instance


_doc_snippets = {}
_doc_snippets['box_params'] = """
Expand All @@ -25,8 +28,35 @@
one of 'success', 'info', 'warning' or 'danger', or ''.
Applies a predefined style to the box. Defaults to '',
which applies no pre-defined style.
validate_mode: str
one of 'raise', 'warning', error'.
How invalid children will be treated.
'raise' will raise a trait error.
'warning' and 'error' will log an error using box.log dropping
the invalid items from children.
"""

class Children(TraitType['tuple[Widget,...]', typing.Iterable[Widget]]):
default_value = ()

def validate(self, obj: Box, value: typing.Iterable[Widget]):
valid, invalid = [], []
for v in value:
if isinstance(v, Widget) and v._repr_mimebundle_:
valid.append(v)
else:
invalid.append(v)
if invalid:
msg = f'Invalid or closed items found: {invalid}'
if obj.validate_mode == 'log_warning':
obj.log.warning(msg)
elif obj.validate_mode == 'log_error':
obj.log.error(msg)
else:
raise TraitError(msg)
return tuple(valid)


@register
@doc_subst(_doc_snippets)
Expand All @@ -48,19 +78,23 @@ class Box(DOMWidget, CoreWidget):
"""
_model_name = Unicode('BoxModel').tag(sync=True)
_view_name = Unicode('BoxView').tag(sync=True)
tooltip = Unicode('', allow_none=True, help='A tooltip caption.').tag(sync=True)
validate_mode = CaselessStrEnum(['raise', 'log_warning', 'log_error'], 'raise')

# Child widgets in the container.
# Using a tuple here to force reassignment to update the list.
# When a proper notifying-list trait exists, use that instead.
children = TypedTuple(trait=Instance(Widget), help="List of widget children").tag(
sync=True, **widget_serialization)
children = Children(help='List of widget children').tag(
sync=True, **widget_serialization
)

box_style = CaselessStrEnum(
values=['success', 'info', 'warning', 'danger', ''], default_value='',
help="""Use a predefined styling for the box.""").tag(sync=True)

def __init__(self, children=(), **kwargs):
kwargs['children'] = children
if children:
kwargs['children'] = children
super().__init__(**kwargs)

@register
Expand Down

0 comments on commit be31488

Please sign in to comment.