Repository: matplotlib/matplotlib
Pull request: Deprecate is_string_like, is_sequence_of_strings
While implementing #7996 (see also #7835), I had missed that numpy's `str_` (and `unicode_` on Py2) derive from the corresponding builtin type(s), so `isinstance(x, six.text_type)` is just as good.  So I just inlined that and restored the old definition of `is_string_like`, immediately deprecating it.

Would also (upon removal) close #7725.

Problem statement:
`is_string_like` returns True for numpy `object` arrays
### Bug report

**Bug summary**

Function `is_string_like` returns True for numpy `object` arrays

**Code for reproduction**

```python
import numpy as np
from matplotlib.cbook import is_string_like
print(is_string_like(np.array(map(str, [1,2,3]), dtype=object)))
```

**Actual outcome**
```
True
```

**Expected outcome**
```
False
```

The problem is that the line 707 `obj + ''` in `is_string_like` does not generate an exception with such numpy array.

**Matplotlib version**

- [ ] Matplotlib version: 1.5.3
- [ ] OS: Ubuntu 14.04
- [ ] Python and Matplotlib Installed with Anaconda

Hints from issue discussion:
In what context is this a problem?  A numpy object array of str objects _is_ very string like [he says having flash-backs to MATLAB days]. 
I use `seaborn`, and a `pandas.Dataframe` to scatter some points.
Here, I need to concatenate a label vector (of type `object`) to my data matrix. Such operation causes the DataFrame to force all columns to have the `object` type.

For the moment, in my project, I overcame the issue by forcing the columns related to the points to have again the `float` type, since the `is_string_like` function with `object` arrays seems to consider my columns as strings.

I understand this may be an unexpected behaviour of `numpy`, rather than `matplotlib`'s.
In fact, the operation
```
np.array(['1','2'], dtype=object) + ''
```
does not generate any type of errors or warnings. It simply has no effect.
Regarding the observations, I'd say that
```
np.array(['1','2'], dtype=str) + ''
```
instead, generates an error, hence `is_string_like` in this case would return `False`.

It seemed reasonable, however, to open an issue here, due to the fact that assuming the generation of some errors in such operations, causes the function to consider strings something which is not.
That sounds like pandas is doing something wrong (as one of the big advantages of panadas over numpy is to have heterogeneous columns)

That test has no effect because you are adding an empty string, if you do

```python
In [5]: np.array(['1','2'], dtype=object) + 'b'
Out[5]: 
array(['1b', '2b'], dtype=object)
```

what is doing is clearer (the `add` unfunc is falling back to defering to python to deal with the `+` operation and giving you back a new object array with concatenation broadcast across all entries).

In the second case, you get

```pytb
In [4]: np.array(['1','2'], dtype=str) + ''
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-1ccaacc2525d> in <module>()
----> 1 np.array(['1','2'], dtype=str) + ''

TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U1') dtype('<U1') dtype('<U1')
```

Because instead of holding the values as python string objects (which know how to add with another string and is just a black-box to numpy) it is holding the values as fixed length c-strings and the dispatch mechanism in numpy does not know how to deal with this.

Commit message: Deprecate is_sequence_of_strings; cleanup.

`Axes3D.scatter` no longer flattens a 2D color input.

Patch to review:
diff --git a/doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst b/doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst
index ba062de5d71a..d3ff6036234d 100644
--- a/doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst
+++ b/doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst
@@ -1,8 +1,10 @@
-`cbook.is_numlike` and `cbook.is_string_like` only perform an instance check
-````````````````````````````````````````````````````````````````````````````
+`cbook.is_numlike` only performs an instance check, `cbook.is_string_like` is deprecated
+````````````````````````````````````````````````````````````````````````````````````````
 
-`cbook.is_numlike` and `cbook.is_string_like` now only check that
-their argument is an instance of ``(numbers.Number, np.Number)`` and
-``(six.string_types, np.str_, np.unicode_)`` respectively.  In particular, this
-means that arrays are now never num-like or string-like regardless of their
-dtype.
+`cbook.is_numlike` now only checks that its argument is an instance of
+``(numbers.Number, np.Number)`` and.  In particular, this means that arrays are
+now not num-like.
+
+`cbook.is_string_like` and `cbook.is_sequence_of_strings` have been
+deprecated.  Use ``isinstance(obj, six.string_types)`` and ``all(isinstance(o,
+six.string_types) for o in obj) and not iterable(obj)`` instead.
diff --git a/examples/misc/rc_traits.py b/examples/misc/rc_traits.py
index e5aa417f4cd3..a2b397e5d252 100644
--- a/examples/misc/rc_traits.py
+++ b/examples/misc/rc_traits.py
@@ -10,7 +10,6 @@
 import os
 import re
 import traits.api as traits
-from matplotlib.cbook import is_string_like
 from matplotlib.artist import Artist
 
 doprint = True
@@ -75,7 +74,7 @@ def tuple_to_rgba(ob, name, val):
 def hex_to_rgba(ob, name, val):
     rgx = re.compile('^#[0-9A-Fa-f]{6}$')
 
-    if not is_string_like(val):
+    if not isinstance(val, six.string_types):
         raise TypeError
     if rgx.match(val) is None:
         raise ValueError
diff --git a/examples/mplot3d/2dcollections3d.py b/examples/mplot3d/2dcollections3d.py
index 436219ae8e93..21a7a4148749 100644
--- a/examples/mplot3d/2dcollections3d.py
+++ b/examples/mplot3d/2dcollections3d.py
@@ -25,11 +25,11 @@
 # Fixing random state for reproducibility
 np.random.seed(19680801)
 
-x = np.random.sample(20*len(colors))
-y = np.random.sample(20*len(colors))
+x = np.random.sample(20 * len(colors))
+y = np.random.sample(20 * len(colors))
 c_list = []
 for c in colors:
-    c_list.append([c]*20)
+    c_list.extend([c] * 20)
 # By using zdir='y', the y value of these points is fixed to the zs value 0
 # and the (x,y) points are plotted on the x and z axes.
 ax.scatter(x, y, zs=0, zdir='y', c=c_list, label='points in (x,z)')
diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py
index 700ea7412acf..5ee6fc197905 100644
--- a/lib/matplotlib/__init__.py
+++ b/lib/matplotlib/__init__.py
@@ -121,14 +121,10 @@
 # cbook must import matplotlib only within function
 # definitions, so it is safe to import from it here.
 from . import cbook
-from matplotlib.cbook import (is_string_like,
-                              mplDeprecation,
-                              dedent, get_label,
-                              sanitize_sequence)
+from matplotlib.cbook import (
+    mplDeprecation, dedent, get_label, sanitize_sequence)
 from matplotlib.compat import subprocess
-from matplotlib.rcsetup import (defaultParams,
-                                validate_backend,
-                                cycler)
+from matplotlib.rcsetup import defaultParams, validate_backend, cycler
 
 import numpy
 from six.moves.urllib.request import urlopen
@@ -1225,7 +1221,7 @@ def rc(group, **kwargs):
         'aa':  'antialiased',
         }
 
-    if is_string_like(group):
+    if isinstance(group, six.string_types):
         group = (group,)
     for g in group:
         for k, v in six.iteritems(kwargs):
diff --git a/lib/matplotlib/animation.py b/lib/matplotlib/animation.py
index 03bc155c63a6..244af8568230 100644
--- a/lib/matplotlib/animation.py
+++ b/lib/matplotlib/animation.py
@@ -38,7 +38,7 @@
 import contextlib
 import tempfile
 import warnings
-from matplotlib.cbook import iterable, is_string_like, deprecated
+from matplotlib.cbook import iterable, deprecated
 from matplotlib.compat import subprocess
 from matplotlib import verbose
 from matplotlib import rcParams, rcParamsDefault, rc_context
