diff --git a/IPython/html/widgets/__init__.py b/IPython/html/widgets/__init__.py index a91d3a0..ab5b2f8 100644 --- a/IPython/html/widgets/__init__.py +++ b/IPython/html/widgets/__init__.py @@ -1,6 +1,6 @@ from .widget import Widget, DOMWidget, CallbackDispatcher, register, widget_serialization -from .trait_types import Color +from .trait_types import Color, EventfulDict, EventfulList from .widget_bool import Checkbox, ToggleButton, Valid from .widget_button import Button diff --git a/traitlets/eventful.py b/IPython/html/widgets/eventful.py similarity index 100% rename from traitlets/eventful.py rename to IPython/html/widgets/eventful.py diff --git a/IPython/html/widgets/tests/test_traits.py b/IPython/html/widgets/tests/test_traits.py index bb74949..474743b 100644 --- a/IPython/html/widgets/tests/test_traits.py +++ b/IPython/html/widgets/tests/test_traits.py @@ -6,7 +6,7 @@ from unittest import TestCase from IPython.utils.traitlets import HasTraits from traitlets.tests.test_traitlets import TraitTestBase -from IPython.html.widgets import Color +from IPython.html.widgets import Color, EventfulDict, EventfulList class ColorTrait(HasTraits): @@ -18,3 +18,66 @@ class TestColor(TraitTestBase): _good_values = ["blue", "#AA0", "#FFFFFF"] _bad_values = ["vanilla", "blues"] + + +class TestEventful(TestCase): + + def test_list(self): + """Does the EventfulList work?""" + event_cache = [] + + class A(HasTraits): + x = EventfulList([c for c in 'abc']) + a = A() + a.x.on_events(lambda i, x: event_cache.append('insert'), \ + lambda i, x: event_cache.append('set'), \ + lambda i: event_cache.append('del'), \ + lambda: event_cache.append('reverse'), \ + lambda *p, **k: event_cache.append('sort')) + + a.x.remove('c') + # ab + a.x.insert(0, 'z') + # zab + del a.x[1] + # zb + a.x.reverse() + # bz + a.x[1] = 'o' + # bo + a.x.append('a') + # boa + a.x.sort() + # abo + + # Were the correct events captured? + self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort']) + + # Is the output correct? + self.assertEqual(a.x, [c for c in 'abo']) + + def test_dict(self): + """Does the EventfulDict work?""" + event_cache = [] + + class A(HasTraits): + x = EventfulDict({c: c for c in 'abc'}) + a = A() + a.x.on_events(lambda k, v: event_cache.append('add'), \ + lambda k, v: event_cache.append('set'), \ + lambda k: event_cache.append('del')) + + del a.x['c'] + # ab + a.x['z'] = 1 + # abz + a.x['z'] = 'z' + # abz + a.x.pop('a') + # bz + + # Were the correct events captured? + self.assertEqual(event_cache, ['del', 'add', 'set', 'del']) + + # Is the output correct? + self.assertEqual(a.x, {c: c for c in 'bz'}) diff --git a/IPython/html/widgets/trait_types.py b/IPython/html/widgets/trait_types.py index e09caaa..b6bb670 100644 --- a/IPython/html/widgets/trait_types.py +++ b/IPython/html/widgets/trait_types.py @@ -9,9 +9,7 @@ Trait types for html widgets. import re from IPython.utils import traitlets -#----------------------------------------------------------------------------- -# Utilities -#----------------------------------------------------------------------------- +from . import eventful _color_names = ['aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure', 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood', 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan', 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkkhaki', 'darkmagenta', 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue', 'darkslategray', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray', 'dodgerblue', 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia', 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'honeydew', 'hotpink', 'indianred ', 'indigo ', 'ivory', 'khaki', 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan', 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightpink', 'lightsalmon', 'lightseagreen', 'lightskyblue', 'lightslategray', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen', 'linen', 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen', 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream', 'mistyrose', 'moccasin', 'navajowhite', 'navy', 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid', 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink', 'plum', 'powderblue', 'purple', 'rebeccapurple', 'red', 'rosybrown', 'royalblue', 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue', 'slategray', 'snow', 'springgreen', 'steelblue', 'tan', 'teal', 'thistle', 'tomato', 'turquoise', 'violet', 'wheat', 'white', 'whitesmoke', 'yellow', 'yellowgreen'] _color_re = re.compile(r'#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?$') @@ -26,3 +24,47 @@ class Color(traitlets.Unicode): if value.lower() in _color_names or _color_re.match(value): return value self.error(obj, value) + + +class EventfulDict(traitlets.Instance): + """An instance of an EventfulDict.""" + + def __init__(self, default_value={}, **metadata): + """Create a EventfulDict trait type from a dict. + + The default value is created by doing + ``eventful.EvenfulDict(default_value)``, which creates a copy of the + ``default_value``. + """ + if default_value is None: + args = None + elif isinstance(default_value, dict): + args = (default_value,) + elif isinstance(default_value, SequenceTypes): + args = (default_value,) + else: + raise TypeError('default value of EventfulDict was %s' % default_value) + + super(EventfulDict, self).__init__(klass=eventful.EventfulDict, args=args, + **metadata) + + +class EventfulList(traitlets.Instance): + """An instance of an EventfulList.""" + + def __init__(self, default_value=None, **metadata): + """Create a EventfulList trait type from a dict. + + The default value is created by doing + ``eventful.EvenfulList(default_value)``, which creates a copy of the + ``default_value``. + """ + if default_value is None: + args = ((),) + else: + args = (default_value,) + + super(EventfulList, self).__init__(klass=eventful.EventfulList, args=args, + **metadata) + + diff --git a/traitlets/tests/test_traitlets.py b/traitlets/tests/test_traitlets.py index 6c9b7c5..3bab848 100644 --- a/traitlets/tests/test_traitlets.py +++ b/traitlets/tests/test_traitlets.py @@ -20,7 +20,7 @@ from IPython.utils.traitlets import ( Int, Long, Integer, Float, Complex, Bytes, Unicode, TraitError, Union, Undefined, Type, This, Instance, TCPAddress, List, Tuple, ObjectName, DottedObjectName, CRegExp, link, directional_link, - EventfulList, EventfulDict, ForwardDeclaredType, ForwardDeclaredInstance, + ForwardDeclaredType, ForwardDeclaredInstance, ) from IPython.utils import py3compat from IPython.testing.decorators import skipif @@ -1419,67 +1419,6 @@ def test_notification_order(): nt.assert_equal(obj.notified, notifications) -class TestEventful(TestCase): - - def test_list(self): - """Does the EventfulList work?""" - event_cache = [] - - class A(HasTraits): - x = EventfulList([c for c in 'abc']) - a = A() - a.x.on_events(lambda i, x: event_cache.append('insert'), \ - lambda i, x: event_cache.append('set'), \ - lambda i: event_cache.append('del'), \ - lambda: event_cache.append('reverse'), \ - lambda *p, **k: event_cache.append('sort')) - - a.x.remove('c') - # ab - a.x.insert(0, 'z') - # zab - del a.x[1] - # zb - a.x.reverse() - # bz - a.x[1] = 'o' - # bo - a.x.append('a') - # boa - a.x.sort() - # abo - - # Were the correct events captured? - self.assertEqual(event_cache, ['del', 'insert', 'del', 'reverse', 'set', 'set', 'sort']) - - # Is the output correct? - self.assertEqual(a.x, [c for c in 'abo']) - - def test_dict(self): - """Does the EventfulDict work?""" - event_cache = [] - - class A(HasTraits): - x = EventfulDict({c: c for c in 'abc'}) - a = A() - a.x.on_events(lambda k, v: event_cache.append('add'), \ - lambda k, v: event_cache.append('set'), \ - lambda k: event_cache.append('del')) - - del a.x['c'] - # ab - a.x['z'] = 1 - # abz - a.x['z'] = 'z' - # abz - a.x.pop('a') - # bz - - # Were the correct events captured? - self.assertEqual(event_cache, ['del', 'add', 'set', 'del']) - - # Is the output correct? - self.assertEqual(a.x, {c: c for c in 'bz'}) ### # Traits for Forward Declaration Tests diff --git a/traitlets/traitlets.py b/traitlets/traitlets.py index 876a4a9..2983b61 100644 --- a/traitlets/traitlets.py +++ b/traitlets/traitlets.py @@ -58,7 +58,6 @@ from IPython.utils.getargspec import getargspec from IPython.utils.importstring import import_item from IPython.utils.py3compat import iteritems, string_types -from . import eventful from .sentinel import Sentinel SequenceTypes = (list, tuple, set, frozenset) @@ -1793,48 +1792,6 @@ class Dict(Instance): super(Dict, self).instance_init() -class EventfulDict(Instance): - """An instance of an EventfulDict.""" - - def __init__(self, default_value={}, **metadata): - """Create a EventfulDict trait type from a dict. - - The default value is created by doing - ``eventful.EvenfulDict(default_value)``, which creates a copy of the - ``default_value``. - """ - if default_value is None: - args = None - elif isinstance(default_value, dict): - args = (default_value,) - elif isinstance(default_value, SequenceTypes): - args = (default_value,) - else: - raise TypeError('default value of EventfulDict was %s' % default_value) - - super(EventfulDict, self).__init__(klass=eventful.EventfulDict, args=args, - **metadata) - - -class EventfulList(Instance): - """An instance of an EventfulList.""" - - def __init__(self, default_value=None, **metadata): - """Create a EventfulList trait type from a dict. - - The default value is created by doing - ``eventful.EvenfulList(default_value)``, which creates a copy of the - ``default_value``. - """ - if default_value is None: - args = ((),) - else: - args = (default_value,) - - super(EventfulList, self).__init__(klass=eventful.EventfulList, args=args, - **metadata) - - class TCPAddress(TraitType): """A trait for an (ip, port) tuple.