diff --git a/IPython/html/widgets/__init__.py b/IPython/html/widgets/__init__.py index 8b19449..bd8d237 100644 --- a/IPython/html/widgets/__init__.py +++ b/IPython/html/widgets/__init__.py @@ -1,5 +1,7 @@ from .widget import Widget, DOMWidget, CallbackDispatcher, register +from .trait_types import Color + from .widget_bool import Checkbox, ToggleButton from .widget_button import Button from .widget_box import Box, FlexBox, HBox, VBox diff --git a/IPython/html/widgets/tests/test_traits.py b/IPython/html/widgets/tests/test_traits.py new file mode 100644 index 0000000..c25960a --- /dev/null +++ b/IPython/html/widgets/tests/test_traits.py @@ -0,0 +1,20 @@ +"""Test trait types of the widget packages.""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +from unittest import TestCase +from IPython.utils.traitlets import HasTraits +from IPython.utils.tests.test_traitlets import TraitTestBase +from IPython.html.widgets import Color + + +class ColorTrait(HasTraits): + value = Color("black") + + +class TestColor(TraitTestBase): + obj = ColorTrait() + + _good_values = ["blue", "#AA0", "#FFFFFF"] + _bad_values = ["vanilla", "blues"] diff --git a/IPython/html/widgets/trait_types.py b/IPython/html/widgets/trait_types.py new file mode 100644 index 0000000..cef80db --- /dev/null +++ b/IPython/html/widgets/trait_types.py @@ -0,0 +1,29 @@ +# encoding: utf-8 +""" +Trait types for html widgets. +""" + +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +import re +from IPython.utils import traitlets + +#----------------------------------------------------------------------------- +# Utilities +#----------------------------------------------------------------------------- + +_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})?$') + + +class Color(traitlets._CoercedString): + """A string holding a valid HTML color such as 'blue', '#060482', '#A80'""" + + info_text = 'a valid HTML color' + + def validate(self, obj, value): + value = self._coerce_str(obj, value) + if value.lower() in _color_names or _color_re.match(value): + return value + self.error(obj, value) \ No newline at end of file diff --git a/IPython/html/widgets/widget.py b/IPython/html/widgets/widget.py index 694f592..456133d 100644 --- a/IPython/html/widgets/widget.py +++ b/IPython/html/widgets/widget.py @@ -20,8 +20,9 @@ from IPython.kernel.comm import Comm from IPython.config import LoggingConfigurable from IPython.utils.importstring import import_item from IPython.utils.traitlets import Unicode, Dict, Instance, Bool, List, \ - CaselessStrEnum, Tuple, CUnicode, Int, Set, Color + CaselessStrEnum, Tuple, CUnicode, Int, Set from IPython.utils.py3compat import string_types +from .trait_types import Color #----------------------------------------------------------------------------- # Classes diff --git a/IPython/html/widgets/widget_float.py b/IPython/html/widgets/widget_float.py index 5a0a190..afc7936 100644 --- a/IPython/html/widgets/widget_float.py +++ b/IPython/html/widgets/widget_float.py @@ -14,7 +14,8 @@ Represents an unbounded float using a widget. # Imports #----------------------------------------------------------------------------- from .widget import DOMWidget, register -from IPython.utils.traitlets import Unicode, CFloat, Bool, CaselessStrEnum, Tuple, Color +from .trait_types import Color +from IPython.utils.traitlets import Unicode, CFloat, Bool, CaselessStrEnum, Tuple from IPython.utils.warn import DeprecatedClass #----------------------------------------------------------------------------- diff --git a/IPython/html/widgets/widget_int.py b/IPython/html/widgets/widget_int.py index f1d1411..e006054 100644 --- a/IPython/html/widgets/widget_int.py +++ b/IPython/html/widgets/widget_int.py @@ -14,7 +14,8 @@ Represents an unbounded int using a widget. # Imports #----------------------------------------------------------------------------- from .widget import DOMWidget, register -from IPython.utils.traitlets import Unicode, CInt, Bool, CaselessStrEnum, Tuple, Color +from .trait_types import Color +from IPython.utils.traitlets import Unicode, CInt, Bool, CaselessStrEnum, Tuple from IPython.utils.warn import DeprecatedClass #----------------------------------------------------------------------------- diff --git a/IPython/utils/tests/test_traitlets.py b/IPython/utils/tests/test_traitlets.py index 340893e..30d82a9 100644 --- a/IPython/utils/tests/test_traitlets.py +++ b/IPython/utils/tests/test_traitlets.py @@ -17,7 +17,7 @@ from nose import SkipTest from IPython.utils.traitlets import ( HasTraits, MetaHasTraits, TraitType, Any, Bool, CBytes, Dict, Enum, - Int, Long, Integer, Float, Complex, Bytes, Unicode, Color, TraitError, + 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, @@ -918,16 +918,6 @@ class TestDottedObjectName(TraitTestBase): _good_values.append(u"t.รพ") -class ColorTrait(HasTraits): - value = Color("black") - -class TestColor(TraitTestBase): - obj = ColorTrait() - - _good_values = ["blue", "#AA0", "#FFFFFF"] - _bad_values = ["vanilla", "blues"] - - class TCPAddressTrait(HasTraits): value = TCPAddress() diff --git a/IPython/utils/traitlets.py b/IPython/utils/traitlets.py index e48e721..38a56e4 100644 --- a/IPython/utils/traitlets.py +++ b/IPython/utils/traitlets.py @@ -1331,22 +1331,6 @@ class DottedObjectName(ObjectName): self.error(obj, value) -_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})?$') - - -class Color(_CoercedString): - """A string holding a valid HTML color such as 'blue', '#060482', '#A80'""" - - info_text = 'a valid HTML color' - - def validate(self, obj, value): - value = self._coerce_str(obj, value) - if value.lower() in _color_names or _color_re.match(value): - return value - self.error(obj, value) - - class Bool(TraitType): """A boolean (True, False) trait."""