We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fido HECClient returns out-of-date results
When trying to access HEC data through Fido HECClient, the data returned is ~1 month out of date. Looking at the current web gui for the HEC API, it returns events up to today but through Fido, the latest data is from ~ 2021-11-03

```python
from sunpy.net import Fido, attrs as a


timerange = a.Time('2021/11/01 00:00:00', '2021/12/01 00:00:00')
results_hec = Fido.search(timerange,
                           a.helio.TableName('gevloc_sxr_flare'))
results_hec                         
<sunpy.net.fido_factory.UnifiedResponse object at 0x000002B89664B730>
Results from 1 Provider:

10 Results from the HECClient:
     time_start     ...
------------------- ...
2021-11-02T02:57:00 ...
2021-11-02T07:37:00 ...
2021-11-02T12:55:00 ...
2021-11-02T21:09:00 ...
2021-11-03T00:10:00 ...
2021-11-03T00:56:00 ...
2021-11-03T08:15:00 ...
2021-11-03T14:32:00 ...
2021-11-03T14:43:00 ...
2021-11-03T15:18:00 ...

```
I have also tested with 'goes_sxr_flare' and get roughly the same time for the latest event ( 2021-11-02T21:09:00 )
You can see the expected returns from this query for both gevloc and goes_sxr here:

http://hec.helio-vo.eu/hec/hec_gui_fetch.php?y_from=2021&mo_from=11&d_from=1&y_to=2021&mo_to=12&d_to=1&radioremote=on&titlesearch2=&goes_sxr_flare=istable&gevloc_sxr_flare=istable


- SunPy Version: 3.1
- Astropy Version: 4.3.1
- Python Version: 3.8.8
- OS information: Win & WSL same issue


