添加了py代码评分代码 #9

Merged
p5i4afnyx merged 2 commits from cxf into main 2 months ago

Binary file not shown.

@ -0,0 +1,64 @@
@startuml
skinparam dpi 180
skinparam shadowing false
skinparam ArrowColor #00AEEF
skinparam DefaultFontName Microsoft YaHei
skinparam ArrowThickness 1.2
title 界面跳转图OpenRank 可视化系统)
[*] --> 主界面 : 进入系统
state 主界面
state 开发者分析
state 仓库概览
state 网络图谱
state 项目模式概览
state 计算弹窗
state 算法配置界面
state "仓库详情 Modal" as 仓库详情
state "项目 Overview (approx)" as 项目Approx
state "项目 Overview (full)" as 项目Full
' 主界面导航
主界面 --> 开发者分析
主界面 --> 仓库概览
主界面 --> 网络图谱
主界面 --> 项目模式概览
主界面 --> 计算弹窗 : 一键计算
' 计算弹窗返回刷新各视图
计算弹窗 --> 主界面 : 提交 owner/repo
计算弹窗 --> 开发者分析 : 结果刷新
计算弹窗 --> 仓库概览 : 结果刷新
计算弹窗 --> 项目模式概览 : 可切换模式
' 仓库概览交互
仓库概览 --> 仓库详情 : 查看详情
仓库概览 --> 开发者分析 : 贡献分析
仓库概览 --> 仓库概览 : 关键词/筛选
' 仓库详情交互
仓库详情 --> 仓库详情 : 时间窗口/粒度
仓库详情 --> 仓库概览 : 关闭
仓库详情 --> 开发者分析 : 跳转贡献者
' 项目模式approx/full交互
项目模式概览 --> 项目Approx : 选择仓库
项目Approx --> 项目Full : 触发正式重算
项目Full --> 项目Approx : 计算完成 替换 approx
项目Approx --> 项目Approx : 贡献者 Top/活动占比
项目Approx --> 开发者分析 : 跳转贡献者分析
' 网络图谱与算法配置
网络图谱 --> 算法配置界面 : 参数调节
算法配置界面 --> 网络图谱 : 保存参数
算法配置界面 --> 主界面 : 近似预览/正式重算
' 返回导航
开发者分析 --> 主界面 : 返回
仓库概览 --> 主界面 : 返回
网络图谱 --> 主界面 : 返回
项目模式概览 --> 主界面 : 返回
@enduml

