From 55d7e7bb4f611c4ee1c04d0c511b68f8a275042f Mon Sep 17 00:00:00 2001 From: Ryan May Date: Sun, 9 Jul 2017 13:59:55 -0600 Subject: [PATCH] ENH: Add ability to access datasets by index (Fixes #134) When getting an item by string, work as before. For all else, treat as an index into values. Works for catalog refs as well. --- siphon/catalog.py | 16 ++++++++++++++-- siphon/tests/test_catalog.py | 11 +++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/siphon/catalog.py b/siphon/catalog.py index 9e4d8d2e4..3ed0dc8c0 100644 --- a/siphon/catalog.py +++ b/siphon/catalog.py @@ -24,6 +24,18 @@ log.setLevel(logging.ERROR) +class IndexableMapping(OrderedDict): + """Extend ``OrderedDict`` to allow index-based access to values.""" + + def __getitem__(self, item): + """Return an item either by index or name.""" + try: + item + '' # Raises if item not a string + return super().__getitem__(item) + except TypeError: + return list(self.values())[item] + + class TDSCatalog(object): """ Parse information from a THREDDS Client Catalog. @@ -79,9 +91,9 @@ def __init__(self, catalog_url): root = ET.fromstring(resp.text) self.catalog_name = root.attrib.get('name', 'No name found') - self.datasets = OrderedDict() + self.datasets = IndexableMapping() self.services = [] - self.catalog_refs = OrderedDict() + self.catalog_refs = IndexableMapping() self.metadata = {} self.ds_with_access_elements_to_process = [] service_skip_count = 0 diff --git a/siphon/tests/test_catalog.py b/siphon/tests/test_catalog.py index 305a9a534..82c0befce 100644 --- a/siphon/tests/test_catalog.py +++ b/siphon/tests/test_catalog.py @@ -116,6 +116,17 @@ def test_datasets_order(): 'Latest Collection for NAM CONUS 20km'] +@recorder.use_cassette('top_level_20km_rap_catalog') +def test_datasets_get_by_index(): + """Test that datasets can be accessed by index.""" + url = ('http://thredds.ucar.edu/thredds/catalog/grib/NCEP/NAM/' + 'CONUS_20km/noaaport/catalog.xml') + cat = TDSCatalog(url) + assert cat.datasets[0].name == 'Full Collection (Reference / Forecast Time) Dataset' + assert cat.datasets[1].name == 'Best NAM CONUS 20km Time Series' + assert cat.datasets[2].name == 'Latest Collection for NAM CONUS 20km' + + @recorder.use_cassette('top_level_cat') def test_catalog_ref_order(): """Test that catalog references are properly ordered."""