From 643c74b96459bb26bd1d366241197a646bafb72b Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 21 Jul 2013 01:53:58 -0500
Subject: [PATCH 01/35] Add easy style sheet selection.

---
 doc/conf.py                                   |   4 +-
 examples/style_sheets/plot_dark_background.py |  24 ++++
 examples/style_sheets/plot_ggplot.py          |  51 +++++++++
 examples/style_sheets/plot_grayscale.py       |  34 ++++++
 lib/matplotlib/style/__init__.py              |   2 +
 lib/matplotlib/style/core.py                  | 106 ++++++++++++++++++
 .../style/stylelib/dark_background.mplrc      |  23 ++++
 lib/matplotlib/style/stylelib/ggplot.mplrc    |  39 +++++++
 lib/matplotlib/style/stylelib/grayscale.mplrc |  29 +++++
 9 files changed, 311 insertions(+), 1 deletion(-)
 create mode 100644 examples/style_sheets/plot_dark_background.py
 create mode 100644 examples/style_sheets/plot_ggplot.py
 create mode 100644 examples/style_sheets/plot_grayscale.py
 create mode 100644 lib/matplotlib/style/__init__.py
 create mode 100644 lib/matplotlib/style/core.py
 create mode 100644 lib/matplotlib/style/stylelib/dark_background.mplrc
 create mode 100644 lib/matplotlib/style/stylelib/ggplot.mplrc
 create mode 100644 lib/matplotlib/style/stylelib/grayscale.mplrc

