mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			167 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
			
		
		
	
	
			167 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable file
		
	
	
	
	
| #! /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)
 | 