@ -0,0 +1,22 @@
[paths]
source =
pylint
[report]
include =
pylint/*
omit =
*/test/*
exclude_also =
# Debug-only code
def __repr__
# Type checking code not executed during pytest runs
if TYPE_CHECKING:
@overload
# Abstract methods are not executed during pytest runs
raise NotImplementedError()
# Fallback cases which should never be executed
raise AssertionError

@ -0,0 +1 @@
3f2842400795ae1aaffc4ae6c35c4ef26857c239

@ -0,0 +1,7 @@
* text=auto
tests/**/functional/** -text
tests/input/** -text
tests/**/data/** -text
tests/regrtest_data/** -text
doc/data/messages/u/unexpected-line-ending-format/bad.py -text
doc/data/messages/m/mixed-line-endings/bad.py -text

@ -0,0 +1,35 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
# These owners will be the default owners for everything in the repo.
# Right now there is not default owner to avoid spam
# * @pierre-sassoulas @DanielNoord @cdce8p @jacobtylerwalls @hippo91
# Order is important. The last matching pattern has the most precedence.
### Core components
# internal message handling
pylint/message/* @pierre-sassoulas
tests/message/* @pierre-sassoulas
# typing
pylint/typing.py @DanielNoord
# multiprocessing (doublethefish is not yet a contributor with write access)
# pylint/lint/parallel.py @doublethefish
# tests/test_check_parallel.py @doublethefish
### Pyreverse
pylint/pyreverse/* @DudeNr33
tests/pyreverse/* @DudeNr33
### Extensions
# CodeStyle
pylint/extensions/code_style.* @cdce8p
tests/functional/ext/code_style/* @cdce8p
# Typing
pylint/extensions/typing.* @cdce8p
tests/functional/ext/typing/* @cdce8p

@ -0,0 +1,2 @@
Please read the
[contribute doc](https://pylint.readthedocs.io/en/latest/development_guide/contributor_guide/contribute.html).

@ -0,0 +1,3 @@
# These are supported funding model platforms
tidelift: "pypi/pylint"
github: [cdce8p, DanielNoord, jacobtylerwalls,Pierre-Sassoulas]

@ -0,0 +1,108 @@
name: 🐛 Bug report
description: Report a bug in pylint
labels: ["Needs triage :inbox_tray:"]
body:
- type: markdown
attributes:
value: |
**Thank you for wanting to report a bug in pylint!**
⚠ Please make sure that this [issue wasn't already requested][issue search], or already implemented in the main branch.
[issue search]: https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+
- type: textarea
id: what-happened
attributes:
label: Bug description
description:
What is the bug about? Please provide the code that is causing the issue, and
configurations used if required
placeholder: |
# Please disable message unrelated to the bug
# pylint: disable=missing-docstring,
<a> = b + 1
render: python
validations:
required: true
- type: textarea
id: configuration
attributes:
label: Configuration
description:
Please provide the part of the configuration that is causing the bug if required
(Leave this part blank if the configuration is not relevant)
placeholder: |
# Leave this blank if the configuration is not relevant!
[MAIN]
load-plugins=
pylint.extensions.code_style
[MESSAGE CONTROL]
enable=
useless-suppression
# ...
render: ini
- type: textarea
id: cmd-used
attributes:
label: Command used
description: What was the command used to invoke pylint?
placeholder: |
pylint a.py
render: shell
validations:
required: true
- type: textarea
id: current-behavior
attributes:
label: Pylint output
description: What is the current pylint output?
placeholder: |
************* Module a
a.py:3:1: E0001: invalid syntax (<unknown>, line 1) (syntax-error)
render: python
validations:
required: true
- type: textarea
id: future-behavior
attributes:
label: Expected behavior
description:
What would you expect instead? For example expected output or behavior
validations:
required: true
- type: textarea
id: python-interpreter
attributes:
label: Pylint version
description: >-
Please copy and paste the result of `pylint --version` or specify the range of
versions affected.
placeholder: |
pylint 3.3.0
astroid 3.3.0
Python 3.12.0 (v3.12.0:0fb18b02c8, Oct 2 2023, 09:45:56)
render: shell
validations:
required: true
- type: textarea
attributes:
label: OS / Environment
description: >-
Provide all relevant information below, e.g. OS version, terminal etc.
placeholder: Fedora 33, Cygwin, etc.
- type: textarea
id: additional-deps
attributes:
label: Additional dependencies
description:
If applicable ie, if we can't reproduce without it. Please copy and paste the
result of `pip freeze`.
placeholder: |
pandas==0.23.2
marshmallow==3.10.0
render: python

@ -0,0 +1,45 @@
name: ✨ Feature request
description: Suggest an idea for pylint
labels: ["Needs triage :inbox_tray:"]
body:
- type: markdown
attributes:
value: |
**Thank you for wanting to make a suggestion for pylint!**
⚠ Please make sure that [this feature wasn't already requested][issue search] or already implemented in the main branch.
[issue search]: https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+
- type: textarea
id: current-problem
attributes:
label: Current problem
description:
What are you trying to do, that you are unable to achieve with pylint as it
currently stands?
placeholder: >-
I'm trying to do X and I'm missing feature Y for this to be easily achievable.
validations:
required: true
- type: textarea
id: proposed-solution
attributes:
label: Desired solution
description: A clear and concise description of what you want to happen.
placeholder: >-
When I do X, I want to achieve Y in a situation when Z.
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: >
Add any other context, links, etc. about the feature here. Describe how the
feature would be used, why it is needed and what it would solve.
**HINT:** You can paste https://gist.github.com links for larger files.
placeholder: >-
I asked on https://stackoverflow.com/... and the community advised me to do X, Y
and Z.

@ -0,0 +1,49 @@
name: 🤔 Support question
description: Questions about pylint that are not covered in the documentation
labels: ["Needs triage :inbox_tray:", "Question", "Documentation :green_book:"]
body:
- type: markdown
attributes:
value: >
**Thank you for wanting to report a problem with pylint documentation!**
Please fill out your suggestions below. If the problem seems straightforward,
feel free to go ahead and submit a pull request instead!
⚠ Verify first that your issue is not [already reported on GitHub][issue
search].
💬 If you are seeking community support, please consider [starting a discussion
on Discord][Discussions].
[issue search]:
https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+
[Discussions]: https://discord.com/invite/Egy6P8AMB5
- type: textarea
id: question
attributes:
label: Question
validations:
required: true
- type: textarea
id: documentation
attributes:
label: Documentation for future user
description:
Where did you expect this information to be? What do we need to add or what do
we need to reorganize?
validations:
required: true
- type: textarea
attributes:
label: Additional context
description: >
Add any other context, links, etc. about the question here.
placeholder: >-
I asked on https://stackoverflow.com/... and the community advised me to do X, Y
and Z.

@ -0,0 +1,5 @@
blank_issues_enabled: true
contact_links:
- name: 💬 Discord
url: https://discord.com/invite/Egy6P8AMB5
about: Astroid and pylint informal dev discussion

@ -0,0 +1,41 @@
<!--
Thank you for submitting a PR to pylint!
To ease the process of reviewing your PR, do make sure to complete the following boxes.
- [ ] Document your change, if it is a non-trivial one.
- A maintainer might label the issue ``skip-news`` if the change does not need to be in the changelog.
- Otherwise, create a news fragment with ``towncrier create <IssueNumber>.<type>`` which will be
included in the changelog. ``<type>`` can be one of the types defined in `./towncrier.toml`.
If necessary you can write details or offer examples on how the new change is supposed to work.
- Generating the doc is done with ``tox -e docs``
- [ ] Relate your change to an issue in the tracker if such an issue exists (Refs #1234, Closes #1234)
- [ ] Write comprehensive commit messages and/or a good description of what the PR does.
- [ ] Keep the change small, separate the consensual changes from the opinionated one.
Don't hesitate to open multiple PRs if the change requires it. If your review is so
big it requires to actually plan and allocate time to review, it's more likely
that it's going to go stale.
- [ ] If you used multiple emails or multiple names when contributing, add your mails
and preferred name in ``script/.contributors_aliases.json``
-->
## Type of Changes
<!-- Leave the corresponding lines for the applicable type of change: -->
| | Type |
| --- | ---------------------- |
| ✓ | :bug: Bug fix |
| ✓ | :sparkles: New feature |
| ✓ | :hammer: Refactoring |
| ✓ | :scroll: Docs |
## Description
<!-- If this PR references an issue without fixing it: -->
Refs #XXXX
<!-- If this PR fixes an issue, use the following to automatically close when we merge: -->
Closes #XXXX

@ -0,0 +1 @@
Coordinated Disclosure Plan: https://tidelift.com/security

@ -0,0 +1,255 @@
# Pylint Development Instructions
Always follow these instructions first and fallback to additional search and context
gathering only if the information in these instructions is incomplete or found to be in
error.
## Issue Label Guidelines
Before attempting to fix any issue, check the GitHub issue labels using the GitHub API:
- If an issue is labeled with "Astroid", "Needs astroid update", "Needs astroid
constraint", or "Needs astroid Brain 🧠", **ONLY** create regression tests
- Do **NOT** attempt to fix astroid-related issues as you cannot modify astroid from
this repository
- For astroid-related issues, focus on creating comprehensive regression tests that
reproduce the problem
- All other issues can be fixed normally following the standard development workflow
## Development Environment Setup
### Basic Installation
Clone and set up pylint development environment:
- `git clone https://github.com/pylint-dev/pylint` -- clone repository
- `cd pylint` -- enter directory
- `python3 -m venv venv` -- create virtual environment
- `source venv/bin/activate` -- activate virtual environment (Linux/Mac)
- `pip install -r requirements_test_min.txt` -- install test dependencies (~30 seconds)
- `pip install -e .` -- install pylint in editable mode (~30-60 seconds)
### Optional Setup Steps
- `pre-commit install` -- enable pre-commit hooks for autoformatting
- `pip install pre-commit` -- install pre-commit separately if needed
### Astroid Development (if needed)
If working on astroid changes:
- `git clone https://github.com/pylint-dev/astroid.git` -- clone astroid
- `pip install -e astroid/` -- install astroid in editable mode
- `cd astroid/ && git switch my-astroid-dev-branch` -- switch to development branch
## Running Tests
### Core Test Commands
- `pytest tests/test_functional.py -k test_functional` -- run functional tests (~60
seconds, NEVER CANCEL, set timeout to 120+ seconds)
- `pytest tests/` -- run all tests (several minutes, NEVER CANCEL, set timeout to 300+
seconds)
- `python3 -m pytest` -- run tests with local python
- `pytest tests/test_check_parallel.py -v` -- quick test file (~2 seconds)
### Specific Test Types
- **Functional tests:**
`pytest "tests/test_functional.py::test_functional[missing_kwoa_py3]"` -- single
functional test (~1 second)
- **Unit tests:** Located in `/tests/` directory, test specific pylint functionality
- **Configuration tests:** In `/tests/config/functional/` for testing configuration
loading
- **Primer tests:** `pytest -m primer_stdlib --primer-stdlib` -- test on stdlib for
crashes
### Test with Coverage
- `pytest tests/message/ --cov=pylint.message` -- run with coverage
- `coverage html` -- generate HTML coverage report
### Tox Usage (Optional)
- `python -m tox` -- run all tox environments
- `python -m tox -epy313` -- run Python 3.13 suite only
- `python -m tox -epylint` -- run pylint on pylint's codebase
- `python -m tox -eformatting` -- run formatting checks
- `python -m tox --recreate` -- recreate environments (recommended)
- `python -m tox -e py310 -- -k test_functional` -- run specific tests in tox
## Documentation
### Building Documentation
- `make -C doc/ install-dependencies` -- install doc dependencies (~10 seconds)
- `make -C doc/ html` -- build documentation (~3 minutes, NEVER CANCEL, set timeout to
300+ seconds)
- `make -C doc/ clean` -- clean build files when starting from scratch
- `tox -e docs` -- alternative way to build docs
**Network dependency:** Documentation build requires internet access to fetch external
inventories.
## Validation and Quality Checks
### Running Pylint on Code
- `pylint --help` -- verify pylint installation works
- `pylint --disable=all --enable=E,F pylint/` -- run pylint on itself for errors only
(~20 seconds)
- `pylint --rcfile=pylintrc --fail-on=I path/to/your/changes.py` -- standard pylint run
- `pylint --disable=all --enable=E,F,W path/to/your/changes.py` -- focus on errors and
warnings
### Pre-commit and Formatting
- `pre-commit run --all-files` -- run all formatting checks (requires network for
initial setup)
- **Network dependency:** pre-commit may fail in isolated environments due to hook
downloads
### Validation Test Scenarios
Always test your changes with these validation scenarios:
- `echo "def badFunction(): pass" > /tmp/test_sample.py && pylint --enable=C0103 /tmp/test_sample.py`
-- should find naming issues
- `pylint --help` and `pylint --list-msgs | head -10` -- verify CLI functionality
- `pylint --help-msg=C0103` -- should show invalid-name help
- `pylint --rcfile=pylintrc --fail-on=I pylint/__init__.py` -- should get 10.00/10
rating
## Writing Tests
### Functional Tests
Located in `/tests/functional/`, consists of `.py` test files with corresponding `.txt`
expected output files:
- Annotate lines where messages are expected:
`a, b, c = 1 # [unbalanced-tuple-unpacking]`
- Multiple messages on same line:
`a, b, c = 1.test # [unbalanced-tuple-unpacking, no-member]`
- Use offset syntax for special cases: `# +1: [singleton-comparison]`
- **Run and update:**
`python tests/test_functional.py --update-functional-output -k "test_functional[test_name]"`
### Test File Organization
- **New checkers:** Create `new_checker_message.py` in `/tests/functional/n/`
- **Extensions:** Place in `/tests/functional/ext/extension_name/`
- **Regression tests:** Place in `/tests/r/regression/` with `regression_` prefix
- **Configuration tests:** Place in `/tests/config/functional/`
### Configuration Test Files
Create `.result.json` files with configuration differences from standard config:
```json
{
"functional_append": {
"disable": [["a-message-to-be-added"]]
},
"jobs": 10
}
```
## Codebase Structure
```
pylint/ # Main package
├── checkers/ # All pylint checkers (rules implementation)
├── config/ # Configuration handling and parsing
├── message/ # Message system and formatting
├── reporters/ # Output formatters (text, json, etc.)
├── testutils/ # Testing utilities and helpers
└── extensions/ # Optional extensions and plugins
tests/ # Test suite
├── functional/ # Functional test files (.py + .txt expected output)
├── config/functional/ # Configuration functional tests
├── r/regression/ # Regression tests
├── test_*.py # Unit tests
└── regrtest_data/ # Test data files
doc/ # Documentation
├── user_guide/ # User documentation
├── development_guide/ # Developer and contributor documentation
│ ├── contributor_guide/ # Setup, testing, contribution guidelines
│ ├── technical_reference/ # Technical implementation details
│ └── how_tos/ # Guides for custom checkers, plugins
└── additional_tools/ # Tools documentation
script/ # Development utility scripts
```
### Key Files
- `pyproject.toml` -- Main configuration (dependencies, build, tools)
- `tox.ini` -- Multi-environment testing configuration
- `.pre-commit-config.yaml` -- Code quality checks configuration
- `pylintrc` -- Pylint's own configuration
- `requirements_test_min.txt` -- Minimal test dependencies
- `.gitignore` do not add the 'venv' inside the .gitignore, don't commit the venv in the
first place (humans add it to their global gitignore)
## Creating New Checkers
### Getting Started
- `python script/get_unused_message_id_category.py` -- get next available message ID
- Study existing checkers in `pylint/checkers/` for patterns
- Read technical reference documentation in `doc/development_guide/technical_reference/`
- Use `astroid.extract_node` for AST manipulation
### Workflow
1. Create checker class in appropriate `pylint/checkers/` file
2. Add functional tests in `tests/functional/`
3. Search existing code for warning message to find where logic exists
4. Test with sample code to ensure functionality works
## Pull Request Guidelines
### Before Submitting
- Use Python 3.8+ for development (required for latest AST parser and pre-commit hooks)
- Write comprehensive commit messages relating to tracker issues
- Keep changes small and separate consensual from opinionated changes
- Add news fragment: `towncrier create <IssueNumber>.<type>`
- Always launch `pre-commit run -a` before committing
### Documentation Changes
- Document non-trivial changes
- Generate docs with `tox -e docs`
- Maintainers may label issues `skip-news` if no changelog needed
### Contribution Credits
- Add emails/names to `script/.contributors_aliases.json` if using multiple identities
## Critical Timing Information
- **NEVER CANCEL:** All operations that show "NEVER CANCEL" may take significant time
- **Full test suite:** 60+ seconds (set timeout to 120+ seconds)
- **Documentation build:** 180 seconds (set timeout to 300+ seconds)
- **Functional tests:** 60 seconds (set timeout to 120+ seconds)
- **Pylint self-check:** 20 seconds (set timeout to 60+ seconds)
- **Individual test files:** 1-15 seconds
- **Installation steps:** 30-60 seconds each
## Environment Limitations and Workarounds
- **Network connectivity required:** Documentation build and pre-commit setup require
internet access
- **Tox failures:** In isolated environments, use direct pytest and pip commands instead
of tox
- **Import errors in self-check:** Some import errors when running pylint on itself are
expected (git dependencies not installed)
- **Build environments:** Use direct pip/pytest commands when tox environments fail to
build
Always validate your changes by running pylint on sample code to ensure functionality
works correctly.

@ -0,0 +1,21 @@
version: 2
updates:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependency"
- "Skip news :mute:"
open-pull-requests-limit: 10
rebase-strategy: "disabled"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
labels:
- "dependency"
- "Skip news :mute:"
open-pull-requests-limit: 10
rebase-strategy: "disabled"

@ -0,0 +1,40 @@
name: Backport
on:
pull_request_target:
types:
- closed
- labeled
permissions:
contents: read
jobs:
backport:
name: Backport
runs-on: ubuntu-latest
environment:
name: Backport
# Only react to merged PRs for security reasons.
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
if: >
github.event.pull_request.merged && (
github.event.action == 'closed'
|| (
github.event.action == 'labeled'
&& contains(github.event.label.name, 'backport')
)
)
steps:
- uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4
id: app-token
with:
app-id: ${{ vars.BACKPORT_APP_ID }}
private-key: ${{ secrets.PRIVATE_KEY }}
permission-contents: write # push branch to Github
permission-pull-requests: write # create PR / add comment for manual backport
permission-workflows: write # modify files in .github/workflows
- uses: pylint-dev/backport@94367840595495e101f9a31415897c05da1f08d9 # v2.1.1
with:
github_token: ${{ steps.app-token.outputs.token }}
user_name: ${{ vars.BACKPORT_USER_NAME }}
user_email: ${{ vars.BACKPORT_USER_EMAIL }}

@ -0,0 +1,65 @@
name: changelog
on:
pull_request:
types: [opened, synchronize, labeled, unlabeled, reopened]
branches-ignore:
- "maintenance/**"
env:
CACHE_VERSION: 1
KEY_PREFIX: base-venv
DEFAULT_PYTHON: "3.13"
permissions:
contents: read
jobs:
check-changelog:
if: contains(github.event.pull_request.labels.*.name, 'skip news :mute:') != true
name: Changelog Entry Check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
with:
# `towncrier check` runs `git diff --name-only origin/main...`, which
# needs a non-shallow clone.
fetch-depth: 0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Generate partial Python venv restore key
id: generate-python-key
run: >-
echo "key=${{ env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{
hashFiles('pyproject.toml', 'requirements_test.txt',
'requirements_test_min.txt', 'requirements_test_pre_commit.txt') }}" >>
$GITHUB_OUTPUT
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.3.0
with:
path: venv
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
steps.generate-python-key.outputs.key }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt --requirement doc/requirements.txt
- name: Emit warning if news fragment is missing
env:
BASE_BRANCH: ${{ github.base_ref }}
run: |
# Fetch the pull request' base branch so towncrier will be able to
# compare the current branch with the base branch.
git fetch --no-tags origin +refs/heads/${BASE_BRANCH}:refs/remotes/origin/${BASE_BRANCH}
. venv/bin/activate
towncrier check --compare-with origin/${{ github.base_ref }}

@ -0,0 +1,160 @@
name: Checks
on:
push:
branches:
- main
- "maintenance/**"
pull_request:
branches:
- main
- "maintenance/**"
workflow_dispatch:
env:
CACHE_VERSION: 3
KEY_PREFIX: base-venv
DEFAULT_PYTHON: "3.13"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
prepare-base:
name: Prepare base dependencies
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
python-key: ${{ steps.generate-python-key.outputs.key }}
pre-commit-key: ${{ steps.generate-pre-commit-key.outputs.key }}
steps:
- &checkout
name: Check out code from GitHub
uses: actions/checkout@v5.0.0
- &setup-python
name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Generate partial Python venv restore key
id: generate-python-key
run: >-
echo "key=${{ env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{
hashFiles('pyproject.toml', 'requirements_test.txt',
'requirements_test_min.txt', 'requirements_test_pre_commit.txt') }}" >>
$GITHUB_OUTPUT
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.3.0
with:
path: venv
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
steps.generate-python-key.outputs.key }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt --requirement doc/requirements.txt
pip install pre-commit
- name: Generate pre-commit restore key
id: generate-pre-commit-key
run: >-
echo "key=pre-commit-${{ env.CACHE_VERSION }}-${{
hashFiles('.pre-commit-config.yaml') }}" >> $GITHUB_OUTPUT
- name: Restore pre-commit environment
id: cache-precommit
uses: actions/cache@v4.3.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
key: >-
${{ runner.os }}-${{ steps.generate-pre-commit-key.outputs.key }}
- name: Install pre-commit dependencies
if: steps.cache-precommit.outputs.cache-hit != 'true'
run: |
. venv/bin/activate
pre-commit install --install-hooks
pylint:
name: pylint
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [prepare-base]
steps:
- *checkout
- *setup-python
- &cache-restore-python
name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.3.0
with:
path: venv
fail-on-cache-miss: true
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.prepare-base.outputs.python-key }}
- name: Restore pre-commit environment
id: cache-precommit
uses: actions/cache/restore@v4.3.0
with:
path: ${{ env.PRE_COMMIT_CACHE }}
fail-on-cache-miss: true
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
- name: Install enchant and aspell
run: |
sudo apt-get update
sudo apt-get install enchant-2 aspell-en
- name: Run pylint checks
run: |
. venv/bin/activate
pip install . --no-deps
pip list | grep 'astroid\|pylint'
pre-commit run --hook-stage manual pylint-with-spelling --all-files
spelling:
name: spelling tests
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [prepare-base]
steps:
- *checkout
- *setup-python
- *cache-restore-python
- name: Run spelling checks
run: |
. venv/bin/activate
pip install . --no-deps
pytest tests/ -k unittest_spelling --benchmark-disable
documentation:
name: documentation
runs-on: ubuntu-latest
timeout-minutes: 20
needs: [prepare-base]
steps:
- *checkout
- *setup-python
- *cache-restore-python
- name: Run checks on documentation code examples
run: |
. venv/bin/activate
tox -e test_doc
- name: Check documentation build and links
run: |
. venv/bin/activate
tox -e docs || {
echo "git diff:" ; \
git diff ; \
echo "End of 'git diff'" ; \
echo "Make sure that 'tox -e docs' succeed without any modifications locally." ; \
exit 1; \
}

@ -0,0 +1,80 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [main]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
schedule:
- cron: "44 16 * * 4"
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
analyze:
if:
${{ github.repository_owner == 'pylint-dev' || github.event_name != 'schedule' }}
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: ["python"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v5.0.0
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v4
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4

@ -0,0 +1,95 @@
name: Primer
on:
push:
branches:
- main
pull_request:
paths:
- "pylint/**"
- "tests/primer/**"
- "requirements*"
- ".github/workflows/primer-test.yaml"
branches:
- main
env:
CACHE_VERSION: 4
KEY_PREFIX: venv
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
prepare-tests-linux:
name: prepare / ${{ matrix.python-version }} / Linux
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
python-version: &matrix-python-version ["3.10", "3.11", "3.12", "3.13", "3.14"]
outputs:
python-key: ${{ steps.generate-python-key.outputs.key }}
steps:
- &checkout
name: Check out code from GitHub
uses: actions/checkout@v5.0.0
- &setup-python
name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
check-latest: true
- name: Generate partial Python venv restore key
id: generate-python-key
run: >-
echo "key=${{ env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{
hashFiles('pyproject.toml', 'requirements_test.txt',
'requirements_test_min.txt', 'requirements_test_pre_commit.txt') }}" >>
$GITHUB_OUTPUT
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.3.0
with:
path: venv
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
steps.generate-python-key.outputs.key }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt
pytest-primer-stdlib:
name: run on stdlib / ${{ matrix.python-version }} / Linux
runs-on: ubuntu-latest
timeout-minutes: 10
needs: prepare-tests-linux
strategy:
matrix:
python-version: *matrix-python-version
steps:
- *checkout
- *setup-python
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.3.0
with:
path: venv
fail-on-cache-miss: true
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.prepare-tests-linux.outputs.python-key }}
- name: Run pytest
run: |
. venv/bin/activate
pip install . --no-deps
pytest -m primer_stdlib --primer-stdlib -n auto -vv --benchmark-disable

@ -0,0 +1,125 @@
# Most of this is inspired by the mypy primer
# See: https://github.com/hauntsaninja/mypy_primer
# This is the primer job that creates the comment on the PR
# It needs to trigger on workflow_run instead of pull_request
# as we need repository wide access to create a comment
name: Primer / Comment
on:
workflow_run:
workflows: [Primer / Run]
types:
- completed
env:
# This needs to be the SAME as in the Main and PR job
CACHE_VERSION: 4
KEY_PREFIX: venv-primer
# If you change this, also change PRIMER_CURRENT_INTERPRETER in
# tests/testutils/_primer/test_primer.py
DEFAULT_PYTHON: "3.13"
permissions:
contents: read
pull-requests: write
jobs:
primer-comment:
# Skip job if the workflow failed
if: ${{ github.event.workflow_run.conclusion == 'success' }}
name: Run
runs-on: ubuntu-latest
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
# Restore cached Python environment
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.3.0
with:
path: venv
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml',
'requirements_test.txt', 'requirements_test_min.txt',
'requirements_test_pre_commit.txt') }}
- name: Download outputs
uses: actions/github-script@v8.0.0
with:
script: |
// Download workflow pylint output
const fs = require('fs');
const artifacts_workflow = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{ github.event.workflow_run.id }},
});
// Get 'main' and 'PR' outputs and PR number
const artifacts = artifacts_workflow.data.artifacts.filter((artifact) =>
artifact.name.startsWith(`primer_output_main_${process.env.DEFAULT_PYTHON}`)
|| artifact.name.startsWith(`primer_output_pr_${process.env.DEFAULT_PYTHON}`)
|| artifact.name === 'pr_number'
);
for (const artifact of artifacts) {
const downloaded = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: artifact.id,
archive_format: "zip",
});
fs.writeFileSync(`${artifact.name}.zip`, Buffer.from(downloaded.data));
}
- name: Unzip outputs
run: |
unzip primer_output_main_${{ env.DEFAULT_PYTHON }}_batch0.zip
unzip primer_output_main_${{ env.DEFAULT_PYTHON }}_batch1.zip
unzip primer_output_main_${{ env.DEFAULT_PYTHON }}_batch2.zip
unzip primer_output_main_${{ env.DEFAULT_PYTHON }}_batch3.zip
unzip primer_output_pr_${{ env.DEFAULT_PYTHON }}_batch0.zip
unzip primer_output_pr_${{ env.DEFAULT_PYTHON }}_batch1.zip
unzip primer_output_pr_${{ env.DEFAULT_PYTHON }}_batch2.zip
unzip primer_output_pr_${{ env.DEFAULT_PYTHON }}_batch3.zip
unzip pr_number.zip
- name: Compare outputs
run: |
. venv/bin/activate
python tests/primer/__main__.py compare \
--commit=${{ github.event.workflow_run.head_sha }} \
--base-file=output_${{ env.DEFAULT_PYTHON }}_main_BATCHIDX.txt \
--new-file=output_${{ env.DEFAULT_PYTHON }}_pr_BATCHIDX.txt \
--batches=4
- name: Post comment
id: post-comment
uses: actions/github-script@v8.0.0
with:
script: |
const fs = require('fs')
const comment = fs.readFileSync('tests/.pylint_primer_tests/comment.txt', { encoding: 'utf8' })
console.log("Comment to post:")
console.log(comment)
const prNumber = parseInt(fs.readFileSync("pr_number.txt", { encoding: "utf8" }))
await github.rest.issues.createComment({
issue_number: prNumber,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
})
return prNumber
- name: Hide old comments
# Taken from mypy primer
uses: kanga333/comment-hider@c12bb20b48aeb8fc098e35967de8d4f8018fffdf # v0.4.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
leave_visible: 1
issue_number: ${{ steps.post-comment.outputs.result }}

@ -0,0 +1,132 @@
# Most of this is inspired by the mypy primer
# See: https://github.com/hauntsaninja/mypy_primer
# This is the primer job that runs on the default 'main' branch
# It is also responsible for caching the packages to prime on
name: Primer / Main
on:
push:
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# This needs to be the SAME as in the PR and comment job
CACHE_VERSION: 4
KEY_PREFIX: venv-primer
permissions:
contents: read
jobs:
run-primer:
name: Run / ${{ matrix.python-version }} / batch index ${{ matrix.batchIdx }}
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
matrix:
python-version: ["3.10", "3.13"]
batches: [4]
batchIdx: [0, 1, 2, 3]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
# Create a re-usable virtual environment
- name: Restore Python virtual environment cache
id: cache-venv
uses: actions/cache/restore@v4.3.0
with:
path: venv
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml',
'requirements_test.txt', 'requirements_test_min.txt',
'requirements_test_pre_commit.txt') }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt
# Save cached Python environment (explicit because cancel-in-progress: true)
- name: Save Python virtual environment to cache
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/save@v4.3.0
with:
path: venv
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml',
'requirements_test.txt', 'requirements_test_min.txt',
'requirements_test_pre_commit.txt') }}
# Cache primer packages
- name: Get commit string
id: commitstring
run: |
. venv/bin/activate
python tests/primer/__main__.py prepare --make-commit-string
output=$(python tests/primer/__main__.py prepare --read-commit-string)
echo "commitstring=$output" >> $GITHUB_OUTPUT
- name: Restore projects cache
id: cache-projects
uses: actions/cache/restore@v4.3.0
with:
path: tests/.pylint_primer_tests/
key: >-
${{ runner.os }}-${{ matrix.python-version }}-${{
steps.commitstring.outputs.commitstring }}-primer
- name: Regenerate cache
if: steps.cache-projects.outputs.cache-hit != 'true'
run: |
. venv/bin/activate
python tests/primer/__main__.py prepare --clone
- name: Save projects cache
if: steps.cache-projects.outputs.cache-hit != 'true'
uses: actions/cache/save@v4.3.0
with:
path: tests/.pylint_primer_tests/
key: >-
${{ runner.os }}-${{ matrix.python-version }}-${{
steps.commitstring.outputs.commitstring }}-primer
- name: Upload commit string
uses: actions/upload-artifact@v4.6.2
if: matrix.batchIdx == 0
with:
name: primer_commitstring_${{ matrix.python-version }}
path:
tests/.pylint_primer_tests/commit_string_${{ matrix.python-version }}.txt
# Run primer
- name: Run pylint primer
run: |
. venv/bin/activate
pip install . --no-deps
python tests/primer/__main__.py run --type=main --batches=${{ matrix.batches }} --batchIdx=${{ matrix.batchIdx }} 2>warnings.txt
- name: Echo warnings
if: success() || failure()
run: |
WARNINGS=$(head -c 65000 < warnings.txt)
if [[ $WARNINGS ]]
then echo "::warning ::$WARNINGS"
fi
- name: Upload output
uses: actions/upload-artifact@v4.6.2
with:
name:
primer_output_main_${{ matrix.python-version }}_batch${{ matrix.batchIdx }}
path: >-
tests/.pylint_primer_tests/output_${{ matrix.python-version }}_main_batch${{
matrix.batchIdx }}.txt

@ -0,0 +1,225 @@
# Most of this is inspired by the mypy primer
# See: https://github.com/hauntsaninja/mypy_primer
# This is the primer job that runs on every PR
name: Primer / Run
on:
pull_request:
paths:
- "pylint/**"
- "tests/primer/**"
- "requirements*"
- ".github/workflows/**"
# We ignore these specific files because they need to be changed
# on 'main' and will always fail the PR run.
- "!.github/workflows/primer_run_main.yaml"
- "!.github/workflows/primer_comment.yaml"
- "!tests/primer/packages_to_prime.json"
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
env:
# This needs to be the SAME as in the Main and comment job
CACHE_VERSION: 4
KEY_PREFIX: venv-primer
permissions:
contents: read
jobs:
run-primer:
name: Run / ${{ matrix.python-version }} / batch index ${{ matrix.batchIdx }}
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
matrix:
python-version: ["3.10", "3.13"]
batches: [4]
batchIdx: [0, 1, 2, 3]
steps:
- name: Check out code from GitHub
uses: actions/checkout@v5.0.0
with:
fetch-depth: 0
- name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ matrix.python-version }}
check-latest: true
# Restore cached Python environment
- name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.3.0
with:
path: venv
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml',
'requirements_test.txt', 'requirements_test_min.txt',
'requirements_test_pre_commit.txt') }}
# Create environment must match step in 'Primer / Main'
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt
# Save cached Python environment (explicit because cancel-in-progress: true)
- name: Save Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
uses: actions/cache/save@v4.3.0
with:
path: venv
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{ hashFiles('pyproject.toml',
'requirements_test.txt', 'requirements_test_min.txt',
'requirements_test_pre_commit.txt') }}
# Cache primer packages
- name: Download last 'main' run info
id: download-main-run
uses: actions/github-script@v8.0.0
env:
COMMIT_STRING_ARTIFACT: primer_commitstring_${{ matrix.python-version }}
OUTPUT_ARTIFACT:
primer_output_main_${{ matrix.python-version }}_batch${{ matrix.batchIdx }}
with:
script: |
const { COMMIT_STRING_ARTIFACT, OUTPUT_ARTIFACT } = process.env
// Download 'main' pylint output
const fs = require('fs');
const runs = await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: ".github/workflows/primer_run_main.yaml",
status: "success"
});
const lastRunMain = runs.data.workflow_runs.reduce(function(prev, current) {
return (prev.run_number > current.run_number) ? prev : current
})
console.log("Last run on main:")
console.log(lastRunMain.html_url)
const artifacts_main = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: lastRunMain.id,
});
// Get commitstring
const [matchArtifactMain] = artifacts_main.data.artifacts.filter((artifact) =>
artifact.name === COMMIT_STRING_ARTIFACT);
const downloadWorkflow = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifactMain.id,
archive_format: "zip",
});
fs.writeFileSync(`${COMMIT_STRING_ARTIFACT}.zip`, Buffer.from(downloadWorkflow.data));
// Get output
const [matchArtifactMainOutput] = artifacts_main.data.artifacts.filter((artifact) =>
artifact.name === OUTPUT_ARTIFACT);
const downloadWorkflowTwo = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifactMainOutput.id,
archive_format: "zip",
});
fs.writeFileSync(`${OUTPUT_ARTIFACT}.zip`, Buffer.from(downloadWorkflowTwo.data));
return lastRunMain.head_sha;
- name: Copy and unzip the commit string
run: |
unzip primer_commitstring_${{ matrix.python-version }}.zip
cp commit_string_${{ matrix.python-version }}.txt tests/.pylint_primer_tests/commit_string_${{ matrix.python-version }}.txt
- name: Unzip the output of 'main'
run: |
unzip primer_output_main_${{ matrix.python-version }}_batch${{ matrix.batchIdx }}.zip
- name: Get commit string
id: commitstring
run: |
. venv/bin/activate
output=$(python tests/primer/__main__.py prepare --read-commit-string)
echo "commitstring=$output" >> $GITHUB_OUTPUT
- name: Restore projects cache
id: cache-projects
uses: actions/cache/restore@v4.3.0
with:
path: tests/.pylint_primer_tests/
key: >-
${{ runner.os }}-${{ matrix.python-version }}-${{
steps.commitstring.outputs.commitstring }}-primer
- name: Regenerate cache
if: steps.cache-projects.outputs.cache-hit != 'true'
run: |
. venv/bin/activate
python tests/primer/__main__.py prepare --clone
- name: Save projects cache
if: steps.cache-projects.outputs.cache-hit != 'true'
uses: actions/cache/save@v4.3.0
with:
path: tests/.pylint_primer_tests/
key: >-
${{ runner.os }}-${{ matrix.python-version }}-${{
steps.commitstring.outputs.commitstring }}-primer
- name: Check cache
run: |
. venv/bin/activate
python tests/primer/__main__.py prepare --check
# Merge the 'main' commit of last successful run
- name: Pull 'main'
shell: bash
run: |
git config --global user.email "primer@example.com"
git config --global user.name "Pylint Primer"
git pull origin ${{ steps.download-main-run.outputs.result }} --no-edit --no-commit --no-rebase
# Run primer
- name: Run pylint primer
run: |
. venv/bin/activate
pip install . --no-deps
python tests/primer/__main__.py run --type=pr --batches=${{ matrix.batches }} --batchIdx=${{ matrix.batchIdx }} 2>warnings.txt
- name: Echo warnings
if: success() || failure()
run: |
WARNINGS=$(head -c 65000 < warnings.txt)
if [[ $WARNINGS ]]
then echo "::warning ::$WARNINGS"
fi
- name: Upload output of PR
uses: actions/upload-artifact@v4.6.2
with:
name:
primer_output_pr_${{ matrix.python-version }}_batch${{ matrix.batchIdx }}
path:
tests/.pylint_primer_tests/output_${{ matrix.python-version }}_pr_batch${{
matrix.batchIdx }}.txt
- name: Upload output of 'main'
uses: actions/upload-artifact@v4.6.2
with:
name:
primer_output_main_${{ matrix.python-version }}_batch${{ matrix.batchIdx }}
path: output_${{ matrix.python-version }}_main_batch${{ matrix.batchIdx }}.txt
# Save PR number so we know which PR to comment on
- name: Save PR number
run: |
echo ${{ github.event.pull_request.number }} | tee pr_number.txt
- name: Upload PR number
if:
startsWith(steps.python.outputs.python-version, '3.10') && matrix.batchIdx ==
0
uses: actions/upload-artifact@v4.6.2
with:
name: pr_number
path: pr_number.txt

@ -0,0 +1,80 @@
name: Release
on:
release:
types:
- published
env:
DEFAULT_PYTHON: "3.13"
permissions:
contents: read
jobs:
build:
name: Build release assets
runs-on: ubuntu-latest
if: github.event_name == 'release'
steps:
- name: Check out code from Github
uses: actions/checkout@v5.0.0
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ env.DEFAULT_PYTHON }}
check-latest: true
- name: Install requirements
run: |
# Remove dist, build, and pylint.egg-info
# when building locally for testing!
python -m pip install build
- name: Build distributions
run: |
python -m build
- name: Upload release assets
uses: actions/upload-artifact@v4.6.2
with:
name: release-assets
path: dist/
release-pypi:
name: Upload release to PyPI
runs-on: ubuntu-latest
needs: ["build"]
environment:
name: PyPI
url: https://pypi.org/project/pylint/
permissions:
id-token: write
steps:
- name: Download release assets
uses: actions/download-artifact@v5.0.0
with:
name: release-assets
path: dist/
- name: Upload to PyPI
if: github.event_name == 'release'
uses: pypa/gh-action-pypi-publish@release/v1
release-github:
name: Upload assets to Github release
runs-on: ubuntu-latest
needs: ["build"]
permissions:
contents: write
id-token: write
steps:
- name: Download release assets
uses: actions/download-artifact@v5.0.0
with:
name: release-assets
path: dist/
- name: Sign the dists with Sigstore and upload assets to Github release
if: github.event_name == 'release'
uses: sigstore/gh-action-sigstore-python@v3.0.1
with:
inputs: |
./dist/*.tar.gz
./dist/*.whl

@ -0,0 +1,44 @@
name: close stale issues and pr
on:
schedule:
- cron: "30 1 * * *"
workflow_dispatch:
jobs:
close-issues:
if: github.repository_owner == 'pylint-dev'
runs-on: ubuntu-latest
permissions:
actions: write
issues: write
pull-requests: write
steps:
- uses: actions/stale@v10
with:
operations-per-run: 100
days-before-issue-stale: 28
days-before-issue-close: 7
any-of-issue-labels:
"Waiting on author,Cannot reproduce 🤷,python past end of life,Won't fix/not
planned"
exempt-issue-labels: "High priority,Blocked 🚧,Needs decision 🔒"
stale-issue-message:
"This issue is stale because it has been open 4 weeks with no activity.
Remove 'Stale' label or comment or this will be closed in a week."
close-issue-message:
"This issue was closed because it has been stalled for five weeks with no
activity."
any-of-pr-labels:
"Waiting on author,python past end of life,Won't fix/not planned"
exempt-pr-labels: "High priority,Blocked 🚧,Needs review 🔍"
days-before-pr-stale: 56
days-before-pr-close: -1
stale-pr-label: "Needs take over 🛎️"
close-pr-message:
"This PR was closed because it needed to be taken over for 16 weeks with no
one stepping up."
stale-pr-message:
"This PR needs take over because because it has been open 8 weeks with no
activity."

@ -0,0 +1,208 @@
name: Tests
on:
push:
branches:
- main
- "maintenance/**"
paths-ignore:
- doc/data/messages/**
pull_request:
branches:
- main
- "maintenance/**"
workflow_dispatch:
env:
CACHE_VERSION: 5
KEY_PREFIX: venv
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
tests:
name: run / ${{ matrix.python-version }} / ${{ matrix.os }}
timeout-minutes: 25
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
python-version: &matrix-python-version ["3.10", "3.11", "3.12", "3.13", "3.14"]
include:
- os: macos-latest
python-version: "3.10"
- os: ubuntu-latest
python-version: "pypy-3.10"
- os: ubuntu-latest
python-version: "pypy-3.11"
runs-on: ${{ matrix.os }}
outputs:
python-key: ${{ steps.generate-python-key.outputs.key }}
steps:
- &checkout
name: Check out code from GitHub
uses: actions/checkout@v5.0.0
- &setup-python
name: Set up Python ${{ matrix.python-version }}
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
check-latest: true
- name: Generate partial Python venv restore key
id: generate-python-key
run: >-
echo "key=${{ env.KEY_PREFIX }}-${{ env.CACHE_VERSION }}-${{
hashFiles('pyproject.toml', 'requirements_test.txt',
'requirements_test_min.txt', 'requirements_test_pre_commit.txt') }}" >>
$GITHUB_OUTPUT
- &cache-python
name: Restore Python virtual environment
id: cache-venv
uses: actions/cache@v4.3.0
with:
path: venv
key: >-
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
steps.generate-python-key.outputs.key }}
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv/bin/activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test.txt
- name: Run pytest
run: |
. venv/bin/activate
pip install . --no-deps
pip list | grep 'astroid\|pylint'
python -m pytest --durations=10 --benchmark-disable --cov --cov-report= tests/
- name: Run functional tests with minimal messages config
run: |
. venv/bin/activate
pip list | grep 'astroid\|pylint'
python -m pytest -vv --minimal-messages-config tests/test_functional.py --benchmark-disable
- name: Upload coverage artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4.6.2
with:
name: coverage-${{ matrix.python-version }}
include-hidden-files: true
path: .coverage
coverage:
name: process / coverage
runs-on: ubuntu-latest
timeout-minutes: 5
needs: [tests]
steps:
- *checkout
- name: Set up Python 3.13
id: python
uses: actions/setup-python@v6.0.0
with:
python-version: "3.13"
check-latest: true
- &cache-restore-python
name: Restore Python virtual environment
id: cache-venv
uses: actions/cache/restore@v4.3.0
with:
path: venv
fail-on-cache-miss: true
key:
${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
needs.tests.outputs.python-key }}
- name: Download all coverage artifacts
uses: actions/download-artifact@v5.0.0
- name: Combine coverage results
run: |
. venv/bin/activate
coverage combine coverage*/.coverage
coverage xml
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
fail_ci_if_error: true
verbose: true
benchmark-linux:
name: run benchmark / ${{ matrix.python-version }} / Linux
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [tests]
strategy:
fail-fast: false
matrix:
python-version: ["3.13"]
steps:
- *checkout
- *setup-python
- *cache-restore-python
- name: Run pytest
run: |
. venv/bin/activate
pip install pygal
pip install . --no-deps
pip list | grep 'astroid\|pylint'
pytest --exitfirst \
--benchmark-only \
--benchmark-autosave \
--benchmark-save-data \
--benchmark-group-by="group"
- name: Create partial artifact name suffix
id: artifact-name-suffix
run: >-
echo "datetime="$(date "+%Y%m%d_%H%M") >> $GITHUB_OUTPUT
- name: Upload benchmark artifact
uses: actions/upload-artifact@v4.6.2
with:
name:
benchmark-${{ runner.os }}-${{ matrix.python-version }}_${{
steps.artifact-name-suffix.outputs.datetime }}
include-hidden-files: true
path: .benchmarks/
tests-windows:
name: run / ${{ matrix.python-version }} / Windows
runs-on: windows-latest
timeout-minutes: 25
needs: [tests]
strategy:
fail-fast: false
matrix:
python-version: *matrix-python-version
steps:
- name: Set temp directory
run: echo "TEMP=$env:USERPROFILE\AppData\Local\Temp" >> $env:GITHUB_ENV
# Workaround to set correct temp directory on Windows
# https://github.com/actions/virtual-environments/issues/712
- *checkout
- *setup-python
- name: Generate partial Python venv restore key
id: generate-python-key
run: >-
echo "key=venv-${{ env.CACHE_VERSION }}-${{
hashFiles('pyproject.toml', 'requirements_test_min.txt')
}}" >> $env:GITHUB_OUTPUT
- *cache-python
- name: Create Python virtual environment
if: steps.cache-venv.outputs.cache-hit != 'true'
run: |
python -m venv venv
. venv\\Scripts\\activate
python -m pip install --upgrade pip
pip install --upgrade --requirement requirements_test_min.txt
- name: Run pytest
run: |
. venv\\Scripts\\activate
pip install . --no-deps
pip list | grep 'astroid\|pylint'
python -m pytest --durations=10 --benchmark-disable tests/