diff --git a/doc/conf.py b/doc/conf.py
index d9712743abfc..e62952541a75 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -28,7 +28,8 @@
 extensions = ['matplotlib.sphinxext.mathmpl', 'sphinxext.math_symbol_table',
               'sphinx.ext.autodoc', 'matplotlib.sphinxext.only_directives',
               'sphinx.ext.doctest', 'sphinx.ext.autosummary',
-              'matplotlib.sphinxext.plot_directive', 'sphinx.ext.inheritance_diagram',
+              'matplotlib.sphinxext.plot_directive',
+              'sphinx.ext.inheritance_diagram',
               'sphinxext.gen_gallery', 'sphinxext.gen_rst',
               'matplotlib.sphinxext.ipython_console_highlighting',
               'sphinxext.github',
@@ -117,6 +118,7 @@
     ('text_labels_and_annotations', 'Text, labels, and annotations'),
     ('ticks_and_spines', 'Ticks and spines'),
     ('subplots_axes_and_figures', 'Subplots, axes, and figures'),
+    ('style_sheets', 'Style sheets'),
     ('specialty_plots', 'Specialty plots'),
     ('showcase', 'Showcase'),
     ('api', 'API'),
diff --git a/examples/style_sheets/plot_dark_background.py b/examples/style_sheets/plot_dark_background.py
new file mode 100644
index 000000000000..acb94d4eafa9
--- /dev/null
+++ b/examples/style_sheets/plot_dark_background.py
@@ -0,0 +1,24 @@
+"""
+This example demonstrates the "dark_background" style, which uses white for
+elements that are typically black (text, borders, etc). Note, however, that not
+all plot elements default to colors defined by an rc parameter.
+
+"""
+import numpy as np
+import matplotlib.pyplot as plt
+
+from matplotlib import style
+style.use('dark_background')
+
+
+L = 6
+x = np.linspace(0, L)
+ncolors = len(plt.rcParams['axes.color_cycle'])
+shift = np.linspace(0, L, ncolors, endpoint=False)
+for s in shift:
+    plt.plot(x, np.sin(x + s), 'o-')
+plt.xlabel('x-axis')
+plt.ylabel('y-axis')
+plt.title('title')
+
+plt.show()
diff --git a/examples/style_sheets/plot_ggplot.py b/examples/style_sheets/plot_ggplot.py
new file mode 100644
index 000000000000..726ecb9ce462
--- /dev/null
+++ b/examples/style_sheets/plot_ggplot.py
@@ -0,0 +1,51 @@
+"""
+This example demonstrates the "ggplot" style, which adjusts the style to
+emulate ggplot_ (a popular plotting package for R_).
+
+These settings were shamelessly stolen from [1]_ (with permission).
+
+.. [1] http://www.huyng.com/posts/sane-color-scheme-for-matplotlib/
+
+.. _ggplot: http://had.co.nz/ggplot/
+.. _R: http://www.r-project.org/
+
+"""
+import numpy as np
+import matplotlib.pyplot as plt
+from matplotlib import style
+
+style.use('ggplot')
+
+fig, axes = plt.subplots(ncols=2, nrows=2)
+ax1, ax2, ax3, ax4 = axes.ravel()
+
+# scatter plot (Note: `plt.scatter` doesn't use default colors)
+x, y = np.random.normal(size=(2, 200))
+ax1.plot(x, y, 'o')
+
+# sinusoidal lines with colors from default color cycle
+L = 2*np.pi
+x = np.linspace(0, L)
+ncolors = len(plt.rcParams['axes.color_cycle'])
+shift = np.linspace(0, L, ncolors, endpoint=False)
+for s in shift:
+    ax2.plot(x, np.sin(x + s), '-')
+ax2.margins(0)
+
+# bar graphs
+x = np.arange(5)
+y1, y2 = np.random.randint(1, 25, size=(2, 5))
+width = 0.25
+ax3.bar(x, y1, width)
+ax3.bar(x+width, y2, width, color=plt.rcParams['axes.color_cycle'][2])
+ax3.set_xticks(x+width)
+ax3.set_xticklabels(['a', 'b', 'c', 'd', 'e'])
+
+# circles with colors from default color cycle
+for i, color in enumerate(plt.rcParams['axes.color_cycle']):
+    xy = np.random.normal(size=2)
+    ax4.add_patch(plt.Circle(xy, radius=0.3, color=color))
+ax4.axis('equal')
+ax4.margins(0)
+
+plt.show()
diff --git a/examples/style_sheets/plot_grayscale.py b/examples/style_sheets/plot_grayscale.py
new file mode 100644
index 000000000000..a6d04dc48970
--- /dev/null
+++ b/examples/style_sheets/plot_grayscale.py
@@ -0,0 +1,34 @@
+"""
+This example demonstrates the "grayscale" style sheet, which changes all colors
+that are defined as rc parameters to grayscale. Note, however, that not all
+plot elements default to colors defined by an rc parameter.
+
+"""
+import numpy as np
+import matplotlib.pyplot as plt
+
+from matplotlib import style
+
+
+def color_cycle_example(ax):
+    L = 6
+    x = np.linspace(0, L)
+    ncolors = len(plt.rcParams['axes.color_cycle'])
+    shift = np.linspace(0, L, ncolors, endpoint=False)
+    for s in shift:
+        ax.plot(x, np.sin(x + s), 'o-')
+
+def image_and_patch_example(ax):
+    ax.imshow(np.random.random(size=(20, 20)), interpolation='none')
+    c = plt.Circle((5, 5), radius=5, label='patch')
+    ax.add_patch(c)
+
+
+style.use('grayscale')
+
+fig, (ax1, ax2) = plt.subplots(ncols=2)
+
+color_cycle_example(ax1)
+image_and_patch_example(ax2)
+
+plt.show()
diff --git a/lib/matplotlib/style/__init__.py b/lib/matplotlib/style/__init__.py
new file mode 100644
index 000000000000..c98e84e2ac93
--- /dev/null
+++ b/lib/matplotlib/style/__init__.py
@@ -0,0 +1,2 @@
+from core import *
+
diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
new file mode 100644
index 000000000000..92d916777190
--- /dev/null
+++ b/lib/matplotlib/style/core.py
@@ -0,0 +1,106 @@
+"""
+Core functions and attributes for the matplotlib style library:
+
+``use``
+    Select style sheet to override the current matplotlib settings.
+``available``
+    List available style sheets.
+``library``
+    A dictionary of style names and matplotlib settings.
+"""
+import os
+import re
+
+import numpy as np
+import matplotlib.pyplot as plt
+import matplotlib as mpl
+
+
+__all__ = ['use', 'available', 'library']
+
+
+_here = os.path.abspath(os.path.dirname(__file__))
+BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
+# Users may want multiple library paths, so store a list of paths.
+USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
+STYLE_FILE_PATTERN = re.compile('([A-Za-z._-]+).mplrc$')
+
+
+def use(name):
+    """Use matplotlib rc parameters from a pre-defined name or from a file.
+
+    Parameters
+    ----------
+    name : str or list of str
+        Name of style. For list of available styles see `style.available`.
+        If given a list, each style is applied from first to last in the list.
+    """
+    if np.isscalar(name):
+        name = [name]
+    for s in name:
+        plt.rcParams.update(library[s])
+
+
+def load_base_library():
+    """Load style library defined in this package."""
+    library = dict()
+    library.update(read_style_directory(BASE_LIBRARY_PATH))
+    return library
+
+
+def iter_user_libraries():
+    for stylelib_path in USER_LIBRARY_PATHS:
+        stylelib_path = os.path.expanduser(stylelib_path)
+        if os.path.exists(stylelib_path) and os.path.isdir(stylelib_path):
+            yield stylelib_path
+
+
+def update_user_library(library):
+    """Update style library with user-defined rc files"""
+    for stylelib_path in iter_user_libraries():
+        styles = read_style_directory(stylelib_path)
+        update_nested_dict(library, styles)
+    return library
+
+
+def iter_style_files(style_dir):
+    """Yield file path and name of styles in the given directory."""
+    for path in os.listdir(style_dir):
+        filename = os.path.basename(path)
+        match = STYLE_FILE_PATTERN.match(filename)
+        if match:
+            path = os.path.abspath(os.path.join(style_dir, path))
+            yield path, match.groups()[0]
+
+
+def read_style_directory(style_dir):
+    """Return dictionary of styles defined in `style_dir`."""
+    styles = dict()
+    for path, name in iter_style_files(style_dir):
+        styles[name] = mpl.rc_params_from_file(path)
+    return styles
+
+
+def update_nested_dict(main_dict, new_dict):
+    """Update nested dict (only level of nesting) with new values.
+
+    Unlike dict.update, this assumes that the values of the parent dict are
+    dicts (or dict-like), so you shouldn't replace the nested dict if it
+    already exists. Instead you should update the sub-dict.
+    """
+    # update named styles specified by user
+    for name, rc_dict in new_dict.iteritems():
+        if name in main_dict:
+            # FIXME: This is currently broken because rc_params_from_file fills
+            # in all settings so the update overwrites all values.
+            main_dict[name].update(rc_dict)
+        else:
+            main_dict[name] = rc_dict
+    return main_dict
+
+
+# Load style library
+# ==================
+_base_library = load_base_library()
+library = update_user_library(_base_library)
+available = library.keys()
diff --git a/lib/matplotlib/style/stylelib/dark_background.mplrc b/lib/matplotlib/style/stylelib/dark_background.mplrc
new file mode 100644
index 000000000000..c3557c1f12b4
--- /dev/null
+++ b/lib/matplotlib/style/stylelib/dark_background.mplrc
@@ -0,0 +1,23 @@
+# Set black background default line colors to white.
+
+lines.color: white
+patch.edgecolor: white
+
+text.color: white
+
+axes.facecolor: black
+axes.edgecolor: white
+axes.labelcolor: white
+axes.color_cycle: 8dd3c7, feffb3, bfbbd9, fa8174, 81b1d2, fdb462, b3de69, bc82bd, ccebc4, ffed6f
+
+xtick.color: white
+ytick.color: white
+
+grid.color: white
+
+figure.facecolor: black
+figure.edgecolor: black
+
+savefig.facecolor: black
+savefig.edgecolor: black
+
diff --git a/lib/matplotlib/style/stylelib/ggplot.mplrc b/lib/matplotlib/style/stylelib/ggplot.mplrc
new file mode 100644
index 000000000000..54949aa6d7b5
--- /dev/null
+++ b/lib/matplotlib/style/stylelib/ggplot.mplrc
@@ -0,0 +1,39 @@
+# from http://www.huyng.com/posts/sane-color-scheme-for-matplotlib/
+
+patch.linewidth: 0.5
+patch.facecolor: 348ABD  # blue
+patch.edgecolor: EEEEEE
+patch.antialiased: True
+
+font.size: 10.0
+
+axes.facecolor: E5E5E5
+axes.edgecolor: white
+axes.linewidth: 1
+axes.grid: True
+axes.titlesize: x-large
+axes.labelsize: large
+axes.labelcolor: 555555
+axes.axisbelow: True       # grid/ticks are below elements (eg lines, text)
+
+axes.color_cycle: E24A33, 348ABD, 988ED5, 777777, FBC15E, 8EBA42, FFB5B8
+                   # E24A33 : red
+                   # 348ABD : blue
+                   # 988ED5 : purple
+                   # 777777 : gray
+                   # FBC15E : yellow
+                   # 8EBA42 : green
+                   # FFB5B8 : pink
+
+xtick.color: 555555
+xtick.direction: out
+
+ytick.color: 555555
+ytick.direction: out
+
+grid.color: white
+grid.linestyle: -    # solid line
+
+figure.facecolor: white
+figure.edgecolor: 0.50
+
diff --git a/lib/matplotlib/style/stylelib/grayscale.mplrc b/lib/matplotlib/style/stylelib/grayscale.mplrc
new file mode 100644
index 000000000000..2012b1b95d36
--- /dev/null
+++ b/lib/matplotlib/style/stylelib/grayscale.mplrc
@@ -0,0 +1,29 @@
+# Set all colors to grayscale
+# Note: strings of float values are interpreted by matplotlib as gray values.
+
+
+lines.color: black
+patch.facecolor: gray
+patch.edgecolor: black
+
+text.color: black
+
+axes.facecolor: white
+axes.edgecolor: black
+axes.labelcolor: black
+# black to light gray
+axes.color_cycle: 0.00, 0.40, 0.60, 0.70
+
+xtick.color: black
+ytick.color: black
+
+grid.color: black
+
+figure.facecolor: 0.75
+figure.edgecolor: white
+
+image.cmap: gray
+
+savefig.facecolor: white
+savefig.edgecolor: white
+

From 3270aa4a96eb5f28fd8d5a01e737fe4e715d5373 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 21 Jul 2013 10:47:21 -0500
Subject: [PATCH 02/35] Add rc_params_in_file to return partially-filled
 RcParams

This allows style sheets to update the current settings instead of overwriting them.
---
 lib/matplotlib/__init__.py   | 78 +++++++++++++++++++++++++-----------
 lib/matplotlib/style/core.py |  2 +-
 2 files changed, 55 insertions(+), 25 deletions(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 7207a5ae7442..26e6db8bf96e 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -878,9 +878,14 @@ def rc_params(fail_on_error=False):
     return rc_params_from_file(fname, fail_on_error)
 
 
-def rc_params_from_file(fname, fail_on_error=False):
-    """Return a :class:`matplotlib.RcParams` instance from the
-    contents of the given filename.
+_error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
+
+
+def rc_params_in_file(fname, fail_on_error=False):
+    """Return :class:`matplotlib.RcParams` from the contents of the given file.
+
+    Unlike `rc_params_from_file`, the configuration class only contains the
+    parameters specified in the file (i.e. default values are not filled in).
     """
     cnt = 0
     rc_temp = {}
@@ -891,8 +896,8 @@ def rc_params_from_file(fname, fail_on_error=False):
             if not strippedline: continue
             tup = strippedline.split(':', 1)
             if len(tup) != 2:
-                warnings.warn('Illegal line #%d\n\t%s\n\tin file "%s"' % \
-                              (cnt, line, fname))
+                error_details = _error_details_fmt % (cnt, line, fname)
+                warnings.warn('Illegal %s' % error_details)
                 continue
             key, val = tup
             key = key.strip()
@@ -902,34 +907,35 @@ def rc_params_from_file(fname, fail_on_error=False):
                               (fname, cnt))
             rc_temp[key] = (val, line, cnt)
 
-    ret = RcParams([(key, default) for key, (default, _) in \
-                    six.iteritems(defaultParams)])
+    config = RcParams()
 
     for key in ('verbose.level', 'verbose.fileo'):
         if key in rc_temp:
             val, line, cnt = rc_temp.pop(key)
             if fail_on_error:
-                ret[key] = val # try to convert to proper type or raise
+                config[key] = val # try to convert to proper type or raise
             else:
-                try: ret[key] = val # try to convert to proper type or skip
+                try:
+                    config[key] = val # try to convert to proper type or skip
                 except Exception as msg:
-                    warnings.warn('Bad val "%s" on line #%d\n\t"%s"\n\tin file \
-"%s"\n\t%s' % (val, cnt, line, fname, msg))
-
-    verbose.set_level(ret['verbose.level'])
-    verbose.set_fileo(ret['verbose.fileo'])
+                    error_details = _error_details_fmt % (cnt, line, fname)
+                    warnings.warn('Bad val "%s" on %s\n\t%s' %
+                                  (val, error_details, msg))
 
     for key, (val, line, cnt) in six.iteritems(rc_temp):
         if key in defaultParams:
             if fail_on_error:
-                ret[key] = val # try to convert to proper type or raise
+                config[key] = val # try to convert to proper type or raise
             else:
-                try: ret[key] = val # try to convert to proper type or skip
+                try:
+                    config[key] = val # try to convert to proper type or skip
                 except Exception as msg:
-                    warnings.warn('Bad val "%s" on line #%d\n\t"%s"\n\tin file \
-"%s"\n\t%s' % (val, cnt, line, fname, msg))
+                    error_details = _error_details_fmt % (cnt, line, fname)
+                    warnings.warn('Bad val "%s" on %s\n\t%s' %
+                                  (val, error_details, msg))
         elif key in _deprecated_ignore_map:
-            warnings.warn('%s is deprecated. Update your matplotlibrc to use %s instead.'% (key, _deprecated_ignore_map[key]))
+            warnings.warn('%s is deprecated. Update your matplotlibrc to use '
+                          '%s instead.'% (key, _deprecated_ignore_map[key]))
 
         else:
             print("""
@@ -939,21 +945,45 @@ def rc_params_from_file(fname, fail_on_error=False):
 http://matplotlib.sf.net/_static/matplotlibrc or from the matplotlib source
 distribution""" % (key, cnt, fname), file=sys.stderr)
 
-    if ret['datapath'] is None:
-        ret['datapath'] = get_data_path()
+    return config
+
+
+
+
+def rc_params_from_file(fname, fail_on_error=False):
+    """Return :class:`matplotlib.RcParams` from the contents of the given file.
+
+    Parameters
+    ----------
+    fname : str
+        Name of file parsed for matplotlib settings.
+    fail_on_error : bool
+        If True, raise an error when the parser fails to convert a parameter.
+    """
+
+    config = RcParams([(key, default)
+                       for key, (default, _) in six.iteritems(defaultParams)])
+
+    config.update(rc_params_in_file(fname, fail_on_error))
+
+    verbose.set_level(config['verbose.level'])
+    verbose.set_fileo(config['verbose.fileo'])
+
+    if config['datapath'] is None:
+        config['datapath'] = get_data_path()
 
-    if not ret['text.latex.preamble'] == ['']:
+    if not config['text.latex.preamble'] == ['']:
         verbose.report("""
 *****************************************************************
 You have the following UNSUPPORTED LaTeX preamble customizations:
 %s
 Please do not ask for support with these customizations active.
 *****************************************************************
-"""% '\n'.join(ret['text.latex.preamble']), 'helpful')
+"""% '\n'.join(config['text.latex.preamble']), 'helpful')
 
     verbose.report('loaded rc file %s'%fname)
 
-    return ret
+    return config
 
 
 # this is the instance used by the matplotlib classes
diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 92d916777190..fc6220f372a7 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -77,7 +77,7 @@ def read_style_directory(style_dir):
     """Return dictionary of styles defined in `style_dir`."""
     styles = dict()
     for path, name in iter_style_files(style_dir):
-        styles[name] = mpl.rc_params_from_file(path)
+        styles[name] = mpl.rc_params_in_file(path)
     return styles
 
 

From d83a03ce6ca93a151259864fed991363c71a8203 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 21 Jul 2013 10:53:16 -0500
Subject: [PATCH 03/35] Rename style files to `*.style`

---
 lib/matplotlib/style/core.py                                    | 2 +-
 .../stylelib/{dark_background.mplrc => dark_background.style}   | 0
 lib/matplotlib/style/stylelib/{ggplot.mplrc => ggplot.style}    | 0
 .../style/stylelib/{grayscale.mplrc => grayscale.style}         | 0
 4 files changed, 1 insertion(+), 1 deletion(-)
 rename lib/matplotlib/style/stylelib/{dark_background.mplrc => dark_background.style} (100%)
 rename lib/matplotlib/style/stylelib/{ggplot.mplrc => ggplot.style} (100%)
 rename lib/matplotlib/style/stylelib/{grayscale.mplrc => grayscale.style} (100%)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index fc6220f372a7..1a5b28615e73 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -23,7 +23,7 @@
 BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
 # Users may want multiple library paths, so store a list of paths.
 USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
-STYLE_FILE_PATTERN = re.compile('([A-Za-z._-]+).mplrc$')
+STYLE_FILE_PATTERN = re.compile('([A-Za-z._-]+).style$')
 
 
 def use(name):
diff --git a/lib/matplotlib/style/stylelib/dark_background.mplrc b/lib/matplotlib/style/stylelib/dark_background.style
similarity index 100%
rename from lib/matplotlib/style/stylelib/dark_background.mplrc
rename to lib/matplotlib/style/stylelib/dark_background.style
diff --git a/lib/matplotlib/style/stylelib/ggplot.mplrc b/lib/matplotlib/style/stylelib/ggplot.style
similarity index 100%
rename from lib/matplotlib/style/stylelib/ggplot.mplrc
rename to lib/matplotlib/style/stylelib/ggplot.style
diff --git a/lib/matplotlib/style/stylelib/grayscale.mplrc b/lib/matplotlib/style/stylelib/grayscale.style
similarity index 100%
rename from lib/matplotlib/style/stylelib/grayscale.mplrc
rename to lib/matplotlib/style/stylelib/grayscale.style

From c8cc486d6fcc5020c17c46cd25bd8162f0ace0b5 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 21 Jul 2013 15:03:25 -0500
Subject: [PATCH 04/35] Allow style.use to open URLs

---
 lib/matplotlib/__init__.py   | 37 ++++++++++++++++++++++++++++++------
 lib/matplotlib/style/core.py | 31 +++++++++++++++++++++---------
 2 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 26e6db8bf96e..9bb6b03d51e7 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -155,7 +155,16 @@ def _forward_ilshift(self, other):
             return self
         pyparsing.Forward.__ilshift__ = _forward_ilshift
 
-import os, re, shutil, warnings
+try:
+    from urllib.request import urlopen
+except ImportError:
+    from urllib2 import urlopen
+
+import os
+import re
+import tempfile
+import warnings
+import contextlib
 import distutils.sysconfig
 
 # cbook must import matplotlib only within function
@@ -174,11 +183,8 @@ def _forward_ilshift(self, other):
     sys.argv = ['modpython']
 
 
-import sys, os, tempfile
-
 from matplotlib.rcsetup import (defaultParams,
-                                validate_backend,
-                                validate_toolbar)
+                                validate_backend)
 
 major, minor1, minor2, s, tmp = sys.version_info
 _python24 = (major == 2 and minor1 >= 4) or major >= 3
