home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / programacao / pythonwin / python.exe / PDEPS.PY < prev    next >
Encoding:
Python Source  |  2002-09-11  |  4.0 KB  |  167 lines

  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 regex
  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 = regex.compile('^[ \t]*from[ \t]+\([^ \t]+\)[ \t]+')
  61. m_from = regex.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. try:
  164.     sys.exit(main())
  165. except KeyboardInterrupt:
  166.     sys.exit(1)
  167.