This is a follow-on to my earlier patches to logilab-astng to support
set and dictionary comprehensions in Python 2.7.
I found that PyLint would give variable referenced before assignment
errors when using dictionary comprehensions:
new = {key: value for key, value in dict()}
results in:
test.py|1| [E0601] Using variable 'key' before assignment
test.py|1| [E0601] Using variable 'value' before assignment
This patch eliminates that problem, and fixes up some other places in
the code that I found based on searching for existing list comprehension
behavior:
checkers/base.py:
* make in_loop return true if the parent node is a set comprehension
or a dict comprehension
checkers/string_format.py
in StringFormatChecker.visit_binop:
* add set comprehensions to the list of node types that will
generate E9903 for supplying a non-mapping type for a string that
has only named format specifiers
* for strings that use only unnamed format specifiers, add set
comprehensions and dict comprehensions to the list of node types
that provide a single argument
checkers/utils.py
* add set comprehensions and dict comprehension nodes to the
COMP_NODE_TYPES list, used by is_defined_before to determine if a
variable node is defined by a parent node
* remove the unused FOR_NODE_TYPES constant
* remove the unused comp_nodes_type keyword argument of
is_defined_before and replace it by direct usage of COMP_NODE_TYPES
in the body of the function
I did not add/update any tests because I don't know much about the
PyLint testing mechanism, but if someone can point me in the right
direction, I'm happy to make those changes too.
Cheers,
Daniel Harding
# HG changeset patch
# User Daniel Harding <[email protected]>
# Date 1286445245 0
# Node ID 757e612dddcd2455a1c9f0af5911375c2b58d21f
# Parent f098483da5ab00122a22128acf1bf0ce4ca5a2da
add initial support for set and list comprehensions
diff -r f098483da5ab -r 757e612dddcd checkers/base.py
--- a/checkers/base.py Tue Sep 28 15:02:43 2010 +0200
+++ b/checkers/base.py Thu Oct 07 09:54:05 2010 +0000
@@ -43,7 +43,8 @@
"""return True if the node is inside a kind of for loop"""
parent = node.parent
while parent is not None:
- if isinstance(parent, (astng.For, astng.ListComp, astng.GenExpr)):
+ if isinstance(parent, (astng.For, astng.ListComp, astng.SetComp,
+ astng.DictComp, astng.GenExpr)):
return True
parent = parent.parent
return False
diff -r f098483da5ab -r 757e612dddcd checkers/string_format.py
--- a/checkers/string_format.py Tue Sep 28 15:02:43 2010 +0200
+++ b/checkers/string_format.py Thu Oct 07 09:54:05 2010 +0000
@@ -197,6 +197,7 @@
isinstance(args, astng.Tuple) or
isinstance(args, astng.List) or
isinstance(args, astng.ListComp) or
+ isinstance(args, astng.SetComp) or
isinstance(args, astng.GenExpr) or
isinstance(args, astng.Backquote) or
isinstance(args, astng.Lambda)):
@@ -218,6 +219,8 @@
isinstance(args, astng.Dict) or
isinstance(args, astng.List) or
isinstance(args, astng.ListComp) or
+ isinstance(args, astng.SetComp) or
+ isinstance(args, astng.DictComp) or
isinstance(args, astng.GenExpr) or
isinstance(args, astng.Backquote) or
isinstance(args, astng.Lambda) or
diff -r f098483da5ab -r 757e612dddcd checkers/utils.py
--- a/checkers/utils.py Tue Sep 28 15:02:43 2010 +0200
+++ b/checkers/utils.py Thu Oct 07 09:54:05 2010 +0000
@@ -23,11 +23,10 @@
try:
# python >= 2.4
- COMP_NODE_TYPES = (astng.ListComp, astng.GenExpr)
- FOR_NODE_TYPES = (astng.For, astng.Comprehension, astng.Comprehension)
+ COMP_NODE_TYPES = (astng.ListComp, astng.SetComp, astng.DictComp,
+ astng.GenExpr)
except AttributeError:
COMP_NODE_TYPES = astng.ListComp
- FOR_NODE_TYPES = (astng.For, astng.Comprehension)
def safe_infer(node):
"""return the inferred value for the given node.
@@ -83,15 +82,15 @@
return True
return False
-def is_defined_before(var_node, comp_node_types=COMP_NODE_TYPES):
- """return True if the variable node is defined by a parent node (list
- or generator comprehension, lambda) or in a previous sibling node
- one the same line (statement_defining ; statement_using)
+def is_defined_before(var_node):
+ """return True if the variable node is defined by a parent node (list,
+ set, dict, or generator comprehension, lambda) or in a previous sibling
+ node on the same line (statement_defining ; statement_using)
"""
varname = var_node.name
_node = var_node.parent
while _node:
- if isinstance(_node, comp_node_types):
+ if isinstance(_node, COMP_NODE_TYPES):
for ass_node in _node.nodes_of_class(astng.AssName):
if ass_node.name == varname:
return True
_______________________________________________
Python-Projects mailing list
[email protected]
http://lists.logilab.org/mailman/listinfo/python-projects