5 # Find dependencies between a bunch of Python modules.
8 # pdeps file1.py file2.py ...
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)
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
34 print 'usage: pdeps file.py file.py ...'
44 print '--- Used By ---'
48 print '--- Closure of Uses ---'
49 reach
= closure(table
)
52 print '--- Closure of Used By ---'
53 invreach
= inverse(reach
)
54 printresults(invreach
)
59 # Compiled regular expressions to search for import statements
61 m_import
= regex
.compile('^[ \t]*from[ \t]+\([^ \t]+\)[ \t]+')
62 m_from
= regex
.compile('^[ \t]*import[ \t]+\([^#]+\)')
65 # Collect data from one file
67 def process(filename
, table
):
68 fp
= open(filename
, 'r')
69 mod
= os
.path
.basename(filename
)
72 table
[mod
] = list = []
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]
85 words
= string
.splitfields(line
[a1
:b1
], ',')
86 # print '#', line, words
88 word
= string
.strip(word
)
93 # Compute closure (this is in fact totally general)
96 modules
= table
.keys()
98 # Initialize reach with a copy of table
102 reach
[mod
] = table
[mod
][:]
104 # Iterate until no more change
110 for mo
in reach
[mod
]:
113 if m
not in reach
[mod
]:
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.
126 for key
in table
.keys():
127 if not inv
.has_key(key
):
129 for item
in table
[key
]:
130 store(inv
, item
, key
)
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.
138 def store(dict, key
, item
):
139 if dict.has_key(key
):
140 dict[key
].append(item
)
145 # Tabulate results neatly
147 def printresults(table
):
148 modules
= table
.keys()
150 for mod
in modules
: maxlen
= max(maxlen
, len(mod
))
155 print string
.ljust(mod
, maxlen
), ':',
163 # Call main and honor exit status
166 except KeyboardInterrupt: