#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
@author: Pierre Thibault (pierre.thibault1 -at- gmail.com)
@license: MIT
@since: 2011-06-17
Usage: dict_diff [OPTION]... dict1 dict2
Show the differences for two dictionaries.
-h, --help Display this help message.
dict1 and dict2 are two web2py dictionary files to compare. These are the files
located in the "languages" directory of a web2py app. The tools show the
differences between the two files.
'''
__docformat__ = "epytext en"
import getopt
import os.path
import sys
def main(argv):
"""Parse the arguments and start the main process."""
try:
opts, args = getopt.getopt(argv, "h", ["help"])
except getopt.GetoptError:
exit_with_parsing_error()
for opt, arg in opts:
arg = arg # To avoid a warning from Pydev
if opt in ("-h", "--help"):
usage()
sys.exit()
if len(args) == 2:
params = list(get_dicts(*args))
params.extend(get_dict_names(*args))
compare_dicts(*params)
else:
exit_with_parsing_error()
def exit_with_parsing_error():
"""Report invalid arguments and usage."""
print("Invalid argument(s).")
usage()
sys.exit(2)
def usage():
"""Display the documentation"""
print(__doc__)
def get_dicts(dict_path1, dict_path2):
"""
Parse the dictionaries.
@param dict_path1: The path to the first dictionary.
@param dict_path2: The path to the second dictionary.
@return: The two dictionaries as a sequence.
"""
return eval(open(dict_path1).read()), eval(open(dict_path2).read())
def get_dict_names(dict1_path, dict2_path):
"""
Get the name of the dictionaries for the end user. Use the base name of the
files. If the two base names are identical, returns "dict1" and "dict2."
@param dict1_path: The path to the first dictionary.
@param dict2_path: The path to the second dictionary.
@return: The two dictionary names as a sequence.
"""
dict1_name = os.path.basename(dict1_path)
dict2_name = os.path.basename(dict2_path)
if dict1_name == dict2_name:
dict1_name = "dict1"
dict2_name = "dict2"
return dict1_name, dict2_name
def compare_dicts(dict1, dict2, dict1_name, dict2_name):
"""
Compare the two dictionaries. Print out the result.
@param dict1: The first dictionary.
@param dict1: The second dictionary.
@param dict1_name: The name of the first dictionary.
@param dict2_name: The name of the second dictionary.
"""
dict1_keyset = set(dict1.keys())
dict2_keyset = set(dict2.keys())
print_key_diff(dict1_keyset - dict2_keyset, dict1_name, dict2_name)
print_key_diff(dict2_keyset - dict1_keyset, dict2_name, dict1_name)
print "Value differences:"
has_value_differences = False
for key in dict1_keyset & dict2_keyset:
if dict1[key] != dict2[key]:
print " %s:" % (key,)
print " %s: %s" % (dict1_name, dict1[key],)
print " %s: %s" % (dict2_name, dict2[key],)
print
has_value_differences = True
if not has_value_differences:
print " None"
def print_key_diff(key_diff, dict1_name, dict2_name):
"""
Prints the keys in the first dictionary and are in the second dictionary.
@param key_diff: Keys in dictionary 1 not in dictionary 2.
@param dict1_name: Name used for the first dictionary.
@param dict2_name: Name used for the second dictionary.
"""
print "Keys in %s not in %s:" % (dict1_name, dict2_name)
if len(key_diff):
for key in key_diff:
print " %s" % (key,)
else:
print " None"
print
if __name__ == "__main__":
main(sys.argv[1:]) # Start the process (without the application name)