Example #1
0
def test_extension_proxy_maybe_wrap():
    extension = MinimumExtension()
    proxy = ExtensionProxy.maybe_wrap(extension)
    assert proxy.delegate is extension
    assert ExtensionProxy.maybe_wrap(proxy) is proxy

    with pytest.raises(TypeError):
        ExtensionProxy.maybe_wrap(object())
Example #2
0
def test_extension_proxy_hash_and_eq():
    extension = MinimumExtension()
    proxy1 = ExtensionProxy(extension)
    proxy2 = ExtensionProxy(extension,
                            package_name="foo",
                            package_version="1.2.3")

    assert proxy1 == proxy2
    assert hash(proxy1) == hash(proxy2)
    assert proxy1 != extension
    assert proxy2 != extension
Example #3
0
def test_extension_version_check(installed, extension, warns):
    proxy = ExtensionProxy(FooExtension(),
                           package_name="foo",
                           package_version=installed)

    with config_context() as config:
        config.add_extension(proxy)
        af = asdf.AsdfFile()

    af._fname = 'test.asdf'

    tree = {
        'history': {
            'extensions': [
                asdf.tags.core.ExtensionMetadata(
                    extension_class='asdf.tests.test_api.FooExtension',
                    software=asdf.tags.core.Software(name='foo',
                                                     version=extension)),
            ]
        }
    }

    if warns:
        with pytest.warns(AsdfWarning,
                          match="File 'test.asdf' was created with"):
            af._check_extensions(tree)

        with pytest.raises(RuntimeError) as err:
            af._check_extensions(tree, strict=True)
        err.match("^File 'test.asdf' was created with")
    else:
        af._check_extensions(tree)
Example #4
0
def test_asdf_file_extensions():
    af = AsdfFile()
    assert af.extensions == []

    extension = TestExtension(
        extension_uri="asdf://somewhere.org/extensions/foo-1.0")

    for arg in ([extension], extension, AsdfExtensionList([extension])):
        af = AsdfFile(extensions=arg)
        assert af.extensions == [ExtensionProxy(extension)]

        af = AsdfFile()
        af.extensions = arg
        assert af.extensions == [ExtensionProxy(extension)]

    for arg in (object(), [object()]):
        with pytest.raises(TypeError):
            AsdfFile(extensions=arg)
Example #5
0
def test_extension_proxy_repr():
    proxy = ExtensionProxy(MinimumExtension(),
                           package_name="foo",
                           package_version="1.2.3")
    assert "class: asdf.tests.test_extension.MinimumExtension" in repr(proxy)
    assert "package: foo==1.2.3" in repr(proxy)
    assert "legacy: False" in repr(proxy)

    proxy = ExtensionProxy(MinimumExtension())
    assert "class: asdf.tests.test_extension.MinimumExtension" in repr(proxy)
    assert "package: (none)" in repr(proxy)
    assert "legacy: False" in repr(proxy)

    proxy = ExtensionProxy(LegacyExtension(),
                           package_name="foo",
                           package_version="1.2.3")
    assert "class: asdf.tests.test_extension.LegacyExtension" in repr(proxy)
    assert "package: foo==1.2.3" in repr(proxy)
    assert "legacy: True" in repr(proxy)
