##// END OF EJS Templates
import-checker: make imported_modules yield absolute dotted_name_of_path...
FUJIWARA Katsunori -
r25174:86298718 default
parent child Browse files
Show More
@@ -170,38 +170,94 b' def list_stdlib_modules():'
170
170
171 stdlib_modules = set(list_stdlib_modules())
171 stdlib_modules = set(list_stdlib_modules())
172
172
173 def imported_modules(source, ignore_nested=False):
173 def imported_modules(source, modulename, localmods, ignore_nested=False):
174 """Given the source of a file as a string, yield the names
174 """Given the source of a file as a string, yield the names
175 imported by that file.
175 imported by that file.
176
176
177 Args:
177 Args:
178 source: The python source to examine as a string.
178 source: The python source to examine as a string.
179 modulename: of specified python source (may have `__init__`)
180 localmods: dict of locally defined module names (may have `__init__`)
179 ignore_nested: If true, import statements that do not start in
181 ignore_nested: If true, import statements that do not start in
180 column zero will be ignored.
182 column zero will be ignored.
181
183
182 Returns:
184 Returns:
183 A list of module names imported by the given source.
185 A list of absolute module names imported by the given source.
184
186
187 >>> modulename = 'foo.xxx'
188 >>> localmods = {'foo.__init__': True,
189 ... 'foo.foo1': True, 'foo.foo2': True,
190 ... 'foo.bar.__init__': True, 'foo.bar.bar1': True,
191 ... 'baz.__init__': True, 'baz.baz1': True }
192 >>> # standard library (= not locally defined ones)
193 >>> sorted(imported_modules(
194 ... 'from stdlib1 import foo, bar; import stdlib2',
195 ... modulename, localmods))
196 []
197 >>> # relative importing
185 >>> sorted(imported_modules(
198 >>> sorted(imported_modules(
186 ... 'import foo ; from baz import bar; import foo.qux'))
199 ... 'import foo1; from bar import bar1',
187 ['baz.bar', 'foo', 'foo.qux']
200 ... modulename, localmods))
201 ['foo.bar.__init__', 'foo.bar.bar1', 'foo.foo1']
202 >>> sorted(imported_modules(
203 ... 'from bar.bar1 import name1, name2, name3',
204 ... modulename, localmods))
205 ['foo.bar.bar1']
206 >>> # absolute importing
207 >>> sorted(imported_modules(
208 ... 'from baz import baz1, name1',
209 ... modulename, localmods))
210 ['baz.__init__', 'baz.baz1']
211 >>> # mixed importing, even though it shouldn't be recommended
212 >>> sorted(imported_modules(
213 ... 'import stdlib, foo1, baz',
214 ... modulename, localmods))
215 ['baz.__init__', 'foo.foo1']
216 >>> # ignore_nested
188 >>> sorted(imported_modules(
217 >>> sorted(imported_modules(
189 ... '''import foo
218 ... '''import foo
190 ... def wat():
219 ... def wat():
191 ... import bar
220 ... import bar
192 ... ''', ignore_nested=True))
221 ... ''', modulename, localmods))
193 ['foo']
222 ['foo.__init__', 'foo.bar.__init__']
223 >>> sorted(imported_modules(
224 ... '''import foo
225 ... def wat():
226 ... import bar
227 ... ''', modulename, localmods, ignore_nested=True))
228 ['foo.__init__']
194 """
229 """
230 fromlocal = fromlocalfunc(modulename, localmods)
195 for node in ast.walk(ast.parse(source)):
231 for node in ast.walk(ast.parse(source)):
196 if ignore_nested and getattr(node, 'col_offset', 0) > 0:
232 if ignore_nested and getattr(node, 'col_offset', 0) > 0:
197 continue
233 continue
198 if isinstance(node, ast.Import):
234 if isinstance(node, ast.Import):
199 for n in node.names:
235 for n in node.names:
200 yield n.name
236 found = fromlocal(n.name)
237 if not found:
238 # this should import standard library
239 continue
240 yield found[1]
201 elif isinstance(node, ast.ImportFrom):
241 elif isinstance(node, ast.ImportFrom):
202 prefix = node.module + '.'
242 found = fromlocal(node.module)
243 if not found:
244 # this should import standard library
245 continue
246
247 absname, dottedpath, hassubmod = found
248 yield dottedpath
249 if not hassubmod:
250 # examination of "node.names" should be redundant
251 # e.g.: from mercurial.node import nullid, nullrev
252 continue
253
254 prefix = absname + '.'
203 for n in node.names:
255 for n in node.names:
204 yield prefix + n.name
256 found = fromlocal(prefix + n.name)
257 if not found:
258 # this should be a function or a property of "node.module"
259 continue
260 yield found[1]
205
261
206 def verify_stdlib_on_own_line(source):
262 def verify_stdlib_on_own_line(source):
207 """Given some python source, verify that stdlib imports are done
263 """Given some python source, verify that stdlib imports are done
@@ -297,7 +353,7 b' def main(argv):'
297 f = open(source_path)
353 f = open(source_path)
298 src = f.read()
354 src = f.read()
299 used_imports[modname] = sorted(
355 used_imports[modname] = sorted(
300 imported_modules(src, ignore_nested=True))
356 imported_modules(src, modname, localmods, ignore_nested=True))
301 for error in verify_stdlib_on_own_line(src):
357 for error in verify_stdlib_on_own_line(src):
302 any_errors = True
358 any_errors = True
303 print source_path, error
359 print source_path, error
@@ -37,3 +37,4 b' these may expose other cycles.'
37 stdlib: formatter
37 stdlib: formatter
38 relative: config, error, scmutil, util
38 relative: config, error, scmutil, util
39 Import cycle: mercurial.cmdutil -> mercurial.context -> mercurial.subrepo -> mercurial.cmdutil
39 Import cycle: mercurial.cmdutil -> mercurial.context -> mercurial.subrepo -> mercurial.cmdutil
40 Import cycle: mercurial.commands -> mercurial.commandserver -> mercurial.dispatch -> mercurial.commands
General Comments 0
You need to be logged in to leave comments. Login now