@ -0,0 +1,29 @@
# Do not add entries specific to your dev environment or development
# preferences in this file. You can use the global .gitignore for that:
# git config --global core.excludesFile '~/.gitignore'
/log
*.py[cod]
/build
/doc/_build
/dist/
/pylint.egg-info/
.tox
*.sw[a-z]
# Can't use | operator in .gitignore, see
# https://unix.stackexchange.com/a/31806/189111
doc/user_guide/messages/convention/
doc/user_guide/messages/error/
doc/user_guide/messages/fatal/
doc/user_guide/messages/information/
doc/user_guide/messages/refactor/
doc/user_guide/messages/warning/
tests/.pylint_primer_tests/
pyve
build-stamp
.coverage
.coverage.*
.cache/
.eggs/
.pytest_cache/
.mypy_cache/
.benchmarks/

@ -0,0 +1,174 @@
ci:
skip: [pylint]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: trailing-whitespace
exclude: tests(/\w*)*/functional/t/trailing_whitespaces.py|tests/pyreverse/data/.*.html|doc/data/messages/t/trailing-whitespace/bad.py
# - id: file-contents-sorter # commented out because it does not preserve comments order
# args: ["--ignore-case", "--unique"]
# files: "custom_dict.txt"
- id: end-of-file-fixer
exclude: |
(?x)^(
tests(/\w*)*/functional/m/missing/missing_final_newline.py|
tests/functional/t/trailing_newlines.py|
doc/data/messages/t/trailing-newlines/bad.py|
doc/data/messages/m/missing-final-newline/bad/lf.py|
doc/data/messages/m/missing-final-newline/bad/crlf.py
)$
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.14.0"
hooks:
- id: ruff-check
args: ["--fix"]
exclude: doc/data/messages
- id: ruff-check
name: ruff-doc
files: doc/data/messages
# Please exclude using doc/data/ruff.toml
# exclude: "" # Leave empty
- repo: https://github.com/Pierre-Sassoulas/copyright_notice_precommit
rev: 0.1.2
hooks:
- id: copyright-notice
args: ["--notice=script/copyright.txt", "--enforce-all"]
exclude: tests(/\w*)*/functional/|tests/input|doc/data/messages|examples/|setup.py|tests(/\w*)*data/
types: [python]
- repo: https://github.com/PyCQA/isort
rev: 7.0.0
hooks:
- id: isort
exclude: doc/data/messages/
- repo: https://github.com/psf/black-pre-commit-mirror
rev: 25.9.0
hooks:
- id: black
args: [--safe, --quiet]
exclude: &fixtures tests(/\w*)*/functional/|tests/input|doc/data/messages|tests(/\w*)*data/
- id: black
name: black-doc
args: [--safe, --quiet]
files: doc/data/messages/
exclude: |
(?x)^(
doc/data/messages/b/bad-indentation/bad.py|
doc/data/messages/i/inconsistent-quotes/bad.py|
doc/data/messages/i/invalid-format-index/bad.py|
doc/data/messages/l/line-too-long/bad.py|
doc/data/messages/m/missing-final-newline/bad/crlf.py|
doc/data/messages/m/missing-final-newline/bad/lf.py|
doc/data/messages/m/multiple-statements/bad.py|
doc/data/messages/r/redundant-u-string-prefix/bad.py|
doc/data/messages/s/superfluous-parens/bad/example_1.py|
doc/data/messages/s/syntax-error/bad.py|
doc/data/messages/t/too-many-ancestors/bad.py|
doc/data/messages/t/trailing-comma-tuple/bad.py|
doc/data/messages/t/trailing-newlines/bad.py|
doc/data/messages/t/trailing-whitespace/bad.py|
doc/data/messages/u/unnecessary-semicolon/bad.py
)$
- repo: https://github.com/Pierre-Sassoulas/black-disable-checker
rev: v1.1.3
hooks:
- id: black-disable-checker
- repo: local
hooks:
- id: pylint
name: pylint
entry: pylint
language: system
types: [python]
# Not that problematic to run in parallel see Pre-commit
# integration in the doc for details
# require_serial: true
args: ["-rn", "-sn", "--rcfile=pylintrc", "--fail-on=I"]
exclude: tests(/\w*)*/functional/|tests/input|tests(/\w*)*data/|doc/
- id: pyright
name: pyright
description: "Python command line wrapper for pyright, a static type checker"
entry: pyright
language: python
"types_or": [python, pyi]
require_serial: true
minimum_pre_commit_version: "2.9.2"
exclude: tests(/\w*)*/functional/|tests/input|tests(/.*)+/conftest.py|doc/data/messages|tests(/\w*)*data/
stages: [manual]
# We define an additional manual step to allow running pylint with a spelling
# checker in CI.
- id: pylint
alias: pylint-with-spelling
name: pylint
entry: pylint
language: system
types: [python]
args:
[
"-rn",
"-sn",
"--rcfile=pylintrc",
"--fail-on=I",
"--spelling-dict=en",
"--output-format=github",
]
exclude: tests(/\w*)*/functional/|tests/input|tests(/\w*)*data/|doc/
stages: [manual]
- id: check-newsfragments
name: Check newsfragments
entry: python3 -m script.check_newsfragments
language: system
types: [text]
files: ^(doc/whatsnew/fragments)
exclude: doc/whatsnew/fragments/_.*.rst
- repo: https://github.com/rstcheck/rstcheck
rev: "v6.2.5"
hooks:
- id: rstcheck
args: ["--report-level=warning"]
files: ^(doc/(.*/)*.*\.rst)
additional_dependencies: ["Sphinx==7.4.3"]
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.18.2
hooks:
- id: mypy
name: mypy
args: []
additional_dependencies:
["isort>=5", "platformdirs==2.2.0", "py==1.11", "tomlkit>=0.10.1"]
exclude: tests(/\w*)*/functional/|tests/input|tests(/.*)+/conftest.py|doc/data/messages|tests(/\w*)*data/
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.6.2
hooks:
- id: prettier
args: [--prose-wrap=always, --print-width=88]
exclude: (tests(/\w*)*data/|.github/FUNDING.yml)
- repo: https://github.com/DanielNoord/pydocstringformatter
rev: v0.7.5
hooks:
- id: pydocstringformatter
exclude: *fixtures
args: ["--max-summary-lines=2", "--linewrap-full-docstring"]
files: "pylint"
- repo: https://github.com/PyCQA/bandit
rev: 1.8.6
hooks:
- id: bandit
args: ["-r", "-lll"]
exclude: *fixtures
- repo: https://github.com/codespell-project/codespell
rev: v2.4.1
hooks:
- id: codespell
args: ["--toml=pyproject.toml"]
additional_dependencies:
- tomli
- repo: https://github.com/tox-dev/pyproject-fmt
rev: "v2.10.0"
hooks:
- id: pyproject-fmt
- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.24.1
hooks:
- id: validate-pyproject

