Repository: adamchainz/flake8-comprehensions (python)

Issue:
False positive on C404
I have a block of code that looks like:

    instance_kwargs = dict([
        key_value.split('=')
        key_value in full_lookup.split(':')[1].split('&')
    ])

This is being marked as  C404: unnecessary list comprehension.

However, I don't believe it's possible to use a single dict comprehension to perform this.

(I'm not saying it's great code, btw...)

Pull request description:
Fix false positive in C404
Fixes #194.

Patch:
diff --git a/HISTORY.rst b/HISTORY.rst
index 1a7a439..4c40087 100644
--- a/HISTORY.rst
+++ b/HISTORY.rst
@@ -6,6 +6,8 @@ Pending Release
 ---------------
 
 * Update Python support to 3.5-3.8.
+* Fix false positives for C404 for list comprehensions not directly creating
+  tuples.
 
 3.0.1 (2019-10-28)
 ------------------
diff --git a/src/flake8_comprehensions.py b/src/flake8_comprehensions.py
index 6a8bfe8..c959459 100644
--- a/src/flake8_comprehensions.py
+++ b/src/flake8_comprehensions.py
@@ -56,26 +56,28 @@ class ComprehensionChecker:
 
                 elif (
                     num_positional_args == 1
-                    and isinstance(node.args[0], ast.GeneratorExp)
+                    and isinstance(node.args[0], (ast.GeneratorExp, ast.ListComp))
                     and isinstance(node.args[0].elt, ast.Tuple)
                     and len(node.args[0].elt.elts) == 2
                     and node.func.id == "dict"
                 ):
+                    if isinstance(node.args[0], ast.GeneratorExp):
+                        msg = "C402"
+                    else:
+                        msg = "C404"
                     yield (
                         node.lineno,
                         node.col_offset,
-                        self.messages["C402"],
+                        self.messages[msg],
                         type(self),
                     )
 
                 elif (
                     num_positional_args == 1
                     and isinstance(node.args[0], ast.ListComp)
-                    and node.func.id in ("list", "set", "dict")
+                    and node.func.id in ("list", "set")
                 ):
-                    msg_key = {"list": "C411", "set": "C403", "dict": "C404"}[
-                        node.func.id
-                    ]
+                    msg_key = {"list": "C411", "set": "C403"}[node.func.id]
                     yield (
                         node.lineno,
                         node.col_offset,


Test patch:
diff --git a/tests/test_flake8_comprehensions.py b/tests/test_flake8_comprehensions.py
index 2072075..0924d8c 100644
--- a/tests/test_flake8_comprehensions.py
+++ b/tests/test_flake8_comprehensions.py
@@ -192,21 +192,20 @@ def test_C403_fail_1(flake8dir):
 
 
 def test_C404_pass_1(flake8dir):
-    flake8dir.make_example_py(
-        """
-        foo = {x: x for x in range(10)}
-    """
-    )
+    flake8dir.make_example_py("foo = {x: x for x in range(10)}")
+    result = flake8dir.run_flake8()
+    assert result.out_lines == []
+
+
+def test_C404_pass_2(flake8dir):
+    # Previously a false positive
+    flake8dir.make_example_py("foo = dict([x.split('=') for x in ['a=1', 'b=2']])")
     result = flake8dir.run_flake8()
     assert result.out_lines == []
 
 
 def test_C404_fail_1(flake8dir):
-    flake8dir.make_example_py(
-        """
-        foo = dict([(x, x) for x in range(10)])
-    """
-    )
+    flake8dir.make_example_py("foo = dict([(x, x) for x in range(10)])")
     result = flake8dir.run_flake8()
     assert result.out_lines == [
         "./example.py:1:7: C404 Unnecessary list comprehension - rewrite as a "