Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2948143

Browse files
scottshambaughksunden
authored andcommitted
Support and test cycler integer multiplication, concat, and slicing
1 parent 5a4d76b commit 2948143

3 files changed

Lines changed: 38 additions & 9 deletions

File tree

doc/users/next_whats_new/cycler_rcparam_security.rst

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@
22
--------------------------------------------
33

44
The ``axes.prop_cycle`` rcParam is now parsed safely without ``eval()``. Only
5-
literal ``cycler()`` calls combined with ``+`` and ``*`` are allowed. All
6-
previously valid cycler strings continue to work, for example:
5+
literal ``cycler()`` and ``concat()`` calls combined with ``+``, ``*``, and
6+
slicing are allowed. All previously valid cycler strings continue to work,
7+
for example:
78

89
.. code-block:: none
910
1011
axes.prop_cycle : cycler('color', ['r', 'g', 'b']) + cycler('linewidth', [1, 2, 3])
12+
axes.prop_cycle : 2 * cycler('color', 'rgb')
13+
axes.prop_cycle : concat(cycler('color', 'rgb'), cycler('color', 'cmk'))
14+
axes.prop_cycle : cycler('color', 'rgbcmk')[:3]

lib/matplotlib/rcsetup.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
from matplotlib._enums import JoinStyle, CapStyle
3131

3232
# Don't let the original cycler collide with our validating cycler
33-
from cycler import Cycler, cycler as ccycler
33+
from cycler import Cycler, concat as cconcat, cycler as ccycler
3434

3535

3636
@_api.caching_module_getattr
@@ -789,13 +789,32 @@ def _eval_cycler_expr(node):
789789
return left * right
790790
raise ValueError(f"Unsupported operator: {type(node.op).__name__}")
791791
if isinstance(node, ast.Call):
792-
if not (isinstance(node.func, ast.Name) and node.func.id == 'cycler'):
793-
raise ValueError("only the 'cycler()' function is allowed")
794-
args = [ast.literal_eval(a) for a in node.args]
792+
if not (isinstance(node.func, ast.Name)
793+
and node.func.id in ('cycler', 'concat')):
794+
raise ValueError(
795+
"only the 'cycler()' and 'concat()' functions are allowed")
796+
func = cycler if node.func.id == 'cycler' else cconcat
797+
args = [_eval_cycler_expr(a) for a in node.args]
795798
kwargs = {kw.arg: ast.literal_eval(kw.value) for kw in node.keywords}
796-
return cycler(*args, **kwargs)
797-
raise ValueError(
798-
f"Unsupported expression in cycler string: {ast.dump(node)}")
799+
return func(*args, **kwargs)
800+
if isinstance(node, ast.Subscript):
801+
value = _eval_cycler_expr(node.value)
802+
sl = node.slice
803+
if isinstance(sl, ast.Slice):
804+
s = slice(
805+
ast.literal_eval(sl.lower) if sl.lower else None,
806+
ast.literal_eval(sl.upper) if sl.upper else None,
807+
ast.literal_eval(sl.step) if sl.step else None,
808+
)
809+
return value[s]
810+
raise ValueError("only slicing is supported, not indexing")
811+
# Allow literal values (int, strings, lists, tuples) as arguments
812+
# to cycler() and concat().
813+
try:
814+
return ast.literal_eval(node)
815+
except (ValueError, TypeError):
816+
raise ValueError(
817+
f"Unsupported expression in cycler string: {ast.dump(node)}")
799818

800819

801820
# A validator dedicated to the named legend loc

lib/matplotlib/tests/test_rcparams.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ def generate_validator_testcases(valid):
272272
cycler('linestyle', ['-', '--'])),
273273
(cycler(mew=[2, 5]),
274274
cycler('markeredgewidth', [2, 5])),
275+
("2 * cycler('color', 'rgb')", 2 * cycler('color', 'rgb')),
276+
("cycler('color', 'rgb') * 2", cycler('color', 'rgb') * 2),
277+
("concat(cycler('color', 'rgb'), cycler('color', 'cmk'))",
278+
cycler('color', list('rgbcmk'))),
279+
("cycler('color', 'rgbcmk')[:3]", cycler('color', list('rgb'))),
280+
("cycler('color', 'rgb')[::-1]", cycler('color', list('bgr'))),
275281
),
276282
# validate_cycler() parses an arbitrary string using a safe
277283
# AST-based parser (no eval). These tests verify that only valid

0 commit comments

Comments
 (0)