text: #!/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)
  