Package: linthell
LinthellMeta linter to adapt new linter into existing codebase.The purpose of this tool is to be able to introduce new linter into existing codebase without need to fix all existing code right now but in process.Featuresfilter known errors out of any linter outputpre-commit supportconfig file supportplugins system for easy usageparse using regex to adapt new lintersUsageQuickstartpipinstalllinthellflake8# Generate baseline file of all existing errors in projectflake8.|linthellbaseline--baselineflake8-baseline.txt--plugin-nameflake8# Filter flake8 output to remove existing errors# No new errors!flake8.|linthelllint--baselineflake8-baseline.txt--plugin-nameflake8# Introduce new errorecho"import sys">file.py# New error found!flake8.|linthelllint--baselineflake8-baseline.txt--plugin-nameflake8# To get info about specific command or group of commands, use `<command> --help`linthell--helppre-commitsupportLinthell haspre-commitsupport ifpre-commitpackage is installed in the same environment aslinthell.repos:-repo:localhooks:-id:linthell flake8name:linthell flake8language:systementry:linthell pre-commit lint --baseline flake8-baseline.txt --plugin-name flake8 --linter-command "flake8 --config ..."types:[python]# Generate baseline of all files handled by pre-commit hooklinthellpre-commitbaseline--baselineflake8-baseline.txt--plugin-nameflake8--linter-command"flake8 --config ..."--hook-name"linthell flake8"# Run pre-commit agains all files handled by this hookpre-commitrun--all"linthell black"Config filelinthellcan inject params from config file (linthell --config path/to/config.ini).commonsection applies for all commands, command specific config are specified by their name section, for example[lint]. Nested commands are specified via dot. For examplelinthell pre-commit lintreads config from[pre-commit.lint]section.Keys must have same name as argument name of their command function. For example,baseline_fileandlint_format.How it worksLinthell works with linter's output (stdout or stderr, depends on where linter prints it's errors). The first stage is to generate baseline file - list of all known errors in codebase.graph LR
  lo[Linter output] -->|pipe output| linthell[Linthell baseline]
  linthell -->|write baseline into file| baseline[Baseline file]The second stage is to lint. Linter output pipes tolinthell lint, and the command parses linter output and compares found errors with known from generated baseline file. If it founds new errors, linthell outputs them and returns non-zero exit code. If all found errors are known, linthell filter them all and exit with status code 0.graph LR
  lo[Linter output] -->|pipe output| linthell[Linthell lint]
  baseline[Baseline file] -->|read known errors| linthell
  linthell -->|prints new errors| stdoutAdapt new linterLinthell has 2 way to parse linter's output:easy way - using pluginshard way - using regexPluginsPlugins provide the easy way to connect linthell with linter. You just use--plugin-nameargument like this:flake8.|linthellbaseline--plugin-nameflake8
black--check.|linthelllint--plugin-nameblack-checkWrite your own pluginlinthell provides the API for your own plugin. To make a new plugin you should:Create subclass oflinthell.plugins.base.LinthellPluginclass inside your python project and provide implementation for it's abstract methods.Register your subclass as plugin. To do it you need to register your subclass asentry pointwith group namelinthell.plugins, name equals to your plugin name and value equals to full path to use subclass. The way to registerentry pointcan depends on package manager you use (pip,poetry)Example implementation of plugins can be found in linthell source code, linthell provides couple plugins for some python linters.RegexRegex is the first way to connect linthell with linter. It's powerfull enough to use it almost any linter (as long as linter's output can be parsed regex) and can work with unknown linters or custom linter output formats. The downside of regex is they're hard to write.How to use regexLinthell uses--lint-formatoption to define regex for parsing. Suitable regex must contains 3 namedpython-likecapturing groups:path- relative file pathline- line numbermessage- linter messageLinter error is identified by relative path to file, source code line and message.Your regex should matches all message related to an issue because unfiltered issues are printed by the whole match.You can test your regex against linter output withregex101(use Python flavor).