Skip to content

Commit

Permalink
Handle more data types when parsing dataset.xml
Browse files Browse the repository at this point in the history
  • Loading branch information
lesserwhirls committed Apr 26, 2017
1 parent 33f7bb0 commit 8a096b7
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 19 deletions.
74 changes: 68 additions & 6 deletions siphon/ncss_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,84 @@
class _Types(object):
@staticmethod
def handle_typed_values(val, type_name, value_type):
if value_type == 'int':
r'''Translate typed values into the appropriate python object
Takes an element name, value, and type and returns a list
with the string value(s) properly converted to a python type.
TypedValues are handled in ucar.ma2.DataType in netcdfJava
in the DataType enum. Possibilities are:
"boolean"
"byte"
"char"
"short"
"int"
"long"
"float"
"double"
"Sequence"
"String"
"Structure"
"enum1"
"enum2"
"enum4"
"opaque"
"object"
All of these are values written as strings in the xml, so simply
applying int, float to the values will work in most cases (i.e.
the TDS encodes them as string values properly).
Examle XML element:
<attribute name="scale_factor" type="double" value="0.0010000000474974513"/>
Parameters
----------
val : string
The string representation of the value attribute of the xml element
type_name : string
The string representation of the name attribute of the xml element
value_type : string
The string representation of the type attribute of the xml element
Returns
-------
val : list
A list containing the properly typed python values.
'''
if value_type in ['byte','short', 'int', 'long']:
try:
val = val.split()
val = list(map(int, val))
except ValueError:
logging.warning('Cannot convert %s to float.', val)

elif value_type == 'float':
logging.warning('Cannot convert %s to int.', val)
elif value_type in ['float', 'double']:
try:
val = val.split()
val = list(map(float, val))
except ValueError:
logging.warning('Cannot convert %s to float', val)
elif value_type == 'boolean':
try:
# special case for boolean type
val = val.split()
val = [True if bool == 'true' else False for bool in val]
except ValueError:
logging.warning('Cannot convert %s to boolean', val)
elif value_type == 'String':
# nothing special for String type
pass
else:
logging.warning('%s type %s not understood.', type_name,
value_type)
# possibilities - Sequence, Structure, enum, opaque, object,
# and char.
# Not sure how to handle these as I do not have an example
# of how they would show up in dataset.xml
logging.warning('%s type %s not understood. Keeping as String.',
type_name, value_type)

if not isinstance(val, list):
val = [val]
Expand Down
93 changes: 80 additions & 13 deletions siphon/tests/test_ncss_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,47 @@ class TestSimpleTypes(object):
def setup_class(cls):
cls.types = _Types()

def test_attribute_1(self):
'Test parsing a string attribute'
xml = '<attribute name="long_name" value="Specified height level above ground"/>'
def test_attribute_byte(self):
'Test parsing a byte attribute'
xml = '<attribute name="missing_value" type="byte" value="1"/>'
element = ET.fromstring(xml)
expected = {'long_name': 'Specified height level above ground'}
expected = {'missing_value': [1]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_short(self):
'Test parsing a short attribute'
xml = '<attribute name="missing_value" type="short" value="-999"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [-999]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_2(self):
def test_attribute_int(self):
'Test parsing an int attribute'
xml = '<attribute name="missing_value" type="int" value="-999"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [-999]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_long(self):
'Test parsing a long attribute'
xml = '<attribute name="missing_value" type="long" value="-999"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [-999]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_float(self):
'Test parsing a float value attribute'
xml = '<attribute name="missing_value" type="float" value="-999.0"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [float(-999.0)]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_float_nan(self):
'Test parsing a float nan attribute'
import math
xml = '<attribute name="missing_value" type="float" value="NaN"/>'
Expand All @@ -64,19 +96,54 @@ def test_attribute_2(self):
assert(math.isnan(actual['missing_value'][0]))
assert(math.isnan(expected['missing_value'][0]))

def test_attribute_3(self):
'Test parsing a float value attribute'
xml = '<attribute name="missing_value" type="float" value="-999"/>'
def test_attribute_double(self):
'Test parsing a double attribute'
xml = '<attribute name="missing_value" type="double" value="-999.0"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [float(-999)]}
expected = {'missing_value': [-999.0]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_4(self):
'Test parsing an int attribute'
xml = '<attribute name="missing_value" type="int" value="-999"/>'
def test_attribute_double_nan(self):
'Test parsing a double nan attribute'
import math
xml = '<attribute name="missing_value" type="double" value="NaN"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [-999]}
expected = {'missing_value': [float('NaN')]}
actual = self.types.handle_attribute(element)
assert expected.keys() == actual.keys()
assert(math.isnan(actual['missing_value'][0]))
assert(math.isnan(expected['missing_value'][0]))

def test_attribute_string_implicit(self):
'Test parsing a string attribute'
xml = '<attribute name="long_name" value="Specified height level above ground"/>'
element = ET.fromstring(xml)
expected = {'long_name': 'Specified height level above ground'}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_string_explicit(self):
'Test parsing a string attribute'
xml = '<attribute name="long_name" type="String" value="Specified height level above ground"/>'
element = ET.fromstring(xml)
expected = {'long_name': ['Specified height level above ground']}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_boolean_true(self):
'Test parsing a boolean attribute'
xml = '<attribute name="missing_value" type="boolean" value="true"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [True]}
actual = self.types.handle_attribute(element)
assert expected == actual

def test_attribute_boolean_false(self):
'Test parsing a boolean attribute'
xml = '<attribute name="missing_value" type="boolean" value="false"/>'
element = ET.fromstring(xml)
expected = {'missing_value': [False]}
actual = self.types.handle_attribute(element)
assert expected == actual

Expand Down

0 comments on commit 8a096b7

Please sign in to comment.