@ -0,0 +1,6 @@
- id: pylint
name: pylint
entry: pylint
language: python
types: [python]
require_serial: true

@ -0,0 +1,19 @@
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
version: 2
sphinx:
fail_on_warning: true
configuration: doc/conf.py
python:
install:
- requirements: doc/readthedoc_requirements.txt
build:
os: ubuntu-22.04
tools:
python: "3.11"
jobs:
pre_build:
- towncrier build --yes --date TBA

@ -0,0 +1,14 @@
cff-version: 1.2.0
title: "Pylint"
message: >-
If you use this software, please cite it using the metadata from this file.
type: software
authors:
- name: "Pylint contributors"
repository-code: "https://github.com/pylint-dev/pylint"
url: "https://pylint.readthedocs.io/en/latest/"
abstract: >-
Pylint is a static code analyser for Python 2 or 3. Pylint analyses your code without
actually running it. It checks for errors, enforces a coding standard, looks for code
smells, and can make suggestions about how the code could be refactored.
license: GPL-2.0

@ -0,0 +1,120 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our community a
harassment-free experience for everyone, regardless of age, body size, visible or
invisible disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming, diverse,
inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our community
include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes, and
learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or advances of any
kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without
their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional
setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in response to
any behavior that they deem inappropriate, threatening, offensive, or harmful.
Community leaders have the right and responsibility to remove, edit, or reject comments,
commits, code, wiki edits, issues, and other contributions that are not aligned to this
Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when an
individual is officially representing the community in public spaces. Examples of
representing our community include using an official e-mail address, posting via an
official social media account, or acting as an appointed representative at an online or
offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to
the community leaders responsible for enforcement at pierre.sassoulas at gmail.com. All
complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the reporter
of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining the
consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing clarity
around the nature of the violation and an explanation of why the behavior was
inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of actions.
**Consequence**: A warning with consequences for continued behavior. No interaction with
the people involved, including unsolicited interaction with those enforcing the Code of
Conduct, for a specified period of time. This includes avoiding interactions in
community spaces as well as external channels like social media. Violating these terms
may lead to a temporary or permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including sustained
inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public communication
with the community for a specified period of time. No public or private interaction with
the people involved, including unsolicited interaction with those enforcing the Code of
Conduct, is allowed during this period. Violating these terms may lead to a permanent
ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community standards,
including sustained inappropriate behavior, harassment of an individual, or aggression
toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

