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

Reply via email to