@@ -1023,7 +1023,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`,
         # to use
         if writer is None:
             writer = rcParams['animation.writer']
-        elif (not is_string_like(writer) and
+        elif (not isinstance(writer, six.string_types) and
                 any(arg is not None
                     for arg in (fps, codec, bitrate, extra_args, metadata))):
             raise RuntimeError('Passing in values for arguments '
@@ -1068,7 +1068,7 @@ class to use, such as 'ffmpeg' or 'mencoder'. If `None`,
 
         # If we have the name of a writer, instantiate an instance of the
         # registered class.
-        if is_string_like(writer):
+        if isinstance(writer, six.string_types):
             if writer in writers.avail:
                 writer = writers[writer](fps, codec, bitrate,
                                          extra_args=extra_args,
diff --git a/lib/matplotlib/axes/_axes.py b/lib/matplotlib/axes/_axes.py
index f3930470edec..47b4aa8766ca 100644
--- a/lib/matplotlib/axes/_axes.py
+++ b/lib/matplotlib/axes/_axes.py
@@ -16,9 +16,8 @@
 from matplotlib import _preprocess_data
 
 import matplotlib.cbook as cbook
-from matplotlib.cbook import (mplDeprecation, STEP_LOOKUP_MAP,
-                              iterable, is_string_like,
-                              safe_first_element)
+from matplotlib.cbook import (
+    mplDeprecation, STEP_LOOKUP_MAP, iterable, safe_first_element)
 import matplotlib.collections as mcoll
 import matplotlib.colors as mcolors
 import matplotlib.contour as mcontour
@@ -2662,7 +2661,7 @@ def get_next_color():
             if autopct is not None:
                 xt = x + pctdistance * radius * math.cos(thetam)
                 yt = y + pctdistance * radius * math.sin(thetam)
-                if is_string_like(autopct):
+                if isinstance(autopct, six.string_types):
                     s = autopct % (100. * frac)
                 elif callable(autopct):
                     s = autopct(100. * frac)
@@ -5472,8 +5471,8 @@ def pcolor(self, *args, **kwargs):
         # makes artifacts that are often disturbing.
         if 'antialiased' in kwargs:
             kwargs['antialiaseds'] = kwargs.pop('antialiased')
-        if 'antialiaseds' not in kwargs and (is_string_like(ec) and
-                                             ec.lower() == "none"):
+        if 'antialiaseds' not in kwargs and (
+                isinstance(ec, six.string_types) and ec.lower() == "none"):
             kwargs['antialiaseds'] = False
 
         kwargs.setdefault('snap', False)
@@ -6380,7 +6379,7 @@ def hist(self, x, bins=None, range=None, normed=False, weights=None,
 
         if label is None:
             labels = [None]
-        elif is_string_like(label):
+        elif isinstance(label, six.string_types):
             labels = [label]
         else:
             labels = [six.text_type(lab) for lab in label]
diff --git a/lib/matplotlib/axes/_base.py b/lib/matplotlib/axes/_base.py
index bf44d1176cc7..950ef7953881 100644
--- a/lib/matplotlib/axes/_base.py
+++ b/lib/matplotlib/axes/_base.py
@@ -352,7 +352,7 @@ def _makefill(self, x, y, kw, kwargs):
 
     def _plot_args(self, tup, kwargs):
         ret = []
-        if len(tup) > 1 and is_string_like(tup[-1]):
+        if len(tup) > 1 and isinstance(tup[-1], six.string_types):
             linestyle, marker, color = _process_plot_format(tup[-1])
             tup = tup[:-1]
         elif len(tup) == 3:
@@ -398,7 +398,7 @@ def _plot_args(self, tup, kwargs):
     def _grab_next_args(self, *args, **kwargs):
         while args:
             this, args = args[:2], args[2:]
-            if args and is_string_like(args[0]):
+            if args and isinstance(args[0], six.string_types):
                 this += args[0],
                 args = args[1:]
             for seg in self._plot_args(this, kwargs):
@@ -1281,7 +1281,7 @@ def set_aspect(self, aspect, adjustable=None, anchor=None):
           etc.
           =====   =====================
         """
-        if cbook.is_string_like(aspect) and aspect in ('equal', 'auto'):
+        if isinstance(aspect, six.string_types) and aspect in ('equal', 'auto'):
             self._aspect = aspect
         else:
             self._aspect = float(aspect)  # raise ValueError if necessary
@@ -1556,7 +1556,7 @@ def axis(self, *v, **kwargs):
 
         emit = kwargs.get('emit', True)
 
-        if len(v) == 1 and is_string_like(v[0]):
+        if len(v) == 1 and isinstance(v[0], six.string_types):
             s = v[0].lower()
             if s == 'on':
                 self.set_axis_on()
diff --git a/lib/matplotlib/backend_bases.py b/lib/matplotlib/backend_bases.py
index 01b41e419f11..6f438b9619fe 100644
--- a/lib/matplotlib/backend_bases.py
+++ b/lib/matplotlib/backend_bases.py
@@ -129,7 +129,7 @@ def get_registered_canvas_class(format):
     if format not in _default_backends:
         return None
     backend_class = _default_backends[format]
-    if cbook.is_string_like(backend_class):
+    if isinstance(backend_class, six.string_types):
         backend_class = importlib.import_module(backend_class).FigureCanvas
         _default_backends[format] = backend_class
     return backend_class
@@ -2090,11 +2090,11 @@ def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
 
         if format is None:
             # get format from filename, or from backend's default filetype
-            if cbook.is_string_like(filename):
+            if isinstance(filename, six.string_types):
                 format = os.path.splitext(filename)[1][1:]
             if format is None or format == '':
                 format = self.get_default_filetype()
-                if cbook.is_string_like(filename):
+                if isinstance(filename, six.string_types):
                     filename = filename.rstrip('.') + '.' + format
         format = format.lower()
 
diff --git a/lib/matplotlib/backends/backend_agg.py b/lib/matplotlib/backends/backend_agg.py
index 8f3bce4396b5..0d7cfeac5965 100644
--- a/lib/matplotlib/backends/backend_agg.py
+++ b/lib/matplotlib/backends/backend_agg.py
@@ -31,7 +31,7 @@
 from matplotlib import verbose, rcParams, __version__
 from matplotlib.backend_bases import (RendererBase, FigureManagerBase,
                                       FigureCanvasBase)
-from matplotlib.cbook import is_string_like, maxdict, restrict_dict
+from matplotlib.cbook import maxdict, restrict_dict
 from matplotlib.figure import Figure
 from matplotlib.font_manager import findfont, get_font
 from matplotlib.ft2font import (LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING,
@@ -530,7 +530,7 @@ def print_raw(self, filename_or_obj, *args, **kwargs):
         renderer = self.get_renderer()
         original_dpi = renderer.dpi
         renderer.dpi = self.figure.dpi
-        if is_string_like(filename_or_obj):
+        if isinstance(filename_or_obj, six.string_types):
             fileobj = open(filename_or_obj, 'wb')
             close = True
         else:
@@ -549,7 +549,7 @@ def print_png(self, filename_or_obj, *args, **kwargs):
         renderer = self.get_renderer()
         original_dpi = renderer.dpi
         renderer.dpi = self.figure.dpi
-        if is_string_like(filename_or_obj):
+        if isinstance(filename_or_obj, six.string_types):
             filename_or_obj = open(filename_or_obj, 'wb')
             close = True
         else:
diff --git a/lib/matplotlib/backends/backend_cairo.py b/lib/matplotlib/backends/backend_cairo.py
index e49eb9b1a342..7396452fa0e3 100644
--- a/lib/matplotlib/backends/backend_cairo.py
+++ b/lib/matplotlib/backends/backend_cairo.py
@@ -35,7 +35,8 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
     try:
         import cairo
     except ImportError:
-        raise ImportError("Cairo backend requires that cairocffi or pycairo is installed.")
+        raise ImportError("Cairo backend requires that cairocffi or pycairo "
+                          "is installed.")
     else:
         HAS_CAIRO_CFFI = False
 else:
@@ -49,9 +50,8 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
 backend_version = cairo.version
 del _version_required
 
-from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\
-     FigureManagerBase, FigureCanvasBase
-from matplotlib.cbook        import is_string_like
+from matplotlib.backend_bases import (
+    RendererBase, GraphicsContextBase, FigureManagerBase, FigureCanvasBase)
 from matplotlib.figure       import Figure
 from matplotlib.mathtext     import MathTextParser
 from matplotlib.path         import Path
@@ -555,7 +555,7 @@ def _save (self, fo, format, **kwargs):
                 raise RuntimeError ('cairo has not been compiled with SVG '
                                     'support enabled')
             if format == 'svgz':
-                if is_string_like(fo):
+                if isinstance(fo, six.string_types):
                     fo = gzip.GzipFile(fo, 'wb')
                 else:
                     fo = gzip.GzipFile(None, 'wb', fileobj=fo)
diff --git a/lib/matplotlib/backends/backend_gdk.py b/lib/matplotlib/backends/backend_gdk.py
index 23133503df75..36583cf44402 100644
--- a/lib/matplotlib/backends/backend_gdk.py
+++ b/lib/matplotlib/backends/backend_gdk.py
@@ -26,7 +26,7 @@ def fn_name(): return sys._getframe(1).f_code.co_name
 from matplotlib._pylab_helpers import Gcf
 from matplotlib.backend_bases import RendererBase, GraphicsContextBase, \
      FigureManagerBase, FigureCanvasBase
-from matplotlib.cbook import is_string_like, restrict_dict, warn_deprecated
+from matplotlib.cbook import restrict_dict, warn_deprecated
 from matplotlib.figure import Figure
 from matplotlib.mathtext import MathTextParser
 from matplotlib.transforms import Affine2D
diff --git a/lib/matplotlib/backends/backend_gtk.py b/lib/matplotlib/backends/backend_gtk.py
index ab27b0e913ed..02fc2a22b762 100644
--- a/lib/matplotlib/backends/backend_gtk.py
+++ b/lib/matplotlib/backends/backend_gtk.py
@@ -34,7 +34,7 @@ def fn_name(): return sys._getframe(1).f_code.co_name
 from matplotlib.backend_bases import ShowBase
 
 from matplotlib.backends.backend_gdk import RendererGDK, FigureCanvasGDK
-from matplotlib.cbook import is_string_like, is_writable_file_like
+from matplotlib.cbook import is_writable_file_like
 from matplotlib.figure import Figure
 from matplotlib.widgets import SubplotTool
 from matplotlib.cbook import warn_deprecated
@@ -490,7 +490,7 @@ def _print_image(self, filename, format, *args, **kwargs):
 
             options['quality'] = str(options['quality'])
 
-        if is_string_like(filename):
+        if isinstance(filename, six.string_types):
             try:
                 pixbuf.save(filename, format, options=options)
             except gobject.GError as exc:
@@ -908,7 +908,7 @@ class DialogLineprops(object):
     linestyled = {s: i for i, s in enumerate(linestyles)}
 
     markers =  [m for m in markers.MarkerStyle.markers
-                if cbook.is_string_like(m)]
+                if isinstance(m, six.string_types)]
     markerd = {s: i for i, s in enumerate(markers)}
 
     def __init__(self, lines):
@@ -1068,7 +1068,7 @@ def error_msg_gtk(msg, parent=None):
         if parent.flags() & gtk.TOPLEVEL == 0:
             parent = None
 
-    if not is_string_like(msg):
+    if not isinstance(msg, six.string_types):
         msg = ','.join(map(str,msg))
 
     dialog = gtk.MessageDialog(
diff --git a/lib/matplotlib/backends/backend_gtk3.py b/lib/matplotlib/backends/backend_gtk3.py
index b42f3c5ef2d1..c4b007fdc97c 100644
--- a/lib/matplotlib/backends/backend_gtk3.py
+++ b/lib/matplotlib/backends/backend_gtk3.py
@@ -35,7 +35,7 @@ def fn_name(): return sys._getframe(1).f_code.co_name
 from matplotlib.backend_managers import ToolManager
 from matplotlib import backend_tools
 
-from matplotlib.cbook import is_string_like, is_writable_file_like
+from matplotlib.cbook import is_writable_file_like
 from matplotlib.figure import Figure
 from matplotlib.widgets import SubplotTool
 
@@ -954,7 +954,7 @@ def error_msg_gtk(msg, parent=None):
         if not parent.is_toplevel():
             parent = None
 
-    if not is_string_like(msg):
+    if not isinstance(msg, six.string_types):
         msg = ','.join(map(str,msg))
 
     dialog = Gtk.MessageDialog(
diff --git a/lib/matplotlib/backends/backend_pdf.py b/lib/matplotlib/backends/backend_pdf.py
index abe502ab8b25..e14aadcb48bd 100644
--- a/lib/matplotlib/backends/backend_pdf.py
+++ b/lib/matplotlib/backends/backend_pdf.py
@@ -34,7 +34,7 @@
 from matplotlib.backend_bases import (RendererBase, GraphicsContextBase,
                                       FigureManagerBase, FigureCanvasBase)
 from matplotlib.backends.backend_mixed import MixedModeRenderer
-from matplotlib.cbook import (Bunch, is_string_like, get_realpath_and_stat,
+from matplotlib.cbook import (Bunch, get_realpath_and_stat,
                               is_writable_file_like, maxdict)
 from matplotlib.figure import Figure
 from matplotlib.font_manager import findfont, is_opentype_cff_font, get_font
@@ -434,7 +434,7 @@ def __init__(self, filename, metadata=None):
         self.passed_in_file_object = False
         self.original_file_like = None
         self.tell_base = 0
-        if is_string_like(filename):
+        if isinstance(filename, six.string_types):
             fh = open(filename, 'wb')
         elif is_writable_file_like(filename):
             try:
@@ -1564,6 +1564,9 @@ def writeXref(self):
     def writeInfoDict(self):
         """Write out the info dictionary, checking it for good form"""
 
+        def is_string_like(x):
+            return isinstance(x, six.string_types)
+
         def is_date(x):
             return isinstance(x, datetime)
 
diff --git a/lib/matplotlib/backends/backend_pgf.py b/lib/matplotlib/backends/backend_pgf.py
index 51d8fa2d1f86..ac0c2d6c0ec0 100644
--- a/lib/matplotlib/backends/backend_pgf.py
+++ b/lib/matplotlib/backends/backend_pgf.py
@@ -25,7 +25,7 @@
 from matplotlib.text import Text
 from matplotlib.path import Path
 from matplotlib import _png, rcParams
-from matplotlib.cbook import is_string_like, is_writable_file_like
+from matplotlib.cbook import is_writable_file_like
 from matplotlib.compat import subprocess
 from matplotlib.compat.subprocess import check_output
 
@@ -859,7 +859,7 @@ def print_pgf(self, fname_or_fh, *args, **kwargs):
             return
 
         # figure out where the pgf is to be written to
-        if is_string_like(fname_or_fh):
+        if isinstance(fname_or_fh, six.string_types):
             with codecs.open(fname_or_fh, "w", encoding="utf-8") as fh:
                 self._print_pgf_to_fh(fh, *args, **kwargs)
         elif is_writable_file_like(fname_or_fh):
@@ -923,7 +923,7 @@ def print_pdf(self, fname_or_fh, *args, **kwargs):
             return
 
         # figure out where the pdf is to be written to
-        if is_string_like(fname_or_fh):
+        if isinstance(fname_or_fh, six.string_types):
             with open(fname_or_fh, "wb") as fh:
                 self._print_pdf_to_fh(fh, *args, **kwargs)
         elif is_writable_file_like(fname_or_fh):
@@ -959,7 +959,7 @@ def print_png(self, fname_or_fh, *args, **kwargs):
             self._print_pgf_to_fh(None, *args, **kwargs)
             return
 
-        if is_string_like(fname_or_fh):
+        if isinstance(fname_or_fh, six.string_types):
             with open(fname_or_fh, "wb") as fh:
                 self._print_png_to_fh(fh, *args, **kwargs)
         elif is_writable_file_like(fname_or_fh):
diff --git a/lib/matplotlib/backends/backend_ps.py b/lib/matplotlib/backends/backend_ps.py
index 72d9d6f0f39f..5fc8aef8d3ed 100644
--- a/lib/matplotlib/backends/backend_ps.py
+++ b/lib/matplotlib/backends/backend_ps.py
@@ -15,11 +15,11 @@ def _fn_name(): return sys._getframe(1).f_code.co_name
 from tempfile import mkstemp
 from matplotlib import verbose, __version__, rcParams, checkdep_ghostscript
 from matplotlib.afm import AFM
-from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\
-     FigureManagerBase, FigureCanvasBase
+from matplotlib.backend_bases import (RendererBase, GraphicsContextBase,
+                                      FigureManagerBase, FigureCanvasBase)
 
-from matplotlib.cbook import is_string_like, get_realpath_and_stat, \
-    is_writable_file_like, maxdict, file_requires_unicode
+from matplotlib.cbook import (get_realpath_and_stat, is_writable_file_like,
+                              maxdict, file_requires_unicode)
 from matplotlib.compat.subprocess import subprocess
 from matplotlib.figure import Figure
 
@@ -141,10 +141,10 @@ def _get_papertype(w, h):
         return 'a0'
 
 def _num_to_str(val):
-    if is_string_like(val): return val
+    if isinstance(val, six.string_types): return val
 
     ival = int(val)
-    if val==ival: return str(ival)
+    if val == ival: return str(ival)
 
     s = "%1.3f"%val
     s = s.rstrip("0")
@@ -977,7 +977,7 @@ def _print_figure(self, outfile, format, dpi=72, facecolor='w', edgecolor='w',
         """
         isEPSF = format == 'eps'
         passed_in_file_object = False
-        if is_string_like(outfile):
+        if isinstance(outfile, six.string_types):
             title = outfile
         elif is_writable_file_like(outfile):
             title = None
@@ -1220,7 +1220,7 @@ def _print_figure_tex(self, outfile, format, dpi, facecolor, edgecolor,
         the key 'Creator' is used.
         """
         isEPSF = format == 'eps'
-        if is_string_like(outfile):
+        if isinstance(outfile, six.string_types):
             title = outfile
         elif is_writable_file_like(outfile):
             title = None
diff --git a/lib/matplotlib/backends/backend_qt4.py b/lib/matplotlib/backends/backend_qt4.py
index d19c0433be1b..ef591900ebad 100644
--- a/lib/matplotlib/backends/backend_qt4.py
+++ b/lib/matplotlib/backends/backend_qt4.py
@@ -10,7 +10,6 @@
 
 import matplotlib
 
-from matplotlib.cbook import is_string_like
 from matplotlib.backend_bases import FigureManagerBase
 from matplotlib.backend_bases import FigureCanvasBase
 from matplotlib.backend_bases import NavigationToolbar2
diff --git a/lib/matplotlib/backends/backend_qt5.py b/lib/matplotlib/backends/backend_qt5.py
index 9d21d099e25f..cfd6f1196a01 100644
--- a/lib/matplotlib/backends/backend_qt5.py
+++ b/lib/matplotlib/backends/backend_qt5.py
@@ -10,7 +10,6 @@
 
 import matplotlib
 
-from matplotlib.cbook import is_string_like
 from matplotlib.backend_bases import FigureManagerBase
 from matplotlib.backend_bases import FigureCanvasBase
 from matplotlib.backend_bases import NavigationToolbar2
@@ -865,7 +864,7 @@ def reset(self):
 
 
 def error_msg_qt(msg, parent=None):
-    if not is_string_like(msg):
+    if not isinstance(msg, six.string_types):
         msg = ','.join(map(str, msg))
 
     QtWidgets.QMessageBox.warning(None, "Matplotlib",
diff --git a/lib/matplotlib/backends/backend_svg.py b/lib/matplotlib/backends/backend_svg.py
index 4f6785b7fdc8..0d1506c68dfc 100644
--- a/lib/matplotlib/backends/backend_svg.py
+++ b/lib/matplotlib/backends/backend_svg.py
@@ -18,7 +18,7 @@
 from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\
      FigureManagerBase, FigureCanvasBase
 from matplotlib.backends.backend_mixed import MixedModeRenderer
-from matplotlib.cbook import is_string_like, is_writable_file_like, maxdict
+from matplotlib.cbook import is_writable_file_like, maxdict
 from matplotlib.colors import rgb2hex
 from matplotlib.figure import Figure
 from matplotlib.font_manager import findfont, FontProperties, get_font
@@ -1187,7 +1187,7 @@ class FigureCanvasSVG(FigureCanvasBase):
     fixed_dpi = 72
 
     def print_svg(self, filename, *args, **kwargs):
-        if is_string_like(filename):
+        if isinstance(filename, six.string_types):
             with io.open(filename, 'w', encoding='utf-8') as svgwriter:
                 return self._print_svg(filename, svgwriter, **kwargs)
 
@@ -1222,7 +1222,7 @@ def print_svg(self, filename, *args, **kwargs):
         return result
 
     def print_svgz(self, filename, *args, **kwargs):
-        if is_string_like(filename):
+        if isinstance(filename, six.string_types):
             options = dict(filename=filename)
         elif is_writable_file_like(filename):
             options = dict(fileobj=filename)
diff --git a/lib/matplotlib/backends/backend_tkagg.py b/lib/matplotlib/backends/backend_tkagg.py
index 6e92909d536a..cd2373bf4fe8 100644
--- a/lib/matplotlib/backends/backend_tkagg.py
+++ b/lib/matplotlib/backends/backend_tkagg.py
@@ -16,7 +16,6 @@
 import matplotlib.backends.windowing as windowing
 
 import matplotlib
-from matplotlib.cbook import is_string_like
 from matplotlib.backend_bases import RendererBase, GraphicsContextBase
 from matplotlib.backend_bases import FigureManagerBase, FigureCanvasBase
 from matplotlib.backend_bases import NavigationToolbar2, cursors, TimerBase
@@ -52,7 +51,7 @@
 
 def raise_msg_to_str(msg):
     """msg is a return arg from a raise.  Join with new lines"""
-    if not is_string_like(msg):
+    if not isinstance(msg, six.string_types):
         msg = '\n'.join(map(str, msg))
     return msg
 
diff --git a/lib/matplotlib/backends/backend_wx.py b/lib/matplotlib/backends/backend_wx.py
index b050bb5f7299..aa3f97fddcc5 100644
--- a/lib/matplotlib/backends/backend_wx.py
+++ b/lib/matplotlib/backends/backend_wx.py
@@ -35,8 +35,7 @@
 from matplotlib.backend_bases import _has_pil
 
 from matplotlib._pylab_helpers import Gcf
-from matplotlib.cbook import (is_string_like, is_writable_file_like,
-                              warn_deprecated)
+from matplotlib.cbook import is_writable_file_like, warn_deprecated
 from matplotlib.figure import Figure
 from matplotlib.path import Path
 from matplotlib.transforms import Affine2D
@@ -115,7 +114,7 @@ def error_msg_wx(msg, parent=None):
 
 def raise_msg_to_str(msg):
     """msg is a return arg from a raise.  Join with new lines"""
-    if not is_string_like(msg):
+    if not isinstance(msg, six.string_types):
         msg = '\n'.join(map(str, msg))
     return msg
 
@@ -910,7 +909,7 @@ def _print_image(self, filename, filetype, *args, **kwargs):
 
         # Now that we have rendered into the bitmap, save it
         # to the appropriate file type and clean up
-        if is_string_like(filename):
+        if isinstance(filename, six.string_types):
             if not image.SaveFile(filename, filetype):
                 DEBUG_MSG('print_figure() file save error', 4, self)
                 raise RuntimeError(
diff --git a/lib/matplotlib/blocking_input.py b/lib/matplotlib/blocking_input.py
index d7035221e8eb..516cbeec9bdb 100644
--- a/lib/matplotlib/blocking_input.py
+++ b/lib/matplotlib/blocking_input.py
@@ -27,7 +27,6 @@
 
 import six
 from matplotlib import verbose
-from matplotlib.cbook import is_sequence_of_strings
 import matplotlib.lines as mlines
 
 import warnings
@@ -40,8 +39,6 @@ class BlockingInput(object):
     """
     def __init__(self, fig, eventslist=()):
         self.fig = fig
-        if not is_sequence_of_strings(eventslist):
-            raise ValueError("Requires a sequence of event name strings")
         self.eventslist = eventslist
 
     def on_event(self, event):
diff --git a/lib/matplotlib/cbook/__init__.py b/lib/matplotlib/cbook/__init__.py
index 2bec9f2be6a4..a246669ad43a 100644
--- a/lib/matplotlib/cbook/__init__.py
+++ b/lib/matplotlib/cbook/__init__.py
@@ -494,12 +494,14 @@ def iterable(obj):
     return True
 
 
+@deprecated('2.1')
 def is_string_like(obj):
     """Return True if *obj* looks like a string"""
     # (np.str_ == np.unicode_ on Py3).
     return isinstance(obj, (six.string_types, np.str_, np.unicode_))
 
 
+@deprecated('2.1')
 def is_sequence_of_strings(obj):
     """Returns true if *obj* is iterable and contains strings"""
     if not iterable(obj):
@@ -546,7 +548,7 @@ def file_requires_unicode(x):
 @deprecated('2.1')
 def is_scalar(obj):
     """return true if *obj* is not string like and is not iterable"""
-    return not is_string_like(obj) and not iterable(obj)
+    return not isinstance(obj, six.string_types) and not iterable(obj)
 
 
 def is_numlike(obj):
@@ -560,7 +562,7 @@ def to_filehandle(fname, flag='rU', return_opened=False):
     files is automatic, if the filename ends in .gz.  *flag* is a
     read/write flag for :func:`file`
     """
-    if is_string_like(fname):
+    if isinstance(fname, six.string_types):
         if fname.endswith('.gz'):
             # get rid of 'U' in flag for gzipped files.
             flag = flag.replace('U', '')
@@ -585,12 +587,12 @@ def to_filehandle(fname, flag='rU', return_opened=False):
 
 def is_scalar_or_string(val):
     """Return whether the given object is a scalar or string like."""
-    return is_string_like(val) or not iterable(val)
+    return isinstance(val, six.string_types) or not iterable(val)
 
 
 def _string_to_bool(s):
     """Parses the string argument as a boolean"""
-    if not is_string_like(s):
+    if not isinstance(s, six.string_types):
         return bool(s)
     if s.lower() in ['on', 'true']:
         return True
@@ -1219,10 +1221,10 @@ def finddir(o, match, case=False):
     is True require an exact case match.
     """
     if case:
-        names = [(name, name) for name in dir(o) if is_string_like(name)]
+        names = [(name, name) for name in dir(o) if isinstance(name, six.string_types)]
     else:
         names = [(name.lower(), name) for name in dir(o)
-                 if is_string_like(name)]
+                 if isinstance(name, six.string_types)]
         match = match.lower()
     return [orig for name, orig in names if name.find(match) >= 0]
 
@@ -1590,13 +1592,14 @@ def delete_masked_points(*args):
     """
     if not len(args):
         return ()
-    if (is_string_like(args[0]) or not iterable(args[0])):
+    if (isinstance(args[0], six.string_types) or not iterable(args[0])):
         raise ValueError("First argument must be a sequence")
     nrecs = len(args[0])
     margs = []
     seqlist = [False] * len(args)
     for i, x in enumerate(args):
-        if (not is_string_like(x)) and iterable(x) and len(x) == nrecs:
+        if ((not isinstance(x, six.string_types)) and iterable(x)
+                and len(x) == nrecs):
             seqlist[i] = True
             if isinstance(x, np.ma.MaskedArray):
                 if x.ndim > 1:
diff --git a/lib/matplotlib/cm.py b/lib/matplotlib/cm.py
index 10684da79157..bdf3e1575653 100644
--- a/lib/matplotlib/cm.py
+++ b/lib/matplotlib/cm.py
@@ -124,7 +124,7 @@ def register_cmap(name=None, cmap=None, data=None, lut=None):
         except AttributeError:
             raise ValueError("Arguments must include a name or a Colormap")
 
-    if not cbook.is_string_like(name):
+    if not isinstance(name, six.string_types):
         raise ValueError("Colormap name must be a string")
 
     if isinstance(cmap, colors.Colormap):
diff --git a/lib/matplotlib/collections.py b/lib/matplotlib/collections.py
index 1090ed88f39f..e7e5a7862ccd 100644
--- a/lib/matplotlib/collections.py
+++ b/lib/matplotlib/collections.py
@@ -511,7 +511,7 @@ def set_linestyle(self, ls):
             The line style.
         """
         try:
-            if cbook.is_string_like(ls) and cbook.is_hashable(ls):
+            if isinstance(ls, six.string_types) and cbook.is_hashable(ls):
                 ls = cbook.ls_mapper.get(ls, ls)
                 dashes = [mlines._get_dash_pattern(ls)]
             else:
diff --git a/lib/matplotlib/colorbar.py b/lib/matplotlib/colorbar.py
index be9311926f17..a080eb59247c 100644
--- a/lib/matplotlib/colorbar.py
+++ b/lib/matplotlib/colorbar.py
@@ -317,7 +317,7 @@ def __init__(self, ax, cmap=None,
                                         linthresh=self.norm.linthresh)
             else:
                 self.formatter = ticker.ScalarFormatter()
-        elif cbook.is_string_like(format):
+        elif isinstance(format, six.string_types):
             self.formatter = ticker.FormatStrFormatter(format)
         else:
             self.formatter = format  # Assume it is a Formatter
diff --git a/lib/matplotlib/colors.py b/lib/matplotlib/colors.py
index a97744611a3d..168d1c8797cd 100644
--- a/lib/matplotlib/colors.py
+++ b/lib/matplotlib/colors.py
@@ -696,7 +696,7 @@ def from_list(name, colors, N=256, gamma=1.0):
             raise ValueError('colors must be iterable')
 
         if (isinstance(colors[0], Sized) and len(colors[0]) == 2
-                and not cbook.is_string_like(colors[0])):
+                and not isinstance(colors[0], six.string_types)):
             # List of value, color pairs
             vals, colors = zip(*colors)
         else:
@@ -789,7 +789,7 @@ def __init__(self, colors, name='from_list', N=None):
         if N is None:
             N = len(self.colors)
         else:
-            if (cbook.is_string_like(self.colors) and
+            if (isinstance(self.colors, six.string_types) and
                     cbook.is_hashable(self.colors)):
                 self.colors = [self.colors] * N
                 self.monochrome = True
diff --git a/lib/matplotlib/contour.py b/lib/matplotlib/contour.py
index ab9b1b1cedf3..c3c10a293877 100644
--- a/lib/matplotlib/contour.py
+++ b/lib/matplotlib/contour.py
@@ -265,7 +265,7 @@ def get_label_width(self, lev, fmt, fsize):
         """
         Return the width of the label in points.
         """
-        if not cbook.is_string_like(lev):
+        if not isinstance(lev, six.string_types):
             lev = self.get_text(lev, fmt)
 
         lev, ismath = text.Text.is_math_text(lev)
@@ -321,7 +321,7 @@ def set_label_props(self, label, text, color):
 
     def get_text(self, lev, fmt):
         "get the text of the label"
-        if cbook.is_string_like(lev):
+        if isinstance(lev, six.string_types):
             return lev
         else:
             if isinstance(fmt, dict):
@@ -1300,7 +1300,7 @@ def _process_linestyles(self):
                     if lev < eps:
                         tlinestyles[i] = neg_ls
         else:
-            if cbook.is_string_like(linestyles):
+            if isinstance(linestyles, six.string_types):
                 tlinestyles = [linestyles] * Nlev
             elif cbook.iterable(linestyles):
                 tlinestyles = list(linestyles)
diff --git a/lib/matplotlib/dates.py b/lib/matplotlib/dates.py
index 65a7d249f45e..b7f1ad8fe0f6 100644
--- a/lib/matplotlib/dates.py
+++ b/lib/matplotlib/dates.py
@@ -330,7 +330,7 @@ def datestr2num(d, default=None):
     default : datetime instance
         The default date to use when fields are missing in `d`.
     """
-    if cbook.is_string_like(d):
+    if isinstance(d, six.string_types):
         dt = dateutil.parser.parse(d, default=default)
         return date2num(dt)
     else:
diff --git a/lib/matplotlib/font_manager.py b/lib/matplotlib/font_manager.py
index 38c573b7e5ef..e66fed716ae0 100644
--- a/lib/matplotlib/font_manager.py
+++ b/lib/matplotlib/font_manager.py
@@ -56,7 +56,6 @@
 
 import matplotlib
 from matplotlib import afm, cbook, ft2font, rcParams, get_cachedir
-from matplotlib.cbook import is_string_like
 from matplotlib.compat import subprocess
 from matplotlib.fontconfig_pattern import (
     parse_fontconfig_pattern, generate_fontconfig_pattern)
@@ -234,7 +233,7 @@ def win32InstalledFonts(directory=None, fontext='ttf'):
             for j in range(winreg.QueryInfoKey(local)[1]):
                 try:
                     key, direc, any = winreg.EnumValue( local, j)
-                    if not is_string_like(direc):
+                    if not isinstance(direc, six.string_types):
                         continue
                     if not os.path.dirname(direc):
                         direc = os.path.join(directory, direc)
@@ -688,7 +687,7 @@ def __init__(self,
             self.__dict__.update(_init.__dict__)
             return
 
-        if is_string_like(family):
+        if isinstance(family, six.string_types):
             # Treat family as a fontconfig pattern if it is the only
             # parameter provided.
             if (style is None and
@@ -985,7 +984,7 @@ def json_load(filename):
 
 
 def _normalize_font_family(family):
-    if is_string_like(family):
+    if isinstance(family, six.string_types):
         family = [six.text_type(family)]
     elif isinstance(family, Iterable):
         family = [six.text_type(f) for f in family]
@@ -1402,7 +1401,7 @@ def fc_match(pattern, fontext):
     _fc_match_cache = {}
 
     def findfont(prop, fontext='ttf'):
-        if not is_string_like(prop):
+        if not isinstance(prop, six.string_types):
             prop = prop.get_fontconfig_pattern()
         cached = _fc_match_cache.get(prop)
         if cached is not None:
diff --git a/lib/matplotlib/image.py b/lib/matplotlib/image.py
index aa62c700fa9c..d22e2e255381 100644
--- a/lib/matplotlib/image.py
+++ b/lib/matplotlib/image.py
@@ -1256,7 +1256,7 @@ def pilread(fname):
 
     handlers = {'png': _png.read_png, }
     if format is None:
-        if cbook.is_string_like(fname):
+        if isinstance(fname, six.string_types):
             parsed = urlparse(fname)
             # If the string is a URL, assume png
             if len(parsed.scheme) > 1:
@@ -1285,7 +1285,7 @@ def pilread(fname):
     # To handle Unicode filenames, we pass a file object to the PNG
     # reader extension, since Python handles them quite well, but it's
     # tricky in C.
-    if cbook.is_string_like(fname):
+    if isinstance(fname, six.string_types):
         parsed = urlparse(fname)
         # If fname is a URL, download the data
         if len(parsed.scheme) > 1:
diff --git a/lib/matplotlib/legend.py b/lib/matplotlib/legend.py
index 5165db5c824d..21f87fa3a843 100644
--- a/lib/matplotlib/legend.py
+++ b/lib/matplotlib/legend.py
@@ -33,7 +33,7 @@
 
 from matplotlib import rcParams
 from matplotlib.artist import Artist, allow_rasterization
-from matplotlib.cbook import is_string_like, silent_list, is_hashable
+from matplotlib.cbook import silent_list, is_hashable
 from matplotlib.font_manager import FontProperties
 from matplotlib.lines import Line2D
 from matplotlib.patches import Patch, Rectangle, Shadow, FancyBboxPatch
@@ -317,7 +317,7 @@ def __init__(self, parent, handles, labels,
             loc = rcParams["legend.loc"]
             if not self.isaxes and loc in [0, 'best']:
                 loc = 'upper right'
-        if is_string_like(loc):
+        if isinstance(loc, six.string_types):
             if loc not in self.codes:
                 if self.isaxes:
                     warnings.warn('Unrecognized location "%s". Falling back '
diff --git a/lib/matplotlib/lines.py b/lib/matplotlib/lines.py
index abdca5e31144..c34307f5e3f8 100644
--- a/lib/matplotlib/lines.py
+++ b/lib/matplotlib/lines.py
@@ -16,8 +16,7 @@
 from . import artist, colors as mcolors, docstring, rcParams
 from .artist import Artist, allow_rasterization
 from .cbook import (
-    iterable, is_string_like, is_numlike, ls_mapper, ls_mapper_r, is_hashable,
-    STEP_LOOKUP_MAP)
+    iterable, is_numlike, ls_mapper, ls_mapper_r, is_hashable, STEP_LOOKUP_MAP)
 from .markers import MarkerStyle
 from .path import Path
 from .transforms import Bbox, TransformedPath, IdentityTransform
@@ -37,7 +36,7 @@ def _get_dash_pattern(style):
 
     """
     # go from short hand -> full strings
-    if is_string_like(style) and is_hashable(style):
+    if isinstance(style, six.string_types) and is_hashable(style):
         style = ls_mapper.get(style, style)
     # un-dashed styles
     if style in ['solid', 'None']:
@@ -355,7 +354,7 @@ def __init__(self, xdata, ydata,
         if solid_joinstyle is None:
             solid_joinstyle = rcParams['lines.solid_joinstyle']
 
-        if is_string_like(linestyle):
+        if isinstance(linestyle, six.string_types):
             ds, ls = self._split_drawstyle_linestyle(linestyle)
             if ds is not None and drawstyle is not None and ds != drawstyle:
                 raise ValueError("Inconsistent drawstyle ({0!r}) and "
@@ -806,14 +805,15 @@ def draw(self, renderer):
             rgbaFace = self._get_rgba_face()
             rgbaFaceAlt = self._get_rgba_face(alt=True)
             edgecolor = self.get_markeredgecolor()
-            if is_string_like(edgecolor) and edgecolor.lower() == 'none':
+            if (isinstance(edgecolor, six.string_types)
+                    and edgecolor.lower() == 'none'):
                 gc.set_linewidth(0)
                 gc.set_foreground(rgbaFace, isRGBA=True)
             else:
                 gc.set_foreground(edgecolor)
                 gc.set_linewidth(self._markeredgewidth)
                 mec = self._markeredgecolor
-                if (is_string_like(mec) and mec == 'auto' and
+                if (isinstance(mec, six.string_types) and mec == 'auto' and
                         rgbaFace is not None):
                     gc.set_alpha(rgbaFace[3])
                 else:
@@ -840,7 +840,7 @@ def draw(self, renderer):
                 marker_trans = marker.get_transform()
                 w = renderer.points_to_pixels(self._markersize)
 
-                if (is_string_like(marker.get_marker()) and
+                if (isinstance(marker.get_marker(), six.string_types) and
                         marker.get_marker() == ','):
                     gc.set_linewidth(0)
                 else:
@@ -855,7 +855,7 @@ def draw(self, renderer):
                 if alt_marker_path:
                     alt_marker_trans = marker.get_alt_transform()
                     alt_marker_trans = alt_marker_trans.scale(w)
-                    if (is_string_like(mec) and mec == 'auto' and
+                    if (isinstance(mec, six.string_types) and mec == 'auto' and
                             rgbaFaceAlt is not None):
                         gc.set_alpha(rgbaFaceAlt[3])
                     else:
@@ -890,7 +890,7 @@ def get_marker(self):
 
     def get_markeredgecolor(self):
         mec = self._markeredgecolor
-        if (is_string_like(mec) and mec == 'auto'):
+        if isinstance(mec, six.string_types) and mec == 'auto':
             if rcParams['_internal.classic_mode']:
                 if self._marker.get_marker() in ('.', ','):
                     return self._color
@@ -909,7 +909,7 @@ def _get_markerfacecolor(self, alt=False):
         else:
             fc = self._markerfacecolor
 
-        if (is_string_like(fc) and fc.lower() == 'auto'):
+        if (isinstance(fc, six.string_types) and fc.lower() == 'auto'):
             if self.get_fillstyle() == 'none':
                 return 'none'
             else:
@@ -1106,7 +1106,7 @@ def set_linestyle(self, ls):
         ls : { ``'-'``,  ``'--'``, ``'-.'``, ``':'``} and more see description
             The line style.
         """
-        if is_string_like(ls):
+        if isinstance(ls, six.string_types):
             ds, ls = self._split_drawstyle_linestyle(ls)
             if ds is not None:
                 self.set_drawstyle(ds)
@@ -1289,7 +1289,7 @@ def update_from(self, other):
 
     def _get_rgba_face(self, alt=False):
         facecolor = self._get_markerfacecolor(alt=alt)
-        if is_string_like(facecolor) and facecolor.lower() == 'none':
+        if isinstance(facecolor, six.string_types) and facecolor.lower() == 'none':
             rgbaFace = None
         else:
             rgbaFace = mcolors.to_rgba(facecolor, self._alpha)
diff --git a/lib/matplotlib/markers.py b/lib/matplotlib/markers.py
index 6e5c3e119c3b..c7b233103430 100644
--- a/lib/matplotlib/markers.py
+++ b/lib/matplotlib/markers.py
@@ -94,7 +94,7 @@
 import numpy as np
 
 from . import rcParams
-from .cbook import is_math_text, is_string_like, is_numlike
+from .cbook import is_math_text, is_numlike
 from .path import Path
 from .transforms import IdentityTransform, Affine2D
 
@@ -259,7 +259,7 @@ def set_marker(self, marker):
               marker in self.markers):
             self._marker_function = getattr(
                 self, '_set_' + self.markers[marker])
-        elif is_string_like(marker) and is_math_text(marker):
+        elif isinstance(marker, six.string_types) and is_math_text(marker):
             self._marker_function = self._set_mathtext_path
         elif isinstance(marker, Path):
             self._marker_function = self._set_path_marker
diff --git a/lib/matplotlib/mathtext.py b/lib/matplotlib/mathtext.py
index f22dbe96901f..6fd001ff9a76 100644
--- a/lib/matplotlib/mathtext.py
+++ b/lib/matplotlib/mathtext.py
@@ -44,8 +44,7 @@
     ParserElement.enablePackrat()
 
 from matplotlib.afm import AFM
-from matplotlib.cbook import (Bunch, get_realpath_and_stat, is_string_like,
-                              maxdict)
+from matplotlib.cbook import Bunch, get_realpath_and_stat, maxdict
 from matplotlib.ft2font import (FT2Image, KERNING_DEFAULT, LOAD_FORCE_AUTOHINT,
                                 LOAD_NO_HINTING)
 from matplotlib.font_manager import findfont, FontProperties, get_font
@@ -1841,7 +1840,7 @@ class Glue(Node):
     def __init__(self, glue_type, copy=False):
         Node.__init__(self)
         self.glue_subtype   = 'normal'
-        if is_string_like(glue_type):
+        if isinstance(glue_type, six.string_types):
             glue_spec = GlueSpec.factory(glue_type)
         elif isinstance(glue_type, GlueSpec):
             glue_spec = glue_type
diff --git a/lib/matplotlib/mlab.py b/lib/matplotlib/mlab.py
index 3c99ee340695..dfa22e01888b 100644
--- a/lib/matplotlib/mlab.py
+++ b/lib/matplotlib/mlab.py
@@ -319,7 +319,7 @@ def detrend(x, key=None, axis=None):
         return detrend(x, key=detrend_linear, axis=axis)
     elif key == 'none':
         return detrend(x, key=detrend_none, axis=axis)
-    elif cbook.is_string_like(key):
+    elif isinstance(key, six.string_types):
         raise ValueError("Unknown value for key %s, must be one of: "
                          "'default', 'constant', 'mean', "
                          "'linear', or a function" % key)
@@ -2296,7 +2296,7 @@ def isvector(X):
 
 def safe_isnan(x):
     ':func:`numpy.isnan` for arbitrary types'
-    if cbook.is_string_like(x):
+    if isinstance(x, six.string_types):
         return False
     try:
         b = np.isnan(x)
@@ -2310,7 +2310,7 @@ def safe_isnan(x):
 
 def safe_isinf(x):
     ':func:`numpy.isinf` for arbitrary types'
-    if cbook.is_string_like(x):
+    if isinstance(x, six.string_types):
         return False
     try:
         b = np.isinf(x)
@@ -2329,8 +2329,8 @@ def rec_append_fields(rec, names, arrs, dtypes=None):
     *arrs* and *dtypes* do not have to be lists. They can just be the
     values themselves.
     """
-    if (not cbook.is_string_like(names) and cbook.iterable(names)
-            and len(names) and cbook.is_string_like(names[0])):
+    if (not isinstance(names, six.string_types) and cbook.iterable(names)
+            and len(names) and isinstance(names[0]), six.string_types):
         if len(names) != len(arrs):
             raise ValueError("number of arrays do not match number of names")
     else:  # we have only 1 name and 1 array
@@ -2380,7 +2380,7 @@ def rec_keep_fields(rec, names):
     Return a new numpy record array with only fields listed in names
     """
 
-    if cbook.is_string_like(names):
+    if isinstance(names, six.string_types):
         names = names.split(',')
 
     arrays = []
@@ -2477,7 +2477,7 @@ def rec_join(key, r1, r2, jointype='inner', defaults=None, r1postfix='1',
     (other than keys) that are both in *r1* and *r2*.
     """
 
-    if cbook.is_string_like(key):
+    if isinstance(key, six.string_types):
         key = (key, )
 
     for name in key:
@@ -2888,7 +2888,7 @@ def get_converters(reader, comments):
             seen[item] = cnt+1
 
     else:
-        if cbook.is_string_like(names):
+        if isinstance(names, six.string_types):
             names = [n.strip() for n in names.split(',')]
 
     # get the converter functions by inspecting checkrows
diff --git a/lib/matplotlib/offsetbox.py b/lib/matplotlib/offsetbox.py
index 890a2a485191..4fb1db744270 100644
--- a/lib/matplotlib/offsetbox.py
+++ b/lib/matplotlib/offsetbox.py
@@ -33,7 +33,6 @@
 from matplotlib import rcParams
 
 from matplotlib import docstring
-from matplotlib.cbook import is_string_like
 
 #from bboximage import BboxImage
 from matplotlib.image import BboxImage
@@ -1042,7 +1041,7 @@ def __init__(self, loc,
         self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform)
         self.set_child(child)
 
-        if is_string_like(loc):
+        if isinstance(loc, six.string_types):
             try:
                 loc = self.codes[loc]
             except KeyError:
diff --git a/lib/matplotlib/pylab.py b/lib/matplotlib/pylab.py
index 8b2c96829bec..7482b3396755 100644
--- a/lib/matplotlib/pylab.py
+++ b/lib/matplotlib/pylab.py
@@ -220,7 +220,7 @@
 import sys, warnings
 
 from matplotlib.cbook import (
-    flatten, is_string_like, exception_to_str, silent_list, iterable, dedent)
+    flatten, exception_to_str, silent_list, iterable, dedent)
 
 import matplotlib as mpl
 # make mpl.finance module available for backwards compatability, in case folks
diff --git a/lib/matplotlib/pyplot.py b/lib/matplotlib/pyplot.py
index e265e37b5366..9c1191c76543 100644
--- a/lib/matplotlib/pyplot.py
+++ b/lib/matplotlib/pyplot.py
@@ -29,7 +29,7 @@
 import matplotlib.colorbar
 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 dedent, silent_list, is_numlike
 from matplotlib.cbook import _string_to_bool
 from matplotlib.cbook import deprecated
 from matplotlib import docstring
@@ -505,7 +505,7 @@ def figure(num=None,  # autoincrement if None, else integer from 1-N
     figLabel = ''
     if num is None:
         num = next_num
-    elif is_string_like(num):
+    elif isinstance(num, six.string_types):
         figLabel = num
         allLabels = get_figlabels()
         if figLabel not in allLabels:
@@ -663,7 +663,7 @@ def close(*args):
             # if we are dealing with a type UUID, we
             # can use its integer representation
             _pylab_helpers.Gcf.destroy(arg.int)
-        elif is_string_like(arg):
+        elif isinstance(arg, six.string_types):
             allLabels = get_figlabels()
             if arg in allLabels:
                 num = get_fignums()[allLabels.index(arg)]
@@ -2379,7 +2379,7 @@ def plotfile(fname, cols=(0,), plotfuncs=None,
 
     def getname_val(identifier):
         'return the name and column data for identifier'
-        if is_string_like(identifier):
+        if isinstance(identifier, six.string_types):
             return identifier, r[identifier]
         elif is_numlike(identifier):
             name = r.dtype.names[int(identifier)]
diff --git a/lib/matplotlib/spines.py b/lib/matplotlib/spines.py
index 339753043e9c..c6b04fe43dba 100644
--- a/lib/matplotlib/spines.py
+++ b/lib/matplotlib/spines.py
@@ -177,7 +177,7 @@ def is_frame_like(self):
         """
         self._ensure_position_is_set()
         position = self._position
-        if cbook.is_string_like(position):
+        if isinstance(position, six.string_types):
             if position == 'center':
                 position = ('axes', 0.5)
             elif position == 'zero':
@@ -278,7 +278,7 @@ def _calc_offset_transform(self):
         """calculate the offset transform performed by the spine"""
         self._ensure_position_is_set()
         position = self._position
-        if cbook.is_string_like(position):
+        if isinstance(position, six.string_types):
             if position == 'center':
                 position = ('axes', 0.5)
             elif position == 'zero':
diff --git a/lib/matplotlib/style/core.py b/lib/matplotlib/style/core.py
index 6d8b95cdc31a..d741682b8228 100644
--- a/lib/matplotlib/style/core.py
+++ b/lib/matplotlib/style/core.py
@@ -89,14 +89,14 @@ def use(style):
 
 
     """
-    if cbook.is_string_like(style) or hasattr(style, 'keys'):
+    if isinstance(style, six.string_types) or hasattr(style, 'keys'):
         # If name is a single str or dict, make it a single element list.
         styles = [style]
     else:
         styles = style
 
     for style in styles:
-        if not cbook.is_string_like(style):
+        if not isinstance(style, six.string_types):
             _apply_style(style)
         elif style == 'default':
             _apply_style(rcParamsDefault, warn=False)
diff --git a/lib/matplotlib/table.py b/lib/matplotlib/table.py
index aa145170d565..80c17cfb92b4 100644
--- a/lib/matplotlib/table.py
+++ b/lib/matplotlib/table.py
@@ -30,7 +30,6 @@
 from . import artist
 from .artist import Artist, allow_rasterization
 from .patches import Rectangle
-from .cbook import is_string_like
 from matplotlib import docstring
 from .text import Text
 from .transforms import Bbox
@@ -253,12 +252,12 @@ def __init__(self, ax, loc=None, bbox=None, **kwargs):
 
         Artist.__init__(self)
 
-        if is_string_like(loc) and loc not in self.codes:
+        if isinstance(loc, six.string_types) and loc not in self.codes:
             warnings.warn('Unrecognized location %s. Falling back on '
                           'bottom; valid locations are\n%s\t' %
                           (loc, '\n\t'.join(self.codes)))
             loc = 'bottom'
-        if is_string_like(loc):
+        if isinstance(loc, six.string_types):
             loc = self.codes.get(loc, 1)
         self.set_figure(ax.figure)
         self._axes = ax
diff --git a/lib/matplotlib/testing/__init__.py b/lib/matplotlib/testing/__init__.py
index 4cdfe4bd8b9e..5b9dee44f6eb 100644
--- a/lib/matplotlib/testing/__init__.py
+++ b/lib/matplotlib/testing/__init__.py
@@ -6,13 +6,13 @@
 from contextlib import contextmanager
 
 import matplotlib
-from matplotlib.cbook import is_string_like, iterable
+from matplotlib.cbook import iterable
 from matplotlib import rcParams, rcdefaults, use
 
 
 def _is_list_like(obj):
     """Returns whether the obj is iterable and not a string"""
-    return not is_string_like(obj) and iterable(obj)
+    return not isinstance(obj, six.string_types) and iterable(obj)
 
 
 def is_called_from_pytest():
diff --git a/lib/matplotlib/tests/test_cbook.py b/lib/matplotlib/tests/test_cbook.py
index 12a79639a3a8..7e9f845e3548 100644
--- a/lib/matplotlib/tests/test_cbook.py
+++ b/lib/matplotlib/tests/test_cbook.py
@@ -19,30 +19,6 @@
 from matplotlib.cbook import delete_masked_points as dmp
 
 
-def test_is_string_like():
-    y = np.arange(10)
-    assert not cbook.is_string_like(y)
-    assert not cbook.is_string_like(y.reshape((-1, 1)))
-    assert not cbook.is_string_like(y.reshape((1, -1)))
-
-    assert cbook.is_string_like("hello world")
-    assert not cbook.is_string_like(10)
-
-    y = ['a', 'b', 'c']
-    assert not cbook.is_string_like(y)
-
-    y = np.array(y)
-    assert not cbook.is_string_like(y)
-
-
-def test_is_sequence_of_strings():
-    y = ['a', 'b', 'c']
-    assert cbook.is_sequence_of_strings(y)
-
-    y = np.array(y, dtype=object)
-    assert cbook.is_sequence_of_strings(y)
-
-
 def test_is_hashable():
     s = 'string'
     assert cbook.is_hashable(s)
diff --git a/lib/matplotlib/text.py b/lib/matplotlib/text.py
index 9e2d8be26842..adaf3ffd9047 100644
--- a/lib/matplotlib/text.py
+++ b/lib/matplotlib/text.py
@@ -18,7 +18,7 @@
 from matplotlib import rcParams
 import matplotlib.artist as artist
 from matplotlib.artist import Artist
-from matplotlib.cbook import is_string_like, maxdict
+from matplotlib.cbook import maxdict
 from matplotlib import docstring
 from matplotlib.font_manager import FontProperties
 from matplotlib.patches import FancyBboxPatch
@@ -215,7 +215,7 @@ def __init__(self,
             color = rcParams['text.color']
         if fontproperties is None:
             fontproperties = FontProperties()
-        elif is_string_like(fontproperties):
+        elif isinstance(fontproperties, six.string_types):
             fontproperties = FontProperties(fontproperties)
 
         self.set_text(text)
@@ -506,7 +506,7 @@ def set_bbox(self, rectprops):
                     pad = 0.3
 
             # boxstyle could be a callable or a string
-            if is_string_like(boxstyle) and "pad" not in boxstyle:
+            if isinstance(boxstyle, six.string_types) and "pad" not in boxstyle:
                 boxstyle += ",pad=%0.2f" % pad
 
             bbox_transmuter = props.pop("bbox_transmuter", None)
@@ -1241,7 +1241,7 @@ def set_fontproperties(self, fp):
 
         ACCEPTS: a :class:`matplotlib.font_manager.FontProperties` instance
         """
-        if is_string_like(fp):
+        if isinstance(fp, six.string_types):
             fp = FontProperties(fp)
         self._fontproperties = fp.copy()
         self.stale = True
@@ -1798,7 +1798,7 @@ def _get_xy_transform(self, renderer, s):
             return BboxTransformTo(s)
         elif isinstance(s, Transform):
             return s
-        elif not is_string_like(s):
+        elif not isinstance(s, six.string_types):
             raise RuntimeError("unknown coordinate type : %s" % (s,))
 
         if s == 'data':
@@ -1865,14 +1865,14 @@ def _get_ref_xy(self, renderer):
 
         if isinstance(self.xycoords, tuple):
             s1, s2 = self.xycoords
-            if ((is_string_like(s1) and s1.split()[0] == "offset") or
-                  (is_string_like(s2) and s2.split()[0] == "offset")):
+            if ((isinstance(s1, six.string_types) and s1.split()[0] == "offset") or
+                  (isinstance(s2, six.string_types) and s2.split()[0] == "offset")):
                 raise ValueError("xycoords should not be an offset coordinate")
             x, y = self.xy
             x1, y1 = self._get_xy(renderer, x, y, s1)
             x2, y2 = self._get_xy(renderer, x, y, s2)
             return x1, y2
-        elif (is_string_like(self.xycoords) and
+        elif (isinstance(self.xycoords, six.string_types) and
               self.xycoords.split()[0] == "offset"):
             raise ValueError("xycoords should not be an offset coordinate")
         else:
diff --git a/lib/matplotlib/ticker.py b/lib/matplotlib/ticker.py
index 19cc3810a843..07976372f550 100644
--- a/lib/matplotlib/ticker.py
+++ b/lib/matplotlib/ticker.py
@@ -2057,7 +2057,7 @@ def subs(self, subs):
         """
         if subs is None:  # consistency with previous bad API
             self._subs = 'auto'
-        elif cbook.is_string_like(subs):
+        elif isinstance(subs, six.string_types):
             if subs not in ('all', 'auto'):
                 raise ValueError("A subs string must be 'all' or 'auto'; "
                                  "found '%s'." % subs)
@@ -2105,7 +2105,7 @@ def tick_values(self, vmin, vmax):
 
         numdec = math.floor(vmax) - math.ceil(vmin)
 
-        if cbook.is_string_like(self._subs):
+        if isinstance(self._subs, six.string_types):
             _first = 2.0 if self._subs == 'auto' else 1.0
             if numdec > 10 or b < 3:
                 if self._subs == 'auto':
diff --git a/lib/mpl_toolkits/axes_grid1/axes_grid.py b/lib/mpl_toolkits/axes_grid1/axes_grid.py
index 5765168d215e..f63daa73fa1f 100644
--- a/lib/mpl_toolkits/axes_grid1/axes_grid.py
+++ b/lib/mpl_toolkits/axes_grid1/axes_grid.py
@@ -212,7 +212,7 @@ def __init__(self, fig,
 
         h = []
         v = []
-        if cbook.is_string_like(rect) or cbook.is_numlike(rect):
+        if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
             self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
                                            aspect=False)
         elif isinstance(rect, SubplotSpec):
@@ -533,7 +533,7 @@ def __init__(self, fig,
 
         h = []
         v = []
-        if cbook.is_string_like(rect) or cbook.is_numlike(rect):
+        if isinstance(rect, six.string_types) or cbook.is_numlike(rect):
             self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v,
                                            aspect=aspect)
         elif isinstance(rect, SubplotSpec):
diff --git a/lib/mpl_toolkits/axes_grid1/axes_size.py b/lib/mpl_toolkits/axes_grid1/axes_size.py
index 147a34e25838..552d76d1432f 100644
--- a/lib/mpl_toolkits/axes_grid1/axes_size.py
+++ b/lib/mpl_toolkits/axes_grid1/axes_size.py
@@ -266,7 +266,7 @@ def from_any(size, fraction_ref=None):
     """
     if cbook.is_numlike(size):
         return Fixed(size)
-    elif cbook.is_string_like(size):
+    elif isinstance(size, six.string_types):
         if size[-1] == "%":
             return Fraction(float(size[:-1])/100., fraction_ref)
 
diff --git a/lib/mpl_toolkits/axes_grid1/colorbar.py b/lib/mpl_toolkits/axes_grid1/colorbar.py
index 4f4991a8fe55..793eca5010da 100644
--- a/lib/mpl_toolkits/axes_grid1/colorbar.py
+++ b/lib/mpl_toolkits/axes_grid1/colorbar.py
@@ -380,7 +380,7 @@ def __init__(self, ax, cmap=None,
                 formatter = ticker.LogFormatter()
             else:
                 formatter = None
-        elif cbook.is_string_like(format):
+        elif isinstance(format, six.string_types):
             formatter = ticker.FormatStrFormatter(format)
         else:
             formatter = format  # Assume it is a Formatter
diff --git a/lib/mpl_toolkits/exceltools.py b/lib/mpl_toolkits/exceltools.py
index f230e0641dd2..2fae5b273004 100644
--- a/lib/mpl_toolkits/exceltools.py
+++ b/lib/mpl_toolkits/exceltools.py
@@ -92,7 +92,7 @@ def rec2excel(r, ws, formatd=None, rownum=0, colnum=0, nanstr='NaN', infstr='Inf
     """
 
     autosave = False
-    if cbook.is_string_like(ws):
+    if isinstance(ws, six.string_types):
         filename = ws
         wb = excel.Workbook()
         ws = wb.add_sheet('worksheet')
diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py
index 2b44de576dc0..d2541b6effca 100644
--- a/lib/mpl_toolkits/mplot3d/axes3d.py
+++ b/lib/mpl_toolkits/mplot3d/axes3d.py
@@ -2341,15 +2341,7 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c=None, depthshade=True,
 
         s = np.ma.ravel(s)  # This doesn't have to match x, y in size.
 
-        if c is not None:
-            cstr = cbook.is_string_like(c) or cbook.is_sequence_of_strings(c)
-            if not cstr:
-                c = np.asanyarray(c)
-                if c.size == xs.size:
-                    c = np.ma.ravel(c)
-            xs, ys, zs, s, c = cbook.delete_masked_points(xs, ys, zs, s, c)
-        else:
-            xs, ys, zs, s = cbook.delete_masked_points(xs, ys, zs, s)
+        xs, ys, zs, s, c = cbook.delete_masked_points(xs, ys, zs, s, c)
 
         patches = Axes.scatter(self, xs, ys, s=s, c=c, *args, **kwargs)
         if not cbook.iterable(zs):


Code review comments:
diff_hunk: @@ -1,8 +1,10 @@
-`cbook.is_numlike` and `cbook.is_string_like` only perform an instance check
-````````````````````````````````````````````````````````````````````````````
+`cbook.is_numlike` only performs an instance check, `cbook.is_string_like` is deprecated
+````````````````````````````````````````````````````````````````````````````````````````
 
-`cbook.is_numlike` and `cbook.is_string_like` now only check that
-their argument is an instance of ``(numbers.Number, np.Number)`` and
-``(six.string_types, np.str_, np.unicode_)`` respectively.  In particular, this
-means that arrays are now never num-like or string-like regardless of their
-dtype.
+`cbook.is_numlike` now only checks that its argument is an instance of
+``(numbers.Number, np.Number)`` and.  In particular, this means that arrays are
path: doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst
text: @user1:
and what?

@author:
typo, fixed

diff_hunk: @@ -1865,14 +1865,14 @@ def _get_ref_xy(self, renderer):
 
         if isinstance(self.xycoords, tuple):
             s1, s2 = self.xycoords
-            if ((is_string_like(s1) and s1.split()[0] == "offset") or
-                  (is_string_like(s2) and s2.split()[0] == "offset")):
+            if ((isinstance(s1, six.string_types) and s1.split()[0] == "offset") or
+                  (isinstance(s2, six.string_types) and s2.split()[0] == "offset")):
path: lib/matplotlib/text.py
text: @user1:
Looks a bit over as well.

@author:
fixed

diff_hunk: @@ -1,8 +1,10 @@
-`cbook.is_numlike` and `cbook.is_string_like` only perform an instance check
-````````````````````````````````````````````````````````````````````````````
+`cbook.is_numlike` only performs an instance check, `cbook.is_string_like` is deprecated
+````````````````````````````````````````````````````````````````````````````````````````
 
-`cbook.is_numlike` and `cbook.is_string_like` now only check that
-their argument is an instance of ``(numbers.Number, np.Number)`` and
-``(six.string_types, np.str_, np.unicode_)`` respectively.  In particular, this
-means that arrays are now never num-like or string-like regardless of their
-dtype.
+`cbook.is_numlike` now only checks that its argument is an instance of
+``(numbers.Number, np.Number)`` and.  In particular, this means that arrays are
+now not num-like.
+
+`cbook.is_string_like` and `cbook.is_sequence_of_strings` have been
+deprecated.  Use ``isinstance(obj, six.string_types)`` and ``all(isinstance(o,
+six.string_types) for o in obj) and not iterable(obj)`` instead.
path: doc/api/api_changes/2017-01-30-AL_is_numlike_stringlike.rst
text: @user1:
That doesn't seem right:
```python
In [9]: from matplotlib.cbook import iterable, is_sequence_of_strings

