Skip to content

Commit

Permalink
Merge pull request asdf-format#1745 from braingram/version_map
Browse files Browse the repository at this point in the history
Deprecate `AsdfFile.version_map`
  • Loading branch information
braingram authored Mar 25, 2024
2 parents 9b9d015 + 233db09 commit 1dbf3d7
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 221 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ The ASDF Standard is at v1.6.0
- Only show ``str`` representation during ``info`` and ``search``
if it contains a single line (and does not fail) [#1748]

- Deprecate ``AsdfFile.version_map`` [#1745]

3.0.1 (2023-10-30)
------------------

Expand Down
24 changes: 16 additions & 8 deletions asdf/_asdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@ def __init__(
"""
self._fname = ""

# make a new AsdfVersion instance here so files don't share the same instance
self._file_format_version = versioning.AsdfVersion(versioning._FILE_FORMAT_VERSION)

# Don't use the version setter here; it tries to access
# the extensions, which haven't been assigned yet.
if version is None:
Expand All @@ -167,8 +170,6 @@ def __init__(
# that we've already warned about for this file.
self._warned_tag_pairs = set()

self._file_format_version = None

# Context of a call to treeutil.walk_and_modify, needed in the AsdfFile
# in case walk_and_modify is re-entered by extension code (via
# custom_tree_to_tagged_tree or tagged_tree_to_custom_tree).
Expand Down Expand Up @@ -258,7 +259,11 @@ def version_string(self):

@property
def version_map(self):
return versioning.get_version_map(self.version_string)
warnings.warn(
"AsdfFile.version_map is deprecated. Please use the extension_manager",
AsdfDeprecationWarning,
)
return versioning._get_version_map(self.version_string)

@property
def extensions(self):
Expand Down Expand Up @@ -470,9 +475,6 @@ def _update_extension_history(self, tree, serialization_context):

@property
def file_format_version(self):
if self._file_format_version is None:
return versioning.AsdfVersion(self.version_map["FILE_FORMAT"])

return self._file_format_version

def close(self):
Expand Down Expand Up @@ -748,6 +750,10 @@ def _parse_header_line(cls, line):
msg = f"Unparsable version in ASDF file: {parts[1]}"
raise ValueError(msg) from err

if version != versioning._FILE_FORMAT_VERSION:
msg = f"Unsupported ASDF file format version {version}"
raise ValueError(msg)

return version

@classmethod
Expand Down Expand Up @@ -823,13 +829,15 @@ def _open_asdf(
msg = "Does not appear to be a ASDF file."
raise ValueError(msg) from e
self._file_format_version = cls._parse_header_line(header_line)
self.version = self._file_format_version

self._comments = cls._read_comment_section(fd)

version = cls._find_asdf_version_in_comments(self._comments)
if version is not None:
self.version = version
else:
# If no ASDF_STANDARD comment is found...
self.version = versioning.AsdfVersion("1.0.0")

# Now that version is set for good, we can add any additional
# extensions, which may have narrow ASDF Standard version
Expand Down Expand Up @@ -931,7 +939,7 @@ def _open_impl(
def _write_tree(self, tree, fd, pad_blocks):
fd.write(constants.ASDF_MAGIC)
fd.write(b" ")
fd.write(self.version_map["FILE_FORMAT"].encode("ascii"))
fd.write(f"{self.file_format_version}".encode("ascii"))
fd.write(b"\n")

fd.write(b"#")
Expand Down
121 changes: 0 additions & 121 deletions asdf/_tests/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,11 @@
CartesianDifferential = None

import numpy as np
import yaml

import asdf
from asdf import generic_io, versioning
from asdf._asdf import AsdfFile, _get_asdf_library_info
from asdf.constants import YAML_TAG_PREFIX
from asdf.exceptions import AsdfConversionWarning
from asdf.tags.core import AsdfObject
from asdf.versioning import (
AsdfVersion,
asdf_standard_development_version,
get_version_map,
split_tag_version,
supported_versions,
)

from .httpserver import RangeHTTPServer

Expand All @@ -48,7 +38,6 @@
"get_test_data_path",
"assert_tree_match",
"assert_roundtrip_tree",
"yaml_to_asdf",
"get_file_sizes",
"display_warnings",
]
Expand Down Expand Up @@ -286,57 +275,6 @@ def _assert_roundtrip_tree(
asdf_check_func(ff)


def yaml_to_asdf(yaml_content, yaml_headers=True, standard_version=None):
"""
Given a string of YAML content, adds the extra pre-
and post-amble to make it an ASDF file.
Parameters
----------
yaml_content : string
yaml_headers : bool, optional
When True (default) add the standard ASDF YAML headers.
Returns
-------
buff : io.BytesIO()
A file-like object containing the ASDF-like content.
"""
if isinstance(yaml_content, str):
yaml_content = yaml_content.encode("utf-8")

buff = io.BytesIO()

if standard_version is None:
standard_version = versioning.default_version

standard_version = AsdfVersion(standard_version)

vm = get_version_map(standard_version)
file_format_version = vm["FILE_FORMAT"]
yaml_version = vm["YAML_VERSION"]
tree_version = vm["tags"]["tag:stsci.edu:asdf/core/asdf"]

if yaml_headers:
buff.write(
f"""#ASDF {file_format_version}
#ASDF_STANDARD {standard_version}
%YAML {yaml_version}
%TAG ! tag:stsci.edu:asdf/
--- !core/asdf-{tree_version}
""".encode(
"ascii",
),
)
buff.write(yaml_content)
if yaml_headers:
buff.write(b"\n...\n")

buff.seek(0)
return buff


def get_file_sizes(dirname):
"""
Get the file sizes in a directory.
Expand Down Expand Up @@ -408,62 +346,3 @@ def assert_no_warnings(warning_class=None):
assert not any(isinstance(w.message, warning_class) for w in recorded_warnings), display_warnings(
recorded_warnings,
)


def _assert_extension_type_correctness(extension, extension_type, resolver):
__tracebackhide__ = True

if extension_type.yaml_tag is not None and extension_type.yaml_tag.startswith(YAML_TAG_PREFIX):
return

if extension_type == asdf.Stream:
# Stream is a special case. It was implemented as a subclass of NDArrayType,
# but shares a tag with that class, so it isn't really a distinct type.
return

assert extension_type.name is not None, f"{extension_type.__name__} must set the 'name' class attribute"

# Currently ExtensionType sets a default version of 1.0.0,
# but we want to encourage an explicit version on the subclass.
assert "version" in extension_type.__dict__, f"{extension_type.__name__} must set the 'version' class attribute"

# check the default version
types_to_check = [extension_type]

# Adding or updating a schema/type version might involve updating multiple
# packages. This can result in types without schema and schema without types
# for the development version of the asdf-standard. To account for this,
# don't include versioned siblings of types with versions that are not
# in one of the asdf-standard versions in supported_versions (excluding the
# current development version).
asdf_standard_versions = supported_versions.copy()
if asdf_standard_development_version in asdf_standard_versions:
asdf_standard_versions.remove(asdf_standard_development_version)
for sibling in extension_type.versioned_siblings:
tag_base, version = split_tag_version(sibling.yaml_tag)
for asdf_standard_version in asdf_standard_versions:
vm = get_version_map(asdf_standard_version)
if tag_base in vm["tags"] and AsdfVersion(vm["tags"][tag_base]) == version:
types_to_check.append(sibling)
break

for check_type in types_to_check:
schema_location = resolver(check_type.yaml_tag)

assert schema_location is not None, (
f"{extension_type.__name__} supports tag, {check_type.yaml_tag}, "
"but tag does not resolve. Check the tag_mapping and uri_mapping "
f"properties on the related extension ({extension_type.__name__})."
)

if schema_location not in asdf.get_config().resource_manager:
try:
with generic_io.get_file(schema_location) as f:
yaml.safe_load(f.read())
except Exception as err:
msg = (
f"{extension_type.__name__} supports tag, {check_type.yaml_tag}, "
f"which resolves to schema at {schema_location}, but "
"schema cannot be read."
)
raise AssertionError(msg) from err
11 changes: 6 additions & 5 deletions asdf/_tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
from asdf import config_context, get_config, treeutil, versioning
from asdf.exceptions import AsdfDeprecationWarning, AsdfWarning, ValidationError
from asdf.extension import ExtensionProxy
from asdf.testing.helpers import yaml_to_asdf

from ._helpers import assert_no_warnings, assert_roundtrip_tree, assert_tree_match, yaml_to_asdf
from ._helpers import assert_no_warnings, assert_roundtrip_tree, assert_tree_match

RNG = np.random.default_rng(97)

Expand Down Expand Up @@ -121,11 +122,11 @@ def test_default_version():
"""
See https://github.com/asdf-format/asdf/issues/364
"""

version_map = versioning.get_version_map(versioning.default_version)

ff = asdf.AsdfFile()
assert ff.file_format_version == version_map["FILE_FORMAT"]
assert ff.file_format_version == versioning._FILE_FORMAT_VERSION

# make sure these are different AsdfVersion instances
assert ff.file_format_version is not versioning._FILE_FORMAT_VERSION


def test_update_exceptions(tmp_path):
Expand Down
3 changes: 1 addition & 2 deletions asdf/_tests/test_array_blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,14 +749,13 @@ def test_invalid_block_index_offset(block_index_index):
block_index_start = block_index_header_start + len(constants.INDEX_HEADER)
block_index = yaml.load(bs[block_index_start:], yaml.SafeLoader)
block_index[block_index_index] -= 4
yaml_version = tuple(int(x) for x in ff.version_map["YAML_VERSION"].split("."))
buff.seek(block_index_start)
yaml.dump(
block_index,
stream=buff,
explicit_start=True,
explicit_end=True,
version=yaml_version,
version=asdf.versioning._YAML_VERSION,
allow_unicode=True,
encoding="utf-8",
)
Expand Down
Loading

0 comments on commit 1dbf3d7

Please sign in to comment.