Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions _plotly_utils/basevalidators.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,24 +632,35 @@ class BooleanValidator(BaseValidator):
"description": "A boolean (true/false) value.",
"requiredOpts": [],
"otherOpts": [
"arrayOk",
"dflt"
]
},
"""

def __init__(self, plotly_name, parent_name, **kwargs):
def __init__(self, plotly_name, parent_name, array_ok=False, **kwargs):
super(BooleanValidator, self).__init__(
plotly_name=plotly_name, parent_name=parent_name, **kwargs
)
self.array_ok = array_ok

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

def validate_coerce(self, v):
if is_none_or_typed_array_spec(v):
pass
elif self.array_ok and is_simple_array(v):
invalid_els = [e for e in v if not isinstance(e, bool)]
if invalid_els:
self.raise_invalid_elements(invalid_els[:10])
v = to_scalar_or_list(v)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not 100% sure whether this call to to_scalar_or_list() is necessary, but I don't think it will hurt.

elif not isinstance(v, bool):
self.raise_invalid_val(v)

Expand Down
29 changes: 29 additions & 0 deletions tests/test_plotly_utils/validators/test_boolean_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ def validator(request):
return BooleanValidator("prop", "parent", dflt=request.param)


@pytest.fixture(params=[True, False])
def validator_aok(request):
return BooleanValidator("prop", "parent", dflt=request.param, array_ok=True)


# Array not ok (default)


# Acceptance
@pytest.mark.parametrize("val", [True, False])
def test_acceptance(val, validator):
Expand All @@ -25,3 +33,24 @@ def test_rejection(val, validator):
validator.validate_coerce(val)

assert "Invalid value" in str(validation_failure.value)


# Array ok


# Acceptance
@pytest.mark.parametrize("val", [(True, False), [True, False]])
def test_acceptance_aok(val, validator_aok):
v = validator_aok.validate_coerce(val)
assert list(val) == v


# Rejection
@pytest.mark.parametrize(
"val", [(True, "Planet Express"), ["Hubert Farnsworth", False]]
)
def test_rejection_aok(val, validator_aok):
with pytest.raises(ValueError) as validation_failure:
validator_aok.validate_coerce(val)

assert "Invalid elements" in str(validation_failure.value)