Skip to content

Commit d8095de

Browse files
authored
Add dash length list to dash property validator #1136
Fixes #1107
1 parent d42b2ac commit d8095de

File tree

25 files changed

+211
-66
lines changed

25 files changed

+211
-66
lines changed

_plotly_utils/basevalidators.py

+76
Original file line numberDiff line numberDiff line change
@@ -1677,6 +1677,82 @@ def validate_coerce(self, v):
16771677
return v
16781678

16791679

1680+
class DashValidator(EnumeratedValidator):
1681+
"""
1682+
Special case validator for handling dash properties that may be specified
1683+
as lists of dash lengths. These are not currently specified in the
1684+
schema.
1685+
1686+
"dash": {
1687+
"valType": "string",
1688+
"values": [
1689+
"solid",
1690+
"dot",
1691+
"dash",
1692+
"longdash",
1693+
"dashdot",
1694+
"longdashdot"
1695+
],
1696+
"dflt": "solid",
1697+
"role": "style",
1698+
"editType": "style",
1699+
"description": "Sets the dash style of lines. Set to a dash type
1700+
string (*solid*, *dot*, *dash*, *longdash*, *dashdot*, or
1701+
*longdashdot*) or a dash length list in px (eg *5px,10px,2px,2px*)."
1702+
},
1703+
"""
1704+
def __init__(self,
1705+
plotly_name,
1706+
parent_name,
1707+
values,
1708+
**kwargs):
1709+
1710+
# Add regex to handle dash length lists
1711+
dash_list_regex = \
1712+
r"/^\d+(\.\d+)?(px|%)?((,|\s)\s*\d+(\.\d+)?(px|%)?)*$/"
1713+
1714+
values = values + [dash_list_regex]
1715+
1716+
# Call EnumeratedValidator superclass
1717+
super(DashValidator, self).__init__(
1718+
plotly_name=plotly_name,
1719+
parent_name=parent_name,
1720+
values=values, **kwargs)
1721+
1722+
def description(self):
1723+
1724+
# Separate regular values from regular expressions
1725+
enum_vals = []
1726+
enum_regexs = []
1727+
for v, regex in zip(self.values, self.val_regexs):
1728+
if regex is not None:
1729+
enum_regexs.append(regex.pattern)
1730+
else:
1731+
enum_vals.append(v)
1732+
desc = ("""\
1733+
The '{name}' property is an enumeration that may be specified as:"""
1734+
.format(name=self.plotly_name))
1735+
1736+
if enum_vals:
1737+
enum_vals_str = '\n'.join(
1738+
textwrap.wrap(
1739+
repr(enum_vals),
1740+
initial_indent=' ' * 12,
1741+
subsequent_indent=' ' * 12,
1742+
break_on_hyphens=False,
1743+
width=80))
1744+
1745+
desc = desc + """
1746+
- One of the following dash styles:
1747+
{enum_vals_str}""".format(enum_vals_str=enum_vals_str)
1748+
1749+
desc = desc + """
1750+
- A string containing a dash length list in pixels or percentages
1751+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
1752+
"""
1753+
return desc
1754+
1755+
16801756
class ImageUriValidator(BaseValidator):
16811757
_PIL = None
16821758

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import pytest
2+
from _plotly_utils.basevalidators import DashValidator
3+
4+
5+
# Constants
6+
# ---------
7+
dash_types = ['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
8+
9+
10+
# Fixtures
11+
# --------
12+
@pytest.fixture()
13+
def validator():
14+
return DashValidator('prop', 'parent', dash_types)
15+
16+
17+
# Acceptance
18+
# ----------
19+
@pytest.mark.parametrize('val',
20+
dash_types)
21+
def test_acceptance_dash_types(val, validator):
22+
# Values should be accepted and returned unchanged
23+
assert validator.validate_coerce(val) == val
24+
25+
26+
@pytest.mark.parametrize('val',
27+
['2', '2.2', '2.002', '1 2 002',
28+
'1,2,3', '1, 2, 3',
29+
'1px 2px 3px', '1.5px, 2px, 3.9px',
30+
'23% 18% 13px', '200% 3px'])
31+
def test_acceptance_dash_lists(val, validator):
32+
# Values should be accepted and returned unchanged
33+
assert validator.validate_coerce(val) == val
34+
35+
36+
# Rejection
37+
# ---------
38+
# ### Value Rejection ###
39+
@pytest.mark.parametrize('val', ['bogus', 'not-a-dash'])
40+
def test_rejection_by_bad_dash_type(val, validator):
41+
with pytest.raises(ValueError) as validation_failure:
42+
validator.validate_coerce(val)
43+
44+
assert 'Invalid value' in str(validation_failure.value)
45+
46+
47+
@pytest.mark.parametrize('val',
48+
['', '1,,3,4', '2 3 C', '2pxx 3 4'])
49+
def test_rejection_by_bad_dash_list(val, validator):
50+
with pytest.raises(ValueError) as validation_failure:
51+
validator.validate_coerce(val)
52+
53+
assert 'Invalid value' in str(validation_failure.value)

codegen/utils.py

+16
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,22 @@ def write_init_py(pkg_root, path_parts, import_pairs):
141141
'frame.layout': 'plotly.validators.LayoutValidator'
142142
}
143143