Example #6
0
def test_asdf_file_version_requirement():
    extension_with_requirement = TestExtension(
        extension_uri="asdf://somewhere.org/extensions/foo-1.0",
        asdf_standard_requirement="==1.5.0",
    )

    # No warnings if the requirement is fulfilled:
    with assert_no_warnings():
        AsdfFile(version="1.5.0", extensions=[extension_with_requirement])

    # Version doesn't match the requirement, so we should see a warning
    # and the extension should not be enabled:
    with pytest.warns(AsdfWarning,
                      match="does not support ASDF Standard 1.4.0"):
        af = AsdfFile(version="1.4.0", extensions=[extension_with_requirement])
        assert ExtensionProxy(extension_with_requirement) not in af.extensions

    # Version initially matches the requirement, but changing
    # the version on the AsdfFile invalidates it:
    af = AsdfFile(version="1.5.0", extensions=[extension_with_requirement])
    assert ExtensionProxy(extension_with_requirement) in af.extensions
    with pytest.warns(AsdfWarning,
                      match="does not support ASDF Standard 1.4.0"):
        af.version = "1.4.0"
    assert ExtensionProxy(extension_with_requirement) not in af.extensions

    # Extension registered with the config should not provoke
    # a warning:
    with config_context() as config:
        config.add_extension(extension_with_requirement)
        with assert_no_warnings():
            af = AsdfFile(version="1.4.0")
            assert ExtensionProxy(
                extension_with_requirement) not in af.extensions

        # ... unless the user explicitly requested the invalid exception:
        with pytest.warns(AsdfWarning,
                          match="does not support ASDF Standard 1.4.0"):
            af = AsdfFile(version="1.4.0",
                          extensions=[extension_with_requirement])
Example #7
0
def test_extension_proxy_tags():
    """
    The tags behavior is a tad complex, so they get their own test.
    """
    foo_tag_uri = "asdf://somewhere.org/extensions/full/tags/foo-1.0"
    foo_tag_def = TagDefinition(
        foo_tag_uri,
        schema_uri="asdf://somewhere.org/extensions/full/schemas/foo-1.0",
        title="Some tag title",
        description="Some tag description")

    bar_tag_uri = "asdf://somewhere.org/extensions/full/tags/bar-1.0"
    bar_tag_def = TagDefinition(
        bar_tag_uri,
        schema_uri="asdf://somewhere.org/extensions/full/schemas/bar-1.0",
        title="Some other tag title",
        description="Some other tag description")

    # The converter should return only the tags
    # supported by the extension.
    converter = FullConverter(tags=["**"])
    extension = FullExtension(tags=[foo_tag_def], converters=[converter])
    proxy = ExtensionProxy(extension)
    assert proxy.converters[0].tags == [foo_tag_uri]

    # The converter should not return tags that
    # its patterns do not match.
    converter = FullConverter(tags=["**/foo-1.0"])
    extension = FullExtension(tags=[foo_tag_def, bar_tag_def],
                              converters=[converter])
    proxy = ExtensionProxy(extension)
    assert proxy.converters[0].tags == [foo_tag_uri]

    # The process should still work if the extension property
    # contains str instead of TagDescription.
    converter = FullConverter(tags=["**/foo-1.0"])
    extension = FullExtension(tags=[foo_tag_uri, bar_tag_uri],
                              converters=[converter])
    proxy = ExtensionProxy(extension)
    assert proxy.converters[0].tags == [foo_tag_uri]
Example #8
0
def test_asdf_file_extensions():
    af = AsdfFile()
    assert af.extensions == get_config().extensions

    extension = TestExtension(
        extension_uri="asdf://somewhere.org/extensions/foo-1.0")

    for arg in ([extension], extension, AsdfExtensionList([extension])):
        af = AsdfFile(extensions=arg)
        assert af.extensions[0] == ExtensionProxy(extension)
        assert af.extensions[1:] == get_config().extensions

        af = AsdfFile()
        af.extensions = arg
        assert af.extensions[0] == ExtensionProxy(extension)
        assert af.extensions[1:] == get_config().extensions

    # This use case is a little silly, but in the future it will be
    # possible to disable extensions globally and passing the URI
    # will enable them on an individual file basis.  Currently all
    # we can do with the URI is put the extension at the head of
    # list so that it has priority.
    with config_context() as config:
        config.add_extension(extension)
        for arg in ([extension.extension_uri], extension.extension_uri):
            af = AsdfFile(extensions=arg)
            assert af.extensions[0] == ExtensionProxy(extension)

            af = AsdfFile()
            af.extensions = arg
            assert af.extensions[0] == ExtensionProxy(extension)

    for arg in (object(), [object()]):
        with pytest.raises(TypeError):
            AsdfFile(extensions=arg)

    with pytest.raises(KeyError):
        AsdfFile(extensions="not-a-URI")
