{"id":20285451,"url":"https://github.com/mramshaw/python-linters","last_synced_at":"2025-12-02T01:04:46.902Z","repository":{"id":92905868,"uuid":"128556318","full_name":"mramshaw/Python-Linters","owner":"mramshaw","description":"Linters for Python","archived":false,"fork":false,"pushed_at":"2020-06-09T16:50:53.000Z","size":96,"stargazers_count":1,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-14T08:12:10.723Z","etag":null,"topics":["black","lint","linter","linting","pep8","pycodestyle","pydocstyle","pylint","python","python3"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mramshaw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-07T18:22:05.000Z","updated_at":"2024-03-07T00:10:28.000Z","dependencies_parsed_at":"2023-04-29T00:53:45.728Z","dependency_job_id":null,"html_url":"https://github.com/mramshaw/Python-Linters","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPython-Linters","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPython-Linters/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPython-Linters/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mramshaw%2FPython-Linters/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mramshaw","download_url":"https://codeload.github.com/mramshaw/Python-Linters/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241780465,"owners_count":20019058,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["black","lint","linter","linting","pep8","pycodestyle","pydocstyle","pylint","python","python3"],"created_at":"2024-11-14T14:26:45.801Z","updated_at":"2025-12-02T01:04:46.861Z","avatar_url":"https://github.com/mramshaw.png","language":"Python","readme":"# Python Linters\n\nIt's probably a best practice to use linters, __especially__ with interpreted languages. By which I mean javascript,\nnode.js, PHP or Python (and probably others).\n\nIf you are a beginner linters will generally catch any ___n00b___ errors - which will probably save everyone some\ntime and/or embarrassment. And for most people they will often catch potential problems that were not spotted. For\nanyone who frequently uses different languages, they suggest a style and idiom appropriate for the language. Often\nthese seem to be very minor things - but they may have specific meanings in any particular language. For instance,\nwhether or not a variable or function is __capitalised__ can be significant - but often it will simply be such\nuseful suggestions as using underscores instead of hyphens, and whether or not camel-case is appropriate.\n\nAll in all, it's generally a best practice to keep code as idiomatic as possible. And linters are great for this.\n\nHere I am trying out [pycodestyle](http://pycodestyle.pycqa.org/en/latest/), [pylint](https://www.pylint.org/),\n[pydocstyle](https://github.com/PyCQA/pydocstyle), and [Black](https://github.com/psf/black).\n\n`pycodestyle` and `pylint` are ___code linters___ whereas `pydocstyle` is a ___documentation linter___.\n\n`Black`, on the other hand, is a ___code formatter___ (along the lines of `gofmt`). These can reduce the pain\nof ___code reviews___ as there are fewer arguments about the proper way of formatting code to ensure ___readability___.\nAlso, one of Black's claims is that:\n\n\u003e _Black_ makes code review faster by producing the smallest diffs possible.\n\n[Which sounds pretty useful.]\n\n## Contents\n\nThe contents are as follows:\n\n* [pycodestyle](#pycodestyle)\n    * [Installing pycodestyle](#installing-pycodestyle)\n    * [Verify pycodestyle version](#verify-pycodestyle-version)\n    * [Running pycodestyle](#running-pycodestyle)\n* [pylint](#pylint)\n    * [Installing pylint](#installing-pylint)\n    * [Verify pylint version](#verify-pylint-version)\n    * [Running pylint](#running-pylint)\n    * [pyreverse](#pyreverse)\n* [An example of using `pylint` and `pycodestyle`](#an-example-of-using-pylint-and-pycodestyle)\n* [pydocstyle](#pydocstyle)\n    * [Installing pydocstyle](#installing-pydocstyle)\n    * [Verify pydocstyle version](#verify-pydocstyle-version)\n    * [Running pydocstyle](#running-pydocstyle)\n* [An example of using `pydocstyle`](#an-example-of-using-pydocstyle)\n* [Black](#black)\n    * [Installing Black](#installing-black)\n    * [Verify Black version](#verify-black-version)\n    * [Running Black](#running-black)\n* [To Do](#to-do)\n\n## pycodestyle\n\nThis is probably the linter to use, specifically for the `PEP 8` integration.\n\nIn fact, it was formerly called `pep8`.\n\nHowever, I still like [pylint](#pylint) quite a lot, for one thing it will complain if a file is not named in a\nPythonic way. And they've gamified `pylint` pretty well, it's oddly satisfying to clean up formatting and see the\ncode score improve.\n\n#### Installing pycodestyle\n\nRun the following command:\n\n    $ pip3 install --user pycodestyle\n\n#### Verify pycodestyle version\n\nVerify the version as follows:\n\n    $ pycodestyle --version\n\n#### Running pycodestyle\n\nRun `pycodestyle` as follows:\n\n    $ pycodestyle xxxxx.py\n\nLimit `pycodestyle` to the first occurrence of each linting error:\n\n    $ pycodestyle --first xxxxx.py\n\nShow the offending source code and the relevant text from PEP 8:\n\n    $ pycodestyle --show-source --show-pep8 xxxxx.py\n\n## pylint\n\nI'm kind of a sucker for UML and pylint ships with an interesting-looking tool ([pyreverse](#pyreverse))\nwhich I wanted to try out.\n\nFor anyone preparing to migrate code from Python 2 to Python 3, `pylint` will highlight potential problem areas.\n\n#### Installing pylint\n\nRun the following command:\n\n    $ pip3 install --user pylint\n\n#### Verify pylint version\n\nVerify the version as follows:\n\n    $ pylint --version\n\n#### Running pylint\n\nRun `pylint` as follows:\n\n    $ pylint xxxxx.py\n\nFor any obsessive-compulsives, `pylint` provides a code score (and monitors progress).\n\nIgnore certain linting rules as follows:\n\n    $ pylint --disable=C0103 bad-python.py\n\nIn the example above, we are ignoring snake_case naming style - say to conform to\n`benchmark` or `pytest` coding conventions. We could also achieve the same result\n by annotating all of our offending code blocks as follows:\n\n```python3\n#!/usr/bin/env python3\n\n# pylint: disable=C0103\n\n\"\"\"\nAn example of Python code that will fail linting.\n\"\"\"\n```\n\n`pylint` has some nice features - it is possible to disable a rule by it's __name__\nas well as by it's __key__. And it is also possible to disable a rule (or rules)\nfor a __single line of code__.\n\nFor example, `pylint` will object to the following line of Django code:\n\n```python3\nfrom . import views\n```\n\nIf this line of code is annotated as follows, `pylint` will be happy:\n\n```python3\nfrom . import views  # pylint: disable=relative-beyond-top-level\n```\n\nNote that we did not have to look up the __key__ value for __relative-beyond-top-level__.\n\n#### pyreverse\n\nRun `pyreverse` as follows:\n\n    $ pyreverse -f PUB_ONLY -o png -p \u003cpackage\u003e *.py\n\n[The default output format is `dot`, here we are specifying the graphic format `png`.]\n\nFor `cpuinfo` this looks as follows:\n\n```bash\n$ cd ~/.local/lib/python3.6/site-packages/cpuinfo\n$ pyreverse -f PUB_ONLY -o png -p cpuinfo *.py\nparsing cpuinfo.py...\nparsing __init__.py...\nparsing __main__.py...\n$\n```\n\nThe results look as follows:\n\n![cpuinfo package](images/packages_cpuinfo.png)\n\nAnd:\n\n![cpuinfo classes](images/classes_cpuinfo.png)\n\n## An example of using `pylint` and `pycodestyle`\n\nHere we will use a quick test case:\n\n```bash\n$ python3 bad-python.py\nThis code does not follow 'pylint' file naming conventions!\nThis code does not follow 'pycodestyle' coding conventions!\n$\n```\n\nThese linters flag different things, so it's probably worth running both:\n\n```bash\n$ pycodestyle *.py\nbad-python.py:10:80: E501 line too long (85 \u003e 79 characters)\nbad-python.py:12:1: W391 blank line at end of file\n$\n```\n\nAnd:\n\n```bash\n$ pylint *.py\n************* Module bad-python\nbad-python.py:12:0: C0305: Trailing newlines (trailing-newlines)\nbad-python.py:1:0: C0103: Module name \"bad-python\" doesn't conform to snake_case naming style (invalid-name)\nbad-python.py:7:0: W0105: String statement has no effect (pointless-string-statement)\nbad-python.py:10:0: W0105: String statement has no effect (pointless-string-statement)\n\n------------------------------------------------------------------\nYour code has been rated at 0.00/10 (previous run: 0.00/10, +0.00)\n\n$\n```\n\nOr (disabling checks for snake_case naming):\n\n```bash\n$ pylint --disable=C0103 *.py\n************* Module bad-python\nbad-python.py:12:0: C0305: Trailing newlines (trailing-newlines)\nbad-python.py:7:0: W0105: String statement has no effect (pointless-string-statement)\nbad-python.py:10:0: W0105: String statement has no effect (pointless-string-statement)\n\n------------------------------------------------------------------\nYour code has been rated at 2.50/10 (previous run: 0.00/10, +2.50)\n\n$\n```\n\n[Note that the __code score__ has increased.]\n\n## pydocstyle\n\nWhile not strictly a linter, having well-formed docstrings allows for the use of automated documentation generators.\n\n#### Installing pydocstyle\n\nRun the following command:\n\n    $ pip install --user pydocstyle\n\n#### Verify pydocstyle version\n\nVerify the version as follows:\n\n    $ pydocstyle --version\n\n#### Running pydocstyle\n\nRun `pydocstyle` as follows:\n\n    $ pydocstyle xxxxx.py\n\nThere are a number of configurable options. For instance, it's possible to list PEP257 conventions to ignore as follows:\n\n    $ pydocstyle xxxxx.py --ignore=D210,D213,D401\n\nA full list of pydocstyle errors may be found [here](http://www.pydocstyle.org/en/latest/error_codes.html).\n\n[My personal feeling is that `pydocstyle` should be run from time to time, but is\n probably a bit too finicky for regular use. Your mileage may vary.]\n\n## An example of using `pydocstyle`\n\nAgain, we will use our test case:\n\n```bash\n$ pydocstyle *.py\nbad-python.py:3 at module level:\n        D200: One-line docstring should fit on one line with quotes (found 3)\n$\n```\n\nUseful for anyone not too familiar with what `pythonic` means!\n\n## Black\n\nWhile not strictly a linter, having well-formatted code will save everyone a lot of time.\n\n#### Python 3.6\n\nNote that `black` requires __Python 3.6__ or greater. Verify the version of `python` as follows:\n\n```bash\n$ python3 -V\n...\n$\n```\n\nIf this is less than __3.6__ there is always [Dockerized python](http://hub.docker.com/_/python):\n\n```bash\n$ docker pull python:3.6\n3.6: Pulling from library/python\nc7b7d16361e0: Pull complete\nb7a128769df1: Pull complete\n1128949d0793: Pull complete\n667692510b70: Pull complete\nbed4ecf88e6a: Pull complete\n94d1c1cbf347: Pull complete\nf59f6b55cd0f: Pull complete\n6513a2441bbb: Pull complete\n792e28117005: Pull complete\nDigest: sha256:52f872eae9755743c9494e0e3cf02a47d34b42032cab1e5ab777b30c3665d5f1\nStatus: Downloaded newer image for python:3.6\ndocker.io/library/python:3.6\n$\n```\n\n#### Installing Black\n\nRun the following command:\n\n    $ pip3 install --user black\n\nIf using docker,  this looks as follows:\n\n```bash\n$ docker run -v $(pwd):/app -w /app --rm -it python:3.6 /bin/bash\nroot@7ebc68fc6b42:/app# pip install black\nCollecting black\n  Downloading https://files.pythonhosted.org/packages/fd/bb/ad34bbc93d1bea3de086d7c59e528d4a503ac8fe318bd1fa48605584c3d2/black-19.10b0-py36-none-any.whl (97kB)\n     |████████████████████████████████| 102kB 2.0MB/s\nCollecting toml\u003e=0.9.4\n  Downloading https://files.pythonhosted.org/packages/a2/12/ced7105d2de62fa7c8fb5fce92cc4ce66b57c95fb875e9318dba7f8c5db0/toml-0.10.0-py2.py3-none-any.whl\nCollecting attrs\u003e=18.1.0\n  Downloading https://files.pythonhosted.org/packages/a2/db/4313ab3be961f7a763066401fb77f7748373b6094076ae2bda2806988af6/attrs-19.3.0-py2.py3-none-any.whl\nCollecting regex\n  Downloading https://files.pythonhosted.org/packages/e3/8e/cbf2295643d7265e7883326fb4654e643bfc93b3a8a8274d8010a39d8804/regex-2019.11.1-cp36-cp36m-manylinux1_x86_64.whl (643kB)\n     |████████████████████████████████| 645kB 4.5MB/s\nCollecting appdirs\n  Downloading https://files.pythonhosted.org/packages/56/eb/810e700ed1349edde4cbdc1b2a21e28cdf115f9faf263f6bbf8447c1abf3/appdirs-1.4.3-py2.py3-none-any.whl\nCollecting typed-ast\u003e=1.4.0\n  Downloading https://files.pythonhosted.org/packages/31/d3/9d1802c161626d0278bafb1ffb32f76b9d01e123881bbf9d91e8ccf28e18/typed_ast-1.4.0-cp36-cp36m-manylinux1_x86_64.whl (736kB)\n     |████████████████████████████████| 737kB 6.0MB/s\nCollecting click\u003e=6.5\n  Downloading https://files.pythonhosted.org/packages/fa/37/45185cb5abbc30d7257104c434fe0b07e5a195a6847506c074527aa599ec/Click-7.0-py2.py3-none-any.whl (81kB)\n     |████████████████████████████████| 81kB 7.1MB/s\nCollecting pathspec\u003c1,\u003e=0.6\n  Downloading https://files.pythonhosted.org/packages/7a/68/5902e8cd7f7b17c5879982a3a3ee2ad0c3b92b80c79989a2d3e1ca8d29e1/pathspec-0.6.0.tar.gz\nBuilding wheels for collected packages: pathspec\n  Building wheel for pathspec (setup.py) ... done\n  Created wheel for pathspec: filename=pathspec-0.6.0-cp36-none-any.whl size=26671 sha256=f19ceb5e9213d565a296cf859705ecf2998234a3c3b8e7799641121c601ad3ce\n  Stored in directory: /root/.cache/pip/wheels/62/b8/e1/e2719465b5947c40cd85d613d6cb33449b86a1ca5a6c574269\nSuccessfully built pathspec\nInstalling collected packages: toml, attrs, regex, appdirs, typed-ast, click, pathspec, black\nSuccessfully installed appdirs-1.4.3 attrs-19.3.0 black-19.10b0 click-7.0 pathspec-0.6.0 regex-2019.11.1 toml-0.10.0 typed-ast-1.4.0\nroot@7ebc68fc6b42:/app#\n```\n\n#### Verify Black version\n\nVerify the version as follows:\n\n    $ black --version\n\n#### Running Black\n\nRun `Black` as follows:\n\n    $ black .\n\nOr, to see if `black` would make changes:\n\n    $ black . --check\n\nUsing docker, this looks as follows:\n\n```bash\nroot@7ebc68fc6b42:/app# black . --check\nwould reformat bad-python.py\nOh no! 💥 💔 💥\n1 file would be reformatted.\nroot@7ebc68fc6b42:/app#\n```\n\nOr, to simply view the changes `black` would make (it is still in __beta__, after all):\n\n    $ black . --diff\n\nUsing docker, this looks as follows:\n\n```bash\nroot@325bb7a3d2a3:/app# black . --diff\n--- bad-python.py\t2018-12-14 18:12:44.889095 +0000\n+++ bad-python.py\t2019-11-04 14:03:13.113575 +0000\n@@ -8,6 +8,5 @@\n print \"This code does not follow 'pylint' file naming conventions!\"\n \n \"\"\"'pycodestyle' will complain about the blank line following the print statement.\"\"\"\n print \"This code does not follow 'pycodestyle' coding conventions!\"\n \n-\nreformatted bad-python.py\nAll done! ✨ 🍰 ✨\n1 file reformatted.\nroot@325bb7a3d2a3:/app#\n```\n\n[Note that `black` has removed the trailing blank line that `pycodestyle` was complaining about.]\n\n## To Do\n\n- [x] Add notes on disabling specific `pylint` rules\n- [x] Add notes on disabling specific `pylint` rules for a single line of code\n- [x] Add notes on Black (code formatter)\n- [x] Update for recent Python 3 (__3.6.9__)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fpython-linters","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmramshaw%2Fpython-linters","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmramshaw%2Fpython-linters/lists"}