contrib/import-checker.py
changeset 28921 02ee31a50002
parent 28920 cdf331b54eb8
child 28922 4ec62a084e5c
equal deleted inserted replaced
28920:cdf331b54eb8 28921:02ee31a50002
   223                 mod = dotted_name_of_path(rel_path)
   223                 mod = dotted_name_of_path(rel_path)
   224                 yield mod
   224                 yield mod
   225 
   225 
   226 stdlib_modules = set(list_stdlib_modules())
   226 stdlib_modules = set(list_stdlib_modules())
   227 
   227 
   228 def imported_modules(source, modulename, localmods, ignore_nested=False):
   228 def imported_modules(source, modulename, f, localmods, ignore_nested=False):
   229     """Given the source of a file as a string, yield the names
   229     """Given the source of a file as a string, yield the names
   230     imported by that file.
   230     imported by that file.
   231 
   231 
   232     Args:
   232     Args:
   233       source: The python source to examine as a string.
   233       source: The python source to examine as a string.
   237                      column zero will be ignored.
   237                      column zero will be ignored.
   238 
   238 
   239     Returns:
   239     Returns:
   240       A list of absolute module names imported by the given source.
   240       A list of absolute module names imported by the given source.
   241 
   241 
       
   242     >>> f = 'foo/xxx.py'
   242     >>> modulename = 'foo.xxx'
   243     >>> modulename = 'foo.xxx'
   243     >>> localmods = {'foo.__init__': True,
   244     >>> localmods = {'foo.__init__': True,
   244     ...              'foo.foo1': True, 'foo.foo2': True,
   245     ...              'foo.foo1': True, 'foo.foo2': True,
   245     ...              'foo.bar.__init__': True, 'foo.bar.bar1': True,
   246     ...              'foo.bar.__init__': True, 'foo.bar.bar1': True,
   246     ...              'baz.__init__': True, 'baz.baz1': True }
   247     ...              'baz.__init__': True, 'baz.baz1': True }
   247     >>> # standard library (= not locally defined ones)
   248     >>> # standard library (= not locally defined ones)
   248     >>> sorted(imported_modules(
   249     >>> sorted(imported_modules(
   249     ...        'from stdlib1 import foo, bar; import stdlib2',
   250     ...        'from stdlib1 import foo, bar; import stdlib2',
   250     ...        modulename, localmods))
   251     ...        modulename, f, localmods))
   251     []
   252     []
   252     >>> # relative importing
   253     >>> # relative importing
   253     >>> sorted(imported_modules(
   254     >>> sorted(imported_modules(
   254     ...        'import foo1; from bar import bar1',
   255     ...        'import foo1; from bar import bar1',
   255     ...        modulename, localmods))
   256     ...        modulename, f, localmods))
   256     ['foo.bar.bar1', 'foo.foo1']
   257     ['foo.bar.bar1', 'foo.foo1']
   257     >>> sorted(imported_modules(
   258     >>> sorted(imported_modules(
   258     ...        'from bar.bar1 import name1, name2, name3',
   259     ...        'from bar.bar1 import name1, name2, name3',
   259     ...        modulename, localmods))
   260     ...        modulename, f, localmods))
   260     ['foo.bar.bar1']
   261     ['foo.bar.bar1']
   261     >>> # absolute importing
   262     >>> # absolute importing
   262     >>> sorted(imported_modules(
   263     >>> sorted(imported_modules(
   263     ...        'from baz import baz1, name1',
   264     ...        'from baz import baz1, name1',
   264     ...        modulename, localmods))
   265     ...        modulename, f, localmods))
   265     ['baz.__init__', 'baz.baz1']
   266     ['baz.__init__', 'baz.baz1']
   266     >>> # mixed importing, even though it shouldn't be recommended
   267     >>> # mixed importing, even though it shouldn't be recommended
   267     >>> sorted(imported_modules(
   268     >>> sorted(imported_modules(
   268     ...        'import stdlib, foo1, baz',
   269     ...        'import stdlib, foo1, baz',
   269     ...        modulename, localmods))
   270     ...        modulename, f, localmods))
   270     ['baz.__init__', 'foo.foo1']
   271     ['baz.__init__', 'foo.foo1']
   271     >>> # ignore_nested
   272     >>> # ignore_nested
   272     >>> sorted(imported_modules(
   273     >>> sorted(imported_modules(
   273     ... '''import foo
   274     ... '''import foo
   274     ... def wat():
   275     ... def wat():
   275     ...     import bar
   276     ...     import bar
   276     ... ''', modulename, localmods))
   277     ... ''', modulename, f, localmods))
   277     ['foo.__init__', 'foo.bar.__init__']
   278     ['foo.__init__', 'foo.bar.__init__']
   278     >>> sorted(imported_modules(
   279     >>> sorted(imported_modules(
   279     ... '''import foo
   280     ... '''import foo
   280     ... def wat():
   281     ... def wat():
   281     ...     import bar
   282     ...     import bar
   282     ... ''', modulename, localmods, ignore_nested=True))
   283     ... ''', modulename, f, localmods, ignore_nested=True))
   283     ['foo.__init__']
   284     ['foo.__init__']
   284     """
   285     """
   285     fromlocal = fromlocalfunc(modulename, localmods)
   286     fromlocal = fromlocalfunc(modulename, localmods)
   286     for node in ast.walk(ast.parse(source)):
   287     for node in ast.walk(ast.parse(source, f)):
   287         if ignore_nested and getattr(node, 'col_offset', 0) > 0:
   288         if ignore_nested and getattr(node, 'col_offset', 0) > 0:
   288             continue
   289             continue
   289         if isinstance(node, ast.Import):
   290         if isinstance(node, ast.Import):
   290             for n in node.names:
   291             for n in node.names:
   291                 found = fromlocal(n.name)
   292                 found = fromlocal(n.name)
   587         localmods[modname] = source_path
   588         localmods[modname] = source_path
   588     for localmodname, source_path in sorted(localmods.items()):
   589     for localmodname, source_path in sorted(localmods.items()):
   589         for src, modname in sources(source_path, localmodname):
   590         for src, modname in sources(source_path, localmodname):
   590             try:
   591             try:
   591                 used_imports[modname] = sorted(
   592                 used_imports[modname] = sorted(
   592                     imported_modules(src, modname, localmods,
   593                     imported_modules(src, modname, source_path, localmods,
   593                                      ignore_nested=True))
   594                                      ignore_nested=True))
   594                 for error, lineno in verify_import_convention(modname, src,
   595                 for error, lineno in verify_import_convention(modname, src,
   595                                                               localmods):
   596                                                               localmods):
   596                     any_errors = True
   597                     any_errors = True
   597                     print('%s:%d: %s' % (source_path, lineno, error))
   598                     print('%s:%d: %s' % (source_path, lineno, error))