To automatically
- remove unused imports
- order our imports alphabetically (isort)
- detect basic security guidelines using Bandit
- autoformat our code (line length, etc.)
And have other support for development like refactoring and code quality metrics.
- Install pipx
- Install packages with pipx: bandit, pylama, black, isort, autoflake
- Install VS Code extensions: python, pylance, conventional commits, git graph, gitlens, markdown all in one, jumpy, python docstring generator, Sourcery, Code Spell Checker, indent-rainbow
{
"python.formatting.blackPath": "~/.local/bin/black",
"terminal.integrated.tabs.enabled": false,
"diffEditor.ignoreTrimWhitespace": false,
"python.sortImports.path": "~/.local/bin/isort",
"python.linting.banditPath": "~/.local/bin/bandit",
"python.linting.pylamaPath": "~/.local/bin/pylama",
"terminal.integrated.sendKeybindingsToShell": true,
"terminal.integrated.allowChords": false,
"git.enableSmartCommit": true,
"terminal.integrated.fontSize": 12,
"terminal.integrated.lineHeight": 1.2,
"editor.fontSize": 12.5,
"editor.lineHeight": 2,
"editor.minimap.enabled": false,
"python.linting.banditEnabled": true,
"python.linting.pylamaEnabled": true,
"python.formatting.provider": "black",
"editor.formatOnSave": true,
"python.analysis.typeCheckingMode": "basic",
"gitlens.currentLine.enabled": false,
"files.trimTrailingWhitespace": true,
"diffEditor.renderSideBySide": false,
"python.analysis.completeFunctionParens": true,
"editor.tabSize": 3,
"[python]": {
"editor.tabSize": 4,
},
"editor.fontFamily": "'Fira Code', 'Droid Sans Mono', 'monospace', monospace, 'Droid Sans Fallback'",
"editor.fontLigatures": true,
"editor.rulers": [
88
]
}
Notes
- Disable
Format on Paste
--- Black does not support the "Format Selection" command Issue #1883 · microsoft/vscode-python · GitHub - Set
pylance.typeCheckingMode
tostrict
. Or set tobasic
if using 3rd-party libraries with no type-hinting and no time to create your own stubs.
Problem: I am getting Use of assert detected...bandit(B101)
reports on my tests.
Solution:
// settings.json or .code-workspace file
"python.linting.banditArgs": [
"--exclude",
"/tests"
]
This will exclude ALL bandit rules in tests. Issues to specifically exclude only B101 in tests is in GitHub. PyCQA/bandit#346
- Install VS Code extension
pucelle.run-on-save
- In settings.json or .code-workspace file
"runOnSave.statusMessageTimeout": 3000,
"runOnSave.commands": [
{
"match": ".*\\.py$",
"command": "autoflake -i --remove-all-unused-imports --remove-unused-variables ${file}",
"runIn": "backend",
"runningStatusMessage": "Removing unused imports and variables in ${fileBasename}",
"finishStatusMessage": "${fileBasename} cleaned. 🍰 ✨"
},
{
"match": ".*\\.py$",
"command": "isort ${file}",
"runIn": "backend",
"runningStatusMessage": "Sorting imports in ${fileBasename}",
"finishStatusMessage": "Imports in ${fileBasename} has been sorted. 🍰 ✨"
},
]
This assumes isort
and autoflake
has been installed "globally". I installed them using pipx
{
"key": "ctrl+cmd+enter",
"command": "extension.jumpy-word",
"when": "editorTextFocus"
}
In pyproject.toml
,
[tool.isort]
multi_line_output = 3
include_trailing_comma = true
force_grid_wrap = 0
use_parentheses = true
ensure_newline_before_comments = true
line_length = 88
In pylama.ini
[pylama:pycodestyle]
max_line_length = 88
// tasks.json
{
"label": "autoflake",
"type": "process",
"command": "autoflake",
"args": ["-i", "${file}"],
"presentation": {
"reveal": "silent",
"panel": "shared",
"showReuseMessage": false
}
}
// keybindings.json
{
"key": "ctrl+shift+backspace",
"command": "workbench.action.tasks.runTask",
"args": "autoflake"
}
They would rather run a watcher, than have a task run on every save:
Watching tasks should be implemented using watch support of exist task runners. Always starting a task on save is not very performant nor battery friendly. —Run task on save? · Issue #2159 · microsoft/vscode · GitHub
❗️Low rating ❕Not maintained so much in the past year
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
Python Refactor: Sort Imports
or Organize Imports
does not have the same output as running isort {file}
in the command line, for some reason I don't know.
Original:
from my_project.main import app
from fastapi.testclient import TestClient
"Organize Imports" code action:
from fastapi.testclient import TestClient
from my_project.main import app
isort {file}
in the command line:
from fastapi.testclient import TestClient
from my_project.main import app
- To use mccabe, you can run
pylama -l mccabe
manually against the project using the terminal
What actual linters should I use?
💡 Our own mix
- Pylama
- pycodestyle (formerly pep8)
- pydocstyle (formerly pep257)
- PyFlakes - Analyzes programs and detects various errors
- Mccabe - Analytical Checks McCabe complexity1
- Pylint - Checks for errors, tries to enforce a coding standard, looks for code smells
- Radon - Analyzes code for various metrics (lines of code, complexity, and so on)
- gjslint - irrelevant - a javascript linter?
- Bandit
- Black---as formatter
- isort---to sort and organize imports
- Pyright---for typechecking
- autoflake---to remove unused imports and variables
cookiecutter fullstack-fastapi-postgresql
- Python Code Quality: Tools & Best Practices – Real Python
Footnotes
-
Cyclomatic complexity is a software metric used to indicate the complexity of a program. It is a quantitative measure of the number of linearly independent paths through a program's source code. It was developed by Thomas J. McCabe, Sr. in 1976.) ↩