Example #9
0
def test_open_asdf_extensions(tmpdir):
    extension = TestExtension(
        extension_uri="asdf://somewhere.org/extensions/foo-1.0")

    path = str(tmpdir / "test.asdf")

    with AsdfFile() as af:
        af.write_to(path)

    with open_asdf(path) as af:
        assert af.extensions == []

    for arg in ([extension], extension, AsdfExtensionList([extension])):
        with open_asdf(path, extensions=arg) as af:
            assert af.extensions == [ExtensionProxy(extension)]

    for arg in (object(), [object()]):
        with pytest.raises(TypeError):
            with open_asdf(path, extensions=arg) as af:
                pass
Example #10
0
def test_extension_proxy_legacy():
    extension = LegacyExtension()
    proxy = ExtensionProxy(extension,
                           package_name="foo",
                           package_version="1.2.3")

    assert proxy.extension_uri is None
    assert proxy.legacy_class_names == {
        "asdf.tests.test_extension.LegacyExtension"
    }
    assert proxy.asdf_standard_requirement == SpecifierSet()
    assert proxy.converters == []
    assert proxy.tags == []
    assert proxy.types == [LegacyType]
    assert proxy.tag_mapping == LegacyExtension.tag_mapping
    assert proxy.url_mapping == LegacyExtension.url_mapping
    assert proxy.delegate is extension
    assert proxy.legacy is True
    assert proxy.package_name == "foo"
    assert proxy.package_version == "1.2.3"
    assert proxy.class_name == "asdf.tests.test_extension.LegacyExtension"
Example #11
0
def test_reading_extension_metadata():
    extension_with_uri = ExtensionProxy(
        TestExtension(extension_uri="asdf://somewhere.org/extensions/foo-1.0"),
        package_name="foo",
        package_version="1.2.3",
    )
    extension_without_uri = ExtensionProxy(
        TestExtension(),
        package_name="foo",
        package_version="1.2.3",
    )
    extension_with_legacy_class_names = ExtensionProxy(
        TestExtension(
            extension_uri="asdf://somewhere.org/extensions/with-legacy-1.0",
            legacy_class_names={"some.legacy.class.Name"},
        ),
        package_name="foo",
        package_version="1.2.3",
    )

    with config_context() as config:
        config.add_extension(extension_with_uri)
        config.add_extension(extension_without_uri)
        config.add_extension(extension_with_legacy_class_names)

        # Test missing history:
        content = """
        foo: bar
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)

        # Test the old history format:
        content = """
        history:
          - !core/history_entry-1.0.0
            description: Once upon a time, there was a carnivorous panda.
          - !core/history_entry-1.0.0
            description: This entry intentionally left blank.
        foo: bar
        """
        buff = yaml_to_asdf(content, standard_version="1.0.0")
        with assert_no_warnings():
            open_asdf(buff)

        # Test legacy extension matching by actual class name:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_class: asdf.tests.test_asdf.TestExtension
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)

        # Test matching by URI:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_uri: asdf://somewhere.org/extensions/foo-1.0
              extension_class: some.unrecognized.extension.class.Name
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)

        # Test matching by legacy class name:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_class: some.legacy.class.Name
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)

        # Warn when the URI is missing, even if there's
        # a class name match:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_uri: some-missing-URI
              extension_class: {}
        """.format(extension_with_uri.class_name)
        buff = yaml_to_asdf(content)
        with pytest.warns(AsdfWarning, match="URI 'some-missing-URI'"):
            open_asdf(buff)

        # Warn when the class name is missing:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_class: some.missing.class.Name
        """
        buff = yaml_to_asdf(content)
        with pytest.warns(AsdfWarning,
                          match="class 'some.missing.class.Name'"):
            open_asdf(buff)

        # Warn when the package version is older:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_uri: asdf://somewhere.org/extensions/foo-1.0
              extension_class: some.class.Name
              software: !core/software-1.0.0
                name: foo
                version: 9.2.4
        """
        buff = yaml_to_asdf(content)
        with pytest.warns(AsdfWarning, match="older package"):
            open_asdf(buff)

        # Shouldn't warn when the package version is later:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_uri: asdf://somewhere.org/extensions/foo-1.0
              extension_class: some.class.Name
              software: !core/software-1.0.0
                name: foo
                version: 0.1.2
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)

        # Shouldn't receive a warning when the package
        # name changes, even if the version is later:
        content = """
        history:
          extensions:
            - !core/extension_metadata-1.0.0
              extension_uri: asdf://somewhere.org/extensions/foo-1.0
              extension_class: some.class.Name
              software: !core/software-1.0.0
                name: bar
                version: 9.4.5
        """
        buff = yaml_to_asdf(content)
        with assert_no_warnings():
            open_asdf(buff)
