diff --git a/asdf/_node_info.py b/asdf/_node_info.py index 0d820213a..0a88ddaa2 100644 --- a/asdf/_node_info.py +++ b/asdf/_node_info.py @@ -46,11 +46,12 @@ def _get_subschema_for_property(schema, key): # next handle schema combiners if "not" in schema: - # Since we're only concerned here with if the schema applies - # it doesn't matter if the schema is nested in a not subschema = _get_subschema_for_property(schema["not"], key) if subschema is not None: - applicable.append(subschema) + # We can't resolve a valid subschema under a "not" since + # we'd have to know how to invert a schema + msg = f"schema info could not be determined for {key} since " f"it is nested under a 'not'." + raise AsdfInfoResolutionError(msg) for combiner in ("allOf", "oneOf", "anyOf"): for combined_schema in schema.get(combiner, []): diff --git a/asdf/_tests/test_info.py b/asdf/_tests/test_info.py index b3df11c96..7b28961ad 100644 --- a/asdf/_tests/test_info.py +++ b/asdf/_tests/test_info.py @@ -719,6 +719,65 @@ def __str__(self): assert "(NiceStr): nice\n" in captured.out +@pytest.mark.parametrize( + "schema, expected", + [ + ({"properties": {"foo": {"type": "object"}}}, {"type": "object"}), + ({"allOf": [{"properties": {"foo": {"type": "object"}}}]}, {"type": "object"}), + ({"oneOf": [{"properties": {"foo": {"type": "object"}}}]}, {"type": "object"}), + ({"anyOf": [{"properties": {"foo": {"type": "object"}}}]}, {"type": "object"}), + ], +) +def test_node_property(schema, expected): + ni = asdf._node_info.NodeSchemaInfo.from_root_node("title", "root", {}, schema) + assert ni.get_schema_for_property("foo") == expected + + +@pytest.mark.parametrize( + "schema, msg", + [ + ({"not": {"properties": {"foo": {"type": "object"}}}}, "nested under a 'not'"), + ( + {"properties": {"foo": {"type": "object"}}, "allOf": [{"properties": {"foo": {"type": "object"}}}]}, + "2 possibly applicable schemas", + ), + ( + {"properties": {"foo": {"type": "object"}}, "anyOf": [{"properties": {"foo": {"type": "object"}}}]}, + "2 possibly applicable schemas", + ), + ( + {"properties": {"foo": {"type": "object"}}, "oneOf": [{"properties": {"foo": {"type": "object"}}}]}, + "2 possibly applicable schemas", + ), + ( + { + "allOf": [{"properties": {"foo": {"type": "object"}}}], + "anyOf": [{"properties": {"foo": {"type": "object"}}}], + }, + "2 possibly applicable schemas", + ), + ( + { + "anyOf": [{"properties": {"foo": {"type": "object"}}}], + "oneOf": [{"properties": {"foo": {"type": "object"}}}], + }, + "2 possibly applicable schemas", + ), + ( + { + "oneOf": [{"properties": {"foo": {"type": "object"}}}], + "allOf": [{"properties": {"foo": {"type": "object"}}}], + }, + "2 possibly applicable schemas", + ), + ], +) +def test_node_property_error(schema, msg): + ni = asdf._node_info.NodeSchemaInfo.from_root_node("title", "root", {}, schema) + with pytest.raises(AsdfInfoResolutionError, match=msg): + ni.get_schema_for_property("foo") + + @pytest.mark.parametrize( "schema, expected", [ @@ -745,5 +804,5 @@ def test_node_info(schema, expected): ) def test_node_info_failure(schema): ni = asdf._node_info.NodeSchemaInfo.from_root_node("title", "root", {}, schema) - with pytest.raises(AsdfInfoResolutionError): + with pytest.raises(AsdfInfoResolutionError, match="2 possibly applicable schemas"): ni.info