From 88816809062fed96d2f194184bf53de8268d0973 Mon Sep 17 00:00:00 2001 From: Mad Physicist Date: Thu, 24 Mar 2016 11:05:56 -0400 Subject: [PATCH] BUG: Made `setp` accept arbitrary iterables Previously only accepted sequences. Fixes #6212 Shamelessly borrows from `FIX: handle arbitrary iterables in setp #6220` --- lib/matplotlib/artist.py | 41 ++++++++++++++++------------- lib/matplotlib/tests/test_artist.py | 12 ++++++++- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/lib/matplotlib/artist.py b/lib/matplotlib/artist.py index 0ab4f6819868..1ca40c7b0586 100644 --- a/lib/matplotlib/artist.py +++ b/lib/matplotlib/artist.py @@ -1138,16 +1138,19 @@ class ArtistInspector(object): def __init__(self, o): """ Initialize the artist inspector with an - :class:`~matplotlib.artist.Artist` or sequence of :class:`Artists`. - If a sequence is used, we assume it is a homogeneous sequence (all + :class:`~matplotlib.artist.Artist` or iterable of :class:`Artists`. + If an iterable is used, we assume it is a homogeneous sequence (all :class:`Artists` are of the same type) and it is your responsibility to make sure this is so. """ - if cbook.iterable(o) and len(o): - o = o[0] + if cbook.iterable(o): + # Wrapped in list instead of doing try-except around next(iter(o)) + o = list(o) + if len(o): + o = o[0] self.oorig = o - if not isinstance(o, type): + if not inspect.isclass(o): o = type(o) self.o = o @@ -1514,8 +1517,8 @@ def setp(obj, *args, **kwargs): >>> line, = plot([1,2,3]) >>> setp(line, linestyle='--') - If you want to know the valid types of arguments, you can provide the - name of the property you want to set without a value:: + If you want to know the valid types of arguments, you can provide + the name of the property you want to set without a value:: >>> setp(line, 'linestyle') linestyle: [ '-' | '--' | '-.' | ':' | 'steps' | 'None' ] @@ -1526,12 +1529,12 @@ def setp(obj, *args, **kwargs): >>> setp(line) ... long output listing omitted - :func:`setp` operates on a single instance or a list of instances. - If you are in query mode introspecting the possible values, only - the first instance in the sequence is used. When actually setting - values, all the instances will be set. e.g., suppose you have a - list of two lines, the following will make both lines thicker and - red:: + :func:`setp` operates on a single instance or a iterable of + instances. If you are in query mode introspecting the possible + values, only the first instance in the sequence is used. When + actually setting values, all the instances will be set. e.g., + suppose you have a list of two lines, the following will make both + lines thicker and red:: >>> x = arange(0,1.0,0.01) >>> y1 = sin(2*pi*x) @@ -1546,7 +1549,12 @@ def setp(obj, *args, **kwargs): >>> setp(lines, linewidth=2, color='r') # python style """ - insp = ArtistInspector(obj) + if not cbook.iterable(obj): + objs = [obj] + else: + objs = list(cbook.flatten(obj)) + + insp = ArtistInspector(objs[0]) if len(kwargs) == 0 and len(args) == 0: print('\n'.join(insp.pprint_setters())) @@ -1556,11 +1564,6 @@ def setp(obj, *args, **kwargs): print(insp.pprint_setters(prop=args[0])) return - if not cbook.iterable(obj): - objs = [obj] - else: - objs = list(cbook.flatten(obj)) - if len(args) % 2: raise ValueError('The set args must be string, value pairs') diff --git a/lib/matplotlib/tests/test_artist.py b/lib/matplotlib/tests/test_artist.py index f4eb54ae07de..5cc46021fa56 100644 --- a/lib/matplotlib/tests/test_artist.py +++ b/lib/matplotlib/tests/test_artist.py @@ -4,7 +4,7 @@ from matplotlib.externals import six import io - +from itertools import chain import numpy as np import matplotlib.pyplot as plt @@ -13,6 +13,7 @@ import matplotlib.path as mpath import matplotlib.transforms as mtrans import matplotlib.collections as mcollections +import matplotlib.artist as martist import matplotlib as mpl from matplotlib.testing.decorators import image_comparison, cleanup @@ -208,6 +209,15 @@ def test_properties(): assert len(w) == 0 +@cleanup +def test_setp(): + fig, axes = plt.subplots() + lines1 = axes.plot(range(3)) + lines2 = axes.plot(range(3)) + martist.setp(chain(lines1, lines2), 'lw', 5) + plt.setp(axes.spines.values(), color='green') + + if __name__ == '__main__': import nose nose.runmodule(argv=['-s', '--with-doctest'], exit=False)