Patchwork [3,of,7] import-checker: try a little harder to show fewer cycles

login
register
mail settings
Submitter Augie Fackler
Date Nov. 17, 2013, 5:21 p.m.
Message ID <dcfea9369d456f676ce2.1384708885@hit-nxdomain.opendns.com>
Download mbox | patch
Permalink /patch/3016/
State Superseded
Commit c65a6937b828c0a111584805751e2120b4bce902
Headers show

Comments

Augie Fackler - Nov. 17, 2013, 5:21 p.m.
# HG changeset patch
# User Augie Fackler <raf@durin42.com>
# Date 1383795950 18000
#      Wed Nov 06 22:45:50 2013 -0500
# Node ID dcfea9369d456f676ce2eb80cd60d17d031c04e5
# Parent  8b6007b0ecd735b917d39bdeab1b2ec028fd3992
import-checker: try a little harder to show fewer cycles

This makes sure that all cycles begin with the lexicographically first
module, so that we're less likely to show overlapping cycles in the
final analysis.

Patch

diff --git a/contrib/import-checker.py b/contrib/import-checker.py
--- a/contrib/import-checker.py
+++ b/contrib/import-checker.py
@@ -137,6 +137,15 @@ 
             continue
         check_one_mod(i, imports, path=path, ignore=ignore)
 
+def rotatecycle(cycle):
+    """arrange a cycle so that the lexicographically first module listed first
+
+    >>> rotatecycle(['foo', 'bar', 'foo'])
+    ['bar', 'foo', 'bar']
+    """
+    lowest = min(cycle)
+    idx = cycle.index(lowest)
+    return cycle[idx:] + cycle[1:idx] + [lowest]
 
 def find_cycles(imports):
     """Find cycles in an already-loaded import graph.
@@ -146,8 +155,8 @@ 
     ...            'top.baz': ['foo'],
     ...            'top.qux': ['foo']}
     >>> print '\\n'.join(sorted(find_cycles(imports)))
-    top.bar -> top.baz -> top.foo -> top.bar
-    top.foo -> top.qux -> top.foo
+    top.bar -> top.baz -> top.foo -> top.bar -> top.bar
+    top.foo -> top.qux -> top.foo -> top.foo
     """
     cycles = {}
     seen_in_cycle = set()
@@ -156,7 +165,7 @@ 
             check_one_mod(mod, imports, ignore=cycles)
         except CircularImport, e:
             cycle = e.args[0]
-            cycles[cyclekey(cycle)] = ' -> '.join(cycle)
+            cycles[cyclekey(cycle)] = ' -> '.join(rotatecycle(cycle))
             seen_in_cycle |= set(cycle)
     return cycles.values()