Repository: spyder-ide/spyder

Issue:
How to suppress errors found by pyflakes in Spyder 4
Problem Description

This is from a post I made at the "Spyder" Google Groups. Carlos recommended I open an issue here. The post is as follows:

I just updated to Spyder 4. Nice job developers-- many of the new features (code folding,...) are very useful.

On much of my existing code files that work fine, pyflakes now identifies errors. They appear as red circles in the left margin of the editor. The error message is "Undefined name 'funcname" (pyflakes E)". The errors are because the imports of functions "funcname" are done in an exec statement; I know, I know, using exec like this isn't good form, but I do have my reasons, and this post is about pyflakes more generally than just this specific type of error.

Here are my questions:

* In the past, other linters or code analysis tools have similarly flagged these same lines for errors, for the same reason. I have been suppressing those error notifications/messages successfully by adding  " # analysis:ignore " to the end of the line. Is there a similar way to suppress the pyflakes errors ("  # analysis:ignore " does not work)? This sort of solution is really what I need, otherwise I will want to turn pyflakes off. I tried "  # NOQA" but it apparently doesn't work. I did some searching around for info on this but came up empty.

* Is there a pyflakes config file somewhere, in which I can suppress this particular error wherever it occurs?
 
* Is there a way to just turn pyflakes off? I could not find it in Preferences.

Secondary question:
* When I hover my mouse over the red circle, a pop-up box appears, not adjacent to the red circle but some distance away to the right, showing the error message. The pop-up also has a red X in the corner as if I could click it to suppress the error. As soon as I move my mouse off the red circle, towards pop-up in order to attempt to click the red X, the pop-up disappears (because it is not directly adjacent to the red circle in the left margin). So... I can never actually get my mouse over the red X. Is this the intended behavior? Is the red X meant to enable clicking to suppress the error, or not? Only curious about this; these are such common errors that I doubt I would ever click each pop-up.

