Hide some maybe-no-member Pylint errors - python

The following Python fragment code gets analyzed by Pylint:
if type(result) is array.array:
read = result.tobytes()
... with the following error for the last line:
E:401,22: Instance of 'int' has no 'tobytes' member\
(but some types could not be inferred) (maybe-no-member)
The result variable is received from an external function. How can I change (correct) the code to make Pylint understand? Or how can I tell it that the result of the function can have other types than int? Or how can I tell it to ignore that particular line? (I favor an answer in this order of the questions)

For some reason, pylint doesn't get 'result' may be of the array type (and will be for sure under the 'if' branch). There is currently no way to tell pylint about that, though it will hopefully be possible at some point. So for now, you can only disable the warning for that specific line by adding # pylint: disable=maybe-no-member after the offending statement or right above it. For example:
if type(result) is array.array:
read = result.tobytes() # pylint: disable=maybe-no-member
or
if type(result) is array.array:
# pylint: disable=maybe-no-member
read = result.tobytes()

I disabled all no-member warnings by passing this command line option to pylint
--disable=E1101

While using PyLint you can generate a configuration pylint file using these command in your terminal
$ pylint --generate-rcfile > .pylintrc
the generated file handles the errors and warnings that you have to check.
for the no member in particular you can go to line 560, you can find that it ignored.
this configurations will be applied to all your code files.
and you can edit this configuration file, to meet your requirements.

Instead of
result.tobytes(),
use
getattr(result, 'tobytes')()

Related

How do I tell MyPy that errors about os.path are not errors?

In VS Code, the Problems tab is showing errors when using os.path.join, but the code actually runs. How do I tell MyPy that these are not errors?
I'm working on the Salome platform, and the existing code that runs shows the following as an error: (the specific program is envSalome.py, which is the program that starts the whole salome-meca show):
import os
kernel_root=os.getenv("KERNEL_ROOT_DIR")
kernel_root = os.path.realpath(kernel_root) # this is line 39 in the error below
sys.path[:0]=[os.path.join(kernel_root,"bin","salome")] # this is line 40 in the error below
This program runs without errors.
I've used the python interpreter link at the lower-left corner of VS Code to select the python3.exe that shipped with Salome (and which runs this code without errors).
My problem:
In the "Problems" tab of the Terminal window, MyPy is showing these errors:
Value of type variable "AnyStr" of "realpath" cannot be "Optional[str]" mypy(error) [39, 16]
Argument 1 to "join" has incompatible type "Optional[str]"; expected "Union[str, _PathLike[str]]" mypy(error) [40,29]
os.getenv("KERNEL_ROOT_DIR") may return a str or None. You are not taking that into account and mypy is telling you that you did not cover the case when it returns None.
If you expect the value to always exist in the environment, I suggest using a function which does not return None, e.g.
kernel_root=os.environ["KERNEL_ROOT_DIR"]
MyPy is just doing what it's supposed to do: "type check your code and find common bugs.".
In this case, the error makes sense because os.getenv(key, default=None) returns "the value of the environment variable key if it exists, or default if it doesn’t.". In the event the KERNEL_ROOT_DIR environment variable is not defined, either the os.path realpath or join function will raise an Exception .
If you are 100% sure the KERNEL_ROOT_DIR variable will always exist in the environment where you will run this code, you can tell MyPy to ignore those errors. (We tell MyPy to ignore them because there is no way for MyPy to know about your Salome platform or to understand that they are not errors.)
There are a couple of ways.
Way 1
You can silence that specific error on those specific line/s by adding a special # type: ignore[code] comment on that line:
kernel_root = os.getenv("KERNEL_ROOT_DIR")
kernel_root = os.path.realpath(kernel_root) # type: ignore[type-var]
sys.path[:0] = [os.path.join(kernel_root, "bin", "salome")] # type: ignore[arg-type]
To get the exact MyPy error codes to show up on VS Code's Problems tab, add the following to your settings.json:
"python.linting.mypyArgs": [
"--show-error-codes"
]
If you don't care about finding the specific error/s and you just want to silence all errors for that line, you can just drop the [code] part and just do # type: ignore.
Way 2
If you can isolate those lines into a specific module, you can tell MyPy to ignore all errors for that specific module. This can be done by creating a MyPy configuration file, which is a mypy.ini or a .mypy.ini or a setup.cfg file placed at the root of your workspace, then adding the ignore_errors option.
For example, if those lines are part of a module config.py inside the package myproject, having this MyPy configuration file will silence those errors:
[mypy-myproject.config]
ignore_errors = True
If you want to ignore only specific error codes from the configuration file, there is the disable_error_code option, but it is a global setting only:
[mypy]
disable_error_code = type-var
The sample above ignores one of the errors:
But note that this also ignores other errors on other lines on that same module.

