Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d49884f

Browse files
AndreLobatormorshea
authored andcommitted
Updated hex color validator and test for invalid values #2
1 parent fd7d7c3 commit d49884f

File tree

2 files changed

+36
-32
lines changed

2 files changed

+36
-32
lines changed

lib/matplotlib/tests/test_traitlets.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,24 @@
33
from nose.tools import *
44
from unittest import TestCase
55
from matplotlib.mpl_traitlets import Color, HasTraits
6+
from IPython.utils.traitlets import TraitError
67

78
class ColorTestCase(TestCase):
89
"""Tests for the Color traits"""
910

1011
def setUp(self):
1112
self.transparent_values = [None, False, '', 'none']
12-
self.black_values = ['#000000', (0,0,0,0), 0, 0.0, (.0,.0,.0), (.0,.0,.0,.0)]
13+
self.black_values = ['#000000', '#000',(0,0,0,0), 0, 0.0, (.0,.0,.0), (.0,.0,.0,.0)]
1314
self.colored_values = ['#BE3537', (190,53,55), (0.7451, 0.20784, 0.21569)]
14-
self.invalid_values = ['áfaef', '#FFF', '#0SX#$S', (0,0,0), (0.45,0.3), (()), {}, True]
15+
self.unvalid_values = ['áfaef', '#0SX#$S', (0.45,0.3), 3.4, 344, (()), {}, True]
1516

1617
def _evaluate_unvalids(self, a):
17-
for values in self.invalid_values:
18+
for values in self.unvalid_values:
1819
try:
1920
a.color = values
20-
except:
21-
assert_raises(TypeError)
21+
assert_true(False)
22+
except TraitError:
23+
assert_raises(TraitError)
2224

2325
def test_noargs(self):
2426
class A(HasTraits):

lib/matplotlib/traitlets.py

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# Union, TraitError, HasTraits,
1414
# NoDefaultSpecified, TraitType)
1515
import numpy as np
16+
import re
1617

1718
# override for backward compatability
1819
class Configurable(Configurable): pass
@@ -84,6 +85,7 @@ class Color(TraitType):
8485
info_text = 'float, int, tuple of float or int, or a hex string color'
8586
default_value = (0.0,0.0,0.0,0.0)
8687
named_colors = {}
88+
_is_hex16 = re.compile(r'#[a-fA-F0-9]{3}(?:[a-fA-F0-9]{3})?$')
8789

8890
def _int_to_float(self, value):
8991
as_float = (np.array(value)/255).tolist()
@@ -99,18 +101,13 @@ def _int_to_hex(self, value):
99101
return as_hex
100102

101103
def _hex_to_float(self, value):
102-
# Expects #FFFFFF format
103-
split_hex = (value[1:3],value[3:5],value[5:7])
104-
as_float = (np.array([int(v,16) for v in split_hex])/255.0).tolist()
104+
if len(value) == 7:
105+
split_hex = (value[1:3],value[3:5],value[5:7])
106+
as_float = (np.array([int(v,16) for v in split_hex])/255.0).tolist()
107+
elif len(value) == 4:
108+
as_float = (np.array([int(v+v,16) for v in value[1:]])/255.0).tolist()
105109
return as_float
106110

107-
def _is_hex16(self, value):
108-
try:
109-
int(value, 16)
110-
return True
111-
except:
112-
return False
113-
114111
def _float_to_shade(self, value):
115112
grade = value*255.0
116113
return (grade,grade,grade)
@@ -121,21 +118,28 @@ def _int_to_shade(self, value):
121118

122119
def validate(self, obj, value):
123120
in_range = False
124-
if value is None or value is False or value in ['none','']:
125-
# Return transparent if no other default alpha was set
126-
return (0.0, 0.0, 0.0, 1.0)
121+
if value is True:
122+
self.error(obj, value)
127123

128-
if isinstance(value, float) and 0 <= value <= 1:
129-
value = self._float_to_shade(value)
130-
else:
131-
in_range = False
124+
elif value is None or value is False or value in ['none','']:
125+
value = (0.0, 0.0, 0.0, 1.0)
126+
in_range = True
132127

133-
if isinstance(value, int) and 0 <= value <= 255:
134-
value = self._int_to_shade(value)
135-
else:
136-
in_range = False
128+
elif isinstance(value, float):
129+
if 0 <= value <= 1:
130+
value = self._float_to_shade(value)
131+
in_range = True
132+
else:
133+
in_range = False
137134

138-
if isinstance(value, (tuple, list)) and len(value) in (3,4):
135+
elif isinstance(value, int):
136+
if 0 <= value <= 255:
137+
value = self._int_to_shade(value)
138+
in_range = True
139+
else:
140+
in_range = False
141+
142+
elif isinstance(value, (tuple, list)) and len(value) in (3,4):
139143
is_all_float = np.prod([isinstance(v, (float)) for v in value])
140144
in_range = np.prod([(0 <= v <= 1) for v in value])
141145
if is_all_float and in_range:
@@ -146,10 +150,8 @@ def validate(self, obj, value):
146150
if is_all_int and in_range:
147151
value = self._int_to_float(value)
148152

149-
if isinstance(value, str) and len(value) == 7 and value[0] == '#':
150-
is_all_hex16 = np.prod([self._is_hex16(v) for v in\
151-
(value[1:3],value[3:5],value[5:7])])
152-
if is_all_hex16:
153+
elif isinstance(value, str) and len(value) in [4,7] and value[0] == '#':
154+
if self._is_hex16.match(value):
153155
value = self._hex_to_float(value)
154156
in_range = np.prod([(0 <= v <= 1) for v in value])
155157
if in_range:
@@ -158,7 +160,7 @@ def validate(self, obj, value):
158160
elif isinstance(value, str) and value in self.named_colors:
159161
value = self.validate(obj, self.named_colors[value])
160162
in_range = True
161-
163+
162164
if in_range:
163165
if self._metadata['as_hex']:
164166
return self._float_to_hex(value)

0 commit comments

Comments
 (0)