20 '__future__', |
20 '__future__', |
21 'mercurial.hgweb.common', |
21 'mercurial.hgweb.common', |
22 'mercurial.hgweb.request', |
22 'mercurial.hgweb.request', |
23 'mercurial.i18n', |
23 'mercurial.i18n', |
24 'mercurial.node', |
24 'mercurial.node', |
25 ) |
|
26 |
|
27 # Modules that have both Python and C implementations. |
|
28 _dualmodules = ( |
|
29 ) |
25 ) |
30 |
26 |
31 # Modules that must be aliased because they are commonly confused with |
27 # Modules that must be aliased because they are commonly confused with |
32 # common variables and can create aliasing and readability issues. |
28 # common variables and can create aliasing and readability issues. |
33 requirealias = { |
29 requirealias = { |
57 newscope = isinstance(node, ast.FunctionDef) |
53 newscope = isinstance(node, ast.FunctionDef) |
58 if not newscope: |
54 if not newscope: |
59 todo.extend(ast.iter_child_nodes(node)) |
55 todo.extend(ast.iter_child_nodes(node)) |
60 yield node, newscope |
56 yield node, newscope |
61 |
57 |
62 def dotted_name_of_path(path, trimpure=False): |
58 def dotted_name_of_path(path): |
63 """Given a relative path to a source file, return its dotted module name. |
59 """Given a relative path to a source file, return its dotted module name. |
64 |
60 |
65 >>> dotted_name_of_path('mercurial/error.py') |
61 >>> dotted_name_of_path('mercurial/error.py') |
66 'mercurial.error' |
62 'mercurial.error' |
67 >>> dotted_name_of_path('mercurial/pure/parsers.py', trimpure=True) |
|
68 'mercurial.parsers' |
|
69 >>> dotted_name_of_path('zlibmodule.so') |
63 >>> dotted_name_of_path('zlibmodule.so') |
70 'zlib' |
64 'zlib' |
71 """ |
65 """ |
72 parts = path.replace(os.sep, '/').split('/') |
66 parts = path.replace(os.sep, '/').split('/') |
73 parts[-1] = parts[-1].split('.', 1)[0] # remove .py and .so and .ARCH.so |
67 parts[-1] = parts[-1].split('.', 1)[0] # remove .py and .so and .ARCH.so |
74 if parts[-1].endswith('module'): |
68 if parts[-1].endswith('module'): |
75 parts[-1] = parts[-1][:-6] |
69 parts[-1] = parts[-1][:-6] |
76 if trimpure: |
|
77 return '.'.join(p for p in parts if p != 'pure') |
|
78 return '.'.join(parts) |
70 return '.'.join(parts) |
79 |
71 |
80 def fromlocalfunc(modulename, localmods): |
72 def fromlocalfunc(modulename, localmods): |
81 """Get a function to examine which locally defined module the |
73 """Get a function to examine which locally defined module the |
82 target source imports via a specified name. |
74 target source imports via a specified name. |
693 argv.extend(l.rstrip() for l in sys.stdin.readlines()) |
685 argv.extend(l.rstrip() for l in sys.stdin.readlines()) |
694 localmods = {} |
686 localmods = {} |
695 used_imports = {} |
687 used_imports = {} |
696 any_errors = False |
688 any_errors = False |
697 for source_path in argv[1:]: |
689 for source_path in argv[1:]: |
698 trimpure = source_path.endswith(_dualmodules) |
690 modname = dotted_name_of_path(source_path) |
699 modname = dotted_name_of_path(source_path, trimpure=trimpure) |
|
700 localmods[modname] = source_path |
691 localmods[modname] = source_path |
701 for localmodname, source_path in sorted(localmods.items()): |
692 for localmodname, source_path in sorted(localmods.items()): |
702 for src, modname, name, line in sources(source_path, localmodname): |
693 for src, modname, name, line in sources(source_path, localmodname): |
703 try: |
694 try: |
704 used_imports[modname] = sorted( |
695 used_imports[modname] = sorted( |