@@ -878,6 +884,25 @@ def rc_params(fail_on_error=False):
     return rc_params_from_file(fname, fail_on_error)
 
 
+URL_REGEX = re.compile(r'http://|https://|ftp://|file://|file:\\')
+
+
+def is_url(filename):
+    """Return True if string is an http or ftp path."""
+    return URL_REGEX.match(filename) is not None
+
+
+@contextlib.contextmanager
+def _open_file_or_url(fname):
+    if is_url(fname):
+        f = urlopen(fname)
+        yield f
+        f.close()
+    else:
+        with open(fname) as f:
+            yield f
+
+
 _error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
 
 
@@ -889,7 +914,7 @@ def rc_params_in_file(fname, fail_on_error=False):
     """
     cnt = 0
     rc_temp = {}
-    with open(fname) as fd:
+    with _open_file_or_url(fname) as fd:
         for line in fd:
             cnt += 1
             strippedline = line.split('#', 1)[0].strip()
diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 1a5b28615e73..375b88c2aa98 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -23,7 +23,12 @@
 BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
 # Users may want multiple library paths, so store a list of paths.
 USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
-STYLE_FILE_PATTERN = re.compile('([A-Za-z._-]+).style$')
+STYLE_FILE_PATTERN = re.compile('([\S]+).style$')
+
+
+def is_style_file(filename):
+    """Return True if the filename looks like a style file."""
+    return STYLE_FILE_PATTERN.match(filename) is not None
 
 
 def use(name):
@@ -32,13 +37,23 @@ def use(name):
     Parameters
     ----------
     name : str or list of str
-        Name of style. For list of available styles see `style.available`.
-        If given a list, each style is applied from first to last in the list.
+        Name of style or path/URL to a style file. For a list of available
+        style names, see `style.available`. If given a list, each style is
+        applied from first to last in the list.
     """
     if np.isscalar(name):
         name = [name]
-    for s in name:
-        plt.rcParams.update(library[s])
+
+    for style in name:
+        if is_style_file(style):
+            settings = mpl.rc_params_in_file(style)
+            plt.rcParams.update(settings)
+        elif style not in library:
+            msg = ("'%s' not found in the style library. "
+                   "See `style.available` for list of available styles.")
+            raise ValueError(msg % style)
+        else:
+            plt.rcParams.update(library[style])
 
 
 def load_base_library():
@@ -67,8 +82,8 @@ def iter_style_files(style_dir):
     """Yield file path and name of styles in the given directory."""
     for path in os.listdir(style_dir):
         filename = os.path.basename(path)
-        match = STYLE_FILE_PATTERN.match(filename)
-        if match:
+        if is_style_file(filename):
+            match = STYLE_FILE_PATTERN.match(filename)
             path = os.path.abspath(os.path.join(style_dir, path))
             yield path, match.groups()[0]
 
@@ -91,8 +106,6 @@ def update_nested_dict(main_dict, new_dict):
     # update named styles specified by user
     for name, rc_dict in new_dict.iteritems():
         if name in main_dict:
-            # FIXME: This is currently broken because rc_params_from_file fills
-            # in all settings so the update overwrites all values.
             main_dict[name].update(rc_dict)
         else:
             main_dict[name] = rc_dict

From 455b54ca9cbe28ffbda3a8effc80d27121d8dcd7 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 21 Jul 2013 16:10:14 -0500
Subject: [PATCH 05/35] Remove pyplot import

---
 lib/matplotlib/style/core.py | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 375b88c2aa98..c50dcdb1be44 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -12,7 +12,6 @@
 import re
 
 import numpy as np
-import matplotlib.pyplot as plt
 import matplotlib as mpl
 
 
@@ -47,13 +46,13 @@ def use(name):
     for style in name:
         if is_style_file(style):
             settings = mpl.rc_params_in_file(style)
-            plt.rcParams.update(settings)
+            mpl.rcParams.update(settings)
         elif style not in library:
             msg = ("'%s' not found in the style library. "
                    "See `style.available` for list of available styles.")
             raise ValueError(msg % style)
         else:
-            plt.rcParams.update(library[style])
+            mpl.rcParams.update(library[style])
 
 
 def load_base_library():

