129 lines
3.7 KiB
Python
129 lines
3.7 KiB
Python
|
#!/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)
|