def __init__(self,
                 old_obj, new_obj,
                 previous_path=(), previous_new_path=(),
                 patch_extractors=[],
                 key_limits=KeyLimit(),
                 find_moved_patches=False,
                 moved_patches_similarity=0.8):

        super(DictPatchExtractor, self).__init__(old_obj, new_obj,
                                                 previous_path,
                                                 previous_new_path,
                                                 patch_extractors,
                                                 key_limits,
                                                 moved_patches_similarity)

        dict_diff = DictDiffer(new_obj, old_obj)

        for addition_key in dict_diff.added():
            if not self._try_patch_extractors_for_ungrouping(addition_key):
                self._add_patch('add', addition_key, None, new_obj[addition_key])

        for removal_key in dict_diff.removed():
            self._add_patch('remove', removal_key, old_obj[removal_key], None)

        for change_key in dict_diff.changed():
            if not self._try_patch_extractors(change_key, change_key):
                self._add_patch('change', change_key,
                                old_obj[change_key], new_obj[change_key])

        if find_moved_patches:
            self.patches = self._find_moved_parts()
    def __init__(self,
                 old_obj,
                 new_obj,
                 previous_path=(),
                 previous_new_path=(),
                 patch_extractors=[],
                 key_limits=KeyLimit(),
                 find_moved_patches=False,
                 moved_patches_similarity=0.8):

        super(DictPatchExtractor,
              self).__init__(old_obj, new_obj, previous_path,
                             previous_new_path, patch_extractors, key_limits,
                             moved_patches_similarity)

        dict_diff = DictDiffer(new_obj, old_obj)

        for addition_key in dict_diff.added():
            if not self._try_patch_extractors_for_ungrouping(addition_key):
                self._add_patch('add', addition_key, None,
                                new_obj[addition_key])

        for removal_key in dict_diff.removed():
            self._add_patch('remove', removal_key, old_obj[removal_key], None)

        for change_key in dict_diff.changed():
            if not self._try_patch_extractors(change_key, change_key):
                self._add_patch('change', change_key, old_obj[change_key],
                                new_obj[change_key])

        if find_moved_patches:
            self.patches = self._find_moved_parts()
Example #3
0
def compare_sets(file_list):
    comparison_list = comparison_tuples(file_list)
    for tuple in comparison_list:
        print tuple
        past_xml, current_xml = open_xml(tuple)
        past_dict = json.loads(xml2json(past_xml, 0, 1))
        current_dict = json.loads(xml2json(current_xml, 0, 1))
        differ = DictDiffer(current_dict['Ableton']['LiveSet']['Tracks'], past_dict['Ableton']['LiveSet']['Tracks'])
        print "ADDED"
        print json.dumps(differ.added(), indent=4)
        print "REMOVED"
        print json.dumps(differ.removed(), indent=4)
        print "CHANGED"
        print json.dumps(differ.changed(), indent=4)
class TestDictDiffer(TestCase):
    def setUp(self):
        a = {'a': 1, 'b': 1, 'c': 0}
        b = {'a': 1, 'b': 2, 'd': 0}
        self.d = DictDiffer(b, a)

    def test_added(self):
        self.assertEqual(self.d.added(), set(['d']))

    def test_removed(self):
        self.assertEqual(self.d.removed(), set(['c']))

    def test_changed(self):
        self.assertEqual(self.d.changed(), set(['b']))

    def test_unchanged(self):
        self.assertEqual(self.d.unchanged(), set(['a']))
Example #5
0
    def onSaveButtonClicked(self):
        # Set up some variables.
        rowcount = self.ui.evTableWidget.rowCount()
        evdict = {}
        winEnv = windowsev.Win32Environment('system')

        # Grab all of the values from the tablewidget and save them.
        for i in range(0, rowcount):
            evKey = self.ui.evTableWidget.item(i, 0).text()
            evValue = self.ui.evTableWidget.item(i, 1).text()
            # Save in the dictionary.
            evdict[evKey] = evValue

        self.newenvs = evdict
        differ = DictDiffer(self.newenvs, self.oldenvs)
        changed = differ.changed()

        for k in changed:
            print('Key: ' + k + '  ->  Value: ' + self.newenvs[k])
