Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
afvincent opened this issue Nov 15, 2017 · 4 comments · Fixed by #15827
Assignees
Milestone

Comments

@afvincent
Copy link
Contributor

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.
@afvincent afvincent added this to the v2.2 milestone Nov 15, 2017
@afvincent afvincent self-assigned this Nov 15, 2017
@jklymak
Copy link
Member

jklymak commented Nov 15, 2017

Any idea why these lines (

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

@tacaswell
Copy link
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.

@afvincent
Copy link
Contributor Author

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

@afvincent
Copy link
Contributor Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants