Repository: sunpy/sunpy

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.



Discussion:
It would be good to have a simple self contained example that illustrates this issue.
Is this duplicate of https://github.com/sunpy/sunpy/issues/3321 ?

Resolving patch:
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__(self):
     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):
     """


Test patch:
diff --git a/sunpy/net/dataretriever/sources/tests/test_eve.py b/sunpy/net/dataretriever/sources/tests/test_eve.py
--- a/sunpy/net/dataretriever/sources/tests/test_eve.py
+++ b/sunpy/net/dataretriever/sources/tests/test_eve.py
@@ -126,3 +126,37 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.eve.EVEClient\n\nPro'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'SDO',
+        'instrument': 'eve',
+        'physobs': 'irradiance',
+        'provider': 'LASP'
+    }
+    urls = ['http://lasp.colorado.edu/eve/data_access/evewebdata/quicklook/L0CS/SpWx/'
+            '2016/20160101_EVE_L0CS_DIODES_1m.txt',
+            'http://lasp.colorado.edu/eve/data_access/evewebdata/quicklook/L0CS/SpWx/'
+            '2016/20160102_EVE_L0CS_DIODES_1m.txt']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'eve'
diff --git a/sunpy/net/dataretriever/sources/tests/test_fermi_gbm.py b/sunpy/net/dataretriever/sources/tests/test_fermi_gbm.py
--- a/sunpy/net/dataretriever/sources/tests/test_fermi_gbm.py
+++ b/sunpy/net/dataretriever/sources/tests/test_fermi_gbm.py
@@ -7,6 +7,7 @@
 from sunpy.net.dataretriever.client import QueryResponse
 from sunpy.net.fido_factory import UnifiedResponse
 from sunpy.net.tests.strategies import time_attr
+from sunpy.time import parse_time
 from sunpy.time.timerange import TimeRange
 
 
@@ -88,3 +89,37 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.fermi_gbm.GBMClien'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'FERMI',
+        'instrument': 'GBM',
+        'physobs': 'flux',
+        'provider': 'NASA'
+    }
+    urls = ['https://heasarc.gsfc.nasa.gov/FTP/fermi/data/gbm/daily/'
+            '2016/01/01/current/glg_cspec_n5_160101_v00.pha',
+            'https://heasarc.gsfc.nasa.gov/FTP/fermi/data/gbm/daily/'
+            '2016/01/02/current/glg_cspec_n5_160102_v00.pha']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'GBM'
diff --git a/sunpy/net/dataretriever/sources/tests/test_goes_suvi.py b/sunpy/net/dataretriever/sources/tests/test_goes_suvi.py
--- a/sunpy/net/dataretriever/sources/tests/test_goes_suvi.py
+++ b/sunpy/net/dataretriever/sources/tests/test_goes_suvi.py
@@ -62,11 +62,14 @@ def test_get_url_for_timerange_errors(suvi_client):
         suvi_client._get_url_for_timerange(tr, satellitenumber=1)
 
 
-def mock_querry_object(suvi_client, start, end, wave):
+def mock_query_object(suvi_client):
     """
     Creating a Query Response object and prefilling it with some information
     """
     # Creating a Query Response Object
+    start = '2019/05/25 00:50'
+    end = '2019/05/25 00:52'
+    wave = 94 * u.Angstrom
     obj = {
         'TimeRange': TimeRange(parse_time(start), parse_time(end)),
         'Time_start': parse_time(start),
@@ -74,10 +77,13 @@ def mock_querry_object(suvi_client, start, end, wave):
         'source': 'GOES',
         'instrument': 'SUVI',
         'physobs': 'flux',
-        'provider': 'NOAA'
+        'provider': 'NOAA',
+        'wavelength': wave
     }
-    results = QueryResponse.create(obj, suvi_client._get_url_for_timerange(TimeRange(start, end),
-                                                                           wavelength=wave), client=suvi_client)
+    urls = ['https://data.ngdc.noaa.gov/platforms/solar-space-observing-satellites'
+            '/goes/goes16/l2/data/suvi-l2-ci094/2019/05/25/'
+            'dr_suvi-l2-ci094_g16_s20190525T005200Z_e20190525T005600Z_v1-0-0.fits']
+    results = QueryResponse.create(obj, urls, client=suvi_client)
     return results
 
 
@@ -89,7 +95,7 @@ def test_attr_reg():
 @pytest.mark.remote_data
 def test_fetch_working(suvi_client):
     """