```

## Versions
Python 3.6.7 64-bit | Qt 5.9.7 | PyQt5 5.9.2 | Windows 10 

* Spyder version:      4
* Python version:      3.6.7
* Operating System name/version:   Windows 10

About my Qt, PyQt, and dependencies, I already rolled back to Spyder 3 so in order to get them for Spyder 4 I will need to reestablish a new conda env; if this is truly necessary I can do it.



Discussion:
>When I hover my mouse over the red circle, a pop-up box appears, not adjacent to the red circle but some distance away to the right, showing the error message. The pop-up also has a red X in the corner as if I could click it to suppress the error. As soon as I move my mouse off the red circle, towards pop-up in order to attempt to click the red X, the pop-up disappears (because it is not directly adjacent to the red circle in the left margin). So... I can never actually get my mouse over the red X. Is this the intended behavior? Is the red X meant to enable clicking to suppress the error, or not? Only curious about this; these are such common errors that I doubt I would ever click each pop-up.


The message has no click functionality on it so it is normal for it to disappear.


Thanks for reporting. We'll take a look at this in a future release.
The message has no click functionality on it so it is normal for it to disappear.

Good to know, goanpeca. Thank you.

As you are aware I’m sure, the red X inside a circle means, in the context of many other interfaces and apps, “click here to close the window or popup”. I think this is why I found it confusing.

I understand that here in this present context of Spyder and code analysis pyflakes etc, the same graphic red X means only “code has an error”. But still I wonder if some other graphic could be used in its place, which conveys the message “code has an error” but also is not as easily mistaken for meaning “click here to close the window or popup”.

Just a thought.

>I understand that here in this present context of Spyder and code analysis pyflakes etc, the same graphic red X means only “code has an error”. But still I wonder if some other graphic could be used in its place, which conveys the message “code has an error” but also is not as easily mistaken for meaning “click here to close the window or popup”.

Thanks for the suggestion will try to improve this for the next version
Yes, please fix code analysis.  I have basically turned it off and substituted it with static code analysis as I go.  Is there any way that flake8 can be used internally instead of pycodestyle?
Tried Spyder 4.01 now that it's out. Same problem.  

I'm not knowledgeable about linting or code completion tools but most of what I've read in terms of documentation for flake8 says it should respect the "# noqa" at the end of a line of code (including within Spyder) to suppress all warnings otherwise generated on that line. 

In practice, "# noqa" and "# NOQA" doesn't work for me though-- and others have reported it failing as well in other non-Spyder contexts.

In fact I found flake8-respect-noqa, which I tried, but couldn't get to work (don't know how/where to find/create the config file in which to put the "jobs = 1" line... ?).

Bottom line, because I can't get this flake8 feature to work my only options if I want to be able to take advantage of other Spyder 4 features (instead of sticking with Spyder 3) seem to be:
 
(1) Just turn linting off entirely (Spyder preferences, Completion and linting section, Linting tab, uncheck the box for "Enable basic linting") and live without the helpful/useful warnings I've been relying on for so long in Spyder 3.

(2) Learn to live with annoying warnings that I had easily and conveniently been suppressing (by "analysis:ignore") when using Spyder 3. 

Correct? 
@andfoy, please take a look at this one.
I too would like to see the return of `analysis:ignore` in Spyder 4.

I tend to frequently use the `@` feature of [`pandas.DataFrame.query`](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.query.html) to refer to variables in the environment. I need to suppress these "variable is assigned but not used" false positives.
This is probably something that needs to be solved in

https://github.com/palantir/python-language-server

but @andfoy will take care of it.
I think pyflakes does not support noqa annotations, flake8 should be used instead: https://github.com/PyCQA/pyflakes/issues/431
I have the same question. I need to import module to get side effect, but code analysis tells `%s imported but unused`. I'm using workaround ([explained here](https://pypi.org/project/celery-pool-asyncio/)):
```
import my_cool_module  # noqa
my_cool_module.__package__
```
But it's ugly. Is there any way to suppress this warning?
Hi, is there any update on how to ignore code analysis warnings?
I also used to ignore those with "# analysis:ignore (Dict)" but since upgrading to Spyder 4 it does not seem to work any longer.

Also, I do not know if this would be the appropriate channel to raise this, but it would be great if the first line:
`# -*- coding: utf-8 -*-`
Does not raise a pydocstyle D400 issue.
I have been staying with Spyder 3 until now, because of this issue. With Spyder 3, adding "# analysis:ignore" (to the end of a line for which the linter causes a warning) works to suppress the warning. This means I can benefit from linting, but also suppress those few warnings the linter sends me for parts of my code for which I have a good reason not to change the code in response to the warning.

Today I tried using Spyder 4.1.4 and as far as I can tell there is no way to get the benefit of linting ("basic", not PEP8 code style) and also be able to suppress specific warnings from the linter. Very unfortunate imho. On the bright side, at least now I can successfully turn off "basic linting", so the unhelpful warnings are suppressed, but of course then I lose the benefits of linting.

