We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Disallow empty filters
Currently rules can add whatever filters they like. We should guard against simple placeholders like empty strings that will allow everything.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `insights/core/filters.py`
Content:
```
1 """
2 The filters module allows developers to apply filters to datasources,
3 by adding them directly or through dependent components like parsers
4 and combiners. A filter is a simple string, and it matches if it is contained
5 anywhere within a line.
6 
7 If a datasource has filters defined, it will return only lines matching at
8 least one of them. If a datasource has no filters, it will return all lines.
9 
10 Filters can be added to components like parsers and combiners, to apply consistent
11 filtering to multiple underlying datasources that are configured as filterable.
12 
13 Filters aren't applicable to "raw" datasources, which are created with
14 ``kind=RawFileProvider`` and have ``RegistryPoint`` instances with ``raw=True``.
15 
16 The addition of a single filter can cause a datasource to change from returning
17 all lines to returning just those that match. Therefore, any filtered
18 datasource should have at least one filter in the commit introducing it so
19 downstream components don't inadvertently change its behavior.
20 
21 The benefit of this fragility is the ability to drastically reduce in-memory
22 footprint and archive sizes. An additional benefit is the ability to evaluate
23 only lines known to be free of sensitive information.
24 
25 Filters added to a ``RegistryPoint`` will be applied to all datasources that
26 implement it. Filters added to a datasource implementation apply only to that
27 implementation.
28 
29 For example, a filter added to ``Specs.ps_auxww`` will apply to
30 ``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,
31 ``SosSpecs.ps_auxww``, etc. But a filter added to `DefaultSpecs.ps_auxww` will
32 only apply to ``DefaultSpecs.ps_auxww``. See the modules in ``insights.specs``
33 for those classes.
34 
35 Filtering can be disabled globally by setting the environment variable
36 ``INSIGHTS_FILTERS_ENABLED=False``. This means that no datasources will be
37 filtered even if filters are defined for them.
38 """
39 import os
40 import pkgutil
41 import six
42 import yaml as ser
43 from collections import defaultdict
44 
45 import insights
46 from insights.core import dr, plugins
47 from insights.util import parse_bool
48 
49 _CACHE = {}
50 FILTERS = defaultdict(set)
51 ENABLED = parse_bool(os.environ.get("INSIGHTS_FILTERS_ENABLED"), default=True)
52 
53 
54 def add_filter(component, patterns):
55     """
56     Add a filter or list of filters to a component. When the component is
57     a datasource, the filter will be directly added to that datasouce.
58     In cases when the component is a parser or combiner, the filter will be
59     added to underlying filterable datasources by traversing dependency graph.
60     A filter is a simple string, and it matches if it is contained anywhere
61     within a line.
62 
63     Args:
64        component (component): The component to filter, can be datasource,
65             parser or combiner.
66        patterns (str, [str]): A string, list of strings, or set of strings to
67             add to the datasource's filters.
68     """
69     def inner(component, patterns):
70         if component in _CACHE:
71             del _CACHE[component]
72         if isinstance(patterns, six.string_types):
73             FILTERS[component].add(patterns)
74         elif isinstance(patterns, list):
75             FILTERS[component] |= set(patterns)
76         elif isinstance(patterns, set):
77             FILTERS[component] |= patterns
78         else:
79             raise TypeError("patterns must be string, list, or set.")
80 
81     if not plugins.is_datasource(component):
82         for dep in dr.run_order(dr.get_dependency_graph(component)):
83             if plugins.is_datasource(dep):
84                 d = dr.get_delegate(dep)
85                 if d.filterable:
86                     inner(dep, patterns)
87     else:
88         delegate = dr.get_delegate(component)
89 
90         if delegate.raw:
91             raise Exception("Filters aren't applicable to raw datasources.")
92 
93         if not delegate.filterable:
94             raise Exception("Filters aren't applicable to %s." % dr.get_name(component))
95 
96         inner(component, patterns)
97 
98 
99 _add_filter = add_filter
100 
101 
102 def get_filters(component):
103     """
104     Get the set of filters for the given datasource.
105 
106     Filters added to a ``RegistryPoint`` will be applied to all datasources that
107     implement it. Filters added to a datasource implementation apply only to
108     that implementation.
109 
110     For example, a filter added to ``Specs.ps_auxww`` will apply to
111     ``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,
112     ``SosSpecs.ps_auxww``, etc. But a filter added to ``DefaultSpecs.ps_auxww``
113     will only apply to ``DefaultSpecs.ps_auxww``. See the modules in
114     ``insights.specs`` for those classes.
115 
116     Args:
117         component (a datasource): The target datasource
118 
119     Returns:
120         set: The set of filters defined for the datasource
121     """
122     def inner(c, filters=None):
123         filters = filters or set()
124         if not ENABLED:
125             return filters
126 
127         if not plugins.is_datasource(c):
128             return filters
129 
130         if c in FILTERS:
131             filters |= FILTERS[c]
132 
133         for d in dr.get_dependents(c):
134             filters |= inner(d, filters)
135         return filters
136 
137     if component not in _CACHE:
138         _CACHE[component] = inner(component)
139     return _CACHE[component]
140 
141 
142 def apply_filters(target, lines):
143     """
144     Applys filters to the lines of a datasource. This function is used only in
145     integration tests. Filters are applied in an equivalent but more performant
146     way at run time.
147     """
148     filters = get_filters(target)
149     if filters:
150         for l in lines:
151             if any(f in l for f in filters):
152                 yield l
153     else:
154         for l in lines:
155             yield l
156 
157 
158 _filename = ".".join(["filters", ser.__name__])
159 _dumps = ser.dump
160 _loads = ser.safe_load
161 
162 
163 def loads(string):
164     """Loads the filters dictionary given a string."""
165     d = _loads(string)
166     for k, v in d.items():
167         FILTERS[dr.get_component(k) or k] = set(v)
168 
169 
170 def load(stream=None):
171     """
172     Loads filters from a stream, normally an open file. If one is
173     not passed, filters are loaded from a default location within
174     the project.
175     """
176     if stream:
177         loads(stream.read())
178     else:
179         data = pkgutil.get_data(insights.__name__, _filename)
180         return loads(data) if data else None
181 
182 
183 def dumps():
184     """Returns a string representation of the FILTERS dictionary."""
185     d = {}
186     for k, v in FILTERS.items():
187         d[dr.get_name(k)] = list(v)
188     return _dumps(d)
189 
190 
191 def dump(stream=None):
192     """
193     Dumps a string representation of `FILTERS` to a stream, normally an
194     open file. If none is passed, `FILTERS` is dumped to a default location
195     within the project.
196     """
197     if stream:
198         stream.write(dumps())
199     else:
200         path = os.path.join(os.path.dirname(insights.__file__), _filename)
201         with open(path, "w") as f:
202             f.write(dumps())
203
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/insights/core/filters.py b/insights/core/filters.py
--- a/insights/core/filters.py
+++ b/insights/core/filters.py
@@ -69,14 +69,21 @@
     def inner(component, patterns):
         if component in _CACHE:
             del _CACHE[component]
+
+        types = six.string_types + (list, set)
+        if not isinstance(patterns, types):
+            raise TypeError("Filter patterns must be of type string, list, or set.")
+
         if isinstance(patterns, six.string_types):
-            FILTERS[component].add(patterns)
+            patterns = set([patterns])
         elif isinstance(patterns, list):
-            FILTERS[component] |= set(patterns)
-        elif isinstance(patterns, set):
-            FILTERS[component] |= patterns
-        else:
-            raise TypeError("patterns must be string, list, or set.")
+            patterns = set(patterns)
+
+        for pat in patterns:
+            if not pat:
+                raise Exception("Filter patterns must not be empy.")
+
+        FILTERS[component] |= patterns
 
     if not plugins.is_datasource(component):
         for dep in dr.run_order(dr.get_dependency_graph(component)):

{"golden_diff": "diff --git a/insights/core/filters.py b/insights/core/filters.py\n--- a/insights/core/filters.py\n+++ b/insights/core/filters.py\n@@ -69,14 +69,21 @@\n     def inner(component, patterns):\n         if component in _CACHE:\n             del _CACHE[component]\n+\n+        types = six.string_types + (list, set)\n+        if not isinstance(patterns, types):\n+            raise TypeError(\"Filter patterns must be of type string, list, or set.\")\n+\n         if isinstance(patterns, six.string_types):\n-            FILTERS[component].add(patterns)\n+            patterns = set([patterns])\n         elif isinstance(patterns, list):\n-            FILTERS[component] |= set(patterns)\n-        elif isinstance(patterns, set):\n-            FILTERS[component] |= patterns\n-        else:\n-            raise TypeError(\"patterns must be string, list, or set.\")\n+            patterns = set(patterns)\n+\n+        for pat in patterns:\n+            if not pat:\n+                raise Exception(\"Filter patterns must not be empy.\")\n+\n+        FILTERS[component] |= patterns\n \n     if not plugins.is_datasource(component):\n         for dep in dr.run_order(dr.get_dependency_graph(component)):\n", "issue": "Disallow empty filters\nCurrently rules can add whatever filters they like. We should guard against simple placeholders like empty strings that will allow everything.\n", "before_files": [{"content": "\"\"\"\nThe filters module allows developers to apply filters to datasources,\nby adding them directly or through dependent components like parsers\nand combiners. A filter is a simple string, and it matches if it is contained\nanywhere within a line.\n\nIf a datasource has filters defined, it will return only lines matching at\nleast one of them. If a datasource has no filters, it will return all lines.\n\nFilters can be added to components like parsers and combiners, to apply consistent\nfiltering to multiple underlying datasources that are configured as filterable.\n\nFilters aren't applicable to \"raw\" datasources, which are created with\n``kind=RawFileProvider`` and have ``RegistryPoint`` instances with ``raw=True``.\n\nThe addition of a single filter can cause a datasource to change from returning\nall lines to returning just those that match. Therefore, any filtered\ndatasource should have at least one filter in the commit introducing it so\ndownstream components don't inadvertently change its behavior.\n\nThe benefit of this fragility is the ability to drastically reduce in-memory\nfootprint and archive sizes. An additional benefit is the ability to evaluate\nonly lines known to be free of sensitive information.\n\nFilters added to a ``RegistryPoint`` will be applied to all datasources that\nimplement it. Filters added to a datasource implementation apply only to that\nimplementation.\n\nFor example, a filter added to ``Specs.ps_auxww`` will apply to\n``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,\n``SosSpecs.ps_auxww``, etc. But a filter added to `DefaultSpecs.ps_auxww` will\nonly apply to ``DefaultSpecs.ps_auxww``. See the modules in ``insights.specs``\nfor those classes.\n\nFiltering can be disabled globally by setting the environment variable\n``INSIGHTS_FILTERS_ENABLED=False``. This means that no datasources will be\nfiltered even if filters are defined for them.\n\"\"\"\nimport os\nimport pkgutil\nimport six\nimport yaml as ser\nfrom collections import defaultdict\n\nimport insights\nfrom insights.core import dr, plugins\nfrom insights.util import parse_bool\n\n_CACHE = {}\nFILTERS = defaultdict(set)\nENABLED = parse_bool(os.environ.get(\"INSIGHTS_FILTERS_ENABLED\"), default=True)\n\n\ndef add_filter(component, patterns):\n    \"\"\"\n    Add a filter or list of filters to a component. When the component is\n    a datasource, the filter will be directly added to that datasouce.\n    In cases when the component is a parser or combiner, the filter will be\n    added to underlying filterable datasources by traversing dependency graph.\n    A filter is a simple string, and it matches if it is contained anywhere\n    within a line.\n\n    Args:\n       component (component): The component to filter, can be datasource,\n            parser or combiner.\n       patterns (str, [str]): A string, list of strings, or set of strings to\n            add to the datasource's filters.\n    \"\"\"\n    def inner(component, patterns):\n        if component in _CACHE:\n            del _CACHE[component]\n        if isinstance(patterns, six.string_types):\n            FILTERS[component].add(patterns)\n        elif isinstance(patterns, list):\n            FILTERS[component] |= set(patterns)\n        elif isinstance(patterns, set):\n            FILTERS[component] |= patterns\n        else:\n            raise TypeError(\"patterns must be string, list, or set.\")\n\n    if not plugins.is_datasource(component):\n        for dep in dr.run_order(dr.get_dependency_graph(component)):\n            if plugins.is_datasource(dep):\n                d = dr.get_delegate(dep)\n                if d.filterable:\n                    inner(dep, patterns)\n    else:\n        delegate = dr.get_delegate(component)\n\n        if delegate.raw:\n            raise Exception(\"Filters aren't applicable to raw datasources.\")\n\n        if not delegate.filterable:\n            raise Exception(\"Filters aren't applicable to %s.\" % dr.get_name(component))\n\n        inner(component, patterns)\n\n\n_add_filter = add_filter\n\n\ndef get_filters(component):\n    \"\"\"\n    Get the set of filters for the given datasource.\n\n    Filters added to a ``RegistryPoint`` will be applied to all datasources that\n    implement it. Filters added to a datasource implementation apply only to\n    that implementation.\n\n    For example, a filter added to ``Specs.ps_auxww`` will apply to\n    ``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,\n    ``SosSpecs.ps_auxww``, etc. But a filter added to ``DefaultSpecs.ps_auxww``\n    will only apply to ``DefaultSpecs.ps_auxww``. See the modules in\n    ``insights.specs`` for those classes.\n\n    Args:\n        component (a datasource): The target datasource\n\n    Returns:\n        set: The set of filters defined for the datasource\n    \"\"\"\n    def inner(c, filters=None):\n        filters = filters or set()\n        if not ENABLED:\n            return filters\n\n        if not plugins.is_datasource(c):\n            return filters\n\n        if c in FILTERS:\n            filters |= FILTERS[c]\n\n        for d in dr.get_dependents(c):\n            filters |= inner(d, filters)\n        return filters\n\n    if component not in _CACHE:\n        _CACHE[component] = inner(component)\n    return _CACHE[component]\n\n\ndef apply_filters(target, lines):\n    \"\"\"\n    Applys filters to the lines of a datasource. This function is used only in\n    integration tests. Filters are applied in an equivalent but more performant\n    way at run time.\n    \"\"\"\n    filters = get_filters(target)\n    if filters:\n        for l in lines:\n            if any(f in l for f in filters):\n                yield l\n    else:\n        for l in lines:\n            yield l\n\n\n_filename = \".\".join([\"filters\", ser.__name__])\n_dumps = ser.dump\n_loads = ser.safe_load\n\n\ndef loads(string):\n    \"\"\"Loads the filters dictionary given a string.\"\"\"\n    d = _loads(string)\n    for k, v in d.items():\n        FILTERS[dr.get_component(k) or k] = set(v)\n\n\ndef load(stream=None):\n    \"\"\"\n    Loads filters from a stream, normally an open file. If one is\n    not passed, filters are loaded from a default location within\n    the project.\n    \"\"\"\n    if stream:\n        loads(stream.read())\n    else:\n        data = pkgutil.get_data(insights.__name__, _filename)\n        return loads(data) if data else None\n\n\ndef dumps():\n    \"\"\"Returns a string representation of the FILTERS dictionary.\"\"\"\n    d = {}\n    for k, v in FILTERS.items():\n        d[dr.get_name(k)] = list(v)\n    return _dumps(d)\n\n\ndef dump(stream=None):\n    \"\"\"\n    Dumps a string representation of `FILTERS` to a stream, normally an\n    open file. If none is passed, `FILTERS` is dumped to a default location\n    within the project.\n    \"\"\"\n    if stream:\n        stream.write(dumps())\n    else:\n        path = os.path.join(os.path.dirname(insights.__file__), _filename)\n        with open(path, \"w\") as f:\n            f.write(dumps())\n", "path": "insights/core/filters.py"}], "after_files": [{"content": "\"\"\"\nThe filters module allows developers to apply filters to datasources,\nby adding them directly or through dependent components like parsers\nand combiners. A filter is a simple string, and it matches if it is contained\nanywhere within a line.\n\nIf a datasource has filters defined, it will return only lines matching at\nleast one of them. If a datasource has no filters, it will return all lines.\n\nFilters can be added to components like parsers and combiners, to apply consistent\nfiltering to multiple underlying datasources that are configured as filterable.\n\nFilters aren't applicable to \"raw\" datasources, which are created with\n``kind=RawFileProvider`` and have ``RegistryPoint`` instances with ``raw=True``.\n\nThe addition of a single filter can cause a datasource to change from returning\nall lines to returning just those that match. Therefore, any filtered\ndatasource should have at least one filter in the commit introducing it so\ndownstream components don't inadvertently change its behavior.\n\nThe benefit of this fragility is the ability to drastically reduce in-memory\nfootprint and archive sizes. An additional benefit is the ability to evaluate\nonly lines known to be free of sensitive information.\n\nFilters added to a ``RegistryPoint`` will be applied to all datasources that\nimplement it. Filters added to a datasource implementation apply only to that\nimplementation.\n\nFor example, a filter added to ``Specs.ps_auxww`` will apply to\n``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,\n``SosSpecs.ps_auxww``, etc. But a filter added to `DefaultSpecs.ps_auxww` will\nonly apply to ``DefaultSpecs.ps_auxww``. See the modules in ``insights.specs``\nfor those classes.\n\nFiltering can be disabled globally by setting the environment variable\n``INSIGHTS_FILTERS_ENABLED=False``. This means that no datasources will be\nfiltered even if filters are defined for them.\n\"\"\"\nimport os\nimport pkgutil\nimport six\nimport yaml as ser\nfrom collections import defaultdict\n\nimport insights\nfrom insights.core import dr, plugins\nfrom insights.util import parse_bool\n\n_CACHE = {}\nFILTERS = defaultdict(set)\nENABLED = parse_bool(os.environ.get(\"INSIGHTS_FILTERS_ENABLED\"), default=True)\n\n\ndef add_filter(component, patterns):\n    \"\"\"\n    Add a filter or list of filters to a component. When the component is\n    a datasource, the filter will be directly added to that datasouce.\n    In cases when the component is a parser or combiner, the filter will be\n    added to underlying filterable datasources by traversing dependency graph.\n    A filter is a simple string, and it matches if it is contained anywhere\n    within a line.\n\n    Args:\n       component (component): The component to filter, can be datasource,\n            parser or combiner.\n       patterns (str, [str]): A string, list of strings, or set of strings to\n            add to the datasource's filters.\n    \"\"\"\n    def inner(component, patterns):\n        if component in _CACHE:\n            del _CACHE[component]\n\n        types = six.string_types + (list, set)\n        if not isinstance(patterns, types):\n            raise TypeError(\"Filter patterns must be of type string, list, or set.\")\n\n        if isinstance(patterns, six.string_types):\n            patterns = set([patterns])\n        elif isinstance(patterns, list):\n            patterns = set(patterns)\n\n        for pat in patterns:\n            if not pat:\n                raise Exception(\"Filter patterns must not be empy.\")\n\n        FILTERS[component] |= patterns\n\n    if not plugins.is_datasource(component):\n        for dep in dr.run_order(dr.get_dependency_graph(component)):\n            if plugins.is_datasource(dep):\n                d = dr.get_delegate(dep)\n                if d.filterable:\n                    inner(dep, patterns)\n    else:\n        delegate = dr.get_delegate(component)\n\n        if delegate.raw:\n            raise Exception(\"Filters aren't applicable to raw datasources.\")\n\n        if not delegate.filterable:\n            raise Exception(\"Filters aren't applicable to %s.\" % dr.get_name(component))\n\n        inner(component, patterns)\n\n\n_add_filter = add_filter\n\n\ndef get_filters(component):\n    \"\"\"\n    Get the set of filters for the given datasource.\n\n    Filters added to a ``RegistryPoint`` will be applied to all datasources that\n    implement it. Filters added to a datasource implementation apply only to\n    that implementation.\n\n    For example, a filter added to ``Specs.ps_auxww`` will apply to\n    ``DefaultSpecs.ps_auxww``, ``InsightsArchiveSpecs.ps_auxww``,\n    ``SosSpecs.ps_auxww``, etc. But a filter added to ``DefaultSpecs.ps_auxww``\n    will only apply to ``DefaultSpecs.ps_auxww``. See the modules in\n    ``insights.specs`` for those classes.\n\n    Args:\n        component (a datasource): The target datasource\n\n    Returns:\n        set: The set of filters defined for the datasource\n    \"\"\"\n    def inner(c, filters=None):\n        filters = filters or set()\n        if not ENABLED:\n            return filters\n\n        if not plugins.is_datasource(c):\n            return filters\n\n        if c in FILTERS:\n            filters |= FILTERS[c]\n\n        for d in dr.get_dependents(c):\n            filters |= inner(d, filters)\n        return filters\n\n    if component not in _CACHE:\n        _CACHE[component] = inner(component)\n    return _CACHE[component]\n\n\ndef apply_filters(target, lines):\n    \"\"\"\n    Applys filters to the lines of a datasource. This function is used only in\n    integration tests. Filters are applied in an equivalent but more performant\n    way at run time.\n    \"\"\"\n    filters = get_filters(target)\n    if filters:\n        for l in lines:\n            if any(f in l for f in filters):\n                yield l\n    else:\n        for l in lines:\n            yield l\n\n\n_filename = \".\".join([\"filters\", ser.__name__])\n_dumps = ser.dump\n_loads = ser.safe_load\n\n\ndef loads(string):\n    \"\"\"Loads the filters dictionary given a string.\"\"\"\n    d = _loads(string)\n    for k, v in d.items():\n        FILTERS[dr.get_component(k) or k] = set(v)\n\n\ndef load(stream=None):\n    \"\"\"\n    Loads filters from a stream, normally an open file. If one is\n    not passed, filters are loaded from a default location within\n    the project.\n    \"\"\"\n    if stream:\n        loads(stream.read())\n    else:\n        data = pkgutil.get_data(insights.__name__, _filename)\n        return loads(data) if data else None\n\n\ndef dumps():\n    \"\"\"Returns a string representation of the FILTERS dictionary.\"\"\"\n    d = {}\n    for k, v in FILTERS.items():\n        d[dr.get_name(k)] = list(v)\n    return _dumps(d)\n\n\ndef dump(stream=None):\n    \"\"\"\n    Dumps a string representation of `FILTERS` to a stream, normally an\n    open file. If none is passed, `FILTERS` is dumped to a default location\n    within the project.\n    \"\"\"\n    if stream:\n        stream.write(dumps())\n    else:\n        path = os.path.join(os.path.dirname(insights.__file__), _filename)\n        with open(path, \"w\") as f:\n            f.write(dumps())\n", "path": "insights/core/filters.py"}]}