-    Tests if the online server for fermi_gbm is working.
+    Tests if the online server for goes_suvi is working.
     This also checks if the mock is working well.
     """
     start = '2019/05/25 00:50'
@@ -98,7 +104,7 @@ def test_fetch_working(suvi_client):
     qr1 = suvi_client.search(a.Time(start, end), a.Instrument.suvi, a.Wavelength(wave))
 
     # Mock QueryResponse object
-    mock_qr = mock_querry_object(suvi_client, start, end, wave)
+    mock_qr = mock_query_object(suvi_client)
 
     # Compare if two objects have the same attribute
 
@@ -207,3 +213,13 @@ def test_query(suvi_client, start, end, expected_num_files):
     assert len(qr1) == expected_num_files
     assert qr1.time_range().start == parse_time('2019/05/25 00:52')
     assert qr1.time_range().end == parse_time('2019/05/25 00:56')
+
+
+def test_show(suvi_client):
+    mock_qr = mock_query_object(suvi_client)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'SUVI'
diff --git a/sunpy/net/dataretriever/sources/tests/test_goes_ud.py b/sunpy/net/dataretriever/sources/tests/test_goes_ud.py
--- a/sunpy/net/dataretriever/sources/tests/test_goes_ud.py
+++ b/sunpy/net/dataretriever/sources/tests/test_goes_ud.py
@@ -165,3 +165,35 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.goes.XRSClient\n\nPr'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'nasa',
+        'instrument': 'goes',
+        'physobs': 'irradiance',
+        'provider': 'sdac'
+    }
+    urls = ['https://umbra.nascom.nasa.gov/goes/fits/2016/go1520160101.fits',
+            'https://umbra.nascom.nasa.gov/goes/fits/2016/go1520160102.fits']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'goes'
diff --git a/sunpy/net/dataretriever/sources/tests/test_lyra_ud.py b/sunpy/net/dataretriever/sources/tests/test_lyra_ud.py
--- a/sunpy/net/dataretriever/sources/tests/test_lyra_ud.py
+++ b/sunpy/net/dataretriever/sources/tests/test_lyra_ud.py
@@ -8,6 +8,7 @@
 from sunpy.net.dataretriever.client import QueryResponse
 from sunpy.net.fido_factory import UnifiedResponse
 from sunpy.net.tests.strategies import range_time
+from sunpy.time import parse_time
 from sunpy.time.timerange import TimeRange
 
 
@@ -91,3 +92,35 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.lyra.LYRAClient\n\nP'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'Proba2',
+        'instrument': 'lyra',
+        'physobs': 'irradiance',
+        'provider': 'esa'
+    }
+    urls = ['http://proba2.oma.be/lyra/data/bsd/2016/01/01/lyra_20160101-000000_lev2_std.fits',
+            'http://proba2.oma.be/lyra/data/bsd/2016/01/02/lyra_20160102-000000_lev2_std.fits']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'lyra'
diff --git a/sunpy/net/dataretriever/sources/tests/test_noaa.py b/sunpy/net/dataretriever/sources/tests/test_noaa.py
--- a/sunpy/net/dataretriever/sources/tests/test_noaa.py
+++ b/sunpy/net/dataretriever/sources/tests/test_noaa.py
@@ -184,3 +184,13 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.noaa.NOAAIndicesCl'
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object('2012/10/4', '2012/10/6')
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'noaa-indices'
diff --git a/sunpy/net/dataretriever/sources/tests/test_norh.py b/sunpy/net/dataretriever/sources/tests/test_norh.py
--- a/sunpy/net/dataretriever/sources/tests/test_norh.py
+++ b/sunpy/net/dataretriever/sources/tests/test_norh.py
@@ -10,6 +10,7 @@
 from sunpy.net.dataretriever.client import QueryResponse
 from sunpy.net.fido_factory import UnifiedResponse
 from sunpy.net.tests.strategies import range_time, time_attr
+from sunpy.time import parse_time
 from sunpy.time.timerange import TimeRange
 
 
@@ -119,3 +120,38 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.norh.NoRHClient\n\nP'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    wave = 17000000*u.kHz
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'NAOJ',
+        'instrument': 'NORH',
+        'physobs': '',
+        'provider': 'NRO',
+        'wavelength': wave
+    }
+    urls = ['ftp://solar-pub.nao.ac.jp/pub/nsro/norh/data/tcx/2016/01/tca160101',
+            'ftp://solar-pub.nao.ac.jp/pub/nsro/norh/data/tcx/2016/01/tca160102']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Wavelength', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Wavelength', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'NORH'
+    assert qrshow1['Wavelength'][0] == str(17000000*u.kHz)
diff --git a/sunpy/net/dataretriever/sources/tests/test_rhessi.py b/sunpy/net/dataretriever/sources/tests/test_rhessi.py
--- a/sunpy/net/dataretriever/sources/tests/test_rhessi.py
+++ b/sunpy/net/dataretriever/sources/tests/test_rhessi.py
@@ -200,3 +200,36 @@ def test_client_repr(LCClient):
     """
     output = str(LCClient)
     assert output[:50] == 'sunpy.net.dataretriever.sources.rhessi.RHESSIClien'