(Although not really relevant, because I don't use "PEP8 code style linting", I did notice that if I turn that on-- Preferences, Completion and Linting, Code Style tab-- it does appear to allow suppression of specific messages...)

The above posts have covered various topics but just to refocus, here is what specifically would be very helpful to me, so that I could still benefit from linting but also upgrade to Spyder 4 and start taking advantage of its other features:

* A working " # analysis:ignore "  or " # NOQA "  or " # noqa " or equivalent that suppresses warnings the basic linter finds on that line.

* A way to edit a pyflakes config file or other config somewhere, to suppress a specific warning.

From what I can tell, a fix that addresses this is scheduled for 4.2 at earliest. (Btw, I went to check the roadmap but it seems to no longer exist?)

@DanCodigaMWRA, we'll see if we can switch to flake8 from pyflakes for 4.2.0, which provides this functionality.
Thank you Carlos for considering ways to enable a fix for this in 4.2.0, including switching away from flake8 if that is what it takes. 

However, at the flake8 github site, it claims to be "a wrapper around PyFlakes, pycodestyle, and Ned Batchelder's McCabe script", so I'm unsure if flake8 can just be replaced by pyflakes.
 
Should the failure of #analysis:ignore or #noqa to work be posted as an issue at the flake8, PyFlakes, and/or pycodestyle github site(s)? 

The documentation for flake8 clearly states that adding #noqa at the end of a line should suppress its warnings for that line. When in Spyder I'm finding that's not true, so it seems like I should report it as an issue, but it's unclear to me where would be the right place to do so.
> The documentation for flake8 clearly states that adding #noqa at the end of a line should suppress its warnings for that line. When in Spyder I'm finding that's not true

Sorry if I was not clear enough in my previous answer. Right now we're using Pyflakes for linting, which doesn't support the `#noqa` convention (as far as we know). So that's why we're considering to switch to Flake8 for 4.2.
Ok yes d'oh! You wrote it correctly, I read it backwards (and had forgotten the title of this entire issue), sorry. 

So it would be a switch to flake8 from pyflakes. I'm not knowledgeable about linters (let alone linters that spyder could integrate) but some quick superficial searching suggests that if pylint was an option it might be worth considering too. Thanks again.
> if pylint was an option it might be worth considering too

We're also considering to add support for Pylint, but as an advanced linter because it usually requires a config file to be usable (it lints way too many stuff).

Resolving patch:
diff --git a/spyder/plugins/editor/widgets/codeeditor.py b/spyder/plugins/editor/widgets/codeeditor.py
--- a/spyder/plugins/editor/widgets/codeeditor.py
+++ b/spyder/plugins/editor/widgets/codeeditor.py
@@ -95,9 +95,10 @@
 logger = logging.getLogger(__name__)
 
 
+# Regexp to detect noqa inline comments.
+NOQA_INLINE_REGEXP = re.compile(r"#?noqa", re.IGNORECASE)
 
 
-# %% This line is for cell execution testing
 @class_register
 class CodeEditor(TextEditBaseWidget):
     """Source Code Editor Widget based exclusively on Qt"""
@@ -1260,6 +1261,17 @@ def _process_code_analysis(self, underline):
 
             block = document.findBlockByNumber(start['line'])
             data = block.userData()
+
+            # Skip messages according to certain criteria.
+            # This one works for any programming language
+            if 'analysis:ignore' in block.text():
+                continue
+
+            # This only works for Python.
+            if self.language == 'Python':
+                if NOQA_INLINE_REGEXP.search(block.text()) is not None:
+                    continue
+
             if not data:
                 data = BlockUserData(self)
 


Test patch:
diff --git a/spyder/plugins/editor/widgets/tests/test_warnings.py b/spyder/plugins/editor/widgets/tests/test_warnings.py
--- a/spyder/plugins/editor/widgets/tests/test_warnings.py
+++ b/spyder/plugins/editor/widgets/tests/test_warnings.py
@@ -329,3 +329,42 @@ def test_update_warnings_after_closebrackets(qtbot, completions_codeeditor_linti
     qtbot.wait(2000)
     expected = [['D100: Missing docstring in public module', 1]]
     assert editor.get_current_warnings() == expected
+
+
+@pytest.mark.slow
+@pytest.mark.order(2)
+@flaky(max_runs=5)
+@pytest.mark.parametrize(
+    'ignore_comment', ['#noqa', '# NOQA', '# analysis:ignore', '# no-work']
+)
+def test_ignore_warnings_with_comments(
+    qtbot, completions_codeeditor_linting, ignore_comment
+):
+    """
+    Test that ignoring linting messages with inline comments works as
+    expected.
+    """
+    editor, _ = completions_codeeditor_linting
+    editor.textCursor().insertText(
+        f"foo {ignore_comment}\n"
+        "bar\n"
+    )
+
+    if ignore_comment == '# no-work':
+        expected = [
+            ["undefined name 'foo'", 1],
+            ['D100: Missing docstring in public module', 1],
+            ['E261 at least two spaces before inline comment', 1],
+            ["undefined name 'bar'", 2]
+        ]
+    else:
+        expected = [["undefined name 'bar'", 2]]
+
+    # Notify changes.
+    with qtbot.waitSignal(editor.completions_response_signal, timeout=30000):
+        editor.document_did_change()
+
+    # Wait for linting info to arrive
+    qtbot.wait(2000)
+
+    assert editor.get_current_warnings() == expected