diff options
author | Guido van Rossum <guido@python.org> | 1994-10-03 16:33:08 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1994-10-03 16:33:08 (GMT) |
commit | 00ff4336a9c4258d72aa11fb5160f7afbbe88d84 (patch) | |
tree | 993b2895ba2fcf762d756686970be449c448e365 /Tools/freeze/findmodules.py | |
parent | dbaf332107b3188980c0bce6aed7ac6bce212ec7 (diff) | |
download | cpython-00ff4336a9c4258d72aa11fb5160f7afbbe88d84.zip cpython-00ff4336a9c4258d72aa11fb5160f7afbbe88d84.tar.gz cpython-00ff4336a9c4258d72aa11fb5160f7afbbe88d84.tar.bz2 |
Totally new "freeze" program.
Diffstat (limited to 'Tools/freeze/findmodules.py')
-rw-r--r-- | Tools/freeze/findmodules.py | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/Tools/freeze/findmodules.py b/Tools/freeze/findmodules.py new file mode 100644 index 0000000..177f1fd --- /dev/null +++ b/Tools/freeze/findmodules.py @@ -0,0 +1,128 @@ +# Determine the names and filenames of the modules imported by a +# script, recursively. This is done by scanning for lines containing +# import statements. (The scanning has only superficial knowledge of +# Python syntax and no knowledge of semantics, so in theory the result +# may be incorrect -- however this is quite unlikely if you don't +# intentionally obscure your Python code.) + +import os +import regex +import string +import sys + + +# Top-level interface. +# First argument is the main program (script). +# Second optional argument is list of modules to be searched as well. + +def findmodules(scriptfile, modules = [], path = sys.path): + todo = {} + todo['__main__'] = scriptfile + for name in modules: + mod = os.path.basename(name) + if mod[-3:] == '.py': mod = mod[:-3] + todo[mod] = name + done = closure(todo) + return done + + +# Compute the closure of scanfile() and findmodule(). +# Return a dictionary mapping module names to filenames. +# Writes to stderr if a file can't be or read. + +def closure(todo): + done = {} + while todo: + newtodo = {} + for modname in todo.keys(): + if not done.has_key(modname): + filename = todo[modname] + if filename is None: + filename = findmodule(modname) + done[modname] = filename + if filename in ('<builtin>', '<unknown>'): + continue + try: + modules = scanfile(filename) + except IOError, msg: + sys.stderr.write("%s: %s\n" % + (filename, str(msg))) + continue + for m in modules: + if not done.has_key(m): + newtodo[m] = None + todo = newtodo + return done + + +# Scan a file looking for import statements. +# Return list of module names. +# Can raise IOError. + +importstr = '\(^\|:\)[ \t]*import[ \t]+\([a-zA-Z0-9_, \t]+\)' +fromstr = '\(^\|:\)[ \t]*from[ \t]+\([a-zA-Z0-9_]+\)[ \t]+import[ \t]+' +isimport = regex.compile(importstr) +isfrom = regex.compile(fromstr) + +def scanfile(filename): + allmodules = {} + f = open(filename, 'r') + try: + while 1: + line = f.readline() + if not line: break # EOF + while line[-2:] == '\\\n': # Continuation line + line = line[:-2] + ' ' + line = line + f.readline() + if isimport.search(line) >= 0: + rawmodules = isimport.group(2) + modules = string.splitfields(rawmodules, ',') + for i in range(len(modules)): + modules[i] = string.strip(modules[i]) + elif isfrom.search(line) >= 0: + modules = [isfrom.group(2)] + else: + continue + for mod in modules: + allmodules[mod] = None + finally: + f.close() + return allmodules.keys() + + +# Find the file containing a module, given its name. +# Return filename, or '<builtin>', or '<unknown>'. + +builtins = sys.builtin_module_names +if 'sys' not in builtins: builtins.append('sys') +# XXX this table may have to be changed depending on your platform: +tails = ['.so', 'module.so', '.py', '.pyc'] + +def findmodule(modname, path = sys.path): + if modname in builtins: return '<builtin>' + for dirname in path: + for tail in tails: + fullname = os.path.join(dirname, modname + tail) + try: + f = open(fullname, 'r') + except IOError: + continue + f.close() + return fullname + return '<unknown>' + + +# Test the above functions. + +def test(): + if not sys.argv[1:]: + print 'usage: python findmodules.py scriptfile [morefiles ...]' + sys.exit(2) + done = findmodules(sys.argv[1], sys.argv[2:]) + items = done.items() + items.sort() + for mod, file in [('Module', 'File')] + items: + print "%-15s %s" % (mod, file) + +if __name__ == '__main__': + test() |