contrib/import-checker.py
changeset 24488 4b3fc46097f7
parent 24487 642d245ff537
child 24489 0f6594b0a4e2
equal deleted inserted replaced
24487:642d245ff537 24488:4b3fc46097f7
   162 class CircularImport(Exception):
   162 class CircularImport(Exception):
   163     pass
   163     pass
   164 
   164 
   165 
   165 
   166 def cyclekey(names):
   166 def cyclekey(names):
   167     return tuple(sorted(set(names)))
   167     return tuple(sorted((names)))
   168 
   168 
   169 def check_one_mod(mod, imports, path=None, ignore=None):
   169 def check_one_mod(mod, imports, path=None, ignore=None):
   170     if path is None:
   170     if path is None:
   171         path = []
   171         path = []
   172     if ignore is None:
   172     if ignore is None:
   175     for i in sorted(imports.get(mod, [])):
   175     for i in sorted(imports.get(mod, [])):
   176         if i not in stdlib_modules and not i.startswith('mercurial.'):
   176         if i not in stdlib_modules and not i.startswith('mercurial.'):
   177             i = mod.rsplit('.', 1)[0] + '.' + i
   177             i = mod.rsplit('.', 1)[0] + '.' + i
   178         if i in path:
   178         if i in path:
   179             firstspot = path.index(i)
   179             firstspot = path.index(i)
   180             cycle = path[firstspot:] + [i]
   180             cycle = path[firstspot:]
   181             if cyclekey(cycle) not in ignore:
   181             if cyclekey(cycle) not in ignore:
   182                 raise CircularImport(cycle)
   182                 raise CircularImport(cycle)
   183             continue
   183             continue
   184         check_one_mod(i, imports, path=path, ignore=ignore)
   184         check_one_mod(i, imports, path=path, ignore=ignore)
   185 
   185 
   186 def rotatecycle(cycle):
   186 def rotatecycle(cycle):
   187     """arrange a cycle so that the lexicographically first module listed first
   187     """arrange a cycle so that the lexicographically first module listed first
   188 
   188 
   189     >>> rotatecycle(['foo', 'bar', 'foo'])
   189     >>> rotatecycle(['foo', 'bar'])
   190     ['bar', 'foo', 'bar']
   190     ['bar', 'foo', 'bar']
   191     """
   191     """
   192     lowest = min(cycle)
   192     lowest = min(cycle)
   193     idx = cycle.index(lowest)
   193     idx = cycle.index(lowest)
   194     return cycle[idx:-1] + cycle[:idx] + [lowest]
   194     return cycle[idx:] + cycle[:idx] + [lowest]
   195 
   195 
   196 def find_cycles(imports):
   196 def find_cycles(imports):
   197     """Find cycles in an already-loaded import graph.
   197     """Find cycles in an already-loaded import graph.
   198 
   198 
   199     >>> imports = {'top.foo': ['bar', 'os.path', 'qux'],
   199     >>> imports = {'top.foo': ['bar', 'os.path', 'qux'],