Skip to content

Error with linestyles rcParams entries under the form (on, off, ...) and a style context manager #9792

Closed

Description

@afvincent

Bug summary

When defining an rcParams entry that is related to linestyle with an (on, off, ....) pattern, and using a style context manager somewhere in the code to temporarily apply other values of rcParams, an exception occurs.

Code for reproduction

Here is an example with the grid linestyle. (Related discussion on gitter.)

import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams["grid.linestyle"] = (4, 4)  # no error with something liked "dotted"

fig = plt.figure()

with plt.style.context(["default"]):
    ax0 = fig.add_subplot(121)
    ax0.grid()

ax1 = fig.add_subplot(122)
ax1.grid()

#fig.savefig("test.png")

Actual outcome

An exception is raised. With Matplotlib 2.1.0 and the master branch:

ValueError: Key grid.linestyle: linestyle (None, [4.0, 4.0]) is not a valid on-off ink sequence.

See at the end of the post for the full traceback.

I think this is occurs when exiting the style context manager. It looks like the linestyle given as (on, off, ...) is internally processed and stored into a form (offset, (on, off, ...)) that is actually not recognized by the line validator, which then raises an error when it is passed back to rcParams to restore the former style.

Please note that it may not even be due to the stricter linestyle validation that was introduced in Matplotlib 2.1 (#8040), as Matplotlib 2.0.2 as well as Matplotlib 1.5.3 also throw an exception, although slightly different:

ValueError: You passed in an invalid linestyle, `(4, 4)`.  See docs of Line2D.set_linestyle for valid values.

Expected outcome

No exception when exiting the style context manager, and a plot with 2 different grid linestyles, both defined through the dedicated "grid.linestyle" entry in rcParams.

Matplotlib version

  • Operating system: Linux (Fedora 26)
  • Matplotlib version: 2.1.0 from conda, master, 1.5.3 and 2.0.2 from the git repo
  • Matplotlib backend (print(matplotlib.get_backend())): Qt5Agg
  • Python version: 3.6.3 from conda

Miscellaneous

The full traceback of the exception (with Matplotlib from the master branch):

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~/FOSS/matplotlib/lib/matplotlib/rcsetup.py in _validate_linestyle(ls)
    939 
--> 940         return (None, validate_nseq_float()(ls))
    941 

~/FOSS/matplotlib/lib/matplotlib/rcsetup.py in __call__(self, s)
    308                     else val
--> 309                     for val in s]
    310         except ValueError:

~/FOSS/matplotlib/lib/matplotlib/rcsetup.py in <listcomp>(.0)
    308                     else val
--> 309                     for val in s]
    310         except ValueError:

TypeError: float() argument must be a string or a number, not 'NoneType'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
~/FOSS/matplotlib/lib/matplotlib/__init__.py in __setitem__(self, key, val)
    911             try:
--> 912                 cval = self.validate[key](val)
    913             except ValueError as ve:

~/FOSS/matplotlib/lib/matplotlib/rcsetup.py in _validate_linestyle(ls)
    945         raise ValueError("linestyle {!r} is not a valid on-off ink "
--> 946                          "sequence.".format(ls))
    947 

ValueError: linestyle (None, [4.0, 4.0]) is not a valid on-off ink sequence.

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-7-3b8f6f6ce3da> in <module>()
      8 with plt.style.context(["default"]):
      9     ax0 = fig.add_subplot(121)
---> 10     ax0.grid()
     11 
     12 ax1 = fig.add_subplot(122)

~/anaconda3/envs/matplotlib_dev/lib/python3.6/contextlib.py in __exit__(self, type, value, traceback)
     86         if type is None:
     87             try:
---> 88                 next(self.gen)
     89             except StopIteration:
     90                 return False

~/FOSS/matplotlib/lib/matplotlib/style/core.py in context(style, after_reset)
    156         yield
    157     finally:
--> 158         mpl.rcParams.update(initial_settings)
    159 
    160 

~/anaconda3/envs/matplotlib_dev/lib/python3.6/_collections_abc.py in update(*args, **kwds)
    839             if isinstance(other, Mapping):
    840                 for key in other:
--> 841                     self[key] = other[key]
    842             elif hasattr(other, "keys"):
    843                 for key in other.keys():

~/FOSS/matplotlib/lib/matplotlib/__init__.py in __setitem__(self, key, val)
    912                 cval = self.validate[key](val)
    913             except ValueError as ve:
--> 914                 raise ValueError("Key %s: %s" % (key, str(ve)))
    915             dict.__setitem__(self, key, cval)
    916         except KeyError:

ValueError: Key grid.linestyle: linestyle (None, [4.0, 4.0]) is not a valid on-off ink sequence.

Activity

  1. added this to the milestone on Nov 15, 2017
  2. self-assigned this
    on Nov 15, 2017
  3. jklymak commented on Nov 15, 2017

    @jklymak
    Member

    Any idea why these lines (

    dict.update(rcParams, orig)
    ) dict.update instead of just copy or assign?

  4. tacaswell commented on Nov 16, 2017

    @tacaswell
    Member

    rcParams is sometimes treated as a singleton so replacing it with a new dictionary may have surprising side effects. We are using dict.update here to avoid re-validating things that we know are valid.

    I suspect that the linestyle validator needs to learn to understand the (offset, [pattern]) input.

  5. afvincent commented on Nov 16, 2017

    @afvincent
    ContributorAuthor

    @tacaswell Yep, that is what I have in mind (adding the faulty input pattern to the validator).

  6. afvincent commented on Nov 16, 2017

    @afvincent
    ContributorAuthor

    With #9797, the exception is not raised anymore when running the above snippet.

  7. modified the milestones: needs sorting, v3.3.0 on Dec 15, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions