From 690eb5dd68e32353bb432039144591716da819b7 Mon Sep 17 00:00:00 2001 From: Brett Date: Tue, 29 Nov 2022 13:40:11 -0500 Subject: [PATCH] support integer-1.1 and ndarray-1.1 fixes an issue with integer where InterType instead of cls was used during class instantiation which resulted in objects being created with the incorrect version. Prior code (that only had one integer version, 1.0) did not suffer from issues because of this bug. fixes #1245 by removing the use of super in NDArrayType and adding an exception to check for incompatible use of super in classes of type ExtensionTypeMeta. --- asdf/tags/core/integer.py | 3 ++- asdf/tags/core/ndarray.py | 11 ++++++++--- asdf/types.py | 9 +++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/asdf/tags/core/integer.py b/asdf/tags/core/integer.py index 574ff12df..ec8eeaa4c 100644 --- a/asdf/tags/core/integer.py +++ b/asdf/tags/core/integer.py @@ -44,6 +44,7 @@ class IntegerType(AsdfType): name = "core/integer" version = "1.0.0" + supported_versions = {"1.0.0", "1.1.0"} _value_cache = dict() @@ -96,7 +97,7 @@ def from_tree(cls, tree, ctx): if tree["sign"] == "-": value = -value - return IntegerType(value) + return cls(value) def __int__(self): return int(self._value) diff --git a/asdf/tags/core/ndarray.py b/asdf/tags/core/ndarray.py index ff139db4b..08daad783 100644 --- a/asdf/tags/core/ndarray.py +++ b/asdf/tags/core/ndarray.py @@ -214,6 +214,7 @@ def ascii_to_unicode(x): class NDArrayType(AsdfType): name = "core/ndarray" version = "1.0.0" + supported_versions = {"1.0.0", "1.1.0"} types = [np.ndarray, ma.MaskedArray] def __init__(self, source, shape, dtype, offset, strides, order, mask, asdffile): @@ -372,10 +373,10 @@ def __getattribute__(self, name): # can cause problems when the array is passed to other # libraries. # See https://github.com/asdf-format/asdf/issues/1015 - if name in ("name", "version"): + if name in ("name", "version", "supported_versions"): raise AttributeError(f"'{self.__class__.name}' object has no attribute '{name}'") else: - return super().__getattribute__(name) + return AsdfType.__getattribute__(self, name) @classmethod def from_tree(cls, node, ctx): @@ -564,6 +565,9 @@ def __operation__(self, *args): return __operation__ +classes_to_modify = NDArrayType.__versioned_siblings + [ + NDArrayType, +] for op in [ "__neg__", "__pos__", @@ -628,7 +632,8 @@ def __operation__(self, *args): "__delitem__", "__contains__", ]: - setattr(NDArrayType, op, _make_operation(op)) + [setattr(cls, op, _make_operation(op)) for cls in classes_to_modify] +del classes_to_modify def _get_ndim(instance): diff --git a/asdf/types.py b/asdf/types.py index dd53cf63e..bc1da66a6 100644 --- a/asdf/types.py +++ b/asdf/types.py @@ -133,6 +133,15 @@ def __new__(mcls, name, bases, attrs): new_attrs["version"] = version new_attrs["supported_versions"] = set() new_attrs["_latest_version"] = cls.version + if "__classcell__" in new_attrs: + raise RuntimeError( + "Subclasses of ExtensionTypeMeta that define " + "supported_versions cannot used super() to call " + "parent class functions. super() creates a " + "__classcell__ closure that cannot be duplicated " + "during creation of versioned siblings. " + "See https://github.com/asdf-format/asdf/issues/1245" + ) siblings.append(ExtensionTypeMeta.__new__(mcls, name, bases, new_attrs)) setattr(cls, "__versioned_siblings", siblings)