Skip to content
Snippets Groups Projects
Commit 5b8df05b authored by Florian Spreckelsen's avatar Florian Spreckelsen
Browse files

ENH: Implement list and scalar properties

parent 2e1b0e23
No related branches found
No related tags found
2 merge requests!89ENH: JsonSchemaExporter accepts do_not_create parameter.,!80F simple schema export
Pipeline #42156 failed
......@@ -20,6 +20,8 @@
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
import re
import linkahead as db
......@@ -33,15 +35,76 @@ def _make_required_list(rt: db.RecordType):
return required
def _make_prop_from_prop(prop):
def _extract_elemet_dtyp_from_list_dtype(list_dtype):
if not list_dtype.lower().startswith("list"):
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:
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}")
if prop.datatype == db.TEXT:
return _make_text_property(prop.description)
elif prop.datatype == db.DATETIME:
return _make_text_property(prop.description, "date-time")
def _make_prop_from_prop(prop, additional_options_for_text_props):
if prop.is_reference():
raise NotImplementedError(
"Reference properties are not supported in this version of the json schema exporter."
)
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"]
elif prop.datatype == db.DATETIME:
# Set the date or datetime format if only a pattern is given ...
text_format = ["date", "date-time"]
elif prop.datatype == db.DATETIME:
# ... again, for those props that don't appear in the additional
# options list.
text_format = ["date", "date-time"]
return _make_text_property(prop.description, text_format, text_pattern)
json_prop = {}
# if prop.description
if prop.description:
json_prop["description"] = prop.description
if prop.datatype == db.BOOLEAN:
json_prop["type"] = "boolean"
elif prop.datatype == db.INTEGER:
json_prop["type"] = "integer"
elif prop.datatype == db.DOUBLE:
json_prop["type"] = "number"
elif prop.datatype.startswith("LIST"):
json_prop["type"] = "array"
list_element_prop = db.Property(
name=prop.name, datatype=_extract_elemet_dtyp_from_list_dtype(prop.datatype))
json_prop["items"] = _make_prop_from_prop(
list_element_prop, additional_options_for_text_props)
else:
raise ValueError(
f"Unknown or no property datatype. Property {prop.name} with type {prop.datatype}")
return json_prop
def _make_text_property(description="", text_format=None, text_pattern=None):
......@@ -52,7 +115,10 @@ def _make_text_property(description="", text_format=None, text_pattern=None):
if description:
prop["description"] = description
if text_format is not None:
prop["format"] = text_format
if isinstance(text_format, list):
prop["anyOf"] = [{"format": tf} for tf in text_format]
else:
prop["format"] = text_format
if text_pattern is not None:
prop["pattern"] = text_pattern
......@@ -60,7 +126,8 @@ 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):
name_and_description_in_properties: bool = False,
additional_options_for_text_props: dict = {}):
"""Create a jsonschema from a given RecordType that can be used, e.g., to
validate a json specifying a record of the given type.
......@@ -74,6 +141,9 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
name_and_description_in_properties : bool, optional
Whether to include name and description in the `properties` section of
the schema to be exported. Optional, default is False.
additional_options_for_text_props : dict, optional
Dictionary containing additional "pattern" or "format" options for
string-typed properties. Optional, default is empty.
Returns
-------
......@@ -99,5 +169,8 @@ def recordtype_to_json_schema(rt: db.RecordType, additional_properties: bool = T
props["name"] = _make_text_property("The name of the Record to be created")
props["description"] = _make_text_property("The description of the Record to be created")
for prop in rt.properties:
props[prop.name] = _make_prop_from_prop(prop, additional_options_for_text_props)
schema["properties"] = props
return schema
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment