Returns a human-readable diff between two values

    :param value_a: First value to compare
    :param value_b: Second value to compare
    :param raw: True to compare the raw values, e.g. UIDs
    :returns a list of diff tuples
175492
def diff_values(value_a, value_b, raw=False):
    

    if not raw:
        value_a = _process_value(value_a)
        value_b = _process_value(value_b)

    # No changes
    if value_a == value_b:
        return None

    diffs = []
    # N.B.: the choice for the tuple data structure is to enable in the future
    # more granular diffs, e.g. the changed values within a dictionary etc.
    diffs.append((value_a, value_b))
    return diffs
198054
def diff(self, report_a, report_b):
        
        arguments = GLOBAL_ARGUMENTS + ['run_date']

        output = OrderedDict([
            ('a', OrderedDict([(arg, report_a[arg]) for arg in arguments])),
            ('b', OrderedDict([(arg, report_b[arg]) for arg in arguments])),
            ('queries', [])
        ])

        output['a']

        for query_a in report_a['queries']:
            for query_b in report_b['queries']:
                if query_a['config'] == query_b['config']:
                    diff = OrderedDict()

                    diff['config'] = query_a['config']
                    diff['data_types'] = query_a['data_types']
                    diff['data'] = OrderedDict()

                    for metric, values in query_a['data'].items():
                        data_type = diff['data_types'][metric]
                        diff['data'][metric] = OrderedDict()

                        total_a = values['total']
                        total_b = query_b['data'][metric]['total']

                        for label, value in values.items():
                            a = value
                            
                            try:
                                b = query_b['data'][metric][label]
                            # TODO: hack for when labels are different...
                            except KeyError:
                                continue

                            change = b - a
                            percent_change = float(change) / a if a > 0 else None
                            
                            percent_a = float(a) / total_a if total_a > 0 else None
                            percent_b = float(b) / total_b if total_b > 0 else None

                            if label == 'total' or data_type == 'TIME' or percent_a is None or percent_b is None:
                                point_change = None
                            else:
                                point_change = percent_b - percent_a

                            diff['data'][metric][label] = OrderedDict([
                                ('change', change),
                                ('percent_change', percent_change),
                                ('point_change', point_change),
                            ])

                    output['queries'].append(diff)

            query_b = report_b['queries']

        return output
737109
def get_comparable_values(self):
        
        return (int(self.major), int(self.minor), str(self.label), str(self.name))
549601
def find_differences(self, refindex: int):
        
        differences = defaultdict(set)

        if refindex >= len(self.protocol.messages):
            return differences

        if self.proto_view == 0:
            proto = self.protocol.decoded_proto_bits_str
        elif self.proto_view == 1:
            proto = self.protocol.decoded_hex_str
        elif self.proto_view == 2:
            proto = self.protocol.decoded_ascii_str
        else:
            return differences

        ref_message = proto[refindex]
        ref_offset = self.get_alignment_offset_at(refindex)

        for i, message in enumerate(proto):
            if i == refindex:
                continue

            msg_offset = self.get_alignment_offset_at(i)
            short, long = sorted([len(ref_message) + ref_offset, len(message) + msg_offset])

            differences[i] = {
                j for j in range(max(msg_offset, ref_offset), long)
                if j >= short or message[j - msg_offset] != ref_message[j - ref_offset]
            }

        return differences
1074754
def difference(self, *iterables):
        
        diff = self._set.difference(*iterables)
        return self._fromset(diff, key=self._key)
996672
def two_way_difference(self, b, extra_add = (), extra_remove = ()):
        
        if self is b:
            return ((), ())
        if isinstance(b, DiffRef_):
            extra_remove = extra_remove + b.add
            b = b.origin
        if extra_add == extra_remove:
            extra_add = extra_remove = ()
        if isinstance(b, Diff_):
            if self.base is b.base:
                first = self.add + b.remove
                second = self.remove + b.add
            elif self.base is b:
                first = self.add
                second = self.remove
            elif b.base is self:
                first = b.remove
                second = b.add
            else:
                first = self
                second = b
        else:
            first = self
            second = b
        if not first and not extra_add:
            return ((), tuple(second) + tuple(extra_remove))
        elif not second and not extra_remove:
            return (tuple(first) + tuple(extra_add), ())
        else:
            first = set(first)
            first.update(extra_add)
            second = set(second)
            second.update(extra_remove)
            return tuple(first.difference(second)), tuple(second.difference(first))
411538
def diff(self, first_row: List[Row], second_row: List[Row], column: NumberColumn) -> Number:
        
        if not first_row or not second_row:
            return 0.0  # type: ignore
        first_value = first_row[0].values[column.name]
        second_value = second_row[0].values[column.name]
        if isinstance(first_value, float) and isinstance(second_value, float):
            return first_value - second_value  # type: ignore
        else:
            raise ExecutionError(f"Invalid column for diff: {column.name}")
174197
def diff(a, b):
        
        delta = diff(a, b)
        if not a:
            return delta
        for item in delta:
            if isinstance(a[item], list):
                if delta[item] == []:
                    delta[item] = {JSONUtils.DIFF_DELETE : a[item]}
                elif isinstance(delta[item], dict):
                    for key in delta[item].keys():
                        if str(key) == JSONUtils.DIFF_DELETE:
                            delta_upd = {JSONUtils.DIFF_DELETE : []}
                            for i in delta[item][key]:
                                delta_upd[JSONUtils.DIFF_DELETE].append(a[item][i])
                                delta[item] = delta_upd
        return delta
684620
def get_function_diff(self, function_addr_a, function_addr_b):
        
        pair = (function_addr_a, function_addr_b)
        if pair not in self._function_diffs:
            function_a = self.cfg_a.kb.functions.function(function_addr_a)
            function_b = self.cfg_b.kb.functions.function(function_addr_b)
            self._function_diffs[pair] = FunctionDiff(function_a, function_b, self)
        return self._function_diffs[pair]
232435
def _get_val2_dict_from_diff_dict(diff_dict):
    '''
    
    '''
    ret_dict = {}
    for p in diff_dict.keys():
        if not isinstance(diff_dict[p], dict):
            raise ValueError('Unexpected diff difct \'{0}\''.format(diff_dict))
        if 'val2' in diff_dict[p].keys():
            ret_dict.update({p: diff_dict[p]['val2']})
        else:
            ret_dict.update(
                {p: _get_val2_dict_from_diff_dict(diff_dict[p])})
    return ret_dict
591209
def difference(self, other):
        

        obj = self._clone()
        obj.difference_update(other)
        return obj
1005525
def diff(cls, a, b, ignore_formatting=False):
        """"""
        def underline(x): return u'\x1b[4m%s\x1b[0m' % (x,)
        def blink(x): return u'\x1b[5m%s\x1b[0m' % (x,)
        a_rows = []
        b_rows = []
        max_width = max([len(row) for row in a] + [len(row) for row in b])
        a_lengths = []
        b_lengths = []
        for a_row, b_row in zip(a, b):
            a_lengths.append(len(a_row))
            b_lengths.append(len(b_row))
            extra_a = u'`' * (max_width - len(a_row))
            extra_b = u'`' * (max_width - len(b_row))
            a_line = u''
            b_line = u''
            for a_char, b_char in zip(a_row + extra_a, b_row + extra_b):
                if ignore_formatting:
                    a_char_for_eval = a_char.s if isinstance(a_char, FmtStr) else a_char
                    b_char_for_eval = b_char.s if isinstance(b_char, FmtStr) else b_char
                else:
                    a_char_for_eval = a_char
                    b_char_for_eval = b_char
                if a_char_for_eval == b_char_for_eval:
                    a_line += actualize(a_char)
                    b_line += actualize(b_char)
                else:
                    a_line += underline(blink(actualize(a_char)))
                    b_line += underline(blink(actualize(b_char)))
            a_rows.append(a_line)
            b_rows.append(b_line)
        hdiff = '\n'.join(a_line + u' %3d | %3d ' % (a_len, b_len) + b_line for a_line, b_line, a_len, b_len in zip(a_rows, b_rows, a_lengths, b_lengths))
        return hdiff
329626
def get_diff(a, b, *args, **kwargs):
    '''
    
    '''
    encoding = ('utf-8', 'latin-1', __salt_system_encoding__)
    # Late import to avoid circular import
    import salt.utils.data
    return ''.join(
        difflib.unified_diff(
            salt.utils.data.decode_list(a, encoding=encoding),
            salt.utils.data.decode_list(b, encoding=encoding),
            *args, **kwargs
        )
    )
