From c8fae1593943a532f63b2d2544c3bdcc80b00701 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Wed, 27 Mar 2013 11:35:52 +0000 Subject: [PATCH 1/3] Added a find_all method to the RcParams dictionary. --- lib/matplotlib/__init__.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 997e86f40c93..1f8980d7bc98 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -752,6 +752,22 @@ def values(self): """ return [self[k] for k in self.iterkeys()] + def find_all(self, key_contains): + """ + Return the subset of this RcParams dictionary for which the given + ``key_contains`` string is found somewhere in the key. + + .. note:: + + Changes to the returned dictionary are *not* propagated to + the parent RcParams dictionary. + + """ + return RcParams((key, value) + for key, value in self.items() + if key_contains in key) + + def rc_params(fail_on_error=False): 'Return the default params updated from the values in the rc file' From f8d289405caedc5d0bae0c2c7bf094b845d606c7 Mon Sep 17 00:00:00 2001 From: pelson Date: Thu, 28 Mar 2013 09:06:20 +0000 Subject: [PATCH 2/3] Updated RcParams.find_all to use re. Added a str and repr for RcParams & added some tests. --- doc/users/whats_new.rst | 15 +++++++++++ lib/matplotlib/__init__.py | 25 ++++++++++++----- lib/matplotlib/tests/__init__.py | 20 ++++++++++++++ lib/matplotlib/tests/test_rcparams.py | 39 ++++++++++++++++++++++++++- 4 files changed, 92 insertions(+), 7 deletions(-) diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst index d0c3584563bf..4ab982ac4303 100644 --- a/doc/users/whats_new.rst +++ b/doc/users/whats_new.rst @@ -110,6 +110,21 @@ used, which, in the case of straight contours was sometimes quite distant from the requested location. Much more precise label positioning is now possible. +Quickly find rcParams +--------------------- +Phil Elson made it easier to search for rcParameters by passing a +valid regular expression to :func:`matplotlib.RcParams.find_all`. +:class:`matplotlib.RcParams` now also has a pretty repr and str representation +so that search results are printed prettily: + + >>> import matplotlib + >>> print(matplotlib.rcParams.find_all('\.size')) + RcParams({'font.size': 12, + 'xtick.major.size': 4, + 'xtick.minor.size': 2, + 'ytick.major.size': 4, + 'ytick.minor.size': 2}) + .. _whats-new-1-2-2: new in matplotlib 1.2.2 diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 1f8980d7bc98..ece4c79a9520 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -706,8 +706,8 @@ class RcParams(dict): :mod:`matplotlib.rcsetup` """ - validate = dict([ (key, converter) for key, (default, converter) in \ - defaultParams.iteritems() ]) + validate = dict((key, converter) for key, (default, converter) in \ + defaultParams.iteritems()) msg_depr = "%s is deprecated and replaced with %s; please use the latter." msg_depr_ignore = "%s is deprecated and ignored. Use %s" @@ -738,6 +738,17 @@ def __getitem__(self, key): key = alt return dict.__getitem__(self, key) + def __repr__(self): + import pprint + class_name = self.__class__.__name__ + indent = len(class_name) + 1 + repr_split = pprint.pformat(dict(self), indent=1, width=80 - indent).split('\n') + repr_indented = ('\n' + ' ' * indent).join(repr_split) + return '{}({})'.format(class_name, repr_indented) + + def __str__(self): + return '\n'.join('{}: {}'.format(k, v) for k, v in sorted(self.items())) + def keys(self): """ Return sorted list of keys. @@ -750,12 +761,12 @@ def values(self): """ Return values in order of sorted keys. """ - return [self[k] for k in self.iterkeys()] + return [self[k] for k in self.keys()] - def find_all(self, key_contains): + def find_all(self, pattern): """ Return the subset of this RcParams dictionary for which the given - ``key_contains`` string is found somewhere in the key. + ``pattern`` string is found, by :func:`re.search`, somewhere in the key. .. note:: @@ -763,9 +774,11 @@ def find_all(self, key_contains): the parent RcParams dictionary. """ + import re + pattern_re = re.compile(pattern) return RcParams((key, value) for key, value in self.items() - if key_contains in key) + if pattern_re.search(key)) def rc_params(fail_on_error=False): diff --git a/lib/matplotlib/tests/__init__.py b/lib/matplotlib/tests/__init__.py index bd133a4f6645..995ba452dbfa 100644 --- a/lib/matplotlib/tests/__init__.py +++ b/lib/matplotlib/tests/__init__.py @@ -1,8 +1,12 @@ from __future__ import print_function from matplotlib import rcParams, rcdefaults, use +import difflib + + _multiprocess_can_split_ = True + def setup(): use('Agg', warn=False) # use Agg backend for these tests @@ -13,3 +17,19 @@ def setup(): rcParams['font.family'] = 'Bitstream Vera Sans' rcParams['text.hinting'] = False rcParams['text.hinting_factor'] = 8 + + +def assert_str_equal(reference_str, test_str, + format_str='String {str1} and {str2} do not match:\n{differences}'): + """ + Assert the two strings are equal. If not, fail and print their diffs using difflib. + + """ + if reference_str != test_str: + diff = difflib.unified_diff(reference_str.splitlines(1), + test_str.splitlines(1), + 'Reference', 'Test result', + '', '', 0) + raise ValueError(format_str.format(str1=reference_str, + str2=test_str, + differences=''.join(diff))) diff --git a/lib/matplotlib/tests/test_rcparams.py b/lib/matplotlib/tests/test_rcparams.py index 4666c41274c5..efee5b0f94e5 100644 --- a/lib/matplotlib/tests/test_rcparams.py +++ b/lib/matplotlib/tests/test_rcparams.py @@ -1,6 +1,9 @@ import os import matplotlib as mpl +from matplotlib.tests import assert_str_equal + + mpl.rc('text', usetex=False) mpl.rc('lines', linewidth=22) @@ -34,5 +37,39 @@ def test_rcparams(): mpl.rcParams['lines.linewidth'] = linewidth +def test_RcParams_class(): + rc = mpl.RcParams({'font.cursive': ['Apple Chancery', + 'Textile', + 'Zapf Chancery', + 'cursive'], + 'font.family': 'sans-serif', + 'font.weight': 'normal', + 'font.size': 12}) + + + expected_repr = """ +RcParams({'font.cursive': ['Apple Chancery', + 'Textile', + 'Zapf Chancery', + 'cursive'], + 'font.family': 'sans-serif', + 'font.size': 12, + 'font.weight': 'normal'})""".lstrip() + + assert_str_equal(expected_repr, repr(rc)) + + expected_str = """ +font.cursive: ['Apple Chancery', 'Textile', 'Zapf Chancery', 'cursive'] +font.family: sans-serif +font.size: 12 +font.weight: normal""".lstrip() + + assert_str_equal(expected_str, str(rc)) + + # test the find_all functionality + assert ['font.cursive', 'font.size'] == sorted(rc.find_all('i[vz]').keys()) + assert ['font.family'] == rc.find_all('family').keys() + if __name__ == '__main__': - test_rcparams() + import nose + nose.runmodule(argv=['-s', '--with-doctest'], exit=False) From d16ab919a148f2f584a345c63991c3f1c0d20452 Mon Sep 17 00:00:00 2001 From: Phil Elson Date: Fri, 12 Apr 2013 17:59:46 +0100 Subject: [PATCH 3/3] Updated docstring for ``RcParams.find_all``. --- lib/matplotlib/__init__.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index ece4c79a9520..cd300bd428f9 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -742,12 +742,14 @@ def __repr__(self): import pprint class_name = self.__class__.__name__ indent = len(class_name) + 1 - repr_split = pprint.pformat(dict(self), indent=1, width=80 - indent).split('\n') + repr_split = pprint.pformat(dict(self), indent=1, + width=80 - indent).split('\n') repr_indented = ('\n' + ' ' * indent).join(repr_split) - return '{}({})'.format(class_name, repr_indented) + return '{0}({1})'.format(class_name, repr_indented) def __str__(self): - return '\n'.join('{}: {}'.format(k, v) for k, v in sorted(self.items())) + return '\n'.join('{0}: {1}'.format(k, v) + for k, v in sorted(self.items())) def keys(self): """ @@ -765,8 +767,8 @@ def values(self): def find_all(self, pattern): """ - Return the subset of this RcParams dictionary for which the given - ``pattern`` string is found, by :func:`re.search`, somewhere in the key. + Return the subset of this RcParams dictionary whose keys match, + using :func:`re.search`, the given ``pattern``. .. note::