77import pprint
88import re
99import enum
10+ import yaml
11+
1012from . import colors
1113import sys
14+ import logging
15+ log = logging .getLogger (__name__ )
1216
1317# we're normally not interested in imports of std python packages.
1418PYLIB_PATH = {
@@ -40,6 +44,7 @@ def __init__(self, name, kind=imp.UNKNOWN, path=None, imports=(), exclude=False,
4044 print "changing __main__ =>" , self .name
4145 else :
4246 self .name = name
47+
4348 self .kind = kind
4449 self .path = path # needed here..?
4550 self .imports = set (imports ) # modules we import
@@ -58,12 +63,14 @@ def path_parts(self):
5863
5964 @property
6065 def in_degree (self ):
61- "Number of incoming arrows."
66+ """Number of incoming arrows.
67+ """
6268 return len (self .imports )
6369
6470 @property
6571 def out_degree (self ):
66- "Number of outgoing arrows."
72+ """Number of outgoing arrows.
73+ """
6774 return len (self .imported_by )
6875
6976 @property
@@ -107,11 +114,18 @@ def __repr__(self):
107114 return json .dumps (self .__json__ (), indent = 4 )
108115
109116 def __iadd__ (self , other ):
117+ if self .name == other .name and self .imports == other .imports and self .bacon == other .bacon :
118+ return self
119+ log .debug ("iadd lhs: %r" , self )
120+ log .debug ("iadd rhs: %r" , other )
110121 assert self .name == other .name
111122 self .path = self .path or other .path
112123 self .kind = self .kind or other .kind
113124 self .imports |= other .imports
114125 self .imported_by |= other .imported_by
126+ self .bacon = min (self .bacon , other .bacon )
127+ self .excluded = self .excluded or other .excluded
128+ log .debug ("iadd result: %r" , self )
115129 return self
116130
117131 # def imported_modules(self, depgraph):
@@ -166,6 +180,7 @@ def get_colors(self, src, colorspace=None):
166180 return colorspace .color (src )
167181
168182 def _is_pylib (self , path ):
183+ log .info ('path %r in PYLIB_PATH %r => %s' , path , PYLIB_PATH , path in PYLIB_PATH )
169184 return path in PYLIB_PATH
170185
171186 def proximity_metric (self , a , b ):
@@ -194,8 +209,8 @@ def dissimilarity_metric(self, a, b):
194209
195210 Returns an int between 1 (default) and 4 (highly unrelated).
196211 """
197- if self ._is_pylib (a ) and self ._is_pylib (b ):
198- return 1
212+ # if self._is_pylib(a) and self._is_pylib(b):
213+ # return 1
199214
200215 res = 4
201216 for an , bn , n in izip_longest (a .name_parts , b .name_parts , range (4 )):
@@ -205,6 +220,10 @@ def dissimilarity_metric(self, a, b):
205220 return res
206221
207222 def _exclude (self , name ):
223+ # excl = any(skip.match(name) for skip in self.skiplist)
224+ # if 'metar' in name:
225+ # print "Exclude?", name, excl
226+ # print [s.pattern for s in self.skiplist]
208227 return any (skip .match (name ) for skip in self .skiplist )
209228
210229 def __init__ (self , depgraf , types , ** args ):
@@ -215,15 +234,17 @@ def __init__(self, depgraf, types, **args):
215234 self .cyclerelations = set ()
216235
217236 self .args = args
237+
218238 self .sources = {} # module_name -> Source
219239 self .skiplist = [re .compile (fnmatch .translate (arg )) for arg in args ['exclude' ]]
240+ # print "SKPLIST:", self.skiplist[0].pattern
220241
221242 for name , imports in depgraf .items ():
222- self . verbose ( 4 , "depgraph: " , name , imports )
243+ log . debug ( "depgraph name=%r imports=%r " , name , imports )
223244 src = Source (
224245 name = name ,
225246 kind = imp (types .get (name , 0 )),
226- imports = imports .keys (),
247+ imports = imports .keys (), # XXX: throwing away .values(), which is abspath!
227248 args = args ,
228249 exclude = self ._exclude (name ),
229250 )
@@ -252,9 +273,11 @@ def __init__(self, depgraf, types, **args):
252273 self .exclude_bacon (self .args ['max_bacon' ])
253274
254275 excluded = [v for v in self .sources .values () if v .excluded ]
276+ # print "EXCLUDED:", excluded
255277 self .skip_count = len (excluded )
256278 self .verbose (1 , "skipping" , self .skip_count , "modules" )
257279 for module in excluded :
280+ # print 'exclude:', module.name
258281 self .verbose (2 , " " , module .name )
259282
260283 self .remove_excluded ()
@@ -268,8 +291,10 @@ def verbose(self, n, *args):
268291
269292 def add_source (self , src ):
270293 if src .name in self .sources :
294+ log .info ("ADD-SOURCE[+=]\n %r" , src )
271295 self .sources [src .name ] += src
272296 else :
297+ log .info ("ADD-SOURCE[=]\n %r" , src )
273298 self .sources [src .name ] = src
274299
275300 def __getitem__ (self , item ):
@@ -322,7 +347,8 @@ def traverse(node, path):
322347 traverse (src , [])
323348
324349 def connect_generations (self ):
325- "Traverse depth-first adding imported_by."
350+ """Traverse depth-first adding imported_by.
351+ """
326352 for src in self .sources .values ():
327353 for _child in src .imports :
328354 if _child in self .sources :
@@ -355,17 +381,22 @@ def exclude_noise(self):
355381 if src .is_noise ():
356382 self .verbose (2 , "excluding" , src , "because it is noisy:" , src .degree )
357383 src .excluded = True
384+ print "Exluding noise:" , src .name
358385 self ._add_skip (src .name )
359386
360387 def exclude_bacon (self , limit ):
361- "Exclude models that are more than `limit` hops away from __main__."
388+ """Exclude models that are more than `limit` hops away from __main__.
389+ """
362390 for src in self .sources .values ():
363391 if src .bacon > limit :
364392 src .excluded = True
393+ # print "Excluding bacon:", src.name
365394 self ._add_skip (src .name )
366395
367396 def remove_excluded (self ):
368- "Remove all sources marked as excluded."
397+ """Remove all sources marked as excluded.
398+ """
399+ # print yaml.dump({k:v.__json__() for k,v in self.sources.items()}, default_flow_style=False)
369400 sources = self .sources .values ()
370401 for src in sources :
371402 if src .excluded :
@@ -374,4 +405,5 @@ def remove_excluded(self):
374405 src .imported_by = [m for m in src .imported_by if not self ._exclude (m )]
375406
376407 def _add_skip (self , name ):
408+ # print 'add skip:', name
377409 self .skiplist .append (re .compile (fnmatch .translate (name )))
0 commit comments