Repository: asdf-format/asdf (python)

Issue:
`asdf.util.load_yaml` fails on recursive object
# Description of the problem

Attempting to read an asdf file with a recursive reference using `asdf.util.load_yaml` fails with `ConstructorError: found unconstructable recursive node`.

# Example of the problem

```python
import asdf
d = {}
d['a'] = d
asdf.AsdfFile(d).write_to("recursive.asdf")
asdf.util.load_yaml("recursive.asdf")
```
Produces:
```
ConstructorError: found unconstructable recursive node
```

Note that passing `tagged=True` is a work-around for the above issue (as it triggers using the `AsdfLoader` which handles the recursion).

# System information

asdf version: main
python version: 3.10
operating system: osx


Pull request description:
use yaml constructors for _IgnoreCustomTagsLoader
Closes #1821

## Description

The fix in #1825 was partial (only covering non-tagged nodes) since `construct_mapping` is not a generator but `construct_yaml_map` is).

This PR updates `_IgnoreCustomTagsLoader` to use `construct_yaml_map` and `construct_yaml_seq` (both generators) to handled tagged recursive structures.

## Tasks

- [ ] [run `pre-commit` on your machine](https://pre-commit.com/#quick-start)
- [ ] run `pytest` on your machine
- [ ] Does this PR add new features and / or change user-facing code / API? (if not, label with `no-changelog-entry-needed`)
    - [ ] write news fragment(s) in `changes/`: `echo "changed something" > changes/<PR#>.<changetype>.rst` (see below for change types)
    - [ ] update relevant docstrings and / or `docs/` page
    - [ ] for any new features, add unit tests

<details><summary>news fragment change types...</summary>

- ``changes/<PR#>.feature.rst``: new feature
- ``changes/<PR#>.bugfix.rst``: bug fix
- ``changes/<PR#>.doc.rst``: documentation change
- ``changes/<PR#>.removal.rst``: deprecation or removal of public API
- ``changes/<PR#>.general.rst``: infrastructure or miscellaneous change
</details>


Patch:
diff --git a/asdf/yamlutil.py b/asdf/yamlutil.py
index 5615f4b8..c1143814 100644
--- a/asdf/yamlutil.py
+++ b/asdf/yamlutil.py
@@ -147,9 +147,9 @@ class _IgnoreCustomTagsLoader(_yaml_base_loader):
 
     def construct_undefined(self, node):
         if isinstance(node, yaml.MappingNode):
-            return self.construct_mapping(node)
+            return self.construct_yaml_map(node)
         elif isinstance(node, yaml.SequenceNode):
-            return self.construct_sequence(node)
+            return self.construct_yaml_seq(node)
         elif isinstance(node, yaml.ScalarNode):
             return self.construct_scalar(node)
         return super().construct_undefined(node)
diff --git a/changes/1907.bugfix.rst b/changes/1907.bugfix.rst
new file mode 100644
index 00000000..6e933c6a
--- /dev/null
+++ b/changes/1907.bugfix.rst
@@ -0,0 +1,1 @@
+Support recursive tagged nodes in load_yaml.


Test patch:
diff --git a/asdf/_tests/test_util.py b/asdf/_tests/test_util.py
index 97923e79..814e90f6 100644
--- a/asdf/_tests/test_util.py
+++ b/asdf/_tests/test_util.py
@@ -128,3 +128,21 @@ def test_load_yaml_recursion(tmp_path, tagged):
     tree = util.load_yaml(fn, tagged=tagged)
     assert tree["d"]["d"] is tree["d"]
     assert tree["l"][0] is tree["l"]
+
+
+@pytest.mark.parametrize("tagged", [True, False])
+def test_load_yaml_recursion_with_tags(tagged):
+    contents = b"""#ASDF 1.0.0
+#ASDF_STANDARD 1.6.0
+%YAML 1.1
+%TAG ! tag:stsci.edu:asdf/
+--- !core/asdf-1.1.0
+o: &id001 !some/tag-1.0.0
+  inverse: !some/tag-1.0.0
+    inverse: *id001
+l: &id002 !some/tag-1.0.0
+  - *id002
+..."""
+    tree = util.load_yaml(io.BytesIO(contents), tagged=tagged)
+    assert tree["o"] is tree["o"]["inverse"]["inverse"]
+    assert tree["l"] is tree["l"][0]