allow with kwargs (option override) to create nested objects 98/9098/4
authortierno <alfonso.tiernosepulveda@telefonica.com>
Wed, 17 Jun 2020 07:42:30 +0000 (07:42 +0000)
committertierno <alfonso.tiernosepulveda@telefonica.com>
Mon, 22 Jun 2020 13:55:17 +0000 (13:55 +0000)
Change-Id: I4ca24e1117f86eaf6e4d18863c478a4d536e2374
Signed-off-by: tierno <alfonso.tiernosepulveda@telefonica.com>
osm_nbi/base_topic.py
osm_nbi/tests/test_base_topic.py [new file with mode: 0755]

index 2986b81..130d4fc 100644 (file)
@@ -325,12 +325,23 @@ class BaseTopic:
                         update_content = update_content[kitem_old]
                     if isinstance(update_content, dict):
                         kitem_old = kitem
                         update_content = update_content[kitem_old]
                     if isinstance(update_content, dict):
                         kitem_old = kitem
+                        if not isinstance(update_content.get(kitem_old), (dict, list)):
+                            update_content[kitem_old] = {}
                     elif isinstance(update_content, list):
                     elif isinstance(update_content, list):
+                        # key must be an index of the list, must be integer
                         kitem_old = int(kitem)
                         kitem_old = int(kitem)
+                        # if index greater than list, extend the list
+                        if kitem_old >= len(update_content):
+                            update_content += [None] * (kitem_old - len(update_content) + 1)
+                        if not isinstance(update_content[kitem_old], (dict, list)):
+                            update_content[kitem_old] = {}
                     else:
                         raise EngineException(
                             "Invalid query string '{}'. Descriptor is not a list nor dict at '{}'".format(k, kitem))
                     else:
                         raise EngineException(
                             "Invalid query string '{}'. Descriptor is not a list nor dict at '{}'".format(k, kitem))
-                update_content[kitem_old] = v if not yaml_format else safe_load(v)
+                if v is None:
+                    del update_content[kitem_old]
+                else:
+                    update_content[kitem_old] = v if not yaml_format else safe_load(v)
         except KeyError:
             raise EngineException(
                 "Invalid query string '{}'. Descriptor does not contain '{}'".format(k, kitem_old))
         except KeyError:
             raise EngineException(
                 "Invalid query string '{}'. Descriptor does not contain '{}'".format(k, kitem_old))
diff --git a/osm_nbi/tests/test_base_topic.py b/osm_nbi/tests/test_base_topic.py
new file mode 100755 (executable)
index 0000000..a3fc32c
--- /dev/null
@@ -0,0 +1,73 @@
+#! /usr/bin/python3
+# -*- coding: utf-8 -*-
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+__author__ = "Alfonso Tierno, alfonso.tiernosepulveda@telefonica.com"
+__date__ = "2020-06-17"
+
+import unittest
+from unittest import TestCase
+# from unittest.mock import Mock
+# from osm_common import dbbase, fsbase, msgbase
+from osm_nbi.base_topic import BaseTopic, EngineException
+
+
+class Test_BaseTopic(TestCase):
+
+    @classmethod
+    def setUpClass(cls):
+        cls.test_name = "test-base-topic"
+
+    @classmethod
+    def tearDownClass(cls):
+        pass
+
+    def setUp(self):
+        pass
+        # self.db = Mock(dbbase.DbBase())
+        # self.fs = Mock(fsbase.FsBase())
+        # self.msg = Mock(msgbase.MsgBase())
+        # self.auth = Mock(authconn.Authconn(None, None, None))
+
+    def test_update_input_with_kwargs(self):
+
+        test_set = (
+            # (descriptor content, kwargs, expected descriptor (None=fails), message)
+            ({"a": {"none": None}}, {"a.b.num": "v"}, {"a": {"none": None, "b": {"num": "v"}}}, "create dict"),
+            ({"a": {"none": None}}, {"a.none.num": "v"}, {"a": {"none": {"num": "v"}}}, "create dict over none"),
+            ({"a": {"b": {"num": 4}}}, {"a.b.num": "v"}, {"a": {"b": {"num": "v"}}}, "replace_number"),
+            ({"a": {"b": {"num": 4}}}, {"a.b.num.c.d": "v"}, {"a": {"b": {"num": {"c": {"d": "v"}}}}},
+             "create dict over number"),
+            ({"a": {"b": {"num": 4}}}, {"a.b": "v"}, {"a": {"b": "v"}}, "replace dict with a string"),
+            ({"a": {"b": {"num": 4}}}, {"a.b": None}, {"a": {}}, "replace dict with None"),
+            ({"a": [{"b": {"num": 4}}]}, {"a.b.num": "v"}, None, "create dict over list should fail"),
+            ({"a": [{"b": {"num": 4}}]}, {"a.0.b.num": "v"}, {"a": [{"b": {"num": "v"}}]}, "set list"),
+            ({"a": [{"b": {"num": 4}}]}, {"a.3.b.num": "v"},
+             {"a": [{"b": {"num": 4}}, None, None, {"b": {"num": "v"}}]}, "expand list"),
+            ({"a": [[4]]}, {"a.0.0": "v"}, {"a": [["v"]]}, "set nested list"),
+            ({"a": [[4]]}, {"a.0.2": "v"}, {"a": [[4, None, "v"]]}, "expand nested list"),
+            ({"a": [[4]]}, {"a.2.2": "v"}, {"a": [[4], None, {"2": "v"}]}, "expand list and add number key"),
+            ({"a": None}, {"b.c": "v"}, {"a": None, "b": {"c": "v"}}, "expand at root"),
+        )
+        for desc, kwargs, expected, message in test_set:
+            if expected is None:
+                self.assertRaises(EngineException, BaseTopic._update_input_with_kwargs, desc, kwargs)
+            else:
+                BaseTopic._update_input_with_kwargs(desc, kwargs)
+                self.assertEqual(desc, expected, message)
+
+
+if __name__ == '__main__':
+    unittest.main()