diff --git a/src/caosadvancedtools/models/parser.py b/src/caosadvancedtools/models/parser.py index 0baee1dbf98feeff118d54015606489a986e77d9..d542af686a1c3e76b8a87d5084d841bce910a151 100644 --- a/src/caosadvancedtools/models/parser.py +++ b/src/caosadvancedtools/models/parser.py @@ -1,3 +1,22 @@ +# This file is a part of the CaosDB Project. +# +# Copyright (C) 2022 IndiScale GmbH <info@indiscale.com> +# Copyright (C) 2022 Florian Spreckelsen <f.spreckelsen@indiscale.com> +# Copyright (C) 2022 Daniel Hornung <d.hornung@indiscale.com> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + """ This module (and script) provides methods to read a DataModel from a YAML file. @@ -23,6 +42,7 @@ import yaml from typing import List +import jsonschema import caosdb as db from .data_model import DataModel @@ -513,6 +533,12 @@ class JsonSchemaParser(Parser): raise JsonSchemaDefinitionError(f"Object {ii+1} is lacking the `title` key word") if "type" not in elt: raise JsonSchemaDefinitionError(f"Object {ii+1} is lacking the `type` key word") + # Check if this is a valid Json Schema + try: + jsonschema.Draft202012Validator.check_schema(elt) + except jsonschema.SchemaError as err: + raise JsonSchemaDefinitionError( + f"Json Schema error in {elt['title']}:\n{str(err)}") from err name = self._stringify(elt["title"], context=elt) self._treat_element(elt, name) diff --git a/unittests/json-schema-models/datamodel_required_no_list.schema.json b/unittests/json-schema-models/datamodel_required_no_list.schema.json new file mode 100644 index 0000000000000000000000000000000000000000..f3697a71320bc8baf05156bec2c71f3915378654 --- /dev/null +++ b/unittests/json-schema-models/datamodel_required_no_list.schema.json @@ -0,0 +1,7 @@ +{ + "title": "Dataset", + "description": "", + "type": "object", + + "required": "Dataset" +} diff --git a/unittests/json-schema-models/datamodel_string_properties.schema.json b/unittests/json-schema-models/datamodel_string_properties.schema.json index a6b3b6f9484c2d2cad24726e0c4f1cbb12919aa8..62bc0a2a4250050e5433038bf61e7c9692bb0200 100644 --- a/unittests/json-schema-models/datamodel_string_properties.schema.json +++ b/unittests/json-schema-models/datamodel_string_properties.schema.json @@ -6,7 +6,8 @@ "properties": { "title": { "type": "string", "description": "full dataset title" }, "campaign": { "type": "string", "description": "FIXME" }, - "method": { "type": "string", "description": "FIXME" } + "method": { "type": "string", "description": "FIXME" }, + "titled": { "title": "The title", "type": "string", "description": "None" } }, "required": ["title"] diff --git a/unittests/test_json_schema_model_parser.py b/unittests/test_json_schema_model_parser.py index 5b7a2f28f085e6dc2574311065eb729389aaa92a..3e258e244d0f9d58aeae973de00bb0d0c2d19785 100644 --- a/unittests/test_json_schema_model_parser.py +++ b/unittests/test_json_schema_model_parser.py @@ -3,6 +3,7 @@ # # Copyright (C) 2022 IndiScale GmbH <info@indiscale.com> # Copyright (C) 2022 Florian Spreckelsen <f.spreckelsen@indiscale.com> +# Copyright (C) 2022 Daniel Hornung <d.hornung@indiscale.com> # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU Affero General Public License as published by the Free @@ -17,10 +18,15 @@ # You should have received a copy of the GNU Affero General Public License along # with this program. If not, see <https://www.gnu.org/licenses/>. # + +# @review Daniel Hornung 2022-02-18 + import os +import pytest import caosdb as db -from caosadvancedtools.models.parser import parse_model_from_json_schema +from caosadvancedtools.models.parser import (parse_model_from_json_schema, + JsonSchemaDefinitionError) FILEPATH = os.path.join(os.path.dirname( os.path.abspath(__file__)), 'json-schema-models') @@ -39,12 +45,15 @@ def test_rt_with_string_properties(): assert isinstance(dataset_rt, db.RecordType) assert dataset_rt.name == "Dataset" assert dataset_rt.description == "" - assert len(dataset_rt.get_properties()) == 3 + assert len(dataset_rt.get_properties()) == 4 assert dataset_rt.get_property("title") is not None assert dataset_rt.get_property("campaign") is not None assert dataset_rt.get_property("method") is not None + assert dataset_rt.get_property("The title") is not None + assert dataset_rt.get_property("titled") is None + title_prop = dataset_rt.get_property("title") assert title_prop.datatype == db.TEXT assert dataset_rt.get_importance(title_prop.name) == db.OBLIGATORY @@ -105,3 +114,15 @@ def test_datamodel_with_atomic_properties(): bool_prop = rt2.get_property("boolean") assert bool_prop.datatype == db.BOOLEAN + + +def test_required_no_list(): + """Exception must be raised when "required" is not a list.""" + # @author Daniel Hornung + # @date 2022-02-18 + + with pytest.raises(JsonSchemaDefinitionError) as err: + parse_model_from_json_schema( + os.path.join(FILEPATH, + "datamodel_required_no_list.schema.json")) + assert "'Dataset' is not of type 'array'" in str(err.value)