From 32aaee43923b44fdef5e26b5c609f19951245d39 Mon Sep 17 00:00:00 2001
From: Thomas A Caswell <tcaswell@gmail.com>
Date: Sun, 13 Sep 2015 15:40:11 -0400
Subject: [PATCH] MNT: more control of colorbar with CountourSet

In the `ColorBar` constructor values are extracted from the mappable if
it is a ContourSet.  Instead of always overwriting user-input only,
respect user input if given.

If the user passes in kwargs which can be extracted from a ContourSet
raise TypeError instead of silently ignoring user input.
---
 doc/api/api_changes/2016-01-03_colorbar.rst | 12 ++++++++++++
 examples/pylab_examples/contour_demo.py     |  4 ++--
 lib/matplotlib/colorbar.py                  | 11 +++++++----
 lib/matplotlib/tests/test_colorbar.py       | 13 ++++++-------
 4 files changed, 27 insertions(+), 13 deletions(-)
 create mode 100644 doc/api/api_changes/2016-01-03_colorbar.rst

diff --git a/doc/api/api_changes/2016-01-03_colorbar.rst b/doc/api/api_changes/2016-01-03_colorbar.rst
new file mode 100644
index 000000000000..940d5e3ff032
--- /dev/null
+++ b/doc/api/api_changes/2016-01-03_colorbar.rst
@@ -0,0 +1,12 @@
+`ColorBar` raises TypeError rather than ignore user input
+`````````````````````````````````````````````````````````
+
+In ``__init__`` `ColorBar` ignores user supplied ``cmap`` and ``norm``
+keyword arguments in favor of retrieving those values from the
+``mappable`` passed in.  If those keywords are supplied, `ColorBar`
+will now raise a `TypeError` rather than silently dropping user supplied
+input.
+
+If ``mappable`` is a `contour.ContourSet` then a `TypeError` will be raised
+if the user provides any of
+``('alpha', 'boundaries', 'values', 'extend', 'filled')``
diff --git a/examples/pylab_examples/contour_demo.py b/examples/pylab_examples/contour_demo.py
index b3555b1de1eb..506a2017f9ea 100755
--- a/examples/pylab_examples/contour_demo.py
+++ b/examples/pylab_examples/contour_demo.py
@@ -80,7 +80,7 @@
 CS = plt.contour(Z, levels,
                  origin='lower',
                  linewidths=2,
-                 extent=(-3, 3, -2, 2))
+                 extent=(-3, 3, -2, 2), extend='both')
 
 # Thicken the zero contour.
 zc = CS.collections[6]
@@ -92,7 +92,7 @@
            fontsize=14)
 
 # make a colorbar for the contour lines
-CB = plt.colorbar(CS, shrink=0.8, extend='both')
+CB = plt.colorbar(CS, shrink=0.8)
 
 plt.title('Lines with colorbar')
 #plt.hot()  # Now change the colormap for the contour lines and colorbar
diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py
index 9be373e66e86..1ba673ded935 100644
--- a/lib/matplotlib/colorbar.py
+++ b/lib/matplotlib/colorbar.py
@@ -889,18 +889,21 @@ def __init__(self, ax, mappable, **kw):
         mappable.autoscale_None()
 
         self.mappable = mappable
+        kw = cbook.normalize_kwargs(kw, forbidden=('cmap', 'norm'))
         kw['cmap'] = cmap = mappable.cmap
-        kw['norm'] = norm = mappable.norm
+        kw['norm'] = mappable.norm
 
         if isinstance(mappable, contour.ContourSet):
             CS = mappable
+            override_list = ('alpha', 'boundaries', 'values', 'extend',
+                             'filled')
+            kw = cbook.normalize_kwargs(kw, forbidden=override_list)
             kw['alpha'] = mappable.get_alpha()
             kw['boundaries'] = CS._levels
             kw['values'] = CS.cvalues
             kw['extend'] = CS.extend
-            #kw['ticks'] = CS._levels
-            kw.setdefault('ticks', ticker.FixedLocator(CS.levels, nbins=10))
             kw['filled'] = CS.filled
+            kw.setdefault('ticks', ticker.FixedLocator(CS.levels, nbins=10))
             ColorbarBase.__init__(self, ax, **kw)
             if not CS.filled:
                 self.add_lines(CS)
@@ -909,7 +912,7 @@ def __init__(self, ax, mappable, **kw):
                 kw.setdefault('extend', cmap.colorbar_extend)
 
             if isinstance(mappable, martist.Artist):
-                kw['alpha'] = mappable.get_alpha()
+                kw.setdefault('alpha', mappable.get_alpha())
 
             ColorbarBase.__init__(self, ax, **kw)
 
diff --git a/lib/matplotlib/tests/test_colorbar.py b/lib/matplotlib/tests/test_colorbar.py
index d142fbc51e9d..8c49f698fcda 100644
--- a/lib/matplotlib/tests/test_colorbar.py
+++ b/lib/matplotlib/tests/test_colorbar.py
@@ -272,13 +272,13 @@ def test_colorbar_closed_patch():
     values = np.linspace(0, 10, 5)
 
     with rc_context({'axes.linewidth': 16}):
-        plt.colorbar(im, cax=ax2, cmap=cmap, orientation='horizontal',
+        plt.colorbar(im, cax=ax2, orientation='horizontal',
                      extend='both', extendfrac=0.5, values=values)
-        plt.colorbar(im, cax=ax3, cmap=cmap, orientation='horizontal',
+        plt.colorbar(im, cax=ax3,  orientation='horizontal',
                      extend='both', values=values)
-        plt.colorbar(im, cax=ax4, cmap=cmap, orientation='horizontal',
+        plt.colorbar(im, cax=ax4, orientation='horizontal',
                      extend='both', extendrect=True, values=values)
-        plt.colorbar(im, cax=ax5, cmap=cmap, orientation='horizontal',
+        plt.colorbar(im, cax=ax5, orientation='horizontal',
                      extend='neither', values=values)
 
 
@@ -292,9 +292,8 @@ def test_colorbar_ticks():
     Z = X * Y
     clevs = np.array([-12, -5, 0, 5, 12], dtype=float)
     colors = ['r', 'g', 'b', 'c']
-    cs = ax.contourf(X, Y, Z, clevs, colors=colors)
-    cbar = fig.colorbar(cs, ax=ax, extend='neither',
-                        orientation='horizontal', ticks=clevs)
+    cs = ax.contourf(X, Y, Z, clevs, colors=colors, extend='neither')
+    cbar = fig.colorbar(cs, ax=ax, orientation='horizontal')
     assert len(cbar.ax.xaxis.get_ticklocs()) == len(clevs)