Repository: PyCQA/flake8-bugbear

Issue:
B033 should say what the duplicate set item is
I got an error `taxonomy/parsing.py:87:11: B033 Sets should not contain duplicate items. Duplicate items will be replaced with a single item at runtime.`

Now, part of this set looks like this:

```
            "İ",
            "À",
            "Á",
            "Ć",
            "Á",
            "Å",
            "Ä",
```

I think it's the `Á`, but it would have been more helpful if flake8-bugbear had told me directly.

I'll work on a fix.

Comments:

Patch:
diff --git a/bugbear.py b/bugbear.py
index 4717a4f..eff5c58 100644
--- a/bugbear.py
+++ b/bugbear.py
@@ -1351,12 +1351,16 @@ class BugBearVisitor(ast.NodeVisitor):
             self.errors.append(B032(node.lineno, node.col_offset))
 
     def check_for_b033(self, node):
-        constants = [
-            item.value
-            for item in filter(lambda x: isinstance(x, ast.Constant), node.elts)
-        ]
-        if len(constants) != len(set(constants)):
-            self.errors.append(B033(node.lineno, node.col_offset))
+        seen = set()
+        for elt in node.elts:
+            if not isinstance(elt, ast.Constant):
+                continue
+            if elt.value in seen:
+                self.errors.append(
+                    B033(elt.lineno, elt.col_offset, vars=(repr(elt.value),))
+                )
+            else:
+                seen.add(elt.value)
 
 
 def compose_call_path(node):
@@ -1757,8 +1761,8 @@ B032 = Error(
 
 B033 = Error(
     message=(
-        "B033 Sets should not contain duplicate items. Duplicate items will be replaced"
-        " with a single item at runtime."
+        "B033 Set should not contain duplicate item {}. Duplicate items will be"
+        " replaced with a single item at runtime."
     )
 )
 
@@ -1817,7 +1821,7 @@ B907 = Error(
 )
 B908 = Error(
     message=(
-        "B908 assertRaises-type context should not contains more than one top-level"
+        "B908 assertRaises-type context should not contain more than one top-level"
         " statement."
     )
 )


Test patch:
diff --git a/tests/b033.py b/tests/b033.py
index 4738344..8ce42c9 100644
--- a/tests/b033.py
+++ b/tests/b033.py
@@ -1,6 +1,6 @@
 """
 Should emit:
-B033 - on lines 6-12
+B033 - on lines 6-12, 16, 18
 """
 
 test = {1, 2, 3, 3, 5}
@@ -10,6 +10,13 @@ test = {None, True, None}
 test = {3, 3.0}
 test = {1, True}
 test = {0, False}
+multi_line = {
+    "alongvalueeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
+    1,
+    True,
+    0,
+    False,
+}
 
 test = {1, 2, 3, 3.5, 5}
 test = {"a", "b", "c", "d", "e"}
diff --git a/tests/test_bugbear.py b/tests/test_bugbear.py
index 73e7b19..9047a41 100644
--- a/tests/test_bugbear.py
+++ b/tests/test_bugbear.py
@@ -493,13 +493,15 @@ class BugbearTestCase(unittest.TestCase):
         bbc = BugBearChecker(filename=str(filename))
         errors = list(bbc.run())
         expected = self.errors(
-            B033(6, 7),
-            B033(7, 7),
-            B033(8, 7),
-            B033(9, 7),
-            B033(10, 7),
-            B033(11, 7),
-            B033(12, 7),
+            B033(6, 17, vars=("3",)),
+            B033(7, 23, vars=("'c'",)),
+            B033(8, 21, vars=("True",)),
+            B033(9, 20, vars=("None",)),
+            B033(10, 11, vars=("3.0",)),
+            B033(11, 11, vars=("True",)),
+            B033(12, 11, vars=("False",)),
+            B033(16, 4, vars=("True",)),
+            B033(18, 4, vars=("False",)),
         )
         self.assertEqual(errors, expected)