@ -0,0 +1,699 @@
# This file is autocompleted by 'contributors-txt',
# using the configuration in 'script/.contributors_aliases.json'.
# Do not add new persons manually and only add information without
# using '-' as the line first character.
# Please verify that your change are stable if you modify manually.
Ex-maintainers
--------------
- Claudiu Popa <pcmanticore@gmail.com>
- Sylvain Thénault <thenault@gmail.com> : main author / maintainer
- Torsten Marek <shlomme@gmail.com>
Maintainers
-----------
- Pierre Sassoulas <pierre.sassoulas@gmail.com>
- Daniël van Noord <13665637+DanielNoord@users.noreply.github.com>
- Jacob Walls <jacobtylerwalls@gmail.com>
- Marc Mueller <30130371+cdce8p@users.noreply.github.com>
- Hippo91 <guillaume.peillex@gmail.com>
- Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com>
- Andreas Finkler <3929834+DudeNr33@users.noreply.github.com>
- Matus Valo <matusvalo@users.noreply.github.com>
- Dani Alcala <112832187+clavedeluna@users.noreply.github.com>
- Łukasz Rogalski <rogalski.91@gmail.com>
- Nick Drozd <nicholasdrozd@gmail.com>: performance improvements to astroid
- Ashley Whetter <ashley@awhetter.co.uk>
- Bryce Guinta <bryce.paul.guinta@gmail.com>
- Yu Shao, Pang <36848472+yushao2@users.noreply.github.com>
- Dimitri Prybysh <dmand@yandex.ru>
* multiple-imports, not-iterable, not-a-mapping, various patches.
- Roy Williams <roy.williams.iii@gmail.com> (Lyft)
* added check for implementing __eq__ without implementing __hash__,
* Added Python 3 check for accessing Exception.message.
* Added Python 3 check for calling encode/decode with invalid codecs.
* Added Python 3 check for accessing sys.maxint.
* Added Python 3 check for bad import statements.
* Added Python 3 check for accessing deprecated methods on the 'string' module,
various patches.
- Florian Bruhin <me@the-compiler.org>
- Arianna Yang <areveny@protonmail.com>
Contributors
------------
We would not be here without folks that contributed patches, pull requests,
issues and their time to pylint. We're incredibly grateful to all of these
contributors:
- Emile Anclin <emile.anclin@logilab.fr> (Logilab): python 3 support
- Michal Nowikowski <godfryd@gmail.com>:
* wrong-spelling-in-comment
* wrong-spelling-in-docstring
* parallel execution on multiple CPUs
- Julthep Nandakwang <julthep@nandakwang.com>
- Bruno Daniel <bruno.daniel@blue-yonder.com>: check_docs extension.
- Sushobhit <31987769+sushobhit27@users.noreply.github.com> (sushobhit27)
* Added new check 'comparison-with-itself'.
* Added new check 'useless-import-alias'.
* Added support of annotations in missing-type-doc and missing-return-type-doc.
* Added new check 'comparison-with-callable'.
* Removed six package dependency.
* Added new check 'chained-comparison'.
* Added new check 'useless-object-inheritance'.
- Brett Cannon <brett@python.org>:
* Port source code to be Python 2/3 compatible
* Python 3 checker
- Laura Médioni <laura.medioni@logilab.fr> (Logilab, on behalf of the CNES):
* misplaced-comparison-constant
* no-classmethod-decorator
* no-staticmethod-decorator
* too-many-nested-blocks,
* too-many-boolean-expressions
* unneeded-not
* wrong-import-order
* ungrouped-imports,
* wrong-import-position
* redefined-variable-type
- Harutaka Kawamura <hkawamura0130@gmail.com>
- Alexandre Fayolle <alexandre.fayolle@logilab.fr> (Logilab): TkInter gui, documentation, debian support
- Ville Skyttä <ville.skytta@iki.fi>
- Zen Lee <53538590+zenlyj@users.noreply.github.com>
- Julien Cristau <julien.cristau@logilab.fr> (Logilab): python 3 support
- Moisés López <6644187+moylop260@users.noreply.github.com>:
* Support for deprecated-modules in modules not installed,
* Refactor wrong-import-order to integrate it with `isort` library
* Add check too-complex with mccabe for cyclomatic complexity
* Refactor wrong-import-position to skip try-import and nested cases
* Add consider-merging-isinstance, superfluous-else-return
* Fix consider-using-ternary for 'True and True and True or True' case
* Add bad-docstring-quotes and docstring-first-line-empty
* Add missing-timeout
* Fix false negative for `deprecated-module` when a `__import__` method is used instead of `import` sentence
- Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
- Frank Harrison <frank@doublethefish.com> (doublethefish)
- Pierre-Yves David <pierre-yves.david@logilab.fr>
- David Shea <dshea@redhat.com>: invalid sequence and slice index
- Gunung P. Wibisono <55311527+gunungpw@users.noreply.github.com>
- Derek Gustafson <degustaf@gmail.com>
- Cezar Elnazli <cezar.elnazli2@gmail.com>: deprecated-method
- Joseph Young <80432516+jpy-git@users.noreply.github.com> (jpy-git)
- Tim Martin <tim@asymptotic.co.uk>
- Ollie <46904826+ollie-iterators@users.noreply.github.com>
- Julian Grimm <51880314+Julfried@users.noreply.github.com>
- Tushar Sadhwani <tushar.sadhwani000@gmail.com> (tusharsadhwani)
- Nicolas Chauvat <nicolas.chauvat@logilab.fr>
- orSolocate <38433858+orSolocate@users.noreply.github.com>
- Radu Ciorba <radu@devrandom.ro>: not-context-manager and confusing-with-statement warnings.
- Holger Peters <email@holger-peters.de>
- Cosmin Poieană <cmin@ropython.org>: unichr-builtin and improvements to bad-open-mode.
- Yilei "Dolee" Yang <yileiyang@google.com>
- Steven Myint <hg@stevenmyint.com>: duplicate-except.
- Peter Kolbus <peter.kolbus@gmail.com> (Garmin)
- Luigi Bertaco Cristofolini <lucristofolini@gmail.com> (luigibertaco)
- Glenn Matthews <glenn@e-dad.net>:
* autogenerated documentation for optional extensions,
* bug fixes and enhancements for docparams (née check_docs) extension
- crazybolillo <antonio@zoftko.com>
- correctmost <134317971+correctmost@users.noreply.github.com>
- Vlad Temian <vladtemian@gmail.com>: redundant-unittest-assert and the JSON reporter.
- Julien Jehannet <julien.jehannet@logilab.fr>
- Boris Feld <lothiraldan@gmail.com>
- Anthony Sottile <asottile@umich.edu>
- Andrew Haigh <nelfin@gmail.com> (nelfin)
- Robert Hofer <hofrob@protonmail.com>
- Pedro Algarvio <pedro@algarvio.me> (s0undt3ch)
- Julien Palard <julien@palard.fr>
- Hugo van Kemenade <hugovk@users.noreply.github.com>
- David Liu <david@cs.toronto.edu> (david-yz-liu)
- Dan Goldsmith <djgoldsmith@googlemail.com>: support for msg-template in HTML reporter.
- Buck Evan <buck.2019@gmail.com>
- Mariatta Wijaya <Mariatta@users.noreply.github.com>
* Added new check `logging-fstring-interpolation`
* Documentation typo fixes
- Jakub Wilk <jwilk@jwilk.net>
- Eli Fine <ejfine@gmail.com> (eli88fine): Fixed false positive duplicate code warning for lines with symbols only
- Émile Crater <emile@crater.logilab.fr>
- Pavel Roskin <proski@gnu.org>
- David Gilman <davidgilman1@gmail.com>
- へーさん <hira9603859504@gmail.com>
- Thomas Hisch <t.hisch@gmail.com>
- Marianna Polatoglou <mpolatoglou@bloomberg.net>: minor contribution for wildcard import check
- Manuel Vázquez Acosta <mva.led@gmail.com>
- Luis Escobar <lescobar@vauxoo.com> (Vauxoo): Add bad-docstring-quotes and docstring-first-line-empty
- Lucas Cimon <lucas.cimon@gmail.com>
- Konstantina Saketou <56515303+ksaketou@users.noreply.github.com>
- Konstantin <Github@pheanex.de>
- Jim Robertson <jrobertson98atx@gmail.com>
- Ethan Leba <ethanleba5@gmail.com>
- Enji Cooper <yaneurabeya@gmail.com>
- Drum Ogilvie <me@daogilvie.com>
- David Lindquist <dlindquist@google.com>: logging-format-interpolation warning.
- Daniel Harding <dharding@gmail.com>
- Anthony Truchet <anthony.truchet@logilab.fr>
- Alexander Todorov <atodorov@otb.bg>:
* added new error conditions to 'bad-super-call',
* Added new check for incorrect len(SEQUENCE) usage,
* Added new extension for comparison against empty string constants,
* Added new extension which detects comparing integers to zero,
* Added new useless-return checker,
* Added new try-except-raise checker
- theirix <theirix@gmail.com>
- Téo Bouvard <teobouvard@gmail.com>
- Sviatoslav Sydorenko <sviat@redhat.com>
- Stavros Ntentos <133706+stdedos@users.noreply.github.com>
- Nicolas Boulenguez <nicolas@debian.org>
- Mihai Balint <balint.mihai@gmail.com>
- Mark Bell <mark00bell@googlemail.com>
- Levi Gruspe <mail.levig@gmail.com>
- Jakub Kuczys <me@jacken.men>
- Hornwitser <github@hornwitser.no>: fix import graph
- Fureigh <rhys.fureigh@gsa.gov>
- David Douard <david.douard@sdfa3.org>
- Daniel Balparda <balparda@google.com> (Google): GPyLint maintainer (Google's pylint variant)
- Christian Clauss <cclauss@me.com>
- Bastien Vallet <bastien.vallet@gmail.com> (Djailla)
- Aru Sahni <arusahni@gmail.com>: Git ignoring, regex-based ignores
- Andreas Freimuth <andreas.freimuth@united-bits.de>: fix indentation checking with tabs
- Alexandru Coman <fcoman@bitdefender.com>
- jpkotta <jpkotta@gmail.com>
- Thomas Grainger <tagrain@gmail.com>
- Takahide Nojima <nozzy123nozzy@gmail.com>
- Taewon D. Kim <kimt33@mcmaster.ca>
- Sneaky Pete <sneakypete81@gmail.com>
- Sergey B Kirpichev <skirpichev@gmail.com>
- Sandro Tosi <sandro.tosi@gmail.com>: Debian packaging
- Rogdham <contact@rogdham.net>
- Rene Zhang <rz99@cornell.edu>
- Paul Lichtenberger <paul.lichtenberger.rgbg@gmail.com>
- Or Bahari <or.ba402@gmail.com>
- Mr. Senko <atodorov@mrsenko.com>
- Mike Frysinger <vapier@gmail.com>
- Martin von Gagern <gagern@google.com> (Google): Added 'raising-format-tuple' warning.
- Martin Vielsmaier <martin@vielsmaier.net>
- Martin Pool <mbp@google.com> (Google):
* warnings for anomalous backslashes
* symbolic names for messages (like 'unused')
* etc.
- Martin Bašti <MartinBasti@users.noreply.github.com>
* Added new check for shallow copy of os.environ
* Added new check for useless `with threading.Lock():` statement
- Marcus Näslund <naslundx@gmail.com> (naslundx)
- Marco Pernigotti <7657251+mpernigo@users.noreply.github.com>
- Marco Forte <fortemarco.irl@gmail.com>
- James Addison <55152140+jayaddison@users.noreply.github.com>
- Ionel Maries Cristian <contact@ionelmc.ro>
- Gergely Kalmár <gergely.kalmar@logikal.jp>
- Damien Baty <damien.baty@polyconseil.fr>
- Benjamin Drung <benjamin.drung@profitbricks.com>: contributing Debian Developer
- Anubhav <35621759+anubh-v@users.noreply.github.com>
- Antonio Quarta <sgheppy88@gmail.com>
- Andrew J. Simmons <anjsimmo@gmail.com>
- Alvaro Frias <alvarofriasgaray@gmail.com>
- Alexey Pelykh <alexey.pelykh@gmail.com>
- Alex Prabhat Bara <alexpbara@gmail.com>
- wtracy <afishionado@gmail.com>
- jessebrennan <jesse@jesse.computer>
- chohner <mail@chohner.com>
- aatle <168398276+aatle@users.noreply.github.com>
- Tiago Honorato <61059243+tiagohonorato@users.noreply.github.com>
- Steven M. Vascellaro <svascellaro@gmail.com>
- Robin Tweedie <70587124+robin-wayve@users.noreply.github.com>
- Roberto Leinardi <leinardi@gmail.com>: PyCharm plugin maintainer
- Ricardo Gemignani <ricardo.gemignani@gmail.com>
- Piotr Idzik <65706193+vil02@users.noreply.github.com>
- Pieter Engelbrecht <pengelbrecht@rems2.com>
- Philipp Albrecht <flying-sheep@web.de> (pylbrecht)
- Nicolas Dickreuter <dickreuter@gmail.com>
- Nick Bastin <nick.bastin@gmail.com>
- Nathaniel Manista <nathaniel@google.com>: suspicious lambda checking
- Maksym Humetskyi <Humetsky@gmail.com> (mhumetskyi)
* Fixed ignored empty functions by similarities checker with "ignore-signatures" option enabled
* Ignore function decorators signatures as well by similarities checker with "ignore-signatures" option enabled
* Ignore class methods and nested functions signatures as well by similarities checker with "ignore-signatures" option enabled
- Kylian <development@goudcode.nl>
- Konstantin Manna <Konstantin@Manna.uno>
- Kai Mueller <15907922+kasium@users.noreply.github.com>
- Joshua Cannon <joshdcannon@gmail.com>
- John Leach <jfleach@jfleach.com>
- James Morgensen <james.morgensen@gmail.com>: ignored-modules option applies to import errors.
- Jaehoon Hwang <jaehoonhwang@users.noreply.github.com> (jaehoonhwang)
- Huw Jones <huw@huwcbjones.co.uk>
- Gideon <87426140+GideonBear@users.noreply.github.com>
- Ganden Schaffner <gschaffner@pm.me>
- Frost Ming <frostming@tencent.com>
- Federico Bond <federicobond@gmail.com>
- Erik Wright <erik.wright@shopify.com>
- Erik Eriksson <molobrakos@users.noreply.github.com>: Added overlapping-except error check.
- Emmanuel Ferdman <emmanuelferdman@gmail.com>
- Dave Bunten <dave.bunten@cuanschutz.edu>
- Daniel Wang <danielwang405@gmail.com>
- Daniel Mouritzen <dmrtzn@gmail.com>
- Dan Hemberger <846186+hemberger@users.noreply.github.com>
- Chris Rebert <code@rebertia.com>: unidiomatic-typecheck.
- Aurelien Campeas <aurelien.campeas@logilab.fr>
- Alexander Pervakov <frost.nzcr4@jagmort.com>
- Alain Leufroy <alain.leufroy@logilab.fr>
- Akhil Kamat <akhil.kamat@gmail.com>
- Adam Williamson <awilliam@redhat.com>
- Aaron Liu <aaronliu0130@gmail.com>
- xmo-odoo <xmo-odoo@users.noreply.github.com>
- tbennett0 <tbennett0@users.noreply.github.com>
- purajit <7026198+purajit@users.noreply.github.com>
- omarandlorraine <64254276+omarandlorraine@users.noreply.github.com>
- craig-sh <craig-sh@users.noreply.github.com>
- bernie gray <bfgray3@users.noreply.github.com>
- azinneck0485 <123660683+azinneck0485@users.noreply.github.com>
- Wing Lian <wing.lian@gmail.com>
- Wes Turner <westurner@google.com> (Google): added new check 'inconsistent-quotes'
- Tyler Thieding <tyler@thieding.com>
- Tobias Hernstig <30827238+thernstig@users.noreply.github.com>
- Smixi <sismixx@hotmail.fr>
- Simu Toni <simutoni@gmail.com>
- Sergei Lebedev <185856+superbobry@users.noreply.github.com>
- Scott Worley <scottworley@scottworley.com>
- Saugat Pachhai <suagatchhetri@outlook.com>
- Samuel FORESTIER <HorlogeSkynet@users.noreply.github.com>
- Rémi Cardona <remi.cardona@polyconseil.fr>
- Ryan Ozawa <ryan.ozawa21@gmail.com>
- Roger Sheu <78449574+rogersheu@users.noreply.github.com>
- Raphael Gaschignard <raphael@makeleaps.com>
- Ram Rachum <ram@rachum.com> (cool-RR)
- Radostin Stoyanov <rst0git@users.noreply.github.com>
- Peter Bittner <django@bittner.it>
- Paul Renvoisé <PaulRenvoise@users.noreply.github.com>
- PHeanEX <github@pheanex.de>
- Omega Weapon <OmegaPhil+hg@gmail.com>
- Nikolai Kristiansen <nikolaik@gmail.com>
- Nick Pesce <nickpesce22@gmail.com>
- Nedelcu Ioan-Andrei <138256980+nedelcu-ioan@users.noreply.github.com>
- Nathan Marrow <nmarrow@google.com>
- Mikhail Fesenko <m.fesenko@corp.vk.com>
- Matthew Suozzo <msuozzo@google.com>
- Matthew Beckers <17108752+mattlbeck@users.noreply.github.com> (mattlbeck)
- Mark Roman Miller <mtmiller@users.noreply.github.com>: fix inline defs in too-many-statements
- MalanB <malan.kmu@gmail.com>
- Mads Kiilerich <mads@kiilerich.com>
- Maarten ter Huurne <maarten@treewalker.org>
- Lefteris Karapetsas <lefteris@refu.co>
- LCD 47 <lcd047@gmail.com>
- Jérome Perrin <perrinjerome@gmail.com>
- Justin Li <justinnhli@gmail.com>
- John Kirkham <jakirkham@gmail.com>
- Jens H. Nielsen <Jens.Nielsen@microsoft.com>
- Jake Lishman <jake.lishman@ibm.com>
- Ioana Tagirta <ioana.tagirta@gmail.com>: fix bad thread instantiation check
- Ikraduya Edian <ikraduya@gmail.com>: Added new checks 'consider-using-generator' and 'use-a-generator'.
- Hugues Bruant <hugues.bruant@affirm.com>
- Hashem Nasarat <Hnasar@users.noreply.github.com>
- Harut <yes@harutune.name>
- Grygorii Iermolenko <gyermolenko@gmail.com>
- Grizzly Nyo <grizzly.nyo@gmail.com>
- Gabriel R. Sezefredo <g@briel.dev>: Fixed "exception-escape" false positive with generators
- Filipe Brandenburger <filbranden@google.com>
- Fantix King <fantix@uchicago.edu> (UChicago)
- Eric McDonald <221418+emcd@users.noreply.github.com>
- Elias Dorneles <eliasdorneles@gmail.com>: minor adjust to config defaults and docs
- Elazrod56 <thomas.lf5629@gmail.com>
- Edward K. Ream <edreamleo@gmail.com>
- Derek Harland <derek.harland@finq.co.nz>
- David Pursehouse <david.pursehouse@gmail.com>
- Daniel Miller <millerdev@gmail.com>
- Christoph Blessing <33834216+cblessing24@users.noreply.github.com>
- Chris Murray <chris@chrismurray.scot>
- Chris Lamb <chris@chris-lamb.co.uk>
- Charles Hebert <charles.hebert@logilab.fr>
- Carli Freudenberg <carli.freudenberg@energymeteo.de> (CarliJoy)
* Fixed issue 5281, added Unicode checker
* Improve non-ascii-name checker
- Bruce Dawson <randomascii@users.noreply.github.com>
- Brian Shaginaw <brian.shaginaw@warbyparker.com>: prevent error on exception check for functions
- Benny Mueller <benny.mueller91@gmail.com>
- Ben James <benjames1999@hotmail.co.uk>
- Ben Green <benhgreen@icloud.com>
- Batuhan Taskaya <batuhanosmantaskaya@gmail.com>
- Artem Yurchenko <artemyurchenko@zoho.com>
- Alexander Kapshuna <kapsh@kap.sh>
- Akshay Choudhary <153769403+Akshay9715@users.noreply.github.com>
- Adam Parkin <pzelnip@users.noreply.github.com>
- 谭九鼎 <109224573@qq.com>
- Łukasz Sznuk <ls@rdprojekt.pl>
- zasca <gorstav@gmail.com>
- y2kbugger <y2kbugger@users.noreply.github.com>
- vinnyrose <vinnyrose@users.noreply.github.com>
- ttenhoeve-aa <ttenhoeve@appannie.com>
- thinwybk <florian.k@mailbox.org>
- temyurchenko <44875844+temyurchenko@users.noreply.github.com>
- syutbai <syutbai@gmail.com>
- sur.la.route <17788706+christopherpickering@users.noreply.github.com>
- sdet_liang <liangway@users.noreply.github.com>
- pavan-msys <149513767+pavan-msys@users.noreply.github.com>
- paschich <millen@gridium.com>
- oittaa <8972248+oittaa@users.noreply.github.com>
- nyabkun <75878387+nyabkun@users.noreply.github.com>
- nhdsd <wyx070906@outlook.com>
- moxian <aleftmail@inbox.ru>
- mar-chi-pan <mar.polatoglou@gmail.com>
- lrjball <50599110+lrjball@users.noreply.github.com>
- levon-d <mycroft2003@gmail.com>
- laike9m <laike9m@users.noreply.github.com>
- kyoto7250 <50972773+kyoto7250@users.noreply.github.com>
- kriek <sylvain.ackermann@gmail.com>
- kdestin <101366538+kdestin@users.noreply.github.com>
- jaydesl <35102795+jaydesl@users.noreply.github.com>
- jab <jab@users.noreply.github.com>
- gracejiang16 <70730457+gracejiang16@users.noreply.github.com>
- glmdgrielson <32415403+glmdgrielson@users.noreply.github.com>
- glegoux <gilles.legoux@gmail.com>
- gaurikholkar <f2013002@goa.bits-pilani.ac.in>
- flyingbot91 <flyingbot91@gmx.com>
- fly <fly@users.noreply.github.com>
- fahhem <fahhem>
- fadedDexofan <fadedDexofan@gmail.com>
- epenet <6771947+epenet@users.noreply.github.com>
- danields <danields761@gmail.com>
- cosven <cosven@users.noreply.github.com>
- cordis-dev <darius@adroiti.com>
- cherryblossom <31467609+cherryblossom000@users.noreply.github.com>
- bluesheeptoken <louis.fruleux1@gmail.com>
- anatoly techtonik <techtonik@gmail.com>
- amelenty <ada.melentyeva@gmail.com>
- akirchhoff-modular <github-work@kirchhoff.digital>
- agutole <toldo_carp@hotmail.com>
- Zeckie <49095968+Zeckie@users.noreply.github.com>
- Zeb Nicholls <zebedee.nicholls@climate-energy-college.org>
* Made W9011 compatible with 'of' syntax in return types
- Yuval Langer <yuvallanger@mail.tau.ac.il>
- Yury Gribov <tetra2005@gmail.com>
- Yuri Bochkarev <baltazar.bz@gmail.com>: Added epytext support to docparams extension.
- Youngsoo Sung <ysung@bepro11.com>
- Yory <39745367+yory8@users.noreply.github.com>
- Yoichi Nakayama <yoichi.nakayama@gmail.com>
- Yeting Li <liyt@ios.ac.cn> (yetingli)
- Yannack <yannack@users.noreply.github.com>
- Yann Dirson <ydirson@free.fr>
- Yang Yang <y4n9squared@gmail.com>
- Xi Shen <davidshen84@gmail.com>
- Winston H <56998716+winstxnhdw@users.noreply.github.com>
- Will Shanks <wsha@posteo.net>
- Viorel Știrbu <viorels@gmail.com>: intern-builtin warning.
- VictorT <victor.taix@gmail.com>
- Victor Jiajunsu <16359131+jiajunsu@users.noreply.github.com>
- ViRuSTriNiTy <cradle-of-mail@gmx.de>
- Val Lorentz <progval+github@progval.net>
- Ulrich Eckhardt <UlrichEckhardt@users.noreply.github.com>
- Udi Fuchs <udifuchs@gmail.com>
- Trevor Bekolay <tbekolay@gmail.com>
* Added --list-msgs-enabled command
- Tomer Chachamu <tomer.chachamu@gmail.com>: simplifiable-if-expression
- Tomasz Michalski <tomasz.michalski@rtbhouse.com>
- Tomasz Magulski <tomasz@magullab.io>
- Tom <tsarantis@proton.me>
- Tim Hatch <tim@timhatch.com>
- Tim Gates <tim.gates@iress.com>
- Tianyu Chen <124018391+UTsweetyfish@users.noreply.github.com>
- Théo Battrel <theo.util@protonmail.ch>
- Thomas Benhamou <thomas@lightricks.com>
- Theodore Ni <3806110+tjni@users.noreply.github.com>
- Tanvi Moharir <74228962+tanvimoharir@users.noreply.github.com>: Fix for invalid toml config
- T.Rzepka <Tobias.Rzepka@gmail.com>
- Svetoslav Neykov <svet@hyperscience.com>
- SubaruArai <78188579+SubaruArai@users.noreply.github.com>
- Stéphane Wirtel <stephane@wirtel.be>: nonlocal-without-binding
- Stephen Longofono <8992396+SLongofono@users.noreply.github.com>
- Stephane Odul <1504511+sodul@users.noreply.github.com>
- Stanislav Levin <slev@altlinux.org>
- Sorin Sbarnea <ssbarnea@redhat.com>
- Slavfox <slavfoxman@gmail.com>
- Skip Montanaro <skip@pobox.com>
- Sigurd Spieckermann <2206639+sisp@users.noreply.github.com>
- Shiv Venkatasubrahmanyam <shvenkat@users.noreply.github.com>
- Sebastian Müller <mueller.seb@posteo.de>
- Sayyed Faisal Ali <80758388+C0DE-SLAYER@users.noreply.github.com>
- Sasha Bagan <pnlbagan@gmail.com>
- Sardorbek Imomaliev <sardorbek.imomaliev@gmail.com>
- Santiago Castro <bryant@montevideo.com.uy>
- Samuel Freilich <sfreilich@google.com> (sfreilich)
- Sam Vermeiren <88253337+PaaEl@users.noreply.github.com>
- Ryan McGuire <ryan@enigmacurry.com>
- Ry4an Brase <ry4an-hg@ry4an.org>
- Ruro <ruro.ruro@ya.ru>
- Roshan Shetty <roshan.shetty2816@gmail.com>
- Roman Ivanov <me@roivanov.com>
- Robert Schweizer <robert_schweizer@gmx.de>
- Reverb Chu <reverbc@users.noreply.github.com>
- Renat Galimov <renat2017@gmail.com>
- Rebecca Turner <rbt@sent.as> (9999years)
- Randall Leeds <randall@bleeds.info>
- Ranadheer Gorrepati <35244169+ranadheerg@users.noreply.github.com>
- Ramon Saraiva <ramonsaraiva@gmail.com>
- Ramiro Leal-Cavazos <ramiroleal050@gmail.com> (ramiro050): Fixed bug preventing pylint from working with Emacs tramp
- RSTdefg <34202999+RSTdefg@users.noreply.github.com>
- R. N. West <98110034+rnwst@users.noreply.github.com>
- Qwiddle13 <32040075+Qwiddle13@users.noreply.github.com>
- Quentin Young <qlyoung@users.noreply.github.com>
- Prajwal Borkar <sunnyborkar7777@gmail.com>
- Petr Pulc <petrpulc@gmail.com>: require whitespace around annotations
- Peter Dawyndt <Peter.Dawyndt@UGent.be>
- Peter Dave Hello <hsu@peterdavehello.org>
- Peter Aronoff <peter@aronoff.org>
- Paul Cochrane <paul@liekut.de>
- Patrik <patrik.mrx@gmail.com>
- Pascal Corpet <pcorpet@users.noreply.github.com>
- Pablo Galindo Salgado <Pablogsal@gmail.com>
* Fix false positive 'Non-iterable value' with async comprehensions.
- Osher De Paz <odepaz@redhat.com>
- Oisín Moran <OisinMoran@users.noreply.github.com>
- Obscuron <Abscuron@gmail.com>
- Noam Yorav-Raphael <noamraph@gmail.com>
- Noah-Agnel <138210920+Noah-Agnel@users.noreply.github.com>
- Nir Soffer <nirsof@gmail.com>
- Niko Wenselowski <niko@nerdno.de>
- Nikita Sobolev <mail@sobolevn.me>
- Nick Smith <clickthisnick@users.noreply.github.com>
- Neowizard <Neowizard@users.noreply.github.com>
- Ned Batchelder <ned@nedbatchelder.com>
- Natalie Serebryakova <natalie.serebryakova@Natalies-MacBook-Pro.local>
- Naglis Jonaitis <827324+naglis@users.noreply.github.com>
- Moody <mooodyhunter@outlook.com>
- Mitchell Young <mitchelly@gmail.com>: minor adjustment to docparams
- Mitar <mitar.github@tnode.com>
- Ming Lyu <CareF.Lm@gmail.com>
- Mikhail f. Shiryaev <mr.felixoid@gmail.com>
- Mike Fiedler <miketheman@gmail.com> (miketheman)
- Mike Bryant <leachim@leachim.info>
- Mike Bernard <mdbernard@pm.me>
- Michka Popoff <michkapopoff@gmail.com>
- Michal Vasilek <michal@vasilek.cz>
- Michael Scott Cuthbert <cuthbert@mit.edu>
- Michael Kefeder <oss@multiwave.ch>
- Michael K <michael-k@users.noreply.github.com>
- Michael Hudson-Doyle <michael.hudson@canonical.com>
- Michael Giuffrida <mgiuffrida@users.noreply.github.com>
- Melvin Hazeleger <31448155+melvio@users.noreply.github.com>
- Meltem Kenis <meltem.kenis@plentific.com>
- Mehdi Drissi <mdrissi@hmc.edu>
- Matěj Grabovský <mgrabovs@redhat.com>
- Matthijs Blom <19817960+MatthijsBlom@users.noreply.github.com>
- Matej Spiller Muys <matej.spiller-muys@bitstamp.net>
- Matej Marušák <marusak.matej@gmail.com>
- Marzuk Rashid <mail@marzuk.io>
- Markus Siebenhaar <41283549+siehar@users.noreply.github.com>
- Marco Edward Gorelli <marcogorelli@protonmail.com>: Documented Jupyter integration
- Marcin Kurczewski <rr-@sakuya.pl> (rr-)
- Maik Röder <maikroeder@gmail.com>
- Lumír 'Frenzy' Balhar <frenzy.madness@gmail.com>
- Ludovic Aubry <ludal@logilab.fr>
- Louis Sautier <sautier.louis@gmail.com>
- Lorena Buciu <46202743+lorena-b@users.noreply.github.com>
- Logan Miller <14319179+komodo472@users.noreply.github.com>
- Kári Tristan Helgason <kthelgason@gmail.com>
- Kurian Benoy <70306694+kurianbenoy-aot@users.noreply.github.com>
- Krzysztof Czapla <k.czapla68@gmail.com>
- Kraig Brockschmidt <kraigbr@msn.com>
- Kound <norman.freudenberg@posteo.de>
- KotlinIsland <65446343+KotlinIsland@users.noreply.github.com>
- Kosarchuk Sergey <sergeykosarchuk@gmail.com>
- Konrad Weihmann <46938494+priv-kweihmann@users.noreply.github.com>
- Kian Meng, Ang <kianmeng.ang@gmail.com>
- Kevin Phillips <thefriendlycoder@gmail.com>
- Kevin Jing Qiu <kevin.jing.qiu@gmail.com>
- Kenneth Schackart <schackartk1@gmail.com>
- Kayran Schmidt <59456929+yumasheta@users.noreply.github.com>
- Karthik Nadig <kanadig@microsoft.com>
- Jürgen Hermann <jh@web.de>
- Josselin Feist <josselin@trailofbits.com>
- Jonathan Kotta <KottaJonathan@JohnDeere.com>
- John Paraskevopoulos <io.paraskev@gmail.com>: add 'differing-param-doc' and 'differing-type-doc'
- John McGehee <jmcgehee@altera.com>
- John Gabriele <jgabriele@fastmail.fm>
- John Belmonte <john@neggie.net>
- Johannes Maron <johannes@maron.family>
- Joffrey Mander <joffrey.mander+pro@gmail.com>
- Jochen Preusche <iilei@users.noreply.github.com>
- Jeroen Seegers <jeroenseegers@users.noreply.github.com>:
* Fixed `toml` dependency issue
- Jeremy Fleischman <jeremyfleischman@gmail.com>
- Jason Owen <jason.a.owen@gmail.com>
- Jason Lau <github.com@dotkr.nl>
- Jared Garst <cultofjared@gmail.com>
- Jared Deckard <jared.deckard@gmail.com>
- Janne Rönkkö <jannero@users.noreply.github.com>
- Jamie Scott <jamie@jami.org.uk>
- James Sinclair <james@nurfherder.com>
- James M. Allen <james.m.allen@gmail.com>
- James Lingard <jchl@aristanetworks.com>
- James Broadhead <jamesbroadhead@gmail.com>
- Jakub Kulík <Kulikjak@gmail.com>
- Jakob Normark <jakobnormark@gmail.com>
- Jacques Kvam <jwkvam@gmail.com>
- Jace Browning <jacebrowning@gmail.com>: updated default report format with clickable paths
- JZ <jzohrab@gmail.com>
- JT Olds <jtolds@xnet5.com>
- Iggy Eom <iggy.eom@sendbird.com>
- Ige-kun <178478713+Ige-kun@users.noreply.github.com>
- Hayden Richards <62866982+SupImDos@users.noreply.github.com>
* Fixed "no-self-use" for async methods
* Fixed "docparams" extension for async functions and methods
- Harshil <37377066+harshil21@users.noreply.github.com>
- Harry <harrymcwinters@gmail.com>
- Gwanbin Park <bgb1028@gmail.com>
- Grégoire <96051754+gregoire-mullvad@users.noreply.github.com>
- Grant Welch <gwelch925+github@gmail.com>
- Giuseppe Valente <gvalente@arista.com>
- Gary Tyler McLeod <mail@garytyler.com>
- Felix von Drigalski <FvDrigalski@gmail.com>
- Felix Preuschoff <37065638+felixp98@users.noreply.github.com>
- Fabrice Douchant <Fabrice.Douchant@logilab.fr>
- Fabio Natali <me@fabionatali.com>
- Fabian Damken <fdamken+github@frisp.org>
- Eric Froemling <ericfroemling@gmail.com>
- Emmanuel Chaudron <manu.chaud@hotmail.fr>
- Elizabeth Bott <52465744+elizabethbott@users.noreply.github.com>
- Ekin Dursun <ekindursun@gmail.com>
- Eisuke Kawashima <e-kwsm@users.noreply.github.com>
- Edgemaster <grand.edgemaster@gmail.com>
- Eddie Darling <eddie.darling@genapsys.com>
- Drew Risinger <drewrisinger@users.noreply.github.com>
- Dr. Nick <das-intensity@users.noreply.github.com>
- Don Kirkby <donkirkby@users.noreply.github.com>
- Don Jayamanne <don.jayamanne@yahoo.com>
- Dominic Lavery <che@thisdevice.co.uk>
- Dmytro Kyrychuk <dmytro.kyrychuck@gmail.com>
- Dionisio E Alonso <baco@users.noreply.github.com>
- DetachHead <57028336+DetachHead@users.noreply.github.com>
- Dennis Keck <26092524+fellhorn@users.noreply.github.com>
- Denis Laxalde <denis.laxalde@logilab.fr>
- David Lawson <dmrlawson@gmail.com>
- David Cain <davidjosephcain@gmail.com>
- Danny Hermes <daniel.j.hermes@gmail.com>
- Daniele Procida <daniele@vurt.org>
- Daniela Plascencia <daplascen@gmail.com>
- Daniel Werner <daniel.werner@scalableminds.com>
- Daniel R. Neal <dan.r.neal@gmail.com> (danrneal)
- Daniel Draper <Germandrummer92@users.noreply.github.com>
- Daniel Dorani <ddandd@gmail.com> (doranid)
- Daniel Brookman <53625739+dbrookman@users.noreply.github.com>
- Dan Garrette <dhgarrette@gmail.com>
- Damien Nozay <damien.nozay@gmail.com>
- Cubicpath <Cubicpath@protonmail.com>
- Craig Citro <craigcitro@gmail.com>
- Cosmo <cosmo@cosmo.red>
- Clément Schreiner <clement@mux.me>
- Clément Pit-Claudel <cpitclaudel@users.noreply.github.com>
- Christopher Zurcher <zurcher@users.noreply.github.com>
- ChandanChainani <chandan.chainani@ibm.com>
- Carl Crowder <bitbucket@carlcrowder.com>: don't evaluate the value of arguments for 'dangerous-default-value'
- Carey Metcalfe <carey@cmetcalfe.ca>: demoted `try-except-raise` from error to warning
- Cameron Olechowski <camsterole@users.noreply.github.com>
- Calin Don <calin.don@gmail.com>
- Caio Carrara <ccarrara@redhat.com>
- C.A.M. Gerlach <WIDEnetServices@gmail.com>
- Bruno P. Kinoshita <kinow@users.noreply.github.com>
- Brice Chardin <brice.chardin@gmail.com>
- Brian C. Lane <bcl@redhat.com>
- Brandon W Maister <quodlibetor@gmail.com>
- BioGeek <jeroen.vangoey@gmail.com>
- Berker ŞAL <brkr.sal@gmail.com>
- Benjamin Partzsch <32679788+bnjmnp@users.noreply.github.com>
- Benjamin Graham <benwilliamgraham@gmail.com>
- Benedikt Morbach <benedikt.morbach@googlemail.com>
- Ben Greiner <code@bnavigator.de>
- Barak Shoshany <baraksh@gmail.com>
- Banjamin Freeman <befreeman@users.noreply.github.com>
- Ayushi Kotiyal <70513726+Ayushikotiyal@users.noreply.github.com>
- Avram Lubkin <avylove@rockhopper.net>
- Athos Ribeiro <athoscr@fedoraproject.org>: Fixed dict-keys-not-iterating false positive for inverse containment checks
- Arun Persaud <arun@nubati.net>
- Arthur Lutz <arthur.lutz@logilab.fr>
- Antonio Ossa <aaossa@uc.cl>
- Antonio Gámiz Delgado <73933988+antoniogamizbadger@users.noreply.github.com>
- Anthony VEREZ <anthony.verez.external@cassidian.com>
- Anthony Tan <tanant@users.noreply.github.com>
- Anthony Foglia <afoglia@users.noreply.github.com> (Google): Added simple string slots check.
- Anentropic <ego@anentropic.com>
- Andy Young <a7young@ucsd.edu>
- Andy Palmer <25123779+ninezerozeronine@users.noreply.github.com>
- Andrzej Klajnert <github@aklajnert.pl>
- Andrew Howe <howeaj@users.noreply.github.com>
- Andres Perez Hortal <andresperezcba@gmail.com>
- Andre Hora <andrehora@users.noreply.github.com>
- Aman Salwan <121633121+AmanSal1@users.noreply.github.com>
- Alok Singh <8325708+alok@users.noreply.github.com>
- Allan Chandler <95424144+allanc65@users.noreply.github.com> (allanc65)
* Fixed issue 5452, false positive missing-param-doc for multi-line Google-style params
- Alex Waygood <alex.waygood@gmail.com>
- Alex Mor <5476113+nashcontrol@users.noreply.github.com>
- Alex Jurkiewicz <alex@jurkiewi.cz>
- Alex Hearn <alex.d.hearn@gmail.com>
- Alex Fortin <alex.antoine.fortin@gmail.com>
- Aleksander Mamla <alek.mamla@gmail.com>
- Alan Evangelista <alanoe@linux.vnet.ibm.com>
- Alan Chan <achan961117@gmail.com>
- Aivar Annamaa <aivarannamaa@users.noreply.github.com>
- Aidan Haase <44787650+haasea@users.noreply.github.com>
- Ahirnish Pareek <ahirnish@gmail.com>: 'keyword-arg-before-var-arg' check
- Agustin Marquez <agusdmb@gmail.com>
- Adrian Chirieac <chirieacam@gmail.com>
- Aditya Gupta <adityagupta1089@users.noreply.github.com> (adityagupta1089)
* Added ignore_signatures to duplicate checker
- Adam Tuft <73994535+adamtuft@users.noreply.github.com>
- Adam Dangoor <adamdangoor@gmail.com>
- 243f6a88 85a308d3 <33170174+243f6a8885a308d313198a2e037@users.noreply.github.com>
Co-Author
---------
The following persons were credited manually but did not commit themselves
under this name, or we did not manage to find their commits in the history.
- Agustin Toledo
- Amaury Forgeot d'Arc: check names imported from a module exists in the module
- Anthony Tan
- Axel Muller
- Benjamin Niemann: allow block level enabling/disabling of messages
- Bernard Nauwelaerts
- Bill Wendling
- Brian van den Broek: windows installation documentation
- Craig Henriques
- D. Alphus (Alphadelta14)
- Daniil Kharkov
- Eero Vuojolahti
- Fabio Zadrozny
- Gauthier Sebaux
- James DesLauriers
- manderj
- Mirko Friedenhagen
- Nicholas Smith
- Nuzula H. Yudaka (Nuzhuka)
- Pek Chhan
- Peter Hammond
- Pierre Rouleau
- Richard Goodman: simplifiable-if-expression (with Tomer Chachamu)
- Sebastian Ulrich
- Takashi Hirashima
- Thomas Snowden: fix missing-docstring for inner functions
- Wolfgang Grafen
- Yannick Brehon

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

@ -0,0 +1,14 @@
include README.rst
include requirements_test_min.txt
include requirements_test_pre_commit.txt
include requirements_test.txt
include tox.ini
graft doc
graft examples
graft script
graft tests
prune doc/_build
prune tests/.benchmarks
prune tests/.pylint_primer_tests
global-exclude __pycache__
global-exclude *.py[co]

@ -0,0 +1,225 @@
`Pylint`_
=========
.. _`Pylint`: https://pylint.readthedocs.io/
.. This is used inside the doc to recover the start of the introduction
.. image:: https://github.com/pylint-dev/pylint/actions/workflows/tests.yaml/badge.svg?branch=main
:target: https://github.com/pylint-dev/pylint/actions
.. image:: https://codecov.io/gh/pylint-dev/pylint/branch/main/graph/badge.svg?token=ZETEzayrfk
:target: https://codecov.io/gh/pylint-dev/pylint
.. image:: https://img.shields.io/pypi/v/pylint.svg
:alt: PyPI Package version
:target: https://pypi.python.org/pypi/pylint
.. image:: https://readthedocs.org/projects/pylint/badge/?version=latest
:target: https://pylint.readthedocs.io/en/latest/?badge=latest
:alt: Documentation Status
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black
.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
:target: https://github.com/pylint-dev/pylint
.. image:: https://results.pre-commit.ci/badge/github/pylint-dev/pylint/main.svg
:target: https://results.pre-commit.ci/latest/github/pylint-dev/pylint/main
:alt: pre-commit.ci status
.. image:: https://bestpractices.coreinfrastructure.org/projects/6328/badge
:target: https://bestpractices.coreinfrastructure.org/projects/6328
:alt: CII Best Practices
.. image:: https://img.shields.io/ossf-scorecard/github.com/PyCQA/pylint?label=openssf%20scorecard&style=flat
:target: https://api.securityscorecards.dev/projects/github.com/PyCQA/pylint
:alt: OpenSSF Scorecard
.. image:: https://img.shields.io/discord/825463413634891776.svg
:target: https://discord.gg/qYxpadCgkx
:alt: Discord
What is Pylint?
---------------
Pylint is a `static code analyser`_ for Python 2 or 3. The latest version supports Python
3.10.0 and above.
.. _`static code analyser`: https://en.wikipedia.org/wiki/Static_code_analysis
Pylint analyses your code without actually running it. It checks for errors, enforces a
coding standard, looks for `code smells`_, and can make suggestions about how the code
could be refactored.
.. _`code smells`: https://martinfowler.com/bliki/CodeSmell.html
Install
-------
.. This is used inside the doc to recover the start of the short text for installation
For command line use, pylint is installed with::
pip install pylint
Or if you want to also check spelling with ``enchant`` (you might need to
`install the enchant C library <https://pyenchant.github.io/pyenchant/install.html#installing-the-enchant-c-library>`_):
.. code-block:: sh
pip install pylint[spelling]
It can also be integrated in most editors or IDEs. More information can be found
`in the documentation`_.
.. _in the documentation: https://pylint.readthedocs.io/en/latest/user_guide/installation/index.html
.. This is used inside the doc to recover the end of the short text for installation
What differentiates Pylint?
---------------------------
Pylint is not trusting your typing and is inferring the actual values of nodes (for a
start because there was no typing when pylint started off) using its internal code
representation (astroid). If your code is ``import logging as argparse``, Pylint
can check and know that ``argparse.error(...)`` is in fact a logging call and not an
argparse call. This makes pylint slower, but it also lets pylint find more issues if
your code is not fully typed.
[inference] is the killer feature that keeps us using [pylint] in our project despite how painfully slow it is.
- `Realist pylint user`_, 2022
.. _`Realist pylint user`: https://github.com/charliermarsh/ruff/issues/970#issuecomment-1381067064
pylint, not afraid of being a little slower than it already is, is also a lot more thorough than other linters.
There are more checks, including some opinionated ones that are deactivated by default
but can be enabled using configuration.
How to use pylint
-----------------
Pylint isn't smarter than you: it may warn you about things that you have
conscientiously done or check for some things that you don't care about.
During adoption, especially in a legacy project where pylint was never enforced,
it's best to start with the ``--errors-only`` flag, then disable
convention and refactor messages with ``--disable=C,R`` and progressively
re-evaluate and re-enable messages as your priorities evolve.
Pylint is highly configurable and permits to write plugins in order to add your
own checks (for example, for internal libraries or an internal rule). Pylint also has an
ecosystem of existing plugins for popular frameworks and third-party libraries.
.. note::
Pylint supports the Python standard library out of the box. Third-party
libraries are not always supported, so a plugin might be needed. A good place
to start is ``PyPI`` which often returns a plugin by searching for
``pylint <library>``. `pylint-pydantic`_, `pylint-django`_ and
`pylint-sonarjson`_ are examples of such plugins. More information about plugins
and how to load them can be found at `plugins`_.
.. _`plugins`: https://pylint.readthedocs.io/en/latest/development_guide/how_tos/plugins.html#plugins
.. _`pylint-pydantic`: https://pypi.org/project/pylint-pydantic
.. _`pylint-django`: https://github.com/pylint-dev/pylint-django
.. _`pylint-sonarjson`: https://github.com/cnescatlab/pylint-sonarjson-catlab
Advised linters alongside pylint
--------------------------------
Projects that you might want to use alongside pylint include ruff_ (**really** fast,
with builtin auto-fix and a large number of checks taken from popular linters, but
implemented in ``rust``) or flake8_ (a framework to implement your own checks in python using ``ast`` directly),
mypy_, pyright_ / pylance or pyre_ (typing checks), bandit_ (security oriented checks), black_ and
isort_ (auto-formatting), autoflake_ (automated removal of unused imports or variables), pyupgrade_
(automated upgrade to newer python syntax) and pydocstringformatter_ (automated pep257).
.. _ruff: https://github.com/astral-sh/ruff
.. _flake8: https://github.com/PyCQA/flake8
.. _bandit: https://github.com/PyCQA/bandit
.. _mypy: https://github.com/python/mypy
.. _pyright: https://github.com/microsoft/pyright
.. _pyre: https://github.com/facebook/pyre-check
.. _black: https://github.com/psf/black
.. _autoflake: https://github.com/myint/autoflake
.. _pyupgrade: https://github.com/asottile/pyupgrade
.. _pydocstringformatter: https://github.com/DanielNoord/pydocstringformatter
.. _isort: https://pycqa.github.io/isort/
Additional tools included in pylint
-----------------------------------
Pylint ships with two additional tools:
- pyreverse_ (standalone tool that generates package and class diagrams.)
- symilar_ (duplicate code finder that is also integrated in pylint)
.. _pyreverse: https://pylint.readthedocs.io/en/latest/additional_tools/pyreverse/index.html
.. _symilar: https://pylint.readthedocs.io/en/latest/additional_tools/symilar/index.html
.. This is used inside the doc to recover the end of the introduction
Contributing
------------
.. This is used inside the doc to recover the start of the short text for contribution
We welcome all forms of contributions such as updates for documentation, new code, checking issues for duplicates or telling us
that we can close them, confirming that issues still exist, `creating issues because
you found a bug or want a feature`_, etc. Everything is much appreciated!
Please follow the `code of conduct`_ and check `the Contributor Guides`_ if you want to
make a code contribution.
.. _creating issues because you found a bug or want a feature: https://pylint.readthedocs.io/en/latest/contact.html#bug-reports-feedback
.. _code of conduct: https://github.com/pylint-dev/pylint/blob/main/CODE_OF_CONDUCT.md
.. _the Contributor Guides: https://pylint.readthedocs.io/en/latest/development_guide/contribute.html
.. This is used inside the doc to recover the end of the short text for contribution
Show your usage
-----------------
You can place this badge in your README to let others know your project uses pylint.
.. image:: https://img.shields.io/badge/linting-pylint-yellowgreen
:target: https://github.com/pylint-dev/pylint
Learn how to add a badge to your documentation in `the badge documentation`_.
.. _the badge documentation: https://pylint.readthedocs.io/en/latest/user_guide/installation/badge.html
License
-------
pylint is, with a few exceptions listed below, `GPLv2 <https://github.com/pylint-dev/pylint/blob/main/LICENSE>`_.
The icon files are licensed under the `CC BY-SA 4.0 <https://creativecommons.org/licenses/by-sa/4.0/>`_ license:
- `doc/logo.png <https://raw.githubusercontent.com/pylint-dev/pylint/main/doc/logo.png>`_
- `doc/logo.svg <https://raw.githubusercontent.com/pylint-dev/pylint/main/doc/logo.svg>`_
Support
-------
Please check `the contact information`_.
.. _`the contact information`: https://pylint.readthedocs.io/en/latest/contact.html
.. |tideliftlogo| image:: https://raw.githubusercontent.com/pylint-dev/pylint/main/doc/media/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White.png
:width: 200
:alt: Tidelift
.. list-table::
:widths: 10 100
* - |tideliftlogo|
- Professional support for pylint is available as part of the `Tidelift
Subscription`_. Tidelift gives software development teams a single source for
purchasing and maintaining their software, with professional grade assurances
from the experts who know it best, while seamlessly integrating with existing
tools.
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-pylint?utm_source=pypi-pylint&utm_medium=referral&utm_campaign=readme

@ -0,0 +1,10 @@
coverage:
status:
patch:
default:
target: 100%
project:
default:
target: 95%
comment:
layout: "reach, diff, flags, files"

@ -0,0 +1,396 @@
abc
abcmeta
abspath
abstractproperty
analyse
analysed
analysing
arg
argparse
args
argumentdefaultshelpformatter
argumentparser
argumentsparser
argv
ascii
asend
assignattr
assignname
AST
ast
astroid
async
asynccontextmanager
attr
attrib
attrname
backport
BaseChecker
basename
behaviour
bidi
Bitbucket
bla
bom
bool
boolean
booleaness
boolop
boundmethod
builtins
bw
callables
cardinality
cd
cfg
changelog
cheaders
chroot
chunker
classdef
classdiagram
classmethod
classmethod's
classname
classobj
CLI
cls
cmp
codebase
codec
codecs
col's
conf
config
const
Const
contextlib
contextmanager
contravariance
contravariant
cgroup
CPython
cpython
csv
CVE
cwd
cyclomatic
dataclass
dataclasses
datetime
debian
deduplication
deepcopy
defaultdicts
defframe
defstmts
deleter
dependabot
deque
destructured
destructuring
diadefs
diadefslib
dictcomp
dicts
dir
dirname
docparams
docstring
docstrings
dumpable
dunder
elif
elif's
elt
emittable
encodings
endswith
enum
enums
epilog
epylint
epytext
erroring
etree
expr
falsey
favour
filepath
filestream
finalbody
# TODO Remove when we are able to remove our own symbols
fixme
Flymake
fmt
formatter
formfeed
fromlineno
fullname
func
functiondef
functiøn
functools
genexpr
getattr
globals
globbing
GPL
graphname
graphviz
grey
guido's
gv
hashable
hmac
html
idgeneratormixin
ifexpr
igetattr
importedname
importfrom
importnode
importschecker
InferenceError
ini
INI
init
initializer
inlinevar
instantiation
isdir
isfile
isinstance
isort
iter
iterable
iterables
itered
iteritems
iTerm
jn
jpg
json
jx
jython
# class is a reserved word
klass
kwarg
kwargs
kwonlyargs
latin
len
lhs
linecache
lineno
linenum
lineset
lineset's
linesets
linkers
linter
linux
listcomp
Logilab
longstring
lsp
mapfile
mapreduce
maxsize
maxsplit
mcs
mermaidjs
metaclass
metaclasses
misdesign
misdesigns
mixin
modname
monkeypatch
mro
# Used so much that we need the abbreviation
msg
msg-template
msgid
msgids
msgs
mult
multiline
multiset
multisets
myattr
myfunction
mymain
mymethod
mymodule
mypy
namedtuple
namespace
newsfile
newstyle
nl
nodename
nodeng
noinspection
nonlocal
nonlocals
num
numpy
ok
optdict
optik
optionals
optiondict
optname
optparse
optvalue
orelse
os
outputfile
overridable
params
paren
parens
passthru
pathlib
patternerror
png
positionals
pragma
pragma's
pragmas
pre
preorder
prepended
proc
py
pyenchant
pyfile
pyi
pylint
pylint's
pylintdict
pylintrc
pyproject
pypy
pyreverse
pytest
qname
rawcheckers
rc
rcfile
re-usable
readlines
recognise
recurse
recurses
redef
reportid
rgx
rheaders
rhs
roid
rsplit
rst
rstrip
rtype
runtime
se
seaborn
sep
setcomp
shortstrings
singledispatch
singledispatchmethod
spammy
sqlalchemy
src
starargs
stateful
staticmethod
stderr
stdin
stdlib
stdout
stmt
str
stringified
subclasses
subcommands
subdicts
subgraphs
sublists
submodule
submodules
subparsers
subparts
subprocess
subscriptable
subscripted
subtree
supcls
superclass
symilar
symlink
symlinks
sys
tbump
tempfile
testcase
testdata
testoptions
tmp
tokencheckers
tokeninfo
tokenization
tokenize
tokenizer
toml
tomlkit
toplevel
towncrier
tp
truthey
truthness
truthy
tryexcept
txt
typecheck
typechecking
typeddict
typehint
typeshed
uid
uml
un
unary
unflattens
unhandled
unicode
uninferable
Uninferable
unittest
unraisablehook
untriggered
# prefix for string
ur
ureport
ureports
utf
utils
validator
vararg
varargs
variadic
variadics
vcg
vcg's
vectorisation
virtualized
wc
whitespaces
xfails
xml
xyz
yml
yoda

@ -0,0 +1,47 @@
# You can set these variables from the command line, and also
# from the environment for the first two.
SPHINXOPTS ?=
SPHINXBUILD ?= sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
# --------------------------------
# This part is specific to pylint.
#---------------------------------
# Set PYLINT_SPHINX_FATAL_WARNINGS= on the command line to restore the default.
PYLINT_SPHINX_FATAL_WARNINGS = -W --keep-going
# Do not use O, we abuse it for internal purposes.
O = -d $(BUILDDIR)/doctrees -T $(PYLINT_SPHINX_FATAL_WARNINGS) -n
.PHONY clean: remove-generated-messages
remove-generated-messages:
rm -rf user_guide/messages/convention user_guide/messages/error \
user_guide/messages/fatal user_guide/messages/information user_guide/messages/refactor \
user_guide/messages/warning
# Generated by exts/*.py but kept in the VCS for easier review of changes:
.PHONY: distclean
distclean: clean
rm -f user_guide/checkers/extensions.rst user_guide/checkers/features.rst \
user_guide/configuration/all-options.rst user_guide/messages/messages_overview.rst
# Set PIP=true on the command line to skip installation of dependencies.
PIP = pip
.PHONY html: install-dependencies
install-dependencies:
@echo "Install dependencies"
cd ../ && $(PIP) install -r doc/requirements.txt

@ -0,0 +1,201 @@
.. This file is auto-generated. Make any changes to the associated
.. docs extension in 'doc/exts/pyreverse_configuration.py'.
Usage
#####
``pyreverse`` is run from the command line using the following syntax::
pyreverse [options] <packages>
where ``<packages>`` is one or more Python packages or modules to analyze.
The available options are organized into the following categories:
* :ref:`filtering-and-scope` - Control which classes and relationships appear in your diagrams
* :ref:`display-options` - Customize the visual appearance including colors and labels
* :ref:`output-control` - Select output formats and set the destination directory
* :ref:`project-configuration` - Define project settings like source roots and ignored files
.. _filtering-and-scope:
Filtering and Scope
===================
--all-ancestors
---------------
*Show all ancestors of all classes in <projects>.*
**Default:** ``None``
--all-associated
----------------
*Show all classes associated with the target classes, including indirect associations.*
**Default:** ``None``
--class
-------
*Create a class diagram with all classes related to <class>; this uses by default the options -ASmy*
**Default:** ``None``
--filter-mode
-------------
*Filter attributes and functions according to <mode>. Correct modes are:
'PUB_ONLY' filter all non public attributes [DEFAULT], equivalent to PRIVATE+SPECIAL
'ALL' no filter
'SPECIAL' filter Python special functions except constructor
'OTHER' filter protected and private attributes*
**Default:** ``PUB_ONLY``
--max-depth
-----------
*Maximum depth of packages/modules to include in the diagram, relative to the deepest specified package. A depth of 0 shows only the specified packages/modules, while 1 includes their immediate children, etc. When specifying nested packages, depth is calculated from the deepest package level. If not specified, all packages/modules in the hierarchy are shown.*
**Default:** ``None``
--show-ancestors
----------------
*Show <ancestor> generations of ancestor classes not in <projects>.*
**Default:** ``None``
--show-associated
-----------------
*Show <association_level> levels of associated classes not in <projects>.*
**Default:** ``None``
--show-builtin
--------------
*Include builtin objects in representation of classes.*
**Default:** ``False``
--show-stdlib
-------------
*Include standard library objects in representation of classes.*
**Default:** ``False``
.. _display-options:
Display Options
===============
--color-palette
---------------
*Comma separated list of colors to use for the package depth coloring.*
**Default:** ``('#77AADD', '#99DDFF', '#44BB99', '#BBCC33', '#AAAA00', '#EEDD88', '#EE8866', '#FFAABB', '#DDDDDD')``
--colorized
-----------
*Use colored output. Classes/modules of the same package get the same color.*
**Default:** ``False``
--max-color-depth
-----------------
*Use separate colors up to package depth of <depth>. Higher depths will reuse colors.*
**Default:** ``2``
--module-names
--------------
*Include module name in the representation of classes.*
**Default:** ``None``
--no-standalone
---------------
*Only show nodes with connections.*
**Default:** ``False``
--only-classnames
-----------------
*Don't show attributes and methods in the class boxes; this disables -f values.*
**Default:** ``False``
.. _output-control:
Output Control
==============
--output
--------
*Create a *.<format> output file if format is available. Available formats are: .dot, .puml, .plantuml, .mmd, .html. Any other format will be tried to be created by using the 'dot' command line tool, which requires a graphviz installation. In this case, these additional formats are available (see `Graphviz output formats <https://graphviz.org/docs/outputs/>`_).*
**Default:** ``dot``
--output-directory
------------------
*Set the output directory path.*
**Default:** ``""``
.. _project-configuration:
Project Configuration
=====================
--ignore
--------
*Files or directories to be skipped. They should be base names, not paths.*
**Default:** ``('CVS',)``
--project
---------
*Set the project name. This will later be appended to the output file names.*
**Default:** ``""``
--source-roots
--------------
*Add paths to the list of the source roots. Supports globbing patterns. The source root is an absolute path or a path relative to the current working directory used to determine a package namespace for modules located under the source root.*
**Default:** ``()``
--verbose
---------
*Makes pyreverse more verbose/talkative. Mostly useful for debugging.*
**Default:** ``False``

@ -0,0 +1,40 @@
.. _pyreverse:
=========
Pyreverse
=========
``pyreverse`` is a powerful tool that creates UML diagrams from your Python code. It helps you visualize:
- Package dependencies and structure
- Class hierarchies and relationships
- Method and attribute organization
Output Formats
==============
``pyreverse`` supports multiple output formats:
* Native formats:
* ``.dot``/``.gv`` (Graphviz)
* ``.puml``/``.plantuml`` (PlantUML)
* ``.mmd``/``.html`` (MermaidJS)
* Additional formats (requires Graphviz installation):
* All `Graphviz output formats <https://graphviz.org/docs/outputs/>`_ (PNG, SVG, PDF, etc.)
* ``pyreverse`` first generates a temporary ``.gv`` file, which is then fed to Graphviz to generate the final image
Getting Started
===============
Check out the :doc:`configuration` guide to learn about available options, or see :doc:`output_examples`
for sample diagrams and common use cases.
.. toctree::
:maxdepth: 2
:caption: Pyreverse
:titlesonly:
:hidden:
configuration
output_examples

@ -0,0 +1,40 @@
Example Output
##############
Example diagrams generated with the ``.puml`` output format are shown below.
Package Diagram
...............
.. image:: ../../media/pyreverse_example_packages.png
:width: 344
:height: 177
:alt: Package diagram generated by pyreverse
:align: center
Class Diagram
.............
.. image:: ../../media/pyreverse_example_classes.png
:width: 625
:height: 589
:alt: Class diagram generated by pyreverse
:align: center
Creating Class Diagrams for Specific Classes
''''''''''''''''''''''''''''''''''''''''''''
In many cases creating a single diagram depicting all classes in the project yields a rather unwieldy, giant diagram.
While limiting the input path to a single package or module can already help greatly to narrow down the scope, the ``-c`` option
provides another way to create a class diagram focusing on a single class and its collaborators.
For example, running::
pyreverse -ASmy -c pylint.checkers.classes.ClassChecker pylint
will generate the full class and package diagrams for ``pylint``, but will additionally generate a file ``pylint.checkers.classes.ClassChecker.dot``:
.. image:: ../../media/ClassChecker_diagram.png
:width: 757
:height: 1452
:alt: Package diagram generated by pyreverse
:align: center

@ -0,0 +1,37 @@
.. _symilar:
Symilar
-------
The console script ``symilar`` finds copy pasted block of text in a set of files. It provides a command line interface to check only the ``duplicate-code`` message.
It can be invoked with::
symilar [-d|--duplicates min_duplicated_lines] [-i|--ignore-comments] [--ignore-docstrings] [--ignore-imports] [--ignore-signatures] file1...
All files that shall be checked have to be passed in explicitly, e.g.::
symilar foo.py, bar.py, subpackage/spam.py, subpackage/eggs.py
``symilar`` produces output like the following::
17 similar lines in 2 files
==tests/data/clientmodule_test.py:3
==tests/data/suppliermodule_test.py:12
class Ancestor:
""" Ancestor method """
cls_member = DoNothing()
def __init__(self, value):
local_variable = 0
self.attr = 'this method shouldn\'t have a docstring'
self.__value = value
def get_value(self):
""" nice docstring ;-) """
return self.__value
def set_value(self, value):
self.__value = value
return 'this method shouldn\'t have a docstring'
TOTAL lines=58 duplicates=17 percent=29.31

@ -0,0 +1,310 @@
# Licensed under the GPL: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
# For details: https://github.com/pylint-dev/pylint/blob/main/LICENSE
# Copyright (c) https://github.com/pylint-dev/pylint/blob/main/CONTRIBUTORS.txt
from __future__ import annotations
import os
import sys
from datetime import datetime
# Pylint documentation build configuration file, created by
# sphinx-quickstart on Thu Apr 4 20:31:25 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use 'os.path.abspath' to make it absolute, like shown here.
sys.path.append(os.path.abspath("exts"))
sys.path.append(os.path.abspath(".."))
# pylint: disable=wrong-import-position
from pylint import __version__
from pylint.__pkginfo__ import numversion
# pylint: enable=wrong-import-position
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = [
"pylint_features",
"pylint_extensions",
"pylint_messages",
"pylint_options",
"pyreverse_configuration",
"sphinx.ext.autosectionlabel",
"sphinx.ext.intersphinx",
"sphinx_reredirects",
]
# Single file redirects are handled in this file and can be done by a pylint
# contributor. We use the following extension:
# https://documatt.gitlab.io/sphinx-reredirects/usage.html
# Directory redirects are handled in ReadTheDoc admin interface and can only be done
# by pylint maintainers at the following URL:
# https://readthedocs.org/dashboard/pylint/redirects/
redirects: dict[str, str] = {
# "<source>": "<target>"
"additional_commands/index": "../index.html",
"development_guide/index": "api/index.html",
"development_guide/contribute": "../development_guide/contributor_guide/index.html",
"development_guide/contributor_guide": "contributor_guide/index.html",
"development_guide/profiling": "../development_guide/contributor_guide/profiling.html",
"development_guide/tests/index": "../contributor_guide/tests/index.html",
"development_guide/tests/install": "../contributor_guide/tests/install.html",
"development_guide/tests/launching_test": "../contributor_guide/tests/launching_test.html",
# There was a typo in the original file, don't fix.
"development_guide/tests/writting_test": "../contributor_guide/tests/writing_test.html",
"development/testing": "tests/index.html",
"how_tos/custom_checkers": "../development_guide/how_tos/custom_checkers.html",
"how_tos/index": "../development_guide/how_tos/index.html",
"how_tos/plugins": "../development_guide/how_tos/plugins.html",
"how_tos/transform_plugins": "../development_guide/how_tos/transform_plugins.html",
"intro": "index.html",
"messages/messages_introduction": "../user_guide/messages/index.html",
"messages/messages_list": "../user_guide/messages/messages_overview.html",
"support": "contact.html",
"technical_reference/c_extensions": "../user_guide/messages/error/no-member.html",
"technical_reference/extensions": "../user_guide/checkers/extensions.html",
"technical_reference/checkers": "../development_guide/technical_reference/checkers.html",
"technical_reference/features": "../user_guide/checkers/features.html",
"technical_reference/index": "../development_guide/technical_reference/index.html",
"technical_reference/startup": "../development_guide/technical_reference/startup.html",
"user_guide/configuration/naming-styles": "../user_guide/messages/convention/invalid-name.html",
"user_guide/ide_integration/flymake-emacs": "../installation/ide_integration/flymake-emacs.html",
"user_guide/ide_integration/ide-integration": "../installation/ide_integration/index.html",
"user_guide/ide-integration": "installation.html",
"user_guide/ide_integration/textmate": "../installation/ide_integration/textmate.html",
"user_guide/index": "installation/index.html",
"user_guide/message-control": "messages/message_control.html",
"user_guide/options": "configuration/all-options.html",
"user_guide/output": "usage/output.html",
"user_guide/pre-commit-integration": "installation/pre-commit-integration.html",
"user_guide/run": "usage/run.html",
"pyreverse": "additional_tools/pyreverse/index.html",
"symilar": "additional_tools/symilar/index.html",
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix of source filenames.
source_suffix = ".rst"
# The encoding of source files.
# source_encoding = 'utf-8-sig'
# The root toctree document.
root_doc = "index"
# General information about the project.
project = "Pylint"
current_year = datetime.utcnow().year
contributors = "Logilab and Pylint contributors"
copyright = f"2003-{current_year}, {contributors}" # pylint: disable=redefined-builtin
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
# The short X.Y version.
version = f"{numversion[0]}.{numversion[1]}"
# The full version, including alpha/beta/rc tags.
release = __version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
# today = ''
# Else, today_fmt is used as the format for a strftime call.
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ["_build", "data/**", "whatsnew/fragments"]
# The reST default role (used for this markup: `text`) to use for all documents.
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = "furo"
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
# Currently we use the default Furo configuration
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
# html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
# html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
# html_static_path = ['_static']
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
html_last_updated_fmt = "%b %d, %Y"
smartquotes = False
# Custom sidebar templates, maps document names to template names.
# Currently we use the default Furo Sidebar
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
# html_additional_pages = {}
# If false, no module index is generated.
# html_domain_indices = True
# If false, no index is generated.
# html_use_index = True
# If true, the index is split into individual pages for each letter.
# html_split_index = False
# If true, links to the reST sources are added to the pages.
html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = "Pylintdoc"
# -- Options for LaTeX output --------------------------------------------------
# The paper size ('letter' or 'a4').
# latex_paper_size = 'letter'
# The font size ('10pt', '11pt' or '12pt').
# latex_font_size = '10pt'
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
(
"index",
"Pylint.tex",
"Pylint Documentation",
contributors,
"manual",
)
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
# latex_use_parts = False
# If true, show page references after internal links.
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
# latex_show_urls = False
# Additional stuff for the LaTeX preamble.
# latex_preamble = ''
# Documents to append as an appendix to all manuals.
# latex_appendices = []
# If false, no module index is generated.
# latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [("index", "pylint", "Pylint Documentation", [contributors], 1)]
# pylint: disable-next=consider-using-namedtuple-or-dataclass
intersphinx_mapping = {
"astroid": ("https://pylint.readthedocs.io/projects/astroid/en/latest/", None),
"python": ("https://docs.python.org/3", None),
}
# Prevent label issues due to colliding section names
# through including multiple documents
autosectionlabel_prefix_document = True
# Permit duplicated titles in the resulting document.
# See https://github.com/pylint-dev/pylint/issues/7362#issuecomment-1256932866
autosectionlabel_maxdepth = 2
linkcheck_ignore = [
"https://github.com/pylint-dev/pylint/blob/main/pylint/extensions/.*"
]

@ -0,0 +1,58 @@
Contact
=======
Bug reports, feedback
---------------------
.. _bug reports, feedback:
You think you have found a bug in Pylint? Well, this may be the case
since Pylint and Python are under heavy development!
Please take the time to check if it is already in the issue tracker at
https://github.com/pylint-dev/pylint
Note that the issue might also be reported in one of Pylint's major dependencies,
astroid:
* https://github.com/pylint-dev/astroid
Discord server
--------------
You can discuss your problem using the discord server:
https://discord.com/invite/Egy6P8AMB5
Mailing lists
-------------
.. _Mailing lists:
The code-quality mailing list is shared with other tools that aim
at improving the quality of python code.
You can subscribe to this mailing list at
https://mail.python.org/mailman3/lists/code-quality.python.org/
Archives are available at
https://mail.python.org/pipermail/code-quality/
Archives before April 2013 are not available anymore. At
https://mail.python.org/pipermail/ it was under ``python-projects``.
Support
-------
.. image:: media/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White.png
:height: 150
:alt: Tidelift
:align: left
:class: tideliftlogo
Professional support for pylint is available as part of the `Tidelift
Subscription`_. Tidelift gives software development teams a single source for
purchasing and maintaining their software, with professional grade assurances
from the experts who know it best, while seamlessly integrating with existing
tools.
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-pylint?utm_source=pypi-pylint&utm_medium=referral&utm_campaign=readme

@ -0,0 +1,10 @@
import abc
class Animal(abc.ABC):
@abc.abstractmethod
def make_sound(self):
pass
sheep = Animal() # [abstract-class-instantiated]

@ -0,0 +1,15 @@
import abc
class Animal(abc.ABC):
@abc.abstractmethod
def make_sound(self):
pass
class Sheep(Animal):
def make_sound(self):
print("bhaaaaa")
sheep = Sheep()

@ -0,0 +1,11 @@
import abc
class WildAnimal:
@abc.abstractmethod
def make_sound(self):
pass
class Panther(WildAnimal): # [abstract-method]
pass

@ -0,0 +1,7 @@
class Pet:
def make_sound(self):
raise NotImplementedError
class Cat(Pet): # [abstract-method]
pass

@ -0,0 +1,12 @@
import abc
class WildAnimal:
@abc.abstractmethod
def make_sound(self):
pass
class Panther(WildAnimal):
def make_sound(self):
print("MEEEOW")

@ -0,0 +1,8 @@
class Pet:
def make_sound(self):
raise NotImplementedError
class Cat(Pet):
def make_sound(self):
print("Meeeow")

@ -0,0 +1,5 @@
class Unicorn:
def __init__(self, fluffiness_level):
if self.fluffiness_level > 9000: # [access-member-before-definition]
print("It's OVER-FLUFFYYYY ! *crush glasses*")
self.fluffiness_level = fluffiness_level

@ -0,0 +1,5 @@
class Unicorn:
def __init__(self, fluffiness_level):
self.fluffiness_level = fluffiness_level
if self.fluffiness_level > 9000:
print("It's OVER-FLUFFYYYY ! *crush glasses*")

@ -0,0 +1,6 @@
``\z`` is same as ``\\z`` because there's no escape sequence for ``z``. But it is not clear
for the reader of the code.
The only reason this is demonstrated to raise ``syntax-error`` is because
pylint's CI now runs on Python 3.12, where this truly raises a ``SyntaxError``.
We hope to address this discrepancy in the documentation in the future.

@ -0,0 +1,2 @@
- `String and Bytes literals <https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals>`_
- `Long form stackoverflow explanation <https://stackoverflow.com/a/19030982/2519059>`_

@ -0,0 +1,8 @@
class Drink:
def mix(self, fluid_one, fluid_two):
return fluid_one + fluid_two
class Cocktail(Drink):
def mix(self, fluid_one, fluid_two, alcoholic_fluid): # [arguments-differ]
return fluid_one + fluid_two + alcoholic_fluid

@ -0,0 +1,9 @@
``argument-differ`` denotes an issue with the Liskov Substitution Principle.
This means that the code in question violates an important design principle which does not have
one single solution. We recommend to search online for the best solution in your case.
To give some examples of potential solutions:
* Add the argument to the parent class
* Remove the inheritance completely
* Add default arguments to the child class

@ -0,0 +1,20 @@
"""
Here we assume that drink and cocktail are the same thing and should actually
inherit from each over. We also assume that 'Drink' are 'Cocktail' without
alcohol (we added the alcohol option in the base class).
This permit to not have to modify the cocktails calls downstream but the case where
an alcohol is mixed in a soft drink will need to be handled.
"""
class Drink:
def mix(self, fluid_one, fluid_two, alcoholic_fluid=None):
# if alcoholic_fluid is not None:
# raise Exception(f"This soft drink has {alcoholic_fluid} in it !")
return fluid_one + fluid_two
class Cocktail(Drink):
def mix(self, fluid_one, fluid_two, alcoholic_fluid):
return fluid_one + fluid_two + alcoholic_fluid

@ -0,0 +1,18 @@
"""
Here we assume that drink and cocktail are the same thing and should actually
inherit from each over. We also assume that any Cocktail can be treated like
a Drink (if you add beer to it).
This permit to not have to modify the calls downstream and causes the least
amount of disturbance at the cost of making cocktails beer-based implicitly.
"""
class Drink:
def mix(self, fluid_one, fluid_two):
return fluid_one + fluid_two
class Cocktail(Drink):
def mix(self, fluid_one, fluid_two, alcoholic_fluid="Beer"):
return fluid_one + fluid_two + alcoholic_fluid

@ -0,0 +1,19 @@
"""
Here we assume that 'Drink' and 'Cocktail' are different things and should
not be treated together like if they were the same thing.
This will force some downstream changes and force the API user to make a
conscious decision about the alcoholic content of its drink when using the
API. For example, it's impossible to create a mojito with beer without
explicitly wanting to, or to add an alcohol to a soft-drink.
"""
class Drink:
def mix(self, fluid_one, fluid_two):
return fluid_one + fluid_two
class Cocktail:
def mix(self, fluid_one, fluid_two, alcoholic_fluid):
return fluid_one + fluid_two + alcoholic_fluid

@ -0,0 +1 @@
- `Liskov Substitution Principle <https://en.wikipedia.org/wiki/Liskov_substitution_principle>`_

@ -0,0 +1,13 @@
def function_3_args(first_argument, second_argument, third_argument):
"""Three arguments function"""
return first_argument, second_argument, third_argument
def args_out_of_order():
first_argument = 1
second_argument = 2
third_argument = 3
function_3_args( # [arguments-out-of-order]
first_argument, third_argument, second_argument
)

@ -0,0 +1,11 @@
def function_3_args(first_argument, second_argument, third_argument):
"""Three arguments function"""
return first_argument, second_argument, third_argument
def args_out_of_order():
first_argument = 1
second_argument = 2
third_argument = 3
function_3_args(first_argument, second_argument, third_argument)

@ -0,0 +1,15 @@
class Fruit:
def brew(self, ingredient_name: str):
print(f"Brewing a {type(self)} with {ingredient_name}")
class Apple(Fruit): ...
class Orange(Fruit):
def brew(self, flavor: str): # [arguments-renamed]
print(f"Brewing an orange with {flavor}")
for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]:
fruit.brew(ingredient_name=ingredient_name)

@ -0,0 +1,15 @@
class Fruit:
def brew(self, ingredient_name: str):
print(f"Brewing a {type(self)} with {ingredient_name}")
class Apple(Fruit): ...
class Orange(Fruit):
def brew(self, ingredient_name: str):
print(f"Brewing an orange with {ingredient_name}")
for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]:
fruit.brew(ingredient_name=ingredient_name)

