home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / pyth_os2.zip / python-1.0.2 / Demo / scripts / pdeps.py < prev    next >
Text File  |  1992-12-09  |  3KB  |  168 lines

  1. #! /usr/local/bin/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. import string
  27.  
  28.  
  29. # Main program
  30. #
  31. def main():
  32.     args = sys.argv[1:]
  33.     if not args:
  34.         print 'usage: pdeps file.py file.py ...'
  35.         return 2
  36.     #
  37.     table = {}
  38.     for arg in args:
  39.         process(arg, table)
  40.     #
  41.     print '--- Uses ---'
  42.     printresults(table)
  43.     #
  44.     print '--- Used By ---'
  45.     inv = inverse(table)
  46.     printresults(inv)
  47.     #
  48.     print '--- Closure of Uses ---'
  49.     reach = closure(table)
  50.     printresults(reach)
  51.     #
  52.     print '--- Closure of Used By ---'
  53.     invreach = inverse(reach)
  54.     printresults(invreach)
  55.     #
  56.     return 0
  57.  
  58.  
  59. # Compiled regular expressions to search for import statements
  60. #
  61. m_import = regex.compile('^[ \t]*from[ \t]+\([^ \t]+\)[ \t]+')
  62. m_from = regex.compile('^[ \t]*import[ \t]+\([^#]+\)')
  63.  
  64.  
  65. # Collect data from one file
  66. #
  67. def process(filename, table):
  68.     fp = open(filename, 'r')
  69.     mod = os.path.basename(filename)
  70.     if mod[-3:] == '.py':
  71.         mod = mod[:-3]
  72.     table[mod] = list = []
  73.     while 1:
  74.         line = fp.readline()
  75.         if not line: break
  76.         while line[-1:] == '\\':
  77.             nextline = fp.readline()
  78.             if not nextline: break
  79.             line = line[:-1] + nextline
  80.         if m_import.match(line) >= 0:
  81.             (a, b), (a1, b1) = m_import.regs[:2]
  82.         elif m_from.match(line) >= 0:
  83.             (a, b), (a1, b1) = m_from.regs[:2]
  84.         else: continue
  85.         words = string.splitfields(line[a1:b1], ',')
  86.         # print '#', line, words
  87.         for word in words:
  88.             word = string.strip(word)
  89.             if word not in list:
  90.                 list.append(word)
  91.  
  92.  
  93. # Compute closure (this is in fact totally general)
  94. #
  95. def closure(table):
  96.     modules = table.keys()
  97.     #
  98.     # Initialize reach with a copy of table
  99.     #
  100.     reach = {}
  101.     for mod in modules:
  102.         reach[mod] = table[mod][:]
  103.     #
  104.     # Iterate until no more change
  105.     #
  106.     change = 1
  107.     while change:
  108.         change = 0
  109.         for mod in modules:
  110.             for mo in reach[mod]:
  111.                 if mo in modules:
  112.                     for m in reach[mo]:
  113.                         if m not in reach[mod]:
  114.                             reach[mod].append(m)
  115.                             change = 1
  116.     #
  117.     return reach
  118.  
  119.  
  120. # Invert a table (this is again totally general).
  121. # All keys of the original table are made keys of the inverse,
  122. # so there may be empty lists in the inverse.
  123. #
  124. def inverse(table):
  125.     inv = {}
  126.     for key in table.keys():
  127.         if not inv.has_key(key):
  128.             inv[key] = []
  129.         for item in table[key]:
  130.             store(inv, item, key)
  131.     return inv
  132.  
  133.  
  134. # Store "item" in "dict" under "key".
  135. # The dictionary maps keys to lists of items.
  136. # If there is no list for the key yet, it is created.
  137. #
  138. def store(dict, key, item):
  139.     if dict.has_key(key):
  140.         dict[key].append(item)
  141.     else:
  142.         dict[key] = [item]
  143.  
  144.  
  145. # Tabulate results neatly
  146. #
  147. def printresults(table):
  148.     modules = table.keys()
  149.     maxlen = 0
  150.     for mod in modules: maxlen = max(maxlen, len(mod))
  151.     modules.sort()
  152.     for mod in modules:
  153.         list = table[mod]
  154.         list.sort()
  155.         print string.ljust(mod, maxlen), ':',
  156.         if mod in list:
  157.             print '(*)',
  158.         for ref in list:
  159.             print ref,
  160.         print
  161.  
  162.  
  163. # Call main and honor exit status
  164. try:
  165.     sys.exit(main())
  166. except KeyboardInterrupt:
  167.     sys.exit(1)
  168.