diff --git a/_plotly_utils/basevalidators.py b/_plotly_utils/basevalidators.py index 580281f40ba..58f769bc4eb 100644 --- a/_plotly_utils/basevalidators.py +++ b/_plotly_utils/basevalidators.py @@ -938,7 +938,10 @@ def validate_coerce(self, v): elif is_simple_array(v): if not self.strict: - v = [str(e) for e in v] + # Convert all elements other than None to strings + # Leave None as is, Plotly.js will decide how to handle + # these null values. + v = [str(e) if e is not None else None for e in v] # Check no_blank if self.no_blank: diff --git a/_plotly_utils/tests/validators/test_string_validator.py b/_plotly_utils/tests/validators/test_string_validator.py index 7d7256a196c..2c21567cf3e 100644 --- a/_plotly_utils/tests/validators/test_string_validator.py +++ b/_plotly_utils/tests/validators/test_string_validator.py @@ -27,8 +27,12 @@ def validator_strict(): @pytest.fixture def validator_aok(): - return StringValidator('prop', 'parent', array_ok=True, strict=True) + return StringValidator('prop', 'parent', array_ok=True, strict=False) + +@pytest.fixture +def validator_aok_strict(): + return StringValidator('prop', 'parent', array_ok=True, strict=True) @pytest.fixture def validator_aok_values(): @@ -127,7 +131,8 @@ def test_acceptance_aok_scalars(val, validator_aok): ['foo', ['foo'], np.array(['BAR', ''], dtype='object'), - ['baz', 'baz', 'baz']]) + ['baz', 'baz', 'baz'], + ['foo', None, 'bar']]) def test_acceptance_aok_list(val, validator_aok): coerce_val = validator_aok.validate_coerce(val) if isinstance(val, np.ndarray): @@ -143,16 +148,19 @@ def test_acceptance_aok_list(val, validator_aok): # ### Rejection by type ### @pytest.mark.parametrize('val', [['foo', ()], ['foo', 3, 4], [3, 2, 1]]) -def test_rejection_aok(val, validator_aok): +def test_rejection_aok(val, validator_aok_strict): with pytest.raises(ValueError) as validation_failure: - validator_aok.validate_coerce(val) + validator_aok_strict.validate_coerce(val) assert 'Invalid element(s)' in str(validation_failure.value) # ### Rejection by value ### @pytest.mark.parametrize('val', - [['foo', 'bar'], ['3', '4'], ['BAR', 'BAR', 'hello!']]) + [['foo', 'bar'], + ['3', '4'], + ['BAR', 'BAR', 'hello!'], + ['foo', None]]) def test_rejection_aok_values(val, validator_aok_values): with pytest.raises(ValueError) as validation_failure: validator_aok_values.validate_coerce(val)