Skip to content
Snippets Groups Projects
Verified Commit f12bc9cf authored by Daniel Hornung's avatar Daniel Hornung
Browse files

ENH: DataModel now has `get_deep(name)`.

This should make quite a few integration tests unnecessary.  for example it allows
`test_reference_options()` in `test_json_schema_exporter.py`.
parent 1a34df84
No related branches found
No related tags found
2 merge requests!89ENH: JsonSchemaExporter accepts do_not_create parameter.,!82ENH: JsonSchemaExporter accepts do_not_create parameter.
Pipeline #43062 failed
......@@ -137,12 +137,15 @@ class JsonSchemaExporter:
# TODO: different issue
raise NotImplementedError("Files have not been implemented yet.")
else:
values = self._retrieve_enum_values(f"RECORD '{prop.datatype}'")
if prop.datatype in self._do_not_create:
prop_name = prop.datatype
if isinstance(prop.datatype, db.Entity):
prop_name = prop.datatype.name
values = self._retrieve_enum_values(f"RECORD '{prop_name}'")
if prop_name in self._do_not_create:
# Only a simple list of values
json_prop["enum"] = values
else:
rt = db.execute_query(f"FIND RECORDTYPE WITH name='{prop.datatype}'",
rt = db.execute_query(f"FIND RECORDTYPE WITH name='{prop_name}'",
unique=True)
subschema = self._make_segment_from_recordtype(rt)
subschema["title"] = "Create new"
......
......@@ -262,3 +262,27 @@ class DataModel(dict):
all_ents[prop.name] = prop
return list(all_ents.values())
def get_deep(self, name, visited: set = None):
"""Attempt to resolve references for the given ``name``.
This methods only uses data which is available in this datamodel, which acts kind of like a
cache pool.
"""
entity = self.get(name)
if not entity:
return entity
if not visited:
visited = set()
# new_props = []
for prop in list(entity.get_properties()): # Make a change-resistant list copy.
if prop.name in visited:
continue
visited.add(prop.name)
if prop.name in self:
entity.remove_property(prop).add_property(self.get_deep(prop.name,
visited=visited))
else:
print(f"Referenced property \"{prop.name}\" not found in data model.")
return entity
......@@ -22,6 +22,8 @@
"""Tests the Json schema exporter."""
import json
import linkahead as db
from jsonschema import FormatChecker, validate, ValidationError
......@@ -29,6 +31,16 @@ from pytest import raises
from unittest.mock import Mock, patch
from caosadvancedtools.json_schema_exporter import recordtype_to_json_schema as rtjs
from caosadvancedtools.models.parser import parse_model_from_string
RT1 = parse_model_from_string("""
RT1:
description: some description
obligatory_properties:
some_date:
datatype: DATETIME
description: Just some date
""").get_deep("RT1")
def _mock_execute_query(query_string, unique=False, **kwargs):
......@@ -62,6 +74,10 @@ def _mock_execute_query(query_string, unique=False, **kwargs):
return referencing_type_records
elif query_string == "FIND RECORDTYPE WITH name='ReferencingType'" and unique is True:
return referencing_type_rt
elif query_string == "SELECT name, id FROM RECORD 'RT1'":
return referencing_type_records # wrong types, but who cares for the test?
elif query_string == "FIND RECORDTYPE WITH name='RT1'" and unique is True:
return RT1
elif query_string == "SELECT name, id FROM RECORD":
return all_records
elif query_string == "SELECT name, id FROM FILE":
......@@ -548,3 +564,113 @@ def test_broken():
rtjs(rt)
assert "MultiProp" in str(nie)
assert str(nie).startswith("Creating a schema for multi-properties is not specified.")
@patch("linkahead.execute_query", new=Mock(side_effect=_mock_execute_query))
def test_reference_options():
"""Testing miscellaneous options.
"""
model_str = """
RT1:
description: some description
obligatory_properties:
some_date:
datatype: DATETIME
description: Just some date
RT2:
obligatory_properties:
RT1:
"""
model = parse_model_from_string(model_str)
# First test: without reference
rt1_dict = rtjs(model.get_deep("RT1"))
assert json.dumps(rt1_dict, indent=2) == """{
"type": "object",
"required": [],
"additionalProperties": true,
"properties": {
"some_date": {
"description": "Just some date",
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "string",
"format": "date-time"
}
]
}
},
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "RT1",
"description": "some description"
}"""
# Second test: with reference
# from IPython import embed
# embed()
rt2_dict = rtjs(model.get_deep("RT2"))
assert json.dumps(rt2_dict, indent=2) == """{
"type": "object",
"required": [],
"additionalProperties": true,
"properties": {
"RT1": {
"description": "some description",
"oneOf": [
{
"title": "Existing entries",
"enum": [
"103",
"104, referencing"
]
},
{
"type": "object",
"required": [],
"additionalProperties": true,
"properties": {
"some_date": {
"description": "Just some date",
"anyOf": [
{
"type": "string",
"format": "date"
},
{
"type": "string",
"format": "date-time"
}
]
}
},
"title": "Create new"
}
]
}
},
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "RT2"
}"""
# Third test: Reference prop shall be only existing references, no option to create new ones.
rt2_dict = rtjs(model.get_deep("RT2"), do_not_create=["RT1"])
assert json.dumps(rt2_dict, indent=2) == """{
"type": "object",
"required": [],
"additionalProperties": true,
"properties": {
"RT1": {
"description": "some description",
"enum": [
"103",
"104, referencing"
]
}
},
"$schema": "https://json-schema.org/draft/2019-09/schema",
"title": "RT2"
}"""
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