mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
Initial revision
This commit is contained in:
parent
0481447f41
commit
ec758ead39
16 changed files with 1007 additions and 0 deletions
167
Tools/scripts/pdeps.py
Executable file
167
Tools/scripts/pdeps.py
Executable file
|
@ -0,0 +1,167 @@
|
|||
#! /usr/local/python
|
||||
|
||||
# pdeps
|
||||
#
|
||||
# Find dependencies between a bunch of Python modules.
|
||||
#
|
||||
# Usage:
|
||||
# pdeps file1.py file2.py ...
|
||||
#
|
||||
# Output:
|
||||
# Four tables separated by lines like '--- Closure ---':
|
||||
# 1) Direct dependencies, listing which module imports which other modules
|
||||
# 2) The inverse of (1)
|
||||
# 3) Indirect dependencies, or the closure of the above
|
||||
# 4) The inverse of (3)
|
||||
#
|
||||
# To do:
|
||||
# - command line options to select output type
|
||||
# - option to automatically scan the Python library for referenced modules
|
||||
# - option to limit output to particular modules
|
||||
|
||||
|
||||
import sys
|
||||
import regexp
|
||||
import path
|
||||
import string
|
||||
|
||||
|
||||
# Main program
|
||||
#
|
||||
def main():
|
||||
args = sys.argv[1:]
|
||||
if not args:
|
||||
print 'usage: pdeps file.py file.py ...'
|
||||
return 2
|
||||
#
|
||||
table = {}
|
||||
for arg in args:
|
||||
process(arg, table)
|
||||
#
|
||||
print '--- Uses ---'
|
||||
printresults(table)
|
||||
#
|
||||
print '--- Used By ---'
|
||||
inv = inverse(table)
|
||||
printresults(inv)
|
||||
#
|
||||
print '--- Closure of Uses ---'
|
||||
reach = closure(table)
|
||||
printresults(reach)
|
||||
#
|
||||
print '--- Closure of Used By ---'
|
||||
invreach = inverse(reach)
|
||||
printresults(invreach)
|
||||
#
|
||||
return 0
|
||||
|
||||
|
||||
# Compiled regular expressions to search for import statements
|
||||
#
|
||||
m_import = regexp.compile('^[ \t]*from[ \t]+([^ \t]+)[ \t]+')
|
||||
m_from = regexp.compile('^[ \t]*import[ \t]+([^#]+)')
|
||||
|
||||
|
||||
# Collect data from one file
|
||||
#
|
||||
def process(filename, table):
|
||||
fp = open(filename, 'r')
|
||||
mod = path.basename(filename)
|
||||
if mod[-3:] = '.py':
|
||||
mod = mod[:-3]
|
||||
table[mod] = list = []
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line: break
|
||||
while line[-1:] = '\\':
|
||||
nextline = fp.readline()
|
||||
if not nextline: break
|
||||
line = line[:-1] + nextline
|
||||
result = m_import.exec(line)
|
||||
if not result:
|
||||
result = m_from.exec(line)
|
||||
if result:
|
||||
(a, b), (a1, b1) = result
|
||||
words = string.splitfields(line[a1:b1], ',')
|
||||
# print '#', line, words
|
||||
for word in words:
|
||||
word = string.strip(word)
|
||||
if word not in list:
|
||||
list.append(word)
|
||||
|
||||
|
||||
# Compute closure (this is in fact totally general)
|
||||
#
|
||||
def closure(table):
|
||||
modules = table.keys()
|
||||
#
|
||||
# Initialize reach with a copy of table
|
||||
#
|
||||
reach = {}
|
||||
for mod in modules:
|
||||
reach[mod] = table[mod][:]
|
||||
#
|
||||
# Iterate until no more change
|
||||
#
|
||||
change = 1
|
||||
while change:
|
||||
change = 0
|
||||
for mod in modules:
|
||||
for mo in reach[mod]:
|
||||
if mo in modules:
|
||||
for m in reach[mo]:
|
||||
if m not in reach[mod]:
|
||||
reach[mod].append(m)
|
||||
change = 1
|
||||
#
|
||||
return reach
|
||||
|
||||
|
||||
# Invert a table (this is again totally general).
|
||||
# All keys of the original table are made keys of the inverse,
|
||||
# so there may be empty lists in the inverse.
|
||||
#
|
||||
def inverse(table):
|
||||
inv = {}
|
||||
for key in table.keys():
|
||||
if not inv.has_key(key):
|
||||
inv[key] = []
|
||||
for item in table[key]:
|
||||
store(inv, item, key)
|
||||
return inv
|
||||
|
||||
|
||||
# Store "item" in "dict" under "key".
|
||||
# The dictionary maps keys to lists of items.
|
||||
# If there is no list for the key yet, it is created.
|
||||
#
|
||||
def store(dict, key, item):
|
||||
if dict.has_key(key):
|
||||
dict[key].append(item)
|
||||
else:
|
||||
dict[key] = [item]
|
||||
|
||||
|
||||
# Tabulate results neatly
|
||||
#
|
||||
def printresults(table):
|
||||
modules = table.keys()
|
||||
maxlen = 0
|
||||
for mod in modules: maxlen = max(maxlen, len(mod))
|
||||
modules.sort()
|
||||
for mod in modules:
|
||||
list = table[mod]
|
||||
list.sort()
|
||||
print string.ljust(mod, maxlen), ':',
|
||||
if mod in list:
|
||||
print '(*)',
|
||||
for ref in list:
|
||||
print ref,
|
||||
print
|
||||
|
||||
|
||||
# Call main and honor exit status
|
||||
try:
|
||||
sys.exit(main())
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
Loading…
Add table
Add a link
Reference in a new issue