Whether two parameters match values.

        If either ``new`` or ``old`` is a NumPy array or Pandas Series or Index,
        then the result of ``np.array_equal`` will determine if the values match.

        Otherwise, the result of standard Python equality will be returned.

        Returns:
            True, if new and old match, False otherwise

def matches(self, new, old):
        ''' Whether two parameters match values.

        If either ``new`` or ``old`` is a NumPy array or Pandas Series or Index,
        then the result of ``np.array_equal`` will determine if the values match.

        Otherwise, the result of standard Python equality will be returned.

        Returns:
            True, if new and old match, False otherwise

        '''
        if isinstance(new, np.ndarray) or isinstance(old, np.ndarray):
            return np.array_equal(new, old)

        if pd:
            if isinstance(new, pd.Series) or isinstance(old, pd.Series):
                return np.array_equal(new, old)

            if isinstance(new, pd.Index) or isinstance(old, pd.Index):
                return np.array_equal(new, old)

        try:

            # this handles the special but common case where there is a dict with array
            # or series as values (e.g. the .data property of a ColumnDataSource)
            if isinstance(new, dict) and isinstance(old, dict):
                if set(new.keys()) != set(old.keys()):
                    return False
                return all(self.matches(new[k], old[k]) for k in new)

            return new == old

        # if the comparison fails for some reason, just punt and return no-match
        except ValueError:
            return False