def print_report (docs):
    if not docs or len(docs) < 2: return 0

    name = ''
    for doc in docs:
        if 'name' in doc:
            name = doc['name'].encode('utf-8')
            break
    output = ['<h2>Differences for declaration %s, %s</h2>' % (docs[0]['decl_id'], name)]

    past, current = get_pastcurrent(docs)

    differ = DictDiffer(current, past)
    output += report_changed(current, past, differ.changed())
    output += report_added(current, differ.added())
    output += report_removed(past, differ.removed())
    output.append('<hr />')

    print "\n".join(output)
    return 1
def print_report(docs):
    if not docs or len(docs) < 2: return 0

    name = ''
    for doc in docs:
        if 'name' in doc:
            name = doc['name'].encode('utf-8')
            break
    output = [
        '<h2>Differences for declaration %s, %s</h2>' %
        (docs[0]['decl_id'], name)
    ]

    past, current = get_pastcurrent(docs)

    differ = DictDiffer(current, past)
    output += report_changed(current, past, differ.changed())
    output += report_added(current, differ.added())
    output += report_removed(past, differ.removed())
    output.append('<hr />')

    print "\n".join(output)
    return 1
Example #8
0
    def checkDelta(self, letter):
        if letter == 'A':
            delta = self.deltaA
            # Refer to the opposite MHL to access and perform searches on it
            oppositeMHL = self.B

            listLetter = 'A'
            listLabel = '1st'
            listLabelOpposite = '2nd'
            listColor = LOG_COLOR_MHL_A
            listColorOpposite = LOG_COLOR_MHL_B
        elif letter == 'B':
            delta = self.deltaB
            oppositeMHL = self.A

            listLetter = 'B'
            listLabel = '2nd'
            listLabelOpposite = '1st'
            listColor = LOG_COLOR_MHL_B
            listColorOpposite = LOG_COLOR_MHL_A
        else:
            raise Exception(
                "INTERNAL: Couldn't check deltas, none were specified. Specify one"
            )
            return

        # Quickly clean Nonexistent objects out if they exist
        deltaClean = [h for h in delta if not isinstance(h, HashNonexistent)]
        deltaClean.sort()

        for hash in deltaClean:

            # Debug
            # print(color('DEBUG >>>', 'yellow'), hash.identifier, color(hash.filename, 'green'))
            # print('rh', hash.recordedHashes)

            foundHashPossible = None
            beenCounted = False  # If this hash has been counted yet

            # Look for a match by other hash
            # E.g., if XXHASH and MD5 present, search by MD5
            for otherHashType, otherHashValue in hash.recordedHashes.items():
                if otherHashType == hash.identifierType:
                    pass  # Skip the hash type we are already using

                hashPossible = oppositeMHL.findByOtherHash(
                    otherHashType, otherHashValue)
                if isinstance(hashPossible, HashNonexistent):
                    # No result found, move on
                    foundHashPossible = False
                    pass
                else:
                    # Found it
                    # And because we found it by another hash...
                    # Let's update the IDENTIFIER. Risky?
                    hash.identifier = otherHashValue
                    hash.identifierType = otherHashType
                    hashPossible.identifier = otherHashValue
                    hashPossible.identifierType = otherHashType
                    foundHashPossible = True
                    break

            if foundHashPossible is False:
                # Searched but no matches by other hash.
                # Look for a match by filename
                hashPossible = oppositeMHL.findHashByAttribute(
                    'filename', hash.filename)

                if isinstance(hashPossible, HashNonexistent):
                    # Definitely missing. No other matches by name or hash.
                    foundHashPossible = False
                else:
                    foundHashPossible = True

            if foundHashPossible is True:
                # Compare the hash and the possible hash.
                diff = DictDiffer(hash.__dict__, hashPossible.__dict__)
                dAdded = diff.added()
                dRemoved = diff.removed()
                dUnchanged = diff.unchanged()
                dChanged = diff.changed()

                # First print a filename so everything fits underneath it.
                logDetail('  ' +
                          color(hash.filename, None, attrs=LOG_COLOR_BOLD))

                # Then begin testing.
                if hash.identifierType == hashPossible.identifierType:
                    # Hash type is the same
                    if hash.identifier == hashPossible.identifier:
                        # And so are the hashes

                        # But check if it's a duplicate first
                        if hash.isDuplicate is True:
                            logDetail(
                                '      This file is a duplicate. Another file exists in this MHL with the same hash.'
                            )
                            if not beenCounted:
                                self.COUNT['DUPLICATE'] += 1
                                beenCounted = True
                            logDetail(
                                '      Hash ({}):'.format(listLabel),
                                colored(
                                    hash.identifier +
                                    ' ({})'.format(hash.identifierType),
                                    listColor))
                        else:
                            if not beenCounted:
                                self.COUNT['PERFECT'] += 1
                                beenCounted = True
                            logDetail('      Hash: identical.')
                    else:
                        # But the hashes are different. File has changed?
                        if not beenCounted:
                            self.COUNT['HASH_CHANGED'] += 1
                            beenCounted = True
                        logDetail(
                            color(
                                '      Hash: These hashes are different from each other. It is likely the files were different between the time the MHLs were generated.',
                                LOG_COLOR_WARNING))
                else:
                    # Hash type is not the same. Unlikely to be comparable.
                    if not beenCounted:
                        self.COUNT['HASH_TYPE_DIFFERENT'] += 1
                        beenCounted = True
                    logDetail(
                        color(
                            "      Hash: These hashes are of different types. It's not possible to compare them.",
                            LOG_COLOR_INFORMATION))

                if hash.isDuplicate is False:
                    logDetail(
                        '      Hash ({}):'.format(listLabel),
                        color(
                            '{} ({})'.format(hash.identifier,
                                             hash.identifierType), listColor))
                    logDetail(
                        '      Hash ({}):'.format(listLabelOpposite),
                        color(
                            '{} ({})'.format(hashPossible.identifier,
                                             hashPossible.identifierType),
                            listColorOpposite))

                if {'filename', 'directory', 'size'}.issubset(dUnchanged):
                    # If neither of these variables have changed, then we have a perfect match.
                    # EVEN THOUGH we used a slightly different preferred hash.
                    if not beenCounted:
                        self.COUNT['PERFECT'] += 1
                        beenCounted = True
                    continue
                else:

                    if 'filename' in dChanged:
                        if not beenCounted:
                            self.COUNT['MINOR'] += 1
                            beenCounted = True
                        logDetail('      Filename: different (1st):',
                                  color(hash.filename, LOG_COLOR_MHL_A))
                        logDetail(
                            '                          (2nd):',
                            color(hashPossible.filename, LOG_COLOR_MHL_B))
                    else:
                        # If the filename is the same, it has already been declared closer to the top.
                        pass

                    if 'directory' in dChanged:
                        if not beenCounted:
                            self.COUNT['MINOR'] += 1
                            beenCounted = True
                        logDetail('      Path: different (1st):',
                                  color(hash.directory, LOG_COLOR_MHL_A))
                        logDetail(
                            '                      (2nd):',
                            color(hashPossible.directory, LOG_COLOR_MHL_B))
                    else:
                        logDetail('      Path: identical:', hash.directory)

                    if 'size' in dChanged:
                        # First, check if the Size is simply "Not specified"
                        # This is not an anomaly if so.
                        if hash.sizeDefined == False:
                            # If we have come this far (hash match, name, directory) but size can't be compared
                            # That is as good as we are gonna get.
                            self.COUNT['PERFECT'] += 1
                            beenCounted = True
                        else:
                            # It is an anomaly if the size has changed while the hash has not.
                            # Report it as impossible, but also print it to the user anyway.
                            if not beenCounted:
                                self.COUNT['IMPOSSIBLE'] += 1
                                beenCounted = True
                            logDetail('      Size: different (1st):',
                                      color(hash.sizeHuman, LOG_COLOR_MHL_A))
                            logDetail(
                                '                      (2nd):',
                                color(hashPossible.sizeHuman, LOG_COLOR_MHL_B))
                    else:
                        logDetail('      ' + 'Size: identical: ' +
                                  hashPossible.sizeHuman)

                    if 'lastmodificationdate' in dChanged:
                        if LOG_SHOW_DATES:
                            if not beenCounted:
                                self.COUNT['MINOR'] += 1
                                beenCounted = True

                            hModDate = showDate(hash.lastmodificationdate)
                            hPModDate = showDate(
                                hashPossible.lastmodificationdate)

                            logDetail('      Modified date: different (1st):',
                                      color(hModDate, LOG_COLOR_MHL_A))
                            logDetail('                               (2nd):',
                                      color(hPModDate, LOG_COLOR_MHL_B))
                        else:
                            # Don't count date changes unless user wants it (LOG_SHOW_DATES is true)
                            pass

                    # Briefly explain to the user what attributes were added/removed
                    if LOG_SHOW_DATES == False:
                        dAddedFiltered = [
                            i for i in dAdded
                            if i not in LIST_OF_DATE_ATTRIBUTES
                        ]
                        dRemovedFiltered = [
                            i for i in dRemoved
                            if i not in LIST_OF_DATE_ATTRIBUTES
                        ]
                    else:
                        dAddedFiltered = dAdded
                        dRemovedFiltered = dRemoved

                    if len(dAddedFiltered) > 0:
                        dAddedString = ', '.join(
                            str(i) for i in dAddedFiltered)
                        logDetail('      These attributes exist in 1st only:',
                                  color(dAddedString, LOG_COLOR_MHL_A))
                    if len(dRemovedFiltered) > 0:
                        dRemovedString = ', '.join(
                            str(i) for i in dRemovedFiltered)
                        logDetail('      These attributes exist in 2nd only:',
                                  color(dRemovedString, LOG_COLOR_MHL_B))

                    pass

            else:
                # Else if foundHashPossible was False.
                self.COUNT['MISSING'] += 1
                logDetail(
                    '  ' +
                    color(hash.filename, listColor, attrs=LOG_COLOR_BOLD))
                logDetail('  This file only exists in',
                          color(listLabel + ' MHL', listColor) + '.')
                logDetail('      ' + 'Path:', hash.directory)
                logDetail('      ' + 'Size:', hash.sizeHuman)
                logDetail('      ' + 'Hash:', hash.identifier,
                          '({})'.format(hash.identifierType))
