diff --git a/_plotly_utils/basevalidators.py b/_plotly_utils/basevalidators.py index e7b0d9b093f..56011b4517c 100644 --- a/_plotly_utils/basevalidators.py +++ b/_plotly_utils/basevalidators.py @@ -83,11 +83,20 @@ def copy_to_readonly_numpy_array(v, dtype=None, force_numeric=False): # u: unsigned int, i: signed int, f: float numeric_kinds = ['u', 'i', 'f'] + # Unwrap data types that have a `values` property that might be a numpy + # array. If this values property is a numeric numpy array then we + # can take the fast path below + if pd and isinstance(v, (pd.Series, pd.Index)): + v = v.values + if not isinstance(v, np.ndarray): v_list = [to_scalar_or_list(e) for e in v] new_v = np.array(v_list, order='C', dtype=dtype) elif v.dtype.kind in numeric_kinds: - new_v = np.ascontiguousarray(v.astype(dtype)) + if dtype: + new_v = np.ascontiguousarray(v.astype(dtype)) + else: + new_v = np.ascontiguousarray(v) else: new_v = v.copy() diff --git a/_plotly_utils/tests/validators/test_color_validator.py b/_plotly_utils/tests/validators/test_color_validator.py index c83947204ee..0ffb31a2f14 100644 --- a/_plotly_utils/tests/validators/test_color_validator.py +++ b/_plotly_utils/tests/validators/test_color_validator.py @@ -192,12 +192,6 @@ def test_description_aok(validator_aok): assert 'A list or array of any of the above' in desc -def test_description_aok(validator_colorscale): - desc = validator_colorscale.description() - assert 'A number that will be interpreted as a color' in desc - assert 'A list or array of any of the above' not in desc - - def test_description_aok_colorscale(validator_aok_colorscale): desc = validator_aok_colorscale.description() assert 'A number that will be interpreted as a color' in desc diff --git a/_plotly_utils/tests/validators/test_integer_validator.py b/_plotly_utils/tests/validators/test_integer_validator.py index 796622e3792..2aefff0c246 100644 --- a/_plotly_utils/tests/validators/test_integer_validator.py +++ b/_plotly_utils/tests/validators/test_integer_validator.py @@ -4,6 +4,7 @@ from pytest import approx from _plotly_utils.basevalidators import IntegerValidator import numpy as np +import pandas as pd # ### Fixtures ### @@ -121,10 +122,12 @@ def test_acceptance_aok_list(val, validator_aok): [([1, 0], (1, 0)), ((1, -1), (1, -1)), (np.array([-1, 0, 5.0], dtype='int16'), [-1, 0, 5]), - (np.array([1, 0], dtype=np.int64), [1, 0])]) + (np.array([1, 0], dtype=np.int64), [1, 0]), + (pd.Series([1, 0], dtype=np.int64), [1, 0]), + (pd.Index([1, 0], dtype=np.int64), [1, 0])]) def test_coercion_aok_list(val, expected, validator_aok): v = validator_aok.validate_coerce(val) - if isinstance(val, np.ndarray): + if isinstance(val, (np.ndarray, pd.Series, pd.Index)): assert v.dtype == np.int32 assert np.array_equal(validator_aok.present(v), np.array(expected, dtype=np.int32)) @@ -132,6 +135,7 @@ def test_coercion_aok_list(val, expected, validator_aok): assert isinstance(v, list) assert validator_aok.present(v) == expected + # ### Rejection ### # @pytest.mark.parametrize('val', diff --git a/_plotly_utils/tests/validators/test_number_validator.py b/_plotly_utils/tests/validators/test_number_validator.py index 017e92432a0..92412bf7ba3 100644 --- a/_plotly_utils/tests/validators/test_number_validator.py +++ b/_plotly_utils/tests/validators/test_number_validator.py @@ -3,7 +3,7 @@ from _plotly_utils.basevalidators import NumberValidator import numpy as np - +import pandas as pd # Fixtures # -------- @@ -118,12 +118,13 @@ def test_acceptance_aok_list(val, validator_aok): # Coerced to general consistent numeric type @pytest.mark.parametrize('val,expected', [([1.0, 0], (1.0, 0)), - (np.array([1, -1]), np.array([1.0, -1.0])), + (np.array([1, -1]), np.array([1, -1])), + (pd.Series([1, -1]), np.array([1, -1])), + (pd.Index([1, -1]), np.array([1, -1])), ((-0.1234, 0, -1), (-0.1234, 0.0, -1.0))]) def test_coercion_aok_list(val, expected, validator_aok): v = validator_aok.validate_coerce(val) - if isinstance(val, np.ndarray): - assert v.dtype == 'float' + if isinstance(val, (np.ndarray, pd.Series, pd.Index)): assert np.array_equal(v, expected) else: assert isinstance(v, list)