Skip to content

Commit 71fa557

Browse files
committed
Add option to limit the depth of the modules that are reported. Potentially fixes #81.
1 parent 8bb4f56 commit 71fa557

File tree

3 files changed

+31
-20
lines changed

3 files changed

+31
-20
lines changed

pydeps/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ def parse_args(argv=()):
140140
args.add('--debug-mf', default=0, type=int, metavar="INT", help="set the ModuleFinder.debug flag to this value")
141141
args.add('--noise-level', default=200, type=int, metavar="INT", help="exclude sources or sinks with degree greater than noise-level")
142142
args.add('--max-bacon', default=2, type=int, metavar="INT", help="exclude nodes that are more than n hops away (default=2, 0 -> infinite)")
143+
args.add('--max-module-depth', default=0, type=int, metavar="INT", help="coalesce deep modules to at most n levels")
143144
args.add('--pylib', action='store_true', help="include python std lib modules")
144145
args.add('--pylib-all', action='store_true', help="include python all std lib modules (incl. C modules)")
145146
args.add('--include-missing', action='store_true', help="include modules that are not installed (or can't be found on sys.path)")

pydeps/depgraph.py

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,7 @@ class Source(object):
4343
"""
4444
def __init__(self, name, path=None, imports=(), exclude=False, args=None):
4545
self.args = args or {}
46-
if name == "__main__" and path:
47-
self.name = path.replace('\\', '/').replace('/', '.')
48-
if self.args.get('verbose', 0) >= 2: # pragma: nocover
49-
print("changing __main__ =>", self.name)
50-
else:
51-
self.name = name
52-
46+
self.name = name
5347
# self.kind = kind
5448
self.path = path # needed here..?
5549
self.imports = set(imports) # modules we import
@@ -61,6 +55,10 @@ def __init__(self, name, path=None, imports=(), exclude=False, args=None):
6155
def name_parts(self):
6256
return self.name.split('.')
6357

58+
@property
59+
def module_depth(self):
60+
return self.name.count('.')
61+
6462
@property
6563
def path_parts(self):
6664
p = self.path or ""
@@ -176,35 +174,34 @@ class DepGraph(object):
176174
""".split()
177175

178176
def __init__(self, depgraf, types, **args):
177+
# depgraph is py2depgraph.MyModulefinder._depgraph
179178
self.curhue = 150 # start with a green-ish color
180179
self.colors = {}
181180
self.cycles = []
182181
self.cyclenodes = set()
183182
self.cyclerelations = set()
183+
self.max_module_depth = args.get('max_module_depth', 0)
184184

185185
self.args = args
186186

187-
self.sources = {} # module_name -> Source
187+
#: dict[module_name] -> Source object
188+
self.sources = {}
188189
self.skiplist = [re.compile(fnmatch.translate(arg)) for arg in args['exclude']]
189190
self.skiplist += [re.compile('^%s$' % fnmatch.translate(arg)) for arg in args['exclude_exact']]
190191
# depgraf = {name: imports for (name, imports) in depgraf.items()}
191192

192-
for name, imports in list(depgraf.items()):
193+
for name, imports in depgraf.items():
193194
log.debug("depgraph name=%r imports=%r", name, imports)
194-
# if name.endswith('.py'):
195-
# name = name[:-3]
196195
src = Source(
197-
name=name,
198-
imports=list(imports.keys()), # XXX: throwing away .values(), which is abspath!
196+
name=self.source_name(name),
197+
imports=[self.source_name(n) for n in imports.keys()], # values handled below
199198
args=args,
200199
exclude=self._exclude(name),
201200
)
202201
self.add_source(src)
203-
for iname, path in list(imports.items()):
204-
# if iname.endswith('.py'):
205-
# iname = iname[:-3]
202+
for iname, path in imports.items():
206203
src = Source(
207-
name=iname,
204+
name=self.source_name(iname, path),
208205
path=path,
209206
args=args,
210207
exclude=self._exclude(iname)
@@ -236,7 +233,20 @@ def __init__(self, depgraf, types, **args):
236233
self.remove_excluded()
237234

238235
if not self.args['show_deps']:
239-
cli.verbose(3, self)
236+
cli.verbose(3, self)
237+
238+
def source_name(self, name, path=None):
239+
"""Returns the module name, possibly limited by --max-module-depth.
240+
"""
241+
res = name
242+
if name == "__main__" and path:
243+
res = path.replace('\\', '/').replace('/', '.')
244+
if self.args.get('verbose', 0) >= 2: # pragma: nocover
245+
print("changing __main__ =>", res)
246+
247+
if self.max_module_depth > 0:
248+
res = '.'.join(res.split('.')[:self.max_module_depth])
249+
return res
240250

241251
def levelcounts(self):
242252
pass
@@ -313,7 +323,7 @@ def _exclude(self, name):
313323
def add_source(self, src):
314324
if src.name in self.sources:
315325
log.debug("ADD-SOURCE[+=]\n%r", src)
316-
self.sources[src.name] += src
326+
self.sources[src.name] += src # merge
317327
else:
318328
log.debug("ADD-SOURCE[=]\n%r", src)
319329
self.sources[src.name] = src

pydeps/py2depgraph.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ def py2dep(target, **kw):
252252
log.debug('depgraph item: %r %r', k, v)
253253
if k in pylib:
254254
continue
255-
vals = {vk: vv for vk, vv in list(v.items()) if vk not in pylib}
255+
vals = {vk: vv for vk, vv in v.items() if vk not in pylib}
256256
mf_depgraph[k] = vals
257257

258258
# mf_modules = {k: os.syspath.abspath(v.__file__)

0 commit comments

Comments
 (0)