Skip to content

Commit 5a0440c

Browse files
authored
Merge pull request #5464 from plotly/cam/5463/handle-arrays-booleanvalidator
fix: Handle arrays in BooleanValidator
2 parents 4b902be + fff298c commit 5a0440c

File tree

2 files changed

+44
-4
lines changed

2 files changed

+44
-4
lines changed

_plotly_utils/basevalidators.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -632,24 +632,35 @@ class BooleanValidator(BaseValidator):
632632
"description": "A boolean (true/false) value.",
633633
"requiredOpts": [],
634634
"otherOpts": [
635+
"arrayOk",
635636
"dflt"
636637
]
637638
},
638639
"""
639640

640-
def __init__(self, plotly_name, parent_name, **kwargs):
641+
def __init__(self, plotly_name, parent_name, array_ok=False, **kwargs):
641642
super(BooleanValidator, self).__init__(
642643
plotly_name=plotly_name, parent_name=parent_name, **kwargs
643644
)
645+
self.array_ok = array_ok
644646

645647
def description(self):
646-
return """\
647-
The '{plotly_name}' property must be specified as a bool
648-
(either True, or False)""".format(plotly_name=self.plotly_name)
648+
desc = """\
649+
The '{plotly_name}' property is a boolean and must be specified as:
650+
- A boolean value: True or False""".format(plotly_name=self.plotly_name)
651+
if self.array_ok:
652+
desc += """
653+
- A tuple or list of the above"""
654+
return desc
649655

650656
def validate_coerce(self, v):
651657
if is_none_or_typed_array_spec(v):
652658
pass
659+
elif self.array_ok and is_simple_array(v):
660+
invalid_els = [e for e in v if not isinstance(e, bool)]
661+
if invalid_els:
662+
self.raise_invalid_elements(invalid_els[:10])
663+
v = to_scalar_or_list(v)
653664
elif not isinstance(v, bool):
654665
self.raise_invalid_val(v)
655666

tests/test_plotly_utils/validators/test_boolean_validator.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ def validator(request):
1212
return BooleanValidator("prop", "parent", dflt=request.param)
1313

1414

15+
@pytest.fixture(params=[True, False])
16+
def validator_aok(request):
17+
return BooleanValidator("prop", "parent", dflt=request.param, array_ok=True)
18+
19+
20+
# Array not ok (default)
21+
22+
1523
# Acceptance
1624
@pytest.mark.parametrize("val", [True, False])
1725
def test_acceptance(val, validator):
@@ -25,3 +33,24 @@ def test_rejection(val, validator):
2533
validator.validate_coerce(val)
2634

2735
assert "Invalid value" in str(validation_failure.value)
36+
37+
38+
# Array ok
39+
40+
41+
# Acceptance
42+
@pytest.mark.parametrize("val", [(True, False), [True, False]])
43+
def test_acceptance_aok(val, validator_aok):
44+
v = validator_aok.validate_coerce(val)
45+
assert list(val) == v
46+
47+
48+
# Rejection
49+
@pytest.mark.parametrize(
50+
"val", [(True, "Planet Express"), ["Hubert Farnsworth", False]]
51+
)
52+
def test_rejection_aok(val, validator_aok):
53+
with pytest.raises(ValueError) as validation_failure:
54+
validator_aok.validate_coerce(val)
55+
56+
assert "Invalid elements" in str(validation_failure.value)

0 commit comments

Comments
 (0)