def add_diff(self, original, new):
changes = {}<EOL>for new_key, new_value in new.items():<EOL><INDENT>if new_key not in original:<EOL><INDENT>if '<STR_LIT>' not in changes:<EOL><INDENT>changes['<STR_LIT>'] = {}<EOL><DEDENT>new_value = self.diff_safe(new_value)<EOL>changes['<STR_LIT>'][new_key] = new_value<EOL><DEDENT>elif original[new_key] != new_value:<EOL><INDENT>if '<STR_LIT>' not in changes:<EOL><INDENT>changes['<STR_LIT>'] = {}<EOL><DEDENT>original_value = self.diff_safe(original[new_key])<EOL>new_value = self.diff_safe(new_value)<EOL>changes['<STR_LIT>'][new_key] = [original_value, new_value]<EOL>if '<STR_LIT:password>' in new_key:<EOL><INDENT>changes['<STR_LIT>'][new_key] = ['<STR_LIT>', '<STR_LIT>']<EOL><DEDENT><DEDENT><DEDENT>for original_key, original_value in original.items():<EOL><INDENT>if original_key not in new:<EOL><INDENT>if '<STR_LIT>' not in changes:<EOL><INDENT>changes['<STR_LIT>'] = {}<EOL><DEDENT>original_value = self.diff_safe(original_value)<EOL>changes['<STR_LIT>'][original_key] = original_value<EOL><DEDENT><DEDENT>self.details = changes<EOL>
Set the details of the change log entry as the difference between two
dictionaries (original vs. new). The change log uses the following
format:

{
    'additions': {
        'field_name': 'value',
        ...
    },
    'updates': {
       'field_name': ['original_value', 'new_value'],
        ...
    },
    'deletions': {
        'field_name': ['original_value']
    }
}

Values are tested for equality, there is special case handling for
`Frame` class instances (see `diff_safe`) and fields with the word
password in their name are redacted.

Note: Where possible use diff structures that are flat, performing a
diff on a dictionary which contains sub-dictionaries is not recommended
as the verbose output (see `diff_to_html`) is optimized for flat
structures.