summaryrefslogtreecommitdiffstats
path: root/pykolab
diff options
context:
space:
mode:
authorThomas Bruederli <bruederli@kolabsys.com>2015-03-24 21:08:12 +0100
committerThomas Bruederli <bruederli@kolabsys.com>2015-03-24 21:08:12 +0100
commitaa3b0f23dccfb8c8e52fc6f27fb7b99bad42a0b5 (patch)
treee33a9121e4a53ffd66f49fb8c6f94590e4b206a2 /pykolab
parentd222679e9db6abf76578f9b6c5e4ffb96464495c (diff)
downloadpykolab-aa3b0f23dccfb8c8e52fc6f27fb7b99bad42a0b5.tar.gz
Improve object diff computation: ignore order of attribute lists (e.g. attachments, attendees)
Diffstat (limited to 'pykolab')
-rw-r--r--pykolab/xml/utils.py48
1 files changed, 44 insertions, 4 deletions
diff --git a/pykolab/xml/utils.py b/pykolab/xml/utils.py
index c92c52f..261e33c 100644
--- a/pykolab/xml/utils.py
+++ b/pykolab/xml/utils.py
@@ -253,16 +253,15 @@ def compute_diff(a, b, reduced=False):
aa = [aa]
if not isinstance(bb, list):
bb = [bb]
+
+ (aa, bb) = order_proplists(aa, bb)
index = 0
length = max(len(aa), len(bb))
while index < length:
aai = aa[index] if index < len(aa) else None
bbi = bb[index] if index < len(bb) else None
if not compare_values(aai, bbi):
- if reduced:
- (old, new) = reduce_properties(aai, bbi)
- else:
- (old, new) = (aai, bbi)
+ (old, new) = reduce_properties(aai, bbi) if reduced else (aai, bbi)
diff.append(OrderedDict([('property', prop), ('index', index), ('old', old), ('new', new)]))
index += 1
@@ -277,6 +276,47 @@ def compute_diff(a, b, reduced=False):
return diff
+def order_proplists(a, b):
+ """
+ Orders two lists so that equal entries have the same position
+ """
+ # nothing to be done here
+ if len(a) == 0 and len(b) == 0:
+ return (a, b)
+
+ base = a
+ comp = b
+ flip = False
+
+ if len(a) > len(b):
+ flip = True
+ base = b
+ comp = a
+
+ indices = []
+ top = len(comp) + 1
+ for bb in comp:
+ index = None
+
+ # find a matching entry in base
+ for j, aa in enumerate(base):
+ if compare_values(aa, bb):
+ index = j
+ break
+
+ # move non-matching items to the end of the list
+ if index is None:
+ index = top
+ top += 1
+
+ indices.append(index)
+
+ # do sort by indices
+ indices, comp = zip(*sorted(zip(indices, comp), key=lambda x: x[0]))
+
+ return (comp, base) if flip else (base, comp)
+
+
def compare_values(aa, bb):
ignore_keys = ['rsvp']
if not aa.__class__ == bb.__class__: