Add a filter or list of filters to a datasource. A filter is a simple
    string, and it matches if it is contained anywhere within a line.

    Args:
       ds (@datasource component): The datasource to filter
       patterns (str, [str]): A string, list of strings, or set of strings to
            add to the datasource's filters.

def add_filter(ds, patterns):
    """
    Add a filter or list of filters to a datasource. A filter is a simple
    string, and it matches if it is contained anywhere within a line.

    Args:
       ds (@datasource component): The datasource to filter
       patterns (str, [str]): A string, list of strings, or set of strings to
            add to the datasource's filters.
    """
    if not plugins.is_datasource(ds):
        raise Exception("Filters are applicable only to datasources.")

    delegate = dr.get_delegate(ds)

    if delegate.raw:
        raise Exception("Filters aren't applicable to raw datasources.")

    if not delegate.filterable:
        raise Exception("Filters aren't applicable to %s." % dr.get_name(ds))

    if ds in _CACHE:
        del _CACHE[ds]
    if isinstance(patterns, six.string_types):
        FILTERS[ds].add(patterns)
    elif isinstance(patterns, list):
        FILTERS[ds] |= set(patterns)
    elif isinstance(patterns, set):
        FILTERS[ds] |= patterns
    else:
        raise TypeError("patterns must be string, list, or set.")