Beispiel #1
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])
Beispiel #2
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)
Beispiel #3
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)