contrib/import-checker.py
changeset 25702 ab2c5163900e
parent 25701 1f88c0f6ff5a
child 25703 1a6a117d0b95
equal deleted inserted replaced
25701:1f88c0f6ff5a 25702:ab2c5163900e
   270                 if not found:
   270                 if not found:
   271                     # this should be a function or a property of "node.module"
   271                     # this should be a function or a property of "node.module"
   272                     continue
   272                     continue
   273                 yield found[1]
   273                 yield found[1]
   274 
   274 
   275 def verify_stdlib_on_own_line(source):
   275 def verify_import_convention(module, source):
       
   276     """Verify imports match our established coding convention."""
       
   277     root = ast.parse(source)
       
   278 
       
   279     return verify_stdlib_on_own_line(root)
       
   280 
       
   281 def verify_stdlib_on_own_line(root):
   276     """Given some python source, verify that stdlib imports are done
   282     """Given some python source, verify that stdlib imports are done
   277     in separate statements from relative local module imports.
   283     in separate statements from relative local module imports.
   278 
   284 
   279     Observing this limitation is important as it works around an
   285     Observing this limitation is important as it works around an
   280     annoying lib2to3 bug in relative import rewrites:
   286     annoying lib2to3 bug in relative import rewrites:
   281     http://bugs.python.org/issue19510.
   287     http://bugs.python.org/issue19510.
   282 
   288 
   283     >>> list(verify_stdlib_on_own_line('import sys, foo'))
   289     >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo')))
   284     ['mixed imports\\n   stdlib:    sys\\n   relative:  foo']
   290     ['mixed imports\\n   stdlib:    sys\\n   relative:  foo']
   285     >>> list(verify_stdlib_on_own_line('import sys, os'))
   291     >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os')))
   286     []
   292     []
   287     >>> list(verify_stdlib_on_own_line('import foo, bar'))
   293     >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar')))
   288     []
   294     []
   289     """
   295     """
   290     for node in ast.walk(ast.parse(source)):
   296     for node in ast.walk(root):
   291         if isinstance(node, ast.Import):
   297         if isinstance(node, ast.Import):
   292             from_stdlib = {False: [], True: []}
   298             from_stdlib = {False: [], True: []}
   293             for n in node.names:
   299             for n in node.names:
   294                 from_stdlib[n.name in stdlib_modules].append(n.name)
   300                 from_stdlib[n.name in stdlib_modules].append(n.name)
   295             if from_stdlib[True] and from_stdlib[False]:
   301             if from_stdlib[True] and from_stdlib[False]:
   365     for modname, source_path in sorted(localmods.iteritems()):
   371     for modname, source_path in sorted(localmods.iteritems()):
   366         f = open(source_path)
   372         f = open(source_path)
   367         src = f.read()
   373         src = f.read()
   368         used_imports[modname] = sorted(
   374         used_imports[modname] = sorted(
   369             imported_modules(src, modname, localmods, ignore_nested=True))
   375             imported_modules(src, modname, localmods, ignore_nested=True))
   370         for error in verify_stdlib_on_own_line(src):
   376         for error in verify_import_convention(modname, src):
   371             any_errors = True
   377             any_errors = True
   372             print source_path, error
   378             print source_path, error
   373         f.close()
   379         f.close()
   374     cycles = find_cycles(used_imports)
   380     cycles = find_cycles(used_imports)
   375     if cycles:
   381     if cycles: