Repository: python/mypy
Pull request: Add test and docs for top level `mypy: disable-error-code` comment
I went with the smallest change possible.
@xitop, please, take a look. Does it make sense to you? :)

Closes #14750

Problem statement:
# mypy: disable-error-code=... usage details not documented 
**Documentation**

(Based on a SO question) To disable multiple error codes in a whole file, none of the "obvious" ways works.
Please document that feature in greater detail.

---

Not OK:

```
# mypy: disable-error-code=misc
# mypy: disable-error-code=attr-defined
```

```
# mypy: disable-error-code=misc
# mypy: disable-error-code=attr-defined
```

The problem here is that the last such line seems to overwrite alle previous ones. Don't know if it is a bug.

---

Also not working:

`# mypy: disable-error-code=misc, attr-defined`

`# mypy: disable-error-code=misc attr-defined`

Here the problem is the syntax.

---

The correct command uses quotes, I wouldn't guess that:

`# mypy: disable-error-code="misc, attr-defined"`

Hints from issue discussion:

Commit message: Address review

Patch to review:
diff --git a/docs/source/common_issues.rst b/docs/source/common_issues.rst
index afb8e7d3ffe1..e6570b7eef5b 100644
--- a/docs/source/common_issues.rst
+++ b/docs/source/common_issues.rst
@@ -186,7 +186,7 @@ Ignoring a whole file
 
 * To only ignore errors, use a top-level ``# mypy: ignore-errors`` comment instead.
 * To only ignore errors with a specific error code, use a top-level
-  ``# mypy: disable-error-code=...`` comment.
+  ``# mypy: disable-error-code="..."`` comment. Example: ``# mypy: disable-error-code="truthy-bool, ignore-without-code"``
 * To replace the contents of a module with ``Any``, use a per-module ``follow_imports = skip``.
   See :ref:`Following imports <follow-imports>` for details.
 
diff --git a/mypy/fastparse.py b/mypy/fastparse.py
index ef1fdf61af2e..56ba330e9629 100644
--- a/mypy/fastparse.py
+++ b/mypy/fastparse.py
@@ -487,11 +487,12 @@ def translate_stmt_list(
             and self.type_ignores
             and min(self.type_ignores) < self.get_lineno(stmts[0])
         ):
-            if self.type_ignores[min(self.type_ignores)]:
+            if ignores := self.type_ignores[min(self.type_ignores)]:
+                joined_ignores = ", ".join(ignores)
                 self.fail(
                     (
                         "type ignore with error code is not supported for modules; "
-                        "use `# mypy: disable-error-code=...`"
+                        f'use `# mypy: disable-error-code="{joined_ignores}"`'
                     ),
                     line=min(self.type_ignores),
                     column=0,
diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test
index 8b3567ab7cf6..124d6952fe5f 100644
--- a/test-data/unit/check-errorcodes.test
+++ b/test-data/unit/check-errorcodes.test
@@ -960,7 +960,11 @@ def f(d: D, s: str) -> None:
 [typing fixtures/typing-typeddict.pyi]
 
 [case testRecommendErrorCode]
-# type: ignore[whatever]  # E: type ignore with error code is not supported for modules; use `# mypy: disable-error-code=...`  [syntax]
+# type: ignore[whatever]  # E: type ignore with error code is not supported for modules; use `# mypy: disable-error-code="whatever"`  [syntax]
+1 + "asdf"
+
+[case testRecommendErrorCode2]
+# type: ignore[whatever, other]  # E: type ignore with error code is not supported for modules; use `# mypy: disable-error-code="whatever, other"`  [syntax]
 1 + "asdf"
 
 [case testShowErrorCodesInConfig]
diff --git a/test-data/unit/check-inline-config.test b/test-data/unit/check-inline-config.test
index 1b2085e33e91..ee847deabd40 100644
--- a/test-data/unit/check-inline-config.test
+++ b/test-data/unit/check-inline-config.test
@@ -210,3 +210,12 @@ enable_error_code = ignore-without-code, truthy-bool
 
 \[mypy-tests.*]
 disable_error_code = ignore-without-code
+
+[case testInlineErrorCodesMultipleCodes]
+# mypy: disable-error-code="truthy-bool, ignore-without-code"
+class Foo:
+    pass
+
+foo = Foo()
+if foo: ...
+42 + "no"  # type: ignore


Code review comments:
diff_hunk: @@ -487,11 +487,12 @@ def translate_stmt_list(
             and self.type_ignores
             and min(self.type_ignores) < self.get_lineno(stmts[0])
         ):
-            if self.type_ignores[min(self.type_ignores)]:
path: mypy/fastparse.py
text: @user1:
We can't use walrus just yet; we still support 3.7

@author:
This is the first time I've used walrus in real code :)
Probably, the last time.