From 7769b2940768ee81ca2ed031f51ef6b3ed61e3e8 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Mon, 22 Jul 2013 23:16:55 -0500
Subject: [PATCH 06/35] Add style context manager and tests

---
 lib/matplotlib/style/core.py            | 44 ++++++++++++++++--
 lib/matplotlib/style/tests/test_core.py | 61 +++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 5 deletions(-)
 create mode 100644 lib/matplotlib/style/tests/test_core.py

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index c50dcdb1be44..689305c022cb 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -3,6 +3,8 @@
 
 ``use``
     Select style sheet to override the current matplotlib settings.
+``context``
+    Context manager to use a style sheet temporarily.
 ``available``
     List available style sheets.
 ``library``
@@ -10,19 +12,21 @@
 """
 import os
 import re
+import contextlib
 
 import numpy as np
 import matplotlib as mpl
 
 
-__all__ = ['use', 'available', 'library']
+__all__ = ['use', 'context', 'available', 'library', 'reload_library']
 
 
 _here = os.path.abspath(os.path.dirname(__file__))
 BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
 # Users may want multiple library paths, so store a list of paths.
 USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
-STYLE_FILE_PATTERN = re.compile('([\S]+).style$')
+STYLE_EXTENSION = 'style'
+STYLE_FILE_PATTERN = re.compile('([\S]+).%s$' % STYLE_EXTENSION)
 
 
 def is_style_file(filename):
@@ -31,7 +35,7 @@ def is_style_file(filename):
 
 
 def use(name):
-    """Use matplotlib rc parameters from a pre-defined name or from a file.
+    """Use matplotlib style settings from a known style sheet or from a file.
 
     Parameters
     ----------
@@ -55,6 +59,28 @@ def use(name):
             mpl.rcParams.update(library[style])
 
 
+@contextlib.contextmanager
+def context(name, after_reset=False):
+    """Context manager for using style settings temporarily.
+
+    Parameters
+    ----------
+    name : str or list of str
+        Name of style or path/URL to a style file. For a list of available
+        style names, see `style.available`. If given a list, each style is
+        applied from first to last in the list.
+    after_reset : bool
+        If True, apply style after resetting settings to their defaults;
+        otherwise, apply style on top of the current settings.
+    """
+    initial_settings = mpl.rcParams.copy()
+    if after_reset:
+        mpl.rcdefaults()
+    use(name)
+    yield
+    mpl.rcParams.update(initial_settings)
+
+
 def load_base_library():
     """Load style library defined in this package."""
     library = dict()
@@ -114,5 +140,13 @@ def update_nested_dict(main_dict, new_dict):
 # Load style library
 # ==================
 _base_library = load_base_library()
-library = update_user_library(_base_library)
-available = library.keys()
+
+library = None
+available = []
+
+def reload_library():
+    """Reload style library."""
+    global library, available
+    library = update_user_library(_base_library)
+    available[:] = library.keys()
+reload_library()
diff --git a/lib/matplotlib/style/tests/test_core.py b/lib/matplotlib/style/tests/test_core.py
new file mode 100644
index 000000000000..9300b22f2fff
--- /dev/null
+++ b/lib/matplotlib/style/tests/test_core.py
@@ -0,0 +1,61 @@
+import os
+import shutil
+import tempfile
+from contextlib import contextmanager
+
+import matplotlib as mpl
+from matplotlib import style
+from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
+
+
+PARAM = 'image.cmap'
+VALUE = 'pink'
+DUMMY_SETTINGS = {PARAM: VALUE}
+
+
+@contextmanager
+def temp_style(style_name, settings=None):
+    """Context manager to create a style sheet in a temporary directory."""
+    settings = DUMMY_SETTINGS
+    temp_file = '%s.%s' % (style_name, STYLE_EXTENSION)
+
+    # Write style settings to file in the temp directory.
+    tempdir = tempfile.mkdtemp()
+    with open(os.path.join(tempdir, temp_file), 'w') as f:
+        for k, v in settings.iteritems():
+            f.write('%s: %s' % (k, v))
+
+    # Add temp directory to style path and reload so we can access this style.
+    USER_LIBRARY_PATHS.append(tempdir)
+    style.reload_library()
+
+    try:
+        yield
+    finally:
+        shutil.rmtree(tempdir)
+
+
+def test_available():
+    with temp_style('_test_', DUMMY_SETTINGS):
+        assert '_test_' in style.available
+
+
+def test_use():
+    mpl.rcParams[PARAM] = 'gray'
+    with temp_style('test', DUMMY_SETTINGS):
+        style.use('test')
+        assert mpl.rcParams[PARAM] == VALUE
+
+
+def test_context():
+    mpl.rcParams[PARAM] = 'gray'
+    with temp_style('test', DUMMY_SETTINGS):
+        with style.context('test'):
+            assert mpl.rcParams[PARAM] == VALUE
+    # Check that this value is reset after the exiting the context.
+    assert mpl.rcParams[PARAM] == 'gray'
+
+
+if __name__ == '__main__':
+    from numpy import testing
+    testing.run_module_suite()

From 391408928823efa6da45a8b03015d21eaf3d6804 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Mon, 22 Jul 2013 23:37:08 -0500
Subject: [PATCH 07/35] Change style extension to *.mplstyle

---
 lib/matplotlib/style/core.py                                    | 2 +-
 .../{dark_background.style => dark_background.mplstyle}         | 0
 lib/matplotlib/style/stylelib/{ggplot.style => ggplot.mplstyle} | 0
 .../style/stylelib/{grayscale.style => grayscale.mplstyle}      | 0
 4 files changed, 1 insertion(+), 1 deletion(-)
 rename lib/matplotlib/style/stylelib/{dark_background.style => dark_background.mplstyle} (100%)
 rename lib/matplotlib/style/stylelib/{ggplot.style => ggplot.mplstyle} (100%)
 rename lib/matplotlib/style/stylelib/{grayscale.style => grayscale.mplstyle} (100%)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 689305c022cb..24610eb9be74 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -25,7 +25,7 @@
 BASE_LIBRARY_PATH = os.path.join(_here, 'stylelib')
 # Users may want multiple library paths, so store a list of paths.
 USER_LIBRARY_PATHS = [os.path.join('~', '.matplotlib', 'stylelib')]
-STYLE_EXTENSION = 'style'
+STYLE_EXTENSION = 'mplstyle'
 STYLE_FILE_PATTERN = re.compile('([\S]+).%s$' % STYLE_EXTENSION)
 
 
diff --git a/lib/matplotlib/style/stylelib/dark_background.style b/lib/matplotlib/style/stylelib/dark_background.mplstyle
similarity index 100%
rename from lib/matplotlib/style/stylelib/dark_background.style
rename to lib/matplotlib/style/stylelib/dark_background.mplstyle
diff --git a/lib/matplotlib/style/stylelib/ggplot.style b/lib/matplotlib/style/stylelib/ggplot.mplstyle
similarity index 100%
rename from lib/matplotlib/style/stylelib/ggplot.style
rename to lib/matplotlib/style/stylelib/ggplot.mplstyle
diff --git a/lib/matplotlib/style/stylelib/grayscale.style b/lib/matplotlib/style/stylelib/grayscale.mplstyle
similarity index 100%
rename from lib/matplotlib/style/stylelib/grayscale.style
rename to lib/matplotlib/style/stylelib/grayscale.mplstyle

From c3fae2e27698d3b6d7dda5f312a021010fc811dd Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Tue, 23 Jul 2013 00:21:30 -0500
Subject: [PATCH 08/35] Got a little crazy with the whitespace

---
 lib/matplotlib/__init__.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 9bb6b03d51e7..ddb2398db699 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -973,8 +973,6 @@ def rc_params_in_file(fname, fail_on_error=False):
     return config
 
 
-
-
 def rc_params_from_file(fname, fail_on_error=False):
     """Return :class:`matplotlib.RcParams` from the contents of the given file.
 

From a3de2313b7a01aa5fbe667f4017e55f6e10ac594 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 24 Jul 2013 22:23:43 -0500
Subject: [PATCH 09/35] Add style package and data to setupext.py

---
 setupext.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/setupext.py b/setupext.py
index fba77d28244a..1aedcc0c721b 100644
--- a/setupext.py
+++ b/setupext.py
@@ -549,6 +549,7 @@ def get_packages(self):
             'matplotlib.projections',
             'matplotlib.axes',
             'matplotlib.sphinxext',
+            'matplotlib.style',
             'matplotlib.testing',
             'matplotlib.testing.jpl_units',
             'matplotlib.tri',
@@ -581,7 +582,8 @@ def get_package_data(self):
                 'backends/web_backend/jquery/css/themes/base/*.*',
                 'backends/web_backend/jquery/css/themes/base/images/*',
                 'backends/web_backend/css/*.*',
-                'backends/Matplotlib.nib/*'
+                'backends/Matplotlib.nib/*',
+                'style/stylelib/*.mplstyle',
              ]}
 
 

From d56f73e64385b226e70ab85bf68c839640346072 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 18 Sep 2013 22:47:10 -0500
Subject: [PATCH 10/35] Move test so that it actually runs.

---
 lib/matplotlib/__init__.py                                       | 1 +
 lib/matplotlib/{style/tests/test_core.py => tests/test_style.py} | 0
 2 files changed, 1 insertion(+)
 rename lib/matplotlib/{style/tests/test_core.py => tests/test_style.py} (100%)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index ddb2398db699..ced3871a5208 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -1310,6 +1310,7 @@ def tk_window_focus():
     'matplotlib.tests.test_simplification',
     'matplotlib.tests.test_spines',
     'matplotlib.tests.test_streamplot',
