Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asdf odd handling of namedtuple that prevents implementing a Converter #1723

Open
braingram opened this issue Jan 3, 2024 · 0 comments
Open

Comments

@braingram
Copy link
Contributor

braingram commented Jan 3, 2024

Attempts to store a namedtuple instance in the tree result in behavior that doesn't match with other custom objects.

import collections
import asdf

NT = collections.namedtuple("NT", ("a", "b"))
nt = NT(1, 2)
af = asdf.AsdfFile({"nt": nt})
print(type(af['nt']))

produces

/Users/bgraham/projects/240103_named_tuple/asdf/asdf/treeutil.py:360: AsdfWarning: Failed to serialize instance of <class '__main__.NT'>, converting to list instead
  warnings.warn(f"Failed to serialize instance of {type(node)}, converting to list instead", AsdfWarning)
<class 'list'>

The warning can be silenced by passing ignore_implicit_conversion=True when creating the AsdfFile instance.

The conversion to a list loses the by-name item access possible with namedtuple.

This prevents creation of any Converter to support a specific namedtuple.

If the following line is changed to use type(node) == tuple:

elif isinstance(node, tuple):

it becomes possible to put namedtuple instances in the tree and to implement Converter instances for specific namedtuple classes. See the following:

import collections
import asdf


NT = collections.namedtuple("NT", ("a", "b"))
nt = NT(1, 2)

nt_tag = "asdf://example.com/tags/nt-1.0.0"


class NTConverter:
    types = [NT]
    tags = [nt_tag]

    def to_yaml_tree(self, obj, tag, ctx):
        return obj._asdict()

    def from_yaml_tree(self, obj, tag, ctx):
        return NT(**obj)


class NTExtension:
    converters=[NTConverter()]
    tags=[nt_tag]
    extension_uri = "asdf://example.com/extensions/nt-1.0.0"


with asdf.config_context() as cfg:
    cfg.add_extension(NTExtension())

    af = asdf.AsdfFile({"nt": nt})
    assert type(af["nt"]) == NT
    af.write_to("test.asdf")

    with asdf.open("test.asdf") as af:
        assert type(af["nt"]) == NT

In summary, the current way that namedtuple is supported seems incomplete and hinders customization by users.

I propose that we deprecate ignore_implicit_conversion drop our current "support" for namedtuple and allow users to implement Converter instances for any namedtuples they would like to serialize/deserialize.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant