comparison contrib/import-checker.py @ 26956:4b56214ebb7a

import-checker: include lineno in warning message This makes it easy to look for imports in function scope.
author Yuya Nishihara <yuya@tcha.org>
date Sun, 01 Nov 2015 15:46:06 +0900
parents c4114e335b49
children 5abba2c92da3
comparison
equal deleted inserted replaced
26955:c4114e335b49 26956:4b56214ebb7a
354 # Relative import levels encountered so far. 354 # Relative import levels encountered so far.
355 seenlevels = set() 355 seenlevels = set()
356 356
357 for node in ast.walk(root): 357 for node in ast.walk(root):
358 def msg(fmt, *args): 358 def msg(fmt, *args):
359 return fmt % args 359 return (fmt % args, node.lineno)
360 if isinstance(node, ast.Import): 360 if isinstance(node, ast.Import):
361 # Disallow "import foo, bar" and require separate imports 361 # Disallow "import foo, bar" and require separate imports
362 # for each module. 362 # for each module.
363 if len(node.names) > 1: 363 if len(node.names) > 1:
364 yield msg('multiple imported names: %s', 364 yield msg('multiple imported names: %s',
462 Observing this limitation is important as it works around an 462 Observing this limitation is important as it works around an
463 annoying lib2to3 bug in relative import rewrites: 463 annoying lib2to3 bug in relative import rewrites:
464 http://bugs.python.org/issue19510. 464 http://bugs.python.org/issue19510.
465 465
466 >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo'))) 466 >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo')))
467 ['mixed imports\\n stdlib: sys\\n relative: foo'] 467 [('mixed imports\\n stdlib: sys\\n relative: foo', 1)]
468 >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os'))) 468 >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os')))
469 [] 469 []
470 >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar'))) 470 >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar')))
471 [] 471 []
472 """ 472 """
476 for n in node.names: 476 for n in node.names:
477 from_stdlib[n.name in stdlib_modules].append(n.name) 477 from_stdlib[n.name in stdlib_modules].append(n.name)
478 if from_stdlib[True] and from_stdlib[False]: 478 if from_stdlib[True] and from_stdlib[False]:
479 yield ('mixed imports\n stdlib: %s\n relative: %s' % 479 yield ('mixed imports\n stdlib: %s\n relative: %s' %
480 (', '.join(sorted(from_stdlib[True])), 480 (', '.join(sorted(from_stdlib[True])),
481 ', '.join(sorted(from_stdlib[False])))) 481 ', '.join(sorted(from_stdlib[False]))), node.lineno)
482 482
483 class CircularImport(Exception): 483 class CircularImport(Exception):
484 pass 484 pass
485 485
486 def checkmod(mod, imports): 486 def checkmod(mod, imports):
548 for modname, source_path in sorted(localmods.iteritems()): 548 for modname, source_path in sorted(localmods.iteritems()):
549 f = open(source_path) 549 f = open(source_path)
550 src = f.read() 550 src = f.read()
551 used_imports[modname] = sorted( 551 used_imports[modname] = sorted(
552 imported_modules(src, modname, localmods, ignore_nested=True)) 552 imported_modules(src, modname, localmods, ignore_nested=True))
553 for error in verify_import_convention(modname, src): 553 for error, lineno in verify_import_convention(modname, src):
554 any_errors = True 554 any_errors = True
555 print source_path, error 555 print '%s:%d: %s' % (source_path, lineno, error)
556 f.close() 556 f.close()
557 cycles = find_cycles(used_imports) 557 cycles = find_cycles(used_imports)
558 if cycles: 558 if cycles:
559 firstmods = set() 559 firstmods = set()
560 for c in sorted(cycles, key=_cycle_sortkey): 560 for c in sorted(cycles, key=_cycle_sortkey):