mirror of
https://fuchsia.googlesource.com/third_party/github.com/pylint-dev/pylint
synced 2024-09-22 00:24:37 +00:00
add warning for confusing usage of with statement
Emitted when an ambiguous looking with statement is used. For example `with open() as first, second` which looks like a tuple assignment but is actually 2 context managers. --HG-- branch : confusing-with-statement
This commit is contained in:
parent
9299f7a6b8
commit
9970d76a0a
|
@ -2,6 +2,11 @@ ChangeLog for Pylint
|
|||
--------------------
|
||||
|
||||
--
|
||||
* Add a new warning, 'confusing-with-statement', emitted by the
|
||||
base checker, when an ambiguous looking with statement is used.
|
||||
For example `with open() as first, second` which looks like a
|
||||
tuple assignment but is actually 2 context managers.
|
||||
|
||||
* Add a new warning, 'duplicate-except', emitted when there is an
|
||||
exception handler which handles an exception type that was handled
|
||||
before. Closes issue #485.
|
||||
|
|
|
@ -508,6 +508,13 @@ functions, methods
|
|||
'A call of assert on a tuple will always evaluate to true if '
|
||||
'the tuple is not empty, and will always evaluate to false if '
|
||||
'it is.'),
|
||||
'W0124': ('Following "as" with another context manager looks like a tuple.',
|
||||
'confusing-with-statement',
|
||||
'Emitted when a `with` statement component returns multiple values '
|
||||
'and uses name binding with `as` only for a part of those values, '
|
||||
'as in with ctx() as a, b. This can be misleading, since it\'s not '
|
||||
'clear if the context manager returns a tuple or if the node without '
|
||||
'a name binding is another context manager.'),
|
||||
'C0121': ('Missing required attribute "%s"', # W0103
|
||||
'missing-module-attribute',
|
||||
'Used when an attribute required for modules is missing.'),
|
||||
|
@ -872,6 +879,36 @@ functions, methods
|
|||
# everything else is not a proper sequence for reversed()
|
||||
self.add_message('bad-reversed-sequence', node=node)
|
||||
|
||||
@check_messages('confusing-with-statement')
|
||||
def visit_with(self, node):
|
||||
if not PY3K:
|
||||
# in Python 2 a "with" statement with multiple managers coresponds
|
||||
# to multiple nested AST "With" nodes
|
||||
pairs = []
|
||||
parent_node = node.parent
|
||||
if isinstance(parent_node, astroid.With):
|
||||
# we only care about the direct parent, since this method
|
||||
# gets called for each with node anyway
|
||||
pairs.extend(parent_node.items)
|
||||
pairs.extend(node.items)
|
||||
else:
|
||||
# in PY3K a "with" statement with multiple managers coresponds
|
||||
# to one AST "With" node with multiple items
|
||||
pairs = node.items
|
||||
prev_pair = None
|
||||
for pair in pairs:
|
||||
if prev_pair is not None:
|
||||
if (isinstance(prev_pair[1], astroid.AssName) and
|
||||
(pair[1] is None and not isinstance(pair[0], astroid.CallFunc))):
|
||||
# don't emit a message if the second is a function call
|
||||
# there's no way that can be mistaken for a name assignment
|
||||
if PY3K or node.lineno == node.parent.lineno:
|
||||
# if the line number doesn't match
|
||||
# we assume it's a nested "with"
|
||||
self.add_message('confusing-with-statement', node=node)
|
||||
prev_pair = pair
|
||||
|
||||
|
||||
_NAME_TYPES = {
|
||||
'module': (MOD_NAME_RGX, 'module'),
|
||||
'const': (CONST_NAME_RGX, 'constant'),
|
||||
|
|
27
pylint/test/functional/confusing_with_statement.py
Normal file
27
pylint/test/functional/confusing_with_statement.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# pylint: disable=undefined-variable,not-context-manager,missing-docstring
|
||||
|
||||
# both context managers are named
|
||||
with one as first, two as second:
|
||||
pass
|
||||
|
||||
# first matched as tuple; this is ok
|
||||
with one as (first, second), third:
|
||||
pass
|
||||
|
||||
# the first context manager doesn't have as name
|
||||
with one, two as second:
|
||||
pass
|
||||
|
||||
# the second is a function call; this is ok
|
||||
with one as first, two():
|
||||
pass
|
||||
|
||||
# nested with statements; make sure no message is emited
|
||||
# this could be a false positive on Py2
|
||||
with one as first:
|
||||
with two:
|
||||
pass
|
||||
|
||||
# ambiguous looking with statement
|
||||
with one as first, two: # [confusing-with-statement]
|
||||
pass
|
1
pylint/test/functional/confusing_with_statement.txt
Normal file
1
pylint/test/functional/confusing_with_statement.txt
Normal file
|
@ -0,0 +1 @@
|
|||
confusing-with-statement:26::Following "as" with another context manager looks like a tuple.
|
Loading…
Reference in New Issue
Block a user