+    'matplotlib.tests.test_style',
     'matplotlib.tests.test_subplots',
     'matplotlib.tests.test_table',
     'matplotlib.tests.test_text',
diff --git a/lib/matplotlib/style/tests/test_core.py b/lib/matplotlib/tests/test_style.py
similarity index 100%
rename from lib/matplotlib/style/tests/test_core.py
rename to lib/matplotlib/tests/test_style.py

From ec6ce6bbeca84530c23744a239d0a6ef1f88a8cb Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 18 Sep 2013 22:52:40 -0500
Subject: [PATCH 11/35] Use explicit string check

---
 lib/matplotlib/style/core.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 24610eb9be74..3df6ede90321 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -14,8 +14,8 @@
 import re
 import contextlib
 
-import numpy as np
 import matplotlib as mpl
+from matplotlib import cbook
 
 
 __all__ = ['use', 'context', 'available', 'library', 'reload_library']
@@ -44,7 +44,7 @@ def use(name):
         style names, see `style.available`. If given a list, each style is
         applied from first to last in the list.
     """
-    if np.isscalar(name):
+    if cbook.is_string_like(name):
         name = [name]
 
     for style in name:

From 5fdc037c06715ee75ab2c489936896632d3823f0 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 18 Sep 2013 23:15:12 -0500
Subject: [PATCH 12/35] Hide rc_params_in_file from parent namespace

---
 lib/matplotlib/__init__.py   | 17 ++++++++++++-----
 lib/matplotlib/style/core.py |  5 +++--
 2 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index ced3871a5208..91286f7bd1f8 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -906,7 +906,7 @@ def _open_file_or_url(fname):
 _error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
 
 
-def rc_params_in_file(fname, fail_on_error=False):
+def _rc_params_in_file(fname, fail_on_error=False):
     """Return :class:`matplotlib.RcParams` from the contents of the given file.
 
     Unlike `rc_params_from_file`, the configuration class only contains the
@@ -973,7 +973,7 @@ def rc_params_in_file(fname, fail_on_error=False):
     return config
 
 
-def rc_params_from_file(fname, fail_on_error=False):
+def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
     """Return :class:`matplotlib.RcParams` from the contents of the given file.
 
     Parameters
@@ -982,12 +982,19 @@ def rc_params_from_file(fname, fail_on_error=False):
         Name of file parsed for matplotlib settings.
     fail_on_error : bool
         If True, raise an error when the parser fails to convert a parameter.
+    use_default_template : bool
+        If True, initialize with default parameters before updating with those
+        in the given file. If False, the configuration class only contains the
+        parameters specified in the file. (Useful for updating dicts.)
     """
+    config_from_file = _rc_params_in_file(fname, fail_on_error)
 
-    config = RcParams([(key, default)
-                       for key, (default, _) in six.iteritems(defaultParams)])
+    if not use_default_template:
+        return config_from_file
 
-    config.update(rc_params_in_file(fname, fail_on_error))
+    iter_params = six.iteritems(defaultParams)
+    config = RcParams([(key, default) for key, (default, _) in iter_params])
+    config.update(config_from_file)
 
     verbose.set_level(config['verbose.level'])
     verbose.set_fileo(config['verbose.fileo'])
diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 3df6ede90321..686900e0ad90 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -16,6 +16,7 @@
 
 import matplotlib as mpl
 from matplotlib import cbook
+from matplotlib import rc_params_from_file
 
 
 __all__ = ['use', 'context', 'available', 'library', 'reload_library']
@@ -49,7 +50,7 @@ def use(name):
 
     for style in name:
         if is_style_file(style):
