| 1 | #!/usr/bin/python |
|---|
| 2 | # Copyright: 2007 Brian Harring <ferringb@gmail.com> |
|---|
| 3 | # License: GPL2 |
|---|
| 4 | |
|---|
| 5 | import __builtin__ |
|---|
| 6 | |
|---|
| 7 | class intercept_import(object): |
|---|
| 8 | |
|---|
| 9 | def __init__(self, callback): |
|---|
| 10 | self.callback = callback |
|---|
| 11 | self.stack = [] |
|---|
| 12 | self.seen = set() |
|---|
| 13 | |
|---|
| 14 | def __call__(self, *args): |
|---|
| 15 | if args[0] not in self.seen: |
|---|
| 16 | self.disable() |
|---|
| 17 | self.callback(self.stack, args) |
|---|
| 18 | self.enable() |
|---|
| 19 | self.stack.append(args[0]) |
|---|
| 20 | self.seen.add(args[0]) |
|---|
| 21 | try: |
|---|
| 22 | return self.orig_import(*args) |
|---|
| 23 | finally: |
|---|
| 24 | self.stack.pop() |
|---|
| 25 | |
|---|
| 26 | def enable(self): |
|---|
| 27 | cur_import = __builtin__.__import__ |
|---|
| 28 | if isinstance(cur_import, intercept_import): |
|---|
| 29 | raise RuntimeError("an intercept is already active") |
|---|
| 30 | self.orig_import = cur_import |
|---|
| 31 | __builtin__.__import__ = self |
|---|
| 32 | |
|---|
| 33 | def disable(self): |
|---|
| 34 | if __builtin__.__import__ != self: |
|---|
| 35 | raise RuntimeError("either not active, or a different intercept " |
|---|
| 36 | "is in use") |
|---|
| 37 | __builtin__.__import__ = self.orig_import |
|---|
| 38 | del self.orig_import |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | if __name__ == "__main__": |
|---|
| 42 | import __main__ |
|---|
| 43 | orig = dict(__main__.__dict__.iteritems()) |
|---|
| 44 | del orig["intercept_import"] |
|---|
| 45 | del orig["__builtin__"] |
|---|
| 46 | del orig["__main__"] |
|---|
| 47 | |
|---|
| 48 | import sys, imp |
|---|
| 49 | |
|---|
| 50 | usage = "debug_imports.py [-o output_file_path || -i] scriptfile [arg] ..." |
|---|
| 51 | if not sys.argv[1:]: |
|---|
| 52 | print "Usage: ", usage |
|---|
| 53 | sys.exit(2) |
|---|
| 54 | |
|---|
| 55 | # yes, at first thought, this should use getopt or optparse. |
|---|
| 56 | # problem is, folks may want to spot that import, thus we can't. |
|---|
| 57 | |
|---|
| 58 | import traceback, pdb |
|---|
| 59 | |
|---|
| 60 | args = sys.argv[1:] |
|---|
| 61 | if args[0] == '-o': |
|---|
| 62 | if not len(args) > 2: |
|---|
| 63 | print "Usage: ", usage |
|---|
| 64 | sys.exit(2) |
|---|
| 65 | f = open(args[1], 'w') |
|---|
| 66 | def callback(modules, key, val): |
|---|
| 67 | f.write("adding %s\n" % key) |
|---|
| 68 | traceback.print_stack(file=f) |
|---|
| 69 | args = args[2:] |
|---|
| 70 | elif args[0] == '-i': |
|---|
| 71 | def callback(args): |
|---|
| 72 | pdb.set_trace() |
|---|
| 73 | args = args[1:] |
|---|
| 74 | else: |
|---|
| 75 | import time |
|---|
| 76 | def callback(stack, args): |
|---|
| 77 | if stack: |
|---|
| 78 | print "in: %s" % ', '.join(stack) |
|---|
| 79 | if len(args) == 4 and args[3] is not None: |
|---|
| 80 | print "from %s import %s" % (args[0], ', '.join(args[3])) |
|---|
| 81 | else: |
|---|
| 82 | print "import %s " % args[0] |
|---|
| 83 | print time.time() |
|---|
| 84 | # traceback.print_stack(file=sys.stdout) |
|---|
| 85 | print |
|---|
| 86 | |
|---|
| 87 | |
|---|
| 88 | path = args[0] |
|---|
| 89 | |
|---|
| 90 | sys.argv = args[:] |
|---|
| 91 | i = intercept_import(callback) |
|---|
| 92 | i.enable() |
|---|
| 93 | print "starting\n",time.time(),"\n" |
|---|
| 94 | try: |
|---|
| 95 | imp.load_module("__main__", open(args[0]), args[0], ("", "r", imp.PY_SOURCE)) |
|---|
| 96 | finally: |
|---|
| 97 | i.disable() |
|---|
| 98 | print "\nfinished\n",time.time(),"\n" |
|---|
| 99 | sys.exit(0) |
|---|