Esempio n. 1
0
def compare_ordered_element(a_element, b_element, *args, **kwargs):
    """
    Compares two element trees and returns (same,message) where same is true
      if they are the same, and message is a list of the differences
    @ In, a_element, ET.Element, the first element tree
    @ In, b_element, ET.Element, the second element tree
    @ In, args, dict, arguments
    @ In, kwargs, dict, keyword arguments
      accepted args:
        - none -
      accepted kwargs:
        path: a string to describe where the element trees are located (mainly
              used recursively)
    @ Out, compare_ordered_element, (bool,[string]), results of comparison
  """
    same = True
    message = []
    options = kwargs
    path = kwargs.get('path', '')
    counter = kwargs.get('counter', 0)
    DU.set_default_options(options)

    def fail_message(*args):
        """
      adds the fail message to the list
      @ In, args, list, The arguments to the fail message (will be converted with str())
      @ Out, fail_message, (bool,string), results
    """
        print_args = [path]
        print_args.extend(args)
        args_expanded = " ".join([str(x) for x in print_args])
        message.append(args_expanded)

    if a_element.tag != b_element.tag:
        same = False
        fail_message("mismatch tags ", a_element.tag, b_element.tag)
    else:
        path += a_element.tag + "/"
    if a_element.text != b_element.text:
        succeeded, note = cswf(
            a_element.text,
            b_element.text,
            rel_err=options["rel_err"],
            zero_threshold=options["zero_threshold"],
            remove_whitespace=options["remove_whitespace"],
            remove_unicode_identifier=options["remove_unicode_identifier"])
        if not succeeded:
            same = False
            fail_message(note)
            return (same, message)
    different_keys = set(a_element.keys()).symmetric_difference(
        set(b_element.keys()))
    same_keys = set(a_element.keys()).intersection(set(b_element.keys()))
    if len(different_keys) != 0:
        same = False
        fail_message("mismatch attribute keys ", different_keys)
    for key in same_keys:
        if a_element.attrib[key] != b_element.attrib[key]:
            same = False
            fail_message("mismatch attribute ", key, a_element.attrib[key],
                         b_element.attrib[key])
    if len(a_element) != len(b_element):
        same = False
        fail_message("mismatch number of children ", len(a_element),
                     len(b_element))
    else:
        if a_element.tag == b_element.tag:
            #find all matching XML paths
            #WARNING: this will mangle the XML, so other testing should happen above this!
            found = []
            for i in range(len(a_element)):
                sub_options = dict(options)
                sub_options["path"] = path
                (same_child,
                 _) = compare_ordered_element(a_element[i], b_element[i],
                                              *args, **sub_options)
                if same_child:
                    found.append((a_element[i], b_element[i]))
                same = same and same_child
            #prune matches from trees
            for children in found:
                a_element.remove(children[0])
                b_element.remove(children[1])
            #once all pruning done, error on any remaining structure
            if counter == 0:  #on head now, recursion is finished
                if len(a_element) > 0:
                    a_string = ET.tostring(a_element)
                    if len(a_string) > 80:
                        message.append(
                            'Branches in gold not matching test...\n{}'.format(
                                path))
                    else:
                        message.append(
                            'Branches in gold not matching test...\n{} {}'.
                            format(path, a_string))
                if len(b_element) > 0:
                    b_string = ET.tostring(b_element)
                    if len(b_string) > 80:
                        message.append(
                            'Branches in test not matching gold...\n{}'.format(
                                path))
                    else:
                        message.append(
                            'Branches in test not matching gold...\n{} {}'.
                            format(path, b_string))
    return (same, message)
Esempio n. 2
0
 def diff(self):
     """
   Run the comparison.
   returns (same,messages) where same is true if the
   image files are the same, and messages is a string with all the
   differences.
   In, None
   Out, None
 """
     # read in files
     files_read = False
     for outfile in self.__out_file:
         test_filename = os.path.join(self.__test_dir, outfile)
         gold_filename = os.path.join(self.__test_dir, 'gold', outfile)
         if not os.path.exists(test_filename):
             self.__same = False
             self.__messages += 'Test file does not exist: ' + test_filename
         elif not os.path.exists(gold_filename):
             self.__same = False
             self.__messages += 'Gold file does not exist: ' + gold_filename
         else:
             files_read = True
     #read in files
     if files_read:
         if not correctImport:
             self.__messages += 'ImageDiff cannot run with scipy version less '+\
               'than 0.15.0, and requires the PIL installed; scipy version is '+\
               str(scipy.__version__)
             self.__same = False
             return (self.__same, self.__messages)
         try:
             # RAK - The original line...
             # test_image = imread(open(test_filename,'r'))
             # ...didn't work on Windows Python because it couldn't sense the file type
             test_image = imread(test_filename)
         except IOError:
             self.__messages += 'Unrecognized file type for test image in scipy.imread: ' + test_filename
             files_read = False
             return (False, self.__messages)
         try:
             # RAK - The original line...
             # gold_image = imread(open(gold_filename,'r'))
             # ...didn't work on Windows Python because it couldn't sense the file type
             gold_image = imread(gold_filename)
         except IOError:
             files_read = False
             self.__messages += 'Unrecognized file type for test image in scipy.imread: ' + gold_filename
             return (False, self.__messages)
         #first check dimensionality
         if gold_image.shape != test_image.shape:
             self.__messages += 'Gold and test image are not the same shape: '+\
               str(gold_image.shape)+', '+str(test_image.shape)
             self.__same = False
             return (self.__same, self.__messages)
         #set default options
         DU.set_default_options(self.__options)
         #pixelwise comparison
         #TODO in the future we can add greyscale, normalized coloring, etc.
         # For now just do raw comparison of right/wrong pixels
         diff = gold_image - test_image
         only_diffs = diff[abs(diff) > self.__options['zero_threshold']]
         pct_num_diff = only_diffs.size / float(diff.size)
         if pct_num_diff > self.__options['rel_err']:
             self.__messages += 'Difference between images is too large:'+\
               ' %2.2f pct (allowable: %2.2f)' %(100*pct_num_diff,
                                                 100*self.__options['rel_err'])
             self.__same = False
     return (self.__same, self.__messages)
Esempio n. 3
0
def compare_unordered_element(a_element, b_element, **kwargs):
    """
    Compares two element trees and returns (same,message)
    where same is true if they are the same,
    and message is a list of the differences.
    Uses list of tree entries to find best match, instead of climbing the tree
    @ In, a_element, ET.Element, the first element
    @ In, b_element, ET.Element, the second element
    @ Out, compare_unordered_element, (bool,[string]), results of comparison
  """
    same = True
    message = []
    options = kwargs
    matchvals = {}
    diffs = {}
    DU.set_default_options(options)

    def fail_message(*args):
        """
      adds the fail message to the list
      @ In, args, list, The arguments to the fail message (will be converted with str())
      @ Out, fail_message, (bool,string), results
    """
        print_args = []
        print_args.extend(args)
        args_expanded = " ".join([str(x) for x in print_args])
        message.append(args_expanded)

    if a_element.text != b_element.text:
        succeeded, note = cswf(
            a_element.text,
            b_element.text,
            rel_err=options["rel_err"],
            zero_threshold=options["zero_threshold"],
            remove_whitespace=options["remove_whitespace"],
            remove_unicode_identifier=options["remove_unicode_identifier"])
        if not succeeded:
            same = False
            fail_message(note)
            return (same, message)
    a_list = tree_to_list(a_element)
    b_list = tree_to_list(b_element)
    #search a for matches in b
    for a_entry in a_list:
        matchvals[a_entry] = {}
        diffs[a_entry] = {}
        for b_entry in b_list:
            same, matchval, diff = compare_list_entry(a_entry, b_entry,
                                                      **options)
            if same:
                b_list.remove(b_entry)
                del matchvals[a_entry]
                del diffs[a_entry]
                #since we found the match, remove from other near matches
                for close_key in diffs:
                    if b_entry in diffs[close_key].keys():
                        del diffs[close_key][b_entry]
                        del matchvals[close_key][b_entry]
                break
            matchvals[a_entry][b_entry] = matchval
            diffs[a_entry][b_entry] = diff
    if len(matchvals) == 0:  #all matches found
        return (True, '')
    note = ''
    for unmatched, close in matchvals.items():
        #print the path without a match
        path = '/'.join(list(m.tag for m in unmatched))
        note += 'No match for gold node {}\n'.format(path)
        note += '               tag: {}\n'.format(unmatched[-1].tag)
        note += '              attr: {}\n'.format(unmatched[-1].attrib)
        note += '              text: {}\n'.format(unmatched[-1].text)
        #print the tree of the nearest match
        note += '  Nearest unused match: '
        close = sorted(list(close.items()), key=lambda x: x[1], reverse=True)
        if close:
            closest = '/'.join(list(c.tag for c in close[0][0]))
        else:
            closest = '-none found-'
        note += '    ' + closest + '\n'
        #print what was different between them
        if len(close):
            diff = diffs[unmatched][close[0][0]]
            for b_diff, code, right, miss in diff:
                if b_diff is None:
                    b_diff = str(b_diff)
                if code is None:
                    code = str(code)
                if right is None:
                    right = str(right)
                if miss is None:
                    miss = str(miss)
                if code == XMLDiff.missingChildNode:
                    note += '    <' + b_diff.tag + '> is missing child node: <' + right + '> vs <' + miss + '>\n'
                elif code == XMLDiff.missingAttribute:
                    note += '    <' + b_diff.tag + '> is missing attribute: "' + right + '"\n'
                elif code == XMLDiff.extraChildNode:
                    note += '    <' + b_diff.tag + '> has extra child node: <' + right + '>\n'
                elif code == XMLDiff.extraAttribute:
                    note += '    <'+b_diff.tag+'> has extra attribute: "'+right+\
                      '" = "'+b_diff.attrib[right]+'"\n'
                elif code == XMLDiff.notMatchTag:
                    note += '    <' + b_diff.tag + '> tag does not match: <' + right + '> vs <' + miss + '>\n'
                elif code == XMLDiff.notMatchAttribute:
                    note += '    <'+b_diff.tag+'> attribute does not match: "'+right[1]+\
                      '" = "'+right[0].attrib[right[1]]+'" vs "'+miss[0].attrib[miss[1]]+'"\n'
                elif code == XMLDiff.notMatchText:
                    note += '    <' + b_diff.tag + '> text does not match: "' + right + '" vs "' + miss + '"\n'
                else:
                    note += '     UNRECOGNIZED OPTION: "'+b_diff.tag+'" "'+str(code)+\
                      '": "'+str(right)+'" vs "'+str(miss)+'"\n'

    return (False, [note])