+
+
+def mock_query_object(LCClient):
+    """
+    Creating a Query Response object and prefilling it with some information
+    """
+    # Creating a Query Response Object
+    start = '2016/1/1'
+    end = '2016/1/2'
+    obj = {
+        'TimeRange': TimeRange(parse_time(start), parse_time(end)),
+        'Time_start': parse_time(start),
+        'Time_end': parse_time(end),
+        'source': 'rhessi',
+        'instrument': 'rhessi',
+        'physobs': 'irradiance',
+        'provider': 'nasa'
+    }
+    urls = [
+        'https://hesperia.gsfc.nasa.gov/hessidata/metadata/catalog/hsi_obssumm_20160101_078.fits',
+        'https://hesperia.gsfc.nasa.gov/hessidata/metadata/catalog/hsi_obssumm_20160102_084.fits']
+    results = QueryResponse.create(obj, urls, client=LCClient)
+    return results
+
+
+def test_show(LCClient):
+    mock_qr = mock_query_object(LCClient)
+    qrshow0 = mock_qr.show()
+    qrshow1 = mock_qr.show('Start Time', 'Instrument')
+    allcols = ['Start Time', 'End Time', 'Source', 'Instrument', 'Wavelength']
+    assert qrshow0.colnames == allcols
+    assert qrshow1.colnames == ['Start Time', 'Instrument']
+    assert qrshow0['Instrument'][0] == 'rhessi'
diff --git a/sunpy/net/jsoc/tests/test_jsoc.py b/sunpy/net/jsoc/tests/test_jsoc.py
--- a/sunpy/net/jsoc/tests/test_jsoc.py
+++ b/sunpy/net/jsoc/tests/test_jsoc.py
@@ -85,6 +85,15 @@ def test_build_table(client):
     assert columns == table.colnames
 
 
+def test_show(client):
+    jdict = {'TELESCOP': ['SDO/HMI', 'SDO/AIA'], 'CAR_ROT': [2145, 2145]}
+    responses = JSOCResponse(table=astropy.table.Table(jdict))
+    showtable = responses.show('TELESCOP')
+    assert isinstance(showtable, astropy.table.Table)
+    assert showtable.colnames == ['TELESCOP']
+    assert showtable['TELESCOP'][0] == 'SDO/HMI'
+
+
 @pytest.mark.remote_data
 def test_post_wavelength(client):
     responses = client.search(
diff --git a/sunpy/net/vso/tests/test_vso.py b/sunpy/net/vso/tests/test_vso.py
--- a/sunpy/net/vso/tests/test_vso.py
+++ b/sunpy/net/vso/tests/test_vso.py
@@ -268,6 +268,14 @@ def test_repr(mock_build_client):
     assert "Start Time End Time Source Instrument Type" in repr(qr)
 
 
+@mock.patch("sunpy.net.vso.vso.build_client", return_value=True)
+def test_show(mock_build_client):
+    qr = QueryResponse([])
+    qrshow = qr.show('Start Time', 'Source', 'Type')
+    assert str(qrshow) == ('Start Time Source Type\n'
+                           '---------- ------ ----')
+
+
 @pytest.mark.remote_data
 def test_path(client, tmpdir):
     """