Skip to content

Commit 7151847

Browse files
authored
Fix string validation on unicode strings on Python 2.7 (#1380)
1 parent 7df4691 commit 7151847

File tree

2 files changed

+30
-16
lines changed

2 files changed

+30
-16
lines changed

Diff for: _plotly_utils/basevalidators.py

+19-8
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,17 @@ def __init__(self,
874874
self.array_ok = array_ok
875875
self.values = values
876876

877+
@staticmethod
878+
def to_str_or_unicode_or_none(v):
879+
"""
880+
Convert a value to a string if it's not None, a string,
881+
or a unicode (on Python 2).
882+
"""
883+
if v is None or isinstance(v, string_types):
884+
return v
885+
else:
886+
return str(v)
887+
877888
def description(self):
878889
desc = ("""\
879890
The '{plotly_name}' property is a string and must be specified as:"""
@@ -938,10 +949,8 @@ def validate_coerce(self, v):
938949

939950
elif is_simple_array(v):
940951
if not self.strict:
941-
# Convert all elements other than None to strings
942-
# Leave None as is, Plotly.js will decide how to handle
943-
# these null values.
944-
v = [str(e) if e is not None else None for e in v]
952+
v = [StringValidator.to_str_or_unicode_or_none(e)
953+
for e in v]
945954

946955
# Check no_blank
947956
if self.no_blank:
@@ -962,12 +971,14 @@ def validate_coerce(self, v):
962971
if not isinstance(v, string_types):
963972
self.raise_invalid_val(v)
964973
else:
965-
if not isinstance(v, string_types + (int, float)):
974+
if isinstance(v, string_types):
975+
pass
976+
elif isinstance(v, (int, float)):
977+
# Convert value to a string
978+
v = str(v)
979+
else:
966980
self.raise_invalid_val(v)
967981

968-
# Convert value to a string
969-
v = str(v)
970-
971982
if self.no_blank and len(v) == 0:
972983
self.raise_invalid_val(v)
973984

Diff for: _plotly_utils/tests/validators/test_string_validator.py

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import pytest
2+
from six import string_types
3+
24
from _plotly_utils.basevalidators import StringValidator
35
import numpy as np
46

@@ -50,9 +52,10 @@ def validator_no_blanks_aok():
5052
# ### Acceptance ###
5153
@pytest.mark.parametrize('val',
5254
['bar', 234, np.nan,
53-
'HELLO!!!', 'world!@#$%^&*()', ''])
55+
'HELLO!!!', 'world!@#$%^&*()', '', u'\u03BC'])
5456
def test_acceptance(val, validator):
55-
assert validator.validate_coerce(val) == str(val)
57+
expected = str(val) if not isinstance(val, string_types) else val
58+
assert validator.validate_coerce(val) == expected
5659

5760

5861
# ### Rejection by value ###
@@ -85,7 +88,7 @@ def test_rejection_values(val, validator_values):
8588

8689
# ### No blanks ###
8790
@pytest.mark.parametrize('val',
88-
['bar', 'HELLO!!!', 'world!@#$%^&*()'])
91+
['bar', 'HELLO!!!', 'world!@#$%^&*()', u'\u03BC'])
8992
def test_acceptance_no_blanks(val, validator_no_blanks):
9093
assert validator_no_blanks.validate_coerce(val) == val
9194

@@ -103,7 +106,7 @@ def test_rejection_no_blanks(val, validator_no_blanks):
103106
# ------
104107
# ### Acceptance ###
105108
@pytest.mark.parametrize('val',
106-
['bar', 'HELLO!!!', 'world!@#$%^&*()', ''])
109+
['bar', 'HELLO!!!', 'world!@#$%^&*()', '', u'\u03BC'])
107110
def test_acceptance_strict(val, validator_strict):
108111
assert validator_strict.validate_coerce(val) == val
109112

@@ -122,17 +125,17 @@ def test_rejection_strict(val, validator_strict):
122125
# --------
123126
# ### Acceptance ###
124127
@pytest.mark.parametrize('val',
125-
['foo', 'BAR', '', 'baz'])
128+
['foo', 'BAR', '', 'baz', u'\u03BC'])
126129
def test_acceptance_aok_scalars(val, validator_aok):
127130
assert validator_aok.validate_coerce(val) == val
128131

129132

130133
@pytest.mark.parametrize('val',
131134
['foo',
132135
['foo'],
133-
np.array(['BAR', ''], dtype='object'),
136+
np.array(['BAR', '', u'\u03BC'], dtype='object'),
134137
['baz', 'baz', 'baz'],
135-
['foo', None, 'bar']])
138+
['foo', None, 'bar', u'\u03BC']])
136139
def test_acceptance_aok_list(val, validator_aok):
137140
coerce_val = validator_aok.validate_coerce(val)
138141
if isinstance(val, np.ndarray):
@@ -173,7 +176,7 @@ def test_rejection_aok_values(val, validator_aok_values):
173176
['123',
174177
['bar', 'HELLO!!!'],
175178
np.array(['bar', 'HELLO!!!'], dtype='object'),
176-
['world!@#$%^&*()']])
179+
['world!@#$%^&*()', u'\u03BC']])
177180
def test_acceptance_no_blanks_aok(val, validator_no_blanks_aok):
178181
coerce_val = validator_no_blanks_aok.validate_coerce(val)
179182
if isinstance(val, np.ndarray):

0 commit comments

Comments
 (0)