symbian-qemu-0.9.1-12/python-2.6.1/Tools/scripts/pdeps.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 #! /usr/bin/env python
       
     2 
       
     3 # pdeps
       
     4 #
       
     5 # Find dependencies between a bunch of Python modules.
       
     6 #
       
     7 # Usage:
       
     8 #       pdeps file1.py file2.py ...
       
     9 #
       
    10 # Output:
       
    11 # Four tables separated by lines like '--- Closure ---':
       
    12 # 1) Direct dependencies, listing which module imports which other modules
       
    13 # 2) The inverse of (1)
       
    14 # 3) Indirect dependencies, or the closure of the above
       
    15 # 4) The inverse of (3)
       
    16 #
       
    17 # To do:
       
    18 # - command line options to select output type
       
    19 # - option to automatically scan the Python library for referenced modules
       
    20 # - option to limit output to particular modules
       
    21 
       
    22 
       
    23 import sys
       
    24 import re
       
    25 import os
       
    26 
       
    27 
       
    28 # Main program
       
    29 #
       
    30 def main():
       
    31     args = sys.argv[1:]
       
    32     if not args:
       
    33         print 'usage: pdeps file.py file.py ...'
       
    34         return 2
       
    35     #
       
    36     table = {}
       
    37     for arg in args:
       
    38         process(arg, table)
       
    39     #
       
    40     print '--- Uses ---'
       
    41     printresults(table)
       
    42     #
       
    43     print '--- Used By ---'
       
    44     inv = inverse(table)
       
    45     printresults(inv)
       
    46     #
       
    47     print '--- Closure of Uses ---'
       
    48     reach = closure(table)
       
    49     printresults(reach)
       
    50     #
       
    51     print '--- Closure of Used By ---'
       
    52     invreach = inverse(reach)
       
    53     printresults(invreach)
       
    54     #
       
    55     return 0
       
    56 
       
    57 
       
    58 # Compiled regular expressions to search for import statements
       
    59 #
       
    60 m_import = re.compile('^[ \t]*from[ \t]+([^ \t]+)[ \t]+')
       
    61 m_from = re.compile('^[ \t]*import[ \t]+([^#]+)')
       
    62 
       
    63 
       
    64 # Collect data from one file
       
    65 #
       
    66 def process(filename, table):
       
    67     fp = open(filename, 'r')
       
    68     mod = os.path.basename(filename)
       
    69     if mod[-3:] == '.py':
       
    70         mod = mod[:-3]
       
    71     table[mod] = list = []
       
    72     while 1:
       
    73         line = fp.readline()
       
    74         if not line: break
       
    75         while line[-1:] == '\\':
       
    76             nextline = fp.readline()
       
    77             if not nextline: break
       
    78             line = line[:-1] + nextline
       
    79         if m_import.match(line) >= 0:
       
    80             (a, b), (a1, b1) = m_import.regs[:2]
       
    81         elif m_from.match(line) >= 0:
       
    82             (a, b), (a1, b1) = m_from.regs[:2]
       
    83         else: continue
       
    84         words = line[a1:b1].split(',')
       
    85         # print '#', line, words
       
    86         for word in words:
       
    87             word = word.strip()
       
    88             if word not in list:
       
    89                 list.append(word)
       
    90 
       
    91 
       
    92 # Compute closure (this is in fact totally general)
       
    93 #
       
    94 def closure(table):
       
    95     modules = table.keys()
       
    96     #
       
    97     # Initialize reach with a copy of table
       
    98     #
       
    99     reach = {}
       
   100     for mod in modules:
       
   101         reach[mod] = table[mod][:]
       
   102     #
       
   103     # Iterate until no more change
       
   104     #
       
   105     change = 1
       
   106     while change:
       
   107         change = 0
       
   108         for mod in modules:
       
   109             for mo in reach[mod]:
       
   110                 if mo in modules:
       
   111                     for m in reach[mo]:
       
   112                         if m not in reach[mod]:
       
   113                             reach[mod].append(m)
       
   114                             change = 1
       
   115     #
       
   116     return reach
       
   117 
       
   118 
       
   119 # Invert a table (this is again totally general).
       
   120 # All keys of the original table are made keys of the inverse,
       
   121 # so there may be empty lists in the inverse.
       
   122 #
       
   123 def inverse(table):
       
   124     inv = {}
       
   125     for key in table.keys():
       
   126         if not inv.has_key(key):
       
   127             inv[key] = []
       
   128         for item in table[key]:
       
   129             store(inv, item, key)
       
   130     return inv
       
   131 
       
   132 
       
   133 # Store "item" in "dict" under "key".
       
   134 # The dictionary maps keys to lists of items.
       
   135 # If there is no list for the key yet, it is created.
       
   136 #
       
   137 def store(dict, key, item):
       
   138     if dict.has_key(key):
       
   139         dict[key].append(item)
       
   140     else:
       
   141         dict[key] = [item]
       
   142 
       
   143 
       
   144 # Tabulate results neatly
       
   145 #
       
   146 def printresults(table):
       
   147     modules = table.keys()
       
   148     maxlen = 0
       
   149     for mod in modules: maxlen = max(maxlen, len(mod))
       
   150     modules.sort()
       
   151     for mod in modules:
       
   152         list = table[mod]
       
   153         list.sort()
       
   154         print mod.ljust(maxlen), ':',
       
   155         if mod in list:
       
   156             print '(*)',
       
   157         for ref in list:
       
   158             print ref,
       
   159         print
       
   160 
       
   161 
       
   162 # Call main and honor exit status
       
   163 if __name__ == '__main__':
       
   164     try:
       
   165         sys.exit(main())
       
   166     except KeyboardInterrupt:
       
   167         sys.exit(1)