Example #12
0
def test_extensions():
    with asdf.config_context() as config:
        original_extensions = config.extensions
        assert any(
            isinstance(e.delegate, BuiltinExtension)
            for e in original_extensions)

        class FooExtension:
            types = []
            tag_mapping = []
            url_mapping = []

        new_extension = FooExtension()

        class BarExtension:
            extension_uri = "asdf://somewhere.org/extensions/bar-1.0"
            types = []
            tag_mapping = []
            url_mapping = []

        uri_extension = BarExtension()

        # Add an extension:
        config.add_extension(new_extension)
        assert len(config.extensions) == len(original_extensions) + 1
        assert any(e for e in config.extensions if e.delegate is new_extension)

        # Adding an extension should be idempotent:
        config.add_extension(new_extension)
        assert len(config.extensions) == len(original_extensions) + 1

        # Even when wrapped:
        config.add_extension(ExtensionProxy(new_extension))
        assert len(config.extensions) == len(original_extensions) + 1

        # Remove an extension:
        config.remove_extension(new_extension)
        assert len(config.extensions) == len(original_extensions)

        # Removing should work when wrapped:
        config.add_extension(new_extension)
        config.remove_extension(ExtensionProxy(new_extension))
        assert len(config.extensions) == len(original_extensions)

        # And also by URI:
        config.add_extension(uri_extension)
        config.remove_extension(uri_extension.extension_uri)
        assert len(config.extensions) == len(original_extensions)

        # And also by URI pattern:
        config.add_extension(uri_extension)
        config.remove_extension("asdf://somewhere.org/extensions/*")
        assert len(config.extensions) == len(original_extensions)

        # Remove by the name of the extension's package:
        config.add_extension(ExtensionProxy(new_extension, package_name="foo"))
        config.add_extension(ExtensionProxy(uri_extension, package_name="foo"))
        config.remove_extension(package="foo")
        assert len(config.extensions) == len(original_extensions)

        # Can combine remove filters:
        config.add_extension(ExtensionProxy(new_extension, package_name="foo"))
        config.add_extension(ExtensionProxy(uri_extension, package_name="foo"))
        config.remove_extension(uri_extension.extension_uri, package="foo")
        assert len(config.extensions) == len(original_extensions) + 1

        # ... but not omit both:
        with pytest.raises(ValueError):
            config.remove_extension()

        # Removing an extension should be idempotent:
        config.add_extension(new_extension)
        config.remove_extension(new_extension)
        config.remove_extension(new_extension)
        assert len(config.extensions) == len(original_extensions)

        # Resetting should get rid of any additions:
        config.add_extension(new_extension)
        config.add_extension(FooExtension())
        config.reset_extensions()
        assert len(config.extensions) == len(original_extensions)