144+
# Add custom dash validators
145+
CUSTOM_VALIDATOR_DATATYPES.update(
146+
{prop: '_plotly_utils.basevalidators.DashValidator'
147+
for prop in [
148+
'scatter.line.dash',
149+
'histogram2dcontour.line.dash',
150+
'scattergeo.line.dash',
151+
'scatterpolar.line.dash',
152+
'ohlc.line.dash',
153+
'ohlc.decreasing.line.dash',
154+
'ohlc.increasing.line.dash',
155+
'contourcarpet.line.dash',
156+
'contour.line.dash',
157+
'scatterternary.line.dash',
158+
'scattercarpet.line.dash']})
159+
144160
# Mapping from property string (as found in plot-schema.json) to a custom
145161
# class name. If not included here, names are converted to TitleCase and
146162
# underscores are removed.

plotly/graph_objs/contour/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ def dash(self):
7474
*longdashdot*) or a dash length list in px (eg
7575
*5px,10px,2px,2px*).
7676
77-
The 'dash' property is a string and must be specified as:
78-
- One of the following strings:
79-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
80-
'longdashdot']
81-
- A number that will be converted to a string
77+
The 'dash' property is an enumeration that may be specified as:
78+
- One of the following dash styles:
79+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
80+
- A string containing a dash length list in pixels or percentages
81+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8282
8383
Returns
8484
-------

plotly/graph_objs/contourcarpet/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ def dash(self):
7474
*longdashdot*) or a dash length list in px (eg
7575
*5px,10px,2px,2px*).
7676
77-
The 'dash' property is a string and must be specified as:
78-
- One of the following strings:
79-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
80-
'longdashdot']
81-
- A number that will be converted to a string
77+
The 'dash' property is an enumeration that may be specified as:
78+
- One of the following dash styles:
79+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
80+
- A string containing a dash length list in pixels or percentages
81+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8282
8383
Returns
8484
-------

plotly/graph_objs/histogram2dcontour/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ def dash(self):
7474
*longdashdot*) or a dash length list in px (eg
7575
*5px,10px,2px,2px*).
7676
77-
The 'dash' property is a string and must be specified as:
78-
- One of the following strings:
79-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
80-
'longdashdot']
81-
- A number that will be converted to a string
77+
The 'dash' property is an enumeration that may be specified as:
78+
- One of the following dash styles:
79+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
80+
- A string containing a dash length list in pixels or percentages
81+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8282
8383
Returns
8484
-------

plotly/graph_objs/ohlc/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ def dash(self):
1616
set per direction via `increasing.line.dash` and
1717
`decreasing.line.dash`.
1818
19-
The 'dash' property is a string and must be specified as:
20-
- One of the following strings:
21-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
22-
'longdashdot']
23-
- A number that will be converted to a string
19+
The 'dash' property is an enumeration that may be specified as:
20+
- One of the following dash styles:
21+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
22+
- A string containing a dash length list in pixels or percentages
23+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
2424
2525
Returns
2626
-------

plotly/graph_objs/ohlc/decreasing/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/ohlc/increasing/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/scatter/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/scattercarpet/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/scattergeo/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/scatterpolar/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/graph_objs/scatterternary/_line.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ def dash(self):
7373
*longdashdot*) or a dash length list in px (eg
7474
*5px,10px,2px,2px*).
7575
76-
The 'dash' property is a string and must be specified as:
77-
- One of the following strings:
78-
['solid', 'dot', 'dash', 'longdash', 'dashdot',
79-
'longdashdot']
80-
- A number that will be converted to a string
76+
The 'dash' property is an enumeration that may be specified as:
77+
- One of the following dash styles:
78+
['solid', 'dot', 'dash', 'longdash', 'dashdot', 'longdashdot']
79+
- A string containing a dash length list in pixels or percentages
80+
(e.g. '5px 10px 2px 2px', '5, 10, 2, 2', '10% 20% 40%', etc.)
8181
8282
Returns
8383
-------

plotly/validators/contour/line/_dash.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _plotly_utils.basevalidators
22

33

4-
class DashValidator(_plotly_utils.basevalidators.StringValidator):
4+
class DashValidator(_plotly_utils.basevalidators.DashValidator):
55

66
def __init__(
77
self, plotly_name='dash', parent_name='contour.line', **kwargs

plotly/validators/contourcarpet/line/_dash.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _plotly_utils.basevalidators
22

33

4-
class DashValidator(_plotly_utils.basevalidators.StringValidator):
4+
class DashValidator(_plotly_utils.basevalidators.DashValidator):
55

66
def __init__(
77
self, plotly_name='dash', parent_name='contourcarpet.line', **kwargs

plotly/validators/histogram2dcontour/line/_dash.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _plotly_utils.basevalidators
22

33

4-
class DashValidator(_plotly_utils.basevalidators.StringValidator):
4+
class DashValidator(_plotly_utils.basevalidators.DashValidator):
55

66
def __init__(
77
self,

plotly/validators/ohlc/decreasing/line/_dash.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _plotly_utils.basevalidators
22

33

4-
class DashValidator(_plotly_utils.basevalidators.StringValidator):
4+
class DashValidator(_plotly_utils.basevalidators.DashValidator):
55

66
def __init__(
77
self, plotly_name='dash', parent_name='ohlc.decreasing.line', **kwargs

plotly/validators/ohlc/increasing/line/_dash.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import _plotly_utils.basevalidators
22

33

4-
class DashValidator(_plotly_utils.basevalidators.StringValidator):
4+
class DashValidator(_plotly_utils.basevalidators.DashValidator):
55

66
def __init__(
77
self, plotly_name='dash', parent_name='ohlc.increasing.line', **kwargs

0 commit comments

Comments
 (0)