pylint disabling a single line of code just produces another pylint error

The documentation in section 4.1 clearly states:
https://pylint.readthedocs.io/en/latest/faq.html#message-control
4.1 Is it possible to locally disable a particular message?
Yes, this feature has been added in Pylint 0.11. This may be done by adding “#pylint: disable=some-message,another-one” at the desired block level or at the end of the desired line of code
Great! but it doesn't work. Boo.
I get the the following pylint error for the following line of code
W: 26, 2: Redefining built-in 'zip' (redefined-builtin)
try:
from itertools import izip as zip # pylint: disable=bad-builtin
except ImportError:
pass
But pylint just complains even louder about my attempt to shut it up:
E: 26, 0: Bad option value 'bad-builtin' (bad-option-value)
I've also tried the error code # pylint: disable=W0141, that also produces a similar error.
Any idea what I'm doing wrong?
I have been in a similar situation.
Unsolvable pylint issue
class A:
pass
There are many warnings in pylint for the code above, but I want to talk about old-style-class.
In Python 2.7, you will get an old-style-class error.
Of course, you can change your code like this:
class A(object):
pass
However, you will receive a useless-object-inheritance warning in Python 3.
If you are writing a package compatible with python 2.7 and 3 and using pylint, then you are down.
Unavoidable bad-option-value
Yes, if it is accepted to disable either of old-style-class or useless-object-inheritance in a comment, you can go further.
In Python 2.7:
# pylint: disable=old-style-class
class A:
pass
In Python 3:
# pylint: disable=useless-object-inheritance
class A(object):
pass
Eventually, you will get a bad-option-value, just the same as this question.
Disable bad-option-value
I have tried, but bad-option-value can not be disabled locally in this case.
I have to disable bad-option-value in a pylint configuration file, like .pylintrc.
[TYPECHECK]
disable=bad-option-value
Note: My pylint version is 1.9.4 in python 2.7, 2.2.2 in python 3.
Ah, simple answer, it should be # pylint: disable=bad-option-value which is presented in the error message in parenthesis:
E: 26, 0: Bad option value 'bad-builtin' (bad-option-value)
When you get this message:
W: 26, 2: Redefining built-in 'zip' (redefined-builtin)
You have to disable the exact error message you are getting (the one in parenthesis):
try:
from itertools import izip as zip # pylint: disable=redefined-builtin
except ImportError:
pass
That seems to work fine in pylint 2.5.
It can be annoying if you are testing with multiple versions of python or different venvs and the same code base and you get different errors. Be sure you fix the version to one version across all your builds/tests. It sounds like that may have happened here (not sure where you got bad-builtin from).

Pylint: overriding max-line-length in individual file