Example #13
0
def test_manifest_extension():
    with config_context() as config:
        minimal_manifest = """%YAML 1.1
---
id: asdf://somewhere.org/manifests/foo
extension_uri: asdf://somewhere.org/extensions/foo
...
"""
        config.add_resource_mapping(
            {"asdf://somewhere.org/extensions/foo": minimal_manifest})
        extension = ManifestExtension.from_uri(
            "asdf://somewhere.org/extensions/foo")
        assert isinstance(extension, Extension)
        assert extension.extension_uri == "asdf://somewhere.org/extensions/foo"
        assert extension.legacy_class_names == []
        assert extension.asdf_standard_requirement is None
        assert extension.converters == []
        assert extension.compressors == []
        assert extension.tags == []

        proxy = ExtensionProxy(extension)
        assert proxy.extension_uri == "asdf://somewhere.org/extensions/foo"
        assert proxy.legacy_class_names == set()
        assert proxy.asdf_standard_requirement == SpecifierSet()
        assert proxy.converters == []
        assert proxy.compressors == []
        assert proxy.tags == []

    with config_context() as config:
        full_manifest = """%YAML 1.1
---
id: asdf://somewhere.org/manifests/foo
extension_uri: asdf://somewhere.org/extensions/foo
asdf_standard_requirement:
  gte: 1.6.0
  lt: 2.0.0
tags:
  - asdf://somewhere.org/tags/bar
  - tag_uri: asdf://somewhere.org/tags/baz
    schema_uri: asdf://somewhere.org/schemas/baz
    title: Baz title
    description: Bar description
...
"""
        config.add_resource_mapping(
            {"asdf://somewhere.org/extensions/foo": full_manifest})

        class FooConverter:
            tags = [
                "asdf://somewhere.org/tags/bar",
                "asdf://somewhere.org/tags/baz"
            ]
            types = []

            def select_tag(self, *args):
                pass

            def to_yaml_tree(self, *args):
                pass

            def from_yaml_tree(self, *args):
                pass

        converter = FooConverter()

        extension = ManifestExtension.from_uri(
            "asdf://somewhere.org/extensions/foo",
            legacy_class_names=["foo.extension.LegacyExtension"],
            converters=[converter],
            compressors=[MinimalCompressor],
        )
        assert extension.extension_uri == "asdf://somewhere.org/extensions/foo"
        assert extension.legacy_class_names == [
            "foo.extension.LegacyExtension"
        ]
        assert extension.asdf_standard_requirement == SpecifierSet(
            ">=1.6.0,<2.0.0")
        assert extension.converters == [converter]
        assert extension.compressors == [MinimalCompressor]
        assert len(extension.tags) == 2
        assert extension.tags[0] == "asdf://somewhere.org/tags/bar"
        assert extension.tags[1].tag_uri == "asdf://somewhere.org/tags/baz"
        assert extension.tags[
            1].schema_uri == "asdf://somewhere.org/schemas/baz"
        assert extension.tags[1].title == "Baz title"
        assert extension.tags[1].description == "Bar description"

        proxy = ExtensionProxy(extension)
        assert proxy.extension_uri == "asdf://somewhere.org/extensions/foo"
        assert proxy.legacy_class_names == {"foo.extension.LegacyExtension"}
        assert proxy.asdf_standard_requirement == SpecifierSet(
            ">=1.6.0,<2.0.0")
        assert proxy.converters == [ConverterProxy(converter, proxy)]
        assert proxy.compressors == [MinimalCompressor]
        assert len(proxy.tags) == 2
        assert proxy.tags[0].tag_uri == "asdf://somewhere.org/tags/bar"
        assert proxy.tags[1].tag_uri == "asdf://somewhere.org/tags/baz"
        assert proxy.tags[1].schema_uri == "asdf://somewhere.org/schemas/baz"
        assert proxy.tags[1].title == "Baz title"
        assert proxy.tags[1].description == "Bar description"

    with config_context() as config:
        simple_asdf_standard_manifest = """%YAML 1.1
---
id: asdf://somewhere.org/manifests/foo
extension_uri: asdf://somewhere.org/extensions/foo
asdf_standard_requirement: 1.6.0
...
"""
        config.add_resource_mapping({
            "asdf://somewhere.org/extensions/foo":
            simple_asdf_standard_manifest
        })
        extension = ManifestExtension.from_uri(
            "asdf://somewhere.org/extensions/foo")
        assert extension.asdf_standard_requirement == SpecifierSet("==1.6.0")

        proxy = ExtensionProxy(extension)
        assert proxy.asdf_standard_requirement == SpecifierSet("==1.6.0")