Example #9
0
    def checkCommon(self):

        for hashA, hashB in self.common:
            beenCounted = False

            diff = DictDiffer(hashA.__dict__, hashB.__dict__)
            dAdded = diff.added()
            dRemoved = diff.removed()
            dChanged = diff.changed()
            dUnchanged = diff.unchanged()

            if {'filename', 'directory', 'size'}.issubset(dUnchanged):
                # If neither of these variables have changed, then we have a perfect match.
                # Report it and move on.
                if not beenCounted:
                    self.COUNT['PERFECT'] += 1
                    beenCounted = True
                continue

            if 'filename' in dChanged:
                if not beenCounted:
                    self.COUNT['MINOR'] += 1
                    beenCounted = True
                logDetail('  ' +
                          color(hashA.filename, 'green', attrs=LOG_COLOR_BOLD))
                logDetail('      Filename: different (1st):',
                          color(hashA.filename, LOG_COLOR_MHL_A))
                logDetail('                          (2nd):',
                          color(hashB.filename, LOG_COLOR_MHL_B))
            else:
                logDetail('  ' +
                          color(hashA.filename, None, attrs=LOG_COLOR_BOLD))
            if 'directory' in dChanged:
                if not beenCounted:
                    self.COUNT['MINOR'] += 1
                    beenCounted = True
                logDetail('      Path: different (1st):',
                          color(hashA.directory, LOG_COLOR_MHL_A))
                logDetail('                      (2nd):',
                          color(hashB.directory, LOG_COLOR_MHL_B))
            else:
                logDetail('      Path: identical: ' + hashA.directory)

            # Straight up print the hash, don't check it.
            # At this stage, it's not possible for the hash to be different.
            # A check has already been performed for the pair to even be included in this group.
            logDetail('      Hash: identical: {} ({})'.format(
                hashA.identifier, hashA.identifierType))

            if 'size' in dChanged:
                # First, check if the Size is simply "Not specified"
                if hashA.sizeDefined == False or hashB.sizeDefined == False:
                    self.COUNT['PERFECT'] += 1
                    beenCounted = True

                # It is an anomaly if the size has changed, but not the hash.
                # Report it as impossible, but also print it to the user anyway.
                if not beenCounted:
                    self.COUNT['IMPOSSIBLE'] += 1
                    beenCounted = True
                logDetail('      Size: different (1st):',
                          color(hashA.sizeHuman, LOG_COLOR_MHL_A))
                logDetail('                      (2nd):',
                          color(hashB.sizeHuman, LOG_COLOR_MHL_B))
            else:
                logDetail('      ' + 'Size: identical: ' + hashA.sizeHuman)

            if 'lastmodificationdate' in dChanged:
                if LOG_SHOW_DATES:
                    if not beenCounted:
                        self.COUNT['MINOR'] += 1
                        beenCounted = True
                    logDetail(
                        '      Modified date: different (1st):',
                        color(hashA.lastmodificationdate, LOG_COLOR_MHL_A))
                    logDetail(
                        '                               (2nd):',
                        color(hashB.lastmodificationdate, LOG_COLOR_MHL_B))
                else:
                    # Don't count date changes unless user wants it (LOG_SHOW_DATES is true)
                    pass

            # Briefly explain to the user what attributes were added/removed
            if LOG_SHOW_DATES == False:
                dAddedFiltered = [
                    i for i in dAdded if i not in LIST_OF_DATE_ATTRIBUTES
                ]
                dRemovedFiltered = [
                    i for i in dRemoved if i not in LIST_OF_DATE_ATTRIBUTES
                ]
            else:
                dAddedFiltered = dAdded
                dRemovedFiltered = dRemoved

            if len(dAddedFiltered) > 0:
                dAddedString = ', '.join(str(i) for i in dAddedFiltered)
                logDetail('      These attributes exist in 1st only:',
                          color(dAddedString, LOG_COLOR_MHL_A))
            if len(dRemovedFiltered) > 0:
                dRemovedString = ', '.join(str(i) for i in dRemovedFiltered)
                logDetail('      These attributes exist in 2nd only:',
                          color(dRemovedString, LOG_COLOR_MHL_B))
