Don't setdefault in mymf.import_module if import_hook hasn't been run.
[depgraph.git] / py2depgraph.py
index b17c4ddbb3217c9d90fb9ffb9f2c24b4ad00896b..fa1b9304c01bac293cdf2b44e8c4775bbb99f2ce 100755 (executable)
 """Extract a tree of module imports from a Python script.
 """
 
+import logging
 import modulefinder
 
+LOG = logging.getLogger('py2depgraph')
+LOG.setLevel(logging.DEBUG)
+_STREAM_HANDLER = logging.StreamHandler()
+_STREAM_HANDLER.setLevel(logging.CRITICAL)
+_STREAM_HANDLER.setFormatter(
+    logging.Formatter('%(levelname)s - %(message)s'))
+LOG.addHandler(_STREAM_HANDLER)
+
+
 class mymf(modulefinder.ModuleFinder):
     def __init__(self,*args,**kwargs):
         self._depgraph = {}
@@ -34,7 +44,7 @@ class mymf(modulefinder.ModuleFinder):
         self._paths = {}
         self._last_caller = None
         modulefinder.ModuleFinder.__init__(self,*args,**kwargs)
-        
+
     def import_hook(self, name, caller=None, fromlist=None, level=-1):
         old_last_caller = self._last_caller
         try:
@@ -42,21 +52,23 @@ class mymf(modulefinder.ModuleFinder):
             return modulefinder.ModuleFinder.import_hook(self,name,caller,fromlist, level)
         finally:
             self._last_caller = old_last_caller
-            
+        LOG.debug('after import_hook(%s, %s, %s, %s), last_caller is %s'
+                  % (name, caller, fromlist, level, self._last_caller))
+
     def import_module(self,partnam,fqname,parent):
         r = modulefinder.ModuleFinder.import_module(self,partnam,fqname,parent)
-        if r is not None:
+        if None not in [r, self._last_caller]:
             self._depgraph.setdefault(self._last_caller.__name__,{})[r.__name__] = 1
         return r
-    
+
     def load_module(self, fqname, fp, pathname, (suffix, mode, type)):
         r = modulefinder.ModuleFinder.load_module(self, fqname, fp, pathname, (suffix, mode, type))
         if r is not None:
             self._types[r.__name__] = type
             self._paths[r.__name__] = pathname
         return r
-        
-        
+
+
 if __name__=='__main__':
     from optparse import OptionParser
     from pprint import pprint
@@ -64,14 +76,18 @@ if __name__=='__main__':
 
     usage = '%prog [options] path/to/script.py'
     p = OptionParser(usage=usage, description=__doc__)
+    p.add_option('-v', '--verbose', default=0, action='count',
+                 help='Increment verbosity.')
 
     options,args = p.parse_args()
 
+    log_level = logging.CRITICAL - 10*options.verbose
+    _STREAM_HANDLER.setLevel(log_level)
+
     script = args[0]
 
-    path = sys.path[:]
+    debug = options.verbose
     debug = 0
-    exclude = []
-    mf = mymf(path,debug,exclude)
+    mf = mymf(path=sys.path[:], debug=debug, excludes=[])
     mf.run_script(script)
     pprint({'depgraph':mf._depgraph,'types':mf._types,'paths':mf._paths})