Hot take: PyLint is definitely good!
“PyLint can save your life” is an exaggeration, however not as a lot as you may suppose! PyLint can preserve you from actually actually arduous to search out and complex bugs. At worst, it could prevent the time of a take a look at run. At greatest, it could assist you keep away from difficult manufacturing errors.
The good
I’m embarrassed to say how frequent this may be. Naming exams is perpetually bizarre: Nothing cares concerning the identify, and there is usually not a pure identify to be discovered. For occasion, have a look at this code:
def test_add_small():
# Math, am I proper?
assert 1 + 1 == 3
def test_add_large():
assert 5 + 6 == 11
def test_add_small():
assert 1 + 10 == 11
The take a look at works:
collected 2 objects
take a look at.py ..
2 handed
But this is the kicker: If you override a reputation, the testing infrastructure fortunately skips over the take a look at!
In actuality, these information may be tons of of traces lengthy, and the individual including the brand new take a look at may not concentrate on all of the names. Unless somebody is take a look at output fastidiously, the whole lot seems to be superb.
Worst of all, the addition of the overriding take a look at, the breakage of the overridden take a look at, and the downside that ends in prod is perhaps separated by days, months, and even years.
PyLint finds it
But like a superb buddy, PyLint is there for you.
take a look at.py:8:0: E0102: operate already outlined line 1
(function-redefined)
The dangerous
Like a 90s sitcom, the extra you get into PyLint, the extra it turns into problematic. This is totally affordable code for a listing modeling program:
"""Inventory abstractions"""import attrs
@attrs.outline
class Laptop:
"""A laptop"""
ident: str
cpu: str
It appears that PyLint has opinions (in all probability fashioned within the 90s) and isn’t afraid to state them as info:
$ pylint laptop computer.py | sed -n '/^laptop computer/s/[^ ]*: //p'
R0903: Too few public strategies (0/2) (too-few-public-methods)
The ugly
Ever needed so as to add your individual unvetted opinion to a software utilized by hundreds of thousands? PyLint has 12 million month-to-month downloads.
“People will just disable the whole check if it’s too picky.” —PyLint problem 6987, July third, 2022
The angle it takes in direction of including a take a look at with doubtlessly many false positives is…“eh.”
Making it give you the results you want
PyLint is ok, however it’s essential work together with it fastidiously. Here are the three issues I like to recommend to make PyLint give you the results you want.
1. Pin it
Pin the PyLint model you utilize to keep away from any surprises!
In your .toml
file:
[project.optional-dependencies]
pylint = ["pylint"]
In your code:
from unittest import mock
This corresponds with code like this:
# noxfile.py
...
@nox.session(python=VERSIONS[-1])
def refresh_deps(session):
"""Refresh the requirements-*.txt files"""
session.set up("pip-tools")
for deps in [..., "pylint"]:
session.run(
"pip-compile",
"--extra",
deps,
"pyproject.toml",
"--output-file",
f"requirements-{deps}.txt",
)
2. Default deny
Disable all checks. Then allow ones that you just suppose have a excessive value-to-false-positive ratio. (Not simply false-negative-to-false-positive ratio!)
# noxfile.py
...
@nox.session(python="3.10")
def lint(session):
information = ["src/", "noxfile.py"]
session.set up("-r", "requirements-pylint.txt")
session.set up("-e", ".")
session.run(
"pylint",
"--disable=all",
*(f"--enable={checker}" for checker in checkers)
"src",
)
3. Checkers
These are a number of the ones I like. Enforce consistency within the venture, keep away from some apparent errors.
checkers = [
"missing-class-docstring",
"missing-function-docstring",
"missing-module-docstring",
"function-redefined",
]
Using PyLint
You can take simply the nice components of PyLint. Run it in CI to maintain consistency, and use the best worth checkers.
Lose the dangerous components: Default deny checkers.
Avoid the ugly components: Pin the model to keep away from surprises.