-            settings = mpl.rc_params_in_file(style)
+            settings = rc_params_from_file(style, use_default_template=False)
             mpl.rcParams.update(settings)
         elif style not in library:
             msg = ("'%s' not found in the style library. "
@@ -117,7 +118,7 @@ def read_style_directory(style_dir):
     """Return dictionary of styles defined in `style_dir`."""
     styles = dict()
     for path, name in iter_style_files(style_dir):
-        styles[name] = mpl.rc_params_in_file(path)
+        styles[name] = rc_params_from_file(path, use_default_template=False)
     return styles
 
 

From 0c7437c122beaeb9c17b86e96b79a88cb85df143 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 18 Sep 2013 23:19:47 -0500
Subject: [PATCH 13/35] Remove usage of import *

---
 lib/matplotlib/style/__init__.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/lib/matplotlib/style/__init__.py b/lib/matplotlib/style/__init__.py
index c98e84e2ac93..9a9eae7d55db 100644
--- a/lib/matplotlib/style/__init__.py
+++ b/lib/matplotlib/style/__init__.py
@@ -1,2 +1 @@
-from core import *
-
+from core import use, context, available, library, reload_library

From 200d2e0ea8c83ff7afc0bc1d81c580e235876c5c Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 18 Sep 2013 23:21:44 -0500
Subject: [PATCH 14/35] Clarify docstring

---
 lib/matplotlib/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 91286f7bd1f8..794fc6604d44 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -888,7 +888,7 @@ def rc_params(fail_on_error=False):
 
 
 def is_url(filename):
-    """Return True if string is an http or ftp path."""
+    """Return True if string is an http, ftp, or file URL path."""
     return URL_REGEX.match(filename) is not None
 
 

From 7392ce677b15cc41697ba2f25642e2191642c5be Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Thu, 26 Sep 2013 22:20:29 -0500
Subject: [PATCH 15/35] added `matplotlib.style` to pyplot import list

---
 lib/matplotlib/pyplot.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index 8ff3714ff585..0d0c03ce13f3 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -25,6 +25,7 @@
 
 import matplotlib
 import matplotlib.colorbar
+import matplotlib.style
 from matplotlib import _pylab_helpers, interactive
 from matplotlib.cbook import dedent, silent_list, is_string_like, is_numlike
 from matplotlib.cbook import _string_to_bool

From ea63c99b71ab7bcfaf862d75111a2c805c07efde Mon Sep 17 00:00:00 2001
From: Adrian Price-Whelan <adrian.prw@gmail.com>
Date: Tue, 17 Sep 2013 01:50:13 -0400
Subject: [PATCH 16/35] fix url rc specification

smoothed over conflicts

add test for URL stylesheet

whoops, remove extraneous regex I added...

move test to proper location

arg, don't need urllib2 either...didn't realize functionality was in core mpl
---
 lib/matplotlib/style/core.py       | 20 +++++++++++---------
 lib/matplotlib/tests/test_style.py |  5 +++++
 2 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 686900e0ad90..39c4d49d841a 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -29,7 +29,6 @@
 STYLE_EXTENSION = 'mplstyle'
 STYLE_FILE_PATTERN = re.compile('([\S]+).%s$' % STYLE_EXTENSION)
 
-
 def is_style_file(filename):
     """Return True if the filename looks like a style file."""
     return STYLE_FILE_PATTERN.match(filename) is not None
@@ -49,15 +48,18 @@ def use(name):
         name = [name]
 
     for style in name:
-        if is_style_file(style):
-            settings = rc_params_from_file(style, use_default_template=False)
-            mpl.rcParams.update(settings)
-        elif style not in library:
-            msg = ("'%s' not found in the style library. "
-                   "See `style.available` for list of available styles.")
-            raise ValueError(msg % style)
-        else:
+        if style in library:
             mpl.rcParams.update(library[style])
+        else:
+            try:
+                settings = mpl.rc_params_in_file(style)
+                mpl.rcParams.update(settings)
+            except:
+                msg = ("'%s' not found in the style library and input is "
+                       "not a valid URL. See `style.available` for list of "
+                       "available styles.")
+                raise ValueError(msg % style)
+
 
 
 @contextlib.contextmanager
diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 9300b22f2fff..233091ea36d0 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -46,6 +46,11 @@ def test_use():
         style.use('test')
         assert mpl.rcParams[PARAM] == VALUE
 
+def test_use_url():
+    with temp_style('test', DUMMY_SETTINGS):
+        style.use('https://gist.github.com/adrn/6590261/raw')
+
+    assert mpl.rcParams['axes.facecolor'] == "adeade"
 
 def test_context():
     mpl.rcParams[PARAM] = 'gray'

From eaa23ee059ad4fc8e5a2d639a1d0ba746b8a8816 Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Thu, 26 Sep 2013 22:40:36 -0500
Subject: [PATCH 17/35] fixed divergent naming scheme

---
 lib/matplotlib/style/core.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 39c4d49d841a..5e589c8c5f75 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -52,7 +52,7 @@ def use(name):
             mpl.rcParams.update(library[style])
         else:
             try:
-                settings = mpl.rc_params_in_file(style)
+                settings = mpl._rc_params_in_file(style)
                 mpl.rcParams.update(settings)
             except:
                 msg = ("'%s' not found in the style library and input is "

From 5f80ca155abdb9cfb2a7b6e5692e5039f7d6269a Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Thu, 26 Sep 2013 22:53:18 -0500
Subject: [PATCH 18/35] pep8 clean up

---
 lib/matplotlib/style/core.py | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 5e589c8c5f75..870bb34cd704 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -29,6 +29,7 @@
 STYLE_EXTENSION = 'mplstyle'
 STYLE_FILE_PATTERN = re.compile('([\S]+).%s$' % STYLE_EXTENSION)
 
+
 def is_style_file(filename):
     """Return True if the filename looks like a style file."""
     return STYLE_FILE_PATTERN.match(filename) is not None
@@ -61,7 +62,6 @@ def use(name):
                 raise ValueError(msg % style)
 
 
-
 @contextlib.contextmanager
 def context(name, after_reset=False):
     """Context manager for using style settings temporarily.
@@ -147,6 +147,7 @@ def update_nested_dict(main_dict, new_dict):
 library = None
 available = []
 
+
 def reload_library():
     """Reload style library."""
     global library, available

From f5ecf5e70b996de7d25902ada2b1ed2e9218a965 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sat, 28 Sep 2013 22:18:02 -0500
Subject: [PATCH 19/35] Add docs for style package

---
 doc/users/beginner.rst     |  1 +
 doc/users/style_sheets.rst | 90 ++++++++++++++++++++++++++++++++++++++
 doc/users/whats_new.rst    | 17 +++++++
 3 files changed, 108 insertions(+)
 create mode 100644 doc/users/style_sheets.rst

diff --git a/doc/users/beginner.rst b/doc/users/beginner.rst
index d1eb6e9deca5..c895415c4ffd 100644
--- a/doc/users/beginner.rst
+++ b/doc/users/beginner.rst
@@ -13,6 +13,7 @@ Beginner's Guide
     :maxdepth: 2
 
     pyplot_tutorial.rst
+    style_sheets.rst
     navigation_toolbar.rst
     index_text.rst
     image_tutorial.rst
diff --git a/doc/users/style_sheets.rst b/doc/users/style_sheets.rst
new file mode 100644
index 000000000000..92a8d3743d2e
--- /dev/null
+++ b/doc/users/style_sheets.rst
@@ -0,0 +1,90 @@
+.. _style-sheets
+
+***********************************
+Customizing plots with style sheets
+***********************************
+
+
+The ``style`` package adds support for easy-to-switch plotting "styles" with
+the same parameters as a matplotlibrc_ file.
+
+There are a number of pre-defined styles provided by matplotlib. For
+example, there's a pre-defined style called "ggplot", which emulates the
+aesthetics of ggplot_ (a popular plotting package for R_). To use this style,
+just add::
+
+   >>> from matplotlib import style
+   >>> style.use('ggplot')
+
+To list all available styles, use::
+
+   >>> print style.available
+
+
+Defining your own style
+=======================
+
+You can create custom styles and use them by calling ``style.use`` with the
+path or URL to the style sheet. Alternatively, if you add your
+``<style-name>.mplstyle`` file to ``~/.matplotlib/stylelib`` (you may need to
+create this directory), you can reuse your custom style sheet with a call to
+``style.use(<style-name>)``. Note that a custom style sheet in
+``~/.matplotlib/stylelib`` will override a style sheet defined by matplotlib if
+the styles have the same name.
+
+For example, you might want to create
+``~/.matplotlib/stylelib/presentation.mplstyle`` with the following::
+
+   axes.titlesize : 24
+   axes.labelsize : 20
+   lines.linewidth : 3
+   lines.markersize : 10
+   xtick.labelsize : 16
+   ytick.labelsize : 16
+
+Then, when you want to adapt a plot designed for a paper to one that looks
+good in a presentation, you can just add::
+
+   >>> from matplotlib import style
+   >>> style.use('presentation')
+
+
+Composing styles
+================
+
+Style sheets are designed to be composed together. So you can have a style
+sheet that customizes colors and a separate style sheet that alters element
+sizes for presentations. These styles can easily be combined by passing
+a list of styles::
+
+   >>> from matplotlib import style
+   >>> style.use(['dark_background', 'presentation'])
+
+Note that styles further to the right will overwrite values that are already
+defined by styles on the right.
+
+
+Temporary styling
+=================
+
+If you only want to use a style for a specific block of code but don't want
+to change the global styling, the style package provides a context manager
+for limiting your changes to a specific scope. To isolate the your styling
+changes, you can write something like the following::
+
+
+   >>> import numpy as np
+   >>> import matplotlib.pyplot as plt
+   >>> from matplotlib import style
+   >>>
+   >>> with style.context(('dark_background')):
+   >>>     plt.plot(np.sin(np.linspace(0, 2*np.pi)), 'r-o')
+   >>>
+   >>> # Some plotting code with the default style
+   >>>
+   >>> plt.show()
+
+
+.. _matplotlibrc: http://matplotlib.sourceforge.net/users/customizing.html
+.. _ggplot: http://had.co.nz/ggplot/
+.. _R: http://www.r-project.org/
diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst
index 5bd6969afecf..d072c3807f1c 100644
--- a/doc/users/whats_new.rst
+++ b/doc/users/whats_new.rst
@@ -98,6 +98,23 @@ an offset will be determined such that the tick labels are
 meaningful. If `False` then the full number will be formatted in all
 conditions.
 
+``style`` package added
+```````````````````````
+You can now easily switch between different styles using the new ``style``
+package::
+
+   >>> from matplotlib import style
+   >>> style.use('dark_background')
+
+Subsequent plots will use updated colors, sizes, etc. To list all available
+styles, use::
+
+   >>> print style.available
+
+You can add your own custom ``<style name>.mplstyle`` files to
+``~/.matplotlib/stylelib`` or call ``use`` with a URL pointing to a file with
+``matplotlibrc`` settings.
+
 .. _whats-new-1-3:
 
 new in matplotlib-1.3

From a8ef5bfab1614e2db383438be49ec815007f0882 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sat, 28 Sep 2013 23:02:09 -0500
Subject: [PATCH 20/35] Import style package for easy use.

---
 lib/matplotlib/pyplot.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index 0d0c03ce13f3..a67fc8580b1e 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -25,7 +25,7 @@
 
 import matplotlib
 import matplotlib.colorbar
-import matplotlib.style
+from matplotlib import style
 from matplotlib import _pylab_helpers, interactive
 from matplotlib.cbook import dedent, silent_list, is_string_like, is_numlike
 from matplotlib.cbook import _string_to_bool

From dc291e09113181d503554e138184f9d80c897e53 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sat, 28 Sep 2013 23:07:22 -0500
Subject: [PATCH 21/35] Use style package from pyplot

---
 doc/users/style_sheets.rst                    | 17 ++++++++---------
 examples/style_sheets/plot_dark_background.py |  3 +--
 examples/style_sheets/plot_ggplot.py          |  3 +--
 examples/style_sheets/plot_grayscale.py       |  4 +---
 4 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/doc/users/style_sheets.rst b/doc/users/style_sheets.rst
index 92a8d3743d2e..563ac542c8ec 100644
--- a/doc/users/style_sheets.rst
+++ b/doc/users/style_sheets.rst
@@ -13,12 +13,12 @@ example, there's a pre-defined style called "ggplot", which emulates the
 aesthetics of ggplot_ (a popular plotting package for R_). To use this style,
 just add::
 
-   >>> from matplotlib import style
-   >>> style.use('ggplot')
+   >>> import matplotlib.pyplot as plt
+   >>> plt.style.use('ggplot')
 
 To list all available styles, use::
 
-   >>> print style.available
+   >>> print plt.style.available
 
 
 Defining your own style
@@ -45,8 +45,8 @@ For example, you might want to create
 Then, when you want to adapt a plot designed for a paper to one that looks
 good in a presentation, you can just add::
 
-   >>> from matplotlib import style
-   >>> style.use('presentation')
+   >>> import matplotlib.pyplot as plt
+   >>> plt.style.use('presentation')
 
 
 Composing styles
@@ -57,8 +57,8 @@ sheet that customizes colors and a separate style sheet that alters element
 sizes for presentations. These styles can easily be combined by passing
 a list of styles::
 
-   >>> from matplotlib import style
-   >>> style.use(['dark_background', 'presentation'])
+   >>> import matplotlib.pyplot as plt
+   >>> plt.style.use(['dark_background', 'presentation'])
 
 Note that styles further to the right will overwrite values that are already
 defined by styles on the right.
@@ -75,9 +75,8 @@ changes, you can write something like the following::
 
    >>> import numpy as np
    >>> import matplotlib.pyplot as plt
-   >>> from matplotlib import style
    >>>
-   >>> with style.context(('dark_background')):
+   >>> with plt.style.context(('dark_background')):
    >>>     plt.plot(np.sin(np.linspace(0, 2*np.pi)), 'r-o')
    >>>
    >>> # Some plotting code with the default style
diff --git a/examples/style_sheets/plot_dark_background.py b/examples/style_sheets/plot_dark_background.py
index acb94d4eafa9..c2f76b95e6f5 100644
--- a/examples/style_sheets/plot_dark_background.py
+++ b/examples/style_sheets/plot_dark_background.py
@@ -7,9 +7,8 @@
 import numpy as np
 import matplotlib.pyplot as plt
 
-from matplotlib import style
-style.use('dark_background')
 
+plt.style.use('dark_background')
 
 L = 6
 x = np.linspace(0, L)
diff --git a/examples/style_sheets/plot_ggplot.py b/examples/style_sheets/plot_ggplot.py
index 726ecb9ce462..0542ea35b2bf 100644
--- a/examples/style_sheets/plot_ggplot.py
+++ b/examples/style_sheets/plot_ggplot.py
@@ -12,9 +12,8 @@
 """
 import numpy as np
 import matplotlib.pyplot as plt
-from matplotlib import style
 
-style.use('ggplot')
+plt.style.use('ggplot')
 
 fig, axes = plt.subplots(ncols=2, nrows=2)
 ax1, ax2, ax3, ax4 = axes.ravel()
diff --git a/examples/style_sheets/plot_grayscale.py b/examples/style_sheets/plot_grayscale.py
index a6d04dc48970..e233960099d3 100644
--- a/examples/style_sheets/plot_grayscale.py
+++ b/examples/style_sheets/plot_grayscale.py
@@ -7,8 +7,6 @@
 import numpy as np
 import matplotlib.pyplot as plt
 
-from matplotlib import style
-
 
 def color_cycle_example(ax):
     L = 6
@@ -24,7 +22,7 @@ def image_and_patch_example(ax):
     ax.add_patch(c)
 
 
-style.use('grayscale')
+plt.style.use('grayscale')
 
 fig, (ax1, ax2) = plt.subplots(ncols=2)
 

From c5b5bb49d489533b84f873234bbcd6384f98e6f0 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sat, 28 Sep 2013 23:17:53 -0500
Subject: [PATCH 22/35] Fix test

---
 lib/matplotlib/style/core.py       | 10 ++++++----
 lib/matplotlib/tests/test_style.py |  2 +-
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 870bb34cd704..4d412d82ce2f 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -53,12 +53,14 @@ def use(name):
             mpl.rcParams.update(library[style])
         else:
             try:
-                settings = mpl._rc_params_in_file(style)
-                mpl.rcParams.update(settings)
+                rc = rc_params_from_file(style, use_default_template=False)
+                print rc
+                print type(rc)
+                mpl.rcParams.update(rc)
             except:
                 msg = ("'%s' not found in the style library and input is "
-                       "not a valid URL. See `style.available` for list of "
-                       "available styles.")
+                       "not a valid URL or path. See `style.available` for "
+                       "list of available styles.")
                 raise ValueError(msg % style)
 
 
diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 233091ea36d0..24031b0f2ab3 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -50,7 +50,7 @@ def test_use_url():
     with temp_style('test', DUMMY_SETTINGS):
         style.use('https://gist.github.com/adrn/6590261/raw')
 
-    assert mpl.rcParams['axes.facecolor'] == "adeade"
+    assert mpl.rcParams['axes.facecolor'] == "#adeade"
 
 def test_context():
     mpl.rcParams[PARAM] = 'gray'

From 7ac26ee0b5ce5c7ccbad4e53061bc99849ff23bd Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Fri, 18 Oct 2013 11:32:48 -0500
Subject: [PATCH 23/35] pep8

---
 lib/matplotlib/tests/test_style.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 24031b0f2ab3..9a7ee9ac5f8e 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -46,12 +46,14 @@ def test_use():
         style.use('test')
         assert mpl.rcParams[PARAM] == VALUE
 
+
 def test_use_url():
     with temp_style('test', DUMMY_SETTINGS):
         style.use('https://gist.github.com/adrn/6590261/raw')
 
     assert mpl.rcParams['axes.facecolor'] == "#adeade"
 
+
 def test_context():
     mpl.rcParams[PARAM] = 'gray'
     with temp_style('test', DUMMY_SETTINGS):

From 46a725b984c0649d335a0f6019392b29d2a065cf Mon Sep 17 00:00:00 2001
From: Michael Droettboom <mdboom@gmail.com>
Date: Mon, 30 Sep 2013 11:53:26 -0400
Subject: [PATCH 24/35] Clear style settings between tests

Conflicts:
	lib/matplotlib/tests/test_style.py

Conflicts:
	lib/matplotlib/tests/test_style.py
---
 lib/matplotlib/tests/test_style.py | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 9a7ee9ac5f8e..75c59ed20953 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -33,6 +33,7 @@ def temp_style(style_name, settings=None):
         yield
     finally:
         shutil.rmtree(tempdir)
+        style.reload_library()
 
 
 def test_available():
@@ -43,15 +44,14 @@ def test_available():
 def test_use():
     mpl.rcParams[PARAM] = 'gray'
     with temp_style('test', DUMMY_SETTINGS):
-        style.use('test')
-        assert mpl.rcParams[PARAM] == VALUE
+        with style.context('test'):
+            assert mpl.rcParams[PARAM] == VALUE
 
 
 def test_use_url():
     with temp_style('test', DUMMY_SETTINGS):
-        style.use('https://gist.github.com/adrn/6590261/raw')
-
-    assert mpl.rcParams['axes.facecolor'] == "#adeade"
+        with style.context('https://gist.github.com/adrn/6590261/raw'):
+            assert mpl.rcParams['axes.facecolor'] == "#adeade"
 
 
 def test_context():

From d372a3545659e75753019ee9526c9e55f9e03c04 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Fri, 18 Oct 2013 22:47:44 -0500
Subject: [PATCH 25/35] Add note that style sheets are experimental.

---
 doc/users/whats_new.rst | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/doc/users/whats_new.rst b/doc/users/whats_new.rst
index d072c3807f1c..886e60c16f0e 100644
--- a/doc/users/whats_new.rst
+++ b/doc/users/whats_new.rst
@@ -115,6 +115,9 @@ You can add your own custom ``<style name>.mplstyle`` files to
 ``~/.matplotlib/stylelib`` or call ``use`` with a URL pointing to a file with
 ``matplotlibrc`` settings.
 
+*Note that this is an experimental feature*, and the interface may change as
+users test out this new feature.
+
 .. _whats-new-1-3:
 
 new in matplotlib-1.3

From e714c778e8dac04fec7debd63164ab7bbf24cfe8 Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Sat, 26 Oct 2013 23:18:48 -0500
Subject: [PATCH 26/35] added python3 emulation code + six + fixed up print
 calls

---
 lib/matplotlib/style/core.py | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 4d412d82ce2f..1db7e519b292 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -1,3 +1,9 @@
+from __future__ import (absolute_import, division, print_function,
+                        unicode_literals)
+
+import six
+from six.moves import reduce, xrange, zip
+
 """
 Core functions and attributes for the matplotlib style library:
 
@@ -54,8 +60,8 @@ def use(name):
         else:
             try:
                 rc = rc_params_from_file(style, use_default_template=False)
-                print rc
-                print type(rc)
+                print(rc)
+                print(type(rc))
                 mpl.rcParams.update(rc)
             except:
                 msg = ("'%s' not found in the style library and input is "

From 512b77c011bf281b56632ddaa4064e841b38833d Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Thu, 31 Oct 2013 08:48:45 -0500
Subject: [PATCH 27/35] removed unneeded print statements

removed some of the unneeded imports
---
 lib/matplotlib/style/core.py | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 1db7e519b292..d2dca91e1d11 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -2,7 +2,6 @@
                         unicode_literals)
 
 import six
-from six.moves import reduce, xrange, zip
 
 """
 Core functions and attributes for the matplotlib style library:
@@ -60,8 +59,6 @@ def use(name):
         else:
             try:
                 rc = rc_params_from_file(style, use_default_template=False)
-                print(rc)
-                print(type(rc))
                 mpl.rcParams.update(rc)
             except:
                 msg = ("'%s' not found in the style library and input is "

From 17282c88937bf0be1feb49640657cfa1189e0dc0 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Tue, 12 Nov 2013 21:08:00 -0600
Subject: [PATCH 28/35] Attempt to fix python 3 test errors on Travis CI

---
 lib/matplotlib/tests/test_style.py | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 75c59ed20953..224c5960df60 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -61,8 +61,3 @@ def test_context():
             assert mpl.rcParams[PARAM] == VALUE
     # Check that this value is reset after the exiting the context.
     assert mpl.rcParams[PARAM] == 'gray'
-
-
-if __name__ == '__main__':
-    from numpy import testing
-    testing.run_module_suite()

From a6142fc19beb074de34a2f1f1f2ee10830c0a04b Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 13 Nov 2013 21:48:07 -0600
Subject: [PATCH 29/35] Remove test from list to test Travis CI failure.

---
 lib/matplotlib/__init__.py | 1 -
 1 file changed, 1 deletion(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 794fc6604d44..4a5ea5f755d8 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -1317,7 +1317,6 @@ def tk_window_focus():
     'matplotlib.tests.test_simplification',
     'matplotlib.tests.test_spines',
     'matplotlib.tests.test_streamplot',
-    'matplotlib.tests.test_style',
     'matplotlib.tests.test_subplots',
     'matplotlib.tests.test_table',
     'matplotlib.tests.test_text',

From 19e7bed4dcc7fec7af18e05aff6209ed4ae52747 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 13 Nov 2013 21:58:29 -0600
Subject: [PATCH 30/35] Remove test file to test Travis CI failure

---
 lib/matplotlib/tests/test_style.py | 63 ------------------------------
 1 file changed, 63 deletions(-)
 delete mode 100644 lib/matplotlib/tests/test_style.py

diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
deleted file mode 100644
index 224c5960df60..000000000000
--- a/lib/matplotlib/tests/test_style.py
+++ /dev/null
@@ -1,63 +0,0 @@
-import os
-import shutil
-import tempfile
-from contextlib import contextmanager
-
-import matplotlib as mpl
-from matplotlib import style
-from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
-
-
-PARAM = 'image.cmap'
-VALUE = 'pink'
-DUMMY_SETTINGS = {PARAM: VALUE}
-
-
-@contextmanager
-def temp_style(style_name, settings=None):
-    """Context manager to create a style sheet in a temporary directory."""
-    settings = DUMMY_SETTINGS
-    temp_file = '%s.%s' % (style_name, STYLE_EXTENSION)
-
-    # Write style settings to file in the temp directory.
-    tempdir = tempfile.mkdtemp()
-    with open(os.path.join(tempdir, temp_file), 'w') as f:
-        for k, v in settings.iteritems():
-            f.write('%s: %s' % (k, v))
-
-    # Add temp directory to style path and reload so we can access this style.
-    USER_LIBRARY_PATHS.append(tempdir)
-    style.reload_library()
-
-    try:
-        yield
-    finally:
-        shutil.rmtree(tempdir)
-        style.reload_library()
-
-
-def test_available():
-    with temp_style('_test_', DUMMY_SETTINGS):
-        assert '_test_' in style.available
-
-
-def test_use():
-    mpl.rcParams[PARAM] = 'gray'
-    with temp_style('test', DUMMY_SETTINGS):
-        with style.context('test'):
-            assert mpl.rcParams[PARAM] == VALUE
-
-
-def test_use_url():
-    with temp_style('test', DUMMY_SETTINGS):
-        with style.context('https://gist.github.com/adrn/6590261/raw'):
-            assert mpl.rcParams['axes.facecolor'] == "#adeade"
-
-
-def test_context():
-    mpl.rcParams[PARAM] = 'gray'
-    with temp_style('test', DUMMY_SETTINGS):
-        with style.context('test'):
-            assert mpl.rcParams[PARAM] == VALUE
-    # Check that this value is reset after the exiting the context.
-    assert mpl.rcParams[PARAM] == 'gray'

From c60449881b6a46d7f2e1aceb47e8c5f1c1928206 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Wed, 13 Nov 2013 22:15:40 -0600
Subject: [PATCH 31/35] Revert commits used to test Travis CI test failures.

End result of the experiment: The failure isn't related to the tests
added by this PR.
---
 lib/matplotlib/__init__.py         |  1 +
 lib/matplotlib/tests/test_style.py | 68 ++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+)
 create mode 100644 lib/matplotlib/tests/test_style.py

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 4a5ea5f755d8..794fc6604d44 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -1317,6 +1317,7 @@ def tk_window_focus():
     'matplotlib.tests.test_simplification',
     'matplotlib.tests.test_spines',
     'matplotlib.tests.test_streamplot',
+    'matplotlib.tests.test_style',
     'matplotlib.tests.test_subplots',
     'matplotlib.tests.test_table',
     'matplotlib.tests.test_text',
diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
new file mode 100644
index 000000000000..75c59ed20953
--- /dev/null
+++ b/lib/matplotlib/tests/test_style.py
@@ -0,0 +1,68 @@
+import os
+import shutil
+import tempfile
+from contextlib import contextmanager
+
+import matplotlib as mpl
+from matplotlib import style
+from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
+
+
+PARAM = 'image.cmap'
+VALUE = 'pink'
+DUMMY_SETTINGS = {PARAM: VALUE}
+
+
+@contextmanager
+def temp_style(style_name, settings=None):
+    """Context manager to create a style sheet in a temporary directory."""
+    settings = DUMMY_SETTINGS
+    temp_file = '%s.%s' % (style_name, STYLE_EXTENSION)
+
+    # Write style settings to file in the temp directory.
+    tempdir = tempfile.mkdtemp()
+    with open(os.path.join(tempdir, temp_file), 'w') as f:
+        for k, v in settings.iteritems():
+            f.write('%s: %s' % (k, v))
+
+    # Add temp directory to style path and reload so we can access this style.
+    USER_LIBRARY_PATHS.append(tempdir)
+    style.reload_library()
+
+    try:
+        yield
+    finally:
+        shutil.rmtree(tempdir)
+        style.reload_library()
+
+
+def test_available():
+    with temp_style('_test_', DUMMY_SETTINGS):
+        assert '_test_' in style.available
+
+
+def test_use():
+    mpl.rcParams[PARAM] = 'gray'
+    with temp_style('test', DUMMY_SETTINGS):
+        with style.context('test'):
+            assert mpl.rcParams[PARAM] == VALUE
+
+
+def test_use_url():
+    with temp_style('test', DUMMY_SETTINGS):
+        with style.context('https://gist.github.com/adrn/6590261/raw'):
+            assert mpl.rcParams['axes.facecolor'] == "#adeade"
+
+
+def test_context():
+    mpl.rcParams[PARAM] = 'gray'
+    with temp_style('test', DUMMY_SETTINGS):
+        with style.context('test'):
+            assert mpl.rcParams[PARAM] == VALUE
+    # Check that this value is reset after the exiting the context.
+    assert mpl.rcParams[PARAM] == 'gray'
+
+
+if __name__ == '__main__':
+    from numpy import testing
+    testing.run_module_suite()

From 0b098e2aa939f00482602ca2ae4b20eb2b5cfba3 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 17 Nov 2013 11:14:00 -0600
Subject: [PATCH 32/35] Fix import for python 3

---
 lib/matplotlib/style/__init__.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/lib/matplotlib/style/__init__.py b/lib/matplotlib/style/__init__.py
index 9a9eae7d55db..cb0592f41e78 100644
--- a/lib/matplotlib/style/__init__.py
+++ b/lib/matplotlib/style/__init__.py
@@ -1 +1,3 @@
-from core import use, context, available, library, reload_library
+from __future__ import absolute_import
+
+from .core import use, context, available, library, reload_library

From 7e2bffb3b24e6c07ceb2d5a22be8c5b6ff155120 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 17 Nov 2013 11:56:40 -0600
Subject: [PATCH 33/35] Use iteritems from `six` module

---
 lib/matplotlib/style/core.py       | 2 +-
 lib/matplotlib/tests/test_style.py | 7 ++++++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index d2dca91e1d11..845d5472b294 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -137,7 +137,7 @@ def update_nested_dict(main_dict, new_dict):
     already exists. Instead you should update the sub-dict.
     """
     # update named styles specified by user
-    for name, rc_dict in new_dict.iteritems():
+    for name, rc_dict in six.iteritems(new_dict):
         if name in main_dict:
             main_dict[name].update(rc_dict)
         else:
diff --git a/lib/matplotlib/tests/test_style.py b/lib/matplotlib/tests/test_style.py
index 75c59ed20953..d8e71f5cc4d2 100644
--- a/lib/matplotlib/tests/test_style.py
+++ b/lib/matplotlib/tests/test_style.py
@@ -1,3 +1,6 @@
+from __future__ import (absolute_import, division, print_function,
+                        unicode_literals)
+
 import os
 import shutil
 import tempfile
@@ -7,6 +10,8 @@
 from matplotlib import style
 from matplotlib.style.core import USER_LIBRARY_PATHS, STYLE_EXTENSION
 
+import six
+
 
 PARAM = 'image.cmap'
 VALUE = 'pink'
@@ -22,7 +27,7 @@ def temp_style(style_name, settings=None):
     # Write style settings to file in the temp directory.
     tempdir = tempfile.mkdtemp()
     with open(os.path.join(tempdir, temp_file), 'w') as f:
-        for k, v in settings.iteritems():
+        for k, v in six.iteritems(settings):
             f.write('%s: %s' % (k, v))
 
     # Add temp directory to style path and reload so we can access this style.

From 1d87f347ddb89830dcd51884b746fa4d8f8dfb38 Mon Sep 17 00:00:00 2001
From: Tony S Yu <tsyu80@gmail.com>
Date: Sun, 17 Nov 2013 13:59:03 -0600
Subject: [PATCH 34/35] Add compatibility layer for Python 3's urlopen

---
 lib/matplotlib/__init__.py | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 794fc6604d44..9986bb0a37a8 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -892,11 +892,17 @@ def is_url(filename):
     return URL_REGEX.match(filename) is not None
 
 
+def _url_lines(f):
+    # Compatibility for urlopen in python 3, which yields bytes.
+    for line in f:
+        yield line.decode(encoding='utf8')
+
+
 @contextlib.contextmanager
 def _open_file_or_url(fname):
     if is_url(fname):
         f = urlopen(fname)
-        yield f
+        yield _url_lines(f)
         f.close()
     else:
         with open(fname) as f:

From 79f83c996ff611040796605ba76b3fcd109c9914 Mon Sep 17 00:00:00 2001
From: Michael Droettboom <mdboom@gmail.com>
Date: Mon, 18 Nov 2013 07:28:24 -0500
Subject: [PATCH 35/35] Fix _fix_url on Python 2.6

---
 lib/matplotlib/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 9986bb0a37a8..b61f183b767b 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -895,7 +895,7 @@ def is_url(filename):
 def _url_lines(f):
     # Compatibility for urlopen in python 3, which yields bytes.
     for line in f:
-        yield line.decode(encoding='utf8')
+        yield line.decode('utf8')
 
 
 @contextlib.contextmanager