Is it possible to change max-line-length settings for one file out of a project (while performing all other checks defined in rc file on it)?
Ideally, it should behave like inline pylint: disable=x comments.
I've tried putting this line at the module level:
# pylint: max-line-length=240
PyLint failed to recognize it:
my_file.py:15: [E0011(unrecognized-inline-option), ] Unrecognized file option 'max-line-length
Edit: I know I can disable line-too-long check entirely, but to be honest I'd like to avoid doing so, just in case anyone would try to extend this module and add lines even longer than they are now.
You can create .pylintrc file in your python script to overwrite pylint settings and put inside
[FORMAT]
max-line-length=240
edit 240 based on your choice.
According to the doc, I think you cannot modify the pylint config in line.
but you can disable the warning for only one or few line(s) with # pylint: disable=line-too-long:
# disable for only one line
ridiculously_long_variable_name = "this is not a ridiculously long and useless python line" # pylint: disable=line-too-long
# disable for few (or more) lines
# pylint: disable=line-too-long
ridiculously_long_variable_name = "this is not a ridiculously long and useless python line"
# pylint: enable=line-too-long
pylint --max-line-length=240
works for me.
You can pass the additional as below:
C:\Python27\Scripts\pylint.exe --max-line-length=240 <PATH TO FILE>

Disable pylint execution on a section of code or function

I am using pylint 0.27 with python 2.7.3. Pylint has a known bug which hits when it analyses code having a .next() call. As given in http://www.logilab.org/122793 link, it fails with the given traceback.
I cannot change my python and pylint versions but I would like to workaround this problem by disabling pylint on the piece of code that has .next() call by adding a #pylint: MAGIC comment in my code.
I could find support for disabling pylint checking on a file using #pylint: skip-file but I am interested at doing this at function level or rather at line level.
Any other workarounds are also welcomed!
You can accomplish this by adding the pylint comment as the first line of the function body like so:
def wont_raise_pylint():
# pylint: disable=W0212
some_module._protected_member()
some_module._protected_member()
def will_still_raise_pylint():
some_module._protected_member()
When I refactor code, I wrap the portion I have yet to touch
in a class ToDo and start that class with a directive
to ignore all messages. At the end of the class the directive
goes out of scope. MWE:
def unused_variable(foo=''):
"generate W0613"
class ToDo:
#pylint: disable = E, W, R, C
#disables W0613 and E0213
def unused_variable(foo=''):
"generate W0613 and E0213"
def main(foo=''):
"generate W0613"
To disable pylint entirely for a function without needing to enumerate each pylint violation code, specify all to the disable, eg:
def foo():
# pylint: disable=all
"""You put the disable right under the function signature
to disable pylint for the entire function scope.
"""
pass
Unfortunatly you won't be able to locally avoid the error you encounter.
One could expect to locate in the source code the offending piece of code, and then locally disable the involved message(s), but this won't work because it will still be run. This is because when locally disabling a message, the code detecting this message is run, only the message isn't be emitted in the end.
However, it may work if you globally disable this message (depending on the way it's implemented). In your case it seems unfortunatly that you would have to skip the whole 'logging' checker.
To sum up, to avoid your traceback you may either:
locally use pylint: skip-file, in which case every pylint's features will be activated but the whole offending file will be skipped
globally disable the 'logging' checker (--disable=logging), in which case the whole code (including the offending file) will be checked but without the 'logging' checker messages

Same python file with pylint disable=<something> and /usr/bin/env python

Question is simple, I have two lines in my Python script:
# pylint: disable=C0301, W0212
#!/usr/bin/env python
Both of them have to be on the first line otherwise they will not work.
How do you suggest I resolve this?
The following goes on the first line:
#!/usr/bin/env python
Pylint messages can go on any line. As the documentation says:
Is it possible to locally disable a particular message? This may be done by adding “#pylint: disable=W0123,E4567” at the desired block level or at the end of the desired line of code
So the message needs to be at the same block level (so the second line would work as well as that's the same block / scope). Furthermore the documentation says:
Is there a way to disable a message for a particular module only? Yes, you can disable or enable (globally disabled) messages at the module level by adding the corresponding option in a comment at the top of the file:
So it doesn't say: "first line of the file"; as long as the disable message is at the top of the file then it's fine.
Pylint disable comments do not need to be in the top line to work.

Categories