Skip to content

Commit

Permalink
Merge pull request #1250 from braingram/bug/ndarray_schema
Browse files Browse the repository at this point in the history
fixes #1245
  • Loading branch information
WilliamJamieson authored Dec 13, 2022
2 parents 4213bd0 + 80d5904 commit 73d65ec
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ The ASDF Standard is at v1.6.0
The ASDF Standard is at v1.6.0

- Fix issue #1239, close memmap with asdf file context [#1241]
- Add ndarray-1.1.0 and integer-1.1.0 support [#1250]

2.14.0 (2022-11-22)
-------------------
Expand Down
3 changes: 2 additions & 1 deletion asdf/tags/core/integer.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down Expand Up @@ -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)
Expand Down
11 changes: 8 additions & 3 deletions asdf/tags/core/ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -564,6 +565,9 @@ def __operation__(self, *args):
return __operation__


classes_to_modify = NDArrayType.__versioned_siblings + [
NDArrayType,
]
for op in [
"__neg__",
"__pos__",
Expand Down Expand Up @@ -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):
Expand Down
33 changes: 33 additions & 0 deletions asdf/tests/test_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -655,3 +655,36 @@ def test_custom_reference_cycle(tmp_path):

with asdf.open(path, extensions=FractionWithInverseExtension()) as af:
assert af["fraction"].inverse.inverse is af["fraction"]


def test_super_use_in_versioned_subclass():
"""
Test fix for issue: https://github.com/asdf-format/asdf/issues/1245
Legacy extensions cannot use super in subclasses of CustomType
that define supported_versions due to the metaclasses inability
to create distinct __classcell__ closures.
"""

class Foo:
def __init__(self, bar):
self.bar = bar

with pytest.raises(RuntimeError, match=r".* ExtensionTypeMeta .* __classcell__ .*"):

class FooType(asdf.CustomType):
name = "foo"
version = (1, 0, 0)
supported_versions = [(1, 1, 0), (1, 2, 0)]
types = [Foo]

@classmethod
def to_tree(cls, node, ctx):
return {"bar": node.bar}

@classmethod
def from_tree(cls, tree, ctx):
return Foo(tree["bar"])

def __getattribute__(self, name):
return super().__getattribute__(name)
4 changes: 1 addition & 3 deletions asdf/tests/test_versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,11 @@ def xfail_version_map_support_cases(request):
version = request.getfixturevalue("version")
if (version, tag) in [
("1.6.0", "tag:stsci.edu:asdf/core/column-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/core/integer-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/core/ndarray-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/core/table-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/fits/fits-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/time/time-1.2.0"),
("1.6.0", "tag:stsci.edu:asdf/unit/defunit-1.0.0"),
("1.6.0", "tag:stsci.edu:asdf/unit/defunit-1.1.0"),
("1.6.0", "tag:stsci.edu:asdf/unit/defunit-1.0.0"),
("1.6.0", "tag:stsci.edu:asdf/unit/quantity-1.2.0"),
("1.6.0", "tag:stsci.edu:asdf/unit/unit-1.1.0"),
("1.5.0", "tag:stsci.edu:asdf/unit/defunit-1.0.0"),
Expand Down
9 changes: 9 additions & 0 deletions asdf/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down

0 comments on commit 73d65ec

Please sign in to comment.