diff --git a/src/caosadvancedtools/json_schema_exporter.py b/src/caosadvancedtools/json_schema_exporter.py index f18a6116c145ed84eff6a2215793bb97f553221f..58c09672556f2ef9378638f3f1c58eda69bc55ee 100644 --- a/src/caosadvancedtools/json_schema_exporter.py +++ b/src/caosadvancedtools/json_schema_exporter.py @@ -21,47 +21,31 @@ # import re +from typing import Optional import linkahead as db +from linkahead.common.datatype import is_list_datatype, get_list_datatype def _make_required_list(rt: db.RecordType): """Return the list of names of properties with importance db.OBLIGATORY.""" - required = [] - for prop in rt.properties: - importance = rt.get_importance(prop.name) - if importance == db.OBLIGATORY: - required.append(prop.name) - return required - - -def _extract_elemet_dtyp_from_list_dtype(list_dtype): - - if not list_dtype.lower().startswith("list"): + return [prop.name for prop in rt.properties + if rt.get_importance(prop.name) == db.OBLIGATORY] - raise ValueError(f"Not a list dtype: {list_dtype}") - pattern = r"^[Ll][Ii][Ss][Tt](<(?P<dtype1>.*)>|\((?P<dtype2>.*)\))$" - comp = re.compile(pattern) - mtch = comp.match(list_dtype) - if mtch is None: +def _make_prop_from_prop(prop: db.Property, additional_options_for_text_props: Optional[dict]): + """Return the JSON Schema segment for the given property - raise ValueError(f"Not a list dtype: {list_dtype}") - - elif "dtype1" in mtch.groupdict() and mtch.groupdict()["dtype1"] is not None: - return mtch.groupdict()["dtype1"] - - elif "dtype2" in mtch.groupdict() and mtch.groupdict()["dtype2"] is not None: - return mtch.groupdict()["dtype2"] - - else: - raise ValueError(f"Not a list dtype: {list_dtype}") - - -def _make_prop_from_prop(prop, additional_options_for_text_props): + Parameters + ---------- + prop : db.Property + the property to be transformed + additional_options_for_text_props : Optional[dict] + dict that may contain the keys 'pattern' and 'format' to + further define the rules for the JSON Schema segment + """ if prop.is_reference(): - raise NotImplementedError( "Reference properties are not supported in this version of the json schema exporter." ) @@ -69,11 +53,11 @@ def _make_prop_from_prop(prop, additional_options_for_text_props): if prop.datatype == db.TEXT or prop.datatype == db.DATETIME: text_format = None text_pattern = None - if prop.name in additional_options_for_text_props: - if "pattern" in additional_options_for_text_props[prop.name]: - text_pattern = additional_options_for_text_props[prop.name]["pattern"] - if "format" in additional_options_for_text_props[prop.name]: - text_format = additional_options_for_text_props[prop.name]["format"] + if additional_options_for_text_props: + if "pattern" in additional_options_for_text_props: + text_pattern = additional_options_for_text_props["pattern"] + if "format" in additional_options_for_text_props: + text_format = additional_options_for_text_props["format"] elif prop.datatype == db.DATETIME: # Set the date or datetime format if only a pattern is given ... text_format = ["date", "date-time"] @@ -94,10 +78,10 @@ def _make_prop_from_prop(prop, additional_options_for_text_props): json_prop["type"] = "integer" elif prop.datatype == db.DOUBLE: json_prop["type"] = "number" - elif isinstance(prop.datatype, str) and prop.datatype.startswith("LIST"): + elif is_list_datatype(prop.datatype): json_prop["type"] = "array" list_element_prop = db.Property( - name=prop.name, datatype=_extract_elemet_dtyp_from_list_dtype(prop.datatype)) + name=prop.name, datatype=get_list_datatype(prop.datatype, strict=True)) json_prop["items"] = _make_prop_from_prop( list_element_prop, additional_options_for_text_props) else: @@ -127,7 +111,7 @@ def _make_text_property(description="", text_format=None, text_pattern=None): def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = True, name_and_description_in_properties: bool = False, - additional_options_for_text_props: dict = {}): + additional_options_for_text_props: Optional[dict] = None): """Create a jsonschema from a given RecordType that can be used, e.g., to validate a json specifying a record of the given type. @@ -152,6 +136,9 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T """ + if additional_options_for_text_props is None: + additional_options_for_text_props = {} + schema = { "$schema": "https://json-schema.org/draft/2019-09/schema", "type": "object" @@ -176,7 +163,9 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T "Creating a schema for multi-properties is not specified. " f"Property {prop.name} occurs more than once." ) - props[prop.name] = _make_prop_from_prop(prop, additional_options_for_text_props) + props[prop.name] = _make_prop_from_prop(prop, additional_options_for_text_props[prop.name] + if prop.name in additional_options_for_text_props + else None) schema["properties"] = props return schema diff --git a/unittests/test_json_schema_exporter.py b/unittests/test_json_schema_exporter.py index b62349d3c14c598a8331707efafa733a0650d95c..42ab9d909ad844cee93db70f75321b5e5e8723ff 100644 --- a/unittests/test_json_schema_exporter.py +++ b/unittests/test_json_schema_exporter.py @@ -38,6 +38,7 @@ def test_empty_rt(): assert schema["description"] == rt.description assert len(schema["properties"]) == 0 assert len(schema["required"]) == 0 + assert schema["additionalProperties"] is True schema = rtjs(rt, additional_properties=False)