Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
==================

- Add support for <EnumTypeDef>. By @bzah
- Update XSD schema and dataclasses to latest version from netcdf-java to add support
for unsigned types. By @bzah
- Add support for scalar variables. By @Bzah
- [fix] empty attributes now are parsed into an empty string instead of crashing the parser. By @Bzah

0.3.1 (2023-11-10)
==================
Expand Down
8 changes: 6 additions & 2 deletions schemas/ncml-2.2.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
<xsd:attribute name="value" type="xsd:string"/>
<xsd:attribute name="separator" type="xsd:string"/>
<xsd:attribute name="orgName" type="xsd:string"/>
<xsd:attribute name="isUnsigned" type="xsd:boolean"/>
<xsd:attribute name="isUnsigned" type="xsd:boolean"/> <!-- deprecated - use unsigned type -->
</xsd:complexType>
</xsd:element>

Expand All @@ -136,12 +136,16 @@
<xsd:enumeration value="enum1"/>
<xsd:enumeration value="enum2"/>
<xsd:enumeration value="enum4"/>
<xsd:enumeration value="ubyte"/>
<xsd:enumeration value="ushort"/>
<xsd:enumeration value="uint"/>
<xsd:enumeration value="ulong"/>
</xsd:restriction>
</xsd:simpleType>

<!-- XML encoding of enum typedef object -->
<xsd:element name="enumTypedef">
<xsd:complexType>
<xsd:complexType mixed="true">
<xsd:sequence>
<xsd:element name="enum" minOccurs="1" maxOccurs="unbounded">
<xsd:complexType mixed="true">
Expand Down
4 changes: 4 additions & 0 deletions tests/data/testEmptyAttr.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
<attribute name="comment" value="" />
</netcdf>
5 changes: 5 additions & 0 deletions tests/data/testEmptyScalar.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
<variable name="empty_scalar_var" type="double" shape="">
</variable>
</netcdf>
6 changes: 6 additions & 0 deletions tests/data/testEmptyScalar_withMultipleValues.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
<variable name="empty_scalar_var" type="double" shape="">
<values>1 2 3 42</values>
</variable>
</netcdf>
6 changes: 6 additions & 0 deletions tests/data/testEmptyScalar_withValuesTag.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
<variable name="empty_scalar_var" type="double" shape="">
<values></values>
</variable>
</netcdf>
1 change: 1 addition & 0 deletions tests/data/testEnums.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
<enum key="1">true</enum>
</enumTypedef>
<variable name="be_or_not_to_be" shape="" type="enum1" typedef="boolean">
<values>0</values>
</variable>
</netcdf>
6 changes: 6 additions & 0 deletions tests/data/testUnsignedType.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<netcdf xmlns="http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2">
<variable name="be_or_not_to_be" shape="" type="uint">
<values>42</values>
</variable>
</netcdf>
34 changes: 34 additions & 0 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,46 @@ def test_read_meta_data():
assert ds.variables['T'].attrs['units'] == 'degC'


def test_unsigned_type():
ds = xncml.open_ncml(data / 'testUnsignedType.xml')
assert ds['be_or_not_to_be'].dtype == np.uintc


def test_empty_scalar__no_values_tag():
"""
Scalar without values loose their type because we can't create a typed numpy
scalar which is empty
"""
ds = xncml.open_ncml(data / 'testEmptyScalar.xml')
assert ds['empty_scalar_var'].dtype == np.dtype('O')
assert ds['empty_scalar_var'].item() is None


def test_empty_scalar__with_empty_values_tag():
"""A scalar variable with an empty <values> tag is invalid."""
with pytest.raises(ValueError, match='No values found for variable .*'):
xncml.open_ncml(data / 'testEmptyScalar_withValuesTag.xml')


def test_multiple_values_for_scalar():
"""Scalar with an multiple values in <values> tag is invalid."""
with pytest.raises(ValueError, match='The expected size for variable .* was 1, .*'):
xncml.open_ncml(data / 'testEmptyScalar_withMultipleValues.xml')


def test_read_enum():
"""A enum should be turned into CF flag_values and flag_meanings attributes."""
ds = xncml.open_ncml(data / 'testEnums.xml')
assert ds['be_or_not_to_be'].attrs['flag_values'] == [0, 1]
assert ds['be_or_not_to_be'].attrs['flag_meanings'] == ['false', 'true']


def test_empty_attr():
"""A empty attribute is valid."""
ds = xncml.open_ncml(data / 'testEmptyAttr.xml')
assert ds.attrs['comment'] == ''


# --- #
def check_dimension(ds):
assert len(ds['lat']) == 3
Expand Down
25 changes: 18 additions & 7 deletions xncml/generated/ncml_2_2.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class DataType(Enum):
ENUM1 = 'enum1'
ENUM2 = 'enum2'
ENUM4 = 'enum4'
UBYTE = 'ubyte'
USHORT = 'ushort'
UINT = 'uint'
ULONG = 'ulong'


class ObjectType(Enum):
Expand Down Expand Up @@ -289,13 +293,6 @@ class Meta:
name = 'enumTypedef'
namespace = 'http://www.unidata.ucar.edu/namespaces/netcdf/ncml-2.2'

enum: List['EnumTypedef.EnumType'] = field(
default_factory=list,
metadata={
'type': 'Element',
'min_occurs': 1,
},
)
name: Optional[str] = field(
default=None,
metadata={
Expand All @@ -309,6 +306,20 @@ class Meta:
'type': 'Attribute',
},
)
content: List[object] = field(
default_factory=list,
metadata={
'type': 'Wildcard',
'namespace': '##any',
'mixed': True,
'choices': (
{
'name': 'enum',
'type': Type['EnumTypedef.EnumType'],
},
),
},
)

@dataclass
class EnumType:
Expand Down
Loading