From d97c542607f59e5d6d54f5334220c3f5a3905c0e Mon Sep 17 00:00:00 2001 From: Daniel <d.hornung@indiscale.com> Date: Mon, 30 Oct 2023 18:11:15 +0100 Subject: [PATCH] FIX: Fixed get_deep a bit, added more tests. --- src/caosadvancedtools/json_schema_exporter.py | 12 ++++++-- src/caosadvancedtools/models/data_model.py | 14 +++++++-- unittests/test_data_model.py | 29 +++++++++++++++++++ unittests/test_json_schema_exporter.py | 23 ++++++++++----- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/caosadvancedtools/json_schema_exporter.py b/src/caosadvancedtools/json_schema_exporter.py index 66cda6d8..cfe17dba 100644 --- a/src/caosadvancedtools/json_schema_exporter.py +++ b/src/caosadvancedtools/json_schema_exporter.py @@ -75,8 +75,16 @@ class JsonSchemaExporter: @staticmethod def _make_required_list(rt: db.RecordType): """Return the list of names of properties with importance db.OBLIGATORY.""" - return [prop.name for prop in rt.properties - if rt.get_importance(prop.name) == db.OBLIGATORY] + required_list = [] + for prop in rt.properties: + if rt.get_importance(prop.name) != db.OBLIGATORY: + continue + prop_name = prop.name + if isinstance(prop.datatype, db.Entity): + prop_name = prop.datatype.name + required_list.append(prop_name) + + return required_list def _make_segment_from_prop(self, prop: db.Property): """Return the JSON Schema segment for the given property diff --git a/src/caosadvancedtools/models/data_model.py b/src/caosadvancedtools/models/data_model.py index b578223c..bb40939a 100644 --- a/src/caosadvancedtools/models/data_model.py +++ b/src/caosadvancedtools/models/data_model.py @@ -268,6 +268,9 @@ class DataModel(dict): This methods only uses data which is available in this datamodel, which acts kind of like a cache pool. + + Note that this may change this data model (subsequent "get" like calls may also return deep + content.) """ entity = self.get(name) if not entity: @@ -281,8 +284,15 @@ class DataModel(dict): continue visited.add(prop.name) if prop.name in self: - entity.remove_property(prop).add_property(self.get_deep(prop.name, - visited=visited)) + deep_prop = self.get_deep(prop.name, visited=visited) + linked_prop = entity.get_property(prop) + if not linked_prop.datatype: + if deep_prop.role == "Property": + linked_prop.datatype = deep_prop.datatype + elif deep_prop.role == "RecordType": + linked_prop.datatype = deep_prop + if deep_prop.description: + linked_prop.description = deep_prop.description else: print(f"Referenced property \"{prop.name}\" not found in data model.") return entity diff --git a/unittests/test_data_model.py b/unittests/test_data_model.py index 159adfca..5aa151b2 100644 --- a/unittests/test_data_model.py +++ b/unittests/test_data_model.py @@ -2,6 +2,7 @@ import unittest import caosdb as db from caosadvancedtools.models.data_model import DataModel +from caosadvancedtools.models.parser import parse_model_from_string class DataModelTest(unittest.TestCase): @@ -33,3 +34,31 @@ class DataModelTest(unittest.TestCase): DataModel.sync_ids_by_name(l1, l2) assert l1["TestRecord"].id == rt.id assert l1["TestRecord2"].id < 0 + + def test_get_deep(self): + model_recursive_str = """ +RT1: + description: some description + obligatory_properties: + RT1: + """ + model_recursive = parse_model_from_string(model_recursive_str) + prop1 = model_recursive["RT1"].get_property("RT1") + assert prop1.datatype is None + # TODO The next line actually changes model_recursive in place, is this OK? + RT1 = model_recursive.get_deep("RT1") + assert model_recursive["RT1"] == RT1 + + model_unresolved_str = """ +RT1: + description: some description + obligatory_properties: + unresolved: + """ + model_unresolved = parse_model_from_string(model_unresolved_str) + rt1_unresolved = model_unresolved["RT1"] + prop_unresolved = model_unresolved.get_deep("unresolved") + assert prop_unresolved.datatype is None + rt1_deep = model_unresolved.get_deep("RT1") + assert rt1_deep == rt1_unresolved + assert rt1_deep is rt1_unresolved diff --git a/unittests/test_json_schema_exporter.py b/unittests/test_json_schema_exporter.py index 2c04e970..597c86a9 100644 --- a/unittests/test_json_schema_exporter.py +++ b/unittests/test_json_schema_exporter.py @@ -83,6 +83,7 @@ def _mock_execute_query(query_string, unique=False, **kwargs): elif query_string == "SELECT name, id FROM FILE": return all_files else: + print(f"Query string: {query_string}") return db.Container() @@ -587,7 +588,9 @@ RT2: rt1_dict = rtjs(model.get_deep("RT1")) assert json.dumps(rt1_dict, indent=2) == """{ "type": "object", - "required": [], + "required": [ + "some_date" + ], "additionalProperties": true, "properties": { "some_date": { @@ -609,13 +612,13 @@ RT2: "description": "some description" }""" # Second test: with reference - - # from IPython import embed - # embed() - rt2_dict = rtjs(model.get_deep("RT2")) + rt2_deep = model.get_deep("RT2") + rt2_dict = rtjs(rt2_deep) assert json.dumps(rt2_dict, indent=2) == """{ "type": "object", - "required": [], + "required": [ + "RT1" + ], "additionalProperties": true, "properties": { "RT1": { @@ -630,7 +633,9 @@ RT2: }, { "type": "object", - "required": [], + "required": [ + "some_date" + ], "additionalProperties": true, "properties": { "some_date": { @@ -660,7 +665,9 @@ RT2: rt2_dict = rtjs(model.get_deep("RT2"), do_not_create=["RT1"]) assert json.dumps(rt2_dict, indent=2) == """{ "type": "object", - "required": [], + "required": [ + "RT1" + ], "additionalProperties": true, "properties": { "RT1": { -- GitLab