variables.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. # Copyright (c) 2003-2011 LOGILAB S.A. (Paris, FRANCE).
  2. # http://www.logilab.fr/ -- mailto:contact@logilab.fr
  3. #
  4. # This program is free software; you can redistribute it and/or modify it under
  5. # the terms of the GNU General Public License as published by the Free Software
  6. # Foundation; either version 2 of the License, or (at your option) any later
  7. # version.
  8. #
  9. # This program is distributed in the hope that it will be useful, but WITHOUT
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License along with
  14. # this program; if not, write to the Free Software Foundation, Inc.,
  15. # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  16. """variables checkers for Python code
  17. """
  18. import sys
  19. from copy import copy
  20. from logilab import astng
  21. from logilab.astng import are_exclusive, builtin_lookup, ASTNGBuildingException
  22. from pylint.interfaces import IASTNGChecker
  23. from pylint.checkers import BaseChecker
  24. from pylint.checkers.utils import (PYMETHODS, is_ancestor_name, is_builtin,
  25. is_defined_before, is_error, is_func_default, is_func_decorator,
  26. assign_parent, check_messages, is_inside_except, clobber_in_except,
  27. get_all_elements)
  28. def in_for_else_branch(parent, stmt):
  29. """Returns True if stmt in inside the else branch for a parent For stmt."""
  30. return (isinstance(parent, astng.For) and
  31. any(else_stmt.parent_of(stmt) for else_stmt in parent.orelse))
  32. def overridden_method(klass, name):
  33. """get overridden method if any"""
  34. try:
  35. parent = klass.local_attr_ancestors(name).next()
  36. except (StopIteration, KeyError):
  37. return None
  38. try:
  39. meth_node = parent[name]
  40. except KeyError:
  41. # We have found an ancestor defining <name> but it's not in the local
  42. # dictionary. This may happen with astng built from living objects.
  43. return None
  44. if isinstance(meth_node, astng.Function):
  45. return meth_node
  46. return None
  47. MSGS = {
  48. 'E0601': ('Using variable %r before assignment',
  49. 'Used when a local variable is accessed before it\'s \
  50. assignment.'),
  51. 'E0602': ('Undefined variable %r',
  52. 'Used when an undefined variable is accessed.'),
  53. 'E0611': ('No name %r in module %r',
  54. 'Used when a name cannot be found in a module.'),
  55. 'W0601': ('Global variable %r undefined at the module level',
  56. 'Used when a variable is defined through the "global" statement \
  57. but the variable is not defined in the module scope.'),
  58. 'W0602': ('Using global for %r but no assignment is done',
  59. 'Used when a variable is defined through the "global" statement \
  60. but no assignment to this variable is done.'),
  61. 'W0603': ('Using the global statement', # W0121
  62. 'Used when you use the "global" statement to update a global \
  63. variable. PyLint just try to discourage this \
  64. usage. That doesn\'t mean you can not use it !'),
  65. 'W0604': ('Using the global statement at the module level', # W0103
  66. 'Used when you use the "global" statement at the module level \
  67. since it has no effect'),
  68. 'W0611': ('Unused import %s',
  69. 'Used when an imported module or variable is not used.'),
  70. 'W0612': ('Unused variable %r',
  71. 'Used when a variable is defined but not used.'),
  72. 'W0613': ('Unused argument %r',
  73. 'Used when a function or method argument is not used.'),
  74. 'W0614': ('Unused import %s from wildcard import',
  75. 'Used when an imported module or variable is not used from a \
  76. \'from X import *\' style import.'),
  77. 'W0621': ('Redefining name %r from outer scope (line %s)',
  78. 'Used when a variable\'s name hide a name defined in the outer \
  79. scope.'),
  80. 'W0622': ('Redefining built-in %r',
  81. 'Used when a variable or function override a built-in.'),
  82. 'W0623': ('Redefining name %r from %s in exception handler',
  83. 'Used when an exception handler assigns the exception \
  84. to an existing name'),
  85. 'W0631': ('Using possibly undefined loop variable %r',
  86. 'Used when an loop variable (i.e. defined by a for loop or \
  87. a list comprehension or a generator expression) is used outside \
  88. the loop.'),
  89. }
  90. class VariablesChecker(BaseChecker):
  91. """checks for
  92. * unused variables / imports
  93. * undefined variables
  94. * redefinition of variable from builtins or from an outer scope
  95. * use of variable before assignment
  96. """
  97. __implements__ = IASTNGChecker
  98. name = 'variables'
  99. msgs = MSGS
  100. priority = -1
  101. options = (
  102. ("init-import",
  103. {'default': 0, 'type' : 'yn', 'metavar' : '<y_or_n>',
  104. 'help' : 'Tells whether we should check for unused import in \
  105. __init__ files.'}),
  106. ("dummy-variables-rgx",
  107. {'default': ('_|dummy'),
  108. 'type' :'regexp', 'metavar' : '<regexp>',
  109. 'help' : 'A regular expression matching the beginning of \
  110. the name of dummy variables (i.e. not used).'}),
  111. ("additional-builtins",
  112. {'default': (), 'type' : 'csv',
  113. 'metavar' : '<comma separated list>',
  114. 'help' : 'List of additional names supposed to be defined in \
  115. builtins. Remember that you should avoid to define new builtins when possible.'
  116. }),
  117. )
  118. def __init__(self, linter=None):
  119. BaseChecker.__init__(self, linter)
  120. self._to_consume = None
  121. self._checking_mod_attr = None
  122. self._vars = None
  123. def visit_module(self, node):
  124. """visit module : update consumption analysis variable
  125. checks globals doesn't overrides builtins
  126. """
  127. self._to_consume = [(copy(node.locals), {}, 'module')]
  128. self._vars = []
  129. for name, stmts in node.locals.items():
  130. if is_builtin(name) and not is_inside_except(stmts[0]):
  131. # do not print Redefining builtin for additional builtins
  132. self.add_message('W0622', args=name, node=stmts[0])
  133. @check_messages('W0611', 'W0614')
  134. def leave_module(self, node):
  135. """leave module: check globals
  136. """
  137. assert len(self._to_consume) == 1
  138. not_consumed = self._to_consume.pop()[0]
  139. # don't check unused imports in __init__ files
  140. if not self.config.init_import and node.package:
  141. return
  142. for name, stmts in not_consumed.items():
  143. stmt = stmts[0]
  144. if isinstance(stmt, astng.Import):
  145. self.add_message('W0611', args=name, node=stmt)
  146. elif isinstance(stmt, astng.From) and stmt.modname != '__future__':
  147. if stmt.names[0][0] == '*':
  148. self.add_message('W0614', args=name, node=stmt)
  149. else:
  150. self.add_message('W0611', args=name, node=stmt)
  151. del self._to_consume
  152. del self._vars
  153. def visit_class(self, node):
  154. """visit class: update consumption analysis variable
  155. """
  156. self._to_consume.append((copy(node.locals), {}, 'class'))
  157. def leave_class(self, _):
  158. """leave class: update consumption analysis variable
  159. """
  160. # do not check for not used locals here (no sense)
  161. self._to_consume.pop()
  162. def visit_lambda(self, node):
  163. """visit lambda: update consumption analysis variable
  164. """
  165. self._to_consume.append((copy(node.locals), {}, 'lambda'))
  166. def leave_lambda(self, _):
  167. """leave lambda: update consumption analysis variable
  168. """
  169. # do not check for not used locals here
  170. self._to_consume.pop()
  171. def visit_genexpr(self, node):
  172. """visit genexpr: update consumption analysis variable
  173. """
  174. self._to_consume.append((copy(node.locals), {}, 'comprehension'))
  175. def leave_genexpr(self, _):
  176. """leave genexpr: update consumption analysis variable
  177. """
  178. # do not check for not used locals here
  179. self._to_consume.pop()
  180. def visit_dictcomp(self, node):
  181. """visit dictcomp: update consumption analysis variable
  182. """
  183. self._to_consume.append((copy(node.locals), {}, 'comprehension'))
  184. def leave_dictcomp(self, _):
  185. """leave dictcomp: update consumption analysis variable
  186. """
  187. # do not check for not used locals here
  188. self._to_consume.pop()
  189. def visit_setcomp(self, node):
  190. """visit setcomp: update consumption analysis variable
  191. """
  192. self._to_consume.append((copy(node.locals), {}, 'comprehension'))
  193. def leave_setcomp(self, _):
  194. """leave setcomp: update consumption analysis variable
  195. """
  196. # do not check for not used locals here
  197. self._to_consume.pop()
  198. def visit_function(self, node):
  199. """visit function: update consumption analysis variable and check locals
  200. """
  201. self._to_consume.append((copy(node.locals), {}, 'function'))
  202. self._vars.append({})
  203. if not set(('W0621', 'W0622')) & self.active_msgs:
  204. return
  205. globs = node.root().globals
  206. for name, stmt in node.items():
  207. if is_inside_except(stmt):
  208. continue
  209. if name in globs and not isinstance(stmt, astng.Global):
  210. line = globs[name][0].lineno
  211. self.add_message('W0621', args=(name, line), node=stmt)
  212. elif is_builtin(name):
  213. # do not print Redefining builtin for additional builtins
  214. self.add_message('W0622', args=name, node=stmt)
  215. def leave_function(self, node):
  216. """leave function: check function's locals are consumed"""
  217. not_consumed = self._to_consume.pop()[0]
  218. self._vars.pop(0)
  219. if not set(('W0612', 'W0613')) & self.active_msgs:
  220. return
  221. # don't check arguments of function which are only raising an exception
  222. if is_error(node):
  223. return
  224. # don't check arguments of abstract methods or within an interface
  225. is_method = node.is_method()
  226. klass = node.parent.frame()
  227. if is_method and (klass.type == 'interface' or node.is_abstract()):
  228. return
  229. authorized_rgx = self.config.dummy_variables_rgx
  230. called_overridden = False
  231. argnames = node.argnames()
  232. for name, stmts in not_consumed.iteritems():
  233. # ignore some special names specified by user configuration
  234. if authorized_rgx.match(name):
  235. continue
  236. # ignore names imported by the global statement
  237. # FIXME: should only ignore them if it's assigned latter
  238. stmt = stmts[0]
  239. if isinstance(stmt, astng.Global):
  240. continue
  241. # care about functions with unknown argument (builtins)
  242. if name in argnames:
  243. if is_method:
  244. # don't warn for the first argument of a (non static) method
  245. if node.type != 'staticmethod' and name == argnames[0]:
  246. continue
  247. # don't warn for argument of an overridden method
  248. if not called_overridden:
  249. overridden = overridden_method(klass, node.name)
  250. called_overridden = True
  251. if overridden is not None and name in overridden.argnames():
  252. continue
  253. if node.name in PYMETHODS and node.name not in ('__init__', '__new__'):
  254. continue
  255. # don't check callback arguments XXX should be configurable
  256. if node.name.startswith('cb_') or node.name.endswith('_cb'):
  257. continue
  258. self.add_message('W0613', args=name, node=stmt)
  259. else:
  260. self.add_message('W0612', args=name, node=stmt)
  261. @check_messages('W0601', 'W0602', 'W0603', 'W0604', 'W0622')
  262. def visit_global(self, node):
  263. """check names imported exists in the global scope"""
  264. frame = node.frame()
  265. if isinstance(frame, astng.Module):
  266. self.add_message('W0604', node=node)
  267. return
  268. module = frame.root()
  269. default_message = True
  270. for name in node.names:
  271. try:
  272. assign_nodes = module.getattr(name)
  273. except astng.NotFoundError:
  274. # unassigned global, skip
  275. assign_nodes = []
  276. for anode in assign_nodes:
  277. if anode.parent is None:
  278. # node returned for builtin attribute such as __file__,
  279. # __doc__, etc...
  280. continue
  281. if anode.frame() is frame:
  282. # same scope level assignment
  283. break
  284. else:
  285. # global but no assignment
  286. self.add_message('W0602', args=name, node=node)
  287. default_message = False
  288. if not assign_nodes:
  289. continue
  290. for anode in assign_nodes:
  291. if anode.parent is None:
  292. self.add_message('W0622', args=name, node=node)
  293. break
  294. if anode.frame() is module:
  295. # module level assignment
  296. break
  297. else:
  298. # global undefined at the module scope
  299. self.add_message('W0601', args=name, node=node)
  300. default_message = False
  301. if default_message:
  302. self.add_message('W0603', node=node)
  303. def _loopvar_name(self, node, name):
  304. # filter variables according to node's scope
  305. # XXX used to filter parents but don't remember why, and removing this
  306. # fixes a W0631 false positive reported by Paul Hachmann on 2008/12 on
  307. # python-projects (added to func_use_for_or_listcomp_var test)
  308. #astmts = [stmt for stmt in node.lookup(name)[1]
  309. # if hasattr(stmt, 'ass_type')] and
  310. # not stmt.statement().parent_of(node)]
  311. if 'W0631' not in self.active_msgs:
  312. return
  313. astmts = [stmt for stmt in node.lookup(name)[1]
  314. if hasattr(stmt, 'ass_type')]
  315. # filter variables according their respective scope test is_statement
  316. # and parent to avoid #74747. This is not a total fix, which would
  317. # introduce a mechanism similar to special attribute lookup in
  318. # modules. Also, in order to get correct inference in this case, the
  319. # scope lookup rules would need to be changed to return the initial
  320. # assignment (which does not exist in code per se) as well as any later
  321. # modifications.
  322. if not astmts or (astmts[0].is_statement or astmts[0].parent) \
  323. and astmts[0].statement().parent_of(node):
  324. _astmts = []
  325. else:
  326. _astmts = astmts[:1]
  327. for i, stmt in enumerate(astmts[1:]):
  328. if (astmts[i].statement().parent_of(stmt)
  329. and not in_for_else_branch(astmts[i].statement(), stmt)):
  330. continue
  331. _astmts.append(stmt)
  332. astmts = _astmts
  333. if len(astmts) == 1:
  334. ass = astmts[0].ass_type()
  335. if isinstance(ass, (astng.For, astng.Comprehension, astng.GenExpr)) \
  336. and not ass.statement() is node.statement():
  337. self.add_message('W0631', args=name, node=node)
  338. def visit_excepthandler(self, node):
  339. for name in get_all_elements(node.name):
  340. clobbering, args = clobber_in_except(name)
  341. if clobbering:
  342. self.add_message('W0623', args=args, node=name)
  343. def visit_assname(self, node):
  344. if isinstance(node.ass_type(), astng.AugAssign):
  345. self.visit_name(node)
  346. def visit_delname(self, node):
  347. self.visit_name(node)
  348. def visit_name(self, node):
  349. """check that a name is defined if the current scope and doesn't
  350. redefine a built-in
  351. """
  352. stmt = node.statement()
  353. if stmt.fromlineno is None:
  354. # name node from a astng built from live code, skip
  355. assert not stmt.root().file.endswith('.py')
  356. return
  357. name = node.name
  358. frame = stmt.scope()
  359. # if the name node is used as a function default argument's value or as
  360. # a decorator, then start from the parent frame of the function instead
  361. # of the function frame - and thus open an inner class scope
  362. if (is_func_default(node) or is_func_decorator(node)
  363. or is_ancestor_name(frame, node)):
  364. start_index = len(self._to_consume) - 2
  365. else:
  366. start_index = len(self._to_consume) - 1
  367. # iterates through parent scopes, from the inner to the outer
  368. base_scope_type = self._to_consume[start_index][-1]
  369. for i in range(start_index, -1, -1):
  370. to_consume, consumed, scope_type = self._to_consume[i]
  371. # if the current scope is a class scope but it's not the inner
  372. # scope, ignore it. This prevents to access this scope instead of
  373. # the globals one in function members when there are some common
  374. # names. The only exception is when the starting scope is a
  375. # comprehension and its direct outer scope is a class
  376. if scope_type == 'class' and i != start_index and not (
  377. base_scope_type == 'comprehension' and i == start_index-1):
  378. # XXX find a way to handle class scope in a smoother way
  379. continue
  380. # the name has already been consumed, only check it's not a loop
  381. # variable used outside the loop
  382. if name in consumed:
  383. self._loopvar_name(node, name)
  384. break
  385. # mark the name as consumed if it's defined in this scope
  386. # (i.e. no KeyError is raised by "to_consume[name]")
  387. try:
  388. consumed[name] = to_consume[name]
  389. except KeyError:
  390. continue
  391. # checks for use before assignment
  392. defnode = assign_parent(to_consume[name][0])
  393. if defnode is not None:
  394. defstmt = defnode.statement()
  395. defframe = defstmt.frame()
  396. maybee0601 = True
  397. if not frame is defframe:
  398. maybee0601 = False
  399. elif defframe.parent is None:
  400. # we are at the module level, check the name is not
  401. # defined in builtins
  402. if name in defframe.scope_attrs or builtin_lookup(name)[1]:
  403. maybee0601 = False
  404. else:
  405. # we are in a local scope, check the name is not
  406. # defined in global or builtin scope
  407. if defframe.root().lookup(name)[1]:
  408. maybee0601 = False
  409. if (maybee0601
  410. and stmt.fromlineno <= defstmt.fromlineno
  411. and not is_defined_before(node)
  412. and not are_exclusive(stmt, defstmt, ('NameError', 'Exception', 'BaseException'))):
  413. if defstmt is stmt and isinstance(node, (astng.DelName,
  414. astng.AssName)):
  415. self.add_message('E0602', args=name, node=node)
  416. elif self._to_consume[-1][-1] != 'lambda':
  417. # E0601 may *not* occurs in lambda scope
  418. self.add_message('E0601', args=name, node=node)
  419. if not isinstance(node, astng.AssName): # Aug AssName
  420. del to_consume[name]
  421. else:
  422. del consumed[name]
  423. # check it's not a loop variable used outside the loop
  424. self._loopvar_name(node, name)
  425. break
  426. else:
  427. # we have not found the name, if it isn't a builtin, that's an
  428. # undefined name !
  429. if not (name in astng.Module.scope_attrs or is_builtin(name)
  430. or name in self.config.additional_builtins):
  431. self.add_message('E0602', args=name, node=node)
  432. @check_messages('E0611')
  433. def visit_import(self, node):
  434. """check modules attribute accesses"""
  435. for name, _ in node.names:
  436. parts = name.split('.')
  437. try:
  438. module = node.infer_name_module(parts[0]).next()
  439. except astng.ResolveError:
  440. continue
  441. self._check_module_attrs(node, module, parts[1:])
  442. @check_messages('E0611')
  443. def visit_from(self, node):
  444. """check modules attribute accesses"""
  445. name_parts = node.modname.split('.')
  446. level = getattr(node, 'level', None)
  447. try:
  448. module = node.root().import_module(name_parts[0], level=level)
  449. except ASTNGBuildingException:
  450. return
  451. except Exception, exc:
  452. print 'Unhandled exception in VariablesChecker:', exc
  453. return
  454. module = self._check_module_attrs(node, module, name_parts[1:])
  455. if not module:
  456. return
  457. for name, _ in node.names:
  458. if name == '*':
  459. continue
  460. self._check_module_attrs(node, module, name.split('.'))
  461. def _check_module_attrs(self, node, module, module_names):
  462. """check that module_names (list of string) are accessible through the
  463. given module
  464. if the latest access name corresponds to a module, return it
  465. """
  466. assert isinstance(module, astng.Module), module
  467. while module_names:
  468. name = module_names.pop(0)
  469. if name == '__dict__':
  470. module = None
  471. break
  472. try:
  473. module = module.getattr(name)[0].infer().next()
  474. if module is astng.YES:
  475. return None
  476. except astng.NotFoundError:
  477. self.add_message('E0611', args=(name, module.name), node=node)
  478. return None
  479. except astng.InferenceError:
  480. return None
  481. if module_names:
  482. # FIXME: other message if name is not the latest part of
  483. # module_names ?
  484. modname = module and module.name or '__dict__'
  485. self.add_message('E0611', node=node,
  486. args=('.'.join(module_names), modname))
  487. return None
  488. if isinstance(module, astng.Module):
  489. return module
  490. return None
  491. class VariablesChecker3k(VariablesChecker):
  492. '''Modified variables checker for 3k'''
  493. # listcomp have now also their scope
  494. def visit_listcomp(self, node):
  495. """visit dictcomp: update consumption analysis variable
  496. """
  497. self._to_consume.append((copy(node.locals), {}, 'comprehension'))
  498. def leave_listcomp(self, _):
  499. """leave dictcomp: update consumption analysis variable
  500. """
  501. # do not check for not used locals here
  502. self._to_consume.pop()
  503. if sys.version_info >= (3, 0):
  504. VariablesChecker = VariablesChecker3k
  505. def register(linter):
  506. """required method to auto register this checker"""
  507. linter.register_checker(VariablesChecker(linter))