Example #14
0
def test_converter_proxy():
    # Test the minimum set of converter methods:
    extension = ExtensionProxy(MinimumExtension())
    converter = MinimumConverter()
    proxy = ConverterProxy(converter, extension)

    assert isinstance(proxy, Converter)

    assert proxy.tags == []
    assert proxy.types == []
    assert proxy.to_yaml_tree(None, None, None) == "to_yaml_tree result"
    assert proxy.from_yaml_tree(None, None, None) == "from_yaml_tree result"
    assert proxy.tags == []
    assert proxy.delegate is converter
    assert proxy.extension == extension
    assert proxy.package_name is None
    assert proxy.package_version is None
    assert proxy.class_name == "asdf.tests.test_extension.MinimumConverter"

    # Check the __eq__ and __hash__ behavior:
    assert proxy == ConverterProxy(converter, extension)
    assert proxy != ConverterProxy(MinimumConverter(), extension)
    assert proxy != ConverterProxy(converter, MinimumExtension())
    assert proxy in {ConverterProxy(converter, extension)}
    assert proxy not in {
        ConverterProxy(MinimumConverter(), extension),
        ConverterProxy(converter, MinimumExtension())
    }

    # Check the __repr__:
    assert "class: asdf.tests.test_extension.MinimumConverter" in repr(proxy)
    assert "package: (none)" in repr(proxy)

    # Test the full set of converter methods:
    converter = FullConverter(tags=[
        "asdf://somewhere.org/extensions/test/tags/foo-*",
        "asdf://somewhere.org/extensions/test/tags/bar-*",
    ],
                              types=[FooType, BarType])

    extension = FullExtension(tags=[
        TagDefinition(
            "asdf://somewhere.org/extensions/test/tags/foo-1.0",
            schema_uri="asdf://somewhere.org/extensions/test/schemas/foo-1.0",
            title="Foo tag title",
            description="Foo tag description"),
        TagDefinition(
            "asdf://somewhere.org/extensions/test/tags/bar-1.0",
            schema_uri="asdf://somewhere.org/extensions/test/schemas/bar-1.0",
            title="Bar tag title",
            description="Bar tag description"),
    ])

    extension_proxy = ExtensionProxy(extension,
                                     package_name="foo",
                                     package_version="1.2.3")
    proxy = ConverterProxy(converter, extension_proxy)
    assert len(proxy.tags) == 2
    assert "asdf://somewhere.org/extensions/test/tags/foo-1.0" in proxy.tags
    assert "asdf://somewhere.org/extensions/test/tags/bar-1.0" in proxy.tags
    assert proxy.types == [FooType, BarType]
    assert proxy.to_yaml_tree(None, None, None) == "to_yaml_tree result"
    assert proxy.from_yaml_tree(None, None, None) == "from_yaml_tree result"
    assert proxy.select_tag(None, None) == "select_tag result"
    assert proxy.delegate is converter
    assert proxy.extension == extension_proxy
    assert proxy.package_name == "foo"
    assert proxy.package_version == "1.2.3"
    assert proxy.class_name == "asdf.tests.test_extension.FullConverter"

    # Check the __repr__ since it will contain package info now:
    assert "class: asdf.tests.test_extension.FullConverter" in repr(proxy)
    assert "package: foo==1.2.3" in repr(proxy)

    # Should error because object() does fulfill the Converter interface:
    with pytest.raises(TypeError):
        ConverterProxy(object(), extension)

    # Should fail because tags must be str:
    with pytest.raises(TypeError):
        ConverterProxy(MinimumConverter(tags=[object()]), extension)

    # Should fail because types must instances of type:
    with pytest.raises(TypeError):
        ConverterProxy(MinimumConverter(types=[object()]), extension)
