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