diff --git a/src/caosadvancedtools/models/parser.py b/src/caosadvancedtools/models/parser.py index bb06823a7398dd4846712077afa0b35d0713185d..3cc370f4908ad87907a100a69d4122053b88f8b5 100644 --- a/src/caosadvancedtools/models/parser.py +++ b/src/caosadvancedtools/models/parser.py @@ -152,13 +152,17 @@ def parse_model_from_string(string): return parser.parse_model_from_string(string) -def parse_model_from_json_schema(filename: str): +def parse_model_from_json_schema(filename: str, top_level_recordtype: bool = True): """Return a datamodel parsed from a json schema definition. Parameters ---------- filename : str The path of the json schema file that is to be parsed + top_level_recordtype : bool, optional + Whether there is a record type defined at the top level of the + schema. Default is true. + Returns ------- @@ -623,7 +627,7 @@ class JsonSchemaParser(Parser): # @date 2022-02-17 # @review Timm Fitschen 2022-02-30 - def parse_model_from_json_schema(self, filename: str): + def parse_model_from_json_schema(self, filename: str, top_level_recordtype: bool = True): """Return a datamodel created from the definition in the json schema in `filename`. @@ -631,6 +635,9 @@ class JsonSchemaParser(Parser): ---------- filename : str The path to the json-schema file containing the datamodel definition + top_level_recordtype : bool, optional + Whether there is a record type defined at the top level of the + schema. Default is true. Returns ------- @@ -643,9 +650,9 @@ class JsonSchemaParser(Parser): with open(filename, 'r') as schema_file: model_dict = json.load(schema_file) - return self._create_model_from_dict(model_dict) + return self._create_model_from_dict(model_dict, top_level_recordtype=top_level_recordtype) - def _create_model_from_dict(self, model_dict: [dict, List[dict]]): + def _create_model_from_dict(self, model_dict: [dict, List[dict]], top_level_recordtype: bool = True): """Parse a dictionary and return the Datamodel created from it. The dictionary was typically created from the model definition in a json schema file. @@ -654,6 +661,9 @@ class JsonSchemaParser(Parser): ---------- model_dict : dict or list[dict] One or several dictionaries read in from a json-schema file + top_level_recordtype : bool, optional + Whether there is a record type defined at the top level of the + schema. Default is true. Returns ------- @@ -665,23 +675,43 @@ class JsonSchemaParser(Parser): model_dict = [model_dict] for ii, elt in enumerate(model_dict): - if "title" not in elt: - 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: + key = elt["title"] if "title" in elt else f"element {ii}" 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) + f"Json Schema error in {key}:\n{str(err)}") from err + + if top_level_recordtype: + if "title" not in elt: + 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 + name = self._stringify(elt["title"], context=elt) + self._treat_element(elt, name) + elif "properties" in elt: + for key, prop in elt["properties"]: + name = self._get_name_from_property(key, prop) + self._treat_element(prop, name) + else: + # Neither RecordType itself, nor further properties in schema, + # so nothing to do here. Maybe add something in the future. + continue return DataModel(self.model.values()) + def _get_name_from_property(self, key: str, prop: dict): + + if "title" in prop: + name = self._stringify(prop["title"]) + else: + name = self._stringify(key) + + return name + def _get_atomic_datatype(self, elt): # @review Timm Fitschen 2022-02-30 if elt["type"] == "string": @@ -745,10 +775,7 @@ class JsonSchemaParser(Parser): required = [] if "properties" in elt: for key, prop in elt["properties"].items(): - if "title" in prop: - name = self._stringify(prop["title"]) - else: - name = self._stringify(key) + name = self._get_name_from_property(key, prop) prop_ent, force_list = self._treat_element(prop, name) if prop_ent is None: # Nothing to be appended since the property has to be