Merge "Remove deep dependency from muranoapi"
This commit is contained in:
commit
246a35b6f9
@ -144,6 +144,60 @@ class TraverseHelper(object):
|
||||
raise ValueError(_('Source object or path is malformed'))
|
||||
|
||||
|
||||
def is_different(obj1, obj2):
|
||||
"""
|
||||
Stripped-down version of deep.diff comparator
|
||||
|
||||
Compares arbitrary nested objects, handles circular links, but doesn't
|
||||
point to the first difference as deep.diff does.
|
||||
"""
|
||||
class Difference(Exception):
|
||||
pass
|
||||
|
||||
def is_in(o, st):
|
||||
for _o in st:
|
||||
if o is _o:
|
||||
return True
|
||||
return False
|
||||
|
||||
def rec(o1, o2, stack1=(), stack2=()):
|
||||
if is_in(o1, stack1) and is_in(o2, stack2):
|
||||
# circular reference detected - break the loop
|
||||
return
|
||||
elif is_in(o1, stack1):
|
||||
raise Difference()
|
||||
else:
|
||||
stack1 += (o1,)
|
||||
stack2 += (o2,)
|
||||
|
||||
if o1 is o2:
|
||||
return
|
||||
elif type(o1) != type(o2):
|
||||
raise Difference()
|
||||
elif isinstance(o1, dict):
|
||||
# check for keys inequality
|
||||
rec(o1.keys(), o2.keys(), stack1, stack2)
|
||||
for key in o1.keys():
|
||||
rec(o1[key], o2[key], stack1, stack2)
|
||||
elif isinstance(o1, (list, tuple, set)):
|
||||
if len(o1) != len(o2):
|
||||
raise Difference()
|
||||
else:
|
||||
for _o1, _o2 in zip(o1, o2):
|
||||
rec(_o1, _o2, stack1, stack2)
|
||||
elif hasattr(o1, '__dict__'):
|
||||
return rec(o1.__dict__, o2.__dict__, stack1, stack2)
|
||||
elif o1 != o2:
|
||||
raise Difference()
|
||||
|
||||
try:
|
||||
rec(obj1, obj2)
|
||||
except Difference:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def build_entity_map(value):
|
||||
def build_entity_map_recursive(value, id_map):
|
||||
if isinstance(value, types.DictionaryType):
|
||||
|
@ -18,10 +18,10 @@ import sys
|
||||
import types
|
||||
import uuid
|
||||
|
||||
import deep
|
||||
import eventlet.greenpool
|
||||
import yaql.expressions
|
||||
|
||||
from muranoapi.common import utils
|
||||
import muranoapi.dsl.murano_object
|
||||
import muranoapi.dsl.yaql_expression as yaql_expression
|
||||
|
||||
@ -97,7 +97,7 @@ def merge_lists(list1, list2):
|
||||
for item in list1 + list2:
|
||||
exists = False
|
||||
for old_item in result:
|
||||
if deep.diff(item, old_item) is None:
|
||||
if not utils.is_different(item, old_item):
|
||||
exists = True
|
||||
break
|
||||
if not exists:
|
||||
|
108
muranoapi/tests/common/is_different_tests.py
Normal file
108
muranoapi/tests/common/is_different_tests.py
Normal file
@ -0,0 +1,108 @@
|
||||
# Copyright (c) 2013 Mirantis, Inc.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import unittest2 as unittest
|
||||
|
||||
from muranoapi.common import utils
|
||||
|
||||
|
||||
class IsDifferentTests(unittest.TestCase):
|
||||
def test_equal_dicts(self):
|
||||
obj1 = {'first': 10, 'second': 12}
|
||||
obj2 = {'second': 12, 'first': 10}
|
||||
comparison = utils.is_different(obj1, obj2)
|
||||
self.assertFalse(comparison)
|
||||
|
||||
def test_different_dicts(self):
|
||||
obj1 = {'first': 10, 'second': 11}
|
||||
obj2 = {'first': 10, 'second': 12}
|
||||
comparison = utils.is_different(obj1, obj2)
|
||||
self.assertTrue(comparison)
|
||||
|
||||
def test_different_objs(self):
|
||||
class Cls1(object):
|
||||
a = 10
|
||||
|
||||
class Cls2(object):
|
||||
b = 20
|
||||
|
||||
obj1 = Cls1()
|
||||
obj2 = Cls2()
|
||||
obj3 = Cls1()
|
||||
obj3.a = {'one': 14, 'two': [(1, 2, 3), 'more']}
|
||||
|
||||
comparison1 = utils.is_different(obj1, obj2)
|
||||
comparison2 = utils.is_different(obj1, obj3)
|
||||
|
||||
self.assertTrue(comparison1)
|
||||
self.assertTrue(comparison2)
|
||||
|
||||
def test_equal_objs(self):
|
||||
class Cls(object):
|
||||
pass
|
||||
|
||||
obj1 = Cls()
|
||||
obj2 = Cls()
|
||||
obj1.a = {'one': 14, 'two': [(1, 2, 3), 'more']}
|
||||
obj2.a = {'one': 14, 'two': [(1, 2, 3), 'more']}
|
||||
|
||||
comparison = utils.is_different(obj1, obj2)
|
||||
|
||||
self.assertFalse(comparison)
|
||||
|
||||
def test_equal_circular_objs(self):
|
||||
class Cls(object):
|
||||
pass
|
||||
|
||||
lst1 = [1, 2, 3]
|
||||
lst2 = [1, 2, 3]
|
||||
lst1.append(lst1)
|
||||
lst2.append(lst2)
|
||||
|
||||
dct1 = {'one': 10, 'two': lst1}
|
||||
dct2 = {'one': 10, 'two': lst1}
|
||||
|
||||
obj1 = Cls()
|
||||
obj2 = Cls()
|
||||
obj1.a = obj2.a = 10
|
||||
obj1.self = obj1
|
||||
obj2.self = obj2
|
||||
|
||||
comparison = utils.is_different(lst1, lst2)
|
||||
comparison2 = utils.is_different(dct1, dct2)
|
||||
comparison3 = utils.is_different(obj1, obj2)
|
||||
|
||||
self.assertFalse(comparison)
|
||||
self.assertFalse(comparison2)
|
||||
self.assertFalse(comparison3)
|
||||
|
||||
def test_different_circular_objs(self):
|
||||
class Cls(object):
|
||||
pass
|
||||
|
||||
obj1 = Cls()
|
||||
obj2 = Cls()
|
||||
obj1.self = obj1
|
||||
obj2.self = {'self': obj2}
|
||||
|
||||
dct1 = {'one': [1, 2], 'three': 10}
|
||||
dct2 = {'one': [1, 2]}
|
||||
dct1['self'] = dct1
|
||||
dct2['self'] = dct2
|
||||
|
||||
comparison = utils.is_different(obj1, obj2)
|
||||
comparison1 = utils.is_different(dct1, dct2)
|
||||
|
||||
self.assertTrue(comparison)
|
||||
self.assertTrue(comparison1)
|
@ -38,4 +38,3 @@ oslo.messaging>=1.3.0a9
|
||||
|
||||
# not listed in global requirements
|
||||
yaql>=0.2.2,<0.3
|
||||
deep
|
||||
|
Loading…
x
Reference in New Issue
Block a user