diff options
Diffstat (limited to 'pykolab/xml/utils.py')
-rw-r--r-- | pykolab/xml/utils.py | 48 |
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__: |