Repository: asdf-format/asdf

Issue:
yaml has not attribute `ConstructorError`
Attempts to raise `yaml.ConstructorError` are included in `asdf.yamlutil`.
https://github.com/asdf-format/asdf/blob/45b166188b58f8516f07f3f4c3399c0a10e61377/asdf/yamlutil.py#L178

For yaml 6.0 (and perhaps other versions) the `ConstructorError` attribute does not exist. However, `yaml.constructor.ConstructorError` does.

Discussion:

Patch:
diff --git a/asdf/yamlutil.py b/asdf/yamlutil.py
index e4b1d504..e40588b5 100644
--- a/asdf/yamlutil.py
+++ b/asdf/yamlutil.py
@@ -175,7 +175,7 @@ class AsdfLoader(_yaml_base_loader):
         yield omap
         if not isinstance(node, yaml.SequenceNode):
             msg = "while constructing an ordered map"
-            raise yaml.ConstructorError(
+            raise yaml.constructor.ConstructorError(
                 msg,
                 node.start_mark,
                 f"expected a sequence, but found {node.id}",
@@ -184,7 +184,7 @@ class AsdfLoader(_yaml_base_loader):
         for subnode in node.value:
             if not isinstance(subnode, yaml.MappingNode):
                 msg = "while constructing an ordered map"
-                raise yaml.ConstructorError(
+                raise yaml.constructor.ConstructorError(
                     msg,
                     node.start_mark,
                     f"expected a mapping of length 1, but found {subnode.id}",
@@ -192,10 +192,10 @@ class AsdfLoader(_yaml_base_loader):
                 )
             if len(subnode.value) != 1:
                 msg = "while constructing an ordered map"
-                raise yaml.ConstructorError(
+                raise yaml.constructor.ConstructorError(
                     msg,
                     node.start_mark,
-                    f"expected a single mapping item, but found {len(subnode.value): %d} items",
+                    f"expected a single mapping item, but found {len(subnode.value)} items",
                     subnode.start_mark,
                 )
             key_node, value_node = subnode.value[0]


Test patch:
diff --git a/asdf/_tests/test_yaml.py b/asdf/_tests/test_yaml.py
index a4f9f7e3..740fcff6 100644
--- a/asdf/_tests/test_yaml.py
+++ b/asdf/_tests/test_yaml.py
@@ -309,3 +309,27 @@ def test_ndarray_subclass_conversion(tmp_path):
         cfg.convert_unknown_ndarray_subclasses = False
         with pytest.raises(yaml.representer.RepresenterError, match=r".*cannot represent.*"):
             af.write_to(fn)
+
+
+@pytest.mark.parametrize(
+    "payload",
+    [
+        "  1: a",  # not a sequence
+        "- !!omap\n  - 1",  # sequence item, not a mapping
+        "- !!omap\n  1: a\n  2: a",  # sequence item, not a one element mapping
+    ],
+)
+def test_invalid_omap(payload):
+    test_yaml = f"""#ASDF {asdf.versioning.default_version}
+%YAML 1.1
+--- !<tag:stsci.edu:asdf/core/asdf-1.1.0>
+od: !!omap
+{payload}
+..."""
+
+    # Check that fully qualified explicit tags work
+    buff = helpers.yaml_to_asdf(test_yaml, yaml_headers=False)
+
+    with pytest.raises(yaml.constructor.ConstructorError):
+        with asdf.open(buff) as ff:
+            ff["od"]