##// END OF EJS Templates
add docstrings, validation to widget links
Min RK -
Show More
@@ -1,38 +1,38 b''
1 1 from .widget import Widget, DOMWidget, CallbackDispatcher, register
2 2
3 3 from .widget_bool import Checkbox, ToggleButton
4 4 from .widget_button import Button
5 5 from .widget_box import Box, FlexBox, HBox, VBox
6 6 from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider
7 7 from .widget_image import Image
8 8 from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider
9 9 from .widget_output import Output
10 10 from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
11 11 from .widget_selectioncontainer import Tab, Accordion
12 12 from .widget_string import HTML, Latex, Text, Textarea
13 13 from .interaction import interact, interactive, fixed, interact_manual
14 from .widget_link import Link, link, DirectionalLink, dlink
14 from .widget_link import Link, link, DirectionalLink, directional_link, dlink
15 15
16 16 # Deprecated classes
17 17 from .widget_bool import CheckboxWidget, ToggleButtonWidget
18 18 from .widget_button import ButtonWidget
19 19 from .widget_box import ContainerWidget
20 20 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
21 21 from .widget_image import ImageWidget
22 22 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
23 23 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
24 24 from .widget_selectioncontainer import TabWidget, AccordionWidget
25 25 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
26 26
27 27 # We use warn_explicit so we have very brief messages without file or line numbers.
28 28 # The concern is that file or line numbers will confuse the interactive user.
29 29 # To ignore this warning, do:
30 30 #
31 31 # from warnings import filterwarnings
32 32 # filterwarnings('ignore', module='IPython.html.widgets')
33 33
34 34 from warnings import warn_explicit
35 35 __warningregistry__ = {}
36 36 warn_explicit("IPython widgets are experimental and may change in the future.",
37 37 FutureWarning, '', 0, module = 'IPython.html.widgets',
38 38 registry = __warningregistry__, module_globals = globals)
@@ -1,61 +1,112 b''
1 1 """Link and DirectionalLink classes.
2 2
3 3 Propagate changes between widgets on the javascript side
4 4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2014, the IPython Development Team.
7 #
5
6 # Copyright (c) IPython Development Team.
8 7 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12 8
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
16 9 from .widget import Widget
17 from IPython.utils.traitlets import Unicode, Tuple, Any
10 from IPython.testing.skipdoctest import skip_doctest
11 from IPython.utils.traitlets import Unicode, Tuple, List,Instance, TraitError
18 12
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
13 class WidgetTraitTuple(Tuple):
14 """Traitlet for validating a single (Widget, 'trait_name') pair"""
15
16 def __init__(self, **kwargs):
17 super(WidgetTraitTuple, self).__init__(Instance(Widget), Unicode, **kwargs)
18
19 def validate_elements(self, obj, value):
20 value = super(WidgetTraitTuple, self).validate_elements(obj, value)
21 widget, trait_name = value
22 trait = widget.traits().get(trait_name)
23 trait_repr = "%s.%s" % (widget.__class__.__name__, trait_name)
24 # Can't raise TraitError because the parent will swallow the message
25 # and throw it away in a new, less informative TraitError
26 if trait is None:
27 raise TypeError("No such trait: %s" % trait_repr)
28 elif not trait.get_metadata('sync'):
29 raise TypeError("%s cannot be synced" % trait_repr)
30
31 return value
22 32
23 33
24 34 class Link(Widget):
25 """Link Widget"""
35 """Link Widget
36
37 one trait:
38 widgets, a list of (widget, 'trait_name') tuples which should be linked in the frontend.
39 """
26 40 _model_name = Unicode('LinkModel', sync=True)
27 widgets = Tuple(sync=True, allow_none=False)
41 widgets = List(WidgetTraitTuple, sync=True)
28 42
29 def __init__(self, widgets=(), **kwargs):
43 def __init__(self, widgets, **kwargs):
44 if len(widgets) < 2:
45 raise TypeError("Require at least two widgets to link")
30 46 kwargs['widgets'] = widgets
31 47 super(Link, self).__init__(**kwargs)
32 48
33 49 # for compatibility with traitlet links
34 50 def unlink(self):
35 51 self.close()
36 52
37 53
54 @skip_doctest
38 55 def link(*args):
56 """Link traits from different widgets together on the frontend so they remain in sync.
57
58 Parameters
59 ----------
60 *args : two or more (Widget, 'trait_name') tuples that should be kept in sync.
61
62 Examples
63 --------
64
65 >>> c = link((widget1, 'value'), (widget2, 'value'), (widget3, 'value'))
66 """
39 67 return Link(widgets=args)
40 68
41 69
42 70 class DirectionalLink(Widget):
43 """Directional Link Widget"""
71 """A directional link
72
73 source: a (Widget, 'trait_name') tuple for the source trait
74 targets: one or more (Widget, 'trait_name') tuples that should be updated
75 when the source trait changes.
76 """
44 77 _model_name = Unicode('DirectionalLinkModel', sync=True)
45 targets = Any(sync=True)
46 source = Tuple(sync=True)
78 targets = List(WidgetTraitTuple, sync=True)
79 source = WidgetTraitTuple(sync=True)
47 80
48 81 # Does not quite behave like other widgets but reproduces
49 82 # the behavior of IPython.utils.traitlets.directional_link
50 def __init__(self, source, targets=(), **kwargs):
83 def __init__(self, source, targets, **kwargs):
84 if len(targets) < 1:
85 raise TypeError("Require at least two widgets to link")
86
51 87 kwargs['source'] = source
52 88 kwargs['targets'] = targets
53 89 super(DirectionalLink, self).__init__(**kwargs)
54 90
55 91 # for compatibility with traitlet links
56 92 def unlink(self):
57 93 self.close()
58 94
95 @skip_doctest
96 def directional_link(source, *targets):
97 """Link the trait of a source widget with traits of target widgets in the frontend.
98
99 Parameters
100 ----------
101 source : a (Widget, 'trait_name') tuple for the source trait
102 *targets : one or more (Widget, 'trait_name') tuples that should be updated
103 when the source trait changes.
104
105 Examples
106 --------
107
108 >>> c = dlink((src_widget, 'value'), (tgt_widget1, 'value'), (tgt_widget2, 'value'))
109 """
110 return DirectionalLink(source=source, targets=targets)
59 111
60 def dlink(source, *targets):
61 return DirectionalLink(source, targets)
112 dlink = directional_link
General Comments 0
You need to be logged in to leave comments. Login now