bundling config files for linters like ruff and flake8
Project description
python-linters
- bundles ruff and basedpyright into a single poetry-script
- project independent linter configuration (via
ruff.toml
,.flake8
) -> one config to rule them all
use-cases:
- interactively learning python code quality standards via ruff+flake8, see local development workflow
- enforcing minimal quality-standards via a "lint-stage" in a ci-pipeline, see setup for ci-pipeline
0. motivation:
Python is a Bicycle!
- initial idea of python:
Bridge the gap between the shell and C.
see
run-time "safety"
- type and data validation at runtime
- pytests run your code -> runtime
lint-time "safety"
- linting and static type checking
- flake8 already fell down!
more "safety" via shorter feed-back loops
1. install (via poetry)
- in
pyproject.toml
add to dependencies
[tool.poetry.group.dev.dependencies]
python-linters = { version = "<some-version-here>" }
- in your
pyproject.toml
specify the directories that you want to be linted (currentlytests
-dir is added by default) a. viapackages
packages = [ { include = "my_package_name" }, ]
b. or viatool.python-linters
[tool.python-linters] folders_to_be_linted=["my_directory","another_dir/my_sub_package"]
2. local development workflow (before pushing to ci-pipeline)
enhanced "usability" via VSCODE-Extension
- git clone this repo
- install ruff-extension
- add the following to your
settings.json
"ruff.lint.args": [
"--config=<wherever-you-git-cloned-it>/python-linters/python_linters/ruff.toml"
],
three scripts/commands that you can run locally
poetry run fixcode
to let black+isort+ruff "auto-fix" your code -> always have aclean
git-repo before doing this (no uncommitted changes)poetry run pythonlinter
-> to lint your code- example black is not happy -> if you ran
fixcode
black is guaranteed to be happy! - example ruff is not happy
- example flake8 is not happy
- example black is not happy -> if you ran
poetry run addnoqa
to let ruff insert rules-violation-comments to your code
flowchart TD
classDef style0 fill:#ffb3ba
classDef style1 fill:#ffdfba
classDef style2 fill:#ffffba
classDef style3 fill:#baffc9
classDef style4 fill:#bae1ff
op1["start: have a 'clean' repo"]:::style4 --> op2
op2[\"poetry run fixcode\n refactor & git commit"/]:::style1 --> cond9{{"poetry run pythonlinter"}}:::style0
cond9 --> | complains | cond47{{"ruff"}}:::style0
cond47 --> | complains | op51[\"poetry run addnoqa"/]:::style1
op51 --> sub53[\"refactor your code \nOR\n keep/add noqa-comment"/]:::style1
sub53 --> op2
cond47 --> | is happy | cond58{{"pyright"}}:::style0
cond58 --> | complains | sub53
cond58 --> | is happy | sub66["git commit"]
sub66 --> sub80
cond9 --> | is happy | sub80["git push"]:::style3
- write-operations (changing your code):
poetry run fixcode
,poerty run addnoqa
,refactor your code
- read-only-operations:
poetry run pythonlinter
,git commit
,git push
3. setup for ci-pipeline
- if you specified the packages in the
pyproject.toml
and you run just runpoetry run pythonlinter
without any arguments than thepyproject.toml
is getting parsed and specified packages are getting linted
stages:
- lint # lint-stage!
- build
- test
- deploy
...
linting:
stage: lint
extends: .poetry
variables:
DEBIAN_FRONTEND: noninteractive
script:
- poetry install --only dev
- poetry run pythonlinter package_a package_b tests # specify folders to be linted
## OR
- poetry run pythonlinter # to be linted folders are parsed out of the pyproject.toml packages-include section
example outputs
fixcode example
cd <somehwere>/whisper-streaming
poetry run fixcode
Fixing <somehwere>/whisper-streaming/whisper_streaming/post_asr_preparations.py
whisper_streaming/faster_whisper_inference/faster_whisper_inferencer.py:231:30: ARG005 Unused lambda argument: `x`
whisper_streaming/faster_whisper_inference/faster_whisper_inferencer.py:234:5: RET503 Missing explicit `return` at the end of function able to return non-`None` value
whisper_streaming/post_asr_preparations.py:113:5: ANN201 Missing return type annotation for public function `remove_empty_segments`
whisper_streaming/post_asr_preparations.py:113:27: ANN001 Missing type annotation for function argument `whisper_output_segments`
Found 5 errors (1 fixed, 4 remaining).
No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option).
reformatted <somehwere>/whisper-streaming/whisper_streaming/post_asr_preparations.py
reformatted <somehwere>/whisper-streaming/whisper_streaming/faster_whisper_inference/faster_whisper_inferencer.py
All done! ✨ 🍰 ✨
2 files reformatted, 20 files left unchanged.
folders_to_be_linted=['whisper_streaming', 'tests']
pythonlinter ruff is not happy
- complains about
- an unused argument
- a missing return statement
- missing type annotations
poetry run pythonlinter
linter-order: black->ruff->flake8
...
running ruff
whisper_streaming/faster_whisper_inference/faster_whisper_inferencer.py:232:29: ARG005 Unused lambda argument: `x`
whisper_streaming/faster_whisper_inference/faster_whisper_inferencer.py:235:5: RET503 Missing explicit `return` at the end of function able to return non-`None` value
whisper_streaming/post_asr_preparations.py:114:5: ANN201 Missing return type annotation for public function `remove_empty_segments`
whisper_streaming/post_asr_preparations.py:114:27: ANN001 Missing type annotation for function argument `whisper_output_segments`
Found 4 errors.
No fixes available (2 hidden fixes can be enabled with the `--unsafe-fixes` option).
python_linters.run_linters.LinterException: 💩 ruff is not happy! 💩
addnoqa example
- only shows how many noqas it added (
3
) and how many files it left unchanged (22
)
poetry run addnoqa
Added 3 noqa directives.
All done! ✨ 🍰 ✨
22 files would be left unchanged.
folders_tobelinted=['whisper_streaming', 'tests']
addnoqa iteration: 0
- it adds noqas like this one:
def foobar(x): # noqa: ANN001, ANN202
return "whatever"
IDE integration
manual vscode integration
- in
.vscode/tasks.json
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "fixcode",
"type": "shell",
"command": "cd $(cd ${fileDirname} && git rev-parse --show-toplevel) && poetry run fixcode"
},
{
"label": "addnoqa",
"type": "shell",
"command": "cd $(cd ${fileDirname} && git rev-parse --show-toplevel) && poetry run addnoqa"
},
{
"label": "pythonlinter",
"type": "shell",
"command": "cd $(cd ${fileDirname} && git rev-parse --show-toplevel) && poetry run pythonlinter"
}
]
}
manual pycharm integration
alternatives
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
python_linters-0.1.5.tar.gz
(35.0 kB
view details)
File details
Details for the file python_linters-0.1.5.tar.gz
.
File metadata
- Download URL: python_linters-0.1.5.tar.gz
- Upload date:
- Size: 35.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/5.1.0 CPython/3.12.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5ff618bd3d0e6a207675d31c4408566cd7fbef91511cf053b8a83fa48b84be42 |
|
MD5 | 9ea53ba5f24e4ca8eb42a123a19fdffc |
|
BLAKE2b-256 | 2cce8319b363e05000ccc5d7f6bf5c08b9eebd50551732dd5d7ffb2c848391ac |