diff options
author | Joel Diaz <jdiaz@redhat.com> | 2017-02-28 17:33:18 +0000 |
---|---|---|
committer | Joel Diaz <jdiaz@redhat.com> | 2017-02-28 17:33:18 +0000 |
commit | 0d9ce34564d72520407cb1dba9a785e2faec49b9 (patch) | |
tree | dddd3e8c797ad3b7fccb53cc36abea0cd0b3fb16 | |
parent | bfe7e99d9a09f06f021f73dfd2631e28dc3983b0 (diff) | |
download | openshift-0d9ce34564d72520407cb1dba9a785e2faec49b9.tar.gz openshift-0d9ce34564d72520407cb1dba9a785e2faec49b9.tar.bz2 openshift-0d9ce34564d72520407cb1dba9a785e2faec49b9.tar.xz openshift-0d9ce34564d72520407cb1dba9a785e2faec49b9.zip |
raise exceptions when walking through object path
if we're given path a.b.c and the existing object is:
a:
b:
- item1
raise an exception due to unexpected objects found while traversing the path (ie. b is a list, not a dict)
also, add_entry assumes new dicts for each sub element when creating elements besides the final assignment value.
doing something like a.b.c[0] = 12 where 'c' doesn't exist raises an exception
add test cases to cover:
access path that differs from existing object
create new objects with an embedded list in the path
create new object with a list at the end (define the end list in the passed in 'value' to avoid this exception)
-rw-r--r-- | roles/lib_utils/library/yedit.py | 11 | ||||
-rw-r--r-- | roles/lib_utils/src/class/yedit.py | 11 | ||||
-rwxr-xr-x | roles/lib_utils/src/test/unit/test_yedit.py | 21 |
3 files changed, 38 insertions, 5 deletions
diff --git a/roles/lib_utils/library/yedit.py b/roles/lib_utils/library/yedit.py index b1d9d6869..a2ae6b4f6 100644 --- a/roles/lib_utils/library/yedit.py +++ b/roles/lib_utils/library/yedit.py @@ -311,7 +311,8 @@ class Yedit(object): continue elif data and not isinstance(data, dict): - return None + raise YeditException("Unexpected item type found while going through key " + + "path: {} (at key: {})".format(key, dict_key)) data[dict_key] = {} data = data[dict_key] @@ -320,7 +321,7 @@ class Yedit(object): int(arr_ind) <= len(data) - 1): data = data[int(arr_ind)] else: - return None + raise YeditException("Unexpected item type found while going through key path: {}".format(key)) if key == '': data = item @@ -334,6 +335,12 @@ class Yedit(object): elif key_indexes[-1][1] and isinstance(data, dict): data[key_indexes[-1][1]] = item + # didn't add/update to an existing list, nor add/update key to a dict + # so we must have been provided some syntax like a.b.c[<int>] = "data" for a + # non-existent array + else: + raise YeditException("Error adding to object at path: {}".format(key)) + return data @staticmethod diff --git a/roles/lib_utils/src/class/yedit.py b/roles/lib_utils/src/class/yedit.py index 74ee52fe3..533665db2 100644 --- a/roles/lib_utils/src/class/yedit.py +++ b/roles/lib_utils/src/class/yedit.py @@ -125,7 +125,8 @@ class Yedit(object): continue elif data and not isinstance(data, dict): - return None + raise YeditException("Unexpected item type found while going through key " + + "path: {} (at key: {})".format(key, dict_key)) data[dict_key] = {} data = data[dict_key] @@ -134,7 +135,7 @@ class Yedit(object): int(arr_ind) <= len(data) - 1): data = data[int(arr_ind)] else: - return None + raise YeditException("Unexpected item type found while going through key path: {}".format(key)) if key == '': data = item @@ -148,6 +149,12 @@ class Yedit(object): elif key_indexes[-1][1] and isinstance(data, dict): data[key_indexes[-1][1]] = item + # didn't add/update to an existing list, nor add/update key to a dict + # so we must have been provided some syntax like a.b.c[<int>] = "data" for a + # non-existent array + else: + raise YeditException("Error adding to object at path: {}".format(key)) + return data @staticmethod diff --git a/roles/lib_utils/src/test/unit/test_yedit.py b/roles/lib_utils/src/test/unit/test_yedit.py index ed07ac96e..ce5e027a7 100755 --- a/roles/lib_utils/src/test/unit/test_yedit.py +++ b/roles/lib_utils/src/test/unit/test_yedit.py @@ -23,7 +23,7 @@ import unittest yedit_path = os.path.join('/'.join(os.path.realpath(__file__).split('/')[:-4]), 'library') # noqa: E501 sys.path.insert(0, yedit_path) -from yedit import Yedit # noqa: E402 +from yedit import Yedit, YeditException # noqa: E402 # pylint: disable=too-many-public-methods # Silly pylint, moar tests! @@ -200,6 +200,7 @@ class YeditTest(unittest.TestCase): yed.append('x:y:z', [5, 6]) yed.append('x:y:z', [5, 6]) self.assertTrue(yed.get('x:y:z') == [1, 2, 3, [5, 6], [5, 6]]) + # pylint: disable=maybe-no-member self.assertTrue(2 == yed.get('x:y:z').count([5, 6])) self.assertFalse(yed.exists('x:y:z', 4)) @@ -268,6 +269,24 @@ class YeditTest(unittest.TestCase): yed.pop('a#b', 'c') self.assertTrue({'a': {'b': {'d': 2}}} == yed.yaml_dict) + def test_accessing_path_with_unexpected_objects(self): + '''test providing source path objects that differ from current object state''' + yed = Yedit(content={'a': {'b': {'c': ['d', 'e']}}}) + with self.assertRaises(YeditException): + yed.put('a.b.c.d', 'x') + + def test_creating_new_objects_with_embedded_list(self): + '''test creating new objects with an embedded list in the creation path''' + yed = Yedit(content={'a': {'b': 12}}) + with self.assertRaises(YeditException): + yed.put('new.stuff[0].here', 'value') + + def test_creating_new_objects_with_trailing_list(self): + '''test creating new object(s) where the final piece is a list''' + yed = Yedit(content={'a': {'b': 12}}) + with self.assertRaises(YeditException): + yed.put('new.stuff.here[0]', 'item') + def tearDown(self): '''TearDown method''' os.unlink(YeditTest.filename) |