Show More
@@ -308,7 +308,7 b' class Widget(LoggingConfigurable):' | |||||
308 | their model ids. Return value must be JSON-able.""" |
|
308 | their model ids. Return value must be JSON-able.""" | |
309 | if isinstance(x, dict): |
|
309 | if isinstance(x, dict): | |
310 | return {k: self._pack_widgets(v) for k, v in x.items()} |
|
310 | return {k: self._pack_widgets(v) for k, v in x.items()} | |
311 | elif isinstance(x, list): |
|
311 | elif isinstance(x, (list, tuple)): | |
312 | return [self._pack_widgets(v) for v in x] |
|
312 | return [self._pack_widgets(v) for v in x] | |
313 | elif isinstance(x, Widget): |
|
313 | elif isinstance(x, Widget): | |
314 | return x.model_id |
|
314 | return x.model_id | |
@@ -322,7 +322,7 b' class Widget(LoggingConfigurable):' | |||||
322 | their model ids.""" |
|
322 | their model ids.""" | |
323 | if isinstance(x, dict): |
|
323 | if isinstance(x, dict): | |
324 | return {k: self._unpack_widgets(v) for k, v in x.items()} |
|
324 | return {k: self._unpack_widgets(v) for k, v in x.items()} | |
325 | elif isinstance(x, list): |
|
325 | elif isinstance(x, (list, tuple)): | |
326 | return [self._unpack_widgets(v) for v in x] |
|
326 | return [self._unpack_widgets(v) for v in x] | |
327 | elif isinstance(x, string_types): |
|
327 | elif isinstance(x, string_types): | |
328 | return x if x not in Widget.widgets else Widget.widgets[x] |
|
328 | return x if x not in Widget.widgets else Widget.widgets[x] | |
@@ -412,7 +412,7 b' class DOMWidget(Widget):' | |||||
412 | be added to. |
|
412 | be added to. | |
413 | """ |
|
413 | """ | |
414 | class_list = class_names |
|
414 | class_list = class_names | |
415 | if isinstance(class_list, list): |
|
415 | if isinstance(class_list, (list, tuple)): | |
416 | class_list = ' '.join(class_list) |
|
416 | class_list = ' '.join(class_list) | |
417 |
|
417 | |||
418 | self.send({ |
|
418 | self.send({ | |
@@ -433,7 +433,7 b' class DOMWidget(Widget):' | |||||
433 | be removed from. |
|
433 | be removed from. | |
434 | """ |
|
434 | """ | |
435 | class_list = class_names |
|
435 | class_list = class_names | |
436 | if isinstance(class_list, list): |
|
436 | if isinstance(class_list, (list, tuple)): | |
437 | class_list = ' '.join(class_list) |
|
437 | class_list = ' '.join(class_list) | |
438 |
|
438 | |||
439 | self.send({ |
|
439 | self.send({ |
@@ -14,7 +14,7 b' Represents a boolean using a widget.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget |
|
16 | from .widget import DOMWidget | |
17 |
from IPython.utils.traitlets import Unicode, Bool |
|
17 | from IPython.utils.traitlets import Unicode, Bool | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes |
@@ -14,18 +14,20 b' Represents a container that can be used to group other widgets.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget |
|
16 | from .widget import DOMWidget | |
17 |
from IPython.utils.traitlets import Unicode, |
|
17 | from IPython.utils.traitlets import Unicode, Tuple, TraitError | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes | |
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
|
22 | ||||
22 | class ContainerWidget(DOMWidget): |
|
23 | class ContainerWidget(DOMWidget): | |
23 | _view_name = Unicode('ContainerView', sync=True) |
|
24 | _view_name = Unicode('ContainerView', sync=True) | |
24 |
|
25 | |||
25 | # Keys, all private and managed by helper methods. Flexible box model |
|
26 | # Child widgets in the container. | |
26 | # classes... |
|
27 | # Using a tuple here to force reassignment to update the list. | |
27 | children = List(Instance(DOMWidget)) |
|
28 | # When a proper notifying-list trait exists, that is what should be used here. | |
28 | _children = List(Instance(DOMWidget), sync=True) |
|
29 | children = Tuple() | |
|
30 | _children = Tuple(sync=True) | |||
29 |
|
31 | |||
30 | def _children_changed(self, name, old, new): |
|
32 | def _children_changed(self, name, old, new): | |
31 | """Validate children list. |
|
33 | """Validate children list. | |
@@ -36,7 +38,7 b' class ContainerWidget(DOMWidget):' | |||||
36 | http://www.peterbe.com/plog/uniqifiers-benchmark |
|
38 | http://www.peterbe.com/plog/uniqifiers-benchmark | |
37 | which provides the inspiration for using this implementation. Below |
|
39 | which provides the inspiration for using this implementation. Below | |
38 | I've implemented the `f5` algorithm using Python comprehensions.""" |
|
40 | I've implemented the `f5` algorithm using Python comprehensions.""" | |
39 |
if new is not None |
|
41 | if new is not None: | |
40 | seen = {} |
|
42 | seen = {} | |
41 | def add_item(i): |
|
43 | def add_item(i): | |
42 | seen[i.model_id] = True |
|
44 | seen[i.model_id] = True |
@@ -14,7 +14,7 b' Represents an unbounded float using a widget.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget |
|
16 | from .widget import DOMWidget | |
17 |
from IPython.utils.traitlets import Unicode, CFloat, Bool, |
|
17 | from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes |
@@ -14,7 +14,7 b' Represents an unbounded int using a widget.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget |
|
16 | from .widget import DOMWidget | |
17 |
from IPython.utils.traitlets import Unicode, CInt, Bool, |
|
17 | from IPython.utils.traitlets import Unicode, CInt, Bool, Enum | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes |
@@ -15,7 +15,7 b' pages.' | |||||
15 | # Imports |
|
15 | # Imports | |
16 | #----------------------------------------------------------------------------- |
|
16 | #----------------------------------------------------------------------------- | |
17 | from .widget_container import ContainerWidget |
|
17 | from .widget_container import ContainerWidget | |
18 |
from IPython.utils.traitlets import Unicode, Dict, CInt |
|
18 | from IPython.utils.traitlets import Unicode, Dict, CInt | |
19 |
|
19 | |||
20 | #----------------------------------------------------------------------------- |
|
20 | #----------------------------------------------------------------------------- | |
21 | # Classes |
|
21 | # Classes |
@@ -14,7 +14,7 b' Represents a unicode string using a widget.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget, CallbackDispatcher |
|
16 | from .widget import DOMWidget, CallbackDispatcher | |
17 |
from IPython.utils.traitlets import Unicode, Bool |
|
17 | from IPython.utils.traitlets import Unicode, Bool | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes |
@@ -886,8 +886,13 b' class TestList(TraitTestBase):' | |||||
886 | obj = ListTrait() |
|
886 | obj = ListTrait() | |
887 |
|
887 | |||
888 | _default_value = [] |
|
888 | _default_value = [] | |
889 | _good_values = [[], [1], list(range(10))] |
|
889 | _good_values = [[], [1], list(range(10)), (1,2)] | |
890 |
_bad_values = [10, [1,'a'], 'a' |
|
890 | _bad_values = [10, [1,'a'], 'a'] | |
|
891 | ||||
|
892 | def coerce(self, value): | |||
|
893 | if value is not None: | |||
|
894 | value = list(value) | |||
|
895 | return value | |||
891 |
|
896 | |||
892 | class LenListTrait(HasTraits): |
|
897 | class LenListTrait(HasTraits): | |
893 |
|
898 | |||
@@ -898,8 +903,13 b' class TestLenList(TraitTestBase):' | |||||
898 | obj = LenListTrait() |
|
903 | obj = LenListTrait() | |
899 |
|
904 | |||
900 | _default_value = [0] |
|
905 | _default_value = [0] | |
901 |
_good_values = [[1], |
|
906 | _good_values = [[1], [1,2], (1,2)] | |
902 |
_bad_values = [10, [1,'a'], 'a', |
|
907 | _bad_values = [10, [1,'a'], 'a', [], list(range(3))] | |
|
908 | ||||
|
909 | def coerce(self, value): | |||
|
910 | if value is not None: | |||
|
911 | value = list(value) | |||
|
912 | return value | |||
903 |
|
913 | |||
904 | class TupleTrait(HasTraits): |
|
914 | class TupleTrait(HasTraits): | |
905 |
|
915 | |||
@@ -910,8 +920,13 b' class TestTupleTrait(TraitTestBase):' | |||||
910 | obj = TupleTrait() |
|
920 | obj = TupleTrait() | |
911 |
|
921 | |||
912 | _default_value = None |
|
922 | _default_value = None | |
913 | _good_values = [(1,), None,(0,)] |
|
923 | _good_values = [(1,), None, (0,), [1]] | |
914 |
_bad_values = [10, (1,2), |
|
924 | _bad_values = [10, (1,2), ('a'), ()] | |
|
925 | ||||
|
926 | def coerce(self, value): | |||
|
927 | if value is not None: | |||
|
928 | value = tuple(value) | |||
|
929 | return value | |||
915 |
|
930 | |||
916 | def test_invalid_args(self): |
|
931 | def test_invalid_args(self): | |
917 | self.assertRaises(TypeError, Tuple, 5) |
|
932 | self.assertRaises(TypeError, Tuple, 5) | |
@@ -927,8 +942,13 b' class TestLooseTupleTrait(TraitTestBase):' | |||||
927 | obj = LooseTupleTrait() |
|
942 | obj = LooseTupleTrait() | |
928 |
|
943 | |||
929 | _default_value = (1,2,3) |
|
944 | _default_value = (1,2,3) | |
930 | _good_values = [(1,), None, (0,), tuple(range(5)), tuple('hello'), ('a',5), ()] |
|
945 | _good_values = [(1,), None, [1], (0,), tuple(range(5)), tuple('hello'), ('a',5), ()] | |
931 |
_bad_values = [10, 'hello', |
|
946 | _bad_values = [10, 'hello', {}] | |
|
947 | ||||
|
948 | def coerce(self, value): | |||
|
949 | if value is not None: | |||
|
950 | value = tuple(value) | |||
|
951 | return value | |||
932 |
|
952 | |||
933 | def test_invalid_args(self): |
|
953 | def test_invalid_args(self): | |
934 | self.assertRaises(TypeError, Tuple, 5) |
|
954 | self.assertRaises(TypeError, Tuple, 5) |
@@ -1210,6 +1210,7 b' class Container(Instance):' | |||||
1210 | To be subclassed by overriding klass. |
|
1210 | To be subclassed by overriding klass. | |
1211 | """ |
|
1211 | """ | |
1212 | klass = None |
|
1212 | klass = None | |
|
1213 | _cast_types = () | |||
1213 | _valid_defaults = SequenceTypes |
|
1214 | _valid_defaults = SequenceTypes | |
1214 | _trait = None |
|
1215 | _trait = None | |
1215 |
|
1216 | |||
@@ -1273,6 +1274,8 b' class Container(Instance):' | |||||
1273 | raise TraitError(e) |
|
1274 | raise TraitError(e) | |
1274 |
|
1275 | |||
1275 | def validate(self, obj, value): |
|
1276 | def validate(self, obj, value): | |
|
1277 | if isinstance(value, self._cast_types): | |||
|
1278 | value = self.klass(value) | |||
1276 | value = super(Container, self).validate(obj, value) |
|
1279 | value = super(Container, self).validate(obj, value) | |
1277 | if value is None: |
|
1280 | if value is None: | |
1278 | return value |
|
1281 | return value | |
@@ -1298,6 +1301,7 b' class Container(Instance):' | |||||
1298 | class List(Container): |
|
1301 | class List(Container): | |
1299 | """An instance of a Python list.""" |
|
1302 | """An instance of a Python list.""" | |
1300 | klass = list |
|
1303 | klass = list | |
|
1304 | _cast_types = (tuple,) | |||
1301 |
|
1305 | |||
1302 | def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, |
|
1306 | def __init__(self, trait=None, default_value=None, minlen=0, maxlen=sys.maxsize, | |
1303 | allow_none=True, **metadata): |
|
1307 | allow_none=True, **metadata): | |
@@ -1354,15 +1358,27 b' class List(Container):' | |||||
1354 | self.length_error(obj, value) |
|
1358 | self.length_error(obj, value) | |
1355 |
|
1359 | |||
1356 | return super(List, self).validate_elements(obj, value) |
|
1360 | return super(List, self).validate_elements(obj, value) | |
|
1361 | ||||
|
1362 | def validate(self, obj, value): | |||
|
1363 | value = super(List, self).validate(obj, value) | |||
|
1364 | if value is None: | |||
|
1365 | return value | |||
|
1366 | ||||
|
1367 | value = self.validate_elements(obj, value) | |||
|
1368 | ||||
|
1369 | return value | |||
|
1370 | ||||
1357 |
|
1371 | |||
1358 |
|
1372 | |||
1359 |
class Set( |
|
1373 | class Set(List): | |
1360 | """An instance of a Python set.""" |
|
1374 | """An instance of a Python set.""" | |
1361 | klass = set |
|
1375 | klass = set | |
|
1376 | _cast_types = (tuple, list) | |||
1362 |
|
1377 | |||
1363 | class Tuple(Container): |
|
1378 | class Tuple(Container): | |
1364 | """An instance of a Python tuple.""" |
|
1379 | """An instance of a Python tuple.""" | |
1365 | klass = tuple |
|
1380 | klass = tuple | |
|
1381 | _cast_types = (list,) | |||
1366 |
|
1382 | |||
1367 | def __init__(self, *traits, **metadata): |
|
1383 | def __init__(self, *traits, **metadata): | |
1368 | """Tuple(*traits, default_value=None, allow_none=True, **medatata) |
|
1384 | """Tuple(*traits, default_value=None, allow_none=True, **medatata) |
General Comments 0
You need to be logged in to leave comments.
Login now