Skip to content

Instantly share code, notes, and snippets.

@jlmelville
Last active December 13, 2023 08:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jlmelville/9d4dcc1470fbbdc6477e8ebd6aeb672b to your computer and use it in GitHub Desktop.
Save jlmelville/9d4dcc1470fbbdc6477e8ebd6aeb672b to your computer and use it in GitHub Desktop.
Setting up Python linting with VS Code

I set up my linters for use with VS Code, so I only use the linting tools that can be integrated into the Problems tab, but these can be used from the command line. I have attempted to avoid having different tools give duplicate warnings, but this is a work in progress. The VS code settings.json is at https://gist.github.com/jlmelville/74d8fe778b0d89574e82ffe47c1e49ae.

Create a linting-requirements.txt file:

# this also installs pylint and pycodestyle
bandit
prospector[with_pyroma]
flake8
black

Due to various clashing version requirements, I then do a silly dance around uninstalling and re-installing, so you may as well create a bash script to do all this, e.g. install-linters.sh:

#!/bin/bash
pip3 install -r linting-requirements.txt
pip3 uninstall --yes pycodestyle
pip3 install pycodestyle
pip3 uninstall --yes flake8
pip3 install flake8

I put the following configuration files in a lint subdirectory:

.flake8:

[flake8]
# Turn on everything
# Default: E,F,W,C90             
# E***/W***: pep8 errors and warnings
# F***: PyFlakes codes 
# C9**: McCabe complexity plugin mccabe
# N8**: Naming Conventions plugin pep8-naming
select = E, W, F, C, N

ignore = E203, E401, E402, E501, E722, W292, W391, W503, W605, F401, F402, F811, F821, F841, N803
# E203 Whitespace before ':' also hits slices, e.g. '1 : 10'.
# E401 Multiple imports on one line: handled by pylint multiple-imports
# E402 Module level import not at top of file: pylint wrong-import-position handles this.
# E501 Line too long (we are using black to enforce this).
# E722 Do not use bare 'except': pylint bare-except handles this
# W292 No newline at end of file: dealt with by pylint
# W391 Blank line at end of file: duplicates pylint trailing-newlines
# W503 Line break occurred before a binary operator
#   PEP8 flipped on this: https://github.com/python/peps/commit/c59c4376ad233a62ca4b3a6060c81368bd21e85b
# W605 Invalid escape sequence: dealt with by pylint anomalous-backslash-in-string
# F401 module imported but unused: false positive when a top-level __init__ wants to export names from submodules.
# F402 shadowed loop variable: duplicates pylint redefined-outer-name
# F811 redefinition: duplicates pylint function-refined
# F821 undefined name: dealt with by pylint undefined-variable
# F841 local variable is assigned to but never used: pylint unused-variable handles this
# N803 Argument name should be lower case

# Other ignored rules I've seen
# E266 Too many leading '#' for block comment 
# F403 'from module import *' used; unable to detect undefined names

max-line-length = 88

# McCabe Complexity
max-complexity = 20

.pylintrc:

[MESSAGES CONTROL]

# disable reasons 
# bad-continuation: incompatible with black formatting https://github.com/python/black/issues/48
# locally-disabled: definitely want to locally turn off some linting
# line-too-long, trailing-whitespace, literal-comparison: handled by flake8
# missing-docstring: handled by pycodestyle
disable = bad-continuation, locally-disabled, line-too-long, trailing-whitespace, missing-docstring, literal-comparison,
too-many-instance-attributes, too-many-public-methods, too-many-arguments, too-many-locals, too-many-branches, invalid-name

[BASIC]

# Uncomment and add short variables names you think should be allowed (e.g. i, j, n)
#good-names=

[FORMAT]

max-line-length=88

[TYPECHECK]

# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=np.*,numba.*,iloc,loc

The above .pylintrc isn't too strict. If you want it to complain more, re-enable the too-many-* warnings that are disabled above.

bandit.yml:

exclude_dirs:
 - tests
 - .eggs
# input
skips:
 - B322

.prospector.yaml:

strictness: veryhigh
doc-warnings: false
test-warnings: true
pyroma:
  run: true
vulture:
  run: false
dodgy:
  run: true
pyflakes:
  run: false
pylint:
  run: false
pep8:
  run: false
mccabe:
  run: false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment