Mercurial > cpython-lru_cache-weakref
annotate Tools/scripts/pdeps.py @ 5817:48b94de85bf3 legacy-trunk
Extensive changes by AMK.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Thu, 17 Jul 1997 16:29:42 +0000 |
| parents | 73758db2f464 |
| children | 14a27acc755a |
| rev | line source |
|---|---|
|
4573
73758db2f464
/usr/local/bin/python -> /usr/bin/env python
Guido van Rossum <guido@python.org>
parents:
1105
diff
changeset
|
1 #! /usr/bin/env python |
| 274 | 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 | |
|
1105
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
24 import regex |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
25 import os |
| 274 | 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 # | |
|
1105
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
61 m_import = regex.compile('^[ \t]*from[ \t]+\([^ \t]+\)[ \t]+') |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
62 m_from = regex.compile('^[ \t]*import[ \t]+\([^#]+\)') |
| 274 | 63 |
| 64 | |
| 65 # Collect data from one file | |
| 66 # | |
| 67 def process(filename, table): | |
| 68 fp = open(filename, 'r') | |
|
1105
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
69 mod = os.path.basename(filename) |
| 559 | 70 if mod[-3:] == '.py': |
| 274 | 71 mod = mod[:-3] |
| 72 table[mod] = list = [] | |
| 73 while 1: | |
| 74 line = fp.readline() | |
| 75 if not line: break | |
| 559 | 76 while line[-1:] == '\\': |
| 274 | 77 nextline = fp.readline() |
| 78 if not nextline: break | |
| 79 line = line[:-1] + nextline | |
|
1105
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
80 if m_import.match(line) >= 0: |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
81 (a, b), (a1, b1) = m_import.regs[:2] |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
82 elif m_from.match(line) >= 0: |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
83 (a, b), (a1, b1) = m_from.regs[:2] |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
84 else: continue |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
85 words = string.splitfields(line[a1:b1], ',') |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
86 # print '#', line, words |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
87 for word in words: |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
88 word = string.strip(word) |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
89 if word not in list: |
|
6f2a6efd019e
Adapt to modern times...
Guido van Rossum <guido@python.org>
parents:
559
diff
changeset
|
90 list.append(word) |
| 274 | 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) |
