Skip to content

Commit

Permalink
DAS-2034 - Convert to harmony.message_utility.rgetattr.
Browse files Browse the repository at this point in the history
  • Loading branch information
owenlittlejohns committed Dec 20, 2023
1 parent 0b45c1f commit 828cd16
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 70 deletions.
3 changes: 2 additions & 1 deletion hoss/dimension_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,14 @@
import numpy as np

from harmony.message import Message
from harmony.message_utility import rgetattr
from harmony.util import Config
from varinfo import VarInfoFromDmr

from hoss.bbox_utilities import flatten_list
from hoss.exceptions import InvalidNamedDimension, InvalidRequestedRange
from hoss.utilities import (format_variable_set_string, get_opendap_nc4,
get_value_or_default, rgetattr)
get_value_or_default)


IndexRange = Tuple[int]
Expand Down
3 changes: 2 additions & 1 deletion hoss/subset.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from typing import List, Set

from harmony.message import Message, Source, Variable as HarmonyVariable
from harmony.message_utility import rgetattr
from harmony.util import Config
from netCDF4 import Dataset
from numpy.ma import masked
Expand All @@ -17,7 +18,7 @@
from hoss.dimension_utilities import (add_index_range, get_fill_slice,
IndexRanges, is_index_subset,
get_requested_index_ranges,
prefetch_dimension_variables, rgetattr)
prefetch_dimension_variables)
from hoss.spatial import get_spatial_index_ranges
from hoss.temporal import get_temporal_index_ranges
from hoss.utilities import (download_url, format_variable_set_string,
Expand Down
19 changes: 0 additions & 19 deletions hoss/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,22 +145,3 @@ def get_value_or_default(value: Optional[float], default: float) -> float:
"""
return value if value is not None else default


def rgetattr(input_object, requested_attribute, *args):
""" This is a recursive version of the inbuilt `getattr` method, such that
it can be called to retrieve nested attributes. For example:
the Message.subset.shape within the input Harmony message.
Note, if a default value is specified, this will be returned if any
attribute in the specified chain is absent from the supplied object.
"""
if '.' not in requested_attribute:
result = getattr(input_object, requested_attribute, *args)
else:
attribute_pieces = requested_attribute.split('.')
result = rgetattr(getattr(input_object, attribute_pieces[0], *args),
'.'.join(attribute_pieces[1:]), *args)

return result
2 changes: 1 addition & 1 deletion pip_requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file should contain requirements to be installed via Pip.
# Open source packages available from PyPI
earthdata-varinfo ~= 1.0.0
harmony-service-lib ~= 1.0.23
harmony-service-lib ~= 1.0.25
netCDF4 ~= 1.6.4
numpy ~= 1.24.2
pyproj ~= 3.6.1
Expand Down
49 changes: 1 addition & 48 deletions tests/unit/test_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
format_variable_set_string,
get_constraint_expression, get_file_mimetype,
get_opendap_nc4, get_value_or_default,
move_downloaded_nc4, rgetattr)
move_downloaded_nc4)


class TestUtilities(TestCase):
Expand Down Expand Up @@ -255,50 +255,3 @@ def test_get_value_or_default(self):

with self.subTest('Value = None returns the supplied default'):
self.assertEqual(get_value_or_default(None, 20), 20)

def test_rgetattr(self):
""" Ensure that the recursive function can retrieve nested attributes
and uses the default argument when required.
"""
class Child:
def __init__(self, name):
self.name = name

class Parent:
def __init__(self, name, child_name):
self.name = name
self.child = Child(child_name)
self.none = None

test_parent = Parent('parent_name', 'child_name')

with self.subTest('Parent level attribute'):
self.assertEqual(rgetattr(test_parent, 'name'), 'parent_name')

with self.subTest('Nested attribute'):
self.assertEqual(rgetattr(test_parent, 'child.name'), 'child_name')
with self.subTest('Missing parent with default'):
self.assertEqual(rgetattr(test_parent, 'absent', 'default'),
'default')

with self.subTest('Missing child attribute with default'):
self.assertEqual(rgetattr(test_parent, 'child.absent', 'default'),
'default')
with self.subTest('Child requested, parent missing, default'):
self.assertEqual(
rgetattr(test_parent, 'none.something', 'default'),
'default'
)

with self.subTest('Missing parent, with no default'):
with self.assertRaises(AttributeError):
rgetattr(test_parent, 'absent')

with self.subTest('Missing child, with no default'):
with self.assertRaises(AttributeError):
rgetattr(test_parent, 'child.absent')

with self.subTest('Child requested, parent missing, no default'):
with self.assertRaises(AttributeError):
rgetattr(test_parent, 'none.something')

0 comments on commit 828cd16

Please sign in to comment.