Example #10
0
class updater():
    def __init__(self, ui):
        super(updater, self).__init__()
        self.pBar1Value = Reference(0)
        self.pBar2Value = Reference(0)
        self.totalDownSize = 0
        self.ui = ui
        self.updaterDir = os.getcwd()
        try:
            self.localHashDict = hashgen.openHashDict(os.path.join(self.updaterDir, 'updater.dat'))
        except IOError as exc:
            # print(exc)
            self.localHashDict = {}

    def login(self, config):
        server = config['FTP_Server']['Server']
        username = config['FTP_Server']['Username']
        password = config['FTP_Server']['Password']
        self.serverpath = config['FTP_Server']['ServerFolder']
        self.download_path = config['DEFAULT']['DownloadPath']

        try:
            self.host = ftputil.FTPHost(server, username, password)
            print("Conection Started")
            self.serverHashDict = hashgen.openHashDict(self.downloadFile(config['FTP_Server']['HashPath'], self.updaterDir))
            self.ui.statusLabel2.setText("")
            self.fileDiffer = DictDiffer(self.serverHashDict, self.localHashDict)
            self.host.chdir(self.serverpath)
        except ftputil.ftp_error.PermanentError:
            print("Error!")
            print("Login authentication failed.")
            self.ui.statusLabel.setText("Error!")
            self.ui.statusLabel2.setText("Login authentication failed.")
            return 0
        except ftputil.ftp_error.FTPOSError as error:
            print("Error!")
            print("No Internet connection.")
            self.ui.statusLabel.setText("Error!")
            self.ui.statusLabel2.setText("No Internet connection.")
            # raise(error)
            return 0

        self.pBar1Value.set(0)
        self.pBar2Value.set(0)

    def close(self):
        try:
            self.host.close()
            print("\nConection Closed")
            return 0
        except:
            pass

    def checkDownloadPath(self, download_path):
        if not os.path.exists(download_path):
            try:
                os.makedirs(download_path)
            except Exception as exc:
                print(exc)

    def downloadEntirePath(self):
        self.totalSize = self.getFullSize()
        try:
            for (ftp_curpath, ftp_dirs, ftp_files) in self.host.walk(self.host.curdir):
                self.downloadFolderFiles(ftp_curpath)
            hashgen.saveHashDict(self.localHashDict, self.updaterDir)
        except Exception as exc:
            raise(exc)

    def checkDiffer(self):
        if len(self.fileDiffer.added()) != 0 or len(self.fileDiffer.changed()) != 0 or len(self.fileDiffer.removed()) != 0 or not os.path.exists(self.download_path):
            return True
        else:
            return False

    def calculateDiffer(self):
        if os.path.exists(os.path.join(self.updaterDir, 'updater.dat')) and os.path.exists(self.download_path):
            self.downloadDiffer(self.fileDiffer.added())
            self.downloadDiffer(self.fileDiffer.changed())
            self.removeDiffer(self.fileDiffer.removed())
            hashgen.saveHashDict(self.localHashDict, self.updaterDir)
        else:
            try:
                try:
                    os.remove(os.path.join(self.updaterDir, 'updater.dat'))
                except:
                    pass
                self.downloadEntirePath()
            except Exception as exc:
                raise(exc)
                os.remove(os.path.join(self.updaterDir, 'updater.dat'))


    def downloadDiffer(self, differ_set):
        for files in differ_set:
            self.downloadFile(files, self.download_path)
            self.localHashDict[files] = self.serverHashDict[files]

    def removeDiffer(self, differ_set):
        for files in differ_set:
            file_path = os.path.join(self.download_path, files)
            os.remove(file_path)
            del self.localHashDict[files]
            print("File", os.path.split(file_path)[1], "removed.")

    def getFullSize(self):
        totalSize = 0
        for (ftp_curpath, ftp_dirs, ftp_files) in self.host.walk(self.host.curdir):
            for files in ftp_files:
                totalSize += self.host.path.getsize(self.host.path.join(ftp_curpath, files))
        return(totalSize)

    def downloadFile(self, ftp_filepath, download_path):
        self.ui.statusText = "Downloading"
        self.dl_file_size = 0
        self.pBar1Value.set(0)
        self.file_size_bytes = self.host.path.getsize(ftp_filepath)
        file_size = self.__size(self.file_size_bytes)
        ftp_path, filename=self.host.path.split(ftp_filepath)
        print("\nDownloading " + filename + " - Size: " + file_size)
        self.ui.statusLabel2.setText(filename + " - Size:" + file_size)
        try:
            self.checkDownloadPath(os.path.join(download_path, ftp_path))
            self.host.download(ftp_filepath, os.path.join(download_path, ftp_filepath), mode='b', callback=self.__downloadBuffer)
            print(end="\n\n")
        except OSError as exc:
            raise(exc)
         
        return os.path.join(download_path, filename)

    def downloadFolderFiles(self, ftp_path=''):
        self.ui.startPBars(self.pBar1Value, self.pBar2Value)

        for filename in self.host.listdir(ftp_path):
            ftp_filepath = self.host.path.join(ftp_path, filename)
            # print(ftp_filepath)

            if self.host.path.isfile(ftp_filepath):
                self.ui.updateStatus = True
                self.ui.statusText = "Checking files"
                self.ui.statusLabel2.setText("Checking " + filename)
                print("Checking", filename)
                try:
                    localFileHash = hashgen.getFileHash(os.path.join(self.download_path, ftp_filepath))
                except Exception as exc:
                    localFileHash = None

                if self.serverHashDict[ftp_filepath] != localFileHash:
                    self.downloadFile(ftp_filepath, self.download_path)
                else:
                    self.totalDownSize += self.host.path.getsize(ftp_filepath)
                    self.pBar2Value.set(int(self.totalDownSize * 100 / self.totalSize))

                self.localHashDict[ftp_filepath] = self.serverHashDict[ftp_filepath]
                    
        self.ui.stopPBars()

    def __downloadBuffer(self, buffer):
        buffer_len = len(buffer)
        self.dl_file_size += buffer_len
        self.totalDownSize += buffer_len
        p = int(self.dl_file_size * 100 / self.file_size_bytes)
        try:
            r = int(self.totalDownSize * 100 / self.totalSize)
        except:
            r = int(self.totalDownSize * 100 / self.file_size_bytes)
        print("Status: ", p, "%", end="\r")
        self.pBar1Value.set(p)
        self.pBar2Value.set(r)        

    def __size(self, size):
        if size < 1024:
            file_size = str("{0:.2f}".format(size)) + " Bytes"
        elif size/1024 < 1024:
            file_size = str("{0:.2f}".format(size/1024)) + " KB"
        elif size/1024**2 < 1024:
            file_size = str("{0:.2f}".format(size/1024**2)) + " MB"
        elif size/1024**3 < 1024:
            file_size = str("{0:.2f}".format(size/1024**3)) + " GB"

        return file_size