In [10]: obj = ['a', 'b', 'c']

In [11]: is_sequence_of_strings(obj)
Out[11]: True

In [12]: import six

In [13]: all(isinstance(o, six.string_types) for o in obj) and not iterable(obj)
Out[13]: False
```
(using 2.0.0, though)

@author:
the "not" needs to be removed, fixed

diff_hunk: @@ -1590,13 +1592,14 @@ def delete_masked_points(*args):
     """
     if not len(args):
         return ()
-    if (is_string_like(args[0]) or not iterable(args[0])):
+    if (isinstance(args[0], six.string_types) or not iterable(args[0])):
         raise ValueError("First argument must be a sequence")
     nrecs = len(args[0])
     margs = []
     seqlist = [False] * len(args)
     for i, x in enumerate(args):
-        if (not is_string_like(x)) and iterable(x) and len(x) == nrecs:
+        if ((not isinstance(x, six.string_types)) and iterable(x)
path: lib/matplotlib/cbook/__init__.py
text: @user1:
Can drop extra parentheses.

@author:
fixed

diff_hunk: @@ -789,7 +789,7 @@ def __init__(self, colors, name='from_list', N=None):
         if N is None:
             N = len(self.colors)
         else:
-            if (cbook.is_string_like(self.colors) and
+            if (isinstance(self.colors, six.string_types) and
                     cbook.is_hashable(self.colors)):
path: lib/matplotlib/colors.py
text: @user1:
Hmm, what strings are not hashable?

@author:
probably was the case of masked string arrays.  removed the now redundant check.

@user1:
I think there might be a few more of these that I didn't comment on.

@author:
Caught two more, should be all fixed now.

@user1:
I don't see it...

@author:
https://github.com/matplotlib/matplotlib/pull/8011/commits/c773d80057944bcb4f387a7f1ec87e71deeac2d1

@user1:
There's only one line that changes `is_hashable` there (this one.)

@author:
Ah sorry, thought you meant overly long lines.  Now I have removed the hashability checks too.

diff_hunk: @@ -1289,7 +1289,7 @@ def update_from(self, other):
 
     def _get_rgba_face(self, alt=False):
         facecolor = self._get_markerfacecolor(alt=alt)
-        if is_string_like(facecolor) and facecolor.lower() == 'none':
+        if isinstance(facecolor, six.string_types) and facecolor.lower() == 'none':
path: lib/matplotlib/lines.py
text: @user1:
Probably too long, also.

@author:
fixed