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: ...@@ -137,12 +137,15 @@ class JsonSchemaExporter:
# TODO: different issue # TODO: different issue
raise NotImplementedError("Files have not been implemented yet.") raise NotImplementedError("Files have not been implemented yet.")
else: else:
values = self._retrieve_enum_values(f"RECORD '{prop.datatype}'") prop_name = prop.datatype
if prop.datatype in self._do_not_create: 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 # Only a simple list of values
json_prop["enum"] = values json_prop["enum"] = values
else: 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) unique=True)
subschema = self._make_segment_from_recordtype(rt) subschema = self._make_segment_from_recordtype(rt)
subschema["title"] = "Create new" subschema["title"] = "Create new"
......
...@@ -262,3 +262,27 @@ class DataModel(dict): ...@@ -262,3 +262,27 @@ class DataModel(dict):
all_ents[prop.name] = prop all_ents[prop.name] = prop
return list(all_ents.values()) 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 @@ ...@@ -22,6 +22,8 @@
"""Tests the Json schema exporter.""" """Tests the Json schema exporter."""
import json
import linkahead as db import linkahead as db
from jsonschema import FormatChecker, validate, ValidationError from jsonschema import FormatChecker, validate, ValidationError
...@@ -29,6 +31,16 @@ from pytest import raises ...@@ -29,6 +31,16 @@ from pytest import raises
from unittest.mock import Mock, patch from unittest.mock import Mock, patch
from caosadvancedtools.json_schema_exporter import recordtype_to_json_schema as rtjs 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): def _mock_execute_query(query_string, unique=False, **kwargs):
...@@ -62,6 +74,10 @@ 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 return referencing_type_records
elif query_string == "FIND RECORDTYPE WITH name='ReferencingType'" and unique is True: elif query_string == "FIND RECORDTYPE WITH name='ReferencingType'" and unique is True:
return referencing_type_rt 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": elif query_string == "SELECT name, id FROM RECORD":
return all_records return all_records
elif query_string == "SELECT name, id FROM FILE": elif query_string == "SELECT name, id FROM FILE":
...@@ -548,3 +564,113 @@ def test_broken(): ...@@ -548,3 +564,113 @@ def test_broken():
rtjs(rt) rtjs(rt)
assert "MultiProp" in str(nie) assert "MultiProp" in str(nie)
assert str(nie).startswith("Creating a schema for multi-properties is not specified.") 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.
Please register or to comment