pax_global_header00006660000000000000000000000064151130426210014505gustar00rootroot0000000000000052 comment=e16f942166511d6fb4427e503a734152fae0c4fe pylint-4.0.4/000077500000000000000000000000001511304262100130315ustar00rootroot00000000000000pylint-4.0.4/.coveragerc000066400000000000000000000006161511304262100151550ustar00rootroot00000000000000[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 pylint-4.0.4/.git-blame-ignore-revs000066400000000000000000000000511511304262100171250ustar00rootroot000000000000003f2842400795ae1aaffc4ae6c35c4ef26857c239 pylint-4.0.4/.gitattributes000066400000000000000000000003451511304262100157260ustar00rootroot00000000000000* 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 pylint-4.0.4/.github/000077500000000000000000000000001511304262100143715ustar00rootroot00000000000000pylint-4.0.4/.github/CODEOWNERS000066400000000000000000000017161511304262100157710ustar00rootroot00000000000000# 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 pylint-4.0.4/.github/CONTRIBUTING.md000066400000000000000000000001771511304262100166270ustar00rootroot00000000000000Please read the [contribute doc](https://pylint.readthedocs.io/en/latest/development_guide/contributor_guide/contribute.html). pylint-4.0.4/.github/FUNDING.yml000066400000000000000000000002061511304262100162040ustar00rootroot00000000000000# These are supported funding model platforms tidelift: "pypi/pylint" github: [cdce8p, DanielNoord, jacobtylerwalls,Pierre-Sassoulas] pylint-4.0.4/.github/ISSUE_TEMPLATE/000077500000000000000000000000001511304262100165545ustar00rootroot00000000000000pylint-4.0.4/.github/ISSUE_TEMPLATE/BUG-REPORT.yml000066400000000000000000000061111511304262100207240ustar00rootroot00000000000000name: 🐛 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, = 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 (, 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 pylint-4.0.4/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml000066400000000000000000000030341511304262100215200ustar00rootroot00000000000000name: ✨ 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. pylint-4.0.4/.github/ISSUE_TEMPLATE/QUESTION.yml000066400000000000000000000030011511304262100205400ustar00rootroot00000000000000name: 🤔 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. pylint-4.0.4/.github/ISSUE_TEMPLATE/config.yml000066400000000000000000000002461511304262100205460ustar00rootroot00000000000000blank_issues_enabled: true contact_links: - name: đŸ’Ŧ Discord url: https://discord.com/invite/Egy6P8AMB5 about: Astroid and pylint informal dev discussion pylint-4.0.4/.github/PULL_REQUEST_TEMPLATE.md000066400000000000000000000033571511304262100202020ustar00rootroot00000000000000 ## Type of Changes | | Type | | --- | ---------------------- | | ✓ | :bug: Bug fix | | ✓ | :sparkles: New feature | | ✓ | :hammer: Refactoring | | ✓ | :scroll: Docs | ## Description Refs #XXXX Closes #XXXX pylint-4.0.4/.github/SECURITY.md000066400000000000000000000000731511304262100161620ustar00rootroot00000000000000Coordinated Disclosure Plan: https://tidelift.com/security pylint-4.0.4/.github/copilot-instructions.md000066400000000000000000000231171511304262100211320ustar00rootroot00000000000000# 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 .` - 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. pylint-4.0.4/.github/dependabot.yml000066400000000000000000000007101511304262100172170ustar00rootroot00000000000000version: 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" pylint-4.0.4/.github/workflows/000077500000000000000000000000001511304262100164265ustar00rootroot00000000000000pylint-4.0.4/.github/workflows/backport.yml000066400000000000000000000024711511304262100207620ustar00rootroot00000000000000name: 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 }} pylint-4.0.4/.github/workflows/changelog.yml000066400000000000000000000044361511304262100211070ustar00rootroot00000000000000name: 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 }} pylint-4.0.4/.github/workflows/checks.yaml000066400000000000000000000115231511304262100205540ustar00rootroot00000000000000name: 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; \ } pylint-4.0.4/.github/workflows/codeql-analysis.yml000066400000000000000000000052721511304262100222470ustar00rootroot00000000000000# 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@v3 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@v3 # â„šī¸ 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@v3 pylint-4.0.4/.github/workflows/primer-test.yaml000066400000000000000000000054771511304262100216020ustar00rootroot00000000000000name: 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 pylint-4.0.4/.github/workflows/primer_comment.yaml000066400000000000000000000113761511304262100223420ustar00rootroot00000000000000# 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 }} pylint-4.0.4/.github/workflows/primer_run_main.yaml000066400000000000000000000112121511304262100224750ustar00rootroot00000000000000# 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 pylint-4.0.4/.github/workflows/primer_run_pr.yaml000066400000000000000000000212071511304262100221770ustar00rootroot00000000000000# 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 pylint-4.0.4/.github/workflows/release.yml000066400000000000000000000037751511304262100206050ustar00rootroot00000000000000name: 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 pylint-4.0.4/.github/workflows/stale.yml000066400000000000000000000030641511304262100202640ustar00rootroot00000000000000name: 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." pylint-4.0.4/.github/workflows/tests.yaml000066400000000000000000000147641511304262100204700ustar00rootroot00000000000000name: 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/ pylint-4.0.4/.gitignore000066400000000000000000000012551511304262100150240ustar00rootroot00000000000000# 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/ pylint-4.0.4/.pre-commit-config.yaml000066400000000000000000000144711511304262100173210ustar00rootroot00000000000000ci: 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.13.3" 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: 6.1.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) # TODO remove pydantic once 2.12.0 is released additional_dependencies: ["Sphinx==7.4.3", "pydantic>=2.12.0a1;python_version>='3.14'"] - 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.7.0" hooks: - id: pyproject-fmt - repo: https://github.com/abravalheri/validate-pyproject rev: v0.24.1 hooks: - id: validate-pyproject pylint-4.0.4/.pre-commit-hooks.yaml000066400000000000000000000001501511304262100171640ustar00rootroot00000000000000- id: pylint name: pylint entry: pylint language: python types: [python] require_serial: true pylint-4.0.4/.readthedocs.yaml000066400000000000000000000005251511304262100162620ustar00rootroot00000000000000# 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 pylint-4.0.4/CITATION.cff000066400000000000000000000010661511304262100147260ustar00rootroot00000000000000cff-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 pylint-4.0.4/CODE_OF_CONDUCT.md000066400000000000000000000121541511304262100156330ustar00rootroot00000000000000# 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. pylint-4.0.4/CONTRIBUTORS.txt000066400000000000000000001006561511304262100155370ustar00rootroot00000000000000# 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 - Sylvain ThÊnault : main author / maintainer - Torsten Marek Maintainers ----------- - Pierre Sassoulas - DaniÃĢl van Noord <13665637+DanielNoord@users.noreply.github.com> - Jacob Walls - Marc Mueller <30130371+cdce8p@users.noreply.github.com> - Hippo91 - Mark Byrne <31762852+mbyrnepr2@users.noreply.github.com> - Andreas Finkler <3929834+DudeNr33@users.noreply.github.com> - Matus Valo - Dani Alcala <112832187+clavedeluna@users.noreply.github.com> - Łukasz Rogalski - Nick Drozd : performance improvements to astroid - Ashley Whetter - Bryce Guinta - Yu Shao, Pang <36848472+yushao2@users.noreply.github.com> - Dimitri Prybysh * multiple-imports, not-iterable, not-a-mapping, various patches. - Roy Williams (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 - Arianna Yang 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 (Logilab): python 3 support - Michal Nowikowski : * wrong-spelling-in-comment * wrong-spelling-in-docstring * parallel execution on multiple CPUs - Julthep Nandakwang - Bruno Daniel : 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 : * Port source code to be Python 2/3 compatible * Python 3 checker - Laura MÊdioni (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 - Alexandre Fayolle (Logilab): TkInter gui, documentation, debian support - Ville Skyttä - Zen Lee <53538590+zenlyj@users.noreply.github.com> - Julien Cristau (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 - Frank Harrison (doublethefish) - Pierre-Yves David - David Shea : invalid sequence and slice index - Gunung P. Wibisono <55311527+gunungpw@users.noreply.github.com> - Derek Gustafson - Cezar Elnazli : deprecated-method - Joseph Young <80432516+jpy-git@users.noreply.github.com> (jpy-git) - Tim Martin - Ollie <46904826+ollie-iterators@users.noreply.github.com> - Julian Grimm <51880314+Julfried@users.noreply.github.com> - Tushar Sadhwani (tusharsadhwani) - Nicolas Chauvat - orSolocate <38433858+orSolocate@users.noreply.github.com> - Radu Ciorba : not-context-manager and confusing-with-statement warnings. - Holger Peters - Cosmin Poieană : unichr-builtin and improvements to bad-open-mode. - Yilei "Dolee" Yang - Steven Myint : duplicate-except. - Peter Kolbus (Garmin) - Luigi Bertaco Cristofolini (luigibertaco) - Glenn Matthews : * autogenerated documentation for optional extensions, * bug fixes and enhancements for docparams (nÊe check_docs) extension - crazybolillo - correctmost <134317971+correctmost@users.noreply.github.com> - Vlad Temian : redundant-unittest-assert and the JSON reporter. - Julien Jehannet - Boris Feld - Anthony Sottile - Andrew Haigh (nelfin) - Robert Hofer - Pedro Algarvio (s0undt3ch) - Julien Palard - Hugo van Kemenade - David Liu (david-yz-liu) - Dan Goldsmith : support for msg-template in HTML reporter. - Buck Evan - Mariatta Wijaya * Added new check `logging-fstring-interpolation` * Documentation typo fixes - Jakub Wilk - Eli Fine (eli88fine): Fixed false positive duplicate code warning for lines with symbols only - Émile Crater - Pavel Roskin - David Gilman - へãƒŧさん - Thomas Hisch - Marianna Polatoglou : minor contribution for wildcard import check - Manuel VÃĄzquez Acosta - Luis Escobar (Vauxoo): Add bad-docstring-quotes and docstring-first-line-empty - Lucas Cimon - Konstantina Saketou <56515303+ksaketou@users.noreply.github.com> - Konstantin - Jim Robertson - Ethan Leba - Enji Cooper - Drum Ogilvie - David Lindquist : logging-format-interpolation warning. - Daniel Harding - Anthony Truchet - Alexander Todorov : * 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 - TÊo Bouvard - Sviatoslav Sydorenko - Stavros Ntentos <133706+stdedos@users.noreply.github.com> - Nicolas Boulenguez - Mihai Balint - Mark Bell - Levi Gruspe - Jakub Kuczys - Hornwitser : fix import graph - Fureigh - David Douard - Daniel Balparda (Google): GPyLint maintainer (Google's pylint variant) - Christian Clauss - Bastien Vallet (Djailla) - Aru Sahni : Git ignoring, regex-based ignores - Andreas Freimuth : fix indentation checking with tabs - Alexandru Coman - jpkotta - Thomas Grainger - Takahide Nojima - Taewon D. Kim - Sneaky Pete - Sergey B Kirpichev - Sandro Tosi : Debian packaging - Rogdham - Rene Zhang - Paul Lichtenberger - Or Bahari - Mr. Senko - Mike Frysinger - Martin von Gagern (Google): Added 'raising-format-tuple' warning. - Martin Vielsmaier - Martin Pool (Google): * warnings for anomalous backslashes * symbolic names for messages (like 'unused') * etc. - Martin BaÅĄti * Added new check for shallow copy of os.environ * Added new check for useless `with threading.Lock():` statement - Marcus Näslund (naslundx) - Marco Pernigotti <7657251+mpernigo@users.noreply.github.com> - Marco Forte - James Addison <55152140+jayaddison@users.noreply.github.com> - Ionel Maries Cristian - Gergely KalmÃĄr - Damien Baty - Benjamin Drung : contributing Debian Developer - Anubhav <35621759+anubh-v@users.noreply.github.com> - Antonio Quarta - Andrew J. Simmons - Alvaro Frias - Alexey Pelykh - Alex Prabhat Bara - wtracy - jessebrennan - chohner - aatle <168398276+aatle@users.noreply.github.com> - Tiago Honorato <61059243+tiagohonorato@users.noreply.github.com> - Steven M. Vascellaro - Robin Tweedie <70587124+robin-wayve@users.noreply.github.com> - Roberto Leinardi : PyCharm plugin maintainer - Ricardo Gemignani - Piotr Idzik <65706193+vil02@users.noreply.github.com> - Pieter Engelbrecht - Philipp Albrecht (pylbrecht) - Nicolas Dickreuter - Nick Bastin - Nathaniel Manista : suspicious lambda checking - Maksym Humetskyi (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 - Konstantin Manna - Kai Mueller <15907922+kasium@users.noreply.github.com> - Joshua Cannon - John Leach - James Morgensen : ignored-modules option applies to import errors. - Jaehoon Hwang (jaehoonhwang) - Huw Jones - Gideon <87426140+GideonBear@users.noreply.github.com> - Ganden Schaffner - Frost Ming - Federico Bond - Erik Wright - Erik Eriksson : Added overlapping-except error check. - Emmanuel Ferdman - Dave Bunten - Daniel Wang - Daniel Mouritzen - Dan Hemberger <846186+hemberger@users.noreply.github.com> - Chris Rebert : unidiomatic-typecheck. - Aurelien Campeas - Alexander Pervakov - Alain Leufroy - Akhil Kamat - Adam Williamson - Aaron Liu - xmo-odoo - tbennett0 - purajit <7026198+purajit@users.noreply.github.com> - omarandlorraine <64254276+omarandlorraine@users.noreply.github.com> - craig-sh - bernie gray - azinneck0485 <123660683+azinneck0485@users.noreply.github.com> - Wing Lian - Wes Turner (Google): added new check 'inconsistent-quotes' - Tyler Thieding - Tobias Hernstig <30827238+thernstig@users.noreply.github.com> - Smixi - Simu Toni - Sergei Lebedev <185856+superbobry@users.noreply.github.com> - Scott Worley - Saugat Pachhai - Samuel FORESTIER - RÊmi Cardona - Ryan Ozawa - Roger Sheu <78449574+rogersheu@users.noreply.github.com> - Raphael Gaschignard - Ram Rachum (cool-RR) - Radostin Stoyanov - Peter Bittner - Paul RenvoisÊ - PHeanEX - Omega Weapon - Nikolai Kristiansen - Nick Pesce - Nedelcu Ioan-Andrei <138256980+nedelcu-ioan@users.noreply.github.com> - Nathan Marrow - Mikhail Fesenko - Matthew Suozzo - Matthew Beckers <17108752+mattlbeck@users.noreply.github.com> (mattlbeck) - Mark Roman Miller : fix inline defs in too-many-statements - MalanB - Mads Kiilerich - Maarten ter Huurne - Lefteris Karapetsas - LCD 47 - JÊrome Perrin - Justin Li - John Kirkham - Jens H. Nielsen - Jake Lishman - Ioana Tagirta : fix bad thread instantiation check - Ikraduya Edian : Added new checks 'consider-using-generator' and 'use-a-generator'. - Hugues Bruant - Hashem Nasarat - Harut - Grygorii Iermolenko - Grizzly Nyo - Gabriel R. Sezefredo : Fixed "exception-escape" false positive with generators - Filipe Brandenburger - Fantix King (UChicago) - Eric McDonald <221418+emcd@users.noreply.github.com> - Elias Dorneles : minor adjust to config defaults and docs - Elazrod56 - Edward K. Ream - Derek Harland - David Pursehouse - Daniel Miller - Christoph Blessing <33834216+cblessing24@users.noreply.github.com> - Chris Murray - Chris Lamb - Charles Hebert - Carli Freudenberg (CarliJoy) * Fixed issue 5281, added Unicode checker * Improve non-ascii-name checker - Bruce Dawson - Brian Shaginaw : prevent error on exception check for functions - Benny Mueller - Ben James - Ben Green - Batuhan Taskaya - Artem Yurchenko - Alexander Kapshuna - Akshay Choudhary <153769403+Akshay9715@users.noreply.github.com> - Adam Parkin - 谭九éŧŽ <109224573@qq.com> - Łukasz Sznuk - zasca - y2kbugger - vinnyrose - ttenhoeve-aa - thinwybk - temyurchenko <44875844+temyurchenko@users.noreply.github.com> - syutbai - sur.la.route <17788706+christopherpickering@users.noreply.github.com> - sdet_liang - pavan-msys <149513767+pavan-msys@users.noreply.github.com> - paschich - oittaa <8972248+oittaa@users.noreply.github.com> - nyabkun <75878387+nyabkun@users.noreply.github.com> - nhdsd - moxian - mar-chi-pan - lrjball <50599110+lrjball@users.noreply.github.com> - levon-d - laike9m - kyoto7250 <50972773+kyoto7250@users.noreply.github.com> - kriek - kdestin <101366538+kdestin@users.noreply.github.com> - jaydesl <35102795+jaydesl@users.noreply.github.com> - jab - gracejiang16 <70730457+gracejiang16@users.noreply.github.com> - glmdgrielson <32415403+glmdgrielson@users.noreply.github.com> - glegoux - gaurikholkar - flyingbot91 - fly - fahhem - fadedDexofan - epenet <6771947+epenet@users.noreply.github.com> - danields - cosven - cordis-dev - cherryblossom <31467609+cherryblossom000@users.noreply.github.com> - bluesheeptoken - anatoly techtonik - amelenty - akirchhoff-modular - agutole - Zeckie <49095968+Zeckie@users.noreply.github.com> - Zeb Nicholls * Made W9011 compatible with 'of' syntax in return types - Yuval Langer - Yury Gribov - Yuri Bochkarev : Added epytext support to docparams extension. - Youngsoo Sung - Yory <39745367+yory8@users.noreply.github.com> - Yoichi Nakayama - Yeting Li (yetingli) - Yannack - Yann Dirson - Yang Yang - Xi Shen - Winston H <56998716+winstxnhdw@users.noreply.github.com> - Will Shanks - Viorel Știrbu : intern-builtin warning. - VictorT - Victor Jiajunsu <16359131+jiajunsu@users.noreply.github.com> - ViRuSTriNiTy - Val Lorentz - Ulrich Eckhardt - Udi Fuchs - Trevor Bekolay * Added --list-msgs-enabled command - Tomer Chachamu : simplifiable-if-expression - Tomasz Michalski - Tomasz Magulski - Tom - Tim Hatch - Tim Gates - Tianyu Chen <124018391+UTsweetyfish@users.noreply.github.com> - ThÊo Battrel - Thomas Benhamou - Theodore Ni <3806110+tjni@users.noreply.github.com> - Tanvi Moharir <74228962+tanvimoharir@users.noreply.github.com>: Fix for invalid toml config - T.Rzepka - Svetoslav Neykov - SubaruArai <78188579+SubaruArai@users.noreply.github.com> - StÊphane Wirtel : nonlocal-without-binding - Stephen Longofono <8992396+SLongofono@users.noreply.github.com> - Stephane Odul <1504511+sodul@users.noreply.github.com> - Stanislav Levin - Sorin Sbarnea - Slavfox - Skip Montanaro - Sigurd Spieckermann <2206639+sisp@users.noreply.github.com> - Shiv Venkatasubrahmanyam - Sebastian MÃŧller - Sayyed Faisal Ali <80758388+C0DE-SLAYER@users.noreply.github.com> - Sasha Bagan - Sardorbek Imomaliev - Santiago Castro - Samuel Freilich (sfreilich) - Sam Vermeiren <88253337+PaaEl@users.noreply.github.com> - Ryan McGuire - Ry4an Brase - Ruro - Roshan Shetty - Roman Ivanov - Robert Schweizer - Reverb Chu - Renat Galimov - Rebecca Turner (9999years) - Randall Leeds - Ranadheer Gorrepati <35244169+ranadheerg@users.noreply.github.com> - Ramon Saraiva - Ramiro Leal-Cavazos (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 - Prajwal Borkar - Petr Pulc : require whitespace around annotations - Peter Dawyndt - Peter Dave Hello - Peter Aronoff - Paul Cochrane - Patrik - Pascal Corpet - Pablo Galindo Salgado * Fix false positive 'Non-iterable value' with async comprehensions. - Osher De Paz - Oisín Moran - Obscuron - Noam Yorav-Raphael - Noah-Agnel <138210920+Noah-Agnel@users.noreply.github.com> - Nir Soffer - Niko Wenselowski - Nikita Sobolev - Nick Smith - Neowizard - Ned Batchelder - Natalie Serebryakova - Naglis Jonaitis <827324+naglis@users.noreply.github.com> - Moody - Mitchell Young : minor adjustment to docparams - Mitar - Ming Lyu - Mikhail f. Shiryaev - Mike Fiedler (miketheman) - Mike Bryant - Mike Bernard - Michka Popoff - Michal Vasilek - Michael Scott Cuthbert - Michael Kefeder - Michael K - Michael Hudson-Doyle - Michael Giuffrida - Melvin Hazeleger <31448155+melvio@users.noreply.github.com> - Meltem Kenis - Mehdi Drissi - Matěj GrabovskÃŊ - Matthijs Blom <19817960+MatthijsBlom@users.noreply.github.com> - Matej Spiller Muys - Matej MaruÅĄÃĄk - Marzuk Rashid - Markus Siebenhaar <41283549+siehar@users.noreply.github.com> - Marco Edward Gorelli : Documented Jupyter integration - Marcin Kurczewski (rr-) - Maik RÃļder - Lumír 'Frenzy' Balhar - Ludovic Aubry - Louis Sautier - Lorena Buciu <46202743+lorena-b@users.noreply.github.com> - Logan Miller <14319179+komodo472@users.noreply.github.com> - KÃĄri Tristan Helgason - Kurian Benoy <70306694+kurianbenoy-aot@users.noreply.github.com> - Krzysztof Czapla - Kraig Brockschmidt - Kound - KotlinIsland <65446343+KotlinIsland@users.noreply.github.com> - Kosarchuk Sergey - Konrad Weihmann <46938494+priv-kweihmann@users.noreply.github.com> - Kian Meng, Ang - Kevin Phillips - Kevin Jing Qiu - Kenneth Schackart - Kayran Schmidt <59456929+yumasheta@users.noreply.github.com> - Karthik Nadig - JÃŧrgen Hermann - Josselin Feist - Jonathan Kotta - John Paraskevopoulos : add 'differing-param-doc' and 'differing-type-doc' - John McGehee - John Gabriele - John Belmonte - Johannes Maron - Joffrey Mander - Jochen Preusche - Jeroen Seegers : * Fixed `toml` dependency issue - Jeremy Fleischman - Jason Owen - Jason Lau - Jared Garst - Jared Deckard - Janne RÃļnkkÃļ - Jamie Scott - James Sinclair - James M. Allen - James Lingard - James Broadhead - Jakub Kulík - Jakob Normark - Jacques Kvam - Jace Browning : updated default report format with clickable paths - JZ - JT Olds - Iggy Eom - 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 - Gwanbin Park - GrÊgoire <96051754+gregoire-mullvad@users.noreply.github.com> - Grant Welch - Giuseppe Valente - Gary Tyler McLeod - Felix von Drigalski - Felix Preuschoff <37065638+felixp98@users.noreply.github.com> - Fabrice Douchant - Fabio Natali - Fabian Damken - Eric Froemling - Emmanuel Chaudron - Elizabeth Bott <52465744+elizabethbott@users.noreply.github.com> - Ekin Dursun - Eisuke Kawashima - Edgemaster - Eddie Darling - Drew Risinger - Dr. Nick - Don Kirkby - Don Jayamanne - Dominic Lavery - Dmytro Kyrychuk - Dionisio E Alonso - DetachHead <57028336+DetachHead@users.noreply.github.com> - Dennis Keck <26092524+fellhorn@users.noreply.github.com> - Denis Laxalde - David Lawson - David Cain - Danny Hermes - Daniele Procida - Daniela Plascencia - Daniel Werner - Daniel R. Neal (danrneal) - Daniel Draper - Daniel Dorani (doranid) - Daniel Brookman <53625739+dbrookman@users.noreply.github.com> - Dan Garrette - Damien Nozay - Cubicpath - Craig Citro - Cosmo - ClÊment Schreiner - ClÊment Pit-Claudel - Christopher Zurcher - ChandanChainani - Carl Crowder : don't evaluate the value of arguments for 'dangerous-default-value' - Carey Metcalfe : demoted `try-except-raise` from error to warning - Cameron Olechowski - Calin Don - Caio Carrara - C.A.M. Gerlach - Bruno P. Kinoshita - Brice Chardin - Brian C. Lane - Brandon W Maister - BioGeek - Berker ŞAL - Benjamin Partzsch <32679788+bnjmnp@users.noreply.github.com> - Benjamin Graham - Benedikt Morbach - Ben Greiner - Barak Shoshany - Banjamin Freeman - Ayushi Kotiyal <70513726+Ayushikotiyal@users.noreply.github.com> - Avram Lubkin - Athos Ribeiro : Fixed dict-keys-not-iterating false positive for inverse containment checks - Arun Persaud - Arthur Lutz - Antonio Ossa - Antonio GÃĄmiz Delgado <73933988+antoniogamizbadger@users.noreply.github.com> - Anthony VEREZ - Anthony Tan - Anthony Foglia (Google): Added simple string slots check. - Anentropic - Andy Young - Andy Palmer <25123779+ninezerozeronine@users.noreply.github.com> - Andrzej Klajnert - Andrew Howe - Andres Perez Hortal - Andre Hora - 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 Mor <5476113+nashcontrol@users.noreply.github.com> - Alex Jurkiewicz - Alex Hearn - Alex Fortin - Aleksander Mamla - Alan Evangelista - Alan Chan - Aivar Annamaa - Aidan Haase <44787650+haasea@users.noreply.github.com> - Ahirnish Pareek : 'keyword-arg-before-var-arg' check - Agustin Marquez - Adrian Chirieac - Aditya Gupta (adityagupta1089) * Added ignore_signatures to duplicate checker - Adam Tuft <73994535+adamtuft@users.noreply.github.com> - Adam Dangoor - 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 pylint-4.0.4/LICENSE000066400000000000000000000431001511304262100140340ustar00rootroot00000000000000 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. Copyright (C) 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. , 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. pylint-4.0.4/MANIFEST.in000066400000000000000000000004731511304262100145730ustar00rootroot00000000000000include 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] pylint-4.0.4/README.rst000066400000000000000000000227711511304262100145310ustar00rootroot00000000000000`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 `_): .. 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 ``. `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 `_. The icon files are licensed under the `CC BY-SA 4.0 `_ license: - `doc/logo.png `_ - `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 pylint-4.0.4/codecov.yml000066400000000000000000000002421511304262100151740ustar00rootroot00000000000000coverage: status: patch: default: target: 100% project: default: target: 95% comment: layout: "reach, diff, flags, files" pylint-4.0.4/custom_dict.txt000066400000000000000000000065241511304262100161160ustar00rootroot00000000000000abc 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 attrs 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 iattrs 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 pylint-4.0.4/doc/000077500000000000000000000000001511304262100135765ustar00rootroot00000000000000pylint-4.0.4/doc/Makefile000066400000000000000000000032341511304262100152400ustar00rootroot00000000000000# 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 pylint-4.0.4/doc/additional_tools/000077500000000000000000000000001511304262100171265ustar00rootroot00000000000000pylint-4.0.4/doc/additional_tools/pyreverse/000077500000000000000000000000001511304262100211525ustar00rootroot00000000000000pylint-4.0.4/doc/additional_tools/pyreverse/configuration.rst000066400000000000000000000111021511304262100245460ustar00rootroot00000000000000.. 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] where ```` 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 .* **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 ; this uses by default the options -ASmy* **Default:** ``None`` --filter-mode ------------- *Filter attributes and functions according to . 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 generations of ancestor classes not in .* **Default:** ``None`` --show-associated ----------------- *Show levels of associated classes not in .* **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 . 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 *. 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 `_).* **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`` pylint-4.0.4/doc/additional_tools/pyreverse/index.rst000066400000000000000000000020271511304262100230140ustar00rootroot00000000000000.. _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 `_ (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 pylint-4.0.4/doc/additional_tools/pyreverse/output_examples.rst000066400000000000000000000024161511304262100251450ustar00rootroot00000000000000Example 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 pylint-4.0.4/doc/additional_tools/symilar/000077500000000000000000000000001511304262100206065ustar00rootroot00000000000000pylint-4.0.4/doc/additional_tools/symilar/index.rst000066400000000000000000000022521511304262100224500ustar00rootroot00000000000000.. _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 pylint-4.0.4/doc/conf.py000066400000000000000000000266561511304262100151140ustar00rootroot00000000000000# 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] = { # "": "" "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 # " v 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 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/.*" ] pylint-4.0.4/doc/contact.rst000066400000000000000000000031731511304262100157670ustar00rootroot00000000000000Contact ======= 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 pylint-4.0.4/doc/data/000077500000000000000000000000001511304262100145075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/000077500000000000000000000000001511304262100163165ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/000077500000000000000000000000001511304262100165365ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/abstract-class-instantiated/000077500000000000000000000000001511304262100241315ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/abstract-class-instantiated/bad.py000066400000000000000000000002271511304262100252320ustar00rootroot00000000000000import abc class Animal(abc.ABC): @abc.abstractmethod def make_sound(self): pass sheep = Animal() # [abstract-class-instantiated] pylint-4.0.4/doc/data/messages/a/abstract-class-instantiated/good.py000066400000000000000000000002771511304262100254410ustar00rootroot00000000000000import abc class Animal(abc.ABC): @abc.abstractmethod def make_sound(self): pass class Sheep(Animal): def make_sound(self): print("bhaaaaa") sheep = Sheep() pylint-4.0.4/doc/data/messages/a/abstract-method/000077500000000000000000000000001511304262100216175ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/abstract-method/bad/000077500000000000000000000000001511304262100223455ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/abstract-method/bad/abstract_method.py000066400000000000000000000002311511304262100260560ustar00rootroot00000000000000import abc class WildAnimal: @abc.abstractmethod def make_sound(self): pass class Panther(WildAnimal): # [abstract-method] pass pylint-4.0.4/doc/data/messages/a/abstract-method/bad/function_raising_not_implemented_error.py000066400000000000000000000001671511304262100327400ustar00rootroot00000000000000class Pet: def make_sound(self): raise NotImplementedError class Cat(Pet): # [abstract-method] pass pylint-4.0.4/doc/data/messages/a/abstract-method/good/000077500000000000000000000000001511304262100225475ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/abstract-method/good/abstract_method.py000066400000000000000000000002551511304262100262660ustar00rootroot00000000000000import abc class WildAnimal: @abc.abstractmethod def make_sound(self): pass class Panther(WildAnimal): def make_sound(self): print("MEEEOW") pylint-4.0.4/doc/data/messages/a/abstract-method/good/function_raising_not_implemented_error.py000066400000000000000000000002131511304262100331320ustar00rootroot00000000000000class Pet: def make_sound(self): raise NotImplementedError class Cat(Pet): def make_sound(self): print("Meeeow") pylint-4.0.4/doc/data/messages/a/access-member-before-definition/000077500000000000000000000000001511304262100246325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/access-member-before-definition/bad.py000066400000000000000000000003631511304262100257340ustar00rootroot00000000000000class 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 pylint-4.0.4/doc/data/messages/a/access-member-before-definition/good.py000066400000000000000000000003161511304262100261340ustar00rootroot00000000000000class Unicorn: def __init__(self, fluffiness_level): self.fluffiness_level = fluffiness_level if self.fluffiness_level > 9000: print("It's OVER-FLUFFYYYY ! *crush glasses*") pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/000077500000000000000000000000001511304262100243755ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/bad.py000066400000000000000000000000401511304262100254670ustar00rootroot00000000000000string = "\z" # [syntax-error] pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/details.rst000066400000000000000000000005331511304262100265550ustar00rootroot00000000000000``\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. pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/good/000077500000000000000000000000001511304262100253255ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/good/double_escape.py000066400000000000000000000000171511304262100304670ustar00rootroot00000000000000string = "\\z" pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/good/existing_escape_sequence.py000066400000000000000000000000161511304262100327360ustar00rootroot00000000000000string = "\t" pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/good/r_prefix.py000066400000000000000000000000171511304262100275130ustar00rootroot00000000000000string = r"\z" pylint-4.0.4/doc/data/messages/a/anomalous-backslash-in-string/related.rst000066400000000000000000000003161511304262100265470ustar00rootroot00000000000000- `String and Bytes literals `_ - `Long form stackoverflow explanation `_ pylint-4.0.4/doc/data/messages/a/anomalous-unicode-escape-in-string/000077500000000000000000000000001511304262100253265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/anomalous-unicode-escape-in-string/bad.py000066400000000000000000000000531511304262100264240ustar00rootroot00000000000000print(b"\u%b" % b"0394") # [syntax-error] pylint-4.0.4/doc/data/messages/a/anomalous-unicode-escape-in-string/good.py000066400000000000000000000000321511304262100266230ustar00rootroot00000000000000print(b"\\u%b" % b"0394") pylint-4.0.4/doc/data/messages/a/arguments-differ/000077500000000000000000000000001511304262100220005ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/arguments-differ/bad.py000066400000000000000000000003731511304262100231030ustar00rootroot00000000000000class 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 pylint-4.0.4/doc/data/messages/a/arguments-differ/details.rst000066400000000000000000000006521511304262100241620ustar00rootroot00000000000000``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 pylint-4.0.4/doc/data/messages/a/arguments-differ/good/000077500000000000000000000000001511304262100227305ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/arguments-differ/good/add_option_in_base_class.py000066400000000000000000000013431511304262100302700ustar00rootroot00000000000000""" 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 pylint-4.0.4/doc/data/messages/a/arguments-differ/good/default_value.py000066400000000000000000000011141511304262100261170ustar00rootroot00000000000000""" 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 pylint-4.0.4/doc/data/messages/a/arguments-differ/good/no_inheritance.py000066400000000000000000000012061511304262100262660ustar00rootroot00000000000000""" 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 pylint-4.0.4/doc/data/messages/a/arguments-differ/related.rst000066400000000000000000000001411511304262100241460ustar00rootroot00000000000000- `Liskov Substitution Principle `_ pylint-4.0.4/doc/data/messages/a/arguments-out-of-order/000077500000000000000000000000001511304262100230635ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/arguments-out-of-order/bad.py000066400000000000000000000005651511304262100241710ustar00rootroot00000000000000def 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 ) pylint-4.0.4/doc/data/messages/a/arguments-out-of-order/good.py000066400000000000000000000005131511304262100243640ustar00rootroot00000000000000def 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) pylint-4.0.4/doc/data/messages/a/arguments-renamed/000077500000000000000000000000001511304262100221545ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/arguments-renamed/bad.py000066400000000000000000000006201511304262100232520ustar00rootroot00000000000000class 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) pylint-4.0.4/doc/data/messages/a/arguments-renamed/good.py000066400000000000000000000006131511304262100234560ustar00rootroot00000000000000class 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) pylint-4.0.4/doc/data/messages/a/assert-on-string-literal/000077500000000000000000000000001511304262100234075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/assert-on-string-literal/bad.py000066400000000000000000000001571511304262100245120ustar00rootroot00000000000000def test_division(): a = 9 / 3 assert "No ZeroDivisionError were raised" # [assert-on-string-literal] pylint-4.0.4/doc/data/messages/a/assert-on-string-literal/details.rst000066400000000000000000000003331511304262100255650ustar00rootroot00000000000000Directly 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. pylint-4.0.4/doc/data/messages/a/assert-on-string-literal/good.py000066400000000000000000000000651511304262100247120ustar00rootroot00000000000000def test_division(): a = 9 / 3 assert a == 3 pylint-4.0.4/doc/data/messages/a/assert-on-string-literal/related.rst000066400000000000000000000004521511304262100255620ustar00rootroot00000000000000- `Tests without assertion `_ - `Testing that there is no error raised `_ - `Parametrizing conditional raising `_ pylint-4.0.4/doc/data/messages/a/assert-on-tuple/000077500000000000000000000000001511304262100216005ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/assert-on-tuple/bad.py000066400000000000000000000000461511304262100227000ustar00rootroot00000000000000assert (1, None) # [assert-on-tuple] pylint-4.0.4/doc/data/messages/a/assert-on-tuple/details.rst000066400000000000000000000003361511304262100237610ustar00rootroot00000000000000Directly 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. pylint-4.0.4/doc/data/messages/a/assert-on-tuple/good.py000066400000000000000000000000431511304262100230770ustar00rootroot00000000000000x, y = (1, None) assert x assert y pylint-4.0.4/doc/data/messages/a/assigning-non-slot/000077500000000000000000000000001511304262100222675ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/assigning-non-slot/bad.py000066400000000000000000000003311511304262100233640ustar00rootroot00000000000000class Student: __slots__ = ("name",) def __init__(self, name, surname): self.name = name self.surname = surname # [assigning-non-slot] self.setup() def setup(self): pass pylint-4.0.4/doc/data/messages/a/assigning-non-slot/good.py000066400000000000000000000003131511304262100235660ustar00rootroot00000000000000class Student: __slots__ = ("name", "surname") def __init__(self, name, surname): self.name = name self.surname = surname self.setup() def setup(self): pass pylint-4.0.4/doc/data/messages/a/assignment-from-no-return/000077500000000000000000000000001511304262100235765ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/assignment-from-no-return/bad.py000066400000000000000000000001251511304262100246740ustar00rootroot00000000000000def add(x, y): print(x + y) value = add(10, 10) # [assignment-from-no-return] pylint-4.0.4/doc/data/messages/a/assignment-from-no-return/good.py000066400000000000000000000000661511304262100251020ustar00rootroot00000000000000def add(x, y): return x + y value = add(10, 10) pylint-4.0.4/doc/data/messages/a/assignment-from-none/000077500000000000000000000000001511304262100226045ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/assignment-from-none/bad.py000066400000000000000000000001131511304262100236770ustar00rootroot00000000000000def function(): return None f = function() # [assignment-from-none] pylint-4.0.4/doc/data/messages/a/assignment-from-none/good.py000066400000000000000000000001061511304262100241030ustar00rootroot00000000000000def function(): return None f = function() if function() else 1 pylint-4.0.4/doc/data/messages/a/astroid-error/000077500000000000000000000000001511304262100213325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/astroid-error/details.rst000066400000000000000000000002301511304262100235040ustar00rootroot00000000000000This 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. pylint-4.0.4/doc/data/messages/a/async-context-manager-with-regular-with/000077500000000000000000000000001511304262100263265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/async-context-manager-with-regular-with/bad.py000066400000000000000000000003351511304262100274270ustar00rootroot00000000000000from 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") pylint-4.0.4/doc/data/messages/a/async-context-manager-with-regular-with/good.py000066400000000000000000000003201511304262100276230ustar00rootroot00000000000000import asyncio from contextlib import asynccontextmanager @asynccontextmanager async def async_context(): yield async def main(): async with async_context(): print("This works correctly") pylint-4.0.4/doc/data/messages/a/async-context-manager-with-regular-with/related.rst000066400000000000000000000003211511304262100304740ustar00rootroot00000000000000- `PEP 492 - Coroutines with async and await syntax `_ - `contextlib.asynccontextmanager `_ pylint-4.0.4/doc/data/messages/a/attribute-defined-outside-init/000077500000000000000000000000001511304262100245505ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/attribute-defined-outside-init/bad.py000066400000000000000000000001551511304262100256510ustar00rootroot00000000000000class Student: def register(self): self.is_registered = True # [attribute-defined-outside-init] pylint-4.0.4/doc/data/messages/a/attribute-defined-outside-init/good.py000066400000000000000000000002051511304262100260470ustar00rootroot00000000000000class Student: def __init__(self): self.is_registered = False def register(self): self.is_registered = True pylint-4.0.4/doc/data/messages/a/await-outside-async/000077500000000000000000000000001511304262100224305ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/a/await-outside-async/bad.py000066400000000000000000000001211511304262100235220ustar00rootroot00000000000000import asyncio def main(): await asyncio.sleep(1) # [await-outside-async] pylint-4.0.4/doc/data/messages/a/await-outside-async/good.py000066400000000000000000000000761511304262100237350ustar00rootroot00000000000000import asyncio async def main(): await asyncio.sleep(1) pylint-4.0.4/doc/data/messages/a/await-outside-async/related.rst000066400000000000000000000001021511304262100245730ustar00rootroot00000000000000- `PEP 492 `_ pylint-4.0.4/doc/data/messages/b/000077500000000000000000000000001511304262100165375ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-builtin/000077500000000000000000000000001511304262100207315ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-builtin/bad.py000066400000000000000000000001201511304262100220220ustar00rootroot00000000000000numbers = list(map(lambda x: 2 * x, [1, 2, 3])) # [bad-builtin] print(numbers) pylint-4.0.4/doc/data/messages/b/bad-builtin/good.py000066400000000000000000000000641511304262100222330ustar00rootroot00000000000000numbers = [2 * x for x in [1, 2, 3]] print(numbers) pylint-4.0.4/doc/data/messages/b/bad-builtin/pylintrc000066400000000000000000000000641511304262100225200ustar00rootroot00000000000000[MAIN] load-plugins = pylint.extensions.bad_builtin pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/000077500000000000000000000000001511304262100230265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/bad/000077500000000000000000000000001511304262100235545ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/bad/parrot.py000066400000000000000000000003761511304262100254430ustar00rootroot00000000000000shop = { # animal: (specie, descriptions) "parrot": ("Norvegian blue", ("restin'", "remarkable", "beautiful plumage")), } if "parrot" in shop is "restin'": # [bad-chained-comparison] print("Hellooooo, Pooolllllyyy ! WAAAAKEEY, WAKKEEEY !") pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/bad/xor.py000066400000000000000000000003361511304262100247400ustar00rootroot00000000000000def 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." ) pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/good/000077500000000000000000000000001511304262100237565ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/good/parrot.py000066400000000000000000000003701511304262100256370ustar00rootroot00000000000000shop = { # animal: (specie, descriptions) "parrot": ("Norvegian blue", ("restin'", "remarkable", "beautiful plumage")), } if "parrot" in shop and "restin'" in shop["parrot"][1]: print("Hellooooo, Pooolllllyyy ! WAAAAKEEY, WAKKEEEY !") pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/good/xor.py000066400000000000000000000003061511304262100251370ustar00rootroot00000000000000def xor_check(*, left=None, right=None): if (left is None) != (right is None): raise ValueError( "Either both left= and right= need to be provided or none should." ) pylint-4.0.4/doc/data/messages/b/bad-chained-comparison/related.rst000066400000000000000000000001341511304262100251760ustar00rootroot00000000000000- `Comparison Chaining `_ pylint-4.0.4/doc/data/messages/b/bad-classmethod-argument/000077500000000000000000000000001511304262100234115ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-classmethod-argument/bad.py000066400000000000000000000001561511304262100245130ustar00rootroot00000000000000class Klass: @classmethod def get_instance(self): # [bad-classmethod-argument] return self() pylint-4.0.4/doc/data/messages/b/bad-classmethod-argument/good.py000066400000000000000000000001161511304262100247110ustar00rootroot00000000000000class Klass: @classmethod def get_instance(cls): return cls() pylint-4.0.4/doc/data/messages/b/bad-configuration-section/000077500000000000000000000000001511304262100235745ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-configuration-section/details.rst000066400000000000000000000002371511304262100257550ustar00rootroot00000000000000This error was raised when we encountered an unexpected value type in a toml configuration between pylint 2.12 and pylint 2.14 (before the argparse refactor). pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/000077500000000000000000000000001511304262100225755ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/bad.py000066400000000000000000000001011511304262100236650ustar00rootroot00000000000000def foo(): # [bad-docstring-quotes] "Docstring." return pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/details.rst000066400000000000000000000001441511304262100247530ustar00rootroot00000000000000From `PEP 257`: "For consistency, always use ``"""triple double quotes"""`` around docstrings." pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/good.py000066400000000000000000000000531511304262100240750ustar00rootroot00000000000000def foo(): """Docstring.""" return pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/pylintrc000066400000000000000000000000571511304262100243660ustar00rootroot00000000000000[main] load-plugins=pylint.extensions.docstyle pylint-4.0.4/doc/data/messages/b/bad-docstring-quotes/related.rst000066400000000000000000000001311511304262100247420ustar00rootroot00000000000000- `PEP 257 – Docstring Conventions `_ pylint-4.0.4/doc/data/messages/b/bad-dunder-name/000077500000000000000000000000001511304262100214625ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-dunder-name/bad.py000066400000000000000000000002141511304262100225570ustar00rootroot00000000000000class Apples: def _init_(self): # [bad-dunder-name] pass def __hello__(self): # [bad-dunder-name] print("hello") pylint-4.0.4/doc/data/messages/b/bad-dunder-name/good.py000066400000000000000000000001401511304262100227570ustar00rootroot00000000000000class Apples: def __init__(self): pass def hello(self): print("hello") pylint-4.0.4/doc/data/messages/b/bad-dunder-name/pylintrc000066400000000000000000000000551511304262100232510ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.dunder pylint-4.0.4/doc/data/messages/b/bad-except-order/000077500000000000000000000000001511304262100216645ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-except-order/bad.py000066400000000000000000000003271511304262100227660ustar00rootroot00000000000000try: print(int(input())) except Exception: raise except TypeError: # [bad-except-order] # This block cannot be reached since TypeError exception # is caught by previous exception handler. raise pylint-4.0.4/doc/data/messages/b/bad-except-order/good.py000066400000000000000000000001251511304262100231640ustar00rootroot00000000000000try: print(int(input())) except TypeError: raise except Exception: raise pylint-4.0.4/doc/data/messages/b/bad-exception-cause/000077500000000000000000000000001511304262100223575ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-exception-cause/bad.py000066400000000000000000000003521511304262100234570ustar00rootroot00000000000000def divide(x, y): result = 0 try: result = x / y except ZeroDivisionError: # +1: [bad-exception-cause] raise ValueError(f"Division by zero when dividing {x} by {y} !") from result return result pylint-4.0.4/doc/data/messages/b/bad-exception-cause/good.py000066400000000000000000000003121511304262100236550ustar00rootroot00000000000000def divide(x, y): result = 0 try: result = x / y except ZeroDivisionError as exc: raise ValueError(f"Division by zero when dividing {x} by {y} !") from exc return result pylint-4.0.4/doc/data/messages/b/bad-exception-cause/related.rst000066400000000000000000000003231511304262100245270ustar00rootroot00000000000000- `The raise statement `_ - `Explicit Exception Chaining `_ per PEP 3134 pylint-4.0.4/doc/data/messages/b/bad-file-encoding/000077500000000000000000000000001511304262100217665ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-file-encoding/bad.py000066400000000000000000000000501511304262100230610ustar00rootroot00000000000000# coding: latin_1 # [bad-file-encoding] pylint-4.0.4/doc/data/messages/b/bad-file-encoding/good.py000066400000000000000000000000001511304262100232560ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-format-character/000077500000000000000000000000001511304262100225055ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-format-character/bad.py000066400000000000000000000000761511304262100236100ustar00rootroot00000000000000print("%s %z" % ("hello", "world")) # [bad-format-character] pylint-4.0.4/doc/data/messages/b/bad-format-character/details.rst000066400000000000000000000002731511304262100246660ustar00rootroot00000000000000This check is currently only active for "old-style" string formatting as seen in the examples. See `Issue #6085 `_ for more information. pylint-4.0.4/doc/data/messages/b/bad-format-character/good.py000066400000000000000000000000441511304262100240050ustar00rootroot00000000000000print("%s %s" % ("hello", "world")) pylint-4.0.4/doc/data/messages/b/bad-format-character/related.rst000066400000000000000000000001771511304262100246640ustar00rootroot00000000000000- `Format String Syntax `_ - `PyFormat `_ pylint-4.0.4/doc/data/messages/b/bad-format-string-key/000077500000000000000000000000001511304262100226455ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-format-string-key/bad.py000066400000000000000000000000771511304262100237510ustar00rootroot00000000000000print("%(one)d" % {"one": 1, 2: 2}) # [bad-format-string-key] pylint-4.0.4/doc/data/messages/b/bad-format-string-key/details.rst000066400000000000000000000006051511304262100250250ustar00rootroot00000000000000This check only works for old-style string formatting using the '%' operator. This check only works if the dictionary with the values to be formatted is defined inline. Passing a variable will not trigger the check as the other keys in this dictionary may be used in other contexts, while an inline defined dictionary is clearly only intended to hold the values that should be formatted. pylint-4.0.4/doc/data/messages/b/bad-format-string-key/good.py000066400000000000000000000000611511304262100241440ustar00rootroot00000000000000print("%(one)d, %(two)d" % {"one": 1, "two": 2}) pylint-4.0.4/doc/data/messages/b/bad-format-string/000077500000000000000000000000001511304262100220575ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-format-string/bad.py000066400000000000000000000000771511304262100231630ustar00rootroot00000000000000print("{a[0] + a[1]}".format(a=[0, 1])) # [bad-format-string] pylint-4.0.4/doc/data/messages/b/bad-format-string/good.py000066400000000000000000000000521511304262100233560ustar00rootroot00000000000000print("{a[0]} + {a[1]}".format(a=[0, 1])) pylint-4.0.4/doc/data/messages/b/bad-format-string/related.rst000066400000000000000000000001771511304262100242360ustar00rootroot00000000000000- `Format String Syntax `_ - `PyFormat `_ pylint-4.0.4/doc/data/messages/b/bad-indentation/000077500000000000000000000000001511304262100215775ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-indentation/bad.py000066400000000000000000000000611511304262100226740ustar00rootroot00000000000000if input(): print('yes') # [bad-indentation] pylint-4.0.4/doc/data/messages/b/bad-indentation/details.rst000066400000000000000000000001271511304262100237560ustar00rootroot00000000000000The option ``--indent-string`` can be used to set the indentation unit for this check. pylint-4.0.4/doc/data/messages/b/bad-indentation/good.py000066400000000000000000000000351511304262100230770ustar00rootroot00000000000000if input(): print("yes") pylint-4.0.4/doc/data/messages/b/bad-inline-option/000077500000000000000000000000001511304262100220475ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-inline-option/bad.py000066400000000000000000000000701511304262100231440ustar00rootroot00000000000000# 2:[bad-inline-option] # pylint: disable line-too-long pylint-4.0.4/doc/data/messages/b/bad-inline-option/good.py000066400000000000000000000000401511304262100233430ustar00rootroot00000000000000# pylint: disable=line-too-long pylint-4.0.4/doc/data/messages/b/bad-mcs-classmethod-argument/000077500000000000000000000000001511304262100241715ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-mcs-classmethod-argument/bad.py000066400000000000000000000001451511304262100252710ustar00rootroot00000000000000class Meta(type): @classmethod def foo(some): # [bad-mcs-classmethod-argument] pass pylint-4.0.4/doc/data/messages/b/bad-mcs-classmethod-argument/good.py000066400000000000000000000001021511304262100254640ustar00rootroot00000000000000class Meta(type): @classmethod def foo(mcs): pass pylint-4.0.4/doc/data/messages/b/bad-mcs-method-argument/000077500000000000000000000000001511304262100231435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-mcs-method-argument/bad.py000066400000000000000000000001201511304262100242340ustar00rootroot00000000000000class Meta(type): def func(some): # [bad-mcs-method-argument] pass pylint-4.0.4/doc/data/messages/b/bad-mcs-method-argument/good.py000066400000000000000000000000621511304262100244430ustar00rootroot00000000000000class Meta(type): def func(cls): pass pylint-4.0.4/doc/data/messages/b/bad-open-mode/000077500000000000000000000000001511304262100211465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-open-mode/bad.py000066400000000000000000000001741511304262100222500ustar00rootroot00000000000000def open_and_get_content(file_path): with open(file_path, "rwx") as file: # [bad-open-mode] return file.read() pylint-4.0.4/doc/data/messages/b/bad-open-mode/good.py000066400000000000000000000001471511304262100224520ustar00rootroot00000000000000def open_and_get_content(file_path): with open(file_path, "r") as file: return file.read() pylint-4.0.4/doc/data/messages/b/bad-plugin-value/000077500000000000000000000000001511304262100216735ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-plugin-value/details.rst000066400000000000000000000006241511304262100240540ustar00rootroot00000000000000One of your pylint plugins cannot be loaded. There's nothing to change in your code, but your pylint configuration or installation has an issue. For example, there might be a typo. The following config:: [MAIN] load-plugins = pylint.extensions.bad_biultin Should be:: [MAIN] load-plugins = pylint.extensions.bad_builtin Or the plugin you added is not importable in your environment. pylint-4.0.4/doc/data/messages/b/bad-reversed-sequence/000077500000000000000000000000001511304262100227105ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-reversed-sequence/bad.py000066400000000000000000000000621511304262100240060ustar00rootroot00000000000000reversed({1, 2, 3, 4}) # [bad-reversed-sequence] pylint-4.0.4/doc/data/messages/b/bad-reversed-sequence/good.py000066400000000000000000000000271511304262100242110ustar00rootroot00000000000000reversed([1, 2, 3, 4]) pylint-4.0.4/doc/data/messages/b/bad-staticmethod-argument/000077500000000000000000000000001511304262100235735ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-staticmethod-argument/bad.py000066400000000000000000000001351511304262100246720ustar00rootroot00000000000000class Wolf: @staticmethod def eat(self): # [bad-staticmethod-argument] pass pylint-4.0.4/doc/data/messages/b/bad-staticmethod-argument/good.py000066400000000000000000000000771511304262100251010ustar00rootroot00000000000000class Wolf: @staticmethod def eat(sheep): pass pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/000077500000000000000000000000001511304262100221435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/bad/000077500000000000000000000000001511304262100226715ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/bad/hello_world.py000066400000000000000000000001041511304262100255500ustar00rootroot00000000000000"Hello World".strip("Hello") # [bad-str-strip-call] # >>> ' World' pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/bad/remove_abc_from_both_side.py000066400000000000000000000001071511304262100304060ustar00rootroot00000000000000"abcbc def bacabc".strip("abcbc ") # [bad-str-strip-call] # >>> 'def' pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/details.rst000066400000000000000000000007651511304262100243320ustar00rootroot00000000000000A common misconception is that ``str.strip('Hello')`` removes the *substring* ``'Hello'`` from the beginning and end of the string. This is **not** the case. From the `documentation `_: > The chars argument is not a prefix or suffix; rather, all combinations of its values are stripped Duplicated characters in the ``str.strip`` call, besides not having any effect on the actual result, may indicate this misunderstanding. pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/good/000077500000000000000000000000001511304262100230735ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/good/hello_world.py000066400000000000000000000000531511304262100257550ustar00rootroot00000000000000"Hello World".strip("Helo") # >>> ' World' pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/good/remove_abc_from_both_side.py000066400000000000000000000000551511304262100306120ustar00rootroot00000000000000"abcbc def bacabc".strip("abc ") # >>> 'def' pylint-4.0.4/doc/data/messages/b/bad-str-strip-call/related.rst000066400000000000000000000001631511304262100243150ustar00rootroot00000000000000- Documentation: `str.strip([chars]) `_ pylint-4.0.4/doc/data/messages/b/bad-string-format-type/000077500000000000000000000000001511304262100230365ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-string-format-type/bad.py000066400000000000000000000000561511304262100241370ustar00rootroot00000000000000print("%d" % "1") # [bad-string-format-type] pylint-4.0.4/doc/data/messages/b/bad-string-format-type/details.rst000066400000000000000000000002731511304262100252170ustar00rootroot00000000000000This check is currently only active for "old-style" string formatting as seen in the examples. See `Issue #6085 `_ for more information. pylint-4.0.4/doc/data/messages/b/bad-string-format-type/good.py000066400000000000000000000000201511304262100243300ustar00rootroot00000000000000print("%d" % 1) pylint-4.0.4/doc/data/messages/b/bad-string-format-type/related.rst000066400000000000000000000001771511304262100252150ustar00rootroot00000000000000- `Format String Syntax `_ - `PyFormat `_ pylint-4.0.4/doc/data/messages/b/bad-super-call/000077500000000000000000000000001511304262100213325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-super-call/bad.py000066400000000000000000000002731511304262100224340ustar00rootroot00000000000000class Animal: pass class Tree: pass class Cat(Animal): def __init__(self): super(Tree, self).__init__() # [bad-super-call] super(Animal, self).__init__() pylint-4.0.4/doc/data/messages/b/bad-super-call/details.rst000066400000000000000000000007001511304262100235060ustar00rootroot00000000000000In Python 2.7, ``super()`` has to be called with its own class and ``self`` as arguments (``super(Cat, self)``), which can lead to a mix up of parent and child class in the code. In Python 3 the recommended way is to call ``super()`` without arguments (see also ``super-with-arguments``). One exception is calling ``super()`` on a non-direct parent class. This can be used to get a method other than the default method returned by the ``mro()``. pylint-4.0.4/doc/data/messages/b/bad-super-call/good.py000066400000000000000000000002021511304262100226260ustar00rootroot00000000000000class Animal: pass class Tree: pass class Cat(Animal): def __init__(self): super(Animal, self).__init__() pylint-4.0.4/doc/data/messages/b/bad-super-call/related.rst000066400000000000000000000001301511304262100234760ustar00rootroot00000000000000- `Documentation for super() `_ pylint-4.0.4/doc/data/messages/b/bad-thread-instantiation/000077500000000000000000000000001511304262100234145ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bad-thread-instantiation/bad.py000066400000000000000000000002201511304262100245060ustar00rootroot00000000000000import threading def thread_target(n): print(n**2) thread = threading.Thread(lambda: None) # [bad-thread-instantiation] thread.start() pylint-4.0.4/doc/data/messages/b/bad-thread-instantiation/good.py000066400000000000000000000002061511304262100247140ustar00rootroot00000000000000import threading def thread_target(n): print(n**2) thread = threading.Thread(target=thread_target, args=(10,)) thread.start() pylint-4.0.4/doc/data/messages/b/bare-except/000077500000000000000000000000001511304262100207365ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bare-except/bad.py000066400000000000000000000001461511304262100220370ustar00rootroot00000000000000try: import platform_specific_module except: # [bare-except] platform_specific_module = None pylint-4.0.4/doc/data/messages/b/bare-except/details.rst000066400000000000000000000005701511304262100231170ustar00rootroot00000000000000A good rule of thumb is to limit use of bare ‘except’ clauses to two cases: - If the exception handler will be printing out or logging the traceback; at least the user will be aware that an error has occurred. - If the code needs to do some cleanup work, but then lets the exception propagate upwards with raise. ``try...finally`` can be a better way to handle this case. pylint-4.0.4/doc/data/messages/b/bare-except/good.py000066400000000000000000000001411511304262100222340ustar00rootroot00000000000000try: import platform_specific_module except ImportError: platform_specific_module = None pylint-4.0.4/doc/data/messages/b/bare-except/related.rst000066400000000000000000000004351511304262100231120ustar00rootroot00000000000000- `Programming recommendation in PEP8 `_ - `PEP 760 – No More Bare Excepts (Rejected) `_ - `Discussion about PEP 760 `_ pylint-4.0.4/doc/data/messages/b/bare-name-capture-pattern/000077500000000000000000000000001511304262100235025ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bare-name-capture-pattern/bad.py000066400000000000000000000004501511304262100246010ustar00rootroot00000000000000red = 0 green = 1 blue = 2 def func(color): match color: case red: # [bare-name-capture-pattern] print("I see red!") case green: # [bare-name-capture-pattern] print("Grass is green") case blue: print("I'm feeling the blues :(") pylint-4.0.4/doc/data/messages/b/bare-name-capture-pattern/good.py000066400000000000000000000005021511304262100250010ustar00rootroot00000000000000from enum import Enum class Color(Enum): RED = 0 GREEN = 1 BLUE = 2 def func(color: Color) -> None: match color: case Color.RED: print("I see red!") case Color.GREEN: print("Grass is green") case Color.BLUE: print("I'm feeling the blues :(") pylint-4.0.4/doc/data/messages/b/bare-name-capture-pattern/related.rst000066400000000000000000000001261511304262100256530ustar00rootroot00000000000000- `PEP 636 `_ pylint-4.0.4/doc/data/messages/b/bidirectional-unicode/000077500000000000000000000000001511304262100227735ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/bidirectional-unicode/bad.py000066400000000000000000000001161511304262100240710ustar00rootroot00000000000000# +1: [bidirectional-unicode] example = "x‏" * 100 # "‏x" is assigned pylint-4.0.4/doc/data/messages/b/bidirectional-unicode/good.py000066400000000000000000000000341511304262100242720ustar00rootroot00000000000000example = "x[U+2194]" * 100 pylint-4.0.4/doc/data/messages/b/binary-op-exception/000077500000000000000000000000001511304262100224335ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/binary-op-exception/bad.py000066400000000000000000000001311511304262100235260ustar00rootroot00000000000000try: 1 / 0 except ZeroDivisionError or ValueError: # [binary-op-exception] pass pylint-4.0.4/doc/data/messages/b/binary-op-exception/good.py000066400000000000000000000001001511304262100237240ustar00rootroot00000000000000try: 1 / 0 except (ZeroDivisionError, ValueError): pass pylint-4.0.4/doc/data/messages/b/boolean-datetime/000077500000000000000000000000001511304262100217505ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/boolean-datetime/bad.py000066400000000000000000000002521511304262100230470ustar00rootroot00000000000000import datetime if datetime.time(): # [boolean-datetime] print("It is time.") if datetime.datetime.now().time(): # [boolean-datetime] print("Now or never.") pylint-4.0.4/doc/data/messages/b/boolean-datetime/good.py000066400000000000000000000003141511304262100232500ustar00rootroot00000000000000import datetime time_now_utc = datetime.datetime.now(tz=datetime.UTC).time() if time_now_utc > datetime.time(6, 0): print("Daytime!") if time_now_utc < datetime.time(6, 0): print("Nighttime!") pylint-4.0.4/doc/data/messages/b/boolean-datetime/pylintrc000066400000000000000000000000261511304262100235350ustar00rootroot00000000000000[main] py-version=3.4 pylint-4.0.4/doc/data/messages/b/boolean-datetime/related.rst000066400000000000000000000000751511304262100241240ustar00rootroot00000000000000- `Python bug tracker `_ pylint-4.0.4/doc/data/messages/b/break-in-finally/000077500000000000000000000000001511304262100216635ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/break-in-finally/bad.py000066400000000000000000000001231511304262100227570ustar00rootroot00000000000000while True: try: pass finally: break # [break-in-finally] pylint-4.0.4/doc/data/messages/b/break-in-finally/good.py000066400000000000000000000001361511304262100231650ustar00rootroot00000000000000while True: try: pass except ValueError: pass else: break pylint-4.0.4/doc/data/messages/b/break-in-finally/related.rst000066400000000000000000000003311511304262100240320ustar00rootroot00000000000000- `Python 3 docs 'finally' clause `_ - `PEP 765 - Disallow return/break/continue that exit a finally block `_ pylint-4.0.4/doc/data/messages/b/broad-exception-caught/000077500000000000000000000000001511304262100230735ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/broad-exception-caught/bad.py000066400000000000000000000001731511304262100241740ustar00rootroot00000000000000try: import platform_specific_module except Exception: # [broad-exception-caught] platform_specific_module = None pylint-4.0.4/doc/data/messages/b/broad-exception-caught/details.rst000066400000000000000000000003761511304262100252600ustar00rootroot00000000000000For example, you're trying to import a library with required system dependencies and you catch everything instead of only import errors, you will miss the error message telling you, that your code could work if you had installed the system dependencies. pylint-4.0.4/doc/data/messages/b/broad-exception-caught/good.py000066400000000000000000000001411511304262100243710ustar00rootroot00000000000000try: import platform_specific_module except ImportError: platform_specific_module = None pylint-4.0.4/doc/data/messages/b/broad-exception-caught/related.rst000066400000000000000000000001661511304262100252500ustar00rootroot00000000000000- `Should I always specify an exception type in 'except' statements? `_ pylint-4.0.4/doc/data/messages/b/broad-exception-raised/000077500000000000000000000000001511304262100230675ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/broad-exception-raised/bad.py000066400000000000000000000002551511304262100241710ustar00rootroot00000000000000def small_apple(apple, length): if len(apple) < length: raise Exception("Apple is too small!") # [broad-exception-raised] print(f"{apple} is proper size.") pylint-4.0.4/doc/data/messages/b/broad-exception-raised/good.py000066400000000000000000000002221511304262100243650ustar00rootroot00000000000000def small_apple(apple, length): if len(apple) < length: raise ValueError("Apple is too small!") print(f"{apple} is proper size.") pylint-4.0.4/doc/data/messages/b/broad-exception-raised/related.rst000066400000000000000000000001501511304262100252350ustar00rootroot00000000000000- `Programming recommendation in PEP8 `_ pylint-4.0.4/doc/data/messages/b/broken-collections-callable/000077500000000000000000000000001511304262100240705ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/broken-collections-callable/bad.py000066400000000000000000000002331511304262100251660ustar00rootroot00000000000000from collections.abc import Callable from typing import Optional def func() -> Optional[Callable[[int], None]]: # [broken-collections-callable] ... pylint-4.0.4/doc/data/messages/b/broken-collections-callable/good.py000066400000000000000000000001331511304262100253670ustar00rootroot00000000000000from typing import Callable, Optional def func() -> Optional[Callable[[int], None]]: ... pylint-4.0.4/doc/data/messages/b/broken-collections-callable/pylintrc000066400000000000000000000000741511304262100256600ustar00rootroot00000000000000[main] py-version=3.9 load-plugins=pylint.extensions.typing pylint-4.0.4/doc/data/messages/b/broken-collections-callable/related.rst000066400000000000000000000000641511304262100262420ustar00rootroot00000000000000- `bpo-42965 `_ pylint-4.0.4/doc/data/messages/b/broken-noreturn/000077500000000000000000000000001511304262100216715ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/b/broken-noreturn/bad.py000066400000000000000000000002311511304262100227650ustar00rootroot00000000000000from typing import NoReturn, Union def exploding_apple(apple) -> Union[None, NoReturn]: # [broken-noreturn] print(f"{apple} is about to explode") pylint-4.0.4/doc/data/messages/b/broken-noreturn/good.py000066400000000000000000000002321511304262100231700ustar00rootroot00000000000000from typing import NoReturn def exploding_apple(apple) -> NoReturn: print(f"{apple} is about to explode") raise Exception("{apple} exploded !") pylint-4.0.4/doc/data/messages/b/broken-noreturn/pylintrc000066400000000000000000000000741511304262100234610ustar00rootroot00000000000000[main] py-version=3.7 load-plugins=pylint.extensions.typing pylint-4.0.4/doc/data/messages/c/000077500000000000000000000000001511304262100165405ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/c-extension-no-member/000077500000000000000000000000001511304262100226535ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/c-extension-no-member/details.rst000066400000000000000000000003751511304262100250370ustar00rootroot00000000000000``c-extension-no-member`` is an informational variant of ``no-member`` to encourage allowing introspection of C extensions as described in the `page `_ for ``no-member``. pylint-4.0.4/doc/data/messages/c/c-extension-no-member/good.py000066400000000000000000000000731511304262100241550ustar00rootroot00000000000000# This is a placeholder for correct code for this message. pylint-4.0.4/doc/data/messages/c/catching-non-exception/000077500000000000000000000000001511304262100231045ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/catching-non-exception/bad.py000066400000000000000000000001401511304262100241770ustar00rootroot00000000000000class FooError: pass try: 1 / 0 except FooError: # [catching-non-exception] pass pylint-4.0.4/doc/data/messages/c/catching-non-exception/good.py000066400000000000000000000001171511304262100244050ustar00rootroot00000000000000class FooError(Exception): pass try: 1 / 0 except FooError: pass pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/000077500000000000000000000000001511304262100221555ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/bad.py000066400000000000000000000011431511304262100232540ustar00rootroot00000000000000def teacher_greeting(names): greetings = [] for name in names: def greet(): # do something print(f"Hello, {name}!") # [cell-var-from-loop] if name.isalpha(): greetings.append(greet) for greet in greetings: # the "name" variable is evaluated when the function is called here, # which is the last value it had in the loop - "Not-A-Name" greet() teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"]) # "Hello, Michael!" # "Hello, Michael!" # "Hello, Michael!" # "Hello, Michael!" # "Hello, Michael!" pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/good/000077500000000000000000000000001511304262100231055ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/good/functools.partial.py000066400000000000000000000011631511304262100271270ustar00rootroot00000000000000import functools def teacher_greeting(names): greetings = [] for name in names: if name.isalpha(): # "name" is evaluated when the partial is created here, so this # does not do lazy evaluation greetings.append(functools.partial(print, f"Hello, {name}!")) for greet in greetings: # `partial`s are called like functions, but you've already passed the # arguments to them greet() teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"]) # "Hello, Graham!" # "Hello, John!" # "Hello, Eric!" # "Hello, Terry!" # "Hello, Michael!" pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/good/new_function.py000066400000000000000000000006411511304262100261560ustar00rootroot00000000000000def teacher_greeting(names): def greet(name): # do something print(f"Hello, {name}!") for name in names: if name.isalpha(): # we're passing the value of "name" to the function here greet(name) teacher_greeting(["Graham", "John", "Terry", "Eric", "Terry", "Michael"]) # "Hello, Graham!" # "Hello, John!" # "Hello, Eric!" # "Hello, Terry!" # "Hello, Michael!" pylint-4.0.4/doc/data/messages/c/cell-var-from-loop/related.rst000066400000000000000000000001641511304262100243300ustar00rootroot00000000000000- `Stackoverflow discussion `_ pylint-4.0.4/doc/data/messages/c/chained-comparison/000077500000000000000000000000001511304262100223035ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/chained-comparison/bad.py000066400000000000000000000001501511304262100233770ustar00rootroot00000000000000a = int(input()) b = int(input()) c = int(input()) if a < b and b < c: # [chained-comparison] pass pylint-4.0.4/doc/data/messages/c/chained-comparison/good.py000066400000000000000000000001121511304262100235770ustar00rootroot00000000000000a = int(input()) b = int(input()) c = int(input()) if a < b < c: pass pylint-4.0.4/doc/data/messages/c/class-variable-slots-conflict/000077500000000000000000000000001511304262100243715ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/class-variable-slots-conflict/bad.py000066400000000000000000000005741511304262100254770ustar00rootroot00000000000000class Person: # +1: [class-variable-slots-conflict, class-variable-slots-conflict, class-variable-slots-conflict] __slots__ = ("age", "name", "say_hi") name = None def __init__(self, age, name): self.age = age self.name = name @property def age(self): return self.age def say_hi(self): print(f"Hi, I'm {self.name}.") pylint-4.0.4/doc/data/messages/c/class-variable-slots-conflict/good.py000066400000000000000000000003751511304262100257000ustar00rootroot00000000000000class Person: __slots__ = ("_age", "name") def __init__(self, age, name): self._age = age self.name = name @property def age(self): return self._age def say_hi(self): print(f"Hi, I'm {self.name}.") pylint-4.0.4/doc/data/messages/c/comparison-of-constants/000077500000000000000000000000001511304262100233265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/comparison-of-constants/bad.py000066400000000000000000000001161511304262100244240ustar00rootroot00000000000000def is_the_answer() -> bool: return 42 == 42 # [comparison-of-constants] pylint-4.0.4/doc/data/messages/c/comparison-of-constants/good.py000066400000000000000000000001221511304262100246230ustar00rootroot00000000000000def is_the_answer(meaning_of_life: int) -> bool: return meaning_of_life == 42 pylint-4.0.4/doc/data/messages/c/comparison-with-callable/000077500000000000000000000000001511304262100234205ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/comparison-with-callable/bad.py000066400000000000000000000003731511304262100245230ustar00rootroot00000000000000def function_returning_a_fruit() -> str: return "orange" def is_an_orange(fruit: str = "apple"): # apple == return fruit == function_returning_a_fruit # [comparison-with-callable] pylint-4.0.4/doc/data/messages/c/comparison-with-callable/good.py000066400000000000000000000002561511304262100247250ustar00rootroot00000000000000def function_returning_a_fruit() -> str: return "orange" def is_an_orange(fruit: str = "apple"): # apple == orange return fruit == function_returning_a_fruit() pylint-4.0.4/doc/data/messages/c/comparison-with-itself/000077500000000000000000000000001511304262100231475ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/comparison-with-itself/bad.py000066400000000000000000000001501511304262100242430ustar00rootroot00000000000000def is_an_orange(fruit): an_orange = "orange" return fruit == fruit # [comparison-with-itself] pylint-4.0.4/doc/data/messages/c/comparison-with-itself/good.py000066400000000000000000000001201511304262100244420ustar00rootroot00000000000000def is_an_orange(fruit): an_orange = "orange" return an_orange == fruit pylint-4.0.4/doc/data/messages/c/condition-evals-to-constant/000077500000000000000000000000001511304262100241055ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/condition-evals-to-constant/bad.py000066400000000000000000000001561511304262100252070ustar00rootroot00000000000000def is_a_fruit(fruit): return bool(fruit in {"apple", "orange"} or True) # [condition-evals-to-constant] pylint-4.0.4/doc/data/messages/c/condition-evals-to-constant/good.py000066400000000000000000000000771511304262100254130ustar00rootroot00000000000000def is_a_fruit(fruit): return fruit in {"apple", "orange"} pylint-4.0.4/doc/data/messages/c/config-parse-error/000077500000000000000000000000001511304262100222445ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/config-parse-error/details.rst000066400000000000000000000001131511304262100244160ustar00rootroot00000000000000This is a message linked to a problem in your configuration not your code. pylint-4.0.4/doc/data/messages/c/confusing-consecutive-elif/000077500000000000000000000000001511304262100237755ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/confusing-consecutive-elif/bad.py000066400000000000000000000003441511304262100250760ustar00rootroot00000000000000def myfunc(shall_continue: bool, shall_exit: bool): if shall_continue: if input("Are you sure?") == "y": print("Moving on.") elif shall_exit: # [confusing-consecutive-elif] print("Exiting.") pylint-4.0.4/doc/data/messages/c/confusing-consecutive-elif/details.rst000066400000000000000000000002731511304262100261560ustar00rootroot00000000000000Creating a function for the nested conditional, or adding an explicit ``else`` in the indented ``if`` statement, even if it only contains a ``pass`` statement, can help clarify the code. pylint-4.0.4/doc/data/messages/c/confusing-consecutive-elif/good.py000066400000000000000000000010261511304262100252760ustar00rootroot00000000000000# Option 1: add explicit 'else' def myfunc(shall_continue: bool, shall_exit: bool): if shall_continue: if input("Are you sure?") == "y": print("Moving on.") else: pass elif shall_exit: print("Exiting.") # Option 2: extract function def user_confirmation(): if input("Are you sure?") == "y": print("Moving on.") def myfunc2(shall_continue: bool, shall_exit: bool): if shall_continue: user_confirmation() elif shall_exit: print("Exiting.") pylint-4.0.4/doc/data/messages/c/confusing-consecutive-elif/pylintrc000066400000000000000000000000651511304262100255650ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.confusing_elif pylint-4.0.4/doc/data/messages/c/confusing-with-statement/000077500000000000000000000000001511304262100235065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/confusing-with-statement/bad.py000066400000000000000000000001171511304262100246050ustar00rootroot00000000000000with open("file.txt", "w") as fh1, fh2: # [confusing-with-statement] pass pylint-4.0.4/doc/data/messages/c/confusing-with-statement/good.py000066400000000000000000000001711511304262100250070ustar00rootroot00000000000000with open("file.txt", "w", encoding="utf8") as fh1: with open("file.txt", "w", encoding="utf8") as fh2: pass pylint-4.0.4/doc/data/messages/c/consider-alternative-union-syntax/000077500000000000000000000000001511304262100253345ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-alternative-union-syntax/bad.py000066400000000000000000000003601511304262100264330ustar00rootroot00000000000000from typing import Optional, Union def forecast( temp: Union[int, float], # [consider-alternative-union-syntax] unit: Optional[str], # [consider-alternative-union-syntax] ) -> None: print(f'Temperature: {temp}{unit or ""}') pylint-4.0.4/doc/data/messages/c/consider-alternative-union-syntax/details.rst000066400000000000000000000012441511304262100275140ustar00rootroot00000000000000Using the shorthand syntax for union types is |recommended over the typing module|__. This is consistent with the broader recommendation to prefer built-in types over imports (for example, using ``list`` instead of the now-deprecated ``typing.List``). ``typing.Optional`` can also cause confusion in annotated function arguments, since an argument annotated as ``Optional`` is still a *required* argument when a default value is not set. Explicitly annotating such arguments with ``type | None`` makes the intention clear. .. |recommended over the typing module| replace:: recommended over the ``typing`` module __ https://docs.python.org/3/library/typing.html#typing.Union pylint-4.0.4/doc/data/messages/c/consider-alternative-union-syntax/good.py000066400000000000000000000001511511304262100266330ustar00rootroot00000000000000def forecast(temp: int | float, unit: str | None) -> None: print(f'Temperature: {temp}{unit or ""}') pylint-4.0.4/doc/data/messages/c/consider-alternative-union-syntax/pylintrc000066400000000000000000000000571511304262100271250ustar00rootroot00000000000000[MAIN] load-plugins = pylint.extensions.typing pylint-4.0.4/doc/data/messages/c/consider-iterating-dictionary/000077500000000000000000000000001511304262100244755ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-iterating-dictionary/bad.py000066400000000000000000000002001511304262100255650ustar00rootroot00000000000000FRUITS = {"apple": 1, "pear": 5, "peach": 10} for fruit in FRUITS.keys(): # [consider-iterating-dictionary] print(fruit) pylint-4.0.4/doc/data/messages/c/consider-iterating-dictionary/good.py000066400000000000000000000001261511304262100257760ustar00rootroot00000000000000FRUITS = {"apple": 1, "pear": 5, "peach": 10} for fruit in FRUITS: print(fruit) pylint-4.0.4/doc/data/messages/c/consider-math-not-float/000077500000000000000000000000001511304262100231765ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-math-not-float/bad.py000066400000000000000000000000611511304262100242730ustar00rootroot00000000000000swag = float("inf") # [consider-math-not-float] pylint-4.0.4/doc/data/messages/c/consider-math-not-float/details.rst000066400000000000000000000022241511304262100253550ustar00rootroot00000000000000This is an extension check because the typing advantage could be fixed. Regarding performance, float("nan") and float("inf") are slower than their counterpart math.inf and math.nan by a factor of 4 after the initial import of math. .. code-block:: python import math import timeit time_math_inf = timeit.timeit('math.nan', globals=globals(), number=10**8) print(f'math.nan: {time_math_inf:.2f} seconds') import timeit time_inf_str = timeit.timeit('float("nan")', number=10**8) print(f'float("nan"): {time_inf_str:.2f} seconds') Result:: math.nan: 1.24 seconds float("nan"): 5.15 seconds But if we take the initial import into account it's worse. .. code-block:: python import timeit time_math_inf = timeit.timeit('import math;math.nan', globals=globals(), number=10**8) print(f'math.nan: {time_math_inf:.2f} seconds') import timeit time_inf_str = timeit.timeit('float("nan")', number=10**8) print(f'float("nan"): {time_inf_str:.2f} seconds') Result:: math.nan: 9.08 seconds float("nan"): 5.33 seconds So the decision depends on how and how often you need to use it and what matter to you. pylint-4.0.4/doc/data/messages/c/consider-math-not-float/good.py000066400000000000000000000000351511304262100244760ustar00rootroot00000000000000import math swag = math.inf pylint-4.0.4/doc/data/messages/c/consider-math-not-float/pylintrc000066400000000000000000000000611511304262100247620ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.code_style pylint-4.0.4/doc/data/messages/c/consider-merging-isinstance/000077500000000000000000000000001511304262100241325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-merging-isinstance/bad.py000066400000000000000000000002421511304262100252300ustar00rootroot00000000000000from typing import Any def is_number(value: Any) -> bool: # +1: [consider-merging-isinstance] return isinstance(value, int) or isinstance(value, float) pylint-4.0.4/doc/data/messages/c/consider-merging-isinstance/good.py000066400000000000000000000001471511304262100254360ustar00rootroot00000000000000from typing import Any def is_number(value: Any) -> bool: return isinstance(value, (int, float)) pylint-4.0.4/doc/data/messages/c/consider-refactoring-into-while-condition/000077500000000000000000000000001511304262100267105ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-refactoring-into-while-condition/bad.py000066400000000000000000000003711511304262100300110ustar00rootroot00000000000000fruit_basket = ["apple", "orange", "banana", "cherry", "guava"] while True: # [consider-refactoring-into-while-condition] if len(fruit_basket) == 0: break fruit = fruit_basket.pop() print(f"We removed {fruit} from the basket") pylint-4.0.4/doc/data/messages/c/consider-refactoring-into-while-condition/good.py000066400000000000000000000002571511304262100302160ustar00rootroot00000000000000fruit_basket = ["apple", "orange", "banana", "cherry", "guava"] while len(fruit_basket) != 0: fruit = fruit_basket.pop() print(f"We removed {fruit} from the basket") pylint-4.0.4/doc/data/messages/c/consider-refactoring-into-while-condition/pylintrc000066400000000000000000000001201511304262100304700ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.consider_refactoring_into_while_condition pylint-4.0.4/doc/data/messages/c/consider-swap-variables/000077500000000000000000000000001511304262100232645ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-swap-variables/bad.py000066400000000000000000000001021511304262100243550ustar00rootroot00000000000000a = 1 b = 2 temp = a # [consider-swap-variables] a = b b = temp pylint-4.0.4/doc/data/messages/c/consider-swap-variables/good.py000066400000000000000000000000311511304262100245600ustar00rootroot00000000000000a = 1 b = 2 a, b = b, a pylint-4.0.4/doc/data/messages/c/consider-ternary-expression/000077500000000000000000000000001511304262100242255ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-ternary-expression/bad.py000066400000000000000000000001521511304262100253230ustar00rootroot00000000000000x, y = input(), input() if x >= y: # [consider-ternary-expression] maximum = x else: maximum = y pylint-4.0.4/doc/data/messages/c/consider-ternary-expression/good.py000066400000000000000000000000651511304262100255300ustar00rootroot00000000000000x, y = input(), input() maximum = x if x >= y else y pylint-4.0.4/doc/data/messages/c/consider-ternary-expression/pylintrc000066400000000000000000000001021511304262100260050ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.consider_ternary_expression pylint-4.0.4/doc/data/messages/c/consider-using-alias/000077500000000000000000000000001511304262100225605ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-alias/bad.py000066400000000000000000000001051511304262100236540ustar00rootroot00000000000000import typing cats: typing.Dict[str, int] # [consider-using-alias] pylint-4.0.4/doc/data/messages/c/consider-using-alias/good.py000066400000000000000000000000731511304262100240620ustar00rootroot00000000000000import typing cats: typing.cast(dict[str, int], "string") pylint-4.0.4/doc/data/messages/c/consider-using-alias/pylintrc000066400000000000000000000001221511304262100243420ustar00rootroot00000000000000[main] load-plugins = pylint.extensions.typing py-version = 3.7 runtime-typing=no pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/000077500000000000000000000000001511304262100234425ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/bad/000077500000000000000000000000001511304262100241705ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/bad/all_even.py000066400000000000000000000003161511304262100263270ustar00rootroot00000000000000def all_even(items): """Return True if the list contains all even numbers""" for item in items: # [consider-using-any-or-all] if not item % 2 == 0: return False return True pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/bad/any_even.py000066400000000000000000000003121511304262100263420ustar00rootroot00000000000000def any_even(items): """Return True if the list contains any even numbers""" for item in items: # [consider-using-any-or-all] if item % 2 == 0: return True return False pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/good/000077500000000000000000000000001511304262100243725ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/good/all_even.py000066400000000000000000000002011511304262100265220ustar00rootroot00000000000000def all_even(items): """Return True if the list contains all even numbers""" return all(item % 2 == 0 for item in items) pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/good/any_even.py000066400000000000000000000002011511304262100265410ustar00rootroot00000000000000def any_even(items): """Return True if the list contains any even numbers""" return any(item % 2 == 0 for item in items) pylint-4.0.4/doc/data/messages/c/consider-using-any-or-all/pylintrc000066400000000000000000000000621511304262100252270ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.for_any_all pylint-4.0.4/doc/data/messages/c/consider-using-assignment-expr/000077500000000000000000000000001511304262100246135ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-assignment-expr/bad.py000066400000000000000000000001241511304262100257100ustar00rootroot00000000000000apples = 2 if apples: # [consider-using-assignment-expr] print("God apples!") pylint-4.0.4/doc/data/messages/c/consider-using-assignment-expr/good.py000066400000000000000000000000511511304262100261110ustar00rootroot00000000000000if apples := 2: print("God apples!") pylint-4.0.4/doc/data/messages/c/consider-using-assignment-expr/pylintrc000066400000000000000000000001001511304262100263710ustar00rootroot00000000000000[MAIN] py-version=3.8 load-plugins=pylint.extensions.code_style pylint-4.0.4/doc/data/messages/c/consider-using-augmented-assign/000077500000000000000000000000001511304262100247225ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-augmented-assign/bad.py000066400000000000000000000000651511304262100260230ustar00rootroot00000000000000x = 1 x = x + 1 # [consider-using-augmented-assign] pylint-4.0.4/doc/data/messages/c/consider-using-augmented-assign/good.py000066400000000000000000000000151511304262100262200ustar00rootroot00000000000000x = 1 x += 1 pylint-4.0.4/doc/data/messages/c/consider-using-augmented-assign/pylintrc000066400000000000000000000001301511304262100265030ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.code_style enable=consider-using-augmented-assign pylint-4.0.4/doc/data/messages/c/consider-using-dict-comprehension/000077500000000000000000000000001511304262100252615ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-dict-comprehension/bad.py000066400000000000000000000002041511304262100263550ustar00rootroot00000000000000NUMBERS = [1, 2, 3] # +1: [consider-using-dict-comprehension] DOUBLED_NUMBERS = dict([(number, number * 2) for number in NUMBERS]) pylint-4.0.4/doc/data/messages/c/consider-using-dict-comprehension/details.rst000066400000000000000000000002231511304262100274350ustar00rootroot00000000000000pyupgrade_ or ruff_ can fix this issue automatically. .. _pyupgrade: https://github.com/asottile/pyupgrade .. _ruff: https://docs.astral.sh/ruff/ pylint-4.0.4/doc/data/messages/c/consider-using-dict-comprehension/good.py000066400000000000000000000001221511304262100265560ustar00rootroot00000000000000NUMBERS = [1, 2, 3] DOUBLED_NUMBERS = {number: number * 2 for number in NUMBERS} pylint-4.0.4/doc/data/messages/c/consider-using-dict-items/000077500000000000000000000000001511304262100235315ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-dict-items/bad.py000066400000000000000000000003421511304262100246300ustar00rootroot00000000000000ORCHESTRA = { "violin": "strings", "oboe": "woodwind", "tuba": "brass", "gong": "percussion", } for instrument in ORCHESTRA: # [consider-using-dict-items] print(f"{instrument}: {ORCHESTRA[instrument]}") pylint-4.0.4/doc/data/messages/c/consider-using-dict-items/good.py000066400000000000000000000003061511304262100250320ustar00rootroot00000000000000ORCHESTRA = { "violin": "strings", "oboe": "woodwind", "tuba": "brass", "gong": "percussion", } for instrument, section in ORCHESTRA.items(): print(f"{instrument}: {section}") pylint-4.0.4/doc/data/messages/c/consider-using-enumerate/000077500000000000000000000000001511304262100234545ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-enumerate/bad.py000066400000000000000000000002071511304262100245530ustar00rootroot00000000000000seasons = ["Spring", "Summer", "Fall", "Winter"] for i in range(len(seasons)): # [consider-using-enumerate] print(i, seasons[i]) pylint-4.0.4/doc/data/messages/c/consider-using-enumerate/good.py000066400000000000000000000001541511304262100247560ustar00rootroot00000000000000seasons = ["Spring", "Summer", "Fall", "Winter"] for i, season in enumerate(seasons): print(i, season) pylint-4.0.4/doc/data/messages/c/consider-using-f-string/000077500000000000000000000000001511304262100232205ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-f-string/bad.py000066400000000000000000000011411511304262100243150ustar00rootroot00000000000000from string import Template menu = ("eggs", "spam", 42.4) old_order = "%s and %s: %.2f ¤" % menu # [consider-using-f-string] beginner_order = menu[0] + " and " + menu[1] + ": " + str(menu[2]) + " ¤" joined_order = " and ".join(menu[:2]) # +1: [consider-using-f-string] format_order = "{} and {}: {:0.2f} ¤".format(menu[0], menu[1], menu[2]) # +1: [consider-using-f-string] named_format_order = "{eggs} and {spam}: {price:0.2f} ¤".format( eggs=menu[0], spam=menu[1], price=menu[2] ) template_order = Template("$eggs and $spam: $price ¤").substitute( eggs=menu[0], spam=menu[1], price=menu[2] ) pylint-4.0.4/doc/data/messages/c/consider-using-f-string/details.rst000066400000000000000000000005111511304262100253740ustar00rootroot00000000000000Formatted string literals (f-strings) give a concise, consistent syntax that can replace most use cases for the ``%`` formatting operator, ``str.format()`` and ``string.Template``. F-strings also perform better than alternatives; see `this tweet `_ for a simple example. pylint-4.0.4/doc/data/messages/c/consider-using-f-string/good.py000066400000000000000000000001361511304262100245220ustar00rootroot00000000000000menu = ("eggs", "spam", 42.4) f_string_order = f"{menu[0]} and {menu[1]}: {menu[2]:0.2f} ¤" pylint-4.0.4/doc/data/messages/c/consider-using-from-import/000077500000000000000000000000001511304262100237425ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-from-import/bad.py000066400000000000000000000000671511304262100250450ustar00rootroot00000000000000import os.path as path # [consider-using-from-import] pylint-4.0.4/doc/data/messages/c/consider-using-from-import/good.py000066400000000000000000000000241511304262100252400ustar00rootroot00000000000000from os import path pylint-4.0.4/doc/data/messages/c/consider-using-generator/000077500000000000000000000000001511304262100234555ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-generator/bad.py000066400000000000000000000005141511304262100245550ustar00rootroot00000000000000list([0 for y in list(range(10))]) # [consider-using-generator] tuple([0 for y in list(range(10))]) # [consider-using-generator] sum([y**2 for y in list(range(10))]) # [consider-using-generator] max([y**2 for y in list(range(10))]) # [consider-using-generator] min([y**2 for y in list(range(10))]) # [consider-using-generator] pylint-4.0.4/doc/data/messages/c/consider-using-generator/details.rst000066400000000000000000000005021511304262100256310ustar00rootroot00000000000000Removing ``[]`` inside calls that can use containers or generators should be considered for performance reasons since a generator will have an upfront cost to pay. The performance will be better if you are working with long lists or sets. For ``max``, ``min`` and ``sum`` using a generator is also recommended by pep289. pylint-4.0.4/doc/data/messages/c/consider-using-generator/good.py000066400000000000000000000002541511304262100247600ustar00rootroot00000000000000list(0 for y in list(range(10))) tuple(0 for y in list(range(10))) sum(y**2 for y in list(range(10))) max(y**2 for y in list(range(10))) min(y**2 for y in list(range(10))) pylint-4.0.4/doc/data/messages/c/consider-using-generator/related.rst000066400000000000000000000004441511304262100256310ustar00rootroot00000000000000- `PEP 289 `_ - `Benchmark and discussion for any/all/list/tuple `_ - `Benchmark and discussion for sum/max/min `_ pylint-4.0.4/doc/data/messages/c/consider-using-get/000077500000000000000000000000001511304262100222465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-get/bad.py000066400000000000000000000002551511304262100233500ustar00rootroot00000000000000knights = {"Gallahad": "the pure", "Robin": "the brave"} if "Gallahad" in knights: # [consider-using-get] DESCRIPTION = knights["Gallahad"] else: DESCRIPTION = "" pylint-4.0.4/doc/data/messages/c/consider-using-get/good.py000066400000000000000000000001441511304262100235470ustar00rootroot00000000000000knights = {"Gallahad": "the pure", "Robin": "the brave"} description = knights.get("Gallahad", "") pylint-4.0.4/doc/data/messages/c/consider-using-in/000077500000000000000000000000001511304262100220755ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-in/bad.py000066400000000000000000000001761511304262100232010ustar00rootroot00000000000000def fruit_is_round(fruit): # +1: [consider-using-in] return fruit == "apple" or fruit == "orange" or fruit == "melon" pylint-4.0.4/doc/data/messages/c/consider-using-in/good.py000066400000000000000000000001141511304262100233730ustar00rootroot00000000000000def fruit_is_round(fruit): return fruit in {"apple", "orange", "melon"} pylint-4.0.4/doc/data/messages/c/consider-using-join/000077500000000000000000000000001511304262100224265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-join/bad.py000066400000000000000000000003331511304262100235250ustar00rootroot00000000000000def fruits_to_string(fruits): formatted_fruit = "" for fruit in fruits: formatted_fruit += fruit # [consider-using-join] return formatted_fruit print(fruits_to_string(["apple", "pear", "peach"])) pylint-4.0.4/doc/data/messages/c/consider-using-join/good.py000066400000000000000000000000531511304262100237260ustar00rootroot00000000000000print("".join(["apple", "pear", "peach"])) pylint-4.0.4/doc/data/messages/c/consider-using-max-builtin/000077500000000000000000000000001511304262100237205ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-max-builtin/bad.py000066400000000000000000000002261511304262100250200ustar00rootroot00000000000000def get_max(value1, value2): if value1 < value2: # [consider-using-max-builtin] value1 = value2 return value1 print(get_max(1, 2)) pylint-4.0.4/doc/data/messages/c/consider-using-max-builtin/good.py000066400000000000000000000000211511304262100252130ustar00rootroot00000000000000print(max(1, 2)) pylint-4.0.4/doc/data/messages/c/consider-using-min-builtin/000077500000000000000000000000001511304262100237165ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-min-builtin/bad.py000066400000000000000000000002261511304262100250160ustar00rootroot00000000000000def get_min(value1, value2): if value1 > value2: # [consider-using-min-builtin] value1 = value2 return value1 print(get_min(1, 2)) pylint-4.0.4/doc/data/messages/c/consider-using-min-builtin/good.py000066400000000000000000000000211511304262100252110ustar00rootroot00000000000000print(min(1, 2)) pylint-4.0.4/doc/data/messages/c/consider-using-namedtuple-or-dataclass/000077500000000000000000000000001511304262100262005ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-namedtuple-or-dataclass/bad.py000066400000000000000000000005441511304262100273030ustar00rootroot00000000000000FELIDAES = { # [consider-using-namedtuple-or-dataclass] "The queen's cymric, fragile furry friend": { "tail_length_cm": 1, "paws": 4, "eyes": 2, "Elizabethan collar": 1, }, "Rackat the red, terror of the sea": { "tail_length_cm": 13, "paws": 3, "eyes": 1, "Red Hat": 1, }, } pylint-4.0.4/doc/data/messages/c/consider-using-namedtuple-or-dataclass/good.py000066400000000000000000000006661511304262100275120ustar00rootroot00000000000000from typing import NamedTuple class FelidaeCharacteristics(NamedTuple): tail_length_cm: int paws: int eyes: int hat: str | None FELIDAES = { "The queen's cymric, fragile furry friend": FelidaeCharacteristics( tail_length_cm=1, paws=4, eyes=2, hat="Elizabethan collar" ), "Rackat the red, terror of the sea": FelidaeCharacteristics( tail_length_cm=21, paws=3, eyes=1, hat="Red Hat" ), } pylint-4.0.4/doc/data/messages/c/consider-using-namedtuple-or-dataclass/pylintrc000066400000000000000000000000611511304262100277640ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.code_style pylint-4.0.4/doc/data/messages/c/consider-using-set-comprehension/000077500000000000000000000000001511304262100251315ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-set-comprehension/bad.py000066400000000000000000000002241511304262100262270ustar00rootroot00000000000000NUMBERS = [1, 2, 2, 3, 4, 4] # +1: [consider-using-set-comprehension] UNIQUE_EVEN_NUMBERS = set([number for number in NUMBERS if number % 2 == 0]) pylint-4.0.4/doc/data/messages/c/consider-using-set-comprehension/details.rst000066400000000000000000000002231511304262100273050ustar00rootroot00000000000000pyupgrade_ or ruff_ can fix this issue automatically. .. _pyupgrade: https://github.com/asottile/pyupgrade .. _ruff: https://docs.astral.sh/ruff/ pylint-4.0.4/doc/data/messages/c/consider-using-set-comprehension/good.py000066400000000000000000000001461511304262100264340ustar00rootroot00000000000000NUMBERS = [1, 2, 2, 3, 4, 4] UNIQUE_EVEN_NUMBERS = {number for number in NUMBERS if number % 2 == 0} pylint-4.0.4/doc/data/messages/c/consider-using-sys-exit/000077500000000000000000000000001511304262100232545ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-sys-exit/bad.py000066400000000000000000000002061511304262100243520ustar00rootroot00000000000000if __name__ == "__main__": user = input("Enter user name: ") print(f"Hello, {user}") exit(0) # [consider-using-sys-exit] pylint-4.0.4/doc/data/messages/c/consider-using-sys-exit/good.py000066400000000000000000000001711511304262100245550ustar00rootroot00000000000000import sys if __name__ == "__main__": user = input("Enter user name: ") print(f"Hello, {user}") sys.exit(0) pylint-4.0.4/doc/data/messages/c/consider-using-ternary/000077500000000000000000000000001511304262100231535ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-ternary/bad.py000066400000000000000000000001041511304262100242460ustar00rootroot00000000000000x, y = 1, 2 maximum = x >= y and x or y # [consider-using-ternary] pylint-4.0.4/doc/data/messages/c/consider-using-ternary/good.py000066400000000000000000000000511511304262100244510ustar00rootroot00000000000000x, y = 1, 2 maximum = x if x >= y else y pylint-4.0.4/doc/data/messages/c/consider-using-tuple/000077500000000000000000000000001511304262100226205ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-tuple/bad.py000066400000000000000000000000731511304262100237200ustar00rootroot00000000000000for i in [1, 2, 3]: # [consider-using-tuple] print(i) pylint-4.0.4/doc/data/messages/c/consider-using-tuple/good.py000066400000000000000000000000411511304262100241150ustar00rootroot00000000000000for i in (1, 2, 3): print(i) pylint-4.0.4/doc/data/messages/c/consider-using-tuple/pylintrc000066400000000000000000000000611511304262100244040ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.code_style pylint-4.0.4/doc/data/messages/c/consider-using-with/000077500000000000000000000000001511304262100224425ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-with/bad/000077500000000000000000000000001511304262100231705ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/consider-using-with/bad/close.py000066400000000000000000000001541511304262100246470ustar00rootroot00000000000000file = open("apple.txt", "r", encoding="utf8") # [consider-using-with] contents = file.read() file.close() pylint-4.0.4/doc/data/messages/c/consider-using-with/bad/not_even_close.py000066400000000000000000000001231511304262100265400ustar00rootroot00000000000000contents = open("apple.txt", "r", encoding="utf8").read() # [consider-using-with] pylint-4.0.4/doc/data/messages/c/consider-using-with/details.rst000066400000000000000000000007761511304262100246330ustar00rootroot00000000000000Calling ``write()`` without using the ``with`` keyword or calling ``close()`` might result in the arguments of ``write()`` not being completely written to the disk, even if the program exits successfully. This message applies to callables of Python's stdlib which can be replaced by a ``with`` statement. It is suppressed in the following cases: - the call is located inside a context manager - the call result is returned from the enclosing function - the call result is used in a ``with`` statement itself pylint-4.0.4/doc/data/messages/c/consider-using-with/good.py000066400000000000000000000001211511304262100237360ustar00rootroot00000000000000with open("apple.txt", "r", encoding="utf8") as file: contents = file.read() pylint-4.0.4/doc/data/messages/c/consider-using-with/related.rst000066400000000000000000000005241511304262100246150ustar00rootroot00000000000000- `Python doc: Reading and writing files `_ - `PEP 343 `_ - `Context managers in Python `_ by John Lekberg - `Rationale `_ pylint-4.0.4/doc/data/messages/c/contextmanager-generator-missing-cleanup/000077500000000000000000000000001511304262100266375ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/contextmanager-generator-missing-cleanup/bad.py000066400000000000000000000004301511304262100277340ustar00rootroot00000000000000import contextlib @contextlib.contextmanager def cm(): contextvar = "acquired context" print("cm enter") yield contextvar print("cm exit") def genfunc_with_cm(): with cm() as context: # [contextmanager-generator-missing-cleanup] yield context * 2 pylint-4.0.4/doc/data/messages/c/contextmanager-generator-missing-cleanup/details.rst000066400000000000000000000025021511304262100310150ustar00rootroot00000000000000Instantiating and using a contextmanager inside a generator function can result in unexpected behavior if there is an expectation that the context is only available for the generator function. In the case that the generator is not closed or destroyed then the context manager is held suspended as is. This message warns on the generator function instead of the contextmanager function because the ways to use a contextmanager are many. A contextmanager can be used as a decorator (which immediately has ``__enter__``/``__exit__`` applied) and the use of ``as ...`` or discard of the return value also implies whether the context needs cleanup or not. So for this message, warning the invoker of the contextmanager is important. The check can create false positives if ``yield`` is used inside an ``if-else`` block without custom cleanup. Use ``pylint: disable`` for these. .. code-block:: python from contextlib import contextmanager @contextmanager def good_cm_no_cleanup(): contextvar = "acquired context" print("cm enter") if some_condition: yield contextvar else: yield contextvar def good_cm_no_cleanup_genfunc(): # pylint: disable-next=contextmanager-generator-missing-cleanup with good_cm_no_cleanup() as context: yield context * 2 pylint-4.0.4/doc/data/messages/c/contextmanager-generator-missing-cleanup/good.py000066400000000000000000000022111511304262100301350ustar00rootroot00000000000000import contextlib @contextlib.contextmanager def good_cm_except(): contextvar = "acquired context" print("good cm enter") try: yield contextvar except GeneratorExit: print("good cm exit") def genfunc_with_cm(): with good_cm_except() as context: yield context * 2 def genfunc_with_discard(): with good_cm_except(): yield "discarded" @contextlib.contextmanager def good_cm_yield_none(): print("good cm enter") yield print("good cm exit") def genfunc_with_none_yield(): with good_cm_yield_none() as var: print(var) yield "constant yield" @contextlib.contextmanager def good_cm_finally(): contextvar = "acquired context" print("good cm enter") try: yield contextvar finally: print("good cm exit") def good_cm_finally_genfunc(): with good_cm_finally() as context: yield context * 2 @contextlib.contextmanager def good_cm_no_cleanup(): contextvar = "acquired context" print("cm enter") yield contextvar def good_cm_no_cleanup_genfunc(): with good_cm_no_cleanup() as context: yield context * 2 pylint-4.0.4/doc/data/messages/c/contextmanager-generator-missing-cleanup/related.rst000066400000000000000000000003001511304262100310020ustar00rootroot00000000000000- `Rationale `_ - `CPython Issue `_ pylint-4.0.4/doc/data/messages/c/continue-in-finally/000077500000000000000000000000001511304262100224245ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/continue-in-finally/bad.py000066400000000000000000000001311511304262100235170ustar00rootroot00000000000000while True: try: pass finally: continue # [continue-in-finally] pylint-4.0.4/doc/data/messages/c/continue-in-finally/good.py000066400000000000000000000001411511304262100237220ustar00rootroot00000000000000while True: try: pass except ValueError: pass else: continue pylint-4.0.4/doc/data/messages/c/continue-in-finally/related.rst000066400000000000000000000003311511304262100245730ustar00rootroot00000000000000- `Python 3 docs 'finally' clause `_ - `PEP 765 - Disallow return/break/continue that exit a finally block `_ pylint-4.0.4/doc/data/messages/c/cyclic-import/000077500000000000000000000000001511304262100213165ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/cyclic-import/bad/000077500000000000000000000000001511304262100220445ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/cyclic-import/bad/__init__.py000066400000000000000000000000001511304262100241430ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/c/cyclic-import/bad/bad.py000066400000000000000000000001731511304262100231450ustar00rootroot00000000000000def count_to_one(): return 1 def count_to_three(): from .bad2 import count_to_two return count_to_two() + 1 pylint-4.0.4/doc/data/messages/c/cyclic-import/bad/bad2.py000066400000000000000000000001451511304262100232260ustar00rootroot00000000000000from .bad import count_to_one # [cyclic-import] def count_to_two(): return count_to_one() + 1 pylint-4.0.4/doc/data/messages/c/cyclic-import/details.rst000066400000000000000000000002631511304262100234760ustar00rootroot00000000000000The good code is just an example. There are various strategies to resolving cyclic imports and the best choice relies heavily on the context of the code and the affected modules. pylint-4.0.4/doc/data/messages/c/cyclic-import/good.py000066400000000000000000000002131511304262100226140ustar00rootroot00000000000000def count_to_one(): return 1 def count_to_two(): return count_to_one() + 1 def count_to_three(): return count_to_two() + 1 pylint-4.0.4/doc/data/messages/d/000077500000000000000000000000001511304262100165415ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/dangerous-default-value/000077500000000000000000000000001511304262100232645ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/dangerous-default-value/bad.py000066400000000000000000000001761511304262100243700ustar00rootroot00000000000000def whats_on_the_telly(penguin=[]): # [dangerous-default-value] penguin.append("property of the zoo") return penguin pylint-4.0.4/doc/data/messages/d/dangerous-default-value/details.rst000066400000000000000000000005111511304262100254400ustar00rootroot00000000000000With a mutable default value, with each call the default value is modified, i.e.: .. code-block:: python whats_on_the_telly() # ["property of the zoo"] whats_on_the_telly() # ["property of the zoo", "property of the zoo"] whats_on_the_telly() # ["property of the zoo", "property of the zoo", "property of the zoo"] pylint-4.0.4/doc/data/messages/d/dangerous-default-value/good.py000066400000000000000000000002201511304262100245600ustar00rootroot00000000000000def whats_on_the_telly(penguin=None): if penguin is None: penguin = [] penguin.append("property of the zoo") return penguin pylint-4.0.4/doc/data/messages/d/declare-non-slot/000077500000000000000000000000001511304262100217075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/declare-non-slot/bad.py000066400000000000000000000001371511304262100230100ustar00rootroot00000000000000class Student: __slots__ = ("name",) name: str surname: str # [declare-non-slot] pylint-4.0.4/doc/data/messages/d/declare-non-slot/good.py000066400000000000000000000001231511304262100232050ustar00rootroot00000000000000class Student: __slots__ = ("name", "surname") name: str surname: str pylint-4.0.4/doc/data/messages/d/deprecated-argument/000077500000000000000000000000001511304262100224615ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-argument/bad.py000066400000000000000000000000421511304262100235550ustar00rootroot00000000000000int(x=1) # [deprecated-argument] pylint-4.0.4/doc/data/messages/d/deprecated-argument/details.rst000066400000000000000000000001741511304262100246420ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-argument/good.py000066400000000000000000000000071511304262100237600ustar00rootroot00000000000000int(1) pylint-4.0.4/doc/data/messages/d/deprecated-argument/pylintrc000066400000000000000000000000001511304262100242360ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-attribute/000077500000000000000000000000001511304262100226425ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-attribute/bad.py000066400000000000000000000001661511304262100237450ustar00rootroot00000000000000from configparser import ParsingError err = ParsingError("filename") source = err.filename # [deprecated-attribute] pylint-4.0.4/doc/data/messages/d/deprecated-attribute/details.rst000066400000000000000000000001741511304262100250230ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-attribute/good.py000066400000000000000000000001321511304262100241400ustar00rootroot00000000000000from configparser import ParsingError err = ParsingError("filename") source = err.source pylint-4.0.4/doc/data/messages/d/deprecated-class/000077500000000000000000000000001511304262100217445ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-class/bad.py000066400000000000000000000000671511304262100230470ustar00rootroot00000000000000from collections import Iterable # [deprecated-class] pylint-4.0.4/doc/data/messages/d/deprecated-class/details.rst000066400000000000000000000001741511304262100241250ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-class/good.py000066400000000000000000000000451511304262100232450ustar00rootroot00000000000000from collections.abc import Iterable pylint-4.0.4/doc/data/messages/d/deprecated-decorator/000077500000000000000000000000001511304262100226215ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-decorator/bad.py000066400000000000000000000001641511304262100237220ustar00rootroot00000000000000import abc class Animal: @abc.abstractclassmethod # [deprecated-decorator] def breath(cls): pass pylint-4.0.4/doc/data/messages/d/deprecated-decorator/details.rst000066400000000000000000000001741511304262100250020ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-decorator/good.py000066400000000000000000000001521511304262100241210ustar00rootroot00000000000000import abc class Animal: @abc.classmethod @abc.abstractmethod def breath(cls): pass pylint-4.0.4/doc/data/messages/d/deprecated-decorator/pylintrc000066400000000000000000000000301511304262100244010ustar00rootroot00000000000000[main] py-version = 3.3 pylint-4.0.4/doc/data/messages/d/deprecated-method/000077500000000000000000000000001511304262100221175ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-method/bad.py000066400000000000000000000001131511304262100232120ustar00rootroot00000000000000import logging logging.warn("I'm coming, world !") # [deprecated-method] pylint-4.0.4/doc/data/messages/d/deprecated-method/details.rst000066400000000000000000000001741511304262100243000ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-method/good.py000066400000000000000000000000671511304262100234240ustar00rootroot00000000000000import logging logging.warning("I'm coming, world !") pylint-4.0.4/doc/data/messages/d/deprecated-module/000077500000000000000000000000001511304262100221245ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-module/bad.py000066400000000000000000000001311511304262100232170ustar00rootroot00000000000000import distutils # [deprecated-module] import whatever_you_want # [deprecated-module] pylint-4.0.4/doc/data/messages/d/deprecated-module/details.rst000066400000000000000000000001741511304262100243050ustar00rootroot00000000000000The actual replacement needs to be studied on a case by case basis by reading the deprecation warning or the release notes. pylint-4.0.4/doc/data/messages/d/deprecated-module/good.py000066400000000000000000000000671511304262100234310ustar00rootroot00000000000000import setuptools import whatever_replacement_you_want pylint-4.0.4/doc/data/messages/d/deprecated-module/pylintrc000066400000000000000000000000731511304262100237130ustar00rootroot00000000000000[main] py-version=3.7 deprecated-modules=whatever_you_want pylint-4.0.4/doc/data/messages/d/deprecated-pragma/000077500000000000000000000000001511304262100221065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-pragma/bad.py000066400000000000000000000000661511304262100232100ustar00rootroot00000000000000# pylint: disable-msg=eval-used # [deprecated-pragma] pylint-4.0.4/doc/data/messages/d/deprecated-pragma/good.py000066400000000000000000000000361511304262100234070ustar00rootroot00000000000000# pylint: disable = eval-used pylint-4.0.4/doc/data/messages/d/deprecated-typing-alias/000077500000000000000000000000001511304262100232405ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/deprecated-typing-alias/bad.py000066400000000000000000000001321511304262100243340ustar00rootroot00000000000000import typing item_to_number_of_item: typing.Dict[str, int] # [deprecated-typing-alias] pylint-4.0.4/doc/data/messages/d/deprecated-typing-alias/good.py000066400000000000000000000000471511304262100245430ustar00rootroot00000000000000item_to_number_of_item: dict[str, int] pylint-4.0.4/doc/data/messages/d/deprecated-typing-alias/pylintrc000066400000000000000000000000571511304262100250310ustar00rootroot00000000000000[main] load-plugins = pylint.extensions.typing pylint-4.0.4/doc/data/messages/d/dict-init-mutate/000077500000000000000000000000001511304262100217225ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/dict-init-mutate/bad.py000066400000000000000000000001361511304262100230220ustar00rootroot00000000000000fruit_prices = {} # [dict-init-mutate] fruit_prices["apple"] = 1 fruit_prices["banana"] = 10 pylint-4.0.4/doc/data/messages/d/dict-init-mutate/good.py000066400000000000000000000000521511304262100232210ustar00rootroot00000000000000fruit_prices = {"apple": 1, "banana": 10} pylint-4.0.4/doc/data/messages/d/dict-init-mutate/pylintrc000066400000000000000000000000701511304262100235060ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.dict_init_mutate, pylint-4.0.4/doc/data/messages/d/dict-iter-missing-items/000077500000000000000000000000001511304262100232135ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/dict-iter-missing-items/bad.py000066400000000000000000000002721511304262100243140ustar00rootroot00000000000000data = {"Paris": 2_165_423, "New York City": 8_804_190, "Tokyo": 13_988_129} for city, population in data: # [dict-iter-missing-items] print(f"{city} has population {population}.") pylint-4.0.4/doc/data/messages/d/dict-iter-missing-items/good.py000066400000000000000000000002451511304262100245160ustar00rootroot00000000000000data = {"Paris": 2_165_423, "New York City": 8_804_190, "Tokyo": 13_988_129} for city, population in data.items(): print(f"{city} has population {population}.") pylint-4.0.4/doc/data/messages/d/differing-param-doc/000077500000000000000000000000001511304262100223375ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/differing-param-doc/bad.py000066400000000000000000000002211511304262100234320ustar00rootroot00000000000000def add(x, y): # [differing-param-doc] """Add two numbers. :param int x: x value. :param int z: z value. """ return x + y pylint-4.0.4/doc/data/messages/d/differing-param-doc/good.py000066400000000000000000000001701511304262100236370ustar00rootroot00000000000000def add(x, y): """Add two numbers. :param int x: x value. :param int y: y value. """ return x + y pylint-4.0.4/doc/data/messages/d/differing-param-doc/pylintrc000066400000000000000000000000621511304262100241240ustar00rootroot00000000000000[MAIN] load-plugins = pylint.extensions.docparams pylint-4.0.4/doc/data/messages/d/differing-type-doc/000077500000000000000000000000001511304262100222205ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/differing-type-doc/bad.py000066400000000000000000000002331511304262100233160ustar00rootroot00000000000000def add(x: int, y: int): # [differing-type-doc] """Add two numbers. :param int xy: x value. :param str y: y value. """ return x + y pylint-4.0.4/doc/data/messages/d/differing-type-doc/good.py000066400000000000000000000001701511304262100235200ustar00rootroot00000000000000def add(x, y): """Add two numbers. :param int x: x value. :param int y: y value. """ return x + y pylint-4.0.4/doc/data/messages/d/differing-type-doc/pylintrc000066400000000000000000000000621511304262100240050ustar00rootroot00000000000000[MAIN] load-plugins = pylint.extensions.docparams pylint-4.0.4/doc/data/messages/d/disallowed-name/000077500000000000000000000000001511304262100216065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/disallowed-name/bad.py000066400000000000000000000000641511304262100227060ustar00rootroot00000000000000def foo(): # [disallowed-name] print("apples") pylint-4.0.4/doc/data/messages/d/disallowed-name/good.py000066400000000000000000000000471511304262100231110ustar00rootroot00000000000000def print_fruit(): print("apples") pylint-4.0.4/doc/data/messages/d/disallowed-name/pylintrc000066400000000000000000000000351511304262100233730ustar00rootroot00000000000000[MAIN] bad-names=foo,bar,baz pylint-4.0.4/doc/data/messages/d/docstring-first-line-empty/000077500000000000000000000000001511304262100237435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/docstring-first-line-empty/bad.py000066400000000000000000000005051511304262100250430ustar00rootroot00000000000000def foo(): # [docstring-first-line-empty] """ Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book """ pylint-4.0.4/doc/data/messages/d/docstring-first-line-empty/good.py000066400000000000000000000004401511304262100252430ustar00rootroot00000000000000def foo(): """Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book """ pylint-4.0.4/doc/data/messages/d/docstring-first-line-empty/pylintrc000066400000000000000000000000611511304262100255270ustar00rootroot00000000000000[MAIN] load-plugins = pylint.extensions.docstyle pylint-4.0.4/doc/data/messages/d/duplicate-argument-name/000077500000000000000000000000001511304262100232515ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-argument-name/bad.py000066400000000000000000000001141511304262100243450ustar00rootroot00000000000000def get_fruits(apple, banana, apple): # [duplicate-argument-name] pass pylint-4.0.4/doc/data/messages/d/duplicate-argument-name/good.py000066400000000000000000000000601511304262100245470ustar00rootroot00000000000000def get_fruits(apple, banana, orange): pass pylint-4.0.4/doc/data/messages/d/duplicate-bases/000077500000000000000000000000001511304262100216065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-bases/bad.py000066400000000000000000000001221511304262100227010ustar00rootroot00000000000000class Animal: pass class Cat(Animal, Animal): # [duplicate-bases] pass pylint-4.0.4/doc/data/messages/d/duplicate-bases/good.py000066400000000000000000000001241511304262100231050ustar00rootroot00000000000000class Animal: pass class Bird(Animal): pass class Cat(Animal): pass pylint-4.0.4/doc/data/messages/d/duplicate-code/000077500000000000000000000000001511304262100214235ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-code/bad/000077500000000000000000000000001511304262100221515ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-code/bad/__init__.py000066400000000000000000000000001511304262100242500ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-code/bad/apple.py000066400000000000000000000006411511304262100236250ustar00rootroot00000000000000class Apple: def __init__(self): self.remaining_bites = 3 def take_bite(self): if self.remaining_bites > 0: print("You take a bite of the apple.") self.remaining_bites -= 1 else: print("The apple is already eaten up!") def eaten_by_animal(self, animal): self.remaining_bites = 0 print("The apple has been eaten by an animal.") pylint-4.0.4/doc/data/messages/d/duplicate-code/bad/orange.py000066400000000000000000000010201511304262100237670ustar00rootroot00000000000000class Orange: # [duplicate-code] def __init__(self): self.remaining_bites = 3 def take_bite(self): if self.remaining_bites > 0: print("You take a bite of the apple.") self.remaining_bites -= 1 else: print("The orange is already eaten up!") def eaten_by_animal(self, animal): if animal == "cat": raise ValueError("A cat would never do that !") self.remaining_bites = 0 print("The orange has been eaten by an animal.") pylint-4.0.4/doc/data/messages/d/duplicate-code/details.rst000066400000000000000000000011651511304262100236050ustar00rootroot00000000000000If you need to make a change to the logic or functionality of the duplicated code, you will need to identify all the places that need to be changed, which can be time-consuming and error-prone. If there are multiple copies of the same code, then you will also need to test each copy to ensure that the functionality is correct. Duplicate code can be confusing for someone who is trying to understand the logic and flow of the code if they come across multiple identical or nearly identical blocks of code. The reader can then skim and think something is identical when it actually isn't. This is particularly true during review. pylint-4.0.4/doc/data/messages/d/duplicate-code/good/000077500000000000000000000000001511304262100223535ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-code/good/__init__.py000066400000000000000000000000001511304262100244520ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-code/good/apple.py000066400000000000000000000000621511304262100240240ustar00rootroot00000000000000from fruit import Fruit class Apple(Fruit): ... pylint-4.0.4/doc/data/messages/d/duplicate-code/good/fruit.py000066400000000000000000000007701511304262100240620ustar00rootroot00000000000000class Fruit: def __init__(self): self.remaining_bites = 3 def take_bite(self): if self.remaining_bites > 0: print(f"You take a bite of the {self.__class__.__name__.lower()}.") self.remaining_bites -= 1 else: print(f"The {self.__class__.__name__.lower()} is already eaten up!") def eaten_by_animal(self, animal): self.remaining_bites = 0 print(f"The {self.__class__.__name__.lower()} has been eaten by an animal.") pylint-4.0.4/doc/data/messages/d/duplicate-code/good/orange.py000066400000000000000000000003261511304262100242010ustar00rootroot00000000000000from fruit import Fruit class Orange(Fruit): def eaten_by_animal(self, animal): if animal == "cat": raise ValueError("A cat would never do that !") super().eaten_by_animal(animal) pylint-4.0.4/doc/data/messages/d/duplicate-except/000077500000000000000000000000001511304262100220015ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-except/bad.py000066400000000000000000000001531511304262100231000ustar00rootroot00000000000000try: 1 / 0 except ZeroDivisionError: pass except ZeroDivisionError: # [duplicate-except] pass pylint-4.0.4/doc/data/messages/d/duplicate-except/good.py000066400000000000000000000000621511304262100233010ustar00rootroot00000000000000try: 1 / 0 except ZeroDivisionError: pass pylint-4.0.4/doc/data/messages/d/duplicate-key/000077500000000000000000000000001511304262100213015ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-key/bad.py000066400000000000000000000001261511304262100224000ustar00rootroot00000000000000test_score = {"Mathematics": 85, "Biology": 90, "Mathematics": 75} # [duplicate-key] pylint-4.0.4/doc/data/messages/d/duplicate-key/good.py000066400000000000000000000000771511304262100226070ustar00rootroot00000000000000test_score = {"Mathematics": 85, "Biology": 90, "History": 75} pylint-4.0.4/doc/data/messages/d/duplicate-key/related.rst000066400000000000000000000002721511304262100234540ustar00rootroot00000000000000- `Python Dictionaries `_ - `Mapping Types — dict `_ pylint-4.0.4/doc/data/messages/d/duplicate-string-formatting-argument/000077500000000000000000000000001511304262100260075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-string-formatting-argument/bad.py000066400000000000000000000007121511304262100271070ustar00rootroot00000000000000# pylint: disable=missing-docstring, consider-using-f-string SEE = "see 👀" SEA = "sea 🌊" # +1: [duplicate-string-formatting-argument,duplicate-string-formatting-argument] CONST = """ A sailor went to {}, {}, {} To {} what he could {}, {}, {} But all that he could {}, {}, {} Was the bottom of the deep blue {}, {}, {}! """.format( SEA, SEA, SEA, SEE, SEE, SEE, SEE, SEE, SEE, SEE, SEA, SEA, SEA, ) pylint-4.0.4/doc/data/messages/d/duplicate-string-formatting-argument/good.py000066400000000000000000000004771511304262100273210ustar00rootroot00000000000000# pylint: disable=missing-docstring, consider-using-f-string SEE = "see 👀" SEA = "sea 🌊" CONST = """ A sailor went to {sea}, {sea}, {sea} To {see} what he could {see}, {see}, {see} But all that he could {see}, {see}, {see} Was the bottom of the deep blue {sea}, {sea}, {sea}! """.format( sea=SEA, see=SEE ) pylint-4.0.4/doc/data/messages/d/duplicate-value/000077500000000000000000000000001511304262100216255ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/d/duplicate-value/bad.py000066400000000000000000000001011511304262100227150ustar00rootroot00000000000000incorrect_set = {"value1", 23, 5, "value1"} # [duplicate-value] pylint-4.0.4/doc/data/messages/d/duplicate-value/good.py000066400000000000000000000000401511304262100231210ustar00rootroot00000000000000correct_set = {"value1", 23, 5} pylint-4.0.4/doc/data/messages/e/000077500000000000000000000000001511304262100165425ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/else-if-used/000077500000000000000000000000001511304262100210245ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/else-if-used/bad.py000066400000000000000000000001541511304262100221240ustar00rootroot00000000000000if input(): pass else: if len(input()) >= 10: # [else-if-used] pass else: pass pylint-4.0.4/doc/data/messages/e/else-if-used/good.py000066400000000000000000000001061511304262100223230ustar00rootroot00000000000000if input(): pass elif len(input()) >= 10: pass else: pass pylint-4.0.4/doc/data/messages/e/else-if-used/pylintrc000066400000000000000000000000611511304262100226100ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.check_elif pylint-4.0.4/doc/data/messages/e/empty-comment/000077500000000000000000000000001511304262100213405ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/empty-comment/bad.py000066400000000000000000000000661511304262100224420ustar00rootroot00000000000000# +1:[empty-comment] # # +1:[empty-comment] x = 0 # pylint-4.0.4/doc/data/messages/e/empty-comment/good.py000066400000000000000000000000341511304262100226370ustar00rootroot00000000000000# comment x = 0 # comment pylint-4.0.4/doc/data/messages/e/empty-comment/pylintrc000066400000000000000000000000641511304262100231270ustar00rootroot00000000000000[main] load-plugins=pylint.extensions.empty_comment pylint-4.0.4/doc/data/messages/e/empty-docstring/000077500000000000000000000000001511304262100216725ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/empty-docstring/bad.py000066400000000000000000000000531511304262100227700ustar00rootroot00000000000000def foo(): # [empty-docstring] """""" pylint-4.0.4/doc/data/messages/e/empty-docstring/good.py000066400000000000000000000000521511304262100231710ustar00rootroot00000000000000def foo(): """A dummy description.""" pylint-4.0.4/doc/data/messages/e/eq-without-hash/000077500000000000000000000000001511304262100215715ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/eq-without-hash/bad.py000066400000000000000000000003201511304262100226640ustar00rootroot00000000000000class Fruit: # [eq-without-hash] def __init__(self) -> None: self.name = "apple" def __eq__(self, other: object) -> bool: return isinstance(other, Fruit) and other.name == self.name pylint-4.0.4/doc/data/messages/e/eq-without-hash/good.py000066400000000000000000000003721511304262100230750ustar00rootroot00000000000000class Fruit: def __init__(self) -> None: self.name = "apple" def __eq__(self, other: object) -> bool: return isinstance(other, Fruit) and other.name == self.name def __hash__(self) -> int: return hash(self.name) pylint-4.0.4/doc/data/messages/e/eq-without-hash/pylintrc000066400000000000000000000000671511304262100233630ustar00rootroot00000000000000[MAIN] load-plugins=pylint.extensions.eq_without_hash, pylint-4.0.4/doc/data/messages/e/eval-used/000077500000000000000000000000001511304262100204275ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/eval-used/bad.py000066400000000000000000000000411511304262100215220ustar00rootroot00000000000000eval("[1, 2, 3]") # [eval-used] pylint-4.0.4/doc/data/messages/e/eval-used/good.py000066400000000000000000000000701511304262100217260ustar00rootroot00000000000000from ast import literal_eval literal_eval("[1, 2, 3]") pylint-4.0.4/doc/data/messages/e/exec-used/000077500000000000000000000000001511304262100204245ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/exec-used/bad.py000066400000000000000000000002561511304262100215270ustar00rootroot00000000000000username = "Ada" code_to_execute = f"""input('Enter code to be executed please, {username}: ')""" program = exec(code_to_execute) # [exec-used] exec(program) # [exec-used] pylint-4.0.4/doc/data/messages/e/exec-used/details.rst000066400000000000000000000032471511304262100226110ustar00rootroot00000000000000The available methods and variables used in ``exec()`` may introduce a security hole. You can restrict the use of these variables and methods by passing optional globals and locals parameters (dictionaries) to the ``exec()`` method. However, use of ``exec()`` is still insecure if you allow some functions like ``__import__`` or ``open``. For example, consider the following call that writes a file to the user's system and then execute code unrestrained by the ``allowed_globals``, or ``allowed_locals`` parameters: .. code-block:: python import textwrap def forbid_print(*args): raise ValueError("This is raised when a print is used") allowed_globals = { "__builtins__": { "__import__": __builtins__.__import__, "open": __builtins__.open, "print": forbid_print, } } exec( textwrap.dedent( """ import textwrap with open("nefarious.py", "w") as f: f.write(textwrap.dedent(''' def connive(): print("Here's some code as nefarious as imaginable") ''')) import nefarious nefarious.connive() # This will NOT raise a ValueError """ ), allowed_globals, ) The import is used only for readability of the example in this case but it could import a dangerous functions: - ``subprocess.run('echo "print(\"Hello, World!\")" > nefarious.py'`` - ``pathlib.Path("nefarious.py").write_file("print(\"Hello, World!\")")`` - ``os.system('echo "print(\"Hello, World!\")" > nefarious.py')`` - ``logging.basicConfig(filename='nefarious.py'); logging.error('print("Hello, World!")')`` - etc. pylint-4.0.4/doc/data/messages/e/exec-used/good.py000066400000000000000000000006451511304262100217330ustar00rootroot00000000000000def get_user_code(name): return input(f"Enter code to be executed please, {name}: ") username = "Ada" # If the globals dictionary does not contain a value for the key __builtins__, # all builtins are allowed. You need to be explicit about it being disallowed. allowed_globals = {"__builtins__": {}} allowed_locals = {} # pylint: disable-next=exec-used exec(get_user_code(username), allowed_globals, allowed_locals) pylint-4.0.4/doc/data/messages/e/exec-used/related.rst000066400000000000000000000002631511304262100225770ustar00rootroot00000000000000- `Be careful with exec and eval in Python `_ - `Python documentation `_ pylint-4.0.4/doc/data/messages/e/expression-not-assigned/000077500000000000000000000000001511304262100233325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/e/expression-not-assigned/bad.py000066400000000000000000000000551511304262100244320ustar00rootroot00000000000000str(42) == "42" # [expression-not-assigned] pylint-4.0.4/doc/data/messages/e/expression-not-assigned/good.py000066400000000000000000000000421511304262100246300ustar00rootroot00000000000000are_equal: bool = str(42) == "42" pylint-4.0.4/doc/data/messages/f/000077500000000000000000000000001511304262100165435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/f-string-without-interpolation/000077500000000000000000000000001511304262100246625ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/f-string-without-interpolation/bad.py000066400000000000000000000001101511304262100257520ustar00rootroot00000000000000x = 1 y = 2 print(f"x + y = x + y") # [f-string-without-interpolation] pylint-4.0.4/doc/data/messages/f/f-string-without-interpolation/good.py000066400000000000000000000000521511304262100261610ustar00rootroot00000000000000x = 1 y = 2 print(f"{x} + {y} = {x + y}") pylint-4.0.4/doc/data/messages/f/fatal/000077500000000000000000000000001511304262100176325ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/fatal/details.rst000066400000000000000000000001431511304262100220070ustar00rootroot00000000000000This is a message linked to an internal problem in pylint. There's nothing to change in your code. pylint-4.0.4/doc/data/messages/f/file-ignored/000077500000000000000000000000001511304262100211075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/file-ignored/bad.py000066400000000000000000000000511511304262100222030ustar00rootroot00000000000000# pylint: skip-file # -1: [file-ignored] pylint-4.0.4/doc/data/messages/f/file-ignored/details.rst000066400000000000000000000001151511304262100232630ustar00rootroot00000000000000There's no checks at all for a file if it starts by ``# pylint: skip-file``. pylint-4.0.4/doc/data/messages/f/file-ignored/good.py000066400000000000000000000000001511304262100223770ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/fixme/000077500000000000000000000000001511304262100176535ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/fixme/bad.py000066400000000000000000000000641511304262100207530ustar00rootroot00000000000000# TODO: We should fix this at some point # [fixme] pylint-4.0.4/doc/data/messages/f/fixme/details.rst000066400000000000000000000003131511304262100220270ustar00rootroot00000000000000You can use regular expressions and the ``notes-rgx`` option to create some constraints for this message. See `the following issue `_ for some examples. pylint-4.0.4/doc/data/messages/f/fixme/good/000077500000000000000000000000001511304262100206035ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/fixme/good/bug_tracker.py000066400000000000000000000001051511304262100234410ustar00rootroot00000000000000# The issue was added to the bug tracker: no longer need the comment pylint-4.0.4/doc/data/messages/f/fixme/good/fixed.py000066400000000000000000000000621511304262100222520ustar00rootroot00000000000000# The issue was fixed: no longer need the comment pylint-4.0.4/doc/data/messages/f/fixme/good/no_fix.py000066400000000000000000000000741511304262100224400ustar00rootroot00000000000000# We no longer want to fix this: no longer need the comment pylint-4.0.4/doc/data/messages/f/forgotten-debug-statement/000077500000000000000000000000001511304262100236405ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/forgotten-debug-statement/bad.py000066400000000000000000000005311511304262100247370ustar00rootroot00000000000000import pdb def find_the_treasure(clues): for clue in clues: pdb.set_trace() # [forgotten-debug-statement] if "treasure" in clue: return True return False treasure_hunt = [ "Dead Man's Chest", "X marks the spot", "The treasure is buried near the palm tree", ] find_the_treasure(treasure_hunt) pylint-4.0.4/doc/data/messages/f/forgotten-debug-statement/good.py000066400000000000000000000004251511304262100251430ustar00rootroot00000000000000def find_the_treasure(clues): for clue in clues: if "treasure" in clue: return True return False treasure_hunt = [ "Dead Man's Chest", "X marks the spot", "The treasure is buried near the palm tree", ] find_the_treasure(treasure_hunt) pylint-4.0.4/doc/data/messages/f/format-combined-specification/000077500000000000000000000000001511304262100244275ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/format-combined-specification/bad.py000066400000000000000000000001141511304262100255230ustar00rootroot00000000000000print("{} {1}".format("hello", "world")) # [format-combined-specification] pylint-4.0.4/doc/data/messages/f/format-combined-specification/good/000077500000000000000000000000001511304262100253575ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/format-combined-specification/good/index_formatting.py000066400000000000000000000000521511304262100312670ustar00rootroot00000000000000print("{0} {1}".format("hello", "world")) pylint-4.0.4/doc/data/messages/f/format-combined-specification/good/order_formatting.py000066400000000000000000000000501511304262100312710ustar00rootroot00000000000000print("{} {}".format("hello", "world")) pylint-4.0.4/doc/data/messages/f/format-needs-mapping/000077500000000000000000000000001511304262100225605ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/format-needs-mapping/bad.py000066400000000000000000000000701511304262100236550ustar00rootroot00000000000000print("%(x)d %(y)d" % [1, 2]) # [format-needs-mapping] pylint-4.0.4/doc/data/messages/f/format-needs-mapping/good.py000066400000000000000000000000501511304262100240550ustar00rootroot00000000000000print("%(x)d %(y)d" % {"x": 1, "y": 2}) pylint-4.0.4/doc/data/messages/f/format-string-without-interpolation/000077500000000000000000000000001511304262100257255ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/format-string-without-interpolation/bad.py000066400000000000000000000001031511304262100270170ustar00rootroot00000000000000print("number".format(1)) # [format-string-without-interpolation] pylint-4.0.4/doc/data/messages/f/format-string-without-interpolation/good.py000066400000000000000000000000361511304262100272260ustar00rootroot00000000000000print("number: {}".format(1)) pylint-4.0.4/doc/data/messages/f/function-redefined/000077500000000000000000000000001511304262100223135ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/f/function-redefined/bad.py000066400000000000000000000001161511304262100234110ustar00rootroot00000000000000def get_email(): pass def get_email(): # [function-redefined] pass pylint-4.0.4/doc/data/messages/f/function-redefined/good.py000066400000000000000000000000321511304262100236100ustar00rootroot00000000000000def get_email(): pass pylint-4.0.4/doc/data/messages/g/000077500000000000000000000000001511304262100165445ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/g/global-at-module-level/000077500000000000000000000000001511304262100227765ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/g/global-at-module-level/bad.py000066400000000000000000000000641511304262100240760ustar00rootroot00000000000000price = 25 global price # [global-at-module-level] pylint-4.0.4/doc/data/messages/g/global-at-module-level/good.py000066400000000000000000000000131511304262100242720ustar00rootroot00000000000000price = 25 pylint-4.0.4/doc/data/messages/g/global-at-module-level/related.rst000066400000000000000000000005111511304262100251450ustar00rootroot00000000000000- `Official Python FAQ - global and local `_ - `PEP 3104 - Access to Names in Outer Scopes `_ - `Python global statement `_ pylint-4.0.4/doc/data/messages/g/global-statement/000077500000000000000000000000001511304262100220065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/g/global-statement/bad.py000066400000000000000000000001511511304262100231030ustar00rootroot00000000000000var = 1 def foo(): global var # [global-statement] var = 10 print(var) foo() print(var) pylint-4.0.4/doc/data/messages/g/global-statement/good.py000066400000000000000000000001131511304262100233030ustar00rootroot00000000000000var = 1 def foo(): print(var) return 10 var = foo() print(var) pylint-4.0.4/doc/data/messages/g/global-variable-not-assigned/000077500000000000000000000000001511304262100241605ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/g/global-variable-not-assigned/bad.py000066400000000000000000000001651511304262100252620ustar00rootroot00000000000000TOMATO = "black cherry" def update_tomato(): global TOMATO # [global-variable-not-assigned] print(TOMATO) pylint-4.0.4/doc/data/messages/g/global-variable-not-assigned/good.py000066400000000000000000000001331511304262100254570ustar00rootroot00000000000000TOMATO = "black cherry" def update_tomato(): global TOMATO TOMATO = "moneymaker" pylint-4.0.4/doc/data/messages/g/global-variable-undefined/000077500000000000000000000000001511304262100235265ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/g/global-variable-undefined/bad.py000066400000000000000000000001401511304262100246210ustar00rootroot00000000000000def update_tomato(): global TOMATO # [global-variable-undefined] TOMATO = "moneymaker" pylint-4.0.4/doc/data/messages/g/global-variable-undefined/good.py000066400000000000000000000001331511304262100250250ustar00rootroot00000000000000TOMATO = "black cherry" def update_tomato(): global TOMATO TOMATO = "moneymaker" pylint-4.0.4/doc/data/messages/i/000077500000000000000000000000001511304262100165465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/implicit-flag-alias/000077500000000000000000000000001511304262100223565ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/implicit-flag-alias/bad.py000066400000000000000000000001771511304262100234630ustar00rootroot00000000000000from enum import IntFlag class FilePermissions(IntFlag): READ = 1 WRITE = 2 EXECUTE = 3 # [implicit-flag-alias] pylint-4.0.4/doc/data/messages/i/implicit-flag-alias/good.py000066400000000000000000000001461511304262100236610ustar00rootroot00000000000000from enum import IntFlag class FilePermissions(IntFlag): READ = 1 WRITE = 2 EXECUTE = 4 pylint-4.0.4/doc/data/messages/i/implicit-str-concat/000077500000000000000000000000001511304262100224335ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/implicit-str-concat/bad/000077500000000000000000000000001511304262100231615ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/implicit-str-concat/bad/list.py000066400000000000000000000000471511304262100245070ustar00rootroot00000000000000x = ["a" "b"] # [implicit-str-concat] pylint-4.0.4/doc/data/messages/i/implicit-str-concat/bad/open.py000066400000000000000000000001161511304262100244720ustar00rootroot00000000000000with open("hello.txt" "r") as f: # [implicit-str-concat] print(f.read()) pylint-4.0.4/doc/data/messages/i/implicit-str-concat/details.rst000066400000000000000000000021141511304262100246100ustar00rootroot00000000000000By default, detection of implicit string concatenation of line jumps is disabled. Hence the following code will not trigger this rule: .. code-block:: python SEQ = ('a', 'b' 'c') In order to detect this case, you must enable `check-str-concat-over-line-jumps`: .. code-block:: toml [STRING_CONSTANT] check-str-concat-over-line-jumps = true However, the drawback of this setting is that it will trigger false positive for string parameters passed on multiple lines in function calls: .. code-block:: python warnings.warn( "rotate() is deprecated and will be removed in a future release. " "Use the rotation() context manager instead.", DeprecationWarning, stacklevel=3, ) No message will be emitted, though, if you clarify the wanted concatenation with parentheses: .. code-block:: python warnings.warn( ( "rotate() is deprecated and will be removed in a future release. " "Use the rotation() context manager instead." ), DeprecationWarning, stacklevel=3, ) pylint-4.0.4/doc/data/messages/i/implicit-str-concat/good/000077500000000000000000000000001511304262100233635ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/implicit-str-concat/good/list.py000066400000000000000000000000171511304262100247060ustar00rootroot00000000000000x = ["a", "b"] pylint-4.0.4/doc/data/messages/i/implicit-str-concat/good/open.py000066400000000000000000000000661511304262100247000ustar00rootroot00000000000000with open("hello.txt", "r") as f: print(f.read()) pylint-4.0.4/doc/data/messages/i/import-error/000077500000000000000000000000001511304262100212075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/import-error/bad.py000066400000000000000000000000521511304262100223040ustar00rootroot00000000000000from patlib import Path # [import-error] pylint-4.0.4/doc/data/messages/i/import-error/details.rst000066400000000000000000000003001511304262100233570ustar00rootroot00000000000000This can happen if you're importing a package that is not installed in your environment, or if you made a typo. The solution is to install the package via pip/setup.py/wheel or fix the typo. pylint-4.0.4/doc/data/messages/i/import-error/good.py000066400000000000000000000000311511304262100225030ustar00rootroot00000000000000from pathlib import Path pylint-4.0.4/doc/data/messages/i/import-outside-toplevel/000077500000000000000000000000001511304262100233625ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/import-outside-toplevel/bad.py000066400000000000000000000001451511304262100244620ustar00rootroot00000000000000def print_python_version(): import sys # [import-outside-toplevel] print(sys.version_info) pylint-4.0.4/doc/data/messages/i/import-outside-toplevel/good.py000066400000000000000000000001051511304262100246600ustar00rootroot00000000000000import sys def print_python_version(): print(sys.version_info) pylint-4.0.4/doc/data/messages/i/import-private-name/000077500000000000000000000000001511304262100224465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/import-private-name/bad.py000066400000000000000000000003371511304262100235510ustar00rootroot00000000000000from argparse import _AttributeHolder, _SubParsersAction # [import-private-name] attr_holder = _AttributeHolder() def add_sub_parser(sub_parsers: _SubParsersAction): sub_parsers.add_parser("my_subparser") # ... pylint-4.0.4/doc/data/messages/i/import-private-name/details.rst000066400000000000000000000002031511304262100246200ustar00rootroot00000000000000Using private imports expose you to unexpected breaking changes for any version bump of your dependencies, even in patch versions. pylint-4.0.4/doc/data/messages/i/import-private-name/good.py000066400000000000000000000003111511304262100237430ustar00rootroot00000000000000"""Private import can be used as type annotations.""" from argparse import _SubParsersAction def add_sub_parser(sub_parsers: _SubParsersAction): sub_parsers.add_parser("my_subparser") # ... pylint-4.0.4/doc/data/messages/i/import-private-name/pylintrc000066400000000000000000000000671511304262100242400ustar00rootroot00000000000000[main] load-plugins = pylint.extensions.private_import pylint-4.0.4/doc/data/messages/i/import-self/000077500000000000000000000000001511304262100210075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/import-self/details.rst000066400000000000000000000004171511304262100231700ustar00rootroot00000000000000Say you have a file called ``my_file.py``. ``import-self`` would be raised on the following code:: from my_file import a_function # [import-self] def a_function(): pass The solution would be to remove the import:: def a_function(): pass pylint-4.0.4/doc/data/messages/i/inconsistent-mro/000077500000000000000000000000001511304262100220615ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/inconsistent-mro/bad.py000066400000000000000000000001311511304262100231540ustar00rootroot00000000000000class A: pass class B(A): pass class C(A, B): # [inconsistent-mro] pass pylint-4.0.4/doc/data/messages/i/inconsistent-mro/good.py000066400000000000000000000001431511304262100233610ustar00rootroot00000000000000class A: pass class B(A): pass class C(B): # or 'B, A' or 'A' but not 'A, B' pass pylint-4.0.4/doc/data/messages/i/inconsistent-quotes/000077500000000000000000000000001511304262100226045ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/inconsistent-quotes/bad.py000066400000000000000000000001471511304262100237060ustar00rootroot00000000000000import datetime print('Current year: ', datetime.date.today().strftime("%Y")) # [inconsistent-quotes] pylint-4.0.4/doc/data/messages/i/inconsistent-quotes/good.py000066400000000000000000000001171511304262100241050ustar00rootroot00000000000000import datetime print("Current year: ", datetime.date.today().strftime("%Y")) pylint-4.0.4/doc/data/messages/i/inconsistent-quotes/pylintrc000066400000000000000000000000431511304262100243700ustar00rootroot00000000000000[main] check-quote-consistency=yes pylint-4.0.4/doc/data/messages/i/inconsistent-return-statements/000077500000000000000000000000001511304262100247705ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/inconsistent-return-statements/bad.py000066400000000000000000000001651511304262100260720ustar00rootroot00000000000000def get_the_answer(value: str) -> str | None: # [inconsistent-return-statements] if value: return value pylint-4.0.4/doc/data/messages/i/inconsistent-return-statements/good.py000066400000000000000000000001411511304262100262660ustar00rootroot00000000000000def get_the_answer(value: str) -> str | None: if value: return value return None pylint-4.0.4/doc/data/messages/i/inherit-non-class/000077500000000000000000000000001511304262100221035ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/inherit-non-class/bad.py000066400000000000000000000000631511304262100232020ustar00rootroot00000000000000class Fruit(bool): # [inherit-non-class] pass pylint-4.0.4/doc/data/messages/i/inherit-non-class/good.py000066400000000000000000000000621511304262100234030ustar00rootroot00000000000000class Fruit: def __bool__(self): pass pylint-4.0.4/doc/data/messages/i/init-is-generator/000077500000000000000000000000001511304262100221065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/init-is-generator/bad.py000066400000000000000000000002141511304262100232030ustar00rootroot00000000000000class Fruit: def __init__(self, worms): # [init-is-generator] yield from worms apple = Fruit(["Fahad", "Anisha", "Tabatha"]) pylint-4.0.4/doc/data/messages/i/init-is-generator/good.py000066400000000000000000000003231511304262100234060ustar00rootroot00000000000000class Fruit: def __init__(self, worms): self.__worms = worms def worms(self): yield from self.__worms apple = Fruit(["Fahad", "Anisha", "Tabatha"]) for worm in apple.worms(): pass pylint-4.0.4/doc/data/messages/i/invalid-all-format/000077500000000000000000000000001511304262100222305ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-all-format/bad.py000066400000000000000000000000661511304262100233320ustar00rootroot00000000000000__all__ = "CONST" # [invalid-all-format] CONST = 42 pylint-4.0.4/doc/data/messages/i/invalid-all-format/good.py000066400000000000000000000000411511304262100235250ustar00rootroot00000000000000__all__ = ("CONST",) CONST = 42 pylint-4.0.4/doc/data/messages/i/invalid-all-object/000077500000000000000000000000001511304262100222065ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-all-object/bad.py000066400000000000000000000001641511304262100233070ustar00rootroot00000000000000__all__ = ( None, # [invalid-all-object] Fruit, Worm, ) class Fruit: pass class Worm: pass pylint-4.0.4/doc/data/messages/i/invalid-all-object/details.rst000066400000000000000000000005571511304262100243740ustar00rootroot00000000000000From `The Python Language Reference – The import statement `_: "The `public names` defined by a module are determined by checking the module's namespace for a variable named ``__all__``; if defined, it must be a sequence of strings which are names defined or imported by that module." pylint-4.0.4/doc/data/messages/i/invalid-all-object/good.py000066400000000000000000000001131511304262100235030ustar00rootroot00000000000000__all__ = ["Fruit", "Worm"] class Fruit: pass class Worm: pass pylint-4.0.4/doc/data/messages/i/invalid-all-object/related.rst000066400000000000000000000001511511304262100243550ustar00rootroot00000000000000- `PEP 8 – Style Guide for Python Code `_ pylint-4.0.4/doc/data/messages/i/invalid-bool-returned/000077500000000000000000000000001511304262100227535ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-bool-returned/bad.py000066400000000000000000000001711511304262100240520ustar00rootroot00000000000000class CustomBool: """__bool__ returns an int""" def __bool__(self): # [invalid-bool-returned] return 1 pylint-4.0.4/doc/data/messages/i/invalid-bool-returned/good.py000066400000000000000000000001411511304262100242510ustar00rootroot00000000000000class CustomBool: """__bool__ returns `bool`""" def __bool__(self): return True pylint-4.0.4/doc/data/messages/i/invalid-bytes-returned/000077500000000000000000000000001511304262100231465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-bytes-returned/bad.py000066400000000000000000000002071511304262100242450ustar00rootroot00000000000000class CustomBytes: """__bytes__ returns """ def __bytes__(self): # [invalid-bytes-returned] return "123" pylint-4.0.4/doc/data/messages/i/invalid-bytes-returned/good.py000066400000000000000000000001651511304262100244520ustar00rootroot00000000000000class CustomBytes: """__bytes__ returns """ def __bytes__(self): return b"some bytes" pylint-4.0.4/doc/data/messages/i/invalid-character-backspace/000077500000000000000000000000001511304262100240405ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-backspace/bad.py000066400000000000000000000001121511304262100251320ustar00rootroot00000000000000STRING = "Invalid character backspace " # [invalid-character-backspace] pylint-4.0.4/doc/data/messages/i/invalid-character-backspace/good.py000066400000000000000000000000501511304262100253350ustar00rootroot00000000000000STRING = "Valid character backspace \b" pylint-4.0.4/doc/data/messages/i/invalid-character-carriage-return/000077500000000000000000000000001511304262100252165ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-carriage-return/details.rst000066400000000000000000000005151511304262100273760ustar00rootroot00000000000000This message exists because one of our checkers is very generic, but it's never going to raise during normal use as it's a ``syntax-error`` that would prevent the python ast (and thus pylint) from constructing a code representation of the file. You could encounter it by feeding a properly constructed node directly to the checker. pylint-4.0.4/doc/data/messages/i/invalid-character-carriage-return/good.py000066400000000000000000000000451511304262100265170ustar00rootroot00000000000000STRING = "Valid carriage return: \r" pylint-4.0.4/doc/data/messages/i/invalid-character-esc/000077500000000000000000000000001511304262100226765ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-esc/bad.py000066400000000000000000000001011511304262100237660ustar00rootroot00000000000000STRING = "Invalid escape character " # [invalid-character-esc] pylint-4.0.4/doc/data/messages/i/invalid-character-esc/good.py000066400000000000000000000000471511304262100242010ustar00rootroot00000000000000STRING = "Valid escape character \x1b" pylint-4.0.4/doc/data/messages/i/invalid-character-nul/000077500000000000000000000000001511304262100227225ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-nul/details.rst000066400000000000000000000001331511304262100250760ustar00rootroot00000000000000There's no need to use end-of-string characters. String objects maintain their own length. pylint-4.0.4/doc/data/messages/i/invalid-character-nul/good.py000066400000000000000000000000461511304262100242240ustar00rootroot00000000000000STRING = "Valid nul terminator: \x00" pylint-4.0.4/doc/data/messages/i/invalid-character-nul/related.rst000066400000000000000000000001171511304262100250730ustar00rootroot00000000000000- `Null terminator in python `_ pylint-4.0.4/doc/data/messages/i/invalid-character-sub/000077500000000000000000000000001511304262100227155ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-sub/bad.py000066400000000000000000000000761511304262100240200ustar00rootroot00000000000000STRING = "Invalid character sub " # [invalid-character-sub] pylint-4.0.4/doc/data/messages/i/invalid-character-sub/good.py000066400000000000000000000000431511304262100242140ustar00rootroot00000000000000STRING = "Valid character sub x1A" pylint-4.0.4/doc/data/messages/i/invalid-character-zero-width-space/000077500000000000000000000000001511304262100253115ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-character-zero-width-space/bad.py000066400000000000000000000001321511304262100264050ustar00rootroot00000000000000STRING = "Invalid character zero-width-space ​" # [invalid-character-zero-width-space] pylint-4.0.4/doc/data/messages/i/invalid-character-zero-width-space/good.py000066400000000000000000000000621511304262100266110ustar00rootroot00000000000000STRING = "Valid character zero-width-space u200B" pylint-4.0.4/doc/data/messages/i/invalid-characters-in-docstring/000077500000000000000000000000001511304262100247075ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-characters-in-docstring/details.rst000066400000000000000000000002771511304262100270740ustar00rootroot00000000000000This is a message linked to an internal problem in enchant. There's nothing to change in your code, but maybe in pylint's configuration or the way you installed the 'enchant' system library. pylint-4.0.4/doc/data/messages/i/invalid-class-object/000077500000000000000000000000001511304262100225435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-class-object/bad.py000066400000000000000000000001061511304262100236400ustar00rootroot00000000000000class Apple: pass Apple.__class__ = 1 # [invalid-class-object] pylint-4.0.4/doc/data/messages/i/invalid-class-object/good.py000066400000000000000000000001261511304262100240440ustar00rootroot00000000000000class Apple: pass class RedDelicious: pass Apple.__class__ = RedDelicious pylint-4.0.4/doc/data/messages/i/invalid-enum-extension/000077500000000000000000000000001511304262100231505ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-enum-extension/bad.py000066400000000000000000000002111511304262100242420ustar00rootroot00000000000000from enum import Enum class Color(Enum): ORANGE = 1 CHERRY = 2 class Fruit(Color): # [invalid-enum-extension] APPLE = 3 pylint-4.0.4/doc/data/messages/i/invalid-enum-extension/good.py000066400000000000000000000002121511304262100244450ustar00rootroot00000000000000from enum import Enum class Color(Enum): ORANGE = 1 CHERRY = 2 class Fruit(Enum): ORANGE = 1 CHERRY = 2 APPLE = 3 pylint-4.0.4/doc/data/messages/i/invalid-envvar-default/000077500000000000000000000000001511304262100231155ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-envvar-default/bad.py000066400000000000000000000001101511304262100242050ustar00rootroot00000000000000import os env = os.getenv("SECRET_KEY", 1) # [invalid-envvar-default] pylint-4.0.4/doc/data/messages/i/invalid-envvar-default/good.py000066400000000000000000000000561511304262100244200ustar00rootroot00000000000000import os env = os.getenv("SECRET_KEY", "1") pylint-4.0.4/doc/data/messages/i/invalid-envvar-value/000077500000000000000000000000001511304262100226055ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-envvar-value/bad.py000066400000000000000000000000621511304262100237030ustar00rootroot00000000000000import os os.getenv(1) # [invalid-envvar-value] pylint-4.0.4/doc/data/messages/i/invalid-envvar-value/good.py000066400000000000000000000000321511304262100241020ustar00rootroot00000000000000import os os.getenv("1") pylint-4.0.4/doc/data/messages/i/invalid-field-call/000077500000000000000000000000001511304262100221665ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-field-call/bad.py000066400000000000000000000004071511304262100232670ustar00rootroot00000000000000from dataclasses import dataclass, field @dataclass class C: a: float b: float c: float field(init=False) # [invalid-field-call] def __post_init__(self): self.c = self.a + self.b print(field(init=False)) # [invalid-field-call] pylint-4.0.4/doc/data/messages/i/invalid-field-call/good.py000066400000000000000000000005221511304262100234670ustar00rootroot00000000000000from dataclasses import dataclass, field, make_dataclass C = make_dataclass( "C", [("x", int), "y", ("z", int, field(default=5))], namespace={"add_one": lambda self: self.x + 1}, ) @dataclass class C: a: float b: float c: float = field(init=False) def __post_init__(self): self.c = self.a + self.b pylint-4.0.4/doc/data/messages/i/invalid-format-index/000077500000000000000000000000001511304262100225675ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-format-index/bad.py000066400000000000000000000002041511304262100236630ustar00rootroot00000000000000not_enough_fruits = ["apple"] print('The second fruit is a {fruits[1]}'.format(fruits=not_enough_fruits)) # [invalid-format-index] pylint-4.0.4/doc/data/messages/i/invalid-format-index/good.py000066400000000000000000000001541511304262100240710ustar00rootroot00000000000000enough_fruits = ["apple", "banana"] print("The second fruit is a {fruits[1]}".format(fruits=enough_fruits)) pylint-4.0.4/doc/data/messages/i/invalid-format-returned/000077500000000000000000000000001511304262100233105ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-format-returned/bad.py000066400000000000000000000002241511304262100244060ustar00rootroot00000000000000class CustomFormat: """__format__ returns """ def __format__(self, format_spec): # [invalid-format-returned] return 1 pylint-4.0.4/doc/data/messages/i/invalid-format-returned/good.py000066400000000000000000000001761511304262100246160ustar00rootroot00000000000000class CustomFormat: """__format__ returns """ def __format__(self, format_spec): return "hello!" pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-ex-returned/000077500000000000000000000000001511304262100246005ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-ex-returned/bad.py000066400000000000000000000003161511304262100257000ustar00rootroot00000000000000class CustomGetNewArgsEx: """__getnewargs_ex__ returns tuple with incorrect arg length""" def __getnewargs_ex__(self): # [invalid-getnewargs-ex-returned] return (tuple(1), dict(x="y"), 1) pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-ex-returned/good.py000066400000000000000000000002171511304262100261020ustar00rootroot00000000000000class CustomGetNewArgsEx: """__getnewargs_ex__ returns """ def __getnewargs_ex__(self): return ((1,), {"2": 2}) pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-returned/000077500000000000000000000000001511304262100241665ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-returned/bad.py000066400000000000000000000002251511304262100252650ustar00rootroot00000000000000class CustomGetNewArgs: """__getnewargs__ returns an integer""" def __getnewargs__(self): # [invalid-getnewargs-returned] return 1 pylint-4.0.4/doc/data/messages/i/invalid-getnewargs-returned/good.py000066400000000000000000000001751511304262100254730ustar00rootroot00000000000000class CustomGetNewArgs: """__getnewargs__ returns """ def __getnewargs__(self): return (1, 2) pylint-4.0.4/doc/data/messages/i/invalid-hash-returned/000077500000000000000000000000001511304262100227435ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-hash-returned/bad.py000066400000000000000000000001701511304262100240410ustar00rootroot00000000000000class CustomHash: """__hash__ returns dict""" def __hash__(self): # [invalid-hash-returned] return {} pylint-4.0.4/doc/data/messages/i/invalid-hash-returned/good.py000066400000000000000000000001361511304262100242450ustar00rootroot00000000000000class CustomHash: """__hash__ returns `int`""" def __hash__(self): return 19 pylint-4.0.4/doc/data/messages/i/invalid-index-returned/000077500000000000000000000000001511304262100231275ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-index-returned/bad.py000066400000000000000000000002101511304262100242200ustar00rootroot00000000000000class CustomIndex: """__index__ returns a dict""" def __index__(self): # [invalid-index-returned] return {"19": "19"} pylint-4.0.4/doc/data/messages/i/invalid-index-returned/good.py000066400000000000000000000001501511304262100244250ustar00rootroot00000000000000class CustomIndex: """__index__ returns """ def __index__(self): return 19 pylint-4.0.4/doc/data/messages/i/invalid-length-hint-returned/000077500000000000000000000000001511304262100242415ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-length-hint-returned/bad.py000066400000000000000000000002271511304262100253420ustar00rootroot00000000000000class CustomLengthHint: """__length_hint__ returns non-int""" def __length_hint__(self): # [invalid-length-hint-returned] return 3.0 pylint-4.0.4/doc/data/messages/i/invalid-length-hint-returned/good.py000066400000000000000000000001711511304262100255420ustar00rootroot00000000000000class CustomLengthHint: """__length_hint__ returns """ def __length_hint__(self): return 10 pylint-4.0.4/doc/data/messages/i/invalid-length-returned/000077500000000000000000000000001511304262100233015ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-length-returned/bad.py000066400000000000000000000002751511304262100244050ustar00rootroot00000000000000class FruitBasket: def __init__(self, fruits): self.fruits = ["Apple", "Banana", "Orange"] def __len__(self): # [invalid-length-returned] return -len(self.fruits) pylint-4.0.4/doc/data/messages/i/invalid-length-returned/good.py000066400000000000000000000002371511304262100246050ustar00rootroot00000000000000class FruitBasket: def __init__(self, fruits): self.fruits = ["Apple", "Banana", "Orange"] def __len__(self): return len(self.fruits) pylint-4.0.4/doc/data/messages/i/invalid-match-args-definition/000077500000000000000000000000001511304262100243465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-match-args-definition/bad.py000066400000000000000000000002601511304262100254440ustar00rootroot00000000000000class Book: __match_args__ = ["title", "year"] # [invalid-match-args-definition] def __init__(self, title, year): self.title = title self.year = year pylint-4.0.4/doc/data/messages/i/invalid-match-args-definition/good.py000066400000000000000000000002151511304262100256460ustar00rootroot00000000000000class Book: __match_args__ = ("title", "year") def __init__(self, title, year): self.title = title self.year = year pylint-4.0.4/doc/data/messages/i/invalid-match-args-definition/related.rst000066400000000000000000000002121511304262100265130ustar00rootroot00000000000000- `Python documentation `_ pylint-4.0.4/doc/data/messages/i/invalid-metaclass/000077500000000000000000000000001511304262100221465ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-metaclass/bad.py000066400000000000000000000000741511304262100232470ustar00rootroot00000000000000class Apple(metaclass=int): # [invalid-metaclass] pass pylint-4.0.4/doc/data/messages/i/invalid-metaclass/good.py000066400000000000000000000000651511304262100234510ustar00rootroot00000000000000class Plant: pass class Apple(Plant): pass pylint-4.0.4/doc/data/messages/i/invalid-name/000077500000000000000000000000001511304262100211125ustar00rootroot00000000000000pylint-4.0.4/doc/data/messages/i/invalid-name/bad.py000066400000000000000000000003171511304262100222130ustar00rootroot00000000000000class cat: # [invalid-name] def Meow(self, NUMBER_OF_MEOW): # [invalid-name, invalid-name] print("Meow" * NUMBER_OF_MEOW) return NUMBER_OF_MEOW Cat = cat().Meow(42) # [invalid-name] pylint-4.0.4/doc/data/messages/i/invalid-name/details.rst000066400000000000000000000271771511304262100233070ustar00rootroot00000000000000Pylint recognizes a number of different name types internally. With a few exceptions, the type of the name is governed by the location the assignment to a name is found in, and not the type of object assigned. +--------------------+-------------------------------------------------------------------------------------------------------------+ | Name Type | Description | +====================+=============================================================================================================+ | ``module`` | Module and package names, same as the file names. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``const`` | Module-level constants: any name defined at module level that is not bound to a class object nor reassigned.| +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``class`` | Names in ``class`` statements, as well as names bound to class objects at module level. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``function`` | Functions, toplevel or nested in functions or methods. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``method`` | Methods, functions defined in class bodies. Includes static and class methods. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``attr`` | Attributes created on class instances inside methods. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``argument`` | Arguments to any function type, including lambdas. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``variable`` | Local variables in function scopes or module-level names that are assigned multiple times. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``class-attribute``| Attributes defined in class bodies. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``class-const`` | Enum constants and class variables annotated with ``Final`` | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``inlinevar`` | Loop variables in list comprehensions and generator expressions. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``typevar`` | Type variable declared with ``TypeVar``. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``paramspec`` | Parameter specification variable declared with ``ParamSpec``. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``typevartuple`` | Type variable tuple declared with ``TypeVarTuple``. | +--------------------+-------------------------------------------------------------------------------------------------------------+ | ``typealias`` | Type alias declared with ``TypeAlias`` or assignments of ``Union``. | +--------------------+-------------------------------------------------------------------------------------------------------------+ Default behavior ~~~~~~~~~~~~~~~~ By default, Pylint will enforce PEP8_-suggested names. Predefined Naming Styles ~~~~~~~~~~~~~~~~~~~~~~~~ Pylint provides set of predefined naming styles. Those predefined naming styles may be used to adjust Pylint configuration to coding style used in linted project. Following predefined naming styles are available: * ``snake_case`` * ``camelCase`` * ``PascalCase`` * ``UPPER_CASE`` * ``any`` - fake style which does not enforce any limitations The following options are exposed: .. option:: --module-naming-style=