Example #11
0
class TestDictDiffer(TestCase):
    def setUp(self):
        a = {'a': 1, 'b': 1, 'c': 0}
        b = {'a': 1, 'b': 2, 'd': 0}
        self.d = DictDiffer(b, a)

    def test_added(self):
        self.assertEqual(self.d.added(), set(['d']))

    def test_removed(self):
        self.assertEqual(self.d.removed(), set(['c']))

    def test_changed(self):
        self.assertEqual(self.d.changed(), set(['b']))

    def test_unchanged(self):
        self.assertEqual(self.d.unchanged(), set(['a']))

    def test_changes(self):
        self.assertEqual(self.d.changes(), {'added': 1,
                                            'removed': 1,
                                            'changed': 1})

    def test_changes_same(self):
        """Dict are same
        """
        a = {'a': 1, 'b': 1, 'c': 0}
        b = {'a': 1, 'b': 1, 'c': 0}
        tdf = DictDiffer(b, a)

        self.assertEqual(tdf.changes(), {'added': 0,
                                         'removed': 0,
                                         'changed': 0})

    def test_haschanges(self):
        self.assertEqual(self.d.has_changes(), True)

    def test_haschanges_no(self):
        """Dict are the same
        """
        a = {'a': 1, 'b': 1, 'c': 0}
        b = {'a': 1, 'b': 1, 'c': 0}
        tdf = DictDiffer(b, a)

        self.assertEqual(tdf.has_changes(), False)

    def test_haschanges_empty(self):
        """Dict are empty
        """
        tdf = DictDiffer({}, {})
        self.assertFalse(tdf.has_changes())

    def test_nb_changes(self):
        """Number of changes
        """
        a = {'a': 1, 'b': 1, 'c': 0}
        b = {'a': 1, 'b': 2}
        tdf = DictDiffer(b, a)

        self.assertEqual(tdf.nb_changes(), 2)

    def test_nb_changes_same(self):
        """Number of changes
        """
        a = {'a': 1, 'b': 1}
        b = {'a': 1, 'b': 1}
        tdf = DictDiffer(b, a)

        self.assertEqual(tdf.nb_changes(), 0)

    def test_nb_changes_full(self):
        """Number of changes
        """
        a = {'a': 1, 'b': 1}
        b = {'d': 1, 'f': 1}
        tdf = DictDiffer(b, a)

        self.assertEqual(tdf.nb_changes(), 4)

    def test_fulldiff(self):
        """
        """
        a = {'a': 1, 'b': 1, 'c': 4}
        b = {'d': 1, 'f': 1, 'c': 5}
        tdf = DictDiffer(b, a)

        diff = tdf.fulldiff()
        result = {'added': [{'d': 1}, {'f': 1}],
                  'changed': [{'key': 'c', 'old': 4, 'new': 5}],
                  'removed': [{'a': 1}, {'b': 1}]}

        self.assertEqual(diff, result)