Esempio n. 4
0
def compare_list_entry(a_list, b_list, **kwargs):
    """
    Comparse flattened XML entries for equality
    return bool is True if all tag, text, and attributes match, False otherwise
    return qual is percent of matching terms
    @ In, a_list, list(ET.Element), first set
    @ In, b_list, list(ET.Element), second set
    @ Out, compare_list_entry, (bool,val), results
  """
    num_match = 0  #number of matching points between entries
    total_matchable = 0  #total tag, text, and attributes available to match
    match = True  #True if entries match
    diff = [
    ]  #tuple of (element, diff code, correct (a) value, test (b) value)
    options = kwargs
    for i in range(len(a_list)):
        if i > len(b_list) - 1:
            match = False
            diff.append(
                (b_list[-1], XMLDiff.missingChildNode, a_list[i].tag, None))
            #could have matched the tag and attributes
            total_matchable += 1 + len(a_list[i].attrib.keys())
            #if text isn't empty, could have matched text, too
            if a_list[i].text is not None and len(a_list[i].text.strip()) > 0:
                total_matchable += 1
            continue
        a_item = a_list[i]
        b_item = b_list[i]
        #match tag
        same, _ = DU.compare_strings_with_floats(
            a_item.tag, b_item.tag, options["rel_err"],
            options["zero_threshold"], options["remove_whitespace"],
            options["remove_unicode_identifier"])
        total_matchable += 1
        if not same:
            match = False
            diff.append((b_item, XMLDiff.notMatchTag, a_item.tag, b_item.tag))
        else:
            num_match += 1
        #match text
        #if (a_item.text is None or len(a_item.text)>0) and (b_item.text is None or len(b_item.text)>0):
        same, _ = DU.compare_strings_with_floats(
            a_item.text, b_item.text, options["rel_err"],
            options["zero_threshold"], options["remove_whitespace"],
            options["remove_unicode_identifier"])
        if not same:
            match = False
            diff.append((b_item, XMLDiff.notMatchText, str(a_item.text),
                         str(b_item.text)))
            total_matchable += 1
        else:
            if not (a_item.text is None or a_item.text.strip() != ''):
                num_match += 1
                total_matchable += 1
        #match attributes
        for attrib in a_item.attrib.keys():
            total_matchable += 1
            if attrib not in b_item.attrib.keys():
                match = False
                diff.append((b_item, XMLDiff.missingAttribute, attrib, None))
                continue
            same, _ = DU.compare_strings_with_floats(
                a_item.attrib[attrib], b_item.attrib[attrib],
                options["rel_err"], options["zero_threshold"],
                options["remove_whitespace"],
                options["remove_unicode_identifier"])
            if not same:
                match = False
                diff.append((b_item, XMLDiff.notMatchAttribute,
                             (a_item, attrib), (b_item, attrib)))
            else:
                num_match += 1
        #note attributes in b_item not in a_item
        for attrib in b_item.attrib.keys():
            if attrib not in a_item.attrib.keys():
                match = False
                diff.append((b_item, XMLDiff.extraAttribute, attrib, None))
                total_matchable += 1
    # note elements in b not in a
    if len(b_list) > len(a_list):
        match = False
        i = len(a_list) - 1
        for j in range(i, len(b_list)):
            diff.append(
                (a_list[-1], XMLDiff.extraChildNode, b_list[j].tag, None))
            #count tag and attributes
            total_matchable += 1 + len(b_list[j].attrib.keys())
            #if text isn't empty, count text, too
            if b_list[i].text is not None and len(b_list[i].text.strip()) > 0:
                total_matchable += 1
    return (match, float(num_match) / float(total_matchable), diff)