--- 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/helio/hec.py`
Content:
```
1 """
2 Access the Helio Event Catalogue
3 """
4 import io
5 import os
6 
7 from lxml import etree
8 from requests import Session
9 from zeep import Client
10 from zeep.transports import Transport
11 
12 from astropy.io.votable.table import parse_single_table
13 
14 from sunpy.net import attrs as a
15 from sunpy.net.base_client import BaseClient, QueryResponseTable
16 from sunpy.net.helio import attrs as ha
17 from sunpy.net.helio import parser
18 from sunpy.time import parse_time
19 from sunpy.util.exceptions import warn_deprecated
20 
21 __all__ = ['HECClient', 'HECResponse']
22 
23 
24 def votable_handler(xml_table):
25     """
26     Returns a VOtable object from a VOtable style xml string
27 
28     In order to get a VOtable object, it has to be parsed from an xml file or
29     file-like object. This function creates a file-like object via the
30     StringIO module, writes the xml data to it, then passes the file-like
31     object to parse_single_table() from the astropy.io.votable.table module
32     and thereby creates a VOtable object.
33 
34     Parameters
35     ----------
36     xml_table : `bytes`
37         Contains the VOtable style xml data
38 
39     Returns
40     -------
41     votable : `astropy.io.votable.tree.Table`
42         A properly formatted VOtable object
43 
44     """
45     fake_file = io.BytesIO()
46     fake_file.write(xml_table)
47     votable = parse_single_table(fake_file)
48     for i in range(len(votable.array)):
49         item = votable.array[i][0]
50         if isinstance(item, bytes):
51             votable.array[i] = (votable.array[i][0].decode(),)
52     fake_file.close()
53     return votable
54 
55 
56 class HECResponse(QueryResponseTable):
57     """
58     A container for data returned from HEC searches.
59     """
60 
61 
62 class HECClient(BaseClient):
63     """
64     Provides access to the HELIO webservices.
65     """
66 
67     def __init__(self, link=None):
68         """
69         The constructor; establishes the webservice link for the client
70 
71         Initializes the client with a weblink
72 
73         Parameters
74         ----------
75         link : str
76             Contains URL to valid WSDL endpoint
77 
78         Examples
79         --------
80         >>> from sunpy.net.helio import hec
81         >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA
82         """
83         if link is None:
84             # The default wsdl file
85             link = parser.wsdl_retriever()
86         session = Session()
87         # This is for use in our test suite.
88         session.verify = not(bool(os.environ.get("NO_VERIFY_HELIO_SSL", 0)))
89         transport = Transport(session=session)
90         self.hec_client = Client(link, transport=transport)
91 
92     @classmethod
93     def _can_handle_query(cls, *query):
94         required = {a.Time}
95         optional = {ha.MaxRecords, ha.TableName}
96         return cls.check_attr_types_in_query(query, required, optional)
97 
98     @classmethod
99     def _attrs_module(cls):
100         return 'helio', 'sunpy.net.helio.attrs'
101 
102     def search(self, *args, **kwargs):
103         """
104         The simple interface to query the wsdl service.
105 
106         Used to utilize the service's TimeQuery() method, this is a simple
107         interface between the sunpy module library and the web-service's API.
108 
109         Examples
110         --------
111         >>> from sunpy.net.helio import attrs as ha
112         >>> from sunpy.net import attrs as a, Fido
113         >>> timerange = a.Time('2005/01/03', '2005/12/03')
114         >>> res = Fido.search(timerange, ha.MaxRecords(10),
115         ...                   ha.TableName('rhessi_hxr_flare'))  # doctest: +REMOTE_DATA
116         >>> res  #doctest: +REMOTE_DATA
117         <sunpy.net.fido_factory.UnifiedResponse object at ...>
118         Results from 1 Provider:
119         <BLANKLINE>
120         10 Results from the HECClient:
121         hec_id      time_start          time_peak      ... energy_kev flare_number
122         ------ ------------------- ------------------- ... ---------- ------------
123          31463 2005-01-03T01:37:36 2005-01-03T01:37:54 ...          6      5010320
124          31464 2005-01-03T01:51:36 2005-01-03T01:59:18 ...         12      5010301
125          31465 2005-01-03T03:26:28 2005-01-03T03:42:50 ...          6      5010332
126          31466 2005-01-03T03:46:04 2005-01-03T04:07:10 ...         12      5010302
127          31467 2005-01-03T05:00:24 2005-01-03T05:00:30 ...          6      5010313
128          31468 2005-01-03T06:40:48 2005-01-03T06:42:46 ...          6      5010314
129          31469 2005-01-03T08:27:56 2005-01-03T08:28:26 ...          6      5010334
130          31470 2005-01-03T09:31:00 2005-01-03T09:33:34 ...          6      5010322
131          31471 2005-01-03T09:34:52 2005-01-03T09:59:46 ...          6      5010336
132          31472 2005-01-03T11:06:48 2005-01-03T11:07:18 ...         12      5010304
133         <BLANKLINE>
134         <BLANKLINE>
135         """
136         qrdict = {}
137         for elem in args:
138             if isinstance(elem, a.Time):
139                 qrdict['Time'] = elem
140             elif isinstance(elem, ha.MaxRecords):
141                 qrdict['max_records'] = elem.value
142             elif isinstance(elem, ha.TableName):
143                 qrdict['table_name'] = elem.value
144             else:
145                 raise ValueError(
146                     f"{elem.__class__.__name__} should be a ``attrs.Time``, ``attrs.hek.MaxRecords`` or ``attrs.hek.TableName`` attribute.")
147         qrdict.update(kwargs)
148         table = qrdict.get('table_name', None)
149         if table:
150             if isinstance(table, bytes):
151                 warn_deprecated('type `bytes` for table_name is deprecated, use `str` instead.')
152             table = str.encode(table)
153         start_time = qrdict['Time'].start
154         end_time = qrdict['Time'].end
155         max_records = qrdict.get('max_records', 10)
156         while table is None:
157             table = self.select_table()
158         start_time = parse_time(start_time)
159         end_time = parse_time(end_time)
160         results = self.hec_client.service.TimeQuery(STARTTIME=start_time.isot,
161                                                     ENDTIME=end_time.isot,
162                                                     FROM=table,
163                                                     MAXRECORDS=max_records)
164         results = votable_handler(etree.tostring(results))
165         return HECResponse(results.to_table(), client=self)
166 
167     def get_table_names(self):
168         """
169         Returns a list of the available tables to query.
170 
171         Returns the names of all the tables that can be queried via the
172         webservice.
173 
174         Returns
175         -------
176         tables.array: `numpy.ma.core.MaskedArray`
177             A VOtable table of available tables names.
178 
179         Examples
180         --------
181         >>> from sunpy.net.helio import hec
182         >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA
183         >>> print(hc.get_table_names())  # doctest: +REMOTE_DATA
184         [('timed_see_flare',) ('hi_event',) ('yohkoh_flare_list',)
185          ('wind_mfi_bs_crossing_time',) ('seeds_soho',) ('seeds_stb',)
186          ...
187          ('rhessi_hxr_flare',) ('cactus_soho_flow',) ('cactus_soho_cme',)
188          ('stereob_het_sep',)]
189         """
190         results = self.hec_client.service.getTableNames()
191         tables = votable_handler(etree.tostring(results))
192         return tables.array
193 
194     def select_table(self):
195         """
196         Creates a list of table names and prompts the user for a choice
197 
198         This takes the table of table names from get_table_names(), creates a
199         list of the names, sorts them, then presents the tables in a
200         convenient menu for the user to choose from. It returns a string
201         containing the name of the table that the user picked.
202 
203         Returns
204         -------
205         `str`
206             Contains the name of the table that the user picked.
207 
208         Examples
209         --------
210         >>> from sunpy.net.helio import hec  # doctest: +SKIP
211         >>> hc = hec.HECClient()  # doctest: +SKIP
212         >>> hc.select_table()  # doctest: +SKIP
213         """
214         tables = self.get_table_names()
215         table_list = [t[0] for t in tables if len(t[0]) > 0]
216         table_list.sort()
217         for index, table in enumerate(table_list):
218             print(f'{index + 1} - {table}')
219         while True:
220             user_input = input(f"\nPlease enter a table number between 1 and {len(table_list)} "
221                                "('e' to exit): ")
222             if user_input.lower() == "e" or user_input.lower() == "exit":
223                 return None
224             if user_input.isdigit() and 1 <= int(user_input) <= len(table_list):
225                 table_no = int(user_input)
226                 return table_list[table_no - 1]
227             else:
228                 print(f"Input must be an integer between 1 and {len(table_list)}")
229 
230     def fetch(self, *args, **kwargs):
231         """
232         This is a no operation function as this client does not download data.
233         """
234         return NotImplemented
235
```
--- 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/helio/hec.py b/sunpy/net/helio/hec.py
--- a/sunpy/net/helio/hec.py
+++ b/sunpy/net/helio/hec.py
@@ -16,7 +16,7 @@
 from sunpy.net.helio import attrs as ha
 from sunpy.net.helio import parser
 from sunpy.time import parse_time
-from sunpy.util.exceptions import warn_deprecated
+from sunpy.util.exceptions import warn_deprecated, warn_user
 
 __all__ = ['HECClient', 'HECResponse']
 
@@ -106,6 +106,10 @@
         Used to utilize the service's TimeQuery() method, this is a simple
         interface between the sunpy module library and the web-service's API.
 
+        .. note::
+           By default the maximum records returned by the service are limited to 500.
+           To obtain more results ``a.helio.MaxRecords`` must be set to a higher value.
+
         Examples
         --------
         >>> from sunpy.net.helio import attrs as ha
@@ -152,7 +156,7 @@
             table = str.encode(table)
         start_time = qrdict['Time'].start
         end_time = qrdict['Time'].end
-        max_records = qrdict.get('max_records', 10)
+        max_records = qrdict.get('max_records', 500)
         while table is None:
             table = self.select_table()
         start_time = parse_time(start_time)
@@ -162,7 +166,12 @@
                                                     FROM=table,
                                                     MAXRECORDS=max_records)
         results = votable_handler(etree.tostring(results))
-        return HECResponse(results.to_table(), client=self)
+        table = HECResponse(results.to_table(), client=self)
+        if len(table) == max_records == 500:
+            warn_user("Number of results is the same as the default `max_records` of 500. "
+                      "It is possible your query has been truncated. "
+                      "If you want to change this, set `a.helio.MaxRecords` to a higher value.")
+        return table
 
     def get_table_names(self):
         """

{"golden_diff": "diff --git a/sunpy/net/helio/hec.py b/sunpy/net/helio/hec.py\n--- a/sunpy/net/helio/hec.py\n+++ b/sunpy/net/helio/hec.py\n@@ -16,7 +16,7 @@\n from sunpy.net.helio import attrs as ha\n from sunpy.net.helio import parser\n from sunpy.time import parse_time\n-from sunpy.util.exceptions import warn_deprecated\n+from sunpy.util.exceptions import warn_deprecated, warn_user\n \n __all__ = ['HECClient', 'HECResponse']\n \n@@ -106,6 +106,10 @@\n         Used to utilize the service's TimeQuery() method, this is a simple\n         interface between the sunpy module library and the web-service's API.\n \n+        .. note::\n+           By default the maximum records returned by the service are limited to 500.\n+           To obtain more results ``a.helio.MaxRecords`` must be set to a higher value.\n+\n         Examples\n         --------\n         >>> from sunpy.net.helio import attrs as ha\n@@ -152,7 +156,7 @@\n             table = str.encode(table)\n         start_time = qrdict['Time'].start\n         end_time = qrdict['Time'].end\n-        max_records = qrdict.get('max_records', 10)\n+        max_records = qrdict.get('max_records', 500)\n         while table is None:\n             table = self.select_table()\n         start_time = parse_time(start_time)\n@@ -162,7 +166,12 @@\n                                                     FROM=table,\n                                                     MAXRECORDS=max_records)\n         results = votable_handler(etree.tostring(results))\n-        return HECResponse(results.to_table(), client=self)\n+        table = HECResponse(results.to_table(), client=self)\n+        if len(table) == max_records == 500:\n+            warn_user(\"Number of results is the same as the default `max_records` of 500. \"\n+                      \"It is possible your query has been truncated. \"\n+                      \"If you want to change this, set `a.helio.MaxRecords` to a higher value.\")\n+        return table\n \n     def get_table_names(self):\n         \"\"\"\n", "issue": "Fido HECClient returns out-of-date results\nWhen trying to access HEC data through Fido HECClient, the data returned is ~1 month out of date. Looking at the current web gui for the HEC API, it returns events up to today but through Fido, the latest data is from ~ 2021-11-03\r\n\r\n```python\r\nfrom sunpy.net import Fido, attrs as a\r\n\r\n\r\ntimerange = a.Time('2021/11/01 00:00:00', '2021/12/01 00:00:00')\r\nresults_hec = Fido.search(timerange,\r\n                           a.helio.TableName('gevloc_sxr_flare'))\r\nresults_hec                         \r\n<sunpy.net.fido_factory.UnifiedResponse object at 0x000002B89664B730>\r\nResults from 1 Provider:\r\n\r\n10 Results from the HECClient:\r\n     time_start     ...\r\n------------------- ...\r\n2021-11-02T02:57:00 ...\r\n2021-11-02T07:37:00 ...\r\n2021-11-02T12:55:00 ...\r\n2021-11-02T21:09:00 ...\r\n2021-11-03T00:10:00 ...\r\n2021-11-03T00:56:00 ...\r\n2021-11-03T08:15:00 ...\r\n2021-11-03T14:32:00 ...\r\n2021-11-03T14:43:00 ...\r\n2021-11-03T15:18:00 ...\r\n\r\n```\r\nI have also tested with 'goes_sxr_flare' and get roughly the same time for the latest event ( 2021-11-02T21:09:00 )\r\nYou can see the expected returns from this query for both gevloc and goes_sxr here:\r\n\r\nhttp://hec.helio-vo.eu/hec/hec_gui_fetch.php?y_from=2021&mo_from=11&d_from=1&y_to=2021&mo_to=12&d_to=1&radioremote=on&titlesearch2=&goes_sxr_flare=istable&gevloc_sxr_flare=istable\r\n\r\n\r\n- SunPy Version: 3.1\r\n- Astropy Version: 4.3.1\r\n- Python Version: 3.8.8\r\n- OS information: Win & WSL same issue\r\n\n", "before_files": [{"content": "\"\"\"\nAccess the Helio Event Catalogue\n\"\"\"\nimport io\nimport os\n\nfrom lxml import etree\nfrom requests import Session\nfrom zeep import Client\nfrom zeep.transports import Transport\n\nfrom astropy.io.votable.table import parse_single_table\n\nfrom sunpy.net import attrs as a\nfrom sunpy.net.base_client import BaseClient, QueryResponseTable\nfrom sunpy.net.helio import attrs as ha\nfrom sunpy.net.helio import parser\nfrom sunpy.time import parse_time\nfrom sunpy.util.exceptions import warn_deprecated\n\n__all__ = ['HECClient', 'HECResponse']\n\n\ndef votable_handler(xml_table):\n    \"\"\"\n    Returns a VOtable object from a VOtable style xml string\n\n    In order to get a VOtable object, it has to be parsed from an xml file or\n    file-like object. This function creates a file-like object via the\n    StringIO module, writes the xml data to it, then passes the file-like\n    object to parse_single_table() from the astropy.io.votable.table module\n    and thereby creates a VOtable object.\n\n    Parameters\n    ----------\n    xml_table : `bytes`\n        Contains the VOtable style xml data\n\n    Returns\n    -------\n    votable : `astropy.io.votable.tree.Table`\n        A properly formatted VOtable object\n\n    \"\"\"\n    fake_file = io.BytesIO()\n    fake_file.write(xml_table)\n    votable = parse_single_table(fake_file)\n    for i in range(len(votable.array)):\n        item = votable.array[i][0]\n        if isinstance(item, bytes):\n            votable.array[i] = (votable.array[i][0].decode(),)\n    fake_file.close()\n    return votable\n\n\nclass HECResponse(QueryResponseTable):\n    \"\"\"\n    A container for data returned from HEC searches.\n    \"\"\"\n\n\nclass HECClient(BaseClient):\n    \"\"\"\n    Provides access to the HELIO webservices.\n    \"\"\"\n\n    def __init__(self, link=None):\n        \"\"\"\n        The constructor; establishes the webservice link for the client\n\n        Initializes the client with a weblink\n\n        Parameters\n        ----------\n        link : str\n            Contains URL to valid WSDL endpoint\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec\n        >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA\n        \"\"\"\n        if link is None:\n            # The default wsdl file\n            link = parser.wsdl_retriever()\n        session = Session()\n        # This is for use in our test suite.\n        session.verify = not(bool(os.environ.get(\"NO_VERIFY_HELIO_SSL\", 0)))\n        transport = Transport(session=session)\n        self.hec_client = Client(link, transport=transport)\n\n    @classmethod\n    def _can_handle_query(cls, *query):\n        required = {a.Time}\n        optional = {ha.MaxRecords, ha.TableName}\n        return cls.check_attr_types_in_query(query, required, optional)\n\n    @classmethod\n    def _attrs_module(cls):\n        return 'helio', 'sunpy.net.helio.attrs'\n\n    def search(self, *args, **kwargs):\n        \"\"\"\n        The simple interface to query the wsdl service.\n\n        Used to utilize the service's TimeQuery() method, this is a simple\n        interface between the sunpy module library and the web-service's API.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import attrs as ha\n        >>> from sunpy.net import attrs as a, Fido\n        >>> timerange = a.Time('2005/01/03', '2005/12/03')\n        >>> res = Fido.search(timerange, ha.MaxRecords(10),\n        ...                   ha.TableName('rhessi_hxr_flare'))  # doctest: +REMOTE_DATA\n        >>> res  #doctest: +REMOTE_DATA\n        <sunpy.net.fido_factory.UnifiedResponse object at ...>\n        Results from 1 Provider:\n        <BLANKLINE>\n        10 Results from the HECClient:\n        hec_id      time_start          time_peak      ... energy_kev flare_number\n        ------ ------------------- ------------------- ... ---------- ------------\n         31463 2005-01-03T01:37:36 2005-01-03T01:37:54 ...          6      5010320\n         31464 2005-01-03T01:51:36 2005-01-03T01:59:18 ...         12      5010301\n         31465 2005-01-03T03:26:28 2005-01-03T03:42:50 ...          6      5010332\n         31466 2005-01-03T03:46:04 2005-01-03T04:07:10 ...         12      5010302\n         31467 2005-01-03T05:00:24 2005-01-03T05:00:30 ...          6      5010313\n         31468 2005-01-03T06:40:48 2005-01-03T06:42:46 ...          6      5010314\n         31469 2005-01-03T08:27:56 2005-01-03T08:28:26 ...          6      5010334\n         31470 2005-01-03T09:31:00 2005-01-03T09:33:34 ...          6      5010322\n         31471 2005-01-03T09:34:52 2005-01-03T09:59:46 ...          6      5010336\n         31472 2005-01-03T11:06:48 2005-01-03T11:07:18 ...         12      5010304\n        <BLANKLINE>\n        <BLANKLINE>\n        \"\"\"\n        qrdict = {}\n        for elem in args:\n            if isinstance(elem, a.Time):\n                qrdict['Time'] = elem\n            elif isinstance(elem, ha.MaxRecords):\n                qrdict['max_records'] = elem.value\n            elif isinstance(elem, ha.TableName):\n                qrdict['table_name'] = elem.value\n            else:\n                raise ValueError(\n                    f\"{elem.__class__.__name__} should be a ``attrs.Time``, ``attrs.hek.MaxRecords`` or ``attrs.hek.TableName`` attribute.\")\n        qrdict.update(kwargs)\n        table = qrdict.get('table_name', None)\n        if table:\n            if isinstance(table, bytes):\n                warn_deprecated('type `bytes` for table_name is deprecated, use `str` instead.')\n            table = str.encode(table)\n        start_time = qrdict['Time'].start\n        end_time = qrdict['Time'].end\n        max_records = qrdict.get('max_records', 10)\n        while table is None:\n            table = self.select_table()\n        start_time = parse_time(start_time)\n        end_time = parse_time(end_time)\n        results = self.hec_client.service.TimeQuery(STARTTIME=start_time.isot,\n                                                    ENDTIME=end_time.isot,\n                                                    FROM=table,\n                                                    MAXRECORDS=max_records)\n        results = votable_handler(etree.tostring(results))\n        return HECResponse(results.to_table(), client=self)\n\n    def get_table_names(self):\n        \"\"\"\n        Returns a list of the available tables to query.\n\n        Returns the names of all the tables that can be queried via the\n        webservice.\n\n        Returns\n        -------\n        tables.array: `numpy.ma.core.MaskedArray`\n            A VOtable table of available tables names.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec\n        >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA\n        >>> print(hc.get_table_names())  # doctest: +REMOTE_DATA\n        [('timed_see_flare',) ('hi_event',) ('yohkoh_flare_list',)\n         ('wind_mfi_bs_crossing_time',) ('seeds_soho',) ('seeds_stb',)\n         ...\n         ('rhessi_hxr_flare',) ('cactus_soho_flow',) ('cactus_soho_cme',)\n         ('stereob_het_sep',)]\n        \"\"\"\n        results = self.hec_client.service.getTableNames()\n        tables = votable_handler(etree.tostring(results))\n        return tables.array\n\n    def select_table(self):\n        \"\"\"\n        Creates a list of table names and prompts the user for a choice\n\n        This takes the table of table names from get_table_names(), creates a\n        list of the names, sorts them, then presents the tables in a\n        convenient menu for the user to choose from. It returns a string\n        containing the name of the table that the user picked.\n\n        Returns\n        -------\n        `str`\n            Contains the name of the table that the user picked.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec  # doctest: +SKIP\n        >>> hc = hec.HECClient()  # doctest: +SKIP\n        >>> hc.select_table()  # doctest: +SKIP\n        \"\"\"\n        tables = self.get_table_names()\n        table_list = [t[0] for t in tables if len(t[0]) > 0]\n        table_list.sort()\n        for index, table in enumerate(table_list):\n            print(f'{index + 1} - {table}')\n        while True:\n            user_input = input(f\"\\nPlease enter a table number between 1 and {len(table_list)} \"\n                               \"('e' to exit): \")\n            if user_input.lower() == \"e\" or user_input.lower() == \"exit\":\n                return None\n            if user_input.isdigit() and 1 <= int(user_input) <= len(table_list):\n                table_no = int(user_input)\n                return table_list[table_no - 1]\n            else:\n                print(f\"Input must be an integer between 1 and {len(table_list)}\")\n\n    def fetch(self, *args, **kwargs):\n        \"\"\"\n        This is a no operation function as this client does not download data.\n        \"\"\"\n        return NotImplemented\n", "path": "sunpy/net/helio/hec.py"}], "after_files": [{"content": "\"\"\"\nAccess the Helio Event Catalogue\n\"\"\"\nimport io\nimport os\n\nfrom lxml import etree\nfrom requests import Session\nfrom zeep import Client\nfrom zeep.transports import Transport\n\nfrom astropy.io.votable.table import parse_single_table\n\nfrom sunpy.net import attrs as a\nfrom sunpy.net.base_client import BaseClient, QueryResponseTable\nfrom sunpy.net.helio import attrs as ha\nfrom sunpy.net.helio import parser\nfrom sunpy.time import parse_time\nfrom sunpy.util.exceptions import warn_deprecated, warn_user\n\n__all__ = ['HECClient', 'HECResponse']\n\n\ndef votable_handler(xml_table):\n    \"\"\"\n    Returns a VOtable object from a VOtable style xml string\n\n    In order to get a VOtable object, it has to be parsed from an xml file or\n    file-like object. This function creates a file-like object via the\n    StringIO module, writes the xml data to it, then passes the file-like\n    object to parse_single_table() from the astropy.io.votable.table module\n    and thereby creates a VOtable object.\n\n    Parameters\n    ----------\n    xml_table : `bytes`\n        Contains the VOtable style xml data\n\n    Returns\n    -------\n    votable : `astropy.io.votable.tree.Table`\n        A properly formatted VOtable object\n\n    \"\"\"\n    fake_file = io.BytesIO()\n    fake_file.write(xml_table)\n    votable = parse_single_table(fake_file)\n    for i in range(len(votable.array)):\n        item = votable.array[i][0]\n        if isinstance(item, bytes):\n            votable.array[i] = (votable.array[i][0].decode(),)\n    fake_file.close()\n    return votable\n\n\nclass HECResponse(QueryResponseTable):\n    \"\"\"\n    A container for data returned from HEC searches.\n    \"\"\"\n\n\nclass HECClient(BaseClient):\n    \"\"\"\n    Provides access to the HELIO webservices.\n    \"\"\"\n\n    def __init__(self, link=None):\n        \"\"\"\n        The constructor; establishes the webservice link for the client\n\n        Initializes the client with a weblink\n\n        Parameters\n        ----------\n        link : str\n            Contains URL to valid WSDL endpoint\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec\n        >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA\n        \"\"\"\n        if link is None:\n            # The default wsdl file\n            link = parser.wsdl_retriever()\n        session = Session()\n        # This is for use in our test suite.\n        session.verify = not(bool(os.environ.get(\"NO_VERIFY_HELIO_SSL\", 0)))\n        transport = Transport(session=session)\n        self.hec_client = Client(link, transport=transport)\n\n    @classmethod\n    def _can_handle_query(cls, *query):\n        required = {a.Time}\n        optional = {ha.MaxRecords, ha.TableName}\n        return cls.check_attr_types_in_query(query, required, optional)\n\n    @classmethod\n    def _attrs_module(cls):\n        return 'helio', 'sunpy.net.helio.attrs'\n\n    def search(self, *args, **kwargs):\n        \"\"\"\n        The simple interface to query the wsdl service.\n\n        Used to utilize the service's TimeQuery() method, this is a simple\n        interface between the sunpy module library and the web-service's API.\n\n        .. note::\n           By default the maximum records returned by the service are limited to 500.\n           To obtain more results ``a.helio.MaxRecords`` must be set to a higher value.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import attrs as ha\n        >>> from sunpy.net import attrs as a, Fido\n        >>> timerange = a.Time('2005/01/03', '2005/12/03')\n        >>> res = Fido.search(timerange, ha.MaxRecords(10),\n        ...                   ha.TableName('rhessi_hxr_flare'))  # doctest: +REMOTE_DATA\n        >>> res  #doctest: +REMOTE_DATA\n        <sunpy.net.fido_factory.UnifiedResponse object at ...>\n        Results from 1 Provider:\n        <BLANKLINE>\n        10 Results from the HECClient:\n        hec_id      time_start          time_peak      ... energy_kev flare_number\n        ------ ------------------- ------------------- ... ---------- ------------\n         31463 2005-01-03T01:37:36 2005-01-03T01:37:54 ...          6      5010320\n         31464 2005-01-03T01:51:36 2005-01-03T01:59:18 ...         12      5010301\n         31465 2005-01-03T03:26:28 2005-01-03T03:42:50 ...          6      5010332\n         31466 2005-01-03T03:46:04 2005-01-03T04:07:10 ...         12      5010302\n         31467 2005-01-03T05:00:24 2005-01-03T05:00:30 ...          6      5010313\n         31468 2005-01-03T06:40:48 2005-01-03T06:42:46 ...          6      5010314\n         31469 2005-01-03T08:27:56 2005-01-03T08:28:26 ...          6      5010334\n         31470 2005-01-03T09:31:00 2005-01-03T09:33:34 ...          6      5010322\n         31471 2005-01-03T09:34:52 2005-01-03T09:59:46 ...          6      5010336\n         31472 2005-01-03T11:06:48 2005-01-03T11:07:18 ...         12      5010304\n        <BLANKLINE>\n        <BLANKLINE>\n        \"\"\"\n        qrdict = {}\n        for elem in args:\n            if isinstance(elem, a.Time):\n                qrdict['Time'] = elem\n            elif isinstance(elem, ha.MaxRecords):\n                qrdict['max_records'] = elem.value\n            elif isinstance(elem, ha.TableName):\n                qrdict['table_name'] = elem.value\n            else:\n                raise ValueError(\n                    f\"{elem.__class__.__name__} should be a ``attrs.Time``, ``attrs.hek.MaxRecords`` or ``attrs.hek.TableName`` attribute.\")\n        qrdict.update(kwargs)\n        table = qrdict.get('table_name', None)\n        if table:\n            if isinstance(table, bytes):\n                warn_deprecated('type `bytes` for table_name is deprecated, use `str` instead.')\n            table = str.encode(table)\n        start_time = qrdict['Time'].start\n        end_time = qrdict['Time'].end\n        max_records = qrdict.get('max_records', 500)\n        while table is None:\n            table = self.select_table()\n        start_time = parse_time(start_time)\n        end_time = parse_time(end_time)\n        results = self.hec_client.service.TimeQuery(STARTTIME=start_time.isot,\n                                                    ENDTIME=end_time.isot,\n                                                    FROM=table,\n                                                    MAXRECORDS=max_records)\n        results = votable_handler(etree.tostring(results))\n        table = HECResponse(results.to_table(), client=self)\n        if len(table) == max_records == 500:\n            warn_user(\"Number of results is the same as the default `max_records` of 500. \"\n                      \"It is possible your query has been truncated. \"\n                      \"If you want to change this, set `a.helio.MaxRecords` to a higher value.\")\n        return table\n\n    def get_table_names(self):\n        \"\"\"\n        Returns a list of the available tables to query.\n\n        Returns the names of all the tables that can be queried via the\n        webservice.\n\n        Returns\n        -------\n        tables.array: `numpy.ma.core.MaskedArray`\n            A VOtable table of available tables names.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec\n        >>> hc = hec.HECClient()  # doctest: +REMOTE_DATA\n        >>> print(hc.get_table_names())  # doctest: +REMOTE_DATA\n        [('timed_see_flare',) ('hi_event',) ('yohkoh_flare_list',)\n         ('wind_mfi_bs_crossing_time',) ('seeds_soho',) ('seeds_stb',)\n         ...\n         ('rhessi_hxr_flare',) ('cactus_soho_flow',) ('cactus_soho_cme',)\n         ('stereob_het_sep',)]\n        \"\"\"\n        results = self.hec_client.service.getTableNames()\n        tables = votable_handler(etree.tostring(results))\n        return tables.array\n\n    def select_table(self):\n        \"\"\"\n        Creates a list of table names and prompts the user for a choice\n\n        This takes the table of table names from get_table_names(), creates a\n        list of the names, sorts them, then presents the tables in a\n        convenient menu for the user to choose from. It returns a string\n        containing the name of the table that the user picked.\n\n        Returns\n        -------\n        `str`\n            Contains the name of the table that the user picked.\n\n        Examples\n        --------\n        >>> from sunpy.net.helio import hec  # doctest: +SKIP\n        >>> hc = hec.HECClient()  # doctest: +SKIP\n        >>> hc.select_table()  # doctest: +SKIP\n        \"\"\"\n        tables = self.get_table_names()\n        table_list = [t[0] for t in tables if len(t[0]) > 0]\n        table_list.sort()\n        for index, table in enumerate(table_list):\n            print(f'{index + 1} - {table}')\n        while True:\n            user_input = input(f\"\\nPlease enter a table number between 1 and {len(table_list)} \"\n                               \"('e' to exit): \")\n            if user_input.lower() == \"e\" or user_input.lower() == \"exit\":\n                return None\n            if user_input.isdigit() and 1 <= int(user_input) <= len(table_list):\n                table_no = int(user_input)\n                return table_list[table_no - 1]\n            else:\n                print(f\"Input must be an integer between 1 and {len(table_list)}\")\n\n    def fetch(self, *args, **kwargs):\n        \"\"\"\n        This is a no operation function as this client does not download data.\n        \"\"\"\n        return NotImplemented\n", "path": "sunpy/net/helio/hec.py"}]}