Example #15
0
def test_extension_manager():
    converter1 = FullConverter(
        tags=[
            "asdf://somewhere.org/extensions/full/tags/foo-*",
            "asdf://somewhere.org/extensions/full/tags/bar-*",
        ],
        types=[
            FooType,
            "asdf.tests.test_extension.BarType",
        ],
    )
    converter2 = FullConverter(
        tags=[
            "asdf://somewhere.org/extensions/full/tags/baz-*",
        ],
        types=[BazType],
    )
    converter3 = FullConverter(
        tags=[
            "asdf://somewhere.org/extensions/full/tags/foo-*",
        ],
        types=[
            FooType,
            BarType,
        ],
    )
    extension1 = FullExtension(
        converters=[converter1, converter2],
        tags=[
            "asdf://somewhere.org/extensions/full/tags/foo-1.0",
            "asdf://somewhere.org/extensions/full/tags/baz-1.0",
        ])
    extension2 = FullExtension(
        converters=[converter3],
        tags=[
            "asdf://somewhere.org/extensions/full/tags/foo-1.0",
        ])

    manager = ExtensionManager([extension1, extension2])

    assert manager.extensions == [
        ExtensionProxy(extension1),
        ExtensionProxy(extension2)
    ]

    assert manager.handles_tag(
        "asdf://somewhere.org/extensions/full/tags/foo-1.0") is True
    assert manager.handles_tag(
        "asdf://somewhere.org/extensions/full/tags/bar-1.0") is False
    assert manager.handles_tag(
        "asdf://somewhere.org/extensions/full/tags/baz-1.0") is True

    assert manager.handles_type(FooType) is True
    # This should return True even though BarType was listed
    # as string class name:
    assert manager.handles_type(BarType) is True
    assert manager.handles_type(BazType) is True

    assert manager.get_tag_definition(
        "asdf://somewhere.org/extensions/full/tags/foo-1.0"
    ).tag_uri == "asdf://somewhere.org/extensions/full/tags/foo-1.0"
    assert manager.get_tag_definition(
        "asdf://somewhere.org/extensions/full/tags/baz-1.0"
    ).tag_uri == "asdf://somewhere.org/extensions/full/tags/baz-1.0"
    with pytest.raises(KeyError):
        manager.get_tag_definition(
            "asdf://somewhere.org/extensions/full/tags/bar-1.0")

    assert manager.get_converter_for_tag(
        "asdf://somewhere.org/extensions/full/tags/foo-1.0"
    ).delegate is converter1
    assert manager.get_converter_for_tag(
        "asdf://somewhere.org/extensions/full/tags/baz-1.0"
    ).delegate is converter2
    with pytest.raises(KeyError):
        manager.get_converter_for_tag(
            "asdf://somewhere.org/extensions/full/tags/bar-1.0")

    assert manager.get_converter_for_type(FooType).delegate is converter1
    assert manager.get_converter_for_type(BarType).delegate is converter1
    assert manager.get_converter_for_type(BazType).delegate is converter2
    with pytest.raises(KeyError):
        manager.get_converter_for_type(object)