@ -0,0 +1,3 @@
def test_division():
a = 9 / 3
assert "No ZeroDivisionError were raised" # [assert-on-string-literal]

@ -0,0 +1,4 @@
Directly asserting a string literal will always pass. The solution is to
test something that could fail, or not assert at all.
For ``unittest`` assertions there is the similar :ref:`redundant-unittest-assert` message.

@ -0,0 +1,3 @@
def test_division():
a = 9 / 3
assert a == 3

@ -0,0 +1,3 @@
- `Tests without assertion <https://stackoverflow.com/a/137418/2519059>`_
- `Testing that there is no error raised <https://stackoverflow.com/questions/20274987>`_
- `Parametrizing conditional raising <https://docs.pytest.org/en/latest/example/parametrize.html#parametrizing-conditional-raising>`_

@ -0,0 +1,4 @@
Directly asserting a non-empty tuple will always pass. The solution is to
test something that could fail, or not assert at all.
For ``unittest`` assertions there is the similar :ref:`redundant-unittest-assert` message.

@ -0,0 +1,10 @@
class Student:
__slots__ = ("name",)
def __init__(self, name, surname):
self.name = name
self.surname = surname # [assigning-non-slot]
self.setup()
def setup(self):
pass

@ -0,0 +1,10 @@
class Student:
__slots__ = ("name", "surname")
def __init__(self, name, surname):
self.name = name
self.surname = surname
self.setup()
def setup(self):
pass

