We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
QueryResponse.show not flexible enough
It would be nice if one could change the columns that will be displayed. 

Compare the function `display_entries` of my database package to get an idea of what I imagine (implementation https://github.com/derdon/sunpy/blob/database/sunpy/database/tables.py#L547, test at https://github.com/derdon/sunpy/blob/database/sunpy/tests/database/test_tables.py#L302). 

So I'd like the signature of `QueryResponse.show` to be `self, columns=['Start time', 'End time', 'Source','Instrument', 'Type']`. This way, the default behaviour will not change to the current implementation.


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sunpy/net/base_client.py`
Content:
```
1 import importlib
2 from abc import ABC, abstractmethod
3 from textwrap import dedent
4 from collections.abc import Sequence
5 
6 from astropy.table import Table
7 
8 from sunpy.util.util import get_width
9 
10 __all__ = ['BaseQueryResponse', 'BaseClient']
11 
12 
13 class BaseQueryResponse(Sequence):
14     """
15     An Abstract Base Class for results returned from BaseClient.
16 
17     Notes
18     -----
19     * A QueryResponse object must be able to be instantiated with only one
20       iterable argument. (i.e. the ``__init__`` must only have one required
21       argument).
22     * The `client` property must be settable.
23     * The base class does not prescribe how you store the results from your
24       client, only that it must be possible to represent them as an astropy
25       table in the ``build_table`` method.
26     * `__getitem__` **must** return an instance of the type it was called on.
27       I.e. it must always return an object of ``type(self)``.
28 
29     """
30 
31     @abstractmethod
32     def build_table(self):
33         """
34         Return an `astropy.table.Table` representation of the query response.
35         """
36 
37     @property
38     @abstractmethod
39     def client(self):
40         """
41         An instance of `BaseClient` used to generate the results.
42 
43         Generally this is used to fetch the results later.
44 
45         .. note::
46 
47             In general, this doesn't have to be the same instance of
48             ``BaseClient``, this is left to the client developer. If there is a
49             significant connection overhead in creating an instance of a client
50             you might want it to be the same instance as used for the search.
51         """
52 
53     @client.setter
54     @abstractmethod
55     def client(self, value):
56         pass
57 
58     @property
59     @abstractmethod
60     def blocks(self):
61         """
62         A `collections.abc.Sequence` object which contains the records
63         contained within the Query Response.
64         """
65 
66     @abstractmethod
67     def response_block_properties(self):
68         """
69         Returns a set of class attributes on all the response blocks.
70 
71         Returns
72         -------
73         s : `set`
74             List of strings, containing attribute names in the response blocks.
75         """
76 
77     def __str__(self):
78         """Print out human-readable summary of records retrieved"""
79         return '\n'.join(self.build_table().pformat(show_dtype=False))
80 
81     def __repr__(self):
82         """Print out human-readable summary of records retrieved"""
83         return object.__repr__(self) + "\n" + str(self)
84 
85     def _repr_html_(self):
86         return self.build_table()._repr_html_()
87 
88 
89 def _print_client(client, html=False):
90     """
91     Given a BaseClient instance will print out each registered attribute.
92 
93     Parameters
94     ----------
95     client : `sunpy.net.base_client.BaseClient`
96         The instance class to print for.
97     html : bool
98         Will return a html table instead.
99 
100     Returns
101     -------
102     `str`
103         String with the client.
104     """
105     width = -1 if html else get_width()
106     class_name = f"{client.__module__+'.' or ''}{client.__class__.__name__}"
107     attrs = client.register_values()
108     lines = []
109     t = Table(names=["Attr Type", "Name", "Description"],
110               dtype=["U80", "U80", "U80"])
111     for client_key in attrs.keys():
112         for name, desc in attrs[client_key]:
113             t.add_row((client_key.__name__, name, desc))
114     lines = [class_name, dedent(client.__doc__.partition("\n\n")[0])]
115     if html:
116         lines = [f"<p>{line}</p>" for line in lines]
117     lines.extend(t.pformat_all(show_dtype=False, max_width=width, align="<", html=html))
118     return '\n'.join(lines)
119 
120 
121 class BaseClient(ABC):
122     """
123     This defines the Abstract Base Class for each download client.
124 
125     The BaseClient has several abstract methods that ensure that any subclass enforces the bare minimum API.
126     These are `search`, `fetch` and `_can_handle_query`.
127     The last one ensures that each download client can be registered with Fido.
128 
129     Most download clients should subclass `~sunpy.net.dataretriever.GenericClient`.
130     If the structure of `~sunpy.net.dataretriever.GenericClient`
131     is not useful you should use `~sunpy.net.BaseClient`.
132     `~sunpy.net.vso.VSOClient` and `~sunpy.net.jsoc.JSOCClient`
133     are examples of download clients that subclass ``BaseClient``.
134     """
135 
136     _registry = dict()
137 
138     def __init_subclass__(cls, *args, **kwargs):
139         """
140         An __init_subclass__ hook initializes all of the subclasses of a given class.
141         So for each subclass, it will call this block of code on import.
142         This replicates some metaclass magic without the need to be aware of metaclasses.
143         Here we use this to register each subclass in a dict that has the `_can_handle_query` attribute.
144         This is then passed into the UnifiedDownloaderFactory so we can register them.
145         This means that Fido can use the clients internally.
146         """
147         super().__init_subclass__(**kwargs)
148 
149         # We do not want to register GenericClient since its a dummy client.
150         if cls.__name__ in ('GenericClient'):
151             return
152 
153         cls._registry[cls] = cls._can_handle_query
154 
155         if hasattr(cls, "_attrs_module"):
156             from sunpy.net import attrs
157 
158             name, module = cls._attrs_module()
159             module_obj = importlib.import_module(module)
160 
161             existing_mod = getattr(attrs, name, None)
162             if existing_mod and existing_mod is not module_obj:
163                 raise NameError(f"{name} has already been registered as an attrs name.")
164 
165             setattr(attrs, name, module_obj)
166 
167             if name not in attrs.__all__:
168                 attrs.__all__.append(name)
169 
170         # Register client attrs after it has regsitered its own attrs
171         from sunpy.net import attr
172         values = cls.register_values()
173         # If the client has no support, we won't try to register attrs
174         if values:
175             attr.Attr.update_values({cls: values})
176 
177     def __repr__(self):
178         """
179         Returns the normal repr plus the pretty client __str__.
180         """
181         return object.__repr__(self) + "\n" + str(self)
182 
183     def __str__(self):
184         """
185         This enables the "pretty" printing of BaseClient.
186         """
187         return _print_client(self)
188 
189     def _repr_html_(self):
190         """
191         This enables the "pretty" printing of the BaseClient with html.
192         """
193         return _print_client(self, html=True)
194 
195     @abstractmethod
196     def search(self, *args, **kwargs):
197         """
198         This enables the user to search for data using the client.
199 
200         Must return a subclass of `BaseQueryResponse`.
201         """
202 
203     @abstractmethod
204     def fetch(self, *query_results, path=None, overwrite=False, progress=True,
205               max_conn=5, downloader=None, wait=True, **kwargs):
206         """
207         This enables the user to fetch the data using the client, after a search.
208 
209         Parameters
210         ----------
211         query_results:
212             Results to download.
213         path : `str` or `pathlib.Path`, optional
214             Path to the download directory
215         overwrite : `bool`, optional
216             Replace files with the same name if True.
217         progress : `bool`, optional
218             Print progress info to terminal.
219         max_conns : `int`, optional
220             Maximum number of download connections.
221         downloader : `parfive.Downloader`, optional
222             The download manager to use.
223         wait : `bool`, optional
224            If `False` ``downloader.download()`` will not be called. Only has
225            any effect if `downloader` is not `None`.
226 
227         Returns
228         -------
229         `parfive.Results`
230             The results object, can be `None` if ``wait`` is `False`.
231         """
232 
233     @classmethod
234     @abstractmethod
235     def _can_handle_query(cls, *query):
236         """
237         This enables the client to register what kind of searches it can handle, to prevent Fido
238         using the incorrect client.
239         """
240 
241     @staticmethod
242     def check_attr_types_in_query(query, required_attrs={}, optional_attrs={}):
243         """
244         Check a query againsted required and optional attributes.
245 
246         Returns `True` if *query* contains all the attrs in *required_attrs*,
247         and if *query* contains only attrs in both *required_attrs* and *optional_attrs*.
248         """
249         query_attrs = {type(x) for x in query}
250         all_attrs = required_attrs.union(optional_attrs)
251 
252         return required_attrs.issubset(query_attrs) and query_attrs.issubset(all_attrs)
253 
254     @classmethod
255     def register_values(cls, *query):
256         """
257         This enables the client to register what kind of Attrs it can use directly.
258 
259         Returns
260         -------
261         `dict`
262             A dictionary with key values of Attrs and the values are a tuple of
263             ("Attr Type", "Name", "Description").
264         """
265         return {}
266
```
--- 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/sunpy/net/base_client.py b/sunpy/net/base_client.py
--- a/sunpy/net/base_client.py
+++ b/sunpy/net/base_client.py
@@ -85,6 +85,25 @@
     def _repr_html_(self):
         return self.build_table()._repr_html_()
 
+    def show(self, *cols):
+        """
+        Returns response tables with desired columns for the Query.
+
+        Parameters
+        ----------
+        \\*cols : `tuple`
+            Name of columns to be shown.
+
+        Returns
+        -------
+        `astropy.table.Table`
+            A table showing values for specified columns.
+        """
+        table = self.build_table()
+        if len(cols) == 0:
+            return table
+        return table[list(cols)]
+
 
 def _print_client(client, html=False):
     """

{"golden_diff": "diff --git a/sunpy/net/base_client.py b/sunpy/net/base_client.py\n--- a/sunpy/net/base_client.py\n+++ b/sunpy/net/base_client.py\n@@ -85,6 +85,25 @@\n     def _repr_html_(self):\n         return self.build_table()._repr_html_()\n \n+    def show(self, *cols):\n+        \"\"\"\n+        Returns response tables with desired columns for the Query.\n+\n+        Parameters\n+        ----------\n+        \\\\*cols : `tuple`\n+            Name of columns to be shown.\n+\n+        Returns\n+        -------\n+        `astropy.table.Table`\n+            A table showing values for specified columns.\n+        \"\"\"\n+        table = self.build_table()\n+        if len(cols) == 0:\n+            return table\n+        return table[list(cols)]\n+\n \n def _print_client(client, html=False):\n     \"\"\"\n", "issue": "QueryResponse.show not flexible enough\nIt would be nice if one could change the columns that will be displayed. \r\n\r\nCompare the function `display_entries` of my database package to get an idea of what I imagine (implementation https://github.com/derdon/sunpy/blob/database/sunpy/database/tables.py#L547, test at https://github.com/derdon/sunpy/blob/database/sunpy/tests/database/test_tables.py#L302). \r\n\r\nSo I'd like the signature of `QueryResponse.show` to be `self, columns=['Start time', 'End time', 'Source','Instrument', 'Type']`. This way, the default behaviour will not change to the current implementation.\r\n\n", "before_files": [{"content": "import importlib\nfrom abc import ABC, abstractmethod\nfrom textwrap import dedent\nfrom collections.abc import Sequence\n\nfrom astropy.table import Table\n\nfrom sunpy.util.util import get_width\n\n__all__ = ['BaseQueryResponse', 'BaseClient']\n\n\nclass BaseQueryResponse(Sequence):\n    \"\"\"\n    An Abstract Base Class for results returned from BaseClient.\n\n    Notes\n    -----\n    * A QueryResponse object must be able to be instantiated with only one\n      iterable argument. (i.e. the ``__init__`` must only have one required\n      argument).\n    * The `client` property must be settable.\n    * The base class does not prescribe how you store the results from your\n      client, only that it must be possible to represent them as an astropy\n      table in the ``build_table`` method.\n    * `__getitem__` **must** return an instance of the type it was called on.\n      I.e. it must always return an object of ``type(self)``.\n\n    \"\"\"\n\n    @abstractmethod\n    def build_table(self):\n        \"\"\"\n        Return an `astropy.table.Table` representation of the query response.\n        \"\"\"\n\n    @property\n    @abstractmethod\n    def client(self):\n        \"\"\"\n        An instance of `BaseClient` used to generate the results.\n\n        Generally this is used to fetch the results later.\n\n        .. note::\n\n            In general, this doesn't have to be the same instance of\n            ``BaseClient``, this is left to the client developer. If there is a\n            significant connection overhead in creating an instance of a client\n            you might want it to be the same instance as used for the search.\n        \"\"\"\n\n    @client.setter\n    @abstractmethod\n    def client(self, value):\n        pass\n\n    @property\n    @abstractmethod\n    def blocks(self):\n        \"\"\"\n        A `collections.abc.Sequence` object which contains the records\n        contained within the Query Response.\n        \"\"\"\n\n    @abstractmethod\n    def response_block_properties(self):\n        \"\"\"\n        Returns a set of class attributes on all the response blocks.\n\n        Returns\n        -------\n        s : `set`\n            List of strings, containing attribute names in the response blocks.\n        \"\"\"\n\n    def __str__(self):\n        \"\"\"Print out human-readable summary of records retrieved\"\"\"\n        return '\\n'.join(self.build_table().pformat(show_dtype=False))\n\n    def __repr__(self):\n        \"\"\"Print out human-readable summary of records retrieved\"\"\"\n        return object.__repr__(self) + \"\\n\" + str(self)\n\n    def _repr_html_(self):\n        return self.build_table()._repr_html_()\n\n\ndef _print_client(client, html=False):\n    \"\"\"\n    Given a BaseClient instance will print out each registered attribute.\n\n    Parameters\n    ----------\n    client : `sunpy.net.base_client.BaseClient`\n        The instance class to print for.\n    html : bool\n        Will return a html table instead.\n\n    Returns\n    -------\n    `str`\n        String with the client.\n    \"\"\"\n    width = -1 if html else get_width()\n    class_name = f\"{client.__module__+'.' or ''}{client.__class__.__name__}\"\n    attrs = client.register_values()\n    lines = []\n    t = Table(names=[\"Attr Type\", \"Name\", \"Description\"],\n              dtype=[\"U80\", \"U80\", \"U80\"])\n    for client_key in attrs.keys():\n        for name, desc in attrs[client_key]:\n            t.add_row((client_key.__name__, name, desc))\n    lines = [class_name, dedent(client.__doc__.partition(\"\\n\\n\")[0])]\n    if html:\n        lines = [f\"<p>{line}</p>\" for line in lines]\n    lines.extend(t.pformat_all(show_dtype=False, max_width=width, align=\"<\", html=html))\n    return '\\n'.join(lines)\n\n\nclass BaseClient(ABC):\n    \"\"\"\n    This defines the Abstract Base Class for each download client.\n\n    The BaseClient has several abstract methods that ensure that any subclass enforces the bare minimum API.\n    These are `search`, `fetch` and `_can_handle_query`.\n    The last one ensures that each download client can be registered with Fido.\n\n    Most download clients should subclass `~sunpy.net.dataretriever.GenericClient`.\n    If the structure of `~sunpy.net.dataretriever.GenericClient`\n    is not useful you should use `~sunpy.net.BaseClient`.\n    `~sunpy.net.vso.VSOClient` and `~sunpy.net.jsoc.JSOCClient`\n    are examples of download clients that subclass ``BaseClient``.\n    \"\"\"\n\n    _registry = dict()\n\n    def __init_subclass__(cls, *args, **kwargs):\n        \"\"\"\n        An __init_subclass__ hook initializes all of the subclasses of a given class.\n        So for each subclass, it will call this block of code on import.\n        This replicates some metaclass magic without the need to be aware of metaclasses.\n        Here we use this to register each subclass in a dict that has the `_can_handle_query` attribute.\n        This is then passed into the UnifiedDownloaderFactory so we can register them.\n        This means that Fido can use the clients internally.\n        \"\"\"\n        super().__init_subclass__(**kwargs)\n\n        # We do not want to register GenericClient since its a dummy client.\n        if cls.__name__ in ('GenericClient'):\n            return\n\n        cls._registry[cls] = cls._can_handle_query\n\n        if hasattr(cls, \"_attrs_module\"):\n            from sunpy.net import attrs\n\n            name, module = cls._attrs_module()\n            module_obj = importlib.import_module(module)\n\n            existing_mod = getattr(attrs, name, None)\n            if existing_mod and existing_mod is not module_obj:\n                raise NameError(f\"{name} has already been registered as an attrs name.\")\n\n            setattr(attrs, name, module_obj)\n\n            if name not in attrs.__all__:\n                attrs.__all__.append(name)\n\n        # Register client attrs after it has regsitered its own attrs\n        from sunpy.net import attr\n        values = cls.register_values()\n        # If the client has no support, we won't try to register attrs\n        if values:\n            attr.Attr.update_values({cls: values})\n\n    def __repr__(self):\n        \"\"\"\n        Returns the normal repr plus the pretty client __str__.\n        \"\"\"\n        return object.__repr__(self) + \"\\n\" + str(self)\n\n    def __str__(self):\n        \"\"\"\n        This enables the \"pretty\" printing of BaseClient.\n        \"\"\"\n        return _print_client(self)\n\n    def _repr_html_(self):\n        \"\"\"\n        This enables the \"pretty\" printing of the BaseClient with html.\n        \"\"\"\n        return _print_client(self, html=True)\n\n    @abstractmethod\n    def search(self, *args, **kwargs):\n        \"\"\"\n        This enables the user to search for data using the client.\n\n        Must return a subclass of `BaseQueryResponse`.\n        \"\"\"\n\n    @abstractmethod\n    def fetch(self, *query_results, path=None, overwrite=False, progress=True,\n              max_conn=5, downloader=None, wait=True, **kwargs):\n        \"\"\"\n        This enables the user to fetch the data using the client, after a search.\n\n        Parameters\n        ----------\n        query_results:\n            Results to download.\n        path : `str` or `pathlib.Path`, optional\n            Path to the download directory\n        overwrite : `bool`, optional\n            Replace files with the same name if True.\n        progress : `bool`, optional\n            Print progress info to terminal.\n        max_conns : `int`, optional\n            Maximum number of download connections.\n        downloader : `parfive.Downloader`, optional\n            The download manager to use.\n        wait : `bool`, optional\n           If `False` ``downloader.download()`` will not be called. Only has\n           any effect if `downloader` is not `None`.\n\n        Returns\n        -------\n        `parfive.Results`\n            The results object, can be `None` if ``wait`` is `False`.\n        \"\"\"\n\n    @classmethod\n    @abstractmethod\n    def _can_handle_query(cls, *query):\n        \"\"\"\n        This enables the client to register what kind of searches it can handle, to prevent Fido\n        using the incorrect client.\n        \"\"\"\n\n    @staticmethod\n    def check_attr_types_in_query(query, required_attrs={}, optional_attrs={}):\n        \"\"\"\n        Check a query againsted required and optional attributes.\n\n        Returns `True` if *query* contains all the attrs in *required_attrs*,\n        and if *query* contains only attrs in both *required_attrs* and *optional_attrs*.\n        \"\"\"\n        query_attrs = {type(x) for x in query}\n        all_attrs = required_attrs.union(optional_attrs)\n\n        return required_attrs.issubset(query_attrs) and query_attrs.issubset(all_attrs)\n\n    @classmethod\n    def register_values(cls, *query):\n        \"\"\"\n        This enables the client to register what kind of Attrs it can use directly.\n\n        Returns\n        -------\n        `dict`\n            A dictionary with key values of Attrs and the values are a tuple of\n            (\"Attr Type\", \"Name\", \"Description\").\n        \"\"\"\n        return {}\n", "path": "sunpy/net/base_client.py"}], "after_files": [{"content": "import importlib\nfrom abc import ABC, abstractmethod\nfrom textwrap import dedent\nfrom collections.abc import Sequence\n\nfrom astropy.table import Table\n\nfrom sunpy.util.util import get_width\n\n__all__ = ['BaseQueryResponse', 'BaseClient']\n\n\nclass BaseQueryResponse(Sequence):\n    \"\"\"\n    An Abstract Base Class for results returned from BaseClient.\n\n    Notes\n    -----\n    * A QueryResponse object must be able to be instantiated with only one\n      iterable argument. (i.e. the ``__init__`` must only have one required\n      argument).\n    * The `client` property must be settable.\n    * The base class does not prescribe how you store the results from your\n      client, only that it must be possible to represent them as an astropy\n      table in the ``build_table`` method.\n    * `__getitem__` **must** return an instance of the type it was called on.\n      I.e. it must always return an object of ``type(self)``.\n\n    \"\"\"\n\n    @abstractmethod\n    def build_table(self):\n        \"\"\"\n        Return an `astropy.table.Table` representation of the query response.\n        \"\"\"\n\n    @property\n    @abstractmethod\n    def client(self):\n        \"\"\"\n        An instance of `BaseClient` used to generate the results.\n\n        Generally this is used to fetch the results later.\n\n        .. note::\n\n            In general, this doesn't have to be the same instance of\n            ``BaseClient``, this is left to the client developer. If there is a\n            significant connection overhead in creating an instance of a client\n            you might want it to be the same instance as used for the search.\n        \"\"\"\n\n    @client.setter\n    @abstractmethod\n    def client(self, value):\n        pass\n\n    @property\n    @abstractmethod\n    def blocks(self):\n        \"\"\"\n        A `collections.abc.Sequence` object which contains the records\n        contained within the Query Response.\n        \"\"\"\n\n    @abstractmethod\n    def response_block_properties(self):\n        \"\"\"\n        Returns a set of class attributes on all the response blocks.\n\n        Returns\n        -------\n        s : `set`\n            List of strings, containing attribute names in the response blocks.\n        \"\"\"\n\n    def __str__(self):\n        \"\"\"Print out human-readable summary of records retrieved\"\"\"\n        return '\\n'.join(self.build_table().pformat(show_dtype=False))\n\n    def __repr__(self):\n        \"\"\"Print out human-readable summary of records retrieved\"\"\"\n        return object.__repr__(self) + \"\\n\" + str(self)\n\n    def _repr_html_(self):\n        return self.build_table()._repr_html_()\n\n    def show(self, *cols):\n        \"\"\"\n        Returns response tables with desired columns for the Query.\n\n        Parameters\n        ----------\n        \\\\*cols : `tuple`\n            Name of columns to be shown.\n\n        Returns\n        -------\n        `astropy.table.Table`\n            A table showing values for specified columns.\n        \"\"\"\n        table = self.build_table()\n        if len(cols) == 0:\n            return table\n        return table[list(cols)]\n\n\ndef _print_client(client, html=False):\n    \"\"\"\n    Given a BaseClient instance will print out each registered attribute.\n\n    Parameters\n    ----------\n    client : `sunpy.net.base_client.BaseClient`\n        The instance class to print for.\n    html : bool\n        Will return a html table instead.\n\n    Returns\n    -------\n    `str`\n        String with the client.\n    \"\"\"\n    width = -1 if html else get_width()\n    class_name = f\"{client.__module__+'.' or ''}{client.__class__.__name__}\"\n    attrs = client.register_values()\n    lines = []\n    t = Table(names=[\"Attr Type\", \"Name\", \"Description\"],\n              dtype=[\"U80\", \"U80\", \"U80\"])\n    for client_key in attrs.keys():\n        for name, desc in attrs[client_key]:\n            t.add_row((client_key.__name__, name, desc))\n    lines = [class_name, dedent(client.__doc__.partition(\"\\n\\n\")[0])]\n    if html:\n        lines = [f\"<p>{line}</p>\" for line in lines]\n    lines.extend(t.pformat_all(show_dtype=False, max_width=width, align=\"<\", html=html))\n    return '\\n'.join(lines)\n\n\nclass BaseClient(ABC):\n    \"\"\"\n    This defines the Abstract Base Class for each download client.\n\n    The BaseClient has several abstract methods that ensure that any subclass enforces the bare minimum API.\n    These are `search`, `fetch` and `_can_handle_query`.\n    The last one ensures that each download client can be registered with Fido.\n\n    Most download clients should subclass `~sunpy.net.dataretriever.GenericClient`.\n    If the structure of `~sunpy.net.dataretriever.GenericClient`\n    is not useful you should use `~sunpy.net.BaseClient`.\n    `~sunpy.net.vso.VSOClient` and `~sunpy.net.jsoc.JSOCClient`\n    are examples of download clients that subclass ``BaseClient``.\n    \"\"\"\n\n    _registry = dict()\n\n    def __init_subclass__(cls, *args, **kwargs):\n        \"\"\"\n        An __init_subclass__ hook initializes all of the subclasses of a given class.\n        So for each subclass, it will call this block of code on import.\n        This replicates some metaclass magic without the need to be aware of metaclasses.\n        Here we use this to register each subclass in a dict that has the `_can_handle_query` attribute.\n        This is then passed into the UnifiedDownloaderFactory so we can register them.\n        This means that Fido can use the clients internally.\n        \"\"\"\n        super().__init_subclass__(**kwargs)\n\n        # We do not want to register GenericClient since its a dummy client.\n        if cls.__name__ in ('GenericClient'):\n            return\n\n        cls._registry[cls] = cls._can_handle_query\n\n        if hasattr(cls, \"_attrs_module\"):\n            from sunpy.net import attrs\n\n            name, module = cls._attrs_module()\n            module_obj = importlib.import_module(module)\n\n            existing_mod = getattr(attrs, name, None)\n            if existing_mod and existing_mod is not module_obj:\n                raise NameError(f\"{name} has already been registered as an attrs name.\")\n\n            setattr(attrs, name, module_obj)\n\n            if name not in attrs.__all__:\n                attrs.__all__.append(name)\n\n        # Register client attrs after it has regsitered its own attrs\n        from sunpy.net import attr\n        values = cls.register_values()\n        # If the client has no support, we won't try to register attrs\n        if values:\n            attr.Attr.update_values({cls: values})\n\n    def __repr__(self):\n        \"\"\"\n        Returns the normal repr plus the pretty client __str__.\n        \"\"\"\n        return object.__repr__(self) + \"\\n\" + str(self)\n\n    def __str__(self):\n        \"\"\"\n        This enables the \"pretty\" printing of BaseClient.\n        \"\"\"\n        return _print_client(self)\n\n    def _repr_html_(self):\n        \"\"\"\n        This enables the \"pretty\" printing of the BaseClient with html.\n        \"\"\"\n        return _print_client(self, html=True)\n\n    @abstractmethod\n    def search(self, *args, **kwargs):\n        \"\"\"\n        This enables the user to search for data using the client.\n\n        Must return a subclass of `BaseQueryResponse`.\n        \"\"\"\n\n    @abstractmethod\n    def fetch(self, *query_results, path=None, overwrite=False, progress=True,\n              max_conn=5, downloader=None, wait=True, **kwargs):\n        \"\"\"\n        This enables the user to fetch the data using the client, after a search.\n\n        Parameters\n        ----------\n        query_results:\n            Results to download.\n        path : `str` or `pathlib.Path`, optional\n            Path to the download directory\n        overwrite : `bool`, optional\n            Replace files with the same name if True.\n        progress : `bool`, optional\n            Print progress info to terminal.\n        max_conns : `int`, optional\n            Maximum number of download connections.\n        downloader : `parfive.Downloader`, optional\n            The download manager to use.\n        wait : `bool`, optional\n           If `False` ``downloader.download()`` will not be called. Only has\n           any effect if `downloader` is not `None`.\n\n        Returns\n        -------\n        `parfive.Results`\n            The results object, can be `None` if ``wait`` is `False`.\n        \"\"\"\n\n    @classmethod\n    @abstractmethod\n    def _can_handle_query(cls, *query):\n        \"\"\"\n        This enables the client to register what kind of searches it can handle, to prevent Fido\n        using the incorrect client.\n        \"\"\"\n\n    @staticmethod\n    def check_attr_types_in_query(query, required_attrs={}, optional_attrs={}):\n        \"\"\"\n        Check a query againsted required and optional attributes.\n\n        Returns `True` if *query* contains all the attrs in *required_attrs*,\n        and if *query* contains only attrs in both *required_attrs* and *optional_attrs*.\n        \"\"\"\n        query_attrs = {type(x) for x in query}\n        all_attrs = required_attrs.union(optional_attrs)\n\n        return required_attrs.issubset(query_attrs) and query_attrs.issubset(all_attrs)\n\n    @classmethod\n    def register_values(cls, *query):\n        \"\"\"\n        This enables the client to register what kind of Attrs it can use directly.\n\n        Returns\n        -------\n        `dict`\n            A dictionary with key values of Attrs and the values are a tuple of\n            (\"Attr Type\", \"Name\", \"Description\").\n        \"\"\"\n        return {}\n", "path": "sunpy/net/base_client.py"}]}