Description
Bug summary
When creating a cycler with a "marker"
property value contains strings that could be converted to integers, they are always converted to integers, even if the string value is valid and the intended value. This is most obvious with the list ["1", "2"]
; which is distinctly different from [1, 2]
. However, the latter is always used. Edit (20.02.2025): This is also the case for "lines.markers"
, "boxplot.flierprops.marker"
, "boxplot.meanprops.marker"
, and "scatter.marker"
.
Relevant functions are _validate_markers
(here) and _listify_validator
(here). It seems like this issue was introduced by #27613, which solved a similar issue reported in #27596.
Code for reproduction
Edited 20.02.2025
from matplotlib import cycler
import matplotlib.pyplot as plt
markers = ["1", "2", "o", 4]
print("Cycler")
test_cycler = cycler("marker", markers)
for prop_dict in test_cycler:
print(
"Marker {} with type {}.".format(prop_dict["marker"], type(prop_dict["marker"]))
)
print("lines.marker")
for marker in markers:
plt.rcParams["lines.marker"] = marker
print(
"Marker {} with type {}.".format(
plt.rcParams["lines.marker"], type(plt.rcParams["lines.marker"])
)
)
Actual outcome
$ python main.py
Cycler
Marker 1 with type <class 'int'>.
Marker 2 with type <class 'int'>.
Marker o with type <class 'str'>.
Marker 4 with type <class 'int'>.
lines.marker
Marker 1 with type <class 'int'>.
Marker 2 with type <class 'int'>.
Marker o with type <class 'str'>.
Marker 4 with type <class 'int'>.
which indicates that the string entries "1"
and "2"
are converted into integers. As the string "o"
cannot be converted into an integer with int("o")
, it is used explicitly.
Expected outcome
$ python main.py
Cycler
Marker 1 with type <class 'str'>.
Marker 2 with type <class 'str'>.
Marker o with type <class 'str'>.
Marker 4 with type <class 'int'>.
lines.marker
Marker 1 with type <class 'str'>.
Marker 2 with type <class 'str'>.
Marker o with type <class 'str'>.
Marker 4 with type <class 'int'>.
This output would indicate that strings containing integers are parsed correctly.
Additional information
This bug was not present prior to #27613, but it did solve a similar bug.
Looking at the code which causes this bug, _validate_markers
(here) and _listify_validator
(here), it's not clear to me why the validation is done this way. I.e., to validate types, values are explicitly converted to see if a ValueError
is raised, instead of testing the type explicitly. Is this the intended method for validation?
I have a draft solution, but I would like clarification on the intended validation mechanisms before I submit the code for review. Edit (20.02.2025): Since finding that other RcParams entries are affected by this bug, my solution is no longer applicable.
Operating system
Fedora 41
Matplotlib Version
3.10.0
Matplotlib Backend
No response
Python version
Python 3.12.9
Jupyter version
No response
Installation
pip