@ -0,0 +1,5 @@
def add(x, y):
print(x + y)
value = add(10, 10) # [assignment-from-no-return]

@ -0,0 +1,5 @@
def add(x, y):
return x + y
value = add(10, 10)

@ -0,0 +1,5 @@
def function():
return None
f = function() # [assignment-from-none]

@ -0,0 +1,5 @@
def function():
return None
f = function() if function() else 1

@ -0,0 +1,2 @@
This is a message linked to an internal problem in pylint. There's nothing to change in your code,
but maybe in pylint's configuration or installation.

@ -0,0 +1,10 @@
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_context():
yield
with async_context(): # [async-context-manager-with-regular-with]
print("This will cause an error at runtime")

@ -0,0 +1,12 @@
import asyncio
from contextlib import asynccontextmanager
@asynccontextmanager
async def async_context():
yield
async def main():
async with async_context():
print("This works correctly")

@ -0,0 +1,2 @@
- `PEP 492 - Coroutines with async and await syntax <https://peps.python.org/pep-0492/>`_
- `contextlib.asynccontextmanager <https://docs.python.org/3/library/contextlib.html#contextlib.asynccontextmanager>`_

@ -0,0 +1,3 @@
class Student:
def register(self):
self.is_registered = True # [attribute-defined-outside-init]