156803
def compare_safe(cls, value):
        """"""

        # Date
        if type(value) == date:
            return str(value)

        # Lists
        elif isinstance(value, (list, tuple)):
            return [cls.compare_safe(v) for v in value]

        # Dictionaries
        elif isinstance(value, dict):
            return {k: cls.compare_safe(v) for k, v in value.items()}

        return value
623151
def compare_version(a, b):  # Ignore PyDocStyleBear
    

    def _range(q):
        """Convert a version string to array of integers.

        "1.2.3" -> [1, 2, 3]

        :param q: str
        :return: List[int]
        """
        r = []
        for n in q.replace("-", ".").split("."):
            try:
                r.append(int(n))
            except ValueError:
                # sort rc*, alpha, beta etc. lower than their non-annotated counterparts
                r.append(-1)
        return r

    def _append_zeros(x, num_zeros):
        """Append `num_zeros` zeros to a copy of `x` and return it.

        :param x: List[int]
        :param num_zeros: int
        :return: List[int]
        """
        nx = list(x)
        for _ in range(num_zeros):
            nx.append(0)
        return nx

    def _cardinal(x, y):
        """Make both input lists be of same cardinality.

        :param x: List[int]
        :param y: List[int]
        :return: List[int]
        """
        lx, ly = len(x), len(y)
        if lx == ly:
            return x, y
        elif lx > ly:
            return x, _append_zeros(y, lx - ly)
        else:
            return _append_zeros(x, ly - lx), y

    left, right = _cardinal(_range(a), _range(b))

    return (left > right) - (left < right)
779971
def diff_texts(a, b, filename):
    """"""
    a = a.splitlines()
    b = b.splitlines()
    return difflib.unified_diff(a, b, filename, filename,
                                "(original)", "(refactored)",
                                lineterm="")
1268703
def compare_dict_iter(propval_a, propval_b, fs_a=None, fs_b=None,
                      options=None):
    
    if fs_a is None:
        fs_a = FieldSelector(tuple())
        fs_b = FieldSelector(tuple())
    if not options:
        options = DiffOptions()
    propvals = dict(a=propval_a, b=propval_b)
    values = dict()
    rev_keys = dict()
    for x in "a", "b":
        propval_x = propvals[x]
        vals = values[x] = set()
        rev_key = rev_keys[x] = dict()
        seen = collections.Counter()
        for k, v in collection_generator(propval_x):
            v = options.normalize_item(
                v, propval_a if options.duck_type else propval_x
            )
            if not v.__hash__:
                v = repr(v)
            if v is not _nothing or not options.ignore_empty_slots:
                vals.add((v, seen[v]))
                rev_key[(v, seen[v])] = k
                seen[v] += 1

    removed = values['a'] - values['b']
    added = values['b'] - values['a']

    if options.moved or options.unchanged:
        unchanged = values['a'] & values['b']
        for v, seq in unchanged:
            a_key = rev_keys['a'][v, seq]
            b_key = rev_keys['b'][v, seq]
            if options.moved and a_key != b_key:
                yield DiffInfo(
                    diff_type=DiffTypes.MOVED,
                    base=fs_a + [a_key],
                    other=fs_b + [b_key],
                )
            elif options.unchanged:
                yield DiffInfo(
                    diff_type=DiffTypes.NO_CHANGE,
                    base=fs_a + [a_key],
                    other=fs_b + [b_key],
                )

    removed_keys = set(rev_keys['a'][v, seq] for v, seq in removed)
    added_keys = set(rev_keys['b'][v, seq] for v, seq in added)
    modified_keys = set(removed_keys.intersection(added_keys))

    for v, seq in removed:
        a_key = rev_keys['a'][v, seq]
        if a_key in modified_keys:
            continue
        selector = fs_a + [a_key]
        yield DiffInfo(
            diff_type=DiffTypes.REMOVED,
            base=selector,
            other=fs_b,
        )

    for v, seq in added:
        b_key = rev_keys['b'][v, seq]
        if b_key in modified_keys:
            continue
        selector = fs_b + [b_key]
        yield DiffInfo(
            diff_type=DiffTypes.ADDED,
            base=fs_a,
            other=selector,
        )

    for key in modified_keys:
        yield DiffInfo(
            diff_type=DiffTypes.MODIFIED,
            base=fs_a + [key],
            other=fs_b + [key],
        )