Example #16
0
def test_extension_proxy():
    # Test with minimum properties:
    extension = MinimumExtension()
    proxy = ExtensionProxy(extension)

    assert isinstance(proxy, Extension)
    assert isinstance(proxy, AsdfExtension)

    assert proxy.extension_uri == "asdf://somewhere.org/extensions/minimum-1.0"
    assert proxy.legacy_class_names == set()
    assert proxy.asdf_standard_requirement == SpecifierSet()
    assert proxy.converters == []
    assert proxy.compressors == []
    assert proxy.tags == []
    assert proxy.types == []
    assert proxy.tag_mapping == []
    assert proxy.url_mapping == []
    assert proxy.delegate is extension
    assert proxy.legacy is False
    assert proxy.package_name is None
    assert proxy.package_version is None
    assert proxy.class_name == "asdf.tests.test_extension.MinimumExtension"

    # The subclassed version should have the same defaults:
    extension = MinimumExtensionSubclassed()
    subclassed_proxy = ExtensionProxy(extension)
    assert subclassed_proxy.extension_uri == proxy.extension_uri
    assert subclassed_proxy.legacy_class_names == proxy.legacy_class_names
    assert subclassed_proxy.asdf_standard_requirement == proxy.asdf_standard_requirement
    assert subclassed_proxy.converters == proxy.converters
    assert subclassed_proxy.tags == proxy.tags
    assert subclassed_proxy.types == proxy.types
    assert subclassed_proxy.tag_mapping == proxy.tag_mapping
    assert subclassed_proxy.url_mapping == proxy.url_mapping
    assert subclassed_proxy.delegate is extension
    assert subclassed_proxy.legacy == proxy.legacy
    assert subclassed_proxy.package_name == proxy.package_name
    assert subclassed_proxy.package_version == proxy.package_name
    assert subclassed_proxy.class_name == "asdf.tests.test_extension.MinimumExtensionSubclassed"

    # Test with all properties present:
    converters = [
        MinimumConverter(
            tags=["asdf://somewhere.org/extensions/full/tags/foo-*"], types=[])
    ]
    extension = FullExtension(
        converters=converters,
        compressors=[MinimalCompressor],
        asdf_standard_requirement=">=1.4.0",
        tags=["asdf://somewhere.org/extensions/full/tags/foo-1.0"],
        legacy_class_names=["foo.extensions.SomeOldExtensionClass"])
    proxy = ExtensionProxy(extension,
                           package_name="foo",
                           package_version="1.2.3")

    assert proxy.extension_uri == "asdf://somewhere.org/extensions/full-1.0"
    assert proxy.legacy_class_names == {"foo.extensions.SomeOldExtensionClass"}
    assert proxy.asdf_standard_requirement == SpecifierSet(">=1.4.0")
    assert proxy.converters == [ConverterProxy(c, proxy) for c in converters]
    assert proxy.compressors == [MinimalCompressor]
    assert len(proxy.tags) == 1
    assert proxy.tags[
        0].tag_uri == "asdf://somewhere.org/extensions/full/tags/foo-1.0"
    assert proxy.types == []
    assert proxy.tag_mapping == []
    assert proxy.url_mapping == []
    assert proxy.delegate is extension
    assert proxy.legacy is False
    assert proxy.package_name == "foo"
    assert proxy.package_version == "1.2.3"
    assert proxy.class_name == "asdf.tests.test_extension.FullExtension"

    # Should fail when the input is not one of the two extension interfaces:
    with pytest.raises(TypeError):
        ExtensionProxy(object)

    # Should fail with a bad converter:
    with pytest.raises(TypeError):
        ExtensionProxy(FullExtension(converters=[object()]))

    # Should fail with a bad compressor:
    with pytest.raises(TypeError):
        ExtensionProxy(FullExtension(compressors=[object()]))

    # Unparseable ASDF Standard requirement:
    with pytest.raises(ValueError):
        ExtensionProxy(
            FullExtension(asdf_standard_requirement="asdf-standard >= 1.4.0"))

    # Unrecognized ASDF Standard requirement type:
    with pytest.raises(TypeError):
        ExtensionProxy(FullExtension(asdf_standard_requirement=object()))

    # Bad tag:
    with pytest.raises(TypeError):
        ExtensionProxy(FullExtension(tags=[object()]))

    # Bad legacy class names:
    with pytest.raises(TypeError):
        ExtensionProxy(FullExtension(legacy_class_names=[object]))