@ -0,0 +1,6 @@
class Student:
def __init__(self):
self.is_registered = False
def register(self):
self.is_registered = True

@ -0,0 +1,5 @@
import asyncio
def main():
await asyncio.sleep(1) # [await-outside-async]

@ -0,0 +1,5 @@
import asyncio
async def main():
await asyncio.sleep(1)

@ -0,0 +1 @@
- `PEP 492 <https://peps.python.org/pep-0492/#await-expression>`_

@ -0,0 +1,2 @@
numbers = list(map(lambda x: 2 * x, [1, 2, 3])) # [bad-builtin]
print(numbers)

@ -0,0 +1,2 @@
numbers = [2 * x for x in [1, 2, 3]]
print(numbers)

@ -0,0 +1,2 @@
[MAIN]
load-plugins = pylint.extensions.bad_builtin

@ -0,0 +1,7 @@
shop = {
# animal: (specie, descriptions)
"parrot": ("Norvegian blue", ("restin'", "remarkable", "beautiful plumage")),
}
if "parrot" in shop is "restin'": # [bad-chained-comparison]
print("Hellooooo, Pooolllllyyy ! WAAAAKEEY, WAKKEEEY !")

@ -0,0 +1,5 @@
def xor_check(*, left=None, right=None):
if left is None != right is None: # [bad-chained-comparison]
raise ValueError(
"Either both left= and right= need to be provided or none should."
)

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save