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

deprecate AsdfFile attrs and methods that use legacy extension api #1417

Merged
merged 3 commits into from
Feb 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The ASDF Standard is at v1.6.0
- Add AsdfDeprecationWarning to asdf.type_index [#1403]
- Add warning to use of asdftool extract and remove-hdu about deprecation
and impending removal [#1411]
- Deprecate AsdfFile attributes that use the legacy extension api [#1417]

2.14.3 (2022-12-15)
-------------------
Expand Down
106 changes: 89 additions & 17 deletions asdf/asdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ def __init__(
self._user_extensions = self._process_user_extensions(extensions)
self._plugin_extensions = self._process_plugin_extensions()
self._extension_manager = None
self._extension_list = None
self._extension_list_ = None

if custom_schema is not None:
self._custom_schema = schema._load_schema_cached(custom_schema, self.resolver, True, False)
self._custom_schema = schema._load_schema_cached(custom_schema, self._resolver, True, False)
else:
self._custom_schema = None

Expand Down Expand Up @@ -170,7 +170,7 @@ def __init__(
# Set directly to self._tree (bypassing property), since
# we can assume the other AsdfFile is already valid.
self._tree = tree.tree
self.run_modifying_hook("copy_to_new_asdf", validate=False)
self._run_modifying_hook("copy_to_new_asdf", validate=False)
self.find_references()
else:
self.tree = tree
Expand Down Expand Up @@ -206,7 +206,7 @@ def version(self, value):
self._user_extensions = self._process_user_extensions(self._user_extensions)
self._plugin_extensions = self._process_plugin_extensions()
self._extension_manager = None
self._extension_list = None
self._extension_list_ = None

@property
def version_string(self):
Expand Down Expand Up @@ -247,7 +247,7 @@ def extensions(self, value):
"""
self._user_extensions = self._process_user_extensions(value)
self._extension_manager = None
self._extension_list = None
self._extension_list_ = None

@property
def extension_manager(self):
Expand All @@ -271,10 +271,20 @@ def extension_list(self):
-------
asdf.extension.AsdfExtensionList
"""
if self._extension_list is None:
self._extension_list = get_cached_asdf_extension_list(self._user_extensions + self._plugin_extensions)
warnings.warn(
"AsdfFile.extension_list is deprecated. "
"Please see the new extension API "
"https://asdf.readthedocs.io/en/stable/asdf/extending/converters.html",
AsdfDeprecationWarning,
)
return self._extension_list

@property
def _extension_list(self):
if self._extension_list_ is None:
self._extension_list_ = get_cached_asdf_extension_list(self._user_extensions + self._plugin_extensions)
return self._extension_list_

def __enter__(self):
return self

Expand Down Expand Up @@ -500,23 +510,67 @@ def tag_to_schema_resolver(self):
"The 'tag_to_schema_resolver' property is deprecated. Use 'tag_mapping' instead.",
AsdfDeprecationWarning,
)
return self.extension_list.tag_mapping
return self._tag_to_schema_resolver

@property
def _tag_to_schema_resolver(self):
return self._extension_list.tag_mapping

@property
def tag_mapping(self):
return self.extension_list.tag_mapping
warnings.warn(
"AsdfFile.tag_mapping is deprecated. "
"Please see Manifests "
"https://asdf.readthedocs.io/en/stable/asdf/extending/manifests.html",
AsdfDeprecationWarning,
)
return self._tag_mapping

@property
def _tag_mapping(self):
return self._extension_list.tag_mapping

@property
def url_mapping(self):
return self.extension_list.url_mapping
warnings.warn(
"AsdfFile.url_mapping is deprecated. "
"Please see Resources "
"https://asdf.readthedocs.io/en/stable/asdf/extending/resources.html",
AsdfDeprecationWarning,
)
return self._url_mapping

@property
def _url_mapping(self):
return self._extension_list.url_mapping

@property
def resolver(self):
return self.extension_list.resolver
warnings.warn(
"AsdfFile.resolver is deprecated. "
"Please see Resources "
"https://asdf.readthedocs.io/en/stable/asdf/extending/resources.html",
AsdfDeprecationWarning,
)
return self._resolver

@property
def _resolver(self):
return self._extension_list.resolver

@property
def type_index(self):
return self.extension_list.type_index
warnings.warn(
"AsdfFile.type_index is deprecated. "
"Please see the new extension API "
"https://asdf.readthedocs.io/en/stable/asdf/extending/converters.html",
AsdfDeprecationWarning,
)
return self._type_index

@property
def _type_index(self):
return self._extension_list.type_index

def resolve_uri(self, uri):
"""
Expand Down Expand Up @@ -903,7 +957,7 @@ def _open_asdf(
self._check_extensions(tree, strict=strict_extension_check)

self._tree = tree
self.run_hook("post_read")
self._run_hook("post_read")

return self

Expand Down Expand Up @@ -1118,7 +1172,7 @@ def _pre_write(self, fd, all_array_storage, all_array_compression, compression_k
self._all_array_compression_kwargs = compression_kwargs

if len(self._tree):
self.run_hook("pre_write")
self._run_hook("pre_write")

# This is where we'd do some more sophisticated block
# reorganization, if necessary
Expand All @@ -1143,7 +1197,7 @@ def _random_write(self, fd, pad_blocks, include_block_index):

def _post_write(self, fd):
if len(self._tree):
self.run_hook("post_write")
self._run_hook("post_write")

def update(
self,
Expand Down Expand Up @@ -1420,7 +1474,16 @@ def run_hook(self, hookname):
with this name, it will be called for every instance of the
corresponding custom type in the tree.
"""
type_index = self.type_index
warnings.warn(
"AsdfFile.run_hook is deprecated. "
"Please see the new extension API "
"https://asdf.readthedocs.io/en/stable/asdf/extending/converters.html",
AsdfDeprecationWarning,
)
self._run_hook(hookname)

def _run_hook(self, hookname):
type_index = self._type_index

if not type_index.has_hook(hookname):
return
Expand All @@ -1446,7 +1509,16 @@ def run_modifying_hook(self, hookname, validate=True):
validate : bool
When `True` (default) validate the resulting tree.
"""
type_index = self.type_index
warnings.warn(
"AsdfFile.run_modifying_hook is deprecated. "
"Please see the new extension API "
"https://asdf.readthedocs.io/en/stable/asdf/extending/converters.html",
AsdfDeprecationWarning,
)
return self._run_modifying_hook(hookname, validate=validate)

def _run_modifying_hook(self, hookname, validate=True):
type_index = self._type_index

if not type_index.has_hook(hookname):
return None
Expand Down
2 changes: 1 addition & 1 deletion asdf/block.py
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@ def _find_used_blocks(self, tree, ctx):
for node in treeutil.iter_tree(tree):
# check that this object will not be handled by a converter
if not ctx.extension_manager.handles_type(type(node)):
hook = ctx.type_index.get_hook_for_type("reserve_blocks", type(node), ctx.version_string)
hook = ctx._type_index.get_hook_for_type("reserve_blocks", type(node), ctx.version_string)
if hook is not None:
for block in hook(node, ctx):
reserved_blocks.add(block)
Expand Down
4 changes: 2 additions & 2 deletions asdf/commands/tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ def list_tags(display_classes=False, iostream=sys.stdout):
tag_pairs = []
for tag in af.extension_manager._converters_by_tag:
tag_pairs.append((tag, af.extension_manager.get_converter_for_tag(tag).types))
for tag in af.type_index._type_by_tag:
tag_pairs.append((tag, [af.type_index._type_by_tag[tag]]))
for tag in af._type_index._type_by_tag:
tag_pairs.append((tag, [af._type_index._type_by_tag[tag]]))

for tag, types in sorted(tag_pairs, key=lambda pair: pair[0]):
string = str(tag)
Expand Down
6 changes: 4 additions & 2 deletions asdf/commands/tests/test_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from asdf import AsdfFile
from asdf.commands import list_tags
from asdf.exceptions import AsdfDeprecationWarning


@pytest.mark.parametrize("display_classes", [True, False])
Expand All @@ -19,7 +20,8 @@ def test_all_tags_present():
tags = {line.strip() for line in iostream.readlines()}

af = AsdfFile()
for tag in af.type_index._type_by_tag:
assert tag in tags
with pytest.warns(AsdfDeprecationWarning, match="AsdfFile.type_index is deprecated"):
for tag in af.type_index._type_by_tag:
assert tag in tags
for tag in af.extension_manager._converters_by_tag:
assert tag in tags
8 changes: 4 additions & 4 deletions asdf/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ def iter_errors(self, instance, *args, **kwargs):
tag_def = self.serialization_context.extension_manager.get_tag_definition(tag)
schema_uris = tag_def.schema_uris
else:
schema_uris = [self.ctx.tag_mapping(tag)]
schema_uris = [self.ctx._tag_mapping(tag)]
if schema_uris[0] == tag:
schema_uris = []

Expand Down Expand Up @@ -573,8 +573,8 @@ def get_validator(

if validators is None:
validators = util.HashableDict(YAML_VALIDATORS.copy())
validators.update(ctx.extension_list.validators)
validators.update(ctx.extension_manager.validator_manager.get_jsonschema_validators())
validators.update(ctx._extension_list.validators)
validators.update(ctx._extension_manager.validator_manager.get_jsonschema_validators())

kwargs["resolver"] = _make_resolver(url_mapping)

Expand Down Expand Up @@ -672,7 +672,7 @@ def validate(instance, ctx=None, schema=None, validators=None, reading=False, *a

ctx = AsdfFile()

validator = get_validator({} if schema is None else schema, ctx, validators, ctx.resolver, *args, **kwargs)
validator = get_validator({} if schema is None else schema, ctx, validators, ctx._resolver, *args, **kwargs)
validator.validate(instance)

additional_validators = [_validate_large_literals]
Expand Down
4 changes: 3 additions & 1 deletion asdf/tags/core/tests/test_ndarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import asdf
from asdf import util
from asdf.exceptions import AsdfDeprecationWarning
from asdf.tags.core import ndarray
from asdf.tests import helpers
from asdf.tests.objects import CustomTestType
Expand Down Expand Up @@ -130,7 +131,8 @@ def test_dont_load_data():

buff.seek(0)
with asdf.open(buff) as ff:
ff.run_hook("reserve_blocks")
with pytest.warns(AsdfDeprecationWarning, match="AsdfFile.run_hook is deprecated"):
ff.run_hook("reserve_blocks")

# repr and str shouldn't load data
str(ff.tree["science_data"])
Expand Down
4 changes: 2 additions & 2 deletions asdf/tests/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ def recurse(old, new):
seen.add(id(old))
seen.add(id(new))

old_type = ctx.type_index.from_custom_type(type(old), version_string)
new_type = ctx.type_index.from_custom_type(type(new), version_string)
old_type = ctx._type_index.from_custom_type(type(old), version_string)
new_type = ctx._type_index.from_custom_type(type(new), version_string)

if (
old_type is not None
Expand Down
17 changes: 17 additions & 0 deletions asdf/tests/test_deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import pytest

import asdf
from asdf.exceptions import AsdfDeprecationWarning
from asdf.tests.helpers import assert_extension_correctness
from asdf.tests.objects import CustomExtension
Expand Down Expand Up @@ -44,3 +45,19 @@ def test_type_index_module_deprecation():
if "asdf.type_index" in sys.modules:
del sys.modules["asdf.type_index"]
import asdf.type_index # noqa: F401


@pytest.mark.parametrize("attr", ["url_mapping", "tag_mapping", "resolver", "extension_list", "type_index"])
def test_asdffile_legacy_extension_api_attr_deprecations(attr):
with asdf.AsdfFile() as af, pytest.warns(AsdfDeprecationWarning, match=f"AsdfFile.{attr} is deprecated"):
getattr(af, attr)


def test_asdfile_run_hook_deprecation():
with asdf.AsdfFile() as af, pytest.warns(AsdfDeprecationWarning, match="AsdfFile.run_hook is deprecated"):
af.run_hook("foo")


def test_asdfile_run_modifying_hook_deprecation():
with asdf.AsdfFile() as af, pytest.warns(AsdfDeprecationWarning, match="AsdfFile.run_modifying_hook is deprecated"):
af.run_modifying_hook("foo")
5 changes: 3 additions & 2 deletions asdf/tests/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,8 +261,9 @@ def test_asdf_file_resolver_hashing():
a1 = asdf.AsdfFile()
a2 = asdf.AsdfFile()

assert hash(a1.resolver) == hash(a2.resolver)
assert a1.resolver == a2.resolver
with pytest.warns(AsdfDeprecationWarning, match="AsdfFile.resolver is deprecated"):
assert hash(a1.resolver) == hash(a2.resolver)
assert a1.resolver == a2.resolver


def test_load_schema_from_resource_mapping():
Expand Down
4 changes: 2 additions & 2 deletions asdf/yamlutil.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ def _walker(obj):
if extension_manager.handles_type(type(obj)):
return _convert_obj(obj)

tag = ctx.type_index.from_custom_type(
tag = ctx._type_index.from_custom_type(
type(obj),
ctx.version_string,
_serialization_context=_serialization_context,
Expand Down Expand Up @@ -297,7 +297,7 @@ def _walker(node):
_serialization_context._mark_extension_used(converter.extension)
return obj

tag_type = ctx.type_index.from_yaml_tag(ctx, tag, _serialization_context=_serialization_context)
tag_type = ctx._type_index.from_yaml_tag(ctx, tag, _serialization_context=_serialization_context)
# This means the tag did not correspond to any type in our type index.
if tag_type is None:
if not ctx._ignore_unrecognized_tag:
Expand Down