diff --git a/.copyrite_aliases b/.copyrite_aliases deleted file mode 100644 index 2d3fb159e0..0000000000 --- a/.copyrite_aliases +++ /dev/null @@ -1,68 +0,0 @@ -[ - { - "mails": [ - "cpopa@cloudbasesolutions.com", - "pcmanticore@gmail.com" - ], - "authoritative_mail": "pcmanticore@gmail.com", - "name": "Claudiu Popa" - }, - { - "mails": [ - "alexandre.fayolle@logilab.fr", - "emile.anclin@logilab.fr", - "david.douard@logilab.fr", - "laura.medioni@logilab.fr", - "anthony.truchet@logilab.fr", - "alain.leufroy@logilab.fr", - "julien.cristau@logilab.fr", - "Adrien.DiMascio@logilab.fr", - "emile@crater.logilab.fr", - "sylvain.thenault@logilab.fr", - "pierre-yves.david@logilab.fr", - "nicolas.chauvat@logilab.fr", - "afayolle.ml@free.fr", - "aurelien.campeas@logilab.fr", - "lmedioni@logilab.fr" - - ], - "authoritative_mail": "contact@logilab.fr", - "name": "LOGILAB S.A. (Paris, FRANCE)" - }, - { - "mails": [ - "moylop260@vauxoo.com" - ], - "name": "Moises Lopez", - "authoritative_mail": "moylop260@vauxoo.com" - }, - { - "mails": [ - "nathaniel@google.com", - "mbp@google.com", - "tmarek@google.com", - "shlomme@gmail.com", - "balparda@google.com", - "dlindquist@google.com" - ], - "name": "Google, Inc." - }, - { - "mails": [ - "ashley@awhetter.co.uk", - "awhetter.2011@my.bristol.ac.uk", - "asw@dneg.com", - "AWhetter@users.noreply.github.com" - ], - "name": "Ashley Whetter", - "authoritative_mail": "ashley@awhetter.co.uk" - }, - { - "mails": [ - "ville.skytta@iki.fi", - "ville.skytta@upcloud.com" - ], - "authoritative_mail": "ville.skytta@iki.fi", - "name": "Ville Skyttรค" - } -] diff --git a/.coveragerc b/.coveragerc index 9e18d8489c..22bacd09f6 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,3 +7,16 @@ include = pylint/* omit = */test/* +exclude_lines = + # Re-enable default pragma + pragma: no cover + + # 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() diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 0000000000..39979df636 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1 @@ +3f2842400795ae1aaffc4ae6c35c4ef26857c239 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..5e9c93734f --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +* text=auto +tests/**/functional/** -text +tests/input/** -text +tests/**/data/** -text +tests/regrtest_data/** -text +doc/data/messages/u/unexpected-line-ending-format/bad.py -text +doc/data/messages/m/mixed-line-endings/bad.py -text diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000000..5083128913 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,35 @@ +# Lines starting with '#' are comments. +# Each line is a file pattern followed by one or more owners. + +# These owners will be the default owners for everything in the repo. +# Right now there is not default owner to avoid spam +# * @pierre-sassoulas @DanielNoord @cdce8p @jacobtylerwalls @hippo91 + +# Order is important. The last matching pattern has the most precedence. + +### Core components + +# internal message handling +pylint/message/* @pierre-sassoulas +tests/message/* @pierre-sassoulas + +# typing +pylint/typing.py @DanielNoord + +# multiprocessing (doublethefish is not yet a contributor with write access) +# pylint/lint/parallel.py @doublethefish +# tests/test_check_parallel.py @doublethefish + +### Pyreverse +pylint/pyreverse/* @DudeNr33 +tests/pyreverse/* @DudeNr33 + +### Extensions + +# CodeStyle +pylint/extensions/code_style.* @cdce8p +tests/functional/ext/code_style/* @cdce8p + +# Typing +pylint/extensions/typing.* @cdce8p +tests/functional/ext/typing/* @cdce8p diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index e3a9ff4245..61adbec74f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -1 +1,2 @@ -Please read the [contribute doc](https://github.com/PyCQA/pylint/blob/master/doc/development_guide/contribute.rst). +Please read the +[contribute doc](https://pylint.readthedocs.io/en/latest/development_guide/contributor_guide/contribute.html). diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000000..8b88c8fcd5 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,17 @@ +# These are supported funding model platforms + +tidelift: "pypi/pylint" +github: + [ + PCManticore, + Pierre-Sassoulas, + cdce8p, + hippo91, + AWhetter, + DanielNoord, + areveny, + DudeNr33, + jacobtylerwalls, + matusvalo, + yushao2, + ] diff --git a/.github/ISSUE_TEMPLATE/1_Bug_report.md b/.github/ISSUE_TEMPLATE/1_Bug_report.md deleted file mode 100644 index 3a7017df0f..0000000000 --- a/.github/ISSUE_TEMPLATE/1_Bug_report.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: Bug report -about: Report a bug in pylint - ---- - - - -### Steps to reproduce -1. -2. -3. - -### Current behavior - - -### Expected behavior - - -### pylint --version output - diff --git a/.github/ISSUE_TEMPLATE/2_Feature_request.md b/.github/ISSUE_TEMPLATE/2_Feature_request.md deleted file mode 100644 index daa030f77a..0000000000 --- a/.github/ISSUE_TEMPLATE/2_Feature_request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- - - - -### Is your feature request related to a problem? Please describe -A clear and concise description of what the problem is. - -### Describe the solution you'd like -A clear and concise description of what you want to happen. - - -### Additional context -Add any other context about the feature request here. \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/3_Question.md b/.github/ISSUE_TEMPLATE/3_Question.md deleted file mode 100644 index 8af6e512d8..0000000000 --- a/.github/ISSUE_TEMPLATE/3_Question.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: Support question -about: Questions about pylint that are not covered in the documentation (http://pylint.pycqa.org/en/latest/) - ---- - -## Question diff --git a/.github/ISSUE_TEMPLATE/BUG-REPORT.yml b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml new file mode 100644 index 0000000000..664f6f1d2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG-REPORT.yml @@ -0,0 +1,108 @@ +name: ๐Ÿ› Bug report +description: Report a bug in pylint +labels: ["Needs triage :inbox_tray:"] +body: + - type: markdown + attributes: + value: | + **Thank you for wanting to report a bug in pylint!** + + โš  Please make sure that this [issue wasn't already requested][issue search], or already implemented in the main branch. + + + [issue search]: https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+ + + - type: textarea + id: what-happened + attributes: + label: Bug description + description: + What is the bug about? Please provide the code that is causing the issue, and + configurations used if required + placeholder: | + # Please disable message unrelated to the bug + # pylint: disable=missing-docstring, + = 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 diff --git a/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml new file mode 100644 index 0000000000..b537e69f0f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml @@ -0,0 +1,45 @@ +name: โœจ Feature request +description: Suggest an idea for pylint +labels: ["Needs triage :inbox_tray:"] +body: + - type: markdown + attributes: + value: | + **Thank you for wanting to make a suggestion for pylint!** + + โš  Please make sure that [this feature wasn't already requested][issue search] or already implemented in the main branch. + + + [issue search]: https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+ + + - type: textarea + id: current-problem + attributes: + label: Current problem + description: + What are you trying to do, that you are unable to achieve with pylint as it + currently stands? + placeholder: >- + I'm trying to do X and I'm missing feature Y for this to be easily achievable. + validations: + required: true + - type: textarea + id: proposed-solution + attributes: + label: Desired solution + description: A clear and concise description of what you want to happen. + placeholder: >- + When I do X, I want to achieve Y in a situation when Z. + validations: + required: true + - type: textarea + attributes: + label: Additional context + description: > + Add any other context, links, etc. about the feature here. Describe how the + feature would be used, why it is needed and what it would solve. + + **HINT:** You can paste https://gist.github.com links for larger files. + placeholder: >- + I asked on https://stackoverflow.com/... and the community advised me to do X, Y + and Z. diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yml b/.github/ISSUE_TEMPLATE/QUESTION.yml new file mode 100644 index 0000000000..ed26c9ffb5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/QUESTION.yml @@ -0,0 +1,49 @@ +name: ๐Ÿค” Support question +description: Questions about pylint that are not covered in the documentation +labels: ["Needs triage :inbox_tray:", "Question", "Documentation :green_book:"] +body: + - type: markdown + attributes: + value: > + **Thank you for wanting to report a problem with pylint documentation!** + + + Please fill out your suggestions below. If the problem seems straightforward, + feel free to go ahead and submit a pull request instead! + + + โš  Verify first that your issue is not [already reported on GitHub][issue + search]. + + ๐Ÿ’ฌ If you are seeking community support, please consider [starting a discussion + on Discord][Discussions]. + + + [issue search]: + https://github.com/pylint-dev/pylint/issues?q=is%3Aissue+is%3Aopen+ + + [Discussions]: https://discord.com/invite/Egy6P8AMB5 + + - type: textarea + id: question + attributes: + label: Question + validations: + required: true + - type: textarea + id: documentation + attributes: + label: Documentation for future user + description: + Where did you expect this information to be? What do we need to add or what do + we need to reorganize? + validations: + required: true + - type: textarea + attributes: + label: Additional context + description: > + Add any other context, links, etc. about the question here. + placeholder: >- + I asked on https://stackoverflow.com/... and the community advised me to do X, Y + and Z. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..76b15114bd --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: true +contact_links: + - name: ๐Ÿ’ฌ Discord + url: https://discord.com/invite/Egy6P8AMB5 + about: Astroid and pylint informal dev discussion diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 016d3bc696..1730a08f7c 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,37 +1,41 @@ -## Steps +## Type of Changes -- [ ] Add yourself to CONTRIBUTORS if you are a new contributor. -- [ ] Add a ChangeLog entry describing what your PR does. -- [ ] If it's a new feature or an important bug fix, add a What's New entry in `doc/whatsnew/`. -- [ ] Write a good description on what the PR does. + -## Description +| | Type | +| --- | ---------------------- | +| โœ“ | :bug: Bug fix | +| โœ“ | :sparkles: New feature | +| โœ“ | :hammer: Refactoring | +| โœ“ | :scroll: Docs | +## Description -## Type of Changes - -| | Type | -| ------------- | ------------- | -| โœ“ | :bug: Bug fix | -| โœ“ | :sparkles: New feature | -| โœ“ | :hammer: Refactoring | -| โœ“ | :scroll: Docs | + -## Related Issue +Refs #XXXX - -Closes #XXX ---> +Closes #XXXX diff --git a/.github/SECURITY.md b/.github/SECURITY.md new file mode 100644 index 0000000000..bbe6fc2fd0 --- /dev/null +++ b/.github/SECURITY.md @@ -0,0 +1 @@ +Coordinated Disclosure Plan: https://tidelift.com/security diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..98e0f3f7ac --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,21 @@ +version: 2 +updates: + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependency" + - "Skip news :mute:" + open-pull-requests-limit: 10 + rebase-strategy: "disabled" + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + labels: + - "dependency" + - "Skip news :mute:" + open-pull-requests-limit: 10 + rebase-strategy: "disabled" diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml new file mode 100644 index 0000000000..9420b7594d --- /dev/null +++ b/.github/workflows/backport.yml @@ -0,0 +1,29 @@ +name: Backport +on: + pull_request_target: + types: + - closed + - labeled + +permissions: + pull-requests: write + contents: write + +jobs: + backport: + name: Backport + runs-on: ubuntu-latest + # 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: tibdex/backport@9565281eda0731b1d20c4025c43339fb0a23812e # v2.0.4 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 0000000000..856ab0d423 --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,66 @@ +name: changelog + +on: + pull_request: + types: [opened, synchronize, labeled, unlabeled, reopened] + branches-ignore: + - "maintenance/**" +env: + CACHE_VERSION: 1 + KEY_PREFIX: base-venv + DEFAULT_PYTHON: "3.12" + +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@v4.1.7 + 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@v5.2.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.2.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 -U pip setuptools wheel + pip install -U -r requirements_test.txt + pip install -U -r 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 }} diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml new file mode 100644 index 0000000000..8668ab6ab5 --- /dev/null +++ b/.github/workflows/checks.yaml @@ -0,0 +1,191 @@ +name: Checks + +on: + push: + branches: + - main + - "maintenance/**" + pull_request: + branches: + - main + - "maintenance/**" + +env: + CACHE_VERSION: 2 + KEY_PREFIX: base-venv + DEFAULT_PYTHON: "3.12" + 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: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.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.2.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 -U pip setuptools wheel + pip install -U -r requirements_test.txt + pip install -U -r 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.2.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: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.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@v4.2.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 . + 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: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.0 + with: + path: venv + fail-on-cache-miss: true + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-base.outputs.python-key }} + - name: Run spelling checks + run: | + . venv/bin/activate + pytest tests/ -k unittest_spelling + + documentation: + name: documentation + runs-on: ubuntu-latest + timeout-minutes: 20 + needs: prepare-base + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ env.DEFAULT_PYTHON }} + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.0 + with: + path: venv + fail-on-cache-miss: true + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.prepare-base.outputs.python-key }} + - 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 + cd doc + pre-commit run --hook-stage push sphinx-generated-doc --all-files || { + echo "git diff:" ; \ + git diff ; \ + echo "End of 'git diff'" ; \ + echo "Make sure that 'make html' succeed without any modifications locally." ; \ + exit 1; \ + } diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..61bfd28de8 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,80 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [main] + pull_request: + # The branches below must be a subset of the branches above + branches: [main] + schedule: + - cron: "44 16 * * 4" + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + analyze: + if: + ${{ github.repository_owner == 'pylint-dev' || github.event_name != 'schedule' }} + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: ["python"] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v4.1.7 + + # 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 diff --git a/.github/workflows/primer-test.yaml b/.github/workflows/primer-test.yaml new file mode 100644 index 0000000000..980f556407 --- /dev/null +++ b/.github/workflows/primer-test.yaml @@ -0,0 +1,98 @@ +name: Primer + +on: + push: + branches: + - main + pull_request: + paths: + - "pylint/**" + - "tests/primer/**" + - "requirements*" + - ".github/workflows/primer-test.yaml" + branches: + - main +env: + CACHE_VERSION: 4 + KEY_PREFIX: venv + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + prepare-tests-linux: + name: prepare / ${{ matrix.python-version }} / Linux + runs-on: ubuntu-latest + timeout-minutes: 5 + strategy: + matrix: + python-version: [3.9, "3.10", "3.11", "3.12", "3.13-dev"] + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + 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.2.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 -U pip setuptools wheel + pip install -U -r 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: [3.9, "3.10", "3.11", "3.12", "3.13-dev"] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.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 . + pytest -m primer_stdlib --primer-stdlib -n auto -vv diff --git a/.github/workflows/primer_comment.yaml b/.github/workflows/primer_comment.yaml new file mode 100644 index 0000000000..e2b6232635 --- /dev/null +++ b/.github/workflows/primer_comment.yaml @@ -0,0 +1,123 @@ +# 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 + DEFAULT_PYTHON: "3.12" + +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@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.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.2.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@v7.0.1 + 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@v7.0.1 + 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 }} diff --git a/.github/workflows/primer_run_main.yaml b/.github/workflows/primer_run_main.yaml new file mode 100644 index 0000000000..7027b1407b --- /dev/null +++ b/.github/workflows/primer_run_main.yaml @@ -0,0 +1,132 @@ +# Most of this is inspired by the mypy primer +# See: https://github.com/hauntsaninja/mypy_primer +# This is the primer job that runs on the default 'main' branch +# It is also responsible for caching the packages to prime on + +name: Primer / Main + +on: + push: + branches: + - main + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +env: + # This needs to be the SAME as in the PR and comment job + CACHE_VERSION: 4 + KEY_PREFIX: venv-primer + +permissions: + contents: read + +jobs: + run-primer: + name: Run / ${{ matrix.python-version }} / batch index ${{ matrix.batchIdx }} + runs-on: ubuntu-latest + timeout-minutes: 45 + strategy: + matrix: + python-version: ["3.9", "3.12"] + batches: [4] + batchIdx: [0, 1, 2, 3] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.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.2.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 -U pip setuptools wheel + pip install -U -r 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.2.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.2.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.2.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.4.0 + 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 . + 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.4.0 + 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 diff --git a/.github/workflows/primer_run_pr.yaml b/.github/workflows/primer_run_pr.yaml new file mode 100644 index 0000000000..9b813c45c4 --- /dev/null +++ b/.github/workflows/primer_run_pr.yaml @@ -0,0 +1,224 @@ +# 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.9", "3.12"] + batches: [4] + batchIdx: [0, 1, 2, 3] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + with: + fetch-depth: 0 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.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.2.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 -U pip setuptools wheel + pip install -U -r 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.2.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@v7.0.1 + 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.2.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.2.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 . + 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.4.0 + 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.4.0 + 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.9') && matrix.batchIdx == 0 + uses: actions/upload-artifact@v4.4.0 + with: + name: pr_number + path: pr_number.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000000..7aa4c51747 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,45 @@ +name: Release + +on: + release: + types: + - published + +env: + DEFAULT_PYTHON: "3.12" + +permissions: + contents: read + +jobs: + release-pypi: + name: Upload release to PyPI + runs-on: ubuntu-latest + environment: + name: PyPI + url: https://pypi.org/project/pylint/ + steps: + - name: Check out code from Github + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ env.DEFAULT_PYTHON }} + id: python + uses: actions/setup-python@v5.2.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 twine build + - name: Build distributions + run: | + python -m build + - name: Upload to PyPI + if: github.event_name == 'release' && startsWith(github.ref, 'refs/tags') + env: + TWINE_REPOSITORY: pypi + TWINE_USERNAME: __token__ + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: | + twine upload --verbose dist/* diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..e7a2b172d9 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,41 @@ +name: close stale issues and pr +on: + schedule: + - cron: "30 1 * * *" + workflow_dispatch: + +jobs: + close-issues: + if: github.repository_owner == 'pylint-dev' + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: + - uses: actions/stale@v9 + with: + 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." diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 0000000000..5559f2b89c --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,309 @@ +name: Tests + +on: + push: + branches: + - main + - "maintenance/**" + paths-ignore: + - doc/data/messages/** + pull_request: + branches: + - main + - "maintenance/**" + +env: + CACHE_VERSION: 4 + KEY_PREFIX: venv + +permissions: + contents: read + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + tests-linux: + name: run / ${{ matrix.python-version }} / Linux + runs-on: ubuntu-latest + timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + python-version: [3.9, "3.10", "3.11", "3.12", "3.13-dev"] + outputs: + python-key: ${{ steps.generate-python-key.outputs.key }} + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + 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.2.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 -U pip setuptools wheel + pip install -U -r requirements_test.txt + - name: Run pytest + run: | + . venv/bin/activate + 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 + - name: Upload coverage artifact + uses: actions/upload-artifact@v4.4.0 + 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-linux + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python 3.12 + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: "3.12" + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.0 + with: + path: venv + fail-on-cache-miss: true + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.tests-linux.outputs.python-key }} + - name: Download all coverage artifacts + uses: actions/download-artifact@v4.1.8 + - name: Combine coverage results + run: | + . venv/bin/activate + coverage combine coverage*/.coverage + coverage xml + - uses: codecov/codecov-action@v4 + 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-linux + strategy: + fail-fast: false + matrix: + python-version: ["3.12"] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.0 + with: + path: venv + fail-on-cache-miss: true + key: + ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{ + needs.tests-linux.outputs.python-key }} + - name: Run pytest + run: | + . venv/bin/activate + pip install pygal + pip install . + 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.4.0 + 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-linux + strategy: + fail-fast: false + matrix: + python-version: [3.9, "3.10", "3.11", "3.12", "3.13-dev"] + 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 + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - 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 + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.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\\Scripts\\activate + python -m pip install -U pip setuptools wheel + pip install -U -r requirements_test_min.txt + - name: Run pytest + run: | + . venv\\Scripts\\activate + pip list | grep 'astroid\|pylint' + python -m pytest --durations=10 --benchmark-disable tests/ + + tests-macos: + name: run / ${{ matrix.python-version }} / macOS + runs-on: macos-latest + timeout-minutes: 25 + needs: tests-linux + strategy: + fail-fast: false + matrix: + # We only run on the oldest supported version on Mac + python-version: [3.9] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - 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') + }}" >> $GITHUB_OUTPUT + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.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 -U pip setuptools wheel + pip install -U -r requirements_test_min.txt + - name: Run pytest + run: | + . venv/bin/activate + pip list | grep 'astroid\|pylint' + python -m pytest --durations=10 --benchmark-disable tests/ + + tests-pypy: + name: run / ${{ matrix.python-version }} / Linux + runs-on: ubuntu-latest + timeout-minutes: 25 + strategy: + fail-fast: false + matrix: + python-version: ["pypy-3.9", "pypy-3.10"] + steps: + - name: Check out code from GitHub + uses: actions/checkout@v4.1.7 + - name: Set up Python ${{ matrix.python-version }} + id: python + uses: actions/setup-python@v5.2.0 + with: + python-version: ${{ matrix.python-version }} + check-latest: true + - 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') + }}" >> $GITHUB_OUTPUT + - name: Restore Python virtual environment + id: cache-venv + uses: actions/cache@v4.2.0 + with: + path: venv + key: >- + ${{ runner.os }}-${{ matrix.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 -U pip setuptools wheel + pip install -U -r requirements_test_min.txt + - name: Run pytest + run: | + . venv/bin/activate + pip list | grep 'astroid\|pylint' + python -m pytest --durations=10 --benchmark-disable tests/ diff --git a/.gitignore b/.gitignore index a652d9145d..d807609565 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ -.svn/ -.hg/ -.hgtags/ +# 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 @@ -9,19 +9,21 @@ /pylint.egg-info/ .tox *.sw[a-z] -doc/technical_reference/extensions.rst -doc/technical_reference/features.rst +# 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 -debian/files -debian/pylint.*.log -debian/pylint.*.debhelper -debian/pylint.substvars -debian/pylint .coverage .coverage.* -.idea .cache/ .eggs/ .pytest_cache/ .mypy_cache/ +.benchmarks/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c750f005a..9b79d406a6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,13 +1,185 @@ +ci: + skip: [pylint] + repos: -- repo: https://github.com/ambv/black - rev: 18.6b4 - hooks: - - id: black - args: [--safe, --quiet] - exclude: functional|input|test/extension|test/regrtest_data|test/data - python_version: python3.6 -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v1.2.3 - hooks: - - id: trailing-whitespace - - id: end-of-file-fixer + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.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.6.5" + hooks: + - id: ruff + args: ["--fix"] + exclude: doc/data/messages + - id: ruff + name: ruff-doc + files: doc/data/messages + - 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: 5.13.2 + hooks: + - id: isort + exclude: doc/data/messages/ + - repo: https://github.com/psf/black + rev: 24.8.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/ + # 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: sphinx-generated-doc + alias: sphinx-generated-doc + name: sphinx-generated-doc + entry: make -C doc/ html + pass_filenames: false + language: system + stages: [pre-push] + - 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.4" + hooks: + - id: rstcheck + args: ["--report-level=warning"] + files: ^(doc/(.*/)*.*\.rst) + additional_dependencies: [Sphinx==7.4.3] + - repo: https://github.com/pre-commit/mirrors-mypy + rev: v1.11.2 + hooks: + - id: mypy + name: mypy + entry: mypy + language: python + types: [python] + args: [] + require_serial: true + additional_dependencies: + [ + "isort>=5", + "platformdirs==2.2.0", + "py==1.11", + "tomlkit>=0.10.1", + "types-setuptools==75.6.0.20241126", + ] + exclude: tests(/\w*)*/functional/|tests/input|tests(/.*)+/conftest.py|doc/data/messages|tests(/\w*)*data/ + - repo: https://github.com/rbubley/mirrors-prettier + rev: v3.3.3 + hooks: + - id: prettier + args: [--prose-wrap=always, --print-width=88] + exclude: tests(/\w*)*data/ + - repo: https://github.com/DanielNoord/pydocstringformatter + rev: v0.7.3 + hooks: + - id: pydocstringformatter + exclude: *fixtures + args: ["--max-summary-lines=2", "--linewrap-full-docstring"] + files: "pylint" + - repo: https://github.com/regebro/pyroma + rev: "4.2" + hooks: + - id: pyroma + # Must be specified because of the default value in pyroma + always_run: false + files: | + (?x)^( + README.rst| + pyproject.toml| + pylint/__init__.py| + pylint/__pkginfo__.py| + setup.cfg + )$ + - repo: https://github.com/PyCQA/bandit + rev: 1.7.9 + hooks: + - id: bandit + args: ["-r", "-lll"] + exclude: *fixtures + - repo: https://github.com/codespell-project/codespell + rev: v2.3.0 + hooks: + - id: codespell + args: ["--toml=pyproject.toml"] + additional_dependencies: + - tomli diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml new file mode 100644 index 0000000000..1bec0790e9 --- /dev/null +++ b/.pre-commit-hooks.yaml @@ -0,0 +1,6 @@ +- id: pylint + name: pylint + entry: pylint + language: python + types: [python] + require_serial: true diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000..5a68950709 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,19 @@ +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +version: 2 + +sphinx: + fail_on_warning: true + configuration: doc/conf.py + +python: + install: + - requirements: doc/requirements.txt + +build: + os: ubuntu-22.04 + tools: + python: "3.11" + jobs: + pre_build: + - towncrier build --yes --date TBA diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8730c87059..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,61 +0,0 @@ -language: python - -stages: - - prechecks - - tests-cpython - - tests-pypy - -# 3.5-dev because of http://bugs.python.org/issue25131 -jobs: - include: - - stage: prechecks - python: 3.6 - env: TOXENV=pylint - - python: 3.6 - env: TOXENV=docs - - python: 3.6 - env: TOXENV=formatting - - python: 3.6 - env: TOXENV=mypy - - stage: tests-cpython - python: 3.4 - env: TOXENV=py34 - - python: 3.5-dev - env: TOXENV=py35 - - python: 3.6 - env: TOXENV=py36 - - python: 3.7 - env: TOXENV=py37 - dist: xenial - - python: 3.6 - env: TOXENV=spelling - - stage: tests-pypy - python: pypy3.5-5.8.0 - env: TOXENV=pypy -before_install: - - python --version - - uname -a - - lsb_release -a - - sudo apt-get -qq update - - sudo apt-get install -y enchant -install: - - pip install -U setuptools - - pip install tox coverage coveralls - - virtualenv --version - - easy_install --version - - pip --version - - tox --version - - coverage --version -script: - # Test install with current version of setuptools - - pip install . - - tox -e coverage-erase,$TOXENV -after_success: - - tox -e coveralls -after_failure: - - more .tox/log/* | cat - - more .tox/*/log/* | cat -notifications: - email: - on_success: always - on_failure: always diff --git a/CITATION.cff b/CITATION.cff new file mode 100644 index 0000000000..53098e8587 --- /dev/null +++ b/CITATION.cff @@ -0,0 +1,14 @@ +cff-version: 1.2.0 +title: "Pylint" +message: >- + If you use this software, please cite it using the metadata from this file. +type: software +authors: + - name: "Pylint contributors" +repository-code: "https://github.com/pylint-dev/pylint" +url: "https://pylint.readthedocs.io/en/latest/" +abstract: >- + Pylint is a static code analyser for Python 2 or 3. Pylint analyses your code without + actually running it. It checks for errors, enforces a coding standard, looks for code + smells, and can make suggestions about how the code could be refactored. +license: GPL-2.0 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..6d30aaaae0 --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,120 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a +harassment-free experience for everyone, regardless of age, body size, visible or +invisible disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal appearance, +race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, +inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community +include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and + learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or advances of any + kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email address, without + their explicit permission +- Other conduct which could reasonably be considered inappropriate in a professional + setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in response to +any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, +commits, code, wiki edits, issues, and other contributions that are not aligned to this +Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an +individual is officially representing the community in public spaces. Examples of +representing our community include using an official e-mail address, posting via an +official social media account, or acting as an appointed representative at an online or +offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to +the community leaders responsible for enforcement at pierre.sassoulas at gmail.com. All +complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter +of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the +consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity +around the nature of the violation and an explanation of why the behavior was +inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with +the people involved, including unsolicited interaction with those enforcing the Code of +Conduct, for a specified period of time. This includes avoiding interactions in +community spaces as well as external channels like social media. Violating these terms +may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained +inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication +with the community for a specified period of time. No public or private interaction with +the people involved, including unsolicited interaction with those enforcing the Code of +Conduct, is allowed during this period. Violating these terms may lead to a permanent +ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, +including sustained inappropriate behavior, harassment of an individual, or aggression +toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, +available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. + +Community Impact Guidelines were inspired by +[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +https://www.contributor-covenant.org/faq. Translations are available at +https://www.contributor-covenant.org/translations. diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 4a4336afd8..c8b7d27fda 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -1,273 +1,671 @@ -๏ปฟContributors +# 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 +- Ashley Whetter +- Nick Drozd : performance improvements to astroid +- 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 ------------ -Current team: - -* Ashley Whetter: maintainer, contributor - -* Bryce Guinta: maintainer, contributor - -* Claudiu Popa: maintainer, contributor - -* Cara Vinson: astroid committer. - -* Guillaume Peillex: committer - -* ลukasz Rogalski: committer. - -* Roy Williams (Lyft): committer - - 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. - -* Dmitry Pribysh: committer - - multiple-imports, not-iterable, not-a-mapping, various patches. - -* Jim Robertson: committer - -Ex-maintainers: - -* Sylvain Thenault (Logilab): main author / maintainer - -* Torsten Marek (Google): committer / contributor - - 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: - -* Daniel Balparda (Google): GPyLint maintainer (Google's pylint variant), - various patches - -* Martin Pool (Google): warnings for anomalous backslashes, symbolic names for - messages (like 'unused'), etc - -* Alexandre Fayolle (Logilab): TkInter gui, documentation, debian support - -* Julien Cristau, Emile Anclin (Logilab): python 3 support - -* Sandro Tosi: Debian packaging - -* Mads Kiilerich, Boris Feld, Bill Wendling, Sebastian Ulrich: - various patches - -* Brian van den Broek: windows installation documentation - -* Amaury Forgeot d'Arc: check names imported from a module exists in the module - -* Benjamin Niemann: allow block level enabling/disabling of messages - -* Nathaniel Manista: suspicious lambda checking - -* David Shea: invalid sequence and slice index - -* Carl Crowder: don't evaluate the value of arguments for 'dangerous-default-value' - -* Michal Nowikowski: wrong-spelling-in-comment, wrong-spelling-in-docstring, - parallel execution on multiple CPUs and other patches. - -* David Lindquist: logging-format-interpolation warning. - -* Brett Cannon: Port source code to be Python 2/3 compatible, Python 3 - checker. - -* Vlad Temian: redundant-unittest-assert and the JSON reporter. - -* Cosmin Poieanฤƒ: unichr-builtin and improvements to bad-open-mode. - -* Viorel ศ˜tirbu: intern-builtin warning. - -* Dan Goldsmith: support for msg-template in HTML reporter. - -* Chris Rebert: unidiomatic-typecheck. - -* Steven Myint: duplicate-except. - -* Radu Ciorba: not-context-manager and confusing-with-statement warnings. - -* Bruno Daniel: check_docs extension. - -* James Morgensen: ignored-modules option applies to import errors. - -* Cezar Elnazli: deprecated-method - -* Stรฉphane Wirtel: nonlocal-without-binding - -* Laura Medioni (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 - -* Aru Sahni: Git ignoring, regex-based ignores - -* Mike Frysinger: contributor. - -* Moisรฉs Lรณpez (Vauxoo): 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 - -* Luis Escobar (Vauxoo), Moisรฉs Lรณpez (Vauxoo): Add bad-docstring-quotes and docstring-first-line-empty - -* Yannick Brehon: contributor. - -* Glenn Matthews: autogenerated documentation for optional extensions, - bug fixes and enhancements for docparams (nรฉe check_docs) extension - -* Elias Dorneles: minor adjust to config defaults and docs - -* Yuri Bochkarev: Added epytext support to docparams extension. - -* 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 - -* Erik Eriksson - Added overlapping-except error check. - -* Anthony Foglia (Google): Added simple string slots check. - -* Derek Gustafson: contributor - -* Petr Pulc: require whitespace around annotations - -* John Paraskevopoulos: add 'differing-param-doc' and 'differing-type-doc' - -* Martin von Gagern (Google): Added 'raising-format-tuple' warning. - -* Ahirnish Pareek, 'keyword-arg-before-var-arg' check - -* Daniel Miller: contributor. - -* Bryce Guinta: contributor - -* Martin Baลกti: contributor - Added new check for shallow copy of os.environ - -* Jacques Kvam: contributor - -* Brian Shaginaw: prevent error on exception check for functions - -* Ioana Tagirta: fix bad thread instantiation check - -* Reverb Chu: contributor - -* Tobias Hernstig: contributor - -* Konstantin Manna: contributor - -* Andreas Freimuth: fix indentation checking with tabs - -* Renat Galimov: contributor - -* Thomas Snowden: fix missing-docstring for inner functions - -* Mitchell Young: minor adjustment to docparams - -* Marianna Polatoglou: minor contribution for wildcard import check - -* Ben Green: contributor - -* Benjamin Freeman: contributor - -* Fureigh: contributor - -* Jace Browning: updated default report format with clickable paths - -* Sushobhit (sushobhit27): contributor - 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'. - -* Mariatta Wijaya: contributor - Added new check `logging-fstring-interpolation` - Documentation typo fixes - -* Jason Owen: contributor - -* Mark Roman Miller: fix inline defs in too-many-statements - -* Adam Dangoor: contributor - -* Gary Tyler McLeod: contributor - -* Wolfgang Grafen, Axel Muller, Fabio Zadrozny, Pierre Rouleau, - Maarten ter Huurne, Mirko Friedenhagen and all the Logilab's team (among others). - -* Matej Marusak: contributor - -* Nick Drozd: contributor, performance improvements to astroid - -* Kosarchuk Sergey: contributor - -* Carey Metcalfe: demoted `try-except-raise` from error to warning - -* Marcus Nรคslund (naslundx): contributor - -* Natalie Serebryakova: contributor - -* Caio Carrara: contributor - -* Roberto Leinardi: PyCharm plugin maintainer - -* Aivar Annamaa: contributor - -* Hornwitser: fix import graph - -* Yuri Gribov: contributor - -* Drew Risinger: committer (docs) - -* Ben James - -* Tomer Chachamu, Richard Goodman: simplifiable-if-expression - -* Alan Chan: contributor - -* Benjamin Drung: contributing Debian Developer - -* Scott Worley: contributor - -* Michael Hudson-Doyle - -* Lucas Cimon: contributor - -* Mike Miller: contributor - -* Sergei Lebedev: contributor - -* Sasha Bagan - -* Pablo Galindo Salgado: contributor - Fix false positive 'Non-iterable value' with async comprehensions. - -* Matus Valo - -* Sardorbek Imomaliev: contributor - -* Justin Li (justinnhli) - -* Nicolas Dickreuter - -* Pascal Corpet - -* Svetoslav Neykov: contributor - -* Federico Bond: contributor - -* Fantix King (UChicago): contributor +- 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รค +- Julien Cristau (Logilab): python 3 support +- Adrien Di Mascio +- Moisรฉs Lรณpez (Vauxoo): + * 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 +- 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> +- Zen Lee <53538590+zenlyj@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 +- Vlad Temian : redundant-unittest-assert and the JSON reporter. +- Julien Jehannet +- Boris Feld +- Anthony Sottile +- Robert Hofer +- Pedro Algarvio (s0undt3ch) +- Julien Palard +- 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 +- Hugo van Kemenade +- Eli Fine (eli88fine): Fixed false positive duplicate code warning for lines with symbols only +- Andrew Haigh (nelfin) +- ร‰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 +- correctmost <134317971+correctmost@users.noreply.github.com> +- Tรฉo Bouvard +- 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) +- 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 +- Alexey Pelykh +- 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 +- 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. +- Daniel Mouritzen +- Dan Hemberger <846186+hemberger@users.noreply.github.com> +- Chris Rebert : unidiomatic-typecheck. +- Aurelien Campeas +- Alvaro Frias +- Alexander Pervakov +- Alain Leufroy +- Adam Williamson +- xmo-odoo +- tbennett0 +- omarandlorraine <64254276+omarandlorraine@users.noreply.github.com> +- craig-sh +- bernie gray +- azinneck0485 <123660683+azinneck0485@users.noreply.github.com> +- Wes Turner (Google): added new check 'inconsistent-quotes' +- Tyler Thieding +- Tobias Hernstig <30827238+thernstig@users.noreply.github.com> +- Sviatoslav Sydorenko +- 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 +- 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 +- Derek Harland +- David Pursehouse +- Dave Bunten +- 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 +- Alexander Kapshuna +- Akhil Kamat +- Adam Parkin +- ่ฐญไน้ผŽ <109224573@qq.com> +- ลukasz Sznuk +- zasca +- y2kbugger +- vinnyrose +- ttenhoeve-aa +- thinwybk +- syutbai +- sur.la.route <17788706+christopherpickering@users.noreply.github.com> +- sdet_liang +- purajit <7026198+purajit@users.noreply.github.com> +- paschich +- oittaa <8972248+oittaa@users.noreply.github.com> +- nyabkun <75878387+nyabkun@users.noreply.github.com> +- moxian +- mar-chi-pan +- lrjball <50599110+lrjball@users.noreply.github.com> +- 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 +- 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 +- 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 +- 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 +- 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 +- JT Olds +- Iggy Eom +- 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 +- Grรฉgoire <96051754+gregoire-mullvad@users.noreply.github.com> +- Grant Welch +- Giuseppe Valente +- Gary Tyler McLeod +- Felix von Drigalski +- Fabrice Douchant +- Fabio Natali +- Fabian Damken +- Eric Froemling +- Emmanuel Chaudron +- Elizabeth Bott <52465744+elizabethbott@users.noreply.github.com> +- Ekin Dursun +- Eisuke Kawashima +- Edward K. Ream +- Edgemaster +- Eddie Darling +- Drew Risinger +- Dr. Nick +- Don Jayamanne +- 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 Wang +- 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 +- Christian Clauss +- 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 +- Benjamin Graham +- Benedikt Morbach +- Ben Greiner +- Barak Shoshany +- Banjamin Freeman +- 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 diff --git a/COPYING b/COPYING deleted file mode 100644 index b7b5f53df1..0000000000 --- a/COPYING +++ /dev/null @@ -1,340 +0,0 @@ - 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. diff --git a/ChangeLog b/ChangeLog deleted file mode 100644 index 0d6813ebdb..0000000000 --- a/ChangeLog +++ /dev/null @@ -1,4104 +0,0 @@ ------------------- -Pylint's ChangeLog ------------------- - -What's New in Pylint 2.3.0? -=========================== - -Release date: 2019-02-27 - -* Protect against `NonDeducibleTypeHierarchy` when calling semi-private `is_subtype` - - `astroid.helpers.is_subtype` raises `NonDeducibleTypeHierarchy` when it cannot infer - the base classes of the given types, but that makes sense in its context given that - the method is mostly used to inform the inference process about the hierarchy of classes. - Doesn't make that much sense for ``pylint`` itself, which is why we're handling the - exception here, rather than in ``astroid`` - - Close PyCQA/astroid#644 - -* Added a new command line option ``list-groups`` for listing all the check groups ``pylint`` knows about. - -* Allow ``BaseException`` for emitting ``broad-except``, just like ``Exception``. - - Close #2741 - -* Fixed a crash that occurred for ``bad-str-strip-call`` when ``strip()`` received ``None`` - - Close #2743 - -* Don't emit ``*-not-iterating`` checks for builtins consumed by ``itertools`` - - Close #2731 - -* Fix a crash caused by iterating over ``Uninferable`` in a string formatting check. - - Close #2727 - -* Fixed false positives for ``no-self-argument`` and ``unsubscriptable-object`` when using ``__class_getitem__`` (new in Python 3.7) - - Close #2416 - -* Support ``Ellipsis`` as a synonym for ``pass`` statements. - - Close #2718 - -* ``fixme`` gets triggered only on comments. - - Close #2321 - -* Fixed a false positive for ``unused-variable`` and ``nonlocal`` assignments - - Close #2671 - -* Added ``load_configuration()`` hook for plugins - - New optional hook for plugins is added: ``load_configuration()``. - This hook is executed after configuration is loaded to prevent - overwriting plugin specific configuration via user-based - configuration. - - Close #2635 - -* Fix missing-raises-doc false positive (W9006) - - Close #1502 - -* Exempt starred unpacking from ``*-not-iterating`` Python 3 checks - - Close #2651 - -* Make ``compare-to-zero`` less zealous by checking against equality and identity - - Close #2645 - -* Add ``no-else-raise`` warning (R1720) - - Close #2558 - -* Exempt ``yield from`` from ``*-not-iterating`` Python 3 checks. - - Close #2643 - -* Fix incorrect generation of ``no-else-return`` warnings (R1705) - - Fixed issue where ``if`` statements with nested ``if`` statements - were incorrectly being flagged as ``no-else-return`` in some cases and - not being flagged as ``no-else-return`` in other cases. Added tests - for verification and updated pylint source files to eliminate newly - exposed warnings. - -* Fix false positive with `not-async-context-manager` caused by not understanding `contextlib.asynccontextmanager` - - Close #2440 - -* Refactor ``bad-reversed-sequence`` to account for more objects that can define ``__reversed__`` - - One such object would be an enum class, for which ``__reversed__`` yields each individual enum. - As such, the check for ``bad-reversed-sequence`` needs to not differentiate between classes - and instances when it comes for checking of ``__reversed__`` presence. - - Close #2598 - -* Added ``wrong-exception-operation`` - - Used when an operation is done against an exception, but the operation - is not valid for the exception in question. Usually emitted when having - binary operations between exceptions in except handlers. - - Close #2494 - -* ``no-member`` is emitted for enums when they lack a member - - Previously we weren't doing this because we detected a - ``__getattr__`` implementation on the ``Enum`` class - (and this check is skipped for classes with ``__getattr__``), - but that is fine for Enums, given that they are inferred in a customised - way in astroid. - - Close #2565 - -* Generalize ``chained-comparison`` - - Previous version incorrectly detects `a < b < c and b < d` and fails to - detect `a < b < c and c < d`. - -* Avoid popping __main__ when using multiple jobs - - Close #2689 - -* Add a new option 'check-str-concat-over-line-jumps' to check 'implicit-str-concat-in-sequence' - -* Fixes for the new style logging format linter. - - The number of arguments was not handled properly, leading to an always - successful check. - -* Fix false positive ``not-callable`` for uninferable properties. - -* Fix false positive ``useless-else-on-loop`` if the break is deep in the else - of an inner loop. - - -What's New in Pylint 2.2.2? -=========================== - -Release date: 2018-11-28 - -* Change the ``logging-format-style`` to use name identifier instead of their - corresponding Python identifiers - - This is to prevent users having to think about escaping the default value for - ``logging-format-style`` in the generated config file. Also our config parsing - utilities don't quite support escaped values when it comes to ``choices`` detection, - so this would have needed various hacks around that. - - Closes #2614 - - -What's New in Pylint 2.2.1? -=========================== - -Release date: 2018-11-27 - -* Fix a crash caused by `implicit-str-concat-in-sequence` and multi-bytes characters. - - Closes #2610 - -What's New in Pylint 2.2? -========================= - -Release date: 2018-11-25 - - * Consider ``range()`` objects for ``undefined-loop-variable`` leaking from iteration. - - Close #2533 - - * ``deprecated-method`` can use the attribute name for identifying a deprecated method - - Previously we were using the fully qualified name, which we still do, but the fully - qualified name for some ``unittest`` deprecated aliases leads to a generic - deprecation function. Instead on relying on that, we now also rely on the attribute - name, which should solve some false positives. - - Close #1653 - Close #1946 - - * Fix compatibility with changes to stdlib tokenizer. - - * ``pylint`` is less eager to consume the whole line for pragmas - - Close #2485 - - * Obtain the correct number of CPUs for virtualized or containerized environments. - - Close #2519 - - * Change ``unbalanced-tuple-unpacking`` back to a warning. - - It used to be a warning until a couple of years ago, after it was promoted to - an error. But the check might be suggesting the wrong thing in some cases, - for instance when checking against ``sys.argv`` which cannot be known at static - analysis time. Given it might rely on potential unknown data, it's best to - have it as a warning. - - Close #2522 - - * Remove ``enumerate`` usage suggestion when defining ``__iter__`` (C0200) - - Close #2477 - - * Emit ``too-many-starred-assignment`` only when the number of Starred nodes is per assignment elements - - Close #2513 - - * `try-except-raise` checker now handles multilevel inheritance hirerachy for exceptions correctly. - - Close #2484 - - * Add a new check, ``simplifiable-if-expression`` for expressions like ``True if cond else False``. - - Close #2487 - - * ``too-few-public-methods`` is not reported for ``typing.NamedTuple`` - - Close #2459 - - * ```too-few-public-methods`` is not reported for dataclasses created with options. - - Close #2488 - - * Remove wrong modules from 'bad-python3-import'. - - Close #2453 - - * The ``json`` reporter prints an empty list when no messages are emitted - - Close #2446 - - * Add a new check, ``duplicate-string-formatting-argument`` - - This new check is emitted whenever a duplicate string formatting argument - is found. - - Close #497 - - * ``assignment-from-no-return`` is not emitted for coroutines. - - Close #1715 - - * Report format string type mismatches. - - * ``consider-using-ternary`` and ``simplified-boolean-expression`` no longer emit for sequence based checks - - Close #2473 - - * Handle ``AstroidSyntaxError`` when trying to import a module. - - Close #2313 - - * Allow ``__module__`` to be redefined at a class level. Close #2451 - - * ``pylint`` used to emit a ``unused-variable`` error if unused import was found in the function. Now instead of - ``unused-variable``, ``unused-import`` is emitted. - - Close #2421 - - * Handle asyncio.coroutine when looking for ``not-an-iterable`` check. - - Close #996 - - * The ``locally-enabled`` check is gone. - - Close #2442 - - * Infer decorated methods when looking for method-hidden - - Close #2369 - - * Pick the latest value from the inferred values when looking for ``raising-non-exception`` - - Close #2431 - - * Extend the TYPE_CHECKING guard to TYPE_CHECKING name as well, not just the attribute - - Close #2411 - - * Ignore import x.y.z as z cases for checker `useless-import-alias`. - - Close #2309 - - * Fix false positive ``undefined-variable`` and ``used-before-assignment`` with nonlocal keyword usage. - - Close #2049 - - * Stop ``protected-access`` exception for missing class attributes - - * Don't emit `assignment-from-no-return` for decorated function nodes - - Close #2385 - - * `unnecessary-pass` is now also emitted when a function or class contains only docstring and pass statement. - - In Python, stubbed functions often have a body that contains just a single `pass` statement, - indicating that the function doesn't do anything. However, a stubbed function can also have just a - docstring, and function with a docstring and no body also does nothing. - - Close #2208 - - * ``duplicate-argument-name`` is emitted for more than one duplicate argument per function - - Close #1712 - - * Allow double indentation levels for more distinguishable indentations - - Close #741 - - * Consider tuples in exception handler for ``try-except-raise``. - Close #2389 - - * Fix astroid.ClassDef check in checkers.utils.is_subclass_of - - * Fix wildcard imports being ignored by the import checker - - * Fix external/internal distinction being broken in the import graph - - * Fix wildcard import check not skipping `__init__.py` - - Close #2430 - - * Add new option to logging checker, ``logging_format_style`` - - * Fix --ignore-imports to understand multi-line imports - - Close #1422 - Close #2019 - - * Add a new check 'implicit-str-concat-in-sequence' to spot string concatenation inside lists, sets & tuples. - - * ``literal-comparison`` is now emitted for 0 and 1 literals. - -What's New in Pylint 2.1.1? -=========================== - -Release date: 2018-08-07 - - * fix pylint crash due to ``misplaced-format-function`` not correctly handling class attribute. - Close #2384 - - * Do not emit \*-builtin for Python 3 builtin checks when the builtin is used inside a try-except - - Close PyCQA/pylint#2228 - - * ``simplifiable-if-statement`` not emitted when dealing with subscripts - -What's New in Pylint 2.1? -========================= - -Release date: 2018-08-01 - * `trailing-comma-tuple` gets emitted for ``yield`` statements as well. - - Close #2363 - - * Get only the arguments of the scope function for `redefined-argument-from-local` - - Close #2364 - - * Add a check `misplaced-format-function` which is emitted if format function is used on - non str object. - - Close #2200 - - * `chain.from_iterable` no longer emits `dict-{}-not-iterating` when dealing with dict values and keys - - * Demote the `try-except-raise` message from an error to a warning (E0705 -> W0706) - - Close #2323 - - * Correctly handle the new name of the Python implementation of the `abc` module. - - Close PyCQA/astroid#2288 - - * Modules with `__getattr__` are exempted by default from `no-member` - - There's no easy way to figure out if a module has a particular member when - the said module uses `__getattr__`, which is a new addition to Python 3.7. - Instead we assume the safe thing to do, in the same way we do for classes, - and skip those modules from checking. - - Close #2331 - - * Fix a false positive `invalid name` message when method or attribute name is longer then 30 characters. - - Close #2047 - - * Include the type of the next branch in `no-else-return` - - Close #2295 - - * Fix inconsistent behaviour for bad-continuation on first line of file - - Close #2281 - - * Fix not being able to disable certain messages on the last line through - the global disable option - - Close #2278 - - * Don't emit `useless-return` when we have a single statement that is the return itself - - We still want to be explicit when a function is supposed to return - an optional value; even though `pass` could still work, it's not explicit - enough and the function might look like it's missing an implementation. - Close #2300 - - * Fix false-positive undefined-variable for self referential class name in lamdbas - - Close #704 - - * Don't crash when `pylint` is unable to infer the value of an argument to `next()` - - Close #2316 - - * Don't emit `not-an-iterable` when dealing with async iterators. - - But do emit it when using the usual iteration protocol against - async iterators. - - Close #2311 - - * Can specify a default docstring type for when the check cannot guess the type - - Close #1169 - - -What's New in Pylint 2.0? -========================= - -Release date: 2018-07-15 - * `try-except-raise` should not be emitted if there are any parent exception class handlers. - - Close #2284 - - * `trailing-comma-tuple` can be emitted for `return` statements as well. - - Close #2269 - - * Fix a false positive ``inconsistent-return-statements`` message when exception is raised - inside an else statement. - - Close #1782 - - * `ImportFrom` nodes correctly use the full name for the import sorting checks. - - Close #2181 - - * [].extend and similar builtin operations don't emit `dict-*-not-iterating` with the Python 3 porting checker - - Close #2187 - - * Add a check `consider-using-dict-comprehension` which is emitted if for dict initialization - the old style with list comprehensions is used. - - * Add a check `consider-using-set-comprehension` which is emitted if for set initialization - the old style with list comprehensions is used. - - * `logging-not-lazy` is emitted whenever pylint infers that a string is built with addition - - Close #2193 - - * Add a check `chained-comparison` which is emitted if a boolean operation can be simplified - by chaining some of its operations. - e.g "a < b and b < c", can be simplified as "a < b < c". - - Close #2032 - - * Add a check `consider-using-in` for comparisons of a variable against - multiple values with "==" and "or"s instead of checking if the variable - is contained "in" a tuple of those values. - - * `in` is considered iterating context for some of the Python 3 porting checkers - - Close #2186 - - * Add `--ignore-none` flag to control if pylint should warn about `no-member` where the owner is None - - * Fix a false positive related to `too-many-arguments` and bounded `__get__` methods - - Close #2172 - - * `mcs` as the first parameter of metaclass's `__new__` method was replaced by `cls` - - Close #2028 - - * `assignment-from-no-return` considers methods as well. - - Close #2081 - - * Support typing.TYPE_CHECKING for *unused-import* errors - - Close #1948 - - * Inferred classes at a function level no longer emit `invalid-name` - when they don't respect the variable regular expression - - Close #1049 - - * Added basic support for postponed evaluation of function annotations. - - Close #2069 - - * Fix a bug with `missing-kwoa` and variadics parameters - - Close #1111 - - * `simplifiable-if-statement` takes in account only when assigning to same targets - - Close #1984 - - * Make ``len-as-condition`` test more cases, such as ``len() < 1`` or ``len <= 0`` - - * Fix false-positive ``line-too-long`` message emission for - commented line at the end of a module - - Close #1950 - - * Fix false-positive ``bad-continuation`` for with statements - - Close #461 - - * Don't warn about `stop-iteration-return` when using `next()` over `itertools.count` - - Close #2158 - - * Add a check `consider-using-get` for unidiomatic usage of value/default-retrieval - for a key from a dictionary - - Close #2076 - - * invalid-slice-index is not emitted when the slice is used as index for a complex object. - - We only use a handful of known objects (list, set and friends) to figure out if - we should emit invalid-slice-index when the slice is used to subscript an object. - - * Don't emit `unused-import` anymore for typing imports used in type comments. - - * Add a new check 'useless-import-alias'. - - Close #2052 - - * Add `comparison-with-callable` to warn for comparison with bare callable, without calling it. - - Close #2082 - - * Don't warn for ``missing-type-doc`` and/or ``missing-return-type-doc``, if type - annotations exist on the function signature for a parameter and/or return type. - Close #2083 - - * Add `--exit-zero` option for continuous integration scripts to more - easily call Pylint in environments that abort when a program returns a - non-zero (error) status code. - - Close #2042 - - * Warn if the first argument of an instance/ class method gets assigned - - Close #977 - - * New check `comparison-with-itself` to check comparison between same value. - - Close #2051 - - * Add a new warning, 'logging-fstring-interpolation', emitted when f-string - is used within logging function calls. - - Close #1998 - - * Don't show 'useless-super-delegation' if the subclass method has different type annotations. - - Close #1923 - - * Add `unhashable-dict-key` check. - - Closes #586 - - * Don't warn that a global variable is unused if it is defined by an import - - Close #1453 - - * Skip wildcard import check for `__init__.py`. - - Close #2026 - - * The Python 3 porting mode can now run with Python 3 as well. - - * `too-few-public-methods` is not emitted for dataclasses. - - Close #1793 - - * New verbose mode option, enabled with `--verbose` command line flag, to - display of extra non-checker-related output. It is disabled by default. - - Close #1863 - - * `undefined-loop-variable` takes in consideration non-empty iterred objects before emitting - - Close #2039 - - * Add support for numpydoc optional return value names. - - Close #2030 - - * `singleton-comparison` accounts for negative checks - - Close #2037 - - * Add a check `consider-using-in` for comparisons of a variable against - multiple values with "==" and "or"s instead of checking if the variable - is contained "in" a tuple of those values. - - Close #1977 - - * defaultdict and subclasses of dict are now handled for dict-iter-* checks - - Close #2005 - - * `logging-format-interpolation` also emits when f-strings are used instead of % syntax. - - Close #1788 - - * Don't trigger misplaced-bare-raise when the raise is in a finally clause - - Close #1924 - - * Add a new check, `possibly-unused-variable`. - - This is similar to `unused-variable`, the only difference is that it is - emitted when we detect a locals() call in the scope of the unused variable. - The `locals()` call could potentially use the said variable, by consuming - all values that are present up to the point of the call. This new check - allows to disable this error when the user intentionally uses `locals()` - to consume everything. - - Close #1909. - - * `no-else-return` accounts for multiple cases - - The check was a bit overrestrictive because we were checking for - return nodes in the .orelse node. At that point though the if statement - can be refactored to not have the orelse. This improves the detection of - other cases, for instance it now detects TryExcept nodes that are part of - the .else branch. - - Close #1852 - - * Added two new checks, `invalid-envvar-value` and `invalid-envvar-default`. - - The former is trigger whenever pylint detects that environment variable manipulation - functions uses a different type than strings, while the latter is emitted whenever - the said functions are using a default variable of different type than expected. - - * Add a check `consider-using-join` for concatenation of strings using str.join(sequence) - - Close #1952 - - * Add a check `consider-swap-variables` for swapping variables with tuple unpacking - - Close #1922 - - * Add new checker `try-except-raise` that warns the user if an except handler block - has a ``raise`` statement as its first operator. The warning is shown when there is - a bare raise statement, effectively re-raising the exception that was caught or the - type of the exception being raised is the same as the one being handled. - - * Don't crash on invalid strings when checking for `logging-format-interpolation` - - Close #1944 - - * Exempt `__doc__` from triggering a `redefined-builtin` - - `__doc__` can be used to specify a docstring for a module without - passing it as a first-statement string. - - * Fix false positive bad-whitespace from function arguments with default - values and annotations - - Close #1831 - - * Fix stop-iteration-return false positive when next builtin has a - default value in a generator - - Close #1830 - - * Fix emission of false positive ``no-member`` message for class with "private" attributes whose name is mangled. - - Close #1643 - - * Fixed a crash which occurred when `Uninferable` wasn't properly handled in `stop-iteration-return` - - Close #1779 - - * Use the proper node to get the name for redefined functions (#1792) - - Close #1774 - - * Don't crash when encountering bare raises while checking inconsistent returns - - Close #1773 - - * Fix a false positive ``inconsistent-return-statements`` message when if statement is inside try/except. - - Close #1770 - - * Fix a false positive ``inconsistent-return-statements`` message when while loop are used. - - Close #1772 - - * Correct column number for whitespace conventions. - - Previously the column was stuck at 0 - - Close #1649 - - * Fix ``unused-argument`` false positives with overshadowed variable in - dictionary comprehension. - - Close #1731 - - * Fix false positive ``inconsistent-return-statements`` message when never - returning functions are used (i.e sys.exit for example). - - Close #1771 - - * Fix error when checking if function is exception, as in ``bad-exception-context``. - - * Fix false positive ``inconsistent-return-statements`` message when a - function is defined under an if statement. - - Close #1794 - - * New ``useless-return`` message when function or method ends with a "return" or - "return None" statement and this is the only return statement in the body. - - * Fix false positive ``inconsistent-return-statements`` message by - avoiding useless exception inference if the exception is not handled. - - Close #1794 (second part) - - * Fix bad thread instantiation check when target function is provided in args. - - Close #1840 - - * Fixed false positive when a numpy Attributes section follows a Parameters - section - - Close #1867 - - * Fix incorrect file path when file absolute path contains multiple ``path_strip_prefix`` strings. - - Close #1120 - - * Fix false positive undefined-variable for lambda argument in class definitions - - Close #1824 - - * Add of a new checker that warns the user if some messages are enabled or disabled - by id instead of symbol. - - Close #1599 - - * Suppress false-positive ``not-callable`` messages from certain - staticmethod descriptors - - Close #1699 - - * Fix indentation handling with tabs - - Close #1148 - - * Fix false-positive ``bad-continuation`` error - - Close #638 - - * Fix false positive unused-variable in lambda default arguments - - Close #1921 - Close #1552 - Close #1099 - Close #210 - - * Updated the default report format to include paths that can be clicked on in some terminals (e.g. iTerm). - - * Fix inline def behavior with ``too-many-statements`` checker - - Close #1978 - - * Fix `KeyError` raised when using docparams and NotImplementedError is documented. - - Close #2102 - - * Fix 'method-hidden' raised when assigning to a property or data descriptor. - - * Fix emitting ``useless-super-delegation`` when changing the default value of keyword arguments. - - Close #2022 - - * Expand ignored-argument-names include starred arguments and keyword arguments - - Close #2214 - - * Fix false-postive undefined-variable in nested lambda - - Close #760 - - * Fix false-positive ``bad-whitespace`` message for typing annoatations - with ellipses in them - - Close 1992 - -What's New in Pylint 1.9? -========================= - -Release date: 2018-05-15 - - * Added two new Python 3 porting checks, `exception-escape` and `comprehension-escape` - - These two are emitted whenever pylint detects that a variable defined in the - said blocks is used outside of the given block. On Python 3 these values are deleted. - - * Added a new `deprecated-sys-function`, emitted when accessing removed sys members. - - * Added `xreadlines-attribute`, emitted when the `xreadlines()` attribute is accessed. - - * The Python 3 porting mode can now run with Python 3 as well. - - * docparams extension allows abstract methods to document what overriding - implementations should return, and to raise NotImplementedError without - documenting it. - - Closes #2044 - - * Special methods do not count towards `too-few-methods`, - and are considered part of the public API. - - * Enum classes do not trigger `too-few-methods` - - Close #605 - - * Added a new Python 2/3 check for accessing `operator.div`, which is removed in Python 3 - - Close #1936 - - * Added a new Python 2/3 check for accessing removed urllib functions - - Close #1997 - - -What's New in Pylint 1.8.1? -=========================== - -Release date: 2017-12-15 - - * Wrong version number in __pkginfo__. - - -What's New in Pylint 1.8? -========================= - -Release date: 2017-12-15 - - * Respect disable=... in config file when running with --py3k. - - * New warning `shallow-copy-environ` added - - Shallow copy of os.environ doesn't work as people may expect. os.environ - is not a dict object but rather a proxy object, so any changes made - on copy may have unexpected effects on os.environ - - Instead of copy.copy(os.environ) method os.environ.copy() should be - used. - - See https://bugs.python.org/issue15373 for details. - - Close #1301 - - * Do not display no-absolute-import warning multiple times per file. - - * `trailing-comma-tuple` refactor check now extends to assignment with - more than one element (such as lists) - - Close #1713 - - * Fixing u'' string in superfluous-parens message - - Close #1420 - - * `abstract-class-instantiated` is now emitted for all inference paths. - - Close #1673 - - * Add set of predefined naming style to ease configuration of checking - naming conventions. - - Closes #1013 - - * Added a new check, ``keyword-arg-before-vararg`` - - This is emitted for function definitions - in which keyword arguments are placed before variable - positional arguments (\*args). - - This may lead to args list getting modified if keyword argument's value - is not provided in the function call assuming it will take default value - provided in the definition. - - * The `invalid-name` check contains the name of the template that caused the failure - - Close #1176 - - * Using the -j flag won't start more child linters than needed. - - Contributed by Roman Ivanov in #1614 - - * Fix a false positive with bad-python3-import on relative imports - - Close #1608 - - * Added a new Python 3 check, ``non-ascii-bytes-literals`` - - Close #1545 - - * Added a couple of new Python 3 checks for accessing dict methods in non-iterable context - - * Protocol checks (not-a-mapping, not-an-iterable and co.) aren't emitted on classes with dynamic getattr - - * Added a new warning, 'bad-thread-instantiation' - - This message is emitted when the threading.Thread class does not - receive the target argument, but receives just one argument, which - is by default the group parameter. - - Close #1327 - - * In non-quiet mode, absolute path of used config file is logged to - standard error. - Close #1519 - - * Raise meaningful exception for invalid reporter class being selected - - When unknown reporter class will be selected as Pylint reporter, - meaningful error message would be raised instead of bare ``ImportError`` - or ``AttribueError`` related to module or reporter class being not found. - Close #1388 - - * Added a new Python 3 check for accessing removed functions from itertools - like ``izip`` or ``ifilterfalse`` - - * Added a new Python 3 check for accessing removed fields from the types - module like ``UnicodeType`` or ``XRangeType`` - - * Added a new Python 3 check for declaring a method ``next`` that would have - been treated as an iterator in Python 2 but a normal function in Python 3. - - * Added a new key-value pair in json output. The key is ``message-id`` - and the value is the message id. - Close #1512 - - * Added a new Python 3.0 check for raising a StopIteration inside a generator. - The check about raising a StopIteration inside a generator is also valid if the exception - raised inherit from StopIteration. - Close #1385 - - * Added a new warning, ``raising-format-tuple``, to detect multi-argument - exception construction instead of message string formatting. - - * Added a new check for method of logging module that concatenate string via + operator - Close #1479 - - * Added parameter for limiting number of suggestions in spellchecking checkers - - * Fix a corner-case in ``consider-using-ternary`` checker. - - When object ``A`` used in ``X and A or B`` was falsy in boolean context, - Pylint incorrectly emitted non-equivalent ternary-based suggestion. - After a change message is correctly not emitted for this case. - Close #1559 - - * Added ``suggestion-mode`` configuration flag. When flag is enabled, informational - message is emitted instead of cryptic error message for attributes accessed on - c-extensions. - Close #1466 - - * Fix a false positive ``useless-super-delegation`` message when - parameters default values are different from those used in the base class. - Close #1085 - - * Disabling 'wrong-import-order', 'wrong-import-position', or - 'ungrouped-imports' for a single line now prevents that line from - triggering violations on subsequent lines. - - Close #1336 - - * Added a new Python check for inconsistent return statements inside method or function. - Close #1267 - - * Fix ``superfluous-parens`` false positive related to handling logical statements - involving ``in`` operator. - - Close #574 - - * ``function-redefined`` message is no longer emitted for functions and - methods which names matches dummy variable name regular expression. - Close #1369 - - * Fix ``missing-param-doc`` and ``missing-type-doc`` false positives when - mixing ``Args`` and ``Keyword Args`` in Google docstring. - Close #1409 - - * Fix ``missing-docstring`` false negatives when modules, classes, or methods - consist of compound statements that exceed the ``docstring-min-length`` - - * Fix ``useless-else-on-loop`` false positives when break statements are - deeply nested inside loop. - Close #1661 - - * Fix no ``wrong-import-order`` message emitted on ordering of first and third party - libraries. With this fix, pylint distinguishes third and first party - modules when checking import order. - Close #1702 - - * Fix ``pylint disable=fixme`` directives ignored for comments following the - last statement in a file. - Close #1681 - - * Fix ``line-too-long`` message deactivated by wrong disable directive. - The directive ``disable=fixme`` doesn't deactivate anymore the emission - of ``line-too-long`` message for long commented lines. - Close #1741 - - * If the rcfile specified on the command line doesn't exist, then an - IOError exception is raised. - Close #1747 - - * Fix the wrong scope of the ``disable=`` directive after a commented line. - For example when a ``disable=line-too-long`` directive is at the end of - a long commented line, it no longer disables the emission of ``line-too-long`` - message for lines that follow. - Close #1742 - -What's New in Pylint 1.7.1? -=========================== - -Release date: 2017-04-17 - - * Fix a false positive which occurred when an exception was reraised - - Close #1419 - - * Fix a false positive of ``disallow-trailing-tuple`` - - The check was improved by verifying for non-terminating newlines, which - should exempt function calls and function definitions from the check - Close #1424 - - -What's New in Pylint 1.7? -========================= - -Release date: 2017-04-13 - - * Don't emit missing-final-newline or trailing-whitespace for formfeeds (page breaks). - - Close #1218 and #1219 - - * Don't emit by default no-member if we have opaque inference objects in the inference results - - This is controlled through the new flag ignore-on-opaque-inference, which is by - default True. The inference can return multiple potential results while - evaluating a Python object, but some branches might not be evaluated, which - results in partial inference. In that case, it might be useful to still emit - no-member and other checks for the rest of the inferred objects. - - * Added new message `assign-to-new-keyword` to warn about assigning to names which - will become a keyword in future Python releases. - - Close #1351 - - * Split the 'missing or differing' in parameter documentation in different error. - 'differing-param-doc' covers the differing part of the old 'missing-param-doc', - and 'differing-type-doc' covers the differing part of the old 'missing-type-doc' - - Close #1342 - - * Added a new error, 'used-prior-global-declaration', which is emitted when a name - is used prior a global declaration in a function. This causes a SyntaxError in - Python 3.6 - - Close #1257 - - * The protocol checks are emitting their messages when a special method is set to None. - - Close #1263 - - * Properly detect if imported name is assigned to same name in different - scope. - - Close #636, #848, #851, and #900 - - * Require one space for annotations with type hints, as per PEP 8. - - * 'trailing-comma-tuple' check was added - - This message is emitted when pylint finds an one-element tuple, - created by a stray comma. This can suggest a potential problem in the - code and it is recommended to use parantheses in order to emphasise the - creation of a tuple, rather than relying on the comma itself. - - * Don't emit not-callable for instances with unknown bases. - - Close #1213 - - * Treat keyword only arguments the same as positional arguments with regard to unused-argument check - - * Don't try to access variables defined in a separate scope when checking for ``protected-access`` - - * Added new check to detect incorrect usage of len(SEQUENCE) inside - test conditions. - - * Added new extension to detect comparisons against empty string constants - - * Added new extension to detect comparisons of integers against zero - - * Added new error conditions for 'bad-super-call' - - Now detects ``super(type(self), self)`` and ``super(self.__class__, self)`` - which can lead to recursion loop in derived classes. - - * PyLinter.should_analyze_file has a new optional parameter, called `is_argument` - - Close #1079 - - * Add attribute hints for missing members - - Closes #1035 - - * Add a new warning, 'redefined-argument-from-local' - - Closes #649 - - * Support inline comments for comma separated values in the config file - - Closes #1024 - - * epylint.py_run's *script* parameter was removed. - - * epylint.py_run now uses ``shell=False`` for running the underlying process. - - Closes #441 - - * Added a new warning, 'useless-super-delegation' - - Close 839. - - * Added a new error, 'invalid-metaclass', raised when - we can detect that a class is using an improper metaclass. - - Close #579 - - * Added a new refactoring message, 'literal-comparison'. - - Close #786 - - * arguments-differ takes in consideration kwonlyargs and variadics - - Close #983 - - * Removed --optimized-ast. Part of #975. - - * Removed --files-output option. Part of #975. - - * Removed pylint-gui from the package. - - * Removed the HTML reporter. Part of #975. - - * ignored-argument-names is now used for ignoring arguments for unused-variable check. - - This option was used for ignoring arguments when computing the correct number of arguments - a function should have, but for handling the arguments with regard - to unused-variable check, dummy-variables-rgx was used instead. Now, ignored-argument-names - is used for its original purpose and also for ignoring the matched arguments for - the unused-variable check. This offers a better control of what should be ignored - and how. - Also, the same option was moved from the design checker to the variables checker, - which means that the option now appears under the ``[VARIABLES]`` section inside - the configuration file. - Close #862. - - * Fix a false positive for keyword variadics with regard to keyword only arguments. - - If a keyword only argument was necessary for a function, but that function was called - with keyword variadics (\**kwargs), then we were emitting a missing-kwoa false positive, - which is now fixed. - - Close #934. - - * Fix some false positives with unknown sized variadics. - - Close #878 - - * Added a new extension, check_docstring, for checking PEP 257 conventions. - - Closes #868. - - * config files with BOM markers can now be read. - - Close #864. - - * epylint.py_run does not crash on big files, using .communicate() instead of .wait() - - Close #599 - - * Disable reports by default and show the evaluation score by default - - As per discussion from issue #746, the reports were disabled by - default in order to simplify the interaction between the tool - and the users. The score is still shown by default, as a way of - closely measuring when it increases or decreases due to changes - brought to the code. - - * Disable the information category messages by default. - - This is a step towards making pylint more sane, as - per the discussion from issue #746. - - * Catch more cases as not proper iterables for __slots__ with - regard to invalid-slots pattern. Closes issue #775. - - * empty indent strings are rejected. - - * Added a new error, 'relative-beyond-top-level', which is emitted - when a relative import was attempted beyond the top level package. - - Closes issue #588. - - * Added a new warning, 'unsupported-assignment-operation', which is - emitted when item assignment is tried on an object which doesn't - have this ability. Closes issue #591. - - * Added a new warning, 'unsupported-delete-operation', which is - emitted when item deletion is tried on an object which doesn't - have this ability. Closes issue #592. - - * Fix a false positive of 'redundant-returns-doc', occurred when the documented - function was using *yield* instead of *return*. - - Closes issue #984. - - * Fix false positives of 'missing-[raises|params|type]-doc' due to not - recognizing keyword synonyms supported by Sphinx. - - * Added a new refactoring message, 'consider-merging-isinstance', which is - emitted whenever we can detect that consecutive isinstance calls can be - merged together. - - Closes issue #968 - - * Fix a false positive of 'missing-param-doc' and 'missing-type-doc', - occurred when a class docstring uses the 'For the parameters, see' - magic string but the class __init__ docstring does not, or vice versa. - - * `redefined-outer-name` is now also emitted when a nested loop's target - variable is the same as a target variable in an outer loop. - - Closes issue #911. - - * Added proper exception type inference for 'missing-raises-doc'. - - * Added InvalidMessageError exception class to replace asserts in - pylint.utils. - - * More thorough validation in MessagesStore.register_messages() to avoid - one message accidentally overwriting another. - - * InvalidMessageError, UnknownMessage, and EmptyReport exceptions are - moved to the new pylint.exceptions submodule. - - * UnknownMessage and EmptyReport are renamed to UnknownMessageError and - EmptyReportError. - - * Warnings 'missing-returns-type-doc' and 'missing-yields-type-doc' - have each been split into two warnings - 'missing-[return|yield]-doc' - and 'missing-[return|yield]-type-doc'. - - * Added epytext support to docparams extension. - - Closes #1029. - - * Support having plugins with the same name and with options defined - - Closes #1018 - - * Sort configuration options in a section - - Closes #1087 - - * Added a new Python 3 warning around implementing '__div__', '__idiv__', or - '__rdiv__' as those methods are phased out in Python 3. - - * Added a new warning, 'overlapping-except', which is - emitted when two exceptions in the same except-clause are aliases - for each other or one exceptions is an ancestor of another. - - * Avoid crashing on ill-formatted strings when checking for string formatting errors. - - * Added a new Python 3 warning for calling 'str.encode' or 'str.decode' with a non-text - encoding. - - * Added new coding convention message, 'single-string-used-for-slots'. - - Closes #1166 - - * Added a new Python 3 check for accessing 'sys.maxint' which was removed in Python 3 in favor - of 'sys.maxsize' - - * Added a new Python 3 check for bad imports. - - * Added a new Python 3 check for accessing deprecated string functions. - - * Do not warn about unused arguments or function being redefined in singledispatch - registered implementations. - - Closes #1032 and #1034 - - * Added refactoring message 'no-else-return'. - - * Improve unused-variable checker to warn about unused variables in module scope. - - Closes #919 - - * Ignore modules import as _ when checking for unused imports. - - Closes #1190 - - * Improve handing of Python 3 classes with metaclasses declared in nested scopes. - - Closes #1177 - - * Added refactoring message 'consider-using-ternary'. - - Closes #1204 - - * Bug-fix for false-positive logging-format-interpolation` when format specifications - are used in formatted string. - - Fixes #572 - - * Added a new switch ``single-line-class-stmt`` to allow single-line declaration - of empty class bodies. - - Closes #738 - - * Protected access in form `type(self)._attribute` are now allowed. - - Fixes #1031 - - * Let the user modify msg-template when Pylint is called from a Python script - - Fixes #1269 - - * Imports checker supports new switch ``allow-wildcard-with-all`` which disables - warning on wildcard import when imported module defines `__all__` variable. - - Fixes #831 - - * `too-many-format-args` and `too-few-format-args` are emitted correctly when - starred expression are used in RHS tuple. - - Fixes #957 - - * `cyclic-import` checker supports local disable clauses. When one - of cycle imports was done in scope where disable clause was active, - cycle is not reported as violation. - - Fixes #59 - - -What's new in Pylint 1.6.3? -=========================== - -Release date: 2016-07-18 - - * Do not crash when inferring uninferable exception types for docparams extension - - Close #998 - - -What's new in Pylint 1.6.2? -=========================== - -Release date: TBA - - * Do not crash when printing the help of options with default regular expressions - - Close #990 - - * More granular versions for deprecated modules. - - Close #991 - - -What's new in Pylint 1.6.1? -=========================== - -Release date: 2016-07-07 - - * Use environment markers for supporting conditional dependencies. - - -What's New in Pylint 1.6.0? -=========================== - -Release date: 2016-07-03 - - * Added a new extension, `pylint.extensions.mccabe`, for warning - about complexity in code. - - * Deprecate support for --optimize-ast. Part of #975. - - * Deprecate support for the HTML output. Part of #975. - - * Deprecate support for --output-files. Part of #975. - - * Fixed a documentation error for the check_docs extension. Fixes #735. - - * Made the list of property-defining decorators configurable. - - * Fix a bug where the top name of a qualified import was detected as unused variable. - - Close #923. - - * bad-builtin is now an extension check. - - * generated-members support qualified name through regular expressions. - - For instance, one can specify a regular expression as --generated-members=astroid.node_classes.* - for ignoring every no-member error that is accessed as in `astroid.node_classes.missing.object`. - - * Add the ability to ignore files based on regex matching, with the new ``--ignore-patterns`` - option. - - This addresses issue #156 by allowing for multiple ignore patterns - to be specified. Rather than clobber the existing ignore option, we - introduced a new one called ignore-patterns. - - * Added a new error, 'trailing-newlines', which is emitted when a file - has trailing new lines. - - Closes issue #682. - - * Add a new option, 'redefining-builtins-modules', for controlling the modules - which can redefine builtins, such as six.moves and future.builtins. - - Close #464. - - * 'reimported' is emitted when the same name is imported from different module. - - Close #162. - - * Add a new recommendation checker, 'consider-iterating-dictionary', which is emitted - which is emitted when a dictionary is iterated through .keys(). - - Close #699 - - * Use the configparser backport for Python 2 - - This fixes a problem we were having with comments inside values, which is fixed - in Python 3's configparser. - Close #828 - - * A new error was added, 'invalid-length-returned', when the `__len__` - special method returned something else than a non-negative number. - - Close issue #557 - - * Switch to using isort internally for wrong-import-order. - - Closes #879. - - * check_docs extension can find constructor parameters in __init__. - - Closes #887. - - * Don't warn about invalid-sequence-index if the indexed object has unknown base - classes. - - Closes #867 - - * Don't crash when checking, for super-init-not-called, a method defined in an if block. - - * Do not emit import-error or no-name-in-module for fallback import blocks by default. - - Until now, we warned with these errors when a fallback import block (a TryExcept block - that contained imports for Python 2 and 3) was found, but this gets cumbersome when - trying to write compatible code. As such, we don't check these blocks by default, - but the analysis can be enforced by using the new ``--analyse-fallback-block`` flag. - - Close #769. - - -What's New in Pylint 1.5.5? -=========================== - -Release date: 2016-03-21 - - - * Let visit_importfrom from Python 3 porting checker be called when everything is disabled - - Because the visit method was filtering the patterns it was expecting to be activated, - it didn't run when everything but one pattern was disabled, leading to spurious false - positives - - Close #852 - - * Don't emit unsubscriptable-value for classes with unknown - base classes. - - Close #776. - - * Use an OrderedDict for storing the configuration elements - - This fixes an issue related to impredictible order of the disable / enable - elements from a config file. In certain cases, the disable was coming before - the enable which resulted in classes of errors to be enabled, even though the intention - was to disable them. The best example for this was in the context of running multiple - processes, each one of it having different enables / disables that affected the output. - - Close #815 - - * Don't consider bare and broad except handlers as ignoring NameError, - AttributeError and similar exceptions, in the context of checkers for - these issues. - - Closes issue #826 - - -What's New in Pylint 1.5.4? -=========================== - -Release date: 2016-01-15 - - - * Merge StringMethodChecker with StringFormatChecker. This fixes a - bug where disabling all the messages and enabling only a handful of - messages from the StringFormatChecker would have resulted in no - messages at all. - - * Don't apply unneeded-not over sets. - - -What's New in Pylint 1.5.3? -=========================== - -Release date: 2016-01-11 - - * Handle the import fallback idiom with regard to wrong-import-order. - - Closes issue #750. - - * Decouple the displaying of reports from the displaying of messages - - Some reporters are aggregating the messages instead of displaying - them when they are available. The actual displaying was conflatted - in the generate_reports. Unfortunately this behaviour was flaky - and in the case of the JSON reporter, the messages weren't shown - at all if a file had syntax errors or if it was missing. - In order to fix this, the aggregated messages can now be - displayed with Reporter.display_message, while the reports are - displayed with display_reports. - - Closes issues #766 and #765. - - * Ignore function calls with variadic arguments without a context. - - Inferring variadic positional arguments and keyword arguments - will result into empty Tuples and Dicts, which can lead in - some cases to false positives with regard to no-value-for-parameter. - In order to avoid this, until we'll have support for call context - propagation, we're ignoring such cases if detected. - Closes issue #722. - - * Treat AsyncFunctionDef just like FunctionDef nodes, - by implementing visit_asyncfunctiondef in terms of - visit_functiondef. - - Closes issue #767. - - * Take in account kwonlyargs when verifying that arguments - are defined with the check_docs extension. - - Closes issue #745. - - * Suppress reporting 'unneeded-not' inside `__ne__` methods - - Closes issue #749. - - -What's New in Pylint 1.5.2? -=========================== - -Release date: 2015-12-21 - - * Don't crash if graphviz is not installed, instead emit a - warning letting the user to know. - - Closes issue #168. - - * Accept only functions and methods for the deprecated-method checker. - - This prevents a crash which can occur when an object doesn't have - .qname() method after the inference. - - * Don't emit super-on-old-class on classes with unknown bases. - Closes issue #721. - - * Allow statements in `if` or `try` blocks containing imports. - - Closes issue #714. - - -What's New in Pylint 1.5.1? -=========================== - -Release date: 2015-12-02 - - - * Fix a crash which occurred when old visit methods are encountered - in plugin modules. Closes issue #711. - - * Add wrong-import-position to check_messages's decorator arguments - for ImportChecker.leave_module - This fixes an esoteric bug which occurs when ungrouped-imports and - wrong-import-order are disabled and pylint is executed on multiple files. - What happens is that without wrong-import-position in check_messages, - leave_module will never be called, which means that the first non-import node - from other files might leak into the current file, - leading to wrong-import-position being emitted by pylint. - - * Fix a crash which occurred when old visit methods are encountered - in plugin modules. Closes issue #711. - - * Don't emit import-self and cyclic-import for relative imports - of modules with the same name as the package itself. - Closes issues #708 and #706. - - -What's New in Pylint 1.5.0? -=========================== - -Release date: 2015-11-29 - - - * Added multiple warnings related to imports. 'wrong-import-order' - is emitted when PEP 8 recommendations regarding imports are not - respected (that is, standard imports should be followed by third-party - imports and then by local imports). 'ungrouped-imports' is emitted - when imports from the same package or module are not placed - together, but scattered around in the code. 'wrong-import-position' - is emitted when code is mixed with imports, being recommended for the - latter to be at the top of the file, in order to figure out easier by - a human reader what dependencies a module has. - Closes issue #692. - - * Added a new refactoring warning, 'unneeded-not', emitted - when an expression with the not operator could be simplified. - Closes issue #670. - - * Added a new refactoring warning, 'simplifiable-if-statement', - used when an if statement could be reduced to a boolean evaluation - of its test. Closes issue #698. - - * Added a new refactoring warning, 'too-many-boolean-expressions', - used when an if statement contains too many boolean expressions, - which makes the code less maintainable and harder to understand. - Closes issue #677. - - * Property methods are shown as attributes instead of functions in - pyreverse class diagrams. Closes Issue #284 - - * Add a new refactoring error, 'too-many-nested-blocks', which is emitted - when a function or a method has too many nested blocks, which makes the - code less readable and harder to understand. Closes issue #668. - - * Add a new error, 'unsubscriptable-object', that is emitted when - value used in subscription expression doesn't support subscription - (i.e. doesn't define __getitem__ method). - - * Don't warn about abstract classes instantiated in their own - body. Closes issue #627. - - * Obsolete options are not present by default in the generated - configuration file. Closes issue #632. - - * non-iterator-returned can detect classes with iterator-metaclasses. - Closes issue #679. - - * Add a new error, 'unsupported-membership-test', emitted when value - to the right of the 'in' operator doesn't support membership test - protocol (i.e. doesn't define __contains__/__iter__/__getitem__) - - * Add new errors, 'not-an-iterable', emitted when non-iterable value - is used in an iterating context (starargs, for-statement, - comprehensions, etc), and 'not-a-mapping', emitted when non-mapping - value is used in a mapping context. Closes issue #563. - - * Make 'no-self-use' checker not emit a warning if there is a 'super()' - call inside the method. - Closes issue #667. - - * Add checker to identify multiple imports on one line. - Closes issue #598. - - * Fix unused-argument false positive when the "+=" operator is used. - Closes issue #518. - - * Don't emit import-error for ignored modules. PyLint will not emit import - errors for any import which is, or is a subpackage of, a module in - the ignored-modules list. Closes issue #223. - - * Fix unused-import false positive when the import is used in a - class assignment. Closes issue #475 - - * Add a new error, 'not-context-manager', emitted when something - that doesn't implement __enter__ and __exit__ is used in a with - statement. - - * Add a new warning, 'confusing-with-statement', emitted by the - base checker, when an ambiguous looking with statement is used. - For example `with open() as first, second` which looks like a - tuple assignment but is actually 2 context managers. - - * Add a new warning, 'duplicate-except', emitted when there is an - exception handler which handles an exception type that was handled - before. Closes issue #485. - - * A couple of warnings got promoted to errors, since they could uncover - potential bugs in the code. These warnings are: assignment-from-none, - unbalanced-tuple-unpacking, unpacking-non-sequence, non-iterator-returned. - Closes issue #388. - - * Allow ending a pragma control with a semicolon. In this way, users - can continue a pragma control with a reason for why it is used, - as in `# pylint: disable=old-style-class;reason=...`. - Closes issue #449. - - * --jobs can be used with --load-plugins now. Closes issue #456. - - * Improve the performance of --jobs when dealing only with a package - name. Closes issue #479. - - * Don't emit an unused-wildcard-import when the imported name comes - from another module and it is in fact a __future__ name. - - * The colorized reporter now works on Windows. Closes issue #96. - - * Remove pointless-except warning. It was previously disabled by - default and it wasn't very useful. Closes issue #506. - - * Fix a crash on Python 3 related to the string checker, which - crashed when it encountered a bytes string with a .format - method called. - - * Don't warn about no-self-use for builtin properties. - - * Fix a false positive for bad-reversed-sequence, when a subclass - of a `dict` provides a __reversed__ method. - - * Change the default no-docstring-rgx so missing-docstring isn't - emitted for private functions. - - * Don't emit redefined-outer-name for __future__ directives. - Closes issue #520. - - * Provide some hints for the bad-builtin message. Closes issue #522. - - * When checking for invalid arguments to a callable, in typecheck.py, - look up for the __init__ in case the found __new__ comes from builtins. - - Since the __new__ comes from builtins, it will not have attached any - information regarding what parameters it expects, so the check - will be useless. Retrieving __init__ in that case will at least - detect a couple of false negatives. Closes issue #429. - - * Don't emit no-member for classes with unknown bases. - - Since we don't know what those bases might add, we simply ignore - the error in this case. - - * Lookup in the implicit metaclass when checking for no-member, - if the class in question has an implicit metaclass, which is - True for new style classes. Closes issue #438. - - * Add two new warnings, duplicate-bases and inconsistent-mro. - - duplicate-bases is emitted when a class has the same bases - listed more than once in its bases definition, while inconsistent-mro - is emitted when no sane mro hierarchy can be determined. Closes issue #526. - - * Remove interface-not-implemented warning. Closes issue #532. - - * Remove the rest of interface checks: interface-is-not-class, - missing-interface-method, unresolved-interface. The reason is that - its better to start recommending ABCs instead of the old Zope era - of interfaces. One side effect of this change is that ignore-iface-methods - becomes a noop, it's deprecated and it will be removed at some time. - - * Emit a proper deprecation warning for reporters.BaseReporter.add_message. - - The alternative way is to use handle_message. add_message will be removed in - Pylint 1.6. - - * Added new module 'extensions' for optional checkers with the test - directory 'test/extensions' and documentation file 'doc/extensions.rst'. - - * Added new checker 'extensions.check_docs' that verifies parameter - documention in Sphinx, Google, and Numpy style. - - * Detect undefined variable cases, where the "definition" of an undefined - variable was in del statement. Instead of emitting used-before-assignment, - which is totally misleading, it now emits undefined-variable. - Closes issue #528. - - * Don't emit attribute-defined-outside-init and access-member-before-definition - for mixin classes. Actual errors can occur in mixin classes, but this is - controlled by the ignore-mixin-members option. Closes issue #412. - - * Improve the detection of undefined variables and variables used before - assignment for variables used as default arguments to function, - where the variable was first defined in the class scope. - Closes issue #342 and issue #404. - - * Add a new warning, 'unexpected-special-method-signature', which is emitted - when a special method (dunder method) doesn't have the expected signature, - which can lead to actual errors in the application code. - Closes issue #253. - - * Remove 'bad-context-manager' due to the inclusion of 'unexpected-special-method-signature'. - - * Don't emit no-name-in-module if the import is guarded by an ImportError, Exception or - a bare except clause. - - * Don't emit no-member if the attribute access node is protected by an - except handler, which handles AttributeError, Exception or it is a - bare except. - - * Don't emit import-error if the import is guarded by an ImportError, Exception or a - bare except clause. - - * Don't emit undefined-variable if the node is guarded by a NameError, Exception - or bare except clause. - - * Add a new warning, 'using-constant-test', which is emitted when a conditional - statement (If, IfExp) uses a test which is always constant, such as numbers, - classes, functions etc. This is most likely an error from the user's part. - Closes issue #524. - - * Don't emit 'raising-non-exception' when the exception has unknown - bases. We don't know what those bases actually are and it's better - to assume that the user knows what he is doing rather than emitting - a message which can be considered a false positive. - - * Look for a .pylintrc configuration file in the current folder, - if pylintrc is not found. Dotted pylintrc files will not be searched - in the parents of the current folder, as it is done for pylintrc. - - * Add a new error, 'invalid-unary-type-operand', emitted when - an unary operand is used on something which doesn't support that - operation (for instance, using the unary bitwise inversion operator - on an instance which doesn't implement __invert__). - - * Take in consideration differences between arguments of various - type of functions (classmethods, staticmethods, properties) - when checking for `arguments-differ`. Closes issue #548. - - * astroid.inspector was moved to pylint.pyreverse, since it belongs - there and it doesn't need to be in astroid. - - * astroid.utils.LocalsVisitor was moved to pylint.pyreverse.LocalsVisitor. - - * pylint.checkers.utils.excepts_import_error was removed. - Use pylint.chekcers.utils.error_of_type instead. - - * Don't emit undefined-all-variables for nodes which can't be - inferred (YES nodes). - - * yield-outside-func is also emitted for `yield from`. - - * Add a new error, 'too-many-star-expressions', emitted when - there are more than one starred expression (`*x`) in an assignment. - The warning is emitted only on Python 3. - - * Add a new error, 'invalid-star-assignment-target', emitted when - a starred expression (`*x`) is used as the lhs side of an assignment, - as in `*x = [1, 2]`. This is not a SyntaxError on Python 3 though. - - * Detect a couple of objects which can't be base classes (bool, - slice, range and memoryview, which weren't detected until now). - - * Add a new error for the Python 3 porting checker, `import-star-module-level`, - which is used when a star import is detected in another scope than the - module level, which is an error on Python 3. Using this will emit a - SyntaxWarning on Python 2. - - * Add a new error, 'star-needs-assignment-target', emitted on Python 3 when - a Starred expression (`*x`) is not used in an assignment target. This is not - caught when parsing the AST on Python 3, so it needs to be a separate check. - - * Add a new error, 'unsupported-binary-operation', emitted when - two a binary arithmetic operation is executed between two objects - which don't support it (a number plus a string for instance). - This is currently disabled, since the it exhibits way too many false - positives, but it will be reenabled as soon as possible. - - * New imported features from astroid into pyreverse: pyreverse.inspector.Project, - pyreverse.inspector.project_from_files and pyreverse.inspector.interfaces. - - These were moved since they didn't belong in astroid. - - * Enable misplaced-future for Python 3. Closes issue #580. - - * Add a new error, 'nonlocal-and-global', which is emitted when a - name is found to be both nonlocal and global in the same scope. - Closes issue #581. - - * ignored-classes option can work with qualified names (ignored-classes=optparse.Values) - Closes issue #297. - - * ignored-modules can work with qualified names as well as with Unix pattern - matching for recursive ignoring. Closes issues #244. - - * Improve detection of relative imports in non-packages, as well as importing - missing modules with a relative import from a package. - - * Don't emit no-init if not all the bases from a class are known. - Closes issue #604. - - * --no-space-check option accepts `empty-line` as a possible option. - Closes issue #541. - - * --generate-rcfile generates by default human readable symbols - for the --disable option. Closes issue #608. - - * Improved the not-in-loop checker to properly detect more cases. - - * Add a new error, 'continue-in-finally', which is emitted when - the `continue` keyword is found inside a `finally` clause, which - is a SyntaxError. - - * The --zope flag is deprecated and it is slated for removal - in Pylint 1.6. - - The reason behind this removal is the fact that it's a specialized - flag and there are solutions for the original problem: - use --generated-members with the members that causes problems - when using Zope or add AST transforms tailored to the zope - project. - - At the same time, --include-ids and --symbols will also be removed - in Pylint 1.6. Closes issue #570. - - * missing-module-attribute was removed and the corresponding - CLI option, required-attributes, which is slated for removal - in Pylint 1.6. - - * missing-reversed-argument was removed. - - The reason behind this is that this kind of errors should be - detected by the type checker for *all* the builtins and not - as a special case for the reversed builtin. This will happen - shortly in the future. - - * --comment flag is obsolete and it will be removed in Pylint 1.6. - - * --profile flag is obsolete and it will be removed in Pylint 1.6. - - * Add a new error, 'misplaced-bare-raise'. - - The error is used when a bare raise is not used inside an except clause. - This can generate a RuntimeError in Python, if there are no active exceptions - to be reraised. While it works in Python 2 due to the fact that the exception - leaks outside of the except block, it's nevertheless a behaviour that - a user shouldn't depend upon, since it's not obvious to the reader of the code - what exception will be raised and it will not be compatible with Python 3 anyhow. - Closes issue #633. - - * Bring logilab-common's ureports into pylint.reporters. - - With this change, we moved away from depending on logilab-common, - having in Pylint all the components that were used from logilab-common. - The API should be considered an implementation detail and can change at - some point in the future. - Closes issue #621. - - * `reimported` is emitted for reimported objects on the same line. - - Closes issue #639. - - * Abbreviations of command line options are not supported anymore. - - Using abbreviations for CLI options was never considered to be - a feature of pylint, this fact being only a side effect of using optparse. - As this was the case, using --load-plugin or other abbreviation - for --load-plugins never actually worked, while it also didn't raise - an error. Closes issue #424. - - * Add a new error, 'nonlocal-without-binding' - - The error is emitted on Python 3 when a nonlocal name is not bound - to any variable in the parents scopes. Closes issue #582. - - * 'deprecated-module' can be shown for modules which aren't - available. Closes issue #362. - - * Don't consider a class abstract if its members can't - be properly inferred. - - This fixes a false positive related to abstract-class-instantiated. - Closes issue #648. - - * Add a new checker for the async features added by PEP 492. - - * Add a new error, 'yield-inside-async-function', emitted on - Python 3.5 and upwards when the `yield` statement is found inside - a new coroutine function (PEP 492). - - * Add a new error, 'not-async-context-manager', emitted when - an async context manager block is used with an object which doesn't - support this protocol (PEP 492). - - * Add a new convention warning, 'singleton-comparison', emitted when - comparison to True, False or None is found. - - * Don't emit 'assigning-non-slot' for descriptors. Closes issue #652. - - * Add a new error, 'repeated-keyword', when a keyword argument is passed - multiple times into a function call. - - This is similar with redundant-keyword-arg, but it's mildly different - that it needs to be a separate error. - - * --enable=all can now be used. Closes issue #142. - - * Add a new convention message, 'misplaced-comparison-constant', - emitted when a constant is placed in the left hand side of a comparison, - as in '5 == func()'. This is also called Yoda condition, since the - flow of code reminds of the Star Wars green character, conditions usually - encountered in languages with variabile assignments in conditional - statements. - - * Add a new convention message, 'consider-using-enumerate', which is - emitted when code that uses `range` and `len` for iterating is encountered. - Closes issue #684. - - * Added two new refactoring messages, 'no-classmethod-decorator' and - 'no-staticmethod-decorator', which are emitted when a static method or a class - method is declared without using decorators syntax. - - Closes issue #675. - - - -What's New in Pylint 1.4.3? -=========================== - -Release date: 2015-03-14 - - - * Remove three warnings: star-args, abstract-class-little-used, - abstract-class-not-used. These warnings don't add any real value - and they don't imply errors or problems in the code. - - * Added a new option for controlling the peephole optimizer in astroid. - The option ``--optimize-ast`` will control the peephole optimizer, - which is used to optimize a couple of AST subtrees. The current problem - solved by the peephole optimizer is when multiple joined strings, - with the addition operator, are encountered. If the numbers of such - strings is high enough, Pylint will then fail with a maximum recursion - depth exceeded error, due to its visitor architecture. The peephole - just transforms such calls, if it can, into the final resulting string - and this exhibit a problem, because the visit_binop method stops being - called (in the optimized AST it will be a Const node). - - -What's New in Pylint 1.4.2? -=========================== - -Release date: 2015-03-11 - - * Don't require a docstring for empty modules. Closes issue #261. - - * Fix a false positive with `too-few-format-args` string warning, - emitted when the string format contained a normal positional - argument ('{0}'), mixed with a positional argument which did - an attribute access ('{0.__class__}'). - Closes issue #463. - - * Take in account all the methods from the ancestors - when checking for too-few-public-methods. Closes issue #471. - - * Catch enchant errors and emit 'invalid-characters-in-docstring' - when checking for spelling errors. Closes issue #469. - - * Use all the inferred statements for the super-init-not-called - check. Closes issue #389. - - * Add a new warning, 'unichr-builtin', emitted by the Python 3 - porting checker, when the unichr builtin is found. Closes issue #472. - - * Add a new warning, 'intern-builtin', emitted by the Python 3 - porting checker, when the intern builtin is found. Closes issue #473. - - * Add support for editable installations. - - * The HTML output accepts the `--msg-template` option. Patch by - Dan Goldsmith. - - * Add 'map-builtin-not-iterating' (replacing 'implicit-map-evaluation'), - 'zip-builtin-not-iterating', 'range-builtin-not-iterating', and - 'filter-builtin-not-iterating' which are emitted by `--py3k` when the - appropriate built-in is not used in an iterating context (semantics - taken from 2to3). - - * Add a new warning, 'unidiomatic-typecheck', emitted when an explicit - typecheck uses type() instead of isinstance(). For example, - `type(x) == Y` instead of `isinstance(x, Y)`. Patch by Chris Rebert. - Closes issue #299. - - * Add support for combining the Python 3 checker mode with the --jobs - flag (--py3k and --jobs). Closes issue #467. - - * Add a new warning for the Python 3 porting checker, 'using-cmp-argument', - emitted when the `cmp` argument for the `list.sort` or `sorted builtin` - is encountered. - - * Make the --py3k flag commutative with the -E flag. Also, this patch - fixes the leaks of error messages from the Python 3 checker when - the errors mode was activated. Closes issue #437. - - -What's New in Pylint 1.4.1? -=========================== - -Release date: 2015-01-16 - - * Look only in the current function's scope for bad-super-call. - Closes issue #403. - - * Check the return of properties when checking for not-callable. - Closes issue #406. - - * Warn about using the input() or round() built-ins for Python 3. - Closes issue #411. - - * Proper abstract method lookup while checking for - abstract-class-instantiated. Closes issue #401. - - * Use a mro traversal for finding abstract methods. Closes issue #415. - - * Fix a false positive with catching-non-exception and tuples of - exceptions. - - * Fix a false negative with raising-non-exception, when the raise used - an uninferrable exception context. - - * Fix a false positive on Python 2 for raising-bad-type, when - raising tuples in the form 'raise (ZeroDivisionError, None)'. - - * Fix a false positive with invalid-slots-objects, where the slot entry - was a unicode string on Python 2. Closes issue #421. - - * Add a new warning, 'redundant-unittest-assert', emitted when using - unittest's methods assertTrue and assertFalse with constant value - as argument. Patch by Vlad Temian. - - * Add a new JSON reporter, usable through -f flag. - - * Add the method names for the 'signature-differs' and 'argument-differs' - warnings. Closes issue #433. - - * Don't compile test files when installing. - - * Fix a crash which occurred when using multiple jobs and the files - given as argument didn't exist at all. - - -What's New in Pylint 1.4.0? -============================ - -Release date: 2014-11-23 - - - * Added new options for controlling the loading of C extensions. - By default, only C extensions from the stdlib will be loaded - into the active Python interpreter for inspection, because they - can run arbitrary code on import. The option - `--extension-pkg-whitelist` can be used to specify modules - or packages that are safe to load. - - * Change default max-line-length to 100 rather than 80 - - * Drop BaseRawChecker class which were only there for backward - compat for a while now - - * Don't try to analyze string formatting with objects coming from - function arguments. Closes issue #373. - - * Port source code to be Python 2/3 compatible. This drops the - need for 2to3, but does drop support for Python 2.5. - - * Each message now comes with a confidence level attached, and - can be filtered base on this level. This allows to filter out - all messages that were emitted even though an inference failure - happened during checking. - - * Improved presenting unused-import message. Closes issue #293. - - * Add new checker for finding spelling errors. New messages: - wrong-spelling-in-comment, wrong-spelling-in-docstring. - New options: spelling-dict, spelling-ignore-words. - - * Add new '-j' option for running checks in sub-processes. - - * Added new checks for line endings if they are mixed (LF vs CRLF) - or if they are not as expected. New messages: mixed-line-endings, - unexpected-line-ending-format. New option: expected-line-ending-format. - - * 'dangerous-default-value' no longer evaluates the value of the arguments, - which could result in long error messages or sensitive data being leaked. - Closes issue #282 - - * Fix a false positive with string formatting checker, when - encountering a string which uses only position-based arguments. - Closes issue #285. - - * Fix a false positive with string formatting checker, when using - keyword argument packing. Closes issue #288. - - * Proper handle class level scope for lambdas. - - * Handle 'too-few-format-args' or 'too-many-format-args' for format - strings with both named and positional fields. Closes issue #286. - - * Analyze only strings by the string format checker. Closes issue #287. - - * Properly handle nested format string fields. Closes issue #294. - - * Don't emit 'attribute-defined-outside-init' if the attribute - was set by a function call in a defining method. Closes issue #192. - - * Properly handle unicode format strings for Python 2. - Closes issue #296. - - * Don't emit 'import-error' if an import was protected by a try-except, - which excepted ImportError. - - * Fix an 'unused-import' false positive, when the error was emitted - for all the members imported with 'from import' form. - Closes issue #304. - - * Don't emit 'invalid-name' when assigning a name in an - ImportError handler. Closes issue #302. - - * Don't count branches from nested functions. - - * Fix a false positive with 'too-few-format-args', when the format - strings contains duplicate manual position arguments. - Closes issue #310. - - * fixme regex handles comments without spaces after the hash. - Closes issue #311. - - * Don't emit 'unused-import' when a special object is imported - (__all__, __doc__ etc.). Closes issue #309. - - * Look in the metaclass, if defined, for members not found in the current - class. Closes issue #306. - - * Don't emit 'protected-access' if the attribute is accessed using - a property defined at the class level. - - * Detect calls of the parent's __init__, through a binded super() call. - - * Check that a class has an explicitly defined metaclass before - emitting 'old-style-class' for Python 2. - - * Emit 'catching-non-exception' for non-class nodes. Closes issue #303. - - * Order of reporting is consistent. - - * Add a new warning, 'boolean-datetime', emitted when an instance - of 'datetime.time' is used in a boolean context. Closes issue #239. - - * Fix a crash which occurred while checking for 'method-hidden', - when the parent frame was something different than a function. - - * Generate html output for missing files. Closes issue #320. - - * Fix a false positive with 'too-many-format-args', when the format - string contains mixed attribute access arguments and manual - fields. Closes issue #322. - - * Extend the cases where 'undefined-variable' and 'used-before-assignment' - can be detected. Closes issue #291. - - * Add support for customising callback identifiers, by adding a new - '--callbacks' command line option. Closes issue #326. - - * Add a new warning, 'logging-format-interpolation', emitted when .format() - string interpolation is used within logging function calls. - - * Don't emit 'unbalanced-tuple-unpacking' when the rhs of the assignment - is a variable length argument. Closes issue #329. - - * Add a new warning, 'inherit-non-class', emitted when a class inherits - from something which is not a class. Closes issue #331. - - * Fix another false positives with 'undefined-variable', where the variable - can be found as a class assignment and used in a function annotation. - Closes issue #342. - - * Handle assignment of the string format method to a variable. - Closes issue #351. - - * Support wheel packaging format for PyPi. Closes issue #334. - - * Check that various built-ins that do not exist in Python 3 are not - used: apply, basestring, buffer, cmp, coerce, execfile, file, long - raw_input, reduce, StandardError, unicode, reload and xrange. - - * Warn for magic methods which are not used in any way in Python 3: - __coerce__, __delslice__, __getslice__, __setslice__, __cmp__, - __oct__, __nonzero__ and __hex__. - - * Don't emit 'assigning-non-slot' when the assignment is for a property. - Closes issue #359. - - * Fix for regression: '{path}' was no longer accepted in '--msg-template'. - - * Report the percentage of all messages, not just for errors and warnings. - Closes issue #319. - - * 'too-many-public-methods' is reported only for methods defined in a class, - not in its ancestors. Closes issue #248. - - * 'too-many-lines' disable pragma can be located on any line, not only the - first. Closes issue #321. - - * Warn in Python 2 when an import statement is found without a - corresponding `from __future__ import absolute_import`. - - * Warn in Python 2 when a non-floor division operation is found without - a corresponding `from __future__ import division`. - - * Add a new option, 'exclude-protected', for excluding members - from the protected-access warning. Closes issue #48. - - * Warn in Python 2 when using dict.iter*(), dict.view*(); none of these - methods are available in Python 3. - - * Warn in Python 2 when calling an object's next() method; Python 3 uses - __next__() instead. - - * Warn when assigning to __metaclass__ at a class scope; in Python 3 a - metaclass is specified as an argument to the 'class' statement. - - * Warn when performing parameter tuple unpacking; it is not supported in - Python 3. - - * 'abstract-class-instantiated' is also emitted for Python 2. - It was previously disabled. - - * Add 'long-suffix' error, emitted when encountering the long suffix - on numbers. - - * Add support for disabling a checker, by specifying an 'enabled' - attribute on the checker class. - - * Add a new CLI option, --py3k, for enabling Python 3 porting mode. This - mode will disable all other checkers and will emit warnings and - errors for constructs which are invalid or removed in Python 3. - - * Add 'old-octal-literal' to Python 3 porting checker, emitted when - encountering octals with the old syntax. - - * Add 'implicit-map-evaluation' to Python 3 porting checker, emitted - when encountering the use of map builtin, without explicit evaluation. - - - -What's New in Pylint 1.3.0? -=========================== - -Release date: 2014-07-26 - - * Allow hanging continued indentation for implicitly concatenated - strings. Closes issue #232. - - * Pylint works under Python 2.5 again, and its test suite passes. - - * Fix some false positives for the cellvar-from-loop warnings. - Closes issue #233. - - * Return new astroid class nodes when the inferencer can detect that - that result of a function invocation on a type (like `type` or - `abc.ABCMeta`) is requested. Closes #205. - - * Emit 'undefined-variable' for undefined names when using the - Python 3 `metaclass=` argument. - - * Checkers respect priority now. Close issue #229. - - * Fix a false positive regarding W0511. Closes issue #149. - - * Fix unused-import false positive with Python 3 metaclasses (#143). - - * Don't warn with 'bad-format-character' when encountering - the 'a' format on Python 3. - - * Add multiple checks for PEP 3101 advanced string formatting: - 'bad-format-string', 'missing-format-argument-key', - 'unused-format-string-argument', 'format-combined-specification', - 'missing-format-attribute' and 'invalid-format-index'. - - * Issue broad-except and bare-except even if the number - of except handlers is different than 1. Fixes issue #113. - - * Issue attribute-defined-outside-init for all cases, not just - for the last assignment. Closes issue #262. - - * Emit 'not-callable' when calling properties. Closes issue #268. - - * Fix a false positive with unbalanced iterable unpacking, - when encountering starred nodes. Closes issue #273. - - * Add new checks, 'invalid-slice-index' and 'invalid-sequence-index' - for invalid sequence and slice indices. - - * Add 'assigning-non-slot' warning, which detects assignments to - attributes not defined in slots. - - * Don't emit 'no-name-in-module' for ignored modules. - Closes issue #223. - - * Fix an 'unused-variable' false positive, where the variable is - assigned through an import. Closes issue #196. - - * Definition order is considered for classes, function arguments - and annotations. Closes issue #257. - - * Don't emit 'unused-variable' when assigning to a nonlocal. - Closes issue #275. - - * Do not let ImportError propagate from the import checker, leading to crash - in some namespace package related cases. Closes issue #203. - - * Don't emit 'pointless-string-statement' for attribute docstrings. - Closes issue #193. - - * Use the proper mode for pickle when opening and writing the stats file. - Closes issue #148. - - * Don't emit hidden-method message when the attribute has been - monkey-patched, you're on your own when you do that. - - * Only emit attribute-defined-outside-init for definition within the same - module as the offended class, avoiding to mangle the output in some cases. - - * Don't emit 'unnecessary-lambda' if the body of the lambda call contains - call chaining. Closes issue #243. - - * Don't emit 'missing-docstring' when the actual docstring uses `.format`. - Closes issue #281. - - -What's New in Pylint 1.2.1? -=========================== - -Release date: 2014-04-30 - - * Restore the ability to specify the init-hook option via the - configuration file, which was accidentally broken in 1.2.0. - - * Add a new warning [bad-continuation] for badly indentend continued - lines. - - * Emit [assignment-from-none] when the function contains bare returns. - Fixes BitBucket issue #191. - - * Added a new warning for closing over variables that are - defined in loops. Fixes Bitbucket issue #176. - - * Do not warn about \u escapes in string literals when Unicode literals - are used for Python 2.*. Fixes BitBucket issue #151. - - * Extend the checking for unbalanced-tuple-unpacking and - unpacking-non-sequence to instance attribute unpacking as well. - - * Fix explicit checking of python script (1.2 regression, #219) - - * Restore --init-hook, renamed accidentally into --init-hooks in 1.2.0 - (#211) - - * Add 'indexing-exception' warning, which detects that indexing - an exception occurs in Python 2 (behaviour removed in Python 3). - - -What's New in Pylint 1.2.0? -=========================== - -Release date: 2014-04-18 - - * Pass the current python paths to pylint process when invoked via - epylint. Fixes BitBucket issue #133. - - * Add -i / --include-ids and -s / --symbols back as completely ignored - options. Fixes BitBucket issue #180. - - * Extend the number of cases in which logging calls are detected. Fixes - bitbucket issue #182. - - * Improve pragma handling to not detect pylint:* strings in non-comments. - Fixes BitBucket issue #79. - - * Do not crash with UnknownMessage if an unknown message ID/name appears - in disable or enable in the configuration. Patch by Cole Robinson. - Fixes bitbucket issue #170. - - * Add new warning 'eval-used', checking that the builtin function `eval` - was used. - - * Make it possible to show a naming hint for invalid name by setting - include-naming-hint. Also make the naming hints configurable. Fixes - BitBucket issue #138. - - * Added support for enforcing multiple, but consistent name styles for - different name types inside a single module; based on a patch written - by morbo@google.com. - - * Also warn about empty docstrings on overridden methods; contributed - by sebastianu@google.com. - - * Also inspect arguments to constructor calls, and emit relevant - warnings; contributed by sebastianu@google.com. - - * Added a new configuration option logging-modules to make the list - of module names that can be checked for 'logging-not-lazy' et. al. - configurable; contributed by morbo@google.com. - - * ensure init-hooks is evaluated before other options, notably load-plugins - (#166) - - * Python 2.5 support restored: fixed small issues preventing pylint to run - on python 2.5. Bitbucket issues #50 and #62. - - * bitbucket #128: pylint doesn't crash when looking - for used-before-assignment in context manager - assignments. - - * Add new warning, 'bad-reversed-sequence', for checking that the - reversed() builtin receive a sequence (implements __getitem__ and __len__, - without being a dict or a dict subclass) or an instance which implements - __reversed__. - - * Mark `file` as a bad function when using python2 (closes #8). - - * Add new warning 'bad-exception-context', checking - that `raise ... from ...` uses a proper exception context - (None or an exception). - - * Enhance the check for 'used-before-assignment' to look - for 'nonlocal' uses. - - * Emit 'undefined-all-variable' if a package's __all__ - variable contains a missing submodule (closes #126). - - * Add a new warning 'abstract-class-instantiated' for checking - that abstract classes created with `abc` module and - with abstract methods are instantied. - - * Do not warn about 'return-arg-in-generator' in Python 3.3+. - - * Do not warn about 'abstract-method' when the abstract method - is implemented through assignment (#155). - - * Improve cyclic import detection in the case of packages, patch by Buck - Golemon - - * Add new warnings for checking proper class __slots__: - `invalid-slots-object` and `invalid-slots`. - - * Search for rc file in `~/.config/pylintrc` if `~/.pylintrc` - doesn't exists (#121) - - * Don't register the newstyle checker w/ python >= 3 - - * Fix unused-import false positive w/ augment assignment (#78) - - * Fix access-member-before-definition false negative wrt aug assign (#164) - - * Do not attempt to analyze non python file, eg .so file (#122) - - -What's New in Pylint 1.1.0? -=========================== - -Release date: 2013-12-22 - - * Add new check for use of deprecated pragma directives "pylint:disable-msg" - or "pylint:enable-msg" (I0022, deprecated-pragma) which was previously - emitted as a regular warn(). - - * Avoid false used-before-assignment for except handler defined - identifier used on the same line (#111). - - * Combine 'no-space-after-operator', 'no-space-after-comma' and - 'no-space-before-operator' into a new warning 'bad-whitespace'. - - * Add a new warning 'superfluous-parens' for unnecessary - parentheses after certain keywords. - - * Fix a potential crash in the redefine-in-handler warning - if the redefined name is a nested getattr node. - - * Add a new option for the multi-statement warning to - allow single-line if statements. - - * Add 'bad-context-manager' error, checking that '__exit__' - special method accepts the right number of arguments. - - * Run pylint as a python module 'python -m pylint' (anatoly techtonik). - - * Check for non-exception classes inside an except clause. - - * epylint support options to give to pylint after the file to analyze and - have basic input validation (bitbucket #53 and #54), patches provided by - felipeochoa and Brian Lane. - - * Added a new warning, 'non-iterator-returned', for non-iterators - returned by '__iter__'. - - * Add new checks for unpacking non-sequences in assignments - (unpacking-non-sequence) as well as unbalanced tuple unpacking - (unbalanced-tuple-unpacking). - - * useless-else-on-loop not emitted if there is a break in the - else clause of inner loop (#117). - - * don't mark `input` as a bad function when using python3 (#110). - - * badly-implemented-container caused several problems in its - current implementation. Deactivate it until we have something - better. See #112 for instance. - - * Use attribute regexp for properties in python3, as in python2 - - * Create the PYLINTHOME directory when needed, it might fail and lead to - spurious warnings on import of pylint.config. - - * Fix setup.py so that pylint properly install on Windows when using python3 - - * Various documentation fixes and enhancements - - * Fix issue #55 (false-positive trailing-whitespace on Windows) - - -What's New in Pylint 1.0.0? -=========================== - -Release date: 2013-08-06 - - - * Add check for the use of 'exec' function - - * New --msg-template option to control output, deprecating "msvc" and - "parseable" output formats as well as killing `--include-ids` and `--symbols` - options - - * Do not emit [fixme] for every line if the config value 'notes' - is empty, but [fixme] is enabled. - - * Emit warnings about lines exceeding the column limit when - those lines are inside multiline docstrings. - - * Do not double-check parameter names with the regex for parameters and - inline variables. - - * Added a new warning missing-final-newline (C0304) for files missing - the final newline. - - * Methods that are decorated as properties are now treated as attributes - for the purposes of name checking. - - * Names of derived instance class member are not checked any more. - - * Names in global statements are now checked against the regular - expression for constants. - - * For toplevel name assignment, the class name regex will be used if - pylint can detect that value on the right-hand side is a class - (like collections.namedtuple()). - - * Simplified invalid-name message - - * Added a new warning invalid-encoded-data (W0512) for files that - contain data that cannot be decoded with the specified or - default encoding. - - * New warning bad-open-mode (W1501) for calls to open (or file) that - specify invalid open modes (Original implementation by Sasha Issayev). - - * New warning old-style-class (C1001) for classes that do not have any - base class. - - * Add new name type 'class_attribute' for attributes defined - in class scope. By default, allow both const and variable names. - - * New warning trailing-whitespace (C0303) that warns about - trailing whitespace. - - * Added a new warning unpacking-in-except (W0712) about unpacking - exceptions in handlers, which is unsupported in Python 3. - - * Add a configuration option for missing-docstring to - optionally exempt short functions/methods/classes from - the check. - - * Add the type of the offending node to missing-docstring - and empty-docstring. - - * New utility classes for per-checker unittests in testutils.py - - * Do not warn about redefinitions of variables that match the - dummy regex. - - * Do not treat all variables starting with _ as dummy variables, - only _ itself. - - * Make the line-too-long warning configurable by adding a regex for lines - for with the length limit should not be enforced - - * Do not warn about a long line if a pylint disable - option brings it above the length limit - - * Do not flag names in nested with statements as undefined. - - * Added a new warning 'old-raise-syntax' for the deprecated syntax - raise Exception, args - - * Support for PEP 3102 and new missing-kwoa (E1125) message for missing - mandatory keyword argument (logilab.org's #107788) - - * Fix spelling of max-branchs option, now max-branches - - * Added a new base class and interface for checkers that work on the - tokens rather than the syntax, and only tokenize the input file - once. - - * Follow astng renaming to astroid - - * bitbucket #37: check for unbalanced unpacking in assignments - - * bitbucket #25: fix incomplete-protocol false positive for read-only - containers like tuple - - * bitbucket #16: fix False positive E1003 on Python 3 for argument-less super() - - * bitbucket #6: put back documentation in source distribution - - * bitbucket #15: epylint shouldn't hang anymore when there is a large - output on pylint'stderr - - * bitbucket #7: fix epylint w/ python3 - - * bitbucket #3: remove string module from the default list of deprecated - modules - - -What's New in Pylint 0.28.0? -============================ - -Release date: 2013-04-25 - - * bitbucket #1: fix "dictionary changed size during iteration" crash - - * #74013: new E1310[bad-str-strip-call] message warning when a call to a - {l,r,}strip method contains duplicate characters (patch by Torsten Marek) - - * #123233: new E0108[duplicate-argument-name] message reporting duplicate - argument names - - * #81378: emit W0120[useless-else-on-loop] for loops without break - - * #124660: internal dependencies should not appear in external dependencies - report - - * #124662: fix name error causing crash when symbols are included in output - messages - - * #123285: apply pragmas for warnings attached to lines to physical source - code lines - - * #123259: do not emit E0105 for yield expressions inside lambdas - - * #123892: don't crash when attempting to show source code line that can't - be encoded with the current locale settings - - * Simplify checks for dangerous default values by unifying tests for all - different mutable compound literals. - - * Improve the description for E1124[redundant-keyword-arg] - - -What's New in Pylint 0.27.0? -============================ - -Release date: 2013-02-26 - - * #20693: replace pylint.el by Ian Eure version (patch by J.Kotta) - - * #105327: add support for --disable=all option and deprecate the - 'disable-all' inline directive in favour of 'skip-file' (patch by - A.Fayolle) - - * #110840: add messages I0020 and I0021 for reporting of suppressed - messages and useless suppression pragmas. (patch by Torsten Marek) - - * #112728: add warning E0604 for non-string objects in __all__ - (patch by Torsten Marek) - - * #120657: add warning W0110/deprecated-lambda when a map/filter - of a lambda could be a comprehension (patch by Martin Pool) - - * #113231: logging checker now looks at instances of Logger classes - in addition to the base logging module. (patch by Mike Bryant) - - * #111799: don't warn about octal escape sequence, but warn about \o - which is not octal in Python (patch by Martin Pool) - - * #110839: bind to Run button in pylint-gui - - * #115580: fix erroneous W0212 (access to protected member) on super call - (patch by Martin Pool) - - * #110853: fix a crash when an __init__ method in a base class has been - created by assignment rather than direct function definition (patch by - Torsten Marek) - - * #110838: fix pylint-gui crash when include-ids is activated (patch by - Omega Weapon) - - * #112667: fix emission of reimport warnings for mixed imports and extend - the testcase (patch by Torsten Marek) - - * #112698: fix crash related to non-inferable __all__ attributes and - invalid __all__ contents (patch by Torsten Marek) - - * Python 3 related fixes: - - * #110213: fix import of checkers broken with python 3.3, causing - "No such message id W0704" breakage - - * #120635: redefine cmp function used in pylint.reporters - - * Include full warning id for I0020 and I0021 and make sure to flush - warnings after each module, not at the end of the pylint run. - (patch by Torsten Marek) - - * Changed the regular expression for inline options so that it must be - preceded by a # (patch by Torsten Marek) - - * Make dot output for import graph predictable and not depend - on ordering of strings in hashes. (patch by Torsten Marek) - - * Add hooks for import path setup and move pylint's sys.path - modifications into them. (patch by Torsten Marek) - - -What's New in Pylint 0.26.0? -============================ - -Release date: 2012-10-05 - - * #106534: add --ignore-imports option to code similarity checking - and 'symilar' command line tool (patch by Ry4an Brase) - - * #104571: check for anomalous backslash escape, introducing new - W1401 and W1402 messages (patch by Martin Pool) - - * #100707: check for boolop being used as exception class, introducing - new W0711 message (patch by Tim Hatch) - - * #4014: improve checking of metaclass methods first args, introducing - new C0204 message (patch by lothiraldan@gmail.com finalized by sthenault) - - * #4685: check for consistency of a module's __all__ variable, - introducing new E0603 message - - * #105337: allow custom reporter in output-format (patch by Kevin Jing Qiu) - - * #104420: check for protocol completness and avoid false R0903 - (patch by Peter Hammond) - - * #100654: fix grammatical error for W0332 message (using 'l' as - long int identifier) - - * #103656: fix W0231 false positive for missing call to object.__init__ - (patch by lothiraldan@gmail.com) - - * #63424: fix similarity report disabling by properly renaming it to RP0801 - - * #103949: create a console_scripts entry point to be used by - easy_install, buildout and pip - - * fix cross-interpreter issue (non compatible access to __builtins__) - - * stop including tests files in distribution, they causes crash when - installed with python3 (#72022, #82417, #76910) - - -What's New in Pylint 0.25.2? -============================ - -Release date: 2012-07-17 - - * #93591: Correctly emit warnings about clobbered variable names when an - except handler contains a tuple of names instead of a single name. - (patch by tmarek@google.com) - - * #7394: W0212 (access to protected member) not emitted on assigments - (patch by lothiraldan@gmail.com) - - * #18772; no prototype consistency check for mangled methods (patch by - lothiraldan@gmail.com) - - * #92911: emit W0102 when sets are used as default arguments in functions - (patch by tmarek@google.com) - - * #77982: do not emit E0602 for loop variables of comprehensions - used as argument values inside a decorator (patch by tmarek@google.com) - - * #89092: don't emit E0202 (attribute hiding a method) on @property methods - - * #92584: fix pylint-gui crash due to internal API change - - * #87192: fix crash when decorators are accessed through more than one dot - (for instance @a.b is fine, @a.b.c crash) - - * #88914: fix parsing of --generated-members options, leading to crash - when using a regexp value set - - * fix potential crashes with utils.safe_infer raising InferenceError - - -What's New in Pylint 0.25.1? -============================ - -Release date: 2011-12-08 - - * #81078: Warn if names in exception handlers clobber overwrite - existing names (patch by tmarek@google.com) - - * #81113: Fix W0702 messages appearing with the wrong line number. - (patch by tmarek@google.com) - - * #50461, #52020, #51222: Do not issue warnings when using 2.6's - property.setter/deleter functionality (patch by dneil@google.com) - - * #9188, #4024: Do not trigger W0631 if a loop variable is assigned - in the else branch of a for loop. - - -What's New in Pylint 0.25.0? -============================ - -Release date: 2011-10-7 - - * #74742: make allowed name for first argument of class method configurable - (patch by Google) - - * #74087: handle case where inference of a module return YES; this avoid - some cases of "TypeError: '_Yes' object does not support indexing" (patch - by Google) - - * #74745: make "too general" exception names configurable (patch by Google) - - * #74747: crash occurs when lookup up a special attribute in class scope - (patch by google) - - * #76920: crash if on eg "pylint --rcfile" (patch by Torsten Marek) - - * #77237: warning for E0202 may be very misleading - - * #73941: HTML report messages table is badly rendered - - -What's New in Pylint 0.24.0? -============================ - -Release date: 2011-07-18 - - * #69738: add regular expressions support for "generated-members" - - * ids of logging and string_format checkers have been changed: - logging: 65 -> 12, string_format: 99 -> 13 - Also add documentation to say that ids of range 1-50 shall be reserved - to pylint internal checkers - - * #69993: Additional string format checks for logging module: - check for missing arguments, too many arguments, or invalid string - formats in the logging checker module. Contributed by Daniel Arena - - * #69220: add column offset to the reports. If you've a custom reporter, - this change may break it has now location gain a new item giving the - column offset. - - * #60828: Fix false positive in reimport check - - * #70495: absolute imports fail depending on module path (patch by Jacek Konieczny) - - * #22273: Fix --ignore option documentation to match reality - - -What's New in Pylint 0.23.0? -============================ - -Release date: 2011-01-11 - - * documentation update, add manpages - - * several performance improvements - - * finalize python3 support - - * new W0106 warning 'Expression "%s" is assigned to nothing' - - * drop E0501 and E0502 messages about wrong source encoding: not anymore - interesting since it's a syntax error for python >= 2.5 and we now only - support this python version and above. - - * don't emit W0221 or W0222 when methods as variable arguments (eg \*arg - and/or \*\*args). Patch submitted by Charles Duffy. - - -What's New in Pylint 0.22.0? -============================ - -Release date: 2010-11-15 - - * python versions: minimal python3.x support; drop python < 2.5 support - - -What's New in Pylint 0.21.4? -============================ - -Release date: 2010-10-27 - - * fix #48066: pylint crashes when redirecting output containing non-ascii characters - - * fix #19799: "pylint -blah" exit with status 2 - - * update documentation - - -What's New in Pylint 0.21.3? -============================ - -Release date: 2010-09-28 - - * restored python 2.3 compatibility. Along with logilab-astng - 0.21.3 and logilab-common 0.52, this will much probably be the - latest release supporting python < 2.5. - - -What's New in Pylint 0.21.2? -============================ - -Release date: 2010-08-26 - - * fix #36193: import checker raise exception on cyclic import - - * fix #28796: regression in --generated-members introduced pylint 0.20 - - * some documentation cleanups - - -What's New in Pylint 0.21.1? -============================ - -Release date: 2010-06-04 - - * fix #28962: pylint crash with new options, due to missing stats data while - writing the Statistics by types report - - * updated man page to 0.21 or greater command line usage (fix debian #582494) - - -What's New in Pylint 0.21.0? -============================ - -Release date: 2010-05-11 - - * command line updated (closes #9774, #9787, #9992, #22962): - - * all enable-* / disable-* options have been merged into --enable / --disable - - * BACKWARD INCOMPATIBLE CHANGE: short name of --errors-only becomes -E, -e being - affected to --enable - - * pylint --help output much simplified, with --long-help available to get the - complete one - - * revisited gui, thanks to students from Toronto university (they are great - contributors to this release!) - - * fix #21591: html reporter produces no output if reports is set to 'no' - - * fix #4581: not Missing docstring (C0111) warning if a method is overridden - - * fix #4683: Non-ASCII characters count double if utf8 encode - - * fix #9018: when using defining-attr-method, method order matters - - * fix #4595: Comma not followed by a space should not occurs on trailing comma - in list/tuple/dict definition - - * fix #22585: [Patch] fix man warnings for pyreverse.1 manpage - - * fix #20067: AttributeError: 'NoneType' object has no attribute 'name' with with - - - -What's New in Pylint 0.20.0? -============================ - -Release date: 2010-03-01 - - * fix #19498: fix windows batch file - - * fix #19339: pylint.el : non existing py-mod-map - (closes Debian Bug report logs - #475939) - - * implement #18860, new W0199 message on assert (a, b) - - * implement #9776, 'W0150' break or return statement in finally block may - swallow exception. - - * fix #9263, __init__ and __new__ are checked for unused arguments - - * fix #20991, class scope definitions ignored in a genexpr - - * fix #5975, Abstract intermediate class not recognized as such - - * fix #5977, yield and return statement have their own counters, no more R0911 - (Too many return statements) when a function have many yield stamtements - - * implement #5564, function / method arguments with leading "_" are ignored in - arguments / local variables count. - - * implement #9982, E0711 specific error message when raising NotImplemented - - * remove --cache-size option - - -What's New in Pylint 0.19.0? -============================ - -Release date: 2009-12-18 - - * implement #18947, #5561: checker for function arguments - - * include James Lingard string format checker - - * include simple message (ids) listing by Vincent Ferotin (#9791) - - * --errors-only does not hide fatal error anymore - - * include james Lingard patches for ++/-- and duplicate key in dicts - - * include James Lingard patches for function call arguments checker - - * improved flymake code and doc provided by Derek Harland - - * refactor and fix the imports checker - - * fix #18862: E0601 false positive with lambda functions - - * fix #8764: More than one statement on a single line false positive with - try/except/finally - - * fix #9215: false undefined variable error in lambda function - - * fix for w0108 false positive (Nathaniel) - - * fix test/fulltest.sh - - * #5821 added a utility function to run pylint in another process (patch provide by Vincent Ferotin) - - -What's New in Pylint 0.18.0? -============================ - -Release date: 2009-03-25 - - * tests ok with python 2.4, 2.5, 2.6. 2.3 not tested - - * fix #8687, W0613 false positive on inner function - - * fix #8350, C0322 false positive on multi-line string - - * fix #8332: set E0501 line no to the first line where non ascii character - has been found - - * avoid some E0203 / E0602 false negatives by detecting respectively - AttributeError / NameError - - * implements #4037: don't issue W0142 (* or ** magic) when they are barely - passed from */** arguments - - * complete #5573: more complete list of special methods, also skip W0613 - for python internal method - - * don't show information messages by default - - * integration of Yuen Ho Wong's patches on emacs lisp files - - -What's New in Pylint 0.17.0? -============================ - -Release date: 2009-03-19 - - * semicolon check : move W0601 to W0301 - - * remove rpython : remove all rpython checker, modules and tests - - * astng 0.18 compatibility: support for _ast module modifies interfaces - - -What's New in Pylint 0.16.0? -============================ - -Release date: 2009-01-28 - - * change [en|dis]able-msg-cat options: only accept message categories - identified by their first letter (eg IRCWEF) without the need for comma - as separator - - * add epylint.bat script to fix Windows installation - - * setuptools/easy_install support - - * include a modified version of Maarten ter Huurne patch to avoid W0613 - warning on arguments from overridden method - - * implement #5575 drop dumb W0704 message) by adding W0704 to ignored - messages by default - - * new W0108 message, checking for suspicious lambda (provided by Nathaniel - Manista) - - * fix W0631, false positive reported by Paul Hachmann - - * fix #6951: false positive with W0104 - - * fix #6949 - - * patches by Mads Kiilerich: - - * implement #4691, make pylint exits with a non zero return - status if any messages other then Information are issued - - * fix #3711, #5626 (name resolution bug w/ decorator and class members) - - * fix #6954 - - -What's New in Pylint 0.15.2? -============================ - -Release date: 2008-10-13 - - * fix #5672: W0706 weirdness ( W0706 removed ) - - * fix #5998: documentation points to wrong url for mailing list - - * fix #6022: no error message on wrong module names - - * fix #6040: pytest doesn't run test/func_test.py - - -What's New in Pylint 0.15.1? -============================ - -Release date: 2008-09-15 - - * fix #4910: default values are missing in manpage - - * fix #5991: missing files in 0.15.0 tarball - - * fix #5993: epylint should work with python 2.3 - - -What's New in Pylint 0.15.0? -============================ - -Release date: 2008-09-10 - - * include pyreverse package and class diagram generation - - * included Stefan Rank's patch to deal with 2.4 relative import - - * included Robert Kirkpatrick's tutorial and typos fixes - - * fix bug in reenabling message - - * fix #2473: invoking pylint on __init__.py (hopefully) - - * typecheck: acquired-members option has been dropped in favor of the more - generic generated-members option. If the zope option is set, the behaviour - is now to add some default values to generated-members. - - * flymake integration: added bin/epylint and elisp/pylint-flymake.el - - -What's New in Pylint 0.14.0? -============================ - -Release date: 2008-01-14 - - * fix #3733: Messages (dis)appear depending on order of file names - - * fix #4026: pylint.el should require compile - - * fix a bug in colorized reporter, spotted by Dave Borowitz - - * applied patch from Stefan Rank to avoid W0410 false positive when - multiple "from __future__" import statements - - * implement #4012: flag back tick as deprecated (new W0333 message) - - * new ignored-class option on typecheck checker allowing to skip members - checking based on class name (patch provided by Thomas W Barr) - - -What's New in Pylint 0.13.2? -============================ - -Release date: 2007-06-07 - - * fix disable-checker option so that it won't accidentally enable the - rpython checker which is disabled by default - - * added note about the gedit plugin into documentation - - - -What's New in Pylint 0.13.1? -============================ - -Release date: 2007-03-02 - - * fix some unexplained 0.13.0 packaging issue which led to a bunch of - files missing from the distribution - - - -What's New in Pylint 0.13.0? -============================ - -Release date: 2007-02-28 - - * new RPython (Restricted Python) checker for PyPy fellow or people - wanting to get a compiled version of their python program using the - translator of the PyPy project. For more information about PyPy or - RPython, visit http://codespeak.net/pypy/ - - * new E0104 and E0105 messages introduced to respectively warn about - "return" and "yield" outside function or method - - * new E0106 message when "yield" and "return something" are mixed in a - function or method - - * new W0107 message for unnecessary pass statement - - * new W0614 message to differentiate between unused `import X` and - unused `from X import *` (#3209, patch submitted by Daniel Drake) - - * included Daniel Drake's patch to have a different message E1003 instead of - E1001 when a missing member is found but an inference failure has been - detected - - * msvs reporter for Visual Studio line number reporting (#3285) - - * allow disable-all option inline (#3218, patch submitted by Daniel Drake) - - * --init-hook option to call arbitrary code necessary to set - environment (eg sys.path) (#3156) - - * One more Daniel's patch fixing a command line option parsing - problem, this'll definitely be the DDrake release :) - - * fix #3184: crashes on "return" outside function - - * fix #3205: W0704 false positive - - * fix #3123: W0212 false positive on static method - - * fix #2485: W0222 false positive - - * fix #3259: when a message is explicitly enabled, check the checker - emitting it is enabled - - -What's New in Pylint 0.12.2? -============================ - -Release date: 2006-11-23 - - * fix #3143: W0233 bug w/ YES objects - - * fix #3119: Off-by-one error counting lines in a file - - * fix #3117: ease sys.stdout overriding for reporters - - * fix #2508: E0601 false positive with lambda - - * fix #3125: E1101 false positive and a message duplication. Only the last part - is actually fixed since the initial false positive is due to dynamic setting of - attributes on the decimal.Context class. - - * fix #3149: E0101 false positives and introduced E0100 for generator __init__ - methods - - * fixed some format checker false positives - - -What's New in Pylint 0.12.1? -============================ - - -Release date: 2006-09-25 - - * fixed python >= 2.4 format false positive with multiple lines statement - - * fixed some 2.5 issues - - * fixed generator expression scope bug (depends on astng 0.16.1) - - * stop requiring __revision__ - - -What's New in Pylint 0.12.0? -============================ - - -Release date: 2006-08-10 - - * usability changes: - - * parseable, html and color options are now handled by a single - output-format option - - * enable- and disable-all options are now handled by - two (exclusive) enable-checker and disable-checker options - taking a comma separated list of checker names as value - - * renamed debug-mode option to errors-only - - * started a reference user manual - - * new W0212 message for access to protected member from client code - (close #14081) - - * new W0105 and W0106 messages extracted from W0104 (statement seems - to have no effect) respectively when the statement is actually string - (that's sometimes used instead of comments for documentation) or an - empty statement generated by a useless semicolon - - * reclassified W0302 to C0302 - - * fix so that global messages are not anymore connected to the last - analyzed module (close #10106) - - * fix some bugs related to local disabling of messages - - * fix cr/lf pb when generating the rc file on windows platforms - - -What's New in Pylint 0.11.0? -============================ - -Release date: 2006-04-19 - - * fix crash caused by the exceptions checker in some case - - * fix some E1101 false positive with abstract method or classes defining - __getattr__ - - * dirty fix to avoid "_socketobject" has not "connect" member. The actual - problem is that astng isn't able to understand the code used to create - socket.socket object with exec - - * added an option in the similarity checker to ignore docstrings, enabled - by default - - * included patch from Benjamin Niemann to allow block level - enabling/disabling of messages - - -What's New in Pylint 0.10.0? -============================ - -Release date: 2006-03-06 - - * WARNING, this release include some configuration changes (see below), - so you may have to check and update your own configuration file(s) if - you use one - - * this release require the 0.15 version of astng or superior (it will save - you a lot of pylint crashes...) - - * W0705 has been reclassified to E0701, and is now detecting more - inheriting problem, and a false positive when empty except clause is - following an Exception catch has been fixed (close #10422) - - * E0212 and E0214 (metaclass/class method should have mcs/cls as first - argument have been reclassified to C0202 and C0203 since this not as - well established as "self" for instance method (E0213) - - * W0224 has been reclassified into F0220 (failed to resolve interfaces - implemented by a class) - - * a new typecheck checker, introducing the following checks: - - - E1101, access to unexistent member (implements #10430), remove - the need of E0201 and so some options has been moved from the - classes checker to this one - - E1102, calling a non callable object - - E1111 and W1111 when an assignment is done on a function call but the - inferred function returns None (implements #10431) - - * change in the base checker: - - - checks module level and instance attribute names (new const-rgx - and attr-rgx configuration option) (implements #10209 and - #10440) - - list comprehension and generator expression variables have their - own regular expression (the inlinevar-rgx option) (implements - #9146) - - the C0101 check with its min-name-length option has - been removed (this can be specified in the regxp after all...) - - W0103 and W0121 are now handled by the variables checker - (W0103 is now W0603 and W0604 has been splitted into different messages) - - W0131 and W0132 messages have been reclassified to C0111 and - C0112 respectively - - new W0104 message on statement without effect - - * regexp support for dummy-variables (dummy-variables-rgx option - replace dummy-variables) (implements #10027) - - * better global statement handling, see W0602, W0603, W0604 messages - (implements #10344 and #10236) - - * --debug-mode option, disabling all checkers without error message - and filtering others to only display error - - * fixed some R0201 (method could be a function) false positive - - -What's New in Pylint 0.9.0? -============================ - -Release date: 2006-01-10 - - * a lot of updates to follow astng 0.14 API changes, so install - logilab-astng 0.14 or greater before using this version of pylint - - * checker number 10 ! newstyle will search for problems regarding old - style / new style classes usage problems (rely on astng 0.14 new - style detection feature) - - * new 'load-plugins' options to load additional pylint plugins (usable - from the command line or from a configuration file) (implements - #10031) - - * check if a "pylintrc" file exists in the current working directory - before using the one specified in the PYLINTRC environment variable - or the default ~/.pylintrc or /etc/pylintrc - - * fixed W0706 (Identifier used to raise an exception is assigned...) - false positive and reraising a catched exception instance - - * fixed E0611 (No name get in module blabla) false positive when accessing - to a class'__dict__ - - * fixed some E0203 ("access to member before its definition") false - positive - - * fixed E0214 ("metaclass method first argument should be mcs) false - positive with staticmethod used on a metaclass - - * fixed packaging which was missing the test/regrtest_data directory - - * W0212 (method could be a function) has been reclassified in the - REFACTOR category as R0201, and is no more considerer when a method - overrides an abstract method from an ancestor class - - * include module name in W0401 (wildcard import), as suggested by - Amaury - - * when using the '--parseable', path are written relative to the - current working directory if in a sub-directory of it (#9789) - - * 'pylint --version' shows logilab-astng and logilab-common versions - - * fixed pylint.el to handle space in file names - - * misc lint style fixes - - -What's New in Pylint 0.8.1? -============================ - - -Release date: 2005-11-07 - - * fix "deprecated module" false positive when the code imports a - module whose name starts with a deprecated module's name (close - #10061) - - * fix "module has no name __dict__" false positive (close #10039) - - * fix "access to undefined variable __path__" false positive (close - #10065) - - * fix "explicit return in __init__" false positive when return is - actually in an inner function (close #10075) - - -What's New in Pylint 0.8.0? -============================ - -Release date: 2005-10-21 - - * check names imported from a module exists in the module (E0611), - patch contributed by Amaury Forgeot d'Arc - - * print a warning (W0212) for methods that could be a function - (implements #9100) - - * new --defining-attr-methods option on classes checker - - * new --acquired-members option on the classes checker, used when - --zope=yes to avoid false positive on acquired attributes (listed - using this new option) (close #8616) - - * generate one E0602 for each use of an undefined variable - (previously, only one for the first use but not for the following) - (implements #1000) - - * make profile option saveable - - * fix Windows .bat file, patch contributed by Amaury Forgeot d'Arc - - * fix one more false positive for E0601 (access before definition) - with for loop such as "for i in range(10): print i" (test - func_noerror_defined_and_used_on_same_line) - - * fix false positive for E0201 (undefined member) when accessing to - __name__ on a class object - - * fix astng checkers traversal order - - * fix bug in format checker when parsing a file from a platform - using different new line characters (close #9239) - - * fix encoding detection regexp - - * fix --rcfile handling (support for --rcfile=file, close #9590) - - -What's New in Pylint 0.7.0? -============================ - - -Release date: 2005-05-27 - - * WARNING: pylint is no longer a logilab subpackage. Users may have to - manually remove the old logilab/pylint directory. - - * introduce a new --additional-builtins option to handle user defined - builtins - - * --reports option has now -r as short alias, and -i for --include-ids - - * fix a bug in the variables checker which may causing some false - positives when variables are defined and used within the same - statement (test func_noerror_defined_and_used_on_same_line) - - * this time, real fix of the "disable-msg in the config file" problem, - test added to unittest_lint - - * fix bug with --list-messages and python -OO - - * fix possible false positive for W0201 - - -What's New in Pylint 0.6.4? -=========================== - - -Release date: 2005-04-14 - - * allow to parse files without extension when a path is given on the - command line (test noext) - - * don't fail if we are unable to read an inline option (e.g. inside a - module), just produce an information message (test func_i0010) - - * new message E0103 for break or continue outside loop (close #8883, - test func_continue_not_in_loop) - - * fix bug in the variables checker, causing non detection of some - actual name error (close #8884, test - func_nameerror_on_string_substitution) - - * fix bug in the classes checker which was making pylint crash if - "object" is assigned in a class inheriting from it (test - func_noerror_object_as_class_attribute) - - * fix problem with the similar checker when related options are - defined in a configuration file - - * new --generate-man option to generate pylint's man page (require the - latest logilab.common (>= 0.9.3) - - * packaged (generated...) man page - - -What's New in Pylint 0.6.3? -=========================== - -Release date: 2005-02-24 - - * fix scope problem which may cause false positive and true negative - on E0602 - - * fix problem with some options such as disable-msg causing error when - they are coming from the configuration file - - -What's New in Pylint 0.6.2? -============================ - - -Release date: 2005-02-16 - - * fix false positive on E0201 ("access to undefined member") with - metaclasses - - * fix false positive on E0203 ("access to member before its - definition") when attributes are defined in a parent class - - * fix false positive on W0706 ("identifier used to raise an exception - assigned to...") - - * fix interpretation of "\t" as value for the indent-string - configuration variable - - * fix --rcfile so that --rcfile=pylintrc (only --rcfile pylintrc was - working in earlier release) - - * new raw checker example in the examples/ directory - - -What's New in Pylint 0.6.1? -=========================== - -Release date: 2005-02-04 - - * new --rcfile option to specify the configuration file without the - PYLINTRC environment variable - - * added an example module for a custom pylint checker (see the - example/ directory) - - * some fixes to handle fixes in common 0.9.1 (should however still working - with common 0.9.0, even if upgrade is recommended) - - -What's New in Pylint 0.6.0? -=========================== - -Release date: 2005-01-20 - - * refix pylint emacs mode - - * no more traceback when just typing "pylint" - - * fix a bug which may cause crashes on resolving parent classes - - * fix problems with the format checker: don't chock on files - containing multiple CR, avoid C0322, C0323, C0324 false positives - with triple quoted string with quote inside - - * correctly detect access to member defined latter in __init__ method - - * now depends on common 0.8.1 to fix problem with interface resolution - (close #8606) - - * new --list-msgs option describing available checkers and their - messages - - * added windows specific documentation to the README file, contributed - by Brian van den Broek - - * updated doc/features.txt (actually this file is now generated using - the --list-msgs option), more entries into the FAQ - - * improved tests coverage - - -What's New in Pylint 0.5.0? -=========================== - -Release date: 2004-10-19 - - * avoid importing analyzed modules ! - - * new Refactor and Convention message categories. Some Warnings have been - remaped into those new categories - - * added "similar", a tool to find copied and pasted lines of code, - both using a specific command line tool and integrated as a - pylint's checker - - * imports checker may report import dependencies as a dot graph - - * new checker regrouping most Refactor detection (with some new metrics) - - * more command line options storable in the configuration file - - * fix bug with total / undocumented number of methods - - -What's New in Pylint 0.4.2? -=========================== - -Release date: 2004-07-08 - - * fix pylint emacs mode - - * fix classes checkers to handler twisted interfaces - - -What's New in Pylint 0.4.1? -=========================== - -Release date: 2004-05-14 - - * fix the setup.py script to allow bdist_winst (well, the generated - installer has not been tested...) with the necessary - logilab/__init__.py file - - * fix file naming convention as suggested by Andreas Amoroso - - * fix stupid crash bug with bad method names - - -What's New in Pylint 0.4.0? -=========================== - -Release date: 2004-05-10 - - * fix file path with --parsable - - * --parsable option has been renamed to --parseable - - * added patch from Andreas Amoroso to output message to files instead - of standard output - - * added Run to the list of correct variable names - - * fix variable names regexp and checking of local classes names - - * some basic handling of metaclasses - - * no-docstring-rgx apply now on classes too - - * new option to specify a different regexp for methods than for - functions - - * do not display the evaluation report when no statements has been - analysed - - * fixed crash with a class nested in a method - - * fixed format checker to deals with triple quoted string and - lines with code and comment mixed - - * use logilab.common.ureports to layout reports - - -What's New in Pylint 0.3.3? -=========================== - -Release date: 2004-02-17 - - * added a parsable text output, used when the --parsable option is - provided - - * added an emacs mode using this output, available in the distrib's - elisp directory - - * fixed some typos in messages - - * change include-ids options to yn, and allow it to be in the - configuration file - - * do not chock on corrupted stats files - - * fixed bug in the format checker which may stop pylint execution - - * provide scripts for unix and windows to wrap the minimal pylint tk - gui - - - -What's New in Pylint 0.3.2? -=========================== - -Release date: 2003-12-23 - - * html-escape messages in the HTML reporter (bug reported by Juergen - Hermann) - - * added "TODO" to the list of default note tags - - * added "rexec" to the list of default deprecated modules - - * fixed typos in some messages - - - -What's New in Pylint 0.3.1? -=========================== - - -Release date: 2003-12-05 - - * bug fix in format and classes checkers - - * remove print statement from imports checkers - - * provide a simple tk gui, essentially useful for windows users - - - -What's New in Pylint 0.3.0? -=========================== - - -Release date: 2003-11-20 - - * new exceptions checker, checking for string exception and empty - except clauses. - - * imports checker checks for reimport of modules - - * classes checker checks for calls to ancestor's __init__ and abstract - method not overridden. It doesn't complain anymore for unused import in - __init__ files, and provides a new option ignore-interface-methods, - useful when you're using zope Interface implementation in your project - - * base checker checks for black listed builtins call (controlled by the - bad-functions option) and for use of * and ** - - * format checker checks for use of <> and "l" as long int marker - - * major internal API changes - - * use the rewrite of astng, based on compiler.ast - - * added unique id for messages, as suggested by Wolfgang Grafen - - * added unique id for reports - - * can take multiple modules or files as argument - - * new options command line options : --disable-msg, --enable-msg, - --help-msg, --include-ids, --reports, --disable-report, --cache-size - - * --version shows the version of the python interpreter - - * removed some options which are now replaced by [en|dis]able-msg, or - disable-report - - * read disable-msg and enable-msg options in source files (should be - in comments on the top of the file, in the form - "# pylint: disable-msg=W0402" - - * new message for modules importing themselves instead of the "cyclic - import" message - - * fix bug with relative and cyclic imports - - * fix bug in imports checker (cycle was not always detected) - - * still fixes in format checker : don't check comment and docstring, - check first line after an indent - - * black and white list now apply to all identifiers, not only - variables, so changed the configuration option from - (good|bad)-variable-names to (good|bad)-names - - * added string, rexec and Bastion to the default list of deprecated - modules - - * do not print redefinition warning for function/class/method defined - in mutually exclusive branches - - - -What's New in Pylint 0.2.1? -=========================== - - -Release date: 2003-10-10 - - * added some documentation, fixed some typos - - * set environment variable PYLINT_IMPORT to 1 during pylint execution. - - * check that variables "imported" using the global statement exist - - * indentation problems are now warning instead of errors - - * fix checkers.initialize to try to load all files with a known python - extension (patch from wrobell) - - * fix a bunch of messages - - * fix sample configuration file - - * fix the bad-construction option - - * fix encoding checker - - * fix format checker - - -What's New in Pylint 0.2.0? -=========================== - - -Release date: 2003-09-12 - - * new source encoding / FIXME checker (pep 263) - - * new --zope option which trigger Zope import. Useful to check Zope - products code. - - * new --comment option which enable the evaluation note comment - (disabled by default). - - * a ton of bug fixes - - * easy functional test infrastructure - - -What's New in Pylint 0.1.2? -=========================== - - -Release date: 2003-06-18 - - * bug fix release - - * remove dependency to pyreverse - - -What's New in Pylint 0.1.1? -=========================== - - -Release date: 2003-06-01 - - * much more functionalities ! - - -What's New in Pylint 0.1? -=========================== - -Release date: 2003-05-19 - - * initial release diff --git a/DEPENDS b/DEPENDS deleted file mode 100644 index 653dfcbda0..0000000000 --- a/DEPENDS +++ /dev/null @@ -1,3 +0,0 @@ -python-logilab-common (>= 0.19.0) -python-astroid (>= 1.3.6) -python-tk diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..8c4c849e23 --- /dev/null +++ b/LICENSE @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + 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. diff --git a/MANIFEST.in b/MANIFEST.in index dc97c4ece3..694393065f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,11 +1,14 @@ -include ChangeLog -include COPYING -include DEPENDS -include README README.Python3 -include bin/* -include examples/*.py examples/pylintrc examples/pylintrc_camelcase -include elisp/startup elisp/*.el -include man/*.1 -include pytest.ini -recursive-include doc *.rst *.jpeg Makefile *.html *.py *.bat -graft pylint/test +include README.rst +include requirements_test_min.txt +include requirements_test_pre_commit.txt +include requirements_test.txt +include tox.ini +graft doc +graft examples +graft script +graft tests +prune doc/_build +prune tests/.benchmarks +prune tests/.pylint_primer_tests +global-exclude __pycache__ +global-exclude *.py[co] diff --git a/Makefile b/Makefile deleted file mode 100644 index 48dda857c9..0000000000 --- a/Makefile +++ /dev/null @@ -1,73 +0,0 @@ -# Makefile for handling various tasks of Pylint sources -PYVE=pyve -PIP=$(PYVE)/bin/pip -TOX=$(PYVE)/bin/tox - -VERSION=$(shell PYTHONPATH=. python -c "from pylint.__pkginfo__ import version; print(version)") - -PKG_SDIST=dist/pylint-$(VERSION).tar.gz -PKG_DEB=../pylint_$(VERSION)-1_all.deb - -# this is default target, it should always be first in this Makefile -help: - @echo "Please use \`make ' where is one of" - @echo " tests to run whole test suit of PyLint" - @echo " docs to generate all docs including man pages and exemplary pylintrc" - @echo " deb to build debian .deb package (it works only on Debian based Linux distros)" - @echo " sdist to build source .tar.gz package" - @echo " lint to check Pylint sources with itself" - @echo " all to run all targets" - - -$(PIP): - virtualenv $(PYVE) - -$(TOX): $(PIP) - $(PIP) install tox~=2.0 - - -ifdef TOXENV -toxparams?=-e $(TOXENV) -endif - -tests: $(TOX) - $(TOX) $(toxparams) - -docs: $(PIP) - $(PIP) install . - $(PIP) install Sphinx - $(PIP) install python-docs-theme - . $(PYVE)/bin/activate; make all -C doc - -deb: $(PKG_DEB) -$(PKG_DEB): /usr/bin/debuild /usr/bin/dh_pysupport - if [ -n "$$SUBVERSION" ]; then sed -i -e "0,/pylint (\(.*\))/s//pylint (\1.$${SUBVERSION})/" debian/changelog; fi - debuild -b -us -uc - -sdist: $(PKG_SDIST) -$(PKG_SDIST): - python setup.py sdist - -lint: $(PIP) - $(PIP) install . - $(PYVE)/bin/pylint lint.py || true # for now ignore errors - -clean: - rm -rf $(PYVE) - rm -rf .tox - rm -rf dist - rm -rf build - make clean -C doc - rm -rf $(PKG_DEB) ../pylint_*.changes ../pylint_*.build - debuild clean || true - - -/usr/bin/debuild: - sudo apt-get -y --force-yes install devscripts - -/usr/bin/dh_pysupport: - sudo apt-get -y --force-yes install python-support - -all: clean lint tests docs sdist deb - -.PHONY: help tests docs deb sdist lint clean all diff --git a/README.rst b/README.rst index 189873f44f..0595d895d8 100644 --- a/README.rst +++ b/README.rst @@ -1,104 +1,225 @@ +`Pylint`_ +========= -README for Pylint - http://pylint.pycqa.org/ -============================================ +.. _`Pylint`: https://pylint.readthedocs.io/ -.. image:: https://travis-ci.org/PyCQA/pylint.svg?branch=master - :target: https://travis-ci.org/PyCQA/pylint +.. This is used inside the doc to recover the start of the introduction -.. image:: https://ci.appveyor.com/api/projects/status/rbvwhakyj1y09atb/branch/master?svg=true - :alt: AppVeyor Build Status - :target: https://ci.appveyor.com/project/PCManticore/pylint - -.. image:: https://coveralls.io/repos/github/PyCQA/pylint/badge.svg?branch=master - :target: https://coveralls.io/github/PyCQA/pylint?branch=master +.. 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 + :alt: PyPI Package version :target: https://pypi.python.org/pypi/pylint .. image:: https://readthedocs.org/projects/pylint/badge/?version=latest - :target: http://pylint.readthedocs.io/en/latest/?badge=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 -====== -Pylint -====== +.. 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 -**It's not just a linter that annoys you!** +.. image:: https://bestpractices.coreinfrastructure.org/projects/6328/badge + :target: https://bestpractices.coreinfrastructure.org/projects/6328 + :alt: CII Best Practices -Pylint is a Python static code analysis tool which looks for programming errors, -helps enforcing a coding standard, sniffs for code smells and offers simple refactoring -suggestions. +.. 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 -It's highly configurable, having special pragmas to control its errors and warnings -from within your code, as well as from an extensive configuration file. -It is also possible to write your own plugins for adding your own checks or for -extending pylint in one way or another. +.. image:: https://img.shields.io/discord/825463413634891776.svg + :target: https://discord.gg/qYxpadCgkx + :alt: Discord -It's a free software distributed under the GNU General Public Licence. +What is Pylint? +--------------- -Development is hosted on GitHub: https://github.com/PyCQA/pylint/ +Pylint is a `static code analyser`_ for Python 2 or 3. The latest version supports Python +3.9.0 and above. -You can use the code-quality@python.org mailing list to discuss about -Pylint. Subscribe at https://mail.python.org/mailman/listinfo/code-quality/ -or read the archives at https://mail.python.org/pipermail/code-quality/ +.. _`static code analyser`: https://en.wikipedia.org/wiki/Static_code_analysis -Pull requests are amazing and most welcome. +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 ------- -Pylint can be simply installed by running:: +.. 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 -If you are using Python 3.6+, upgrade to get full support for your version:: +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. - pip install pylint --upgrade +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. -If you want to install from a source distribution, extract the tarball and run -the following command :: +.. note:: - python setup.py install - + 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`_. -Do make sure to do the same for astroid, which is used internally by pylint. +.. _`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 -For debian and rpm packages, use your usual tools according to your Linux distribution. +Advised linters alongside pylint +-------------------------------- -More information about installation and available distribution format -can be found here_. +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). -Documentation -------------- +.. _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/ -The documentation lives at http://pylint.pycqa.org/. +Additional tools included in pylint +----------------------------------- -Pylint is shipped with following additional commands: +Pylint ships with two additional tools: -* pyreverse: an UML diagram generator -* symilar: an independent similarities checker -* epylint: Emacs and Flymake compatible Pylint +- 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/pyreverse.html +.. _symilar: https://pylint.readthedocs.io/en/latest/symilar.html -Testing + +.. 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 ------- -We use tox_ for running the test suite. You should be able to install it with:: +pylint is, with a few exceptions listed below, `GPLv2 `_. + +The icon files are licensed under the `CC BY-SA 4.0 `_ license: - pip install tox pytest +- `doc/logo.png `_ +- `doc/logo.svg `_ + +Support +------- +Please check `the contact information`_. -To run the test suite for a particular Python version, you can do:: +.. _`the contact information`: https://pylint.readthedocs.io/en/latest/contact.html - tox -e py27 +.. |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 -For more detailed information, check the documentation. + * - |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. -.. _here: http://pylint.pycqa.org/en/latest/user_guide/installation.html -.. _tox: https://tox.readthedocs.io/en/latest/ +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-pylint?utm_source=pypi-pylint&utm_medium=referral&utm_campaign=readme diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 5545fa2b29..0000000000 --- a/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: '{branch}-{build}' -build: off -cache: - - 'C:\\tmp' -environment: - matrix: - - PYTHON: "C:\\Python34" - TOXENV: "py34" - - - PYTHON: "C:\\Python35" - TOXENV: "py35" - - - PYTHON: "C:\\Python36" - TOXENV: "py36" - -init: - - ps: echo $env:TOXENV - - ps: ls C:\Python* - - ps: mkdir C:\tmp -install: - - 'powershell ./appveyor/install.ps1' - - "python -m pip install tox" - - 'python -m pip install wheel' - - 'python -m pip --version' - - 'python -m tox --version' - -test_script: - - 'python -m tox' - -on_failure: - - ps: dir "env:" - - ps: get-content .tox\*\log\* diff --git a/appveyor/install.ps1 b/appveyor/install.ps1 deleted file mode 100644 index e13c3880ff..0000000000 --- a/appveyor/install.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -# Sample script to install pip under Windows -# Authors: Olivier Grisel, Jonathan Helmus and Kyle Kastner -# License: CC0 1.0 Universal: http://creativecommons.org/publicdomain/zero/1.0/ - -$GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" -$GET_PIP_PATH = "C:\get-pip.py" - - -function InstallPip ($python_home) { - $pip_path = $python_home + "\Scripts\pip.exe" - $python_path = $python_home + "\python.exe" - if (-not(Test-Path $pip_path)) { - Write-Host "Installing pip..." - $webclient = New-Object System.Net.WebClient - $webclient.DownloadFile($GET_PIP_URL, $GET_PIP_PATH) - Write-Host "Executing:" $python_path $GET_PIP_PATH - Start-Process -FilePath "$python_path" -ArgumentList "$GET_PIP_PATH" -Wait -Passthru - } else { - Write-Host "pip already installed." - } -} - -function main () { - InstallPip $env:PYTHON -} - -main diff --git a/bin/epylint b/bin/epylint deleted file mode 100755 index 4aad65703b..0000000000 --- a/bin/epylint +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -from pylint import epylint -epylint.Run() diff --git a/bin/epylint.bat b/bin/epylint.bat deleted file mode 100644 index 30c46d7be0..0000000000 --- a/bin/epylint.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -rem Use python to execute the python script having the same name as this batch -rem file, but without any extension, located in the same directory as this -rem batch file -"%~dpn0" %* diff --git a/bin/pylint b/bin/pylint deleted file mode 100755 index e3e520f0c7..0000000000 --- a/bin/pylint +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -from pylint import run_pylint -run_pylint() diff --git a/bin/pylint.bat b/bin/pylint.bat deleted file mode 100644 index 0ff3e3ddc0..0000000000 --- a/bin/pylint.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -rem Use python to execute the python script having the same name as this batch -rem file, but without any extension, located in the same directory as this -rem batch file -"%~dpn0" %* diff --git a/bin/pyreverse b/bin/pyreverse deleted file mode 100755 index 71269e769f..0000000000 --- a/bin/pyreverse +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -from pylint import run_pyreverse -run_pyreverse() diff --git a/bin/pyreverse.bat b/bin/pyreverse.bat deleted file mode 100644 index 30c46d7be0..0000000000 --- a/bin/pyreverse.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -rem Use python to execute the python script having the same name as this batch -rem file, but without any extension, located in the same directory as this -rem batch file -"%~dpn0" %* diff --git a/bin/symilar b/bin/symilar deleted file mode 100755 index ef94462473..0000000000 --- a/bin/symilar +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env python -from pylint import run_symilar -run_symilar() diff --git a/bin/symilar.bat b/bin/symilar.bat deleted file mode 100644 index 0ff3e3ddc0..0000000000 --- a/bin/symilar.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off -rem Use python to execute the python script having the same name as this batch -rem file, but without any extension, located in the same directory as this -rem batch file -"%~dpn0" %* diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000000..c45517a33a --- /dev/null +++ b/codecov.yml @@ -0,0 +1,10 @@ +coverage: + status: + patch: + default: + target: 100% + project: + default: + target: 95% +comment: + layout: "reach, diff, flags, files" diff --git a/custom_dict.txt b/custom_dict.txt new file mode 100644 index 0000000000..265c7cb881 --- /dev/null +++ b/custom_dict.txt @@ -0,0 +1,395 @@ +abc +abcmeta +abspath +abstractproperty +analyse +analysed +analysing +arg +argparse +args +argumentdefaultshelpformatter +argumentparser +argumentsparser +argv +ascii +asend +assignattr +assignname +AST +ast +astroid +async +asynccontextmanager +attr +attrib +attrname +backport +BaseChecker +basename +behaviour +bidi +Bitbucket +bla +bom +bool +boolean +booleaness +boolop +boundmethod +builtins +bw +callables +cardinality +cd +cfg +changelog +cheaders +chroot +chunker +classdef +classdiagram +classmethod +classmethod's +classname +classobj +CLI +cls +cmp +codebase +codec +codecs +col's +conf +config +const +Const +contextlib +contextmanager +contravariance +contravariant +cgroup +CPython +cpython +csv +CVE +cwd +cyclomatic +dataclass +dataclasses +datetime +debian +deduplication +deepcopy +defaultdicts +defframe +defstmts +deleter +dependabot +deque +destructured +destructuring +diadefs +diadefslib +dictcomp +dicts +dir +dirname +docparams +docstring +docstrings +dumpable +dunder +elif +elif's +elt +emittable +encodings +endswith +enum +enums +epilog +epylint +epytext +erroring +etree +expr +falsey +favour +filepath +filestream +finalbody +# TODO Remove when we are able to remove our own symbols +fixme +Flymake +fmt +formatter +formfeed +fromlineno +fullname +func +functiondef +functiรธn +functools +genexpr +getattr +globals +globbing +GPL +graphname +graphviz +grey +guido's +gv +hashable +hmac +html +idgeneratormixin +ifexpr +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 diff --git a/debian.sid/control b/debian.sid/control deleted file mode 100644 index 92d2316c79..0000000000 --- a/debian.sid/control +++ /dev/null @@ -1,57 +0,0 @@ -Source: pylint -Section: python -Priority: optional -Maintainer: Logilab S.A. -Uploaders: Sylvain Thรฉnault , Alexandre Fayolle , - Sandro Tosi , Julien Jehannet -Build-Depends: debhelper (>= 7.0.50~), python-all, python3-all -Standards-Version: 3.9.2 -Homepage: http://www.logilab.org/project/pylint -Vcs-Hg: http://hg.logilab.org/pylint -Vcs-Browser: http://hg.logilab.org/pylint - -Package: pylint -Architecture: all -Depends: ${python:Depends}, ${misc:Depends}, python-logilab-common (>= 0.53), python-astroid -Recommends: python-tk, python-enchant -XB-Python-Version: ${python:Versions} -Description: python code static checker and UML diagram generator - Pylint is a Python source code analyzer which looks for programming - errors, helps enforcing a coding standard and sniffs for some code - smells (as defined in Martin Fowler's Refactoring book) - . - Pylint can be seen as another PyChecker since nearly all tests you - can do with PyChecker can also be done with Pylint. However, Pylint - offers some more features, like checking length of lines of code, - checking if variable names are well-formed according to your coding - standard, or checking if declared interfaces are truly implemented, - and much more. - . - Additionally, it is possible to write plugins to add your own checks. - . - The included command pyreverse generates UML class and package - diagrams. - . - -Package: pylint3 -Architecture: all -Depends: ${python3:Depends}, ${misc:Depends}, python3-logilab-common (>= 0.53), python3-astroid -Recommends: python3-tk, python3-enchant -XB-Python-Version: ${python3:Versions} -Description: python code static checker and UML diagram generator - Pylint is a Python source code analyzer which looks for programming - errors, helps enforcing a coding standard and sniffs for some code - smells (as defined in Martin Fowler's Refactoring book) - . - Pylint can be seen as another PyChecker since nearly all tests you - can do with PyChecker can also be done with Pylint. However, Pylint - offers some more features, like checking length of lines of code, - checking if variable names are well-formed according to your coding - standard, or checking if declared interfaces are truly implemented, - and much more. - . - Additionally, it is possible to write plugins to add your own checks. - . - The included command pyreverse generates UML class and package - diagrams. - . diff --git a/debian.sid/rules b/debian.sid/rules deleted file mode 100755 index 9a26fd63a1..0000000000 --- a/debian.sid/rules +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. -# -# adapted by Logilab for automatic generation by debianize -# (part of the devtools project, http://www.logilab.org/projects/devtools) -# -# Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -include /usr/share/python/python.mk - -PYLIB:=$(call py_libdir,$(shell pyversions -d)) -PACKAGE:=$(call py_pkgname,pylint,python) -PYLIB3:=$(call py_libdir,python3.) -PACKAGE3:="pylint3" - -%: - dh $@ --with python2,python3 - -override_dh_install: - NO_SETUPTOOLS=1 python setup.py -q install --no-compile \ - --root=$(CURDIR)/debian/$(PACKAGE)/ \ - ${py_setup_install_args} - NO_SETUPTOOLS=1 python3 setup.py -q install --no-compile \ - --root=$(CURDIR)/debian/$(PACKAGE3)/ \ - ${py_setup_install_args} - # rename executables - for executable in pylint symilar epylint pyreverse ; do \ - new_exec="$$executable"3; \ - sed 's,^#!.*python$$,&3,' < $(CURDIR)/debian/$(PACKAGE3)/usr/bin/$$executable > $(CURDIR)/debian/$(PACKAGE3)/usr/bin/$$new_exec || exit 1; \ - done - # remove test directory - rm -rf debian/*/usr/lib/python*/*-packages/pylint/test - # generate pylint man page automatically - #PYTHONPATH=$(CURDIR)/debian/$(PACKAGE)/$(PYLIB) python $(CURDIR)/bin/pylint --generate-man > $(CURDIR)/man/pylint.1 - # rename and install man pages - dh_installman -ppylint man/*.1 - cd man && for i in *.1; do cp -v $$i "$$(basename $$i .1)3.1"; done - dh_installman -ppylint3 man/*3.1 - -override_dh_installdocs: - dh_installdocs README* - dh_installchangelogs -i ChangeLog - -override_dh_auto_test: -ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) - # PYTHON 2.X - # PYTHON 3.2 -endif diff --git a/debian.sid/source/format b/debian.sid/source/format deleted file mode 100644 index 163aaf8d82..0000000000 --- a/debian.sid/source/format +++ /dev/null @@ -1 +0,0 @@ -3.0 (quilt) diff --git a/debian/NEWS.Debian b/debian/NEWS.Debian deleted file mode 100644 index 0a7e3ebf59..0000000000 --- a/debian/NEWS.Debian +++ /dev/null @@ -1,10 +0,0 @@ -pylint (0.13.2-2) unstable; urgency=low - - * pylint.el is no longer installed for emacs, because it is not - compatible with emacs22 and has a large number of related bugs. It - will be reenabled in a future version, when all the bugs have been - dealt with by upstream (patches are welcome by the way). Emacs21 - users may get it from /usr/share/doc/pylint/examples/pylint.el - - -- Alexandre Fayolle Wed, 04 Jul 2007 12:18:23 +0200 - diff --git a/debian/README.source b/debian/README.source deleted file mode 100644 index 0d0aa40032..0000000000 --- a/debian/README.source +++ /dev/null @@ -1,4 +0,0 @@ -This package uses dpatch to handle patches against upstream source code; you -can find additional information about dpatch at - - /usr/share/doc/dpatch/ diff --git a/debian/changelog b/debian/changelog deleted file mode 100644 index 73102d3b2b..0000000000 --- a/debian/changelog +++ /dev/null @@ -1,547 +0,0 @@ -pylint (1.4.1-1) precise; urgency=low - - * new upstream release - - -- Ionel Cristian Maries Sun, 15 Feb 2015 12:11:44 +0200 - -pylint (1.2.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Wed, 30 Apr 2014 17:56:29 +0200 - -pylint (1.2.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 18 Apr 2014 15:32:32 +0200 - -pylint (1.1.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Sun, 22 Dec 2013 23:44:15 +0100 - -pylint (1.0.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 30 Jul 2013 18:18:06 +0200 - -pylint (0.28.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 25 Apr 2013 09:43:01 +0200 - -pylint (0.27.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 26 Feb 2013 23:40:46 +0100 - -pylint (0.26.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 05 Oct 2012 11:40:08 +0200 - -pylint (0.25.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 17 Jul 2012 17:04:15 +0200 - -pylint (0.25.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 08 Dec 2011 15:27:47 +0100 - -pylint (0.25.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 07 Oct 2011 12:16:29 +0200 - -pylint (0.24.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Mon, 18 Jul 2011 16:03:24 +0200 - -pylint (0.23.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 11 Jan 2011 15:41:02 +0100 - -pylint (0.22.0-1) unstable; urgency=low - - * new upstream release - - -- ร‰mile Anclin Mon, 15 Nov 2010 15:54:44 +0100 - -pylint (0.21.4-1) unstable; urgency=low - - * new upstream release - - -- Emile Anclin Thu, 27 Oct 2010 13:54:44 +0100 - -pylint (0.21.3-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 28 Sep 2010 14:43:33 +0200 - -pylint (0.21.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 26 Aug 2010 10:03:54 +0200 - -pylint (0.21.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 04 Jun 2010 16:07:42 +0200 - -pylint (0.21.0-2) UNRELEASED; urgency=low - - [ Julien Jehannet ] - * can now retrieve pristine tarball thanks to optional get-orig-source target - - [ Sylvain Thรฉnault ] - * update man-page according to 0.21 usage (Closes: #582494) - - -- Julien Jehannet Tue, 25 May 2010 12:49:44 +0200 - -pylint (0.21.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 11 May 2010 12:27:09 +0200 - -pylint (0.20.0-1) unstable; urgency=low - - * new upstream release - - use Daniel Harding patch for windows batch (Closes: #475939) - - -- Emile Anclin Thu, 23 Jan 2010 16:54:44 +0100 - - -pylint (0.19.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 18 Dec 2009 11:34:44 +0100 - -pylint (0.18.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 27 Aug 2009 08:37:00 +0200 - -pylint (0.18.0-2) unstable; urgency=low - - * Python transition, thanks Alessio Treglia for the patch (Closes: #530509) - - Use --install-layout=deb for setup.py install. - - Replace site-packages by *-packages. - - Build-depends on python >= 2.5.4-1~ for --install-layout=deb. - - -- Julien Lavergne Sun, 31 May 2009 01:24:53 +0200 - -pylint (0.18.0-1) unstable; urgency=low - - * change to python-support - * update StandardVersion to 3.8.1 - * debian/rules: set NO_SETUPTOOLS when calling python setup.py - - -- Sylvain Thรฉnault Wed, 25 Mar 2009 09:39:37 +0100 - -pylint (0.17.0-1) unstable; urgency=low - - * new upstream release - - -- Emile Anclin Thu, 19 Mar 2009 15:55:35 +0100 - -pylint (0.16.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Wed, 28 Jan 2009 12:15:07 +0100 - -pylint (0.15.2-2) unstable; urgency=low - - * debian/control - - added Vcs-{Svn,Browser} field - - -- Sandro Tosi Sat, 29 Nov 2008 14:44:41 +0100 - -pylint (0.15.2-1) unstable; urgency=low - - * New upstream release - * debian/control - - added under PAPT umbrella (in agreement with Alexandre Fayolle) - - added me to uploaders - - moved Homepage field to source stanza - - bump Standards-Version to 3.8.0 - + added debian/README.source - - moved python (removing version, since we are in a 2.4+2.5 distribution) to - build-dep from build-dep-indep (to satisfy clean target needs) - - added ${python:Depends}, ${misc:Depends} to depends instead of directly - depending on "python" package - * debian/watch - - bump verstion to 3 - - left only the url to scan, adding "opts=pasv" for ftp scan - * debian/pylint.docs - - install all doc/ directory files - - added README and TODO (from debian/rules) - * debian/rules - - merged 'rm -f' commands into dh_clean call - - added "python setup.py clean" call in clean target - - install upstream "Changelog" using dh_installchangelog - - removed files passed to dh_installdocs since using debian/pylint.docs and - because debian/NEWS.Debian is automatically installed - - using '-delete' find option instead of xargs - - fix executables shebang with a for loop - - -- Sandro Tosi Wed, 26 Nov 2008 16:45:36 +0100 - -pylint (0.15.2-0) unstable; urgency=low - - * new upstream release - - -- Emile Anclin Mon, 13 Oct 2008 13:38:00 +0200 - -pylint (0.15.1-1) unstable; urgency=low - - * new upstream release - - -- Emile Anclin Mon, 15 Sep 2008 14:38:00 +0200 - -pylint (0.15.0-1) unstable; urgency=low - - * new upstream release - * Acknowledge NMU: thanks a lot, your patches have been backported in - upstream code (closes: #427244, #448102, #415485, #431653) - - -- Emile Anclin Wed, 10 Sep 2008 12:16:00 +0200 - -pylint (0.14.0-2.2) unstable; urgency=low - - * NMU. Rebuild to move files to /usr/share/pyshared. Closes: #490488. - - -- Matthias Klose Fri, 18 Jul 2008 15:53:30 +0000 - -pylint (0.14.0-2.1) unstable; urgency=low - - * Non-maintainer upload. - * BF: flavor -> debian-emacs-flavor in startup - * NF: added pylint-options variable visible to users to tune up (closes: - #427244) - * BF: reenabled installation of pylint.el (closes: #448102) - * Recent upstream of pylint.el fixed few bugs which weren't closed - in the upload to Debian. Since this is first upload which enables - pylint.el, imho it is ok to close them here (closes: #415485, #431653) - - -- Yaroslav Halchenko Mon, 03 Mar 2008 22:22:07 -0500 - -pylint (0.14.0-2) unstable; urgency=low - - * Acknowledge NMU by Kumar Appaiah (Closes: #454401) - * Debian upload of the new upstream release - * Install modules for all available python versions (Closes: #438438) - * new standards version, no changes required - - -- Alexandre Fayolle Wed, 13 Feb 2008 17:36:30 +0100 - -pylint (0.14.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Mon, 14 Jan 2008 13:34:24 +0100 - -pylint (0.13.2-2.1) unstable; urgency=low - - * Non-maintainer upload. - * debian/pylint.postrm: - + Added to remove old Emacs mode upon purge. - (Closes: #454401) - - -- Kumar Appaiah Thu, 31 Jan 2008 22:27:18 +0530 - -pylint (0.13.2-2) unstable; urgency=low - - * Upload package to debian (closes: #426418) - * tests are no longer installed in /usr/share/doc/pylint, use the source - package to get them - * pylint.el is no longer installed for emacs, because it is not - compatible with emacs22. It will be reenabled in a future version, - when all the bugs have been dealt with by upstream. Emacs21 users may - get it from /usr/share/doc/pylint/examples/pylint.el. Added a note - about this in NEWS.Debian. - * Only Recommend python-tk and give a nicer warning in the pylint-gui - script if tkinter is not available. - * Updated versions of dependencies on logilab-common and astng - - -- Alexandre Fayolle Wed, 04 Jul 2007 12:21:24 +0200 - -pylint (0.13.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 07 Jun 2007 16:44:53 +0200 - -pylint (0.13.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 2 Mar 2007 08:24:08 +0100 - -pylint (0.13.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 22 Feb 2007 11:28:23 +0100 - -pylint (0.12.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 23 Nov 2006 16:08:28 +0100 - -pylint (0.12.1-1) unstable; urgency=low - - * new uptream release - - -- Sylvain Thรฉnault Mon, 25 Sep 2006 16:46:40 +0200 - -pylint (0.12.0-2) unstable; urgency=low - - * Upload to Debian - * Fixed the XS-Python-Version value (closes: #388158) - - -- Alexandre Fayolle Tue, 19 Sep 2006 09:51:03 +0200 - -pylint (0.12.0-1) unstable; urgency=low - - * new upstream release - - -- Adrien.DiMascio Thu, 10 Aug 2006 11:18:50 +0200 - -pylint (0.11.0-2) unstable; urgency=low - - * Updated standards to 3.7.2 - * use debhelper 5 - * new python policy - - -- Alexandre Fayolle Thu, 15 Jun 2006 10:38:32 +0200 - -pylint (0.11.0-1) unstable; urgency=low - - * new upstream release, depending on python-astng 0.16 - * Applied Sebastian Rittau's patch to avoid NameError on InferenceError - exception (closes: #358194) - - -- Sylvain Thรฉnault Wed, 19 Apr 2006 18:10:47 +0200 - -pylint (0.10.0-1) unstable; urgency=low - - * new upstream release, depending on python-astng 0.15 - - -- Sylvain Thรฉnault Mon, 6 Mar 2006 09:43:19 +0100 - -pylint (0.9.0-3) unstable; urgency=low - - * Added missing provides/replaces/conflicts on pylint-test (closes: #352316) - - -- Alexandre Fayolle Mon, 13 Feb 2006 10:07:26 +0100 - -pylint (0.9.0-2) unstable; urgency=low - - * Build a single package which installs modules in /usr/lib/site-python - (closes: #351130) - * Remove duplication from man page (closes: #349689) - * Fixed typo in control file - * upload new release to Debian - - -- Alexandre Fayolle Fri, 10 Feb 2006 16:03:37 +0100 - -pylint (0.9.0-1) unstable; urgency=low - - * fix false positive with staticmethod used on a metaclass (closes: #341121) - * reorganization to install into site-python, removing the need for - pythonX.X- packages and for the pylint-common and pylint-test packages - - -- Sylvain Thรฉnault Tue, 10 Jan 2006 14:19:57 +0100 - -pylint (0.8.1-1) unstable; urgency=low - - * added missing dependency to logilab-astng - * added missing .docs and .examples files - * update control'standards-version to 3.6.2 - * fixed FSF address in the copyright file - * new upstream release - - -- Sylvain Thรฉnault Mon, 7 Nov 2005 15:40:52 +0100 - -pylint (0.8.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 21 Oct 2005 18:44:24 +0200 - -pylint (0.7.0-1) unstable; urgency=low - - * new upstream release (closes: #310957) - - -- Sylvain Thรฉnault Fri, 27 May 2005 11:17:44 +0200 - -pylint (0.6.4-1) unstable; urgency=low - - * new upstream release - * added man page for pylint - - -- Sylvain Thรฉnault Thu, 14 Apr 2005 12:02:15 +0200 - -pylint (0.6.3-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Thu, 24 Feb 2005 17:44:35 +0100 - -pylint (0.6.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Wed, 16 Feb 2005 12:00:47 +0100 - -pylint (0.6.1-1) unstable; urgency=low - - * new upstream release - * added option to specify rc file location (closes: #265159) - - -- Sylvain Thรฉnault Fri, 4 Feb 2005 16:48:09 +0100 - -pylint (0.6.0-1) unstable; urgency=low - - * new upstream release - * build package for python 2.4 - * remove unused directory from logilab-common.dirs - * updated copyright - - -- Sylvain Thรฉnault Thu, 20 Jan 2005 18:06:29 +0100 - -pylint (0.5.0-2) unstable; urgency=low - - * Patched pylint.el using latest upsrteam CVS (closes: #280870) - - -- Alexandre Fayolle Mon, 15 Nov 2004 10:59:51 +0100 - -pylint (0.5.0-1) unstable; urgency=low - - * use Build-depends instead of Build-depends-indep in control - * new upstream release - * updated debian/watch file to version 2 - - -- Alexandre Fayolle Tue, 9 Nov 2004 16:22:47 +0100 - -pylint (0.4.2-2) unstable; urgency=low - - * fixed typos in debian/control (closes: #265156) - * updated description of pylint-test - * changed dependency on pylint-common to a recommendation (closes: #265157) - * updated maintainer address - - -- Alexandre Fayolle Sun, 15 Aug 2004 10:39:06 +0200 - -pylint (0.4.2-1) unstable; urgency=low - - * new upstream release - * initial upload to Debian (closes: #258235) - - -- Alexandre Fayolle Thu, 8 Jul 2004 12:54:18 +0200 - -pylint (0.4.0-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Mon, 10 May 2004 17:03:04 +0200 - -pylint (0.3.3-1) unstable; urgency=low - - * new upstream release - * emacs lisp for pylint in a new pylint-common package - - -- Sylvain Thรฉnault Mon, 16 Feb 2004 18:09:23 +0100 - -pylint (0.3.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Tue, 23 Dec 2003 14:56:04 +0100 - -pylint (0.3.1-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Fri, 5 Dec 2003 16:20:44 +0100 - -pylint (0.3.0-1) unstable; urgency=low - - * new upstream release - * depends on logilab.common >= 0.4 - * build depends on debhelper >= 4.0 - - -- Sylvain Thรฉnault Wed, 19 Nov 2003 11:07:45 +0100 - -pylint (0.2.1-2) unstable; urgency=low - - * fixed dependency on logilab-common (>=0.3.4) since earlier versions - caused bugs with some python2.3 code - * included sample pylintrc files with the documentation - * added documentation that had disappeared in the previous 0.2.1-1 - * only puts html documentation in doc/html/, all others in doc/ - - -- Sylvain Thรฉnault Fri, 10 Oct 2003 12:11:53 +0200 - -pylint (0.2.1-1) unstable; urgency=low - - * new upstream release - * package renamed to pylint instead of logilab-pylint - * move tests in a separated package - - -- Sylvain Thรฉnault Fri, 10 Oct 2003 09:39:22 +0200 - -logilab-pylint (0.2.0-1) unstable; urgency=low - - * new upstream release - * dropped python2.1 support - - -- Sylvain Thรฉnault Fri, 12 Sep 2003 18:26:15 +0200 - -logilab-pylint (0.1.2-1) unstable; urgency=low - - * new upstream release - - -- Sylvain Thรฉnault Wed, 11 Jun 2003 15:21:44 +0200 - -logilab-pylint (0.1.1-2) unstable; urgency=low - - * fix dependencies to logilab.common - - -- Sylvain Thรฉnault Wed, 4 Jun 2003 18:07:45 +0200 - -logilab-pylint (0.1.1-1) unstable; urgency=low - - * New upstream release - - -- Sylvain Thรฉnault Mon, 19 May 2003 15:10:25 +0200 - -logilab-pylint (0.1.0-1) unstable; urgency=low - - * Initial Release. - - -- Sylvain Thรฉnault Wed, 23 Apr 2003 14:42:05 +0200 - diff --git a/debian/compat b/debian/compat deleted file mode 100644 index 7ed6ff82de..0000000000 --- a/debian/compat +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/debian/control b/debian/control deleted file mode 100644 index d556c1dcc5..0000000000 --- a/debian/control +++ /dev/null @@ -1,41 +0,0 @@ -Source: pylint -Section: python -Priority: optional -Maintainer: Logilab S.A. -Uploaders: Sylvain Thรฉnault , - Alexandre Fayolle , - Sandro Tosi -Build-Depends: debhelper (>= 5.0.38), python (>= 2.5) -Build-Depends-Indep: python-support -XS-Python-Version: >= 2.5 -Standards-Version: 3.8.2 -Homepage: http://www.pylint.org -Vcs-Svn: svn://svn.debian.org/svn/python-apps/packages/pylint/trunk/ -Vcs-Hg: https://bitbucket.org/logilab/pylint -Vcs-Browser: https://bitbucket.org/logilab/pylint/src - -Package: pylint -Architecture: all -Depends: ${python:Depends}, - ${misc:Depends}, - python-logilab-common (>= 0.53.0), - python-astroid (>= 1.2) -Suggests: python-enchant -XB-Python-Version: ${python:Versions} -Description: python code static checker and UML diagram generator - Pylint is a Python source code analyzer which looks for programming - errors, helps enforcing a coding standard and sniffs for some code - smells (as defined in Martin Fowler's Refactoring book) - . - Pylint can be seen as another PyChecker since nearly all tests you - can do with PyChecker can also be done with Pylint. However, Pylint - offers some more features, like checking length of lines of code, - checking if variable names are well-formed according to your coding - standard, or checking if declared interfaces are truly implemented, - and much more. - . - Additionally, it is possible to write plugins to add your own checks. - . - The included command pyreverse generates UML class and package - diagrams. The included symilar command is a separated similarities checker. - . diff --git a/debian/copyright b/debian/copyright deleted file mode 100644 index c2c1d7de62..0000000000 --- a/debian/copyright +++ /dev/null @@ -1,34 +0,0 @@ -This package was debianized by Sylvain Thenault Sat, 13 Apr 2002 19:05:23 +0200. - -It was downloaded from ftp://ftp.logilab.org/pub/pylint - -Upstream Author: - - Sylvain Thenault - -Copyright: - - Copyright (c) 2003-2009 Sylvain Thenault (thenault@gmail.com). - Copyright (c) 2003-2009 LOGILAB S.A. (Paris, FRANCE). - http://www.logilab.fr/ -- mailto:contact@logilab.fr - -License: - - 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. - -On Debian systems, the complete text of the GNU General Public License v2 -may be found in '/usr/share/common-licenses/GPL-2'. - -The Debian packaging is Copyright (C) 2008-2009, Sandro Tosi -and is licensed under the same terms as upstream code (see above). diff --git a/debian/pycompat b/debian/pycompat deleted file mode 100644 index 0cfbf08886..0000000000 --- a/debian/pycompat +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/debian/pylint.dirs b/debian/pylint.dirs deleted file mode 100644 index 9697bac94f..0000000000 --- a/debian/pylint.dirs +++ /dev/null @@ -1 +0,0 @@ -usr/share/emacs/site-lisp/pylint diff --git a/debian/pylint.docs b/debian/pylint.docs deleted file mode 100644 index a2a5d2ee41..0000000000 --- a/debian/pylint.docs +++ /dev/null @@ -1,2 +0,0 @@ -doc/* -README diff --git a/debian/pylint.emacsen-install b/debian/pylint.emacsen-install deleted file mode 100644 index 66a848063d..0000000000 --- a/debian/pylint.emacsen-install +++ /dev/null @@ -1,45 +0,0 @@ -#! /bin/sh -e -# /usr/lib/emacsen-common/packages/install/#PACKAGE# - -# Written by Jim Van Zandt , borrowing heavily -# from the install scripts for gettext by Santiago Vila -# and octave by Dirk Eddelbuettel . - -FLAVOR=$1 -PACKAGE=pylint - -if [ ${FLAVOR} = emacs ]; then exit 0; fi - -echo install/${PACKAGE}: Handling install for emacsen flavor ${FLAVOR} - -#FLAVORTEST=`echo $FLAVOR | cut -c-6` -#if [ ${FLAVORTEST} = xemacs ] ; then -# SITEFLAG="-no-site-file" -#else -# SITEFLAG="--no-site-file" -#fi -FLAGS="${SITEFLAG} -q -batch -l path.el -f batch-byte-compile" - -ELDIR=/usr/share/emacs/site-lisp/${PACKAGE} -ELCDIR=/usr/share/${FLAVOR}/site-lisp/${PACKAGE} - -# Install-info-altdir does not actually exist. -# Maybe somebody will write it. -if test -x /usr/sbin/install-info-altdir; then - echo install/${PACKAGE}: install Info links for ${FLAVOR} - install-info-altdir --quiet --section "" "" --dirname=${FLAVOR} /usr/info/${PACKAGE}.info.gz -fi - -install -m 755 -d ${ELCDIR} -cd ${ELDIR} -FILES=`echo *.el` -cp ${FILES} ${ELCDIR} -cd ${ELCDIR} - -cat << EOF > path.el -(setq load-path (cons "." load-path) byte-compile-warnings nil) -EOF -${FLAVOR} ${FLAGS} ${FILES} -rm -f *.el path.el - -exit 0 diff --git a/debian/pylint.emacsen-remove b/debian/pylint.emacsen-remove deleted file mode 100644 index 9795dc45ac..0000000000 --- a/debian/pylint.emacsen-remove +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh -e - -FLAVOR=$1 -PACKAGE=pylint - -if [ ${FLAVOR} != emacs ]; then - if test -x /usr/sbin/install-info-altdir; then - echo remove/${PACKAGE}: removing Info links for ${FLAVOR} - install-info-altdir --quiet --remove --dirname=${FLAVOR} /usr/info/${PACKAGE}.info.gz - fi - - echo remove/${PACKAGE}: purging byte-compiled files for ${FLAVOR} - rm -rf /usr/share/${FLAVOR}/site-lisp/${PACKAGE} -fi diff --git a/debian/pylint.emacsen-startup b/debian/pylint.emacsen-startup deleted file mode 100644 index 646bd819bb..0000000000 --- a/debian/pylint.emacsen-startup +++ /dev/null @@ -1,17 +0,0 @@ -;; -*-emacs-lisp-*- -;; -;; Emacs startup file for the Debian GNU/Linux pylint package -;; -;; Originally contributed by Nils Naumann -;; Modified by Dirk Eddelbuettel -;; Adapted for dh-make by Jim Van Zandt - -;; The pylint package follows the Debian/GNU Linux 'emacsen' policy and -;; byte-compiles its elisp files for each 'emacs flavor' (emacs19, -;; xemacs19, emacs20, xemacs20...). The compiled code is then -;; installed in a subdirectory of the respective site-lisp directory. -;; We have to add this to the load-path: -(setq load-path (cons (concat "/usr/share/" - (symbol-name flavor) - "/site-lisp/pylint") load-path)) -(load-library "pylint") diff --git a/debian/pylint.examples b/debian/pylint.examples deleted file mode 100644 index bc35a69ee7..0000000000 --- a/debian/pylint.examples +++ /dev/null @@ -1,2 +0,0 @@ -examples/* -elisp/pylint.el diff --git a/debian/pylint.manpages b/debian/pylint.manpages deleted file mode 100644 index 4b550be555..0000000000 --- a/debian/pylint.manpages +++ /dev/null @@ -1,2 +0,0 @@ -man/pylint.1 -man/pyreverse.1 diff --git a/debian/pylint.postinst b/debian/pylint.postinst deleted file mode 100644 index c426afd894..0000000000 --- a/debian/pylint.postinst +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh -e -# - -#DEBHELPER# - -exit 0 diff --git a/debian/pylint.postrm b/debian/pylint.postrm deleted file mode 100644 index 35920aac14..0000000000 --- a/debian/pylint.postrm +++ /dev/null @@ -1,8 +0,0 @@ -#! /bin/sh -e - -if [ "$1" = "purge" ]; then - # remove old emacs file - rm -f /etc/emacs/site-start.d/50pylint.el -fi - -#DEBHELPER# diff --git a/debian/pylint.prerm b/debian/pylint.prerm deleted file mode 100644 index c426afd894..0000000000 --- a/debian/pylint.prerm +++ /dev/null @@ -1,6 +0,0 @@ -#! /bin/sh -e -# - -#DEBHELPER# - -exit 0 diff --git a/debian/rules b/debian/rules deleted file mode 100755 index ebb56efbf9..0000000000 --- a/debian/rules +++ /dev/null @@ -1,82 +0,0 @@ -#!/usr/bin/make -f -# Sample debian/rules that uses debhelper. -# GNU copyright 1997 to 1999 by Joey Hess. -# -# adapted by Logilab for automatic generation by debianize -# (part of the devtools project, http://www.logilab.org/projects/devtools) -# -# Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE). -# http://www.logilab.fr/ -- mailto:contact@logilab.fr - -# Uncomment this to turn on verbose mode. -#export DH_VERBOSE=1 - -build: build-stamp -build-stamp: - dh_testdir - NO_SETUPTOOLS=1 python setup.py -q build - touch build-stamp - -clean: - dh_testdir - dh_testroot - - NO_SETUPTOOLS=1 python setup.py clean - - find . -name "*.pyc" -delete - - rm -rf build - - dh_clean build-stamp - -install: build - dh_testdir - dh_testroot - dh_clean -k - dh_installdirs - - NO_SETUPTOOLS=1 python setup.py -q install --no-compile \ - --root=$(CURDIR)/debian/pylint \ - --install-layout=deb - - rm -rf debian/pylint/usr/lib/python*/*-packages/pylint/test - - # fixes shebangs - for exec_file in pylint symilar epylint pyreverse ; do \ - if head -1 debian/pylint/usr/bin/$$exec_file | grep "^#! */usr/bin" | grep "python" >/dev/null ; then \ - sed -i "s@^#! */usr/bin/env \+python\$$@#!/usr/bin/python@" debian/pylint/usr/bin/$$exec_file; \ - fi ; \ - chmod a+x debian/pylint/usr/bin/$$exec_file; \ - done - - install -m 644 elisp/pylint.el debian/pylint/usr/share/emacs/site-lisp/pylint/ - - # install tests - #(cd test && find . -type f -not \( -path '*/CVS/*' -or -name '*.pyc' \) -exec install -D --mode=644 {} ../debian/pylint/usr/share/doc/pylint/test/{} \;) - -get-orig-source: - uscan --verbose --force-download --destdir . - -# Build architecture-independent files here. -binary-indep: build install - dh_testdir - dh_testroot - dh_install -i - dh_pysupport -i - dh_installchangelogs -i ChangeLog - dh_installexamples -i - dh_installdocs -i - dh_installman -i - dh_installemacsen - dh_link -i - dh_compress -i -X.py -X.ini -X.xml -Xtest - dh_fixperms -i - dh_installdeb -i - dh_gencontrol -i - dh_md5sums -i - dh_builddeb -i - -binary-arch: - -binary: binary-indep -.PHONY: build clean binary binary-indep binary-arch diff --git a/debian/watch b/debian/watch deleted file mode 100644 index 0c0b773881..0000000000 --- a/debian/watch +++ /dev/null @@ -1,2 +0,0 @@ -version=3 -opts=pasv ftp://ftp.logilab.org/pub/pylint/pylint-(.*)\.tar\.gz diff --git a/doc/Makefile b/doc/Makefile index 8d9480c878..7f21f73349 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -1,163 +1,47 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PIP = pip -PAPER = +# 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 -PYTHON = /usr/bin/env python -PYTHONPATH = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest all +# Put it first so that "make" without argument is like "make help". help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -rm -f reference_guide/features.rst - -rm -f extensions.rst - -html: features.rst extensions.rst - @echo - @echo "Install dependencies" - $(PIP) install python-docs-theme - @echo "Finished installing dependencies" - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." +.PHONY: help Makefile -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Pylint.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Pylint.qhc" +# 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) -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Pylint" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Pylint" - @echo "# devhelp" +# -------------------------------- +# This part is specific to pylint. +#--------------------------------- -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." +# Set PYLINT_SPHINX_FATAL_WARNINGS= on the command line to restore the default. +PYLINT_SPHINX_FATAL_WARNINGS = -W --keep-going -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." +# Do not use O, we abuse it for internal purposes. +O = -d $(BUILDDIR)/doctrees -T $(PYLINT_SPHINX_FATAL_WARNINGS) -n -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." +.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 -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." +# 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 -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." +# Set PIP=true on the command line to skip installation of dependencies. +PIP = pip -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - - -extensions.rst: exts/pylint_extensions.py -extensions.rst: ../pylint/utils.py -extensions.rst: $(shell find ../pylint/extensions -type f -regex '.*\.py') -extensions.rst: $(shell find ../pylint/extensions -type f -regex '.*\.rst') - rm -f extensions.rst - PYTHONPATH=$(PYTHONPATH) $(PYTHON) ./exts/pylint_extensions.py - -features.rst: exts/pylint_features.py -features.rst: ../pylint/utils.py -features.rst: $(shell find ../pylint/checkers -type f -regex '.*\.py') - rm -f features.rst - PYTHONPATH=$(PYTHONPATH) $(PYTHON) ./exts/pylint_features.py - -gen-examples: - chmod u+w ../examples/pylintrc - pylint --rcfile=/dev/null --generate-rcfile > ../examples/pylintrc - -gen-man: - chmod u+w ../man/pylint.1 - pylint --rcfile=/dev/null --generate-man > ../man/pylint.1 - -all: html gen-man gen-examples +.PHONY html: install-dependencies +install-dependencies: + @echo "Install dependencies" + cd ../ && $(PIP) install -r doc/requirements.txt diff --git a/doc/backlinks.rst b/doc/backlinks.rst deleted file mode 100644 index 34323e8f73..0000000000 --- a/doc/backlinks.rst +++ /dev/null @@ -1,15 +0,0 @@ - -Some projects using Pylint --------------------------- -The following projects are known to use Pylint to help develop better -Python code: - -* edX (https://github.com/edx) -* qutebrowser (https://github.com/The-Compiler/qutebrowser) -* Odoo (https://github.com/OCA) -* Landscape.io (https://github.com/landscapeio/) -* Codacy (https://github.com/Codacy/) -* SaltStack (https://github.com/saltstack) -* CodeFactor (https://github.com/codefactor-io) -* many more... - diff --git a/doc/conf.py b/doc/conf.py index ada9ec4933..50d891eb93 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,5 +1,13 @@ -# -*- coding: utf-8 -*- -# +# 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. # @@ -11,233 +19,289 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys -import os -from datetime import datetime # 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')) +# 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' +# 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', - 'sphinx.ext.autosectionlabel', - 'sphinx.ext.intersphinx', + "pylint_features", + "pylint_extensions", + "pylint_messages", + "pylint_options", + "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", +} + + # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' -# The master toctree document. -master_doc = 'index' +# The root toctree document. +root_doc = "index" # General information about the project. -project = 'Pylint' +project = "Pylint" current_year = datetime.utcnow().year -copyright = '2003-{year}, Logilab, PyCQA and contributors'.format(year=current_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. -from pylint.__pkginfo__ import version +version = f"{numversion[0]}.{numversion[1]}" # The full version, including alpha/beta/rc tags. -release = version +release = __version__ # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# 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'] +exclude_patterns = ["_build", "data/**", "whatsnew/fragments"] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# 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 +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# 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 = 'python_docs_theme' +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. -html_theme_options = { - 'collapsiblesidebar': True, - 'issues_url': 'https://github.com/pycqa/pylint/issues/new', - 'root_name': 'PyCQA', - 'root_url': 'http://meta.pycqa.org/en/latest/', -} +# 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 = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# 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 +# 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 +# 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'] +# 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' +html_last_updated_fmt = "%b %d, %Y" smartquotes = False # Custom sidebar templates, maps document names to template names. -html_sidebars = { - '**': [ - 'localtoc.html', - 'globaltoc.html', - 'relations.html', - 'sourcelink.html' - ] -} +# 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 = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# 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 +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = 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 = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'Pylintdoc' +htmlhelp_basename = "Pylintdoc" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# 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', - 'Logilab, PyCQA and contributors', 'manual'), + ( + "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 +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Additional stuff for the LaTeX preamble. -#latex_preamble = '' +# latex_preamble = '' # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# 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', - ['Logilab, PyCQA and contributors'], 1) -] +man_pages = [("index", "pylint", "Pylint Documentation", [contributors], 1)] +# pylint: disable-next=consider-using-namedtuple-or-dataclass intersphinx_mapping = { - 'astroid': ('http://astroid.readthedocs.io/en/latest/', None), - 'python': ('https://docs.python.org/3', None), + "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 mulitple documents +# 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/.*" +] diff --git a/doc/contact.rst b/doc/contact.rst new file mode 100644 index 0000000000..cd3594f39b --- /dev/null +++ b/doc/contact.rst @@ -0,0 +1,58 @@ +Contact +======= + +Bug reports, feedback +--------------------- +.. _bug reports, feedback: + +You think you have found a bug in Pylint? Well, this may be the case +since Pylint and Python are under heavy development! + +Please take the time to check if it is already in the issue tracker at +https://github.com/pylint-dev/pylint + +Note that the issue might also be reported in one of Pylint's major dependencies, +astroid: + +* https://github.com/pylint-dev/astroid + +Discord server +-------------- + +You can discuss your problem using the discord server: + +https://discord.com/invite/Egy6P8AMB5 + +Mailing lists +------------- + +.. _Mailing lists: + +The code-quality mailing list is shared with other tools that aim +at improving the quality of python code. + +You can subscribe to this mailing list at +https://mail.python.org/mailman3/lists/code-quality.python.org/ + +Archives are available at +https://mail.python.org/pipermail/code-quality/ + +Archives before April 2013 are not available anymore. At +https://mail.python.org/pipermail/ it was under ``python-projects``. + +Support +------- + +.. image:: media/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White.png + :height: 150 + :alt: Tidelift + :align: left + :class: tideliftlogo + +Professional support for pylint is available as part of the `Tidelift +Subscription`_. Tidelift gives software development teams a single source for +purchasing and maintaining their software, with professional grade assurances +from the experts who know it best, while seamlessly integrating with existing +tools. + +.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-pylint?utm_source=pypi-pylint&utm_medium=referral&utm_campaign=readme diff --git a/doc/data/messages/a/abstract-class-instantiated/bad.py b/doc/data/messages/a/abstract-class-instantiated/bad.py new file mode 100644 index 0000000000..f514a5c3df --- /dev/null +++ b/doc/data/messages/a/abstract-class-instantiated/bad.py @@ -0,0 +1,10 @@ +import abc + + +class Animal(abc.ABC): + @abc.abstractmethod + def make_sound(self): + pass + + +sheep = Animal() # [abstract-class-instantiated] diff --git a/doc/data/messages/a/abstract-class-instantiated/good.py b/doc/data/messages/a/abstract-class-instantiated/good.py new file mode 100644 index 0000000000..c9dbce107b --- /dev/null +++ b/doc/data/messages/a/abstract-class-instantiated/good.py @@ -0,0 +1,15 @@ +import abc + + +class Animal(abc.ABC): + @abc.abstractmethod + def make_sound(self): + pass + + +class Sheep(Animal): + def make_sound(self): + print("bhaaaaa") + + +sheep = Sheep() diff --git a/doc/data/messages/a/abstract-method/bad/abstract_method.py b/doc/data/messages/a/abstract-method/bad/abstract_method.py new file mode 100644 index 0000000000..35e5c819dd --- /dev/null +++ b/doc/data/messages/a/abstract-method/bad/abstract_method.py @@ -0,0 +1,11 @@ +import abc + + +class WildAnimal: + @abc.abstractmethod + def make_sound(self): + pass + + +class Panther(WildAnimal): # [abstract-method] + pass diff --git a/doc/data/messages/a/abstract-method/bad/function_raising_not_implemented_error.py b/doc/data/messages/a/abstract-method/bad/function_raising_not_implemented_error.py new file mode 100644 index 0000000000..6a6a183af4 --- /dev/null +++ b/doc/data/messages/a/abstract-method/bad/function_raising_not_implemented_error.py @@ -0,0 +1,7 @@ +class Pet: + def make_sound(self): + raise NotImplementedError + + +class Cat(Pet): # [abstract-method] + pass diff --git a/doc/data/messages/a/abstract-method/good/abstract_method.py b/doc/data/messages/a/abstract-method/good/abstract_method.py new file mode 100644 index 0000000000..695443e48d --- /dev/null +++ b/doc/data/messages/a/abstract-method/good/abstract_method.py @@ -0,0 +1,12 @@ +import abc + + +class WildAnimal: + @abc.abstractmethod + def make_sound(self): + pass + + +class Panther(WildAnimal): + def make_sound(self): + print("MEEEOW") diff --git a/doc/data/messages/a/abstract-method/good/function_raising_not_implemented_error.py b/doc/data/messages/a/abstract-method/good/function_raising_not_implemented_error.py new file mode 100644 index 0000000000..d7635f223b --- /dev/null +++ b/doc/data/messages/a/abstract-method/good/function_raising_not_implemented_error.py @@ -0,0 +1,8 @@ +class Pet: + def make_sound(self): + raise NotImplementedError + + +class Cat(Pet): + def make_sound(self): + print("Meeeow") diff --git a/doc/data/messages/a/access-member-before-definition/bad.py b/doc/data/messages/a/access-member-before-definition/bad.py new file mode 100644 index 0000000000..64f349f279 --- /dev/null +++ b/doc/data/messages/a/access-member-before-definition/bad.py @@ -0,0 +1,5 @@ +class Unicorn: + def __init__(self, fluffiness_level): + if self.fluffiness_level > 9000: # [access-member-before-definition] + print("It's OVER-FLUFFYYYY ! *crush glasses*") + self.fluffiness_level = fluffiness_level diff --git a/doc/data/messages/a/access-member-before-definition/good.py b/doc/data/messages/a/access-member-before-definition/good.py new file mode 100644 index 0000000000..78d59fa9e8 --- /dev/null +++ b/doc/data/messages/a/access-member-before-definition/good.py @@ -0,0 +1,5 @@ +class Unicorn: + def __init__(self, fluffiness_level): + self.fluffiness_level = fluffiness_level + if self.fluffiness_level > 9000: + print("It's OVER-FLUFFYYYY ! *crush glasses*") diff --git a/doc/data/messages/a/anomalous-backslash-in-string/bad.py b/doc/data/messages/a/anomalous-backslash-in-string/bad.py new file mode 100644 index 0000000000..32da7ddcc0 --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/bad.py @@ -0,0 +1 @@ +string = "\z" # [syntax-error] diff --git a/doc/data/messages/a/anomalous-backslash-in-string/details.rst b/doc/data/messages/a/anomalous-backslash-in-string/details.rst new file mode 100644 index 0000000000..7f73b513e9 --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/details.rst @@ -0,0 +1,6 @@ +``\z`` is same as ``\\z`` because there's no escape sequence for ``z``. But it is not clear +for the reader of the code. + +The only reason this is demonstrated to raise ``syntax-error`` is because +pylint's CI now runs on Python 3.12, where this truly raises a ``SyntaxError``. +We hope to address this discrepancy in the documentation in the future. diff --git a/doc/data/messages/a/anomalous-backslash-in-string/good/double_escape.py b/doc/data/messages/a/anomalous-backslash-in-string/good/double_escape.py new file mode 100644 index 0000000000..1b2c0c8d39 --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/good/double_escape.py @@ -0,0 +1 @@ +string = "\\z" diff --git a/doc/data/messages/a/anomalous-backslash-in-string/good/existing_escape_sequence.py b/doc/data/messages/a/anomalous-backslash-in-string/good/existing_escape_sequence.py new file mode 100644 index 0000000000..511425a3bc --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/good/existing_escape_sequence.py @@ -0,0 +1 @@ +string = "\t" diff --git a/doc/data/messages/a/anomalous-backslash-in-string/good/r_prefix.py b/doc/data/messages/a/anomalous-backslash-in-string/good/r_prefix.py new file mode 100644 index 0000000000..e78a9ae65d --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/good/r_prefix.py @@ -0,0 +1 @@ +string = r"\z" diff --git a/doc/data/messages/a/anomalous-backslash-in-string/related.rst b/doc/data/messages/a/anomalous-backslash-in-string/related.rst new file mode 100644 index 0000000000..cb63bfd9f8 --- /dev/null +++ b/doc/data/messages/a/anomalous-backslash-in-string/related.rst @@ -0,0 +1,2 @@ +- `String and Bytes literals `_ +- `Long form stackoverflow explanation `_ diff --git a/doc/data/messages/a/anomalous-unicode-escape-in-string/bad.py b/doc/data/messages/a/anomalous-unicode-escape-in-string/bad.py new file mode 100644 index 0000000000..21d25eadf0 --- /dev/null +++ b/doc/data/messages/a/anomalous-unicode-escape-in-string/bad.py @@ -0,0 +1 @@ +print(b"\u%b" % b"0394") # [syntax-error] diff --git a/doc/data/messages/a/anomalous-unicode-escape-in-string/good.py b/doc/data/messages/a/anomalous-unicode-escape-in-string/good.py new file mode 100644 index 0000000000..c5f4cf46b5 --- /dev/null +++ b/doc/data/messages/a/anomalous-unicode-escape-in-string/good.py @@ -0,0 +1 @@ +print(b"\\u%b" % b"0394") diff --git a/doc/data/messages/a/arguments-differ/bad.py b/doc/data/messages/a/arguments-differ/bad.py new file mode 100644 index 0000000000..489ac9de3f --- /dev/null +++ b/doc/data/messages/a/arguments-differ/bad.py @@ -0,0 +1,8 @@ +class Drink: + def mix(self, fluid_one, fluid_two): + return fluid_one + fluid_two + + +class Cocktail(Drink): + def mix(self, fluid_one, fluid_two, alcoholic_fluid): # [arguments-differ] + return fluid_one + fluid_two + alcoholic_fluid diff --git a/doc/data/messages/a/arguments-differ/details.rst b/doc/data/messages/a/arguments-differ/details.rst new file mode 100644 index 0000000000..ba265b27de --- /dev/null +++ b/doc/data/messages/a/arguments-differ/details.rst @@ -0,0 +1,9 @@ +``argument-differ`` denotes an issue with the Liskov Substitution Principle. +This means that the code in question violates an important design principle which does not have +one single solution. We recommend to search online for the best solution in your case. + +To give some examples of potential solutions: + +* Add the argument to the parent class +* Remove the inheritance completely +* Add default arguments to the child class diff --git a/doc/data/messages/a/arguments-differ/good/add_option_in_base_class.py b/doc/data/messages/a/arguments-differ/good/add_option_in_base_class.py new file mode 100644 index 0000000000..35a1095b2a --- /dev/null +++ b/doc/data/messages/a/arguments-differ/good/add_option_in_base_class.py @@ -0,0 +1,20 @@ +""" +Here we assume that drink and cocktail are the same thing and should actually +inherit from each over. We also assume that 'Drink' are 'Cocktail' without +alcohol (we added the alcohol option in the base class). + +This permit to not have to modify the cocktails calls downstream but the case where +an alcohol is mixed in a soft drink will need to be handled. +""" + + +class Drink: + def mix(self, fluid_one, fluid_two, alcoholic_fluid=None): + # if alcoholic_fluid is not None: + # raise Exception(f"This soft drink has {alcoholic_fluid} in it !") + return fluid_one + fluid_two + + +class Cocktail(Drink): + def mix(self, fluid_one, fluid_two, alcoholic_fluid): + return fluid_one + fluid_two + alcoholic_fluid diff --git a/doc/data/messages/a/arguments-differ/good/default_value.py b/doc/data/messages/a/arguments-differ/good/default_value.py new file mode 100644 index 0000000000..7104e4a0d0 --- /dev/null +++ b/doc/data/messages/a/arguments-differ/good/default_value.py @@ -0,0 +1,18 @@ +""" +Here we assume that drink and cocktail are the same thing and should actually +inherit from each over. We also assume that any Cocktail can be treated like +a Drink (if you add beer to it). + +This permit to not have to modify the calls downstream and causes the least +amount of disturbance at the cost of making cocktails beer-based implicitly. +""" + + +class Drink: + def mix(self, fluid_one, fluid_two): + return fluid_one + fluid_two + + +class Cocktail(Drink): + def mix(self, fluid_one, fluid_two, alcoholic_fluid="Beer"): + return fluid_one + fluid_two + alcoholic_fluid diff --git a/doc/data/messages/a/arguments-differ/good/no_inheritance.py b/doc/data/messages/a/arguments-differ/good/no_inheritance.py new file mode 100644 index 0000000000..2fd282216a --- /dev/null +++ b/doc/data/messages/a/arguments-differ/good/no_inheritance.py @@ -0,0 +1,19 @@ +""" +Here we assume that 'Drink' and 'Cocktail' are different things and should +not be treated together like if they were the same thing. + +This will force some downstream changes and force the API user to make a +conscious decision about the alcoholic content of its drink when using the +API. For example, it's impossible to create a mojito with beer without +explicitly wanting to, or to add an alcohol to a soft-drink. +""" + + +class Drink: + def mix(self, fluid_one, fluid_two): + return fluid_one + fluid_two + + +class Cocktail: + def mix(self, fluid_one, fluid_two, alcoholic_fluid): + return fluid_one + fluid_two + alcoholic_fluid diff --git a/doc/data/messages/a/arguments-differ/related.rst b/doc/data/messages/a/arguments-differ/related.rst new file mode 100644 index 0000000000..db005e358b --- /dev/null +++ b/doc/data/messages/a/arguments-differ/related.rst @@ -0,0 +1 @@ +- `Liskov Substitution Principle `_ diff --git a/doc/data/messages/a/arguments-out-of-order/bad.py b/doc/data/messages/a/arguments-out-of-order/bad.py new file mode 100644 index 0000000000..06f6896e67 --- /dev/null +++ b/doc/data/messages/a/arguments-out-of-order/bad.py @@ -0,0 +1,13 @@ +def function_3_args(first_argument, second_argument, third_argument): + """Three arguments function""" + return first_argument, second_argument, third_argument + + +def args_out_of_order(): + first_argument = 1 + second_argument = 2 + third_argument = 3 + + function_3_args( # [arguments-out-of-order] + first_argument, third_argument, second_argument + ) diff --git a/doc/data/messages/a/arguments-out-of-order/good.py b/doc/data/messages/a/arguments-out-of-order/good.py new file mode 100644 index 0000000000..06ce7263f0 --- /dev/null +++ b/doc/data/messages/a/arguments-out-of-order/good.py @@ -0,0 +1,11 @@ +def function_3_args(first_argument, second_argument, third_argument): + """Three arguments function""" + return first_argument, second_argument, third_argument + + +def args_out_of_order(): + first_argument = 1 + second_argument = 2 + third_argument = 3 + + function_3_args(first_argument, second_argument, third_argument) diff --git a/doc/data/messages/a/arguments-renamed/bad.py b/doc/data/messages/a/arguments-renamed/bad.py new file mode 100644 index 0000000000..98f53a14b6 --- /dev/null +++ b/doc/data/messages/a/arguments-renamed/bad.py @@ -0,0 +1,15 @@ +class Fruit: + def brew(self, ingredient_name: str): + print(f"Brewing a {type(self)} with {ingredient_name}") + + +class Apple(Fruit): ... + + +class Orange(Fruit): + def brew(self, flavor: str): # [arguments-renamed] + print(f"Brewing an orange with {flavor}") + + +for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]: + fruit.brew(ingredient_name=ingredient_name) diff --git a/doc/data/messages/a/arguments-renamed/good.py b/doc/data/messages/a/arguments-renamed/good.py new file mode 100644 index 0000000000..e150d65df9 --- /dev/null +++ b/doc/data/messages/a/arguments-renamed/good.py @@ -0,0 +1,15 @@ +class Fruit: + def brew(self, ingredient_name: str): + print(f"Brewing a {type(self)} with {ingredient_name}") + + +class Apple(Fruit): ... + + +class Orange(Fruit): + def brew(self, ingredient_name: str): + print(f"Brewing an orange with {ingredient_name}") + + +for fruit, ingredient_name in [[Orange(), "thyme"], [Apple(), "cinnamon"]]: + fruit.brew(ingredient_name=ingredient_name) diff --git a/doc/data/messages/a/assert-on-string-literal/bad.py b/doc/data/messages/a/assert-on-string-literal/bad.py new file mode 100644 index 0000000000..adbe2a473e --- /dev/null +++ b/doc/data/messages/a/assert-on-string-literal/bad.py @@ -0,0 +1,3 @@ +def test_division(): + a = 9 / 3 + assert "No ZeroDivisionError were raised" # [assert-on-string-literal] diff --git a/doc/data/messages/a/assert-on-string-literal/details.rst b/doc/data/messages/a/assert-on-string-literal/details.rst new file mode 100644 index 0000000000..188d8817e5 --- /dev/null +++ b/doc/data/messages/a/assert-on-string-literal/details.rst @@ -0,0 +1,4 @@ +Directly asserting a string literal will always pass. The solution is to +test something that could fail, or not assert at all. + +For ``unittest`` assertions there is the similar :ref:`redundant-unittest-assert` message. diff --git a/doc/data/messages/a/assert-on-string-literal/good.py b/doc/data/messages/a/assert-on-string-literal/good.py new file mode 100644 index 0000000000..ba2707575f --- /dev/null +++ b/doc/data/messages/a/assert-on-string-literal/good.py @@ -0,0 +1,3 @@ +def test_division(): + a = 9 / 3 + assert a == 3 diff --git a/doc/data/messages/a/assert-on-string-literal/related.rst b/doc/data/messages/a/assert-on-string-literal/related.rst new file mode 100644 index 0000000000..ee8d29fa22 --- /dev/null +++ b/doc/data/messages/a/assert-on-string-literal/related.rst @@ -0,0 +1,3 @@ +- `Tests without assertion `_ +- `Testing that there is no error raised `_ +- `Parametrizing conditional raising `_ diff --git a/doc/data/messages/a/assert-on-tuple/bad.py b/doc/data/messages/a/assert-on-tuple/bad.py new file mode 100644 index 0000000000..ffcc34c536 --- /dev/null +++ b/doc/data/messages/a/assert-on-tuple/bad.py @@ -0,0 +1 @@ +assert (1, None) # [assert-on-tuple] diff --git a/doc/data/messages/a/assert-on-tuple/details.rst b/doc/data/messages/a/assert-on-tuple/details.rst new file mode 100644 index 0000000000..6efb4497f6 --- /dev/null +++ b/doc/data/messages/a/assert-on-tuple/details.rst @@ -0,0 +1,4 @@ +Directly asserting a non-empty tuple will always pass. The solution is to + test something that could fail, or not assert at all. + + For ``unittest`` assertions there is the similar :ref:`redundant-unittest-assert` message. diff --git a/doc/data/messages/a/assert-on-tuple/good.py b/doc/data/messages/a/assert-on-tuple/good.py new file mode 100644 index 0000000000..cea57cf274 --- /dev/null +++ b/doc/data/messages/a/assert-on-tuple/good.py @@ -0,0 +1,3 @@ +x, y = (1, None) +assert x +assert y diff --git a/doc/data/messages/a/assigning-non-slot/bad.py b/doc/data/messages/a/assigning-non-slot/bad.py new file mode 100644 index 0000000000..506ad42cd0 --- /dev/null +++ b/doc/data/messages/a/assigning-non-slot/bad.py @@ -0,0 +1,10 @@ +class Student: + __slots__ = ("name",) + + def __init__(self, name, surname): + self.name = name + self.surname = surname # [assigning-non-slot] + self.setup() + + def setup(self): + pass diff --git a/doc/data/messages/a/assigning-non-slot/good.py b/doc/data/messages/a/assigning-non-slot/good.py new file mode 100644 index 0000000000..733728618c --- /dev/null +++ b/doc/data/messages/a/assigning-non-slot/good.py @@ -0,0 +1,10 @@ +class Student: + __slots__ = ("name", "surname") + + def __init__(self, name, surname): + self.name = name + self.surname = surname + self.setup() + + def setup(self): + pass diff --git a/doc/data/messages/a/assignment-from-no-return/bad.py b/doc/data/messages/a/assignment-from-no-return/bad.py new file mode 100644 index 0000000000..ea3822a795 --- /dev/null +++ b/doc/data/messages/a/assignment-from-no-return/bad.py @@ -0,0 +1,5 @@ +def add(x, y): + print(x + y) + + +value = add(10, 10) # [assignment-from-no-return] diff --git a/doc/data/messages/a/assignment-from-no-return/good.py b/doc/data/messages/a/assignment-from-no-return/good.py new file mode 100644 index 0000000000..c019007e17 --- /dev/null +++ b/doc/data/messages/a/assignment-from-no-return/good.py @@ -0,0 +1,5 @@ +def add(x, y): + return x + y + + +value = add(10, 10) diff --git a/doc/data/messages/a/assignment-from-none/bad.py b/doc/data/messages/a/assignment-from-none/bad.py new file mode 100644 index 0000000000..033bd8974e --- /dev/null +++ b/doc/data/messages/a/assignment-from-none/bad.py @@ -0,0 +1,5 @@ +def function(): + return None + + +f = function() # [assignment-from-none] diff --git a/doc/data/messages/a/assignment-from-none/good.py b/doc/data/messages/a/assignment-from-none/good.py new file mode 100644 index 0000000000..d2f4cbc586 --- /dev/null +++ b/doc/data/messages/a/assignment-from-none/good.py @@ -0,0 +1,5 @@ +def function(): + return None + + +f = function() if function() else 1 diff --git a/doc/data/messages/a/astroid-error/details.rst b/doc/data/messages/a/astroid-error/details.rst new file mode 100644 index 0000000000..96e8f7ade7 --- /dev/null +++ b/doc/data/messages/a/astroid-error/details.rst @@ -0,0 +1,2 @@ +This is a message linked to an internal problem in pylint. There's nothing to change in your code, +but maybe in pylint's configuration or installation. diff --git a/doc/data/messages/a/attribute-defined-outside-init/bad.py b/doc/data/messages/a/attribute-defined-outside-init/bad.py new file mode 100644 index 0000000000..e62884d497 --- /dev/null +++ b/doc/data/messages/a/attribute-defined-outside-init/bad.py @@ -0,0 +1,3 @@ +class Student: + def register(self): + self.is_registered = True # [attribute-defined-outside-init] diff --git a/doc/data/messages/a/attribute-defined-outside-init/good.py b/doc/data/messages/a/attribute-defined-outside-init/good.py new file mode 100644 index 0000000000..cc7d7acb18 --- /dev/null +++ b/doc/data/messages/a/attribute-defined-outside-init/good.py @@ -0,0 +1,6 @@ +class Student: + def __init__(self): + self.is_registered = False + + def register(self): + self.is_registered = True diff --git a/doc/data/messages/a/await-outside-async/bad.py b/doc/data/messages/a/await-outside-async/bad.py new file mode 100644 index 0000000000..35fd8c3439 --- /dev/null +++ b/doc/data/messages/a/await-outside-async/bad.py @@ -0,0 +1,5 @@ +import asyncio + + +def main(): + await asyncio.sleep(1) # [await-outside-async] diff --git a/doc/data/messages/a/await-outside-async/good.py b/doc/data/messages/a/await-outside-async/good.py new file mode 100644 index 0000000000..231794be5e --- /dev/null +++ b/doc/data/messages/a/await-outside-async/good.py @@ -0,0 +1,5 @@ +import asyncio + + +async def main(): + await asyncio.sleep(1) diff --git a/doc/data/messages/a/await-outside-async/related.rst b/doc/data/messages/a/await-outside-async/related.rst new file mode 100644 index 0000000000..6cc66c6863 --- /dev/null +++ b/doc/data/messages/a/await-outside-async/related.rst @@ -0,0 +1 @@ +- `PEP 492 `_ diff --git a/doc/data/messages/b/bad-builtin/bad.py b/doc/data/messages/b/bad-builtin/bad.py new file mode 100644 index 0000000000..1c60815e59 --- /dev/null +++ b/doc/data/messages/b/bad-builtin/bad.py @@ -0,0 +1,2 @@ +numbers = list(map(lambda x: 2 * x, [1, 2, 3])) # [bad-builtin] +print(numbers) diff --git a/doc/data/messages/b/bad-builtin/good.py b/doc/data/messages/b/bad-builtin/good.py new file mode 100644 index 0000000000..c56dbfbe3c --- /dev/null +++ b/doc/data/messages/b/bad-builtin/good.py @@ -0,0 +1,2 @@ +numbers = [2 * x for x in [1, 2, 3]] +print(numbers) diff --git a/doc/data/messages/b/bad-builtin/pylintrc b/doc/data/messages/b/bad-builtin/pylintrc new file mode 100644 index 0000000000..d5dfb0cce8 --- /dev/null +++ b/doc/data/messages/b/bad-builtin/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins = pylint.extensions.bad_builtin diff --git a/doc/data/messages/b/bad-chained-comparison/bad/parrot.py b/doc/data/messages/b/bad-chained-comparison/bad/parrot.py new file mode 100644 index 0000000000..c3ab4d38d5 --- /dev/null +++ b/doc/data/messages/b/bad-chained-comparison/bad/parrot.py @@ -0,0 +1,7 @@ +shop = { + # animal: (specie, descriptions) + "parrot": ("Norvegian blue", ("restin'", "remarkable", "beautiful plumage")), +} + +if "parrot" in shop is "restin'": # [bad-chained-comparison] + print("Hellooooo, Pooolllllyyy ! WAAAAKEEY, WAKKEEEY !") diff --git a/doc/data/messages/b/bad-chained-comparison/bad/xor.py b/doc/data/messages/b/bad-chained-comparison/bad/xor.py new file mode 100644 index 0000000000..09e3ab627c --- /dev/null +++ b/doc/data/messages/b/bad-chained-comparison/bad/xor.py @@ -0,0 +1,5 @@ +def xor_check(*, left=None, right=None): + if left is None != right is None: # [bad-chained-comparison] + raise ValueError( + "Either both left= and right= need to be provided or none should." + ) diff --git a/doc/data/messages/b/bad-chained-comparison/good/parrot.py b/doc/data/messages/b/bad-chained-comparison/good/parrot.py new file mode 100644 index 0000000000..17f316f281 --- /dev/null +++ b/doc/data/messages/b/bad-chained-comparison/good/parrot.py @@ -0,0 +1,7 @@ +shop = { + # 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 !") diff --git a/doc/data/messages/b/bad-chained-comparison/good/xor.py b/doc/data/messages/b/bad-chained-comparison/good/xor.py new file mode 100644 index 0000000000..79bb641513 --- /dev/null +++ b/doc/data/messages/b/bad-chained-comparison/good/xor.py @@ -0,0 +1,5 @@ +def 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." + ) diff --git a/doc/data/messages/b/bad-chained-comparison/related.rst b/doc/data/messages/b/bad-chained-comparison/related.rst new file mode 100644 index 0000000000..620ba6df35 --- /dev/null +++ b/doc/data/messages/b/bad-chained-comparison/related.rst @@ -0,0 +1 @@ +- `Comparison Chaining `_ diff --git a/doc/data/messages/b/bad-classmethod-argument/bad.py b/doc/data/messages/b/bad-classmethod-argument/bad.py new file mode 100644 index 0000000000..b8c6d02a0d --- /dev/null +++ b/doc/data/messages/b/bad-classmethod-argument/bad.py @@ -0,0 +1,4 @@ +class Klass: + @classmethod + def get_instance(self): # [bad-classmethod-argument] + return self() diff --git a/doc/data/messages/b/bad-classmethod-argument/good.py b/doc/data/messages/b/bad-classmethod-argument/good.py new file mode 100644 index 0000000000..6097f1e362 --- /dev/null +++ b/doc/data/messages/b/bad-classmethod-argument/good.py @@ -0,0 +1,4 @@ +class Klass: + @classmethod + def get_instance(cls): + return cls() diff --git a/doc/data/messages/b/bad-configuration-section/details.rst b/doc/data/messages/b/bad-configuration-section/details.rst new file mode 100644 index 0000000000..86035a5e91 --- /dev/null +++ b/doc/data/messages/b/bad-configuration-section/details.rst @@ -0,0 +1,2 @@ +This 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). diff --git a/doc/data/messages/b/bad-docstring-quotes/bad.py b/doc/data/messages/b/bad-docstring-quotes/bad.py new file mode 100644 index 0000000000..bd800a40cc --- /dev/null +++ b/doc/data/messages/b/bad-docstring-quotes/bad.py @@ -0,0 +1,3 @@ +def foo(): # [bad-docstring-quotes] + "Docstring." + return diff --git a/doc/data/messages/b/bad-docstring-quotes/details.rst b/doc/data/messages/b/bad-docstring-quotes/details.rst new file mode 100644 index 0000000000..2a3add6814 --- /dev/null +++ b/doc/data/messages/b/bad-docstring-quotes/details.rst @@ -0,0 +1,2 @@ +From `PEP 257`: + "For consistency, always use ``"""triple double quotes"""`` around docstrings." diff --git a/doc/data/messages/b/bad-docstring-quotes/good.py b/doc/data/messages/b/bad-docstring-quotes/good.py new file mode 100644 index 0000000000..e5f6ceb590 --- /dev/null +++ b/doc/data/messages/b/bad-docstring-quotes/good.py @@ -0,0 +1,3 @@ +def foo(): + """Docstring.""" + return diff --git a/doc/data/messages/b/bad-docstring-quotes/pylintrc b/doc/data/messages/b/bad-docstring-quotes/pylintrc new file mode 100644 index 0000000000..6acf217beb --- /dev/null +++ b/doc/data/messages/b/bad-docstring-quotes/pylintrc @@ -0,0 +1,2 @@ +[main] +load-plugins=pylint.extensions.docstyle diff --git a/doc/data/messages/b/bad-docstring-quotes/related.rst b/doc/data/messages/b/bad-docstring-quotes/related.rst new file mode 100644 index 0000000000..bec6174927 --- /dev/null +++ b/doc/data/messages/b/bad-docstring-quotes/related.rst @@ -0,0 +1 @@ +- `PEP 257 โ€“ Docstring Conventions `_ diff --git a/doc/data/messages/b/bad-dunder-name/bad.py b/doc/data/messages/b/bad-dunder-name/bad.py new file mode 100644 index 0000000000..f01f65010e --- /dev/null +++ b/doc/data/messages/b/bad-dunder-name/bad.py @@ -0,0 +1,6 @@ +class Apples: + def _init_(self): # [bad-dunder-name] + pass + + def __hello__(self): # [bad-dunder-name] + print("hello") diff --git a/doc/data/messages/b/bad-dunder-name/good.py b/doc/data/messages/b/bad-dunder-name/good.py new file mode 100644 index 0000000000..4f0adb9b62 --- /dev/null +++ b/doc/data/messages/b/bad-dunder-name/good.py @@ -0,0 +1,6 @@ +class Apples: + def __init__(self): + pass + + def hello(self): + print("hello") diff --git a/doc/data/messages/b/bad-dunder-name/pylintrc b/doc/data/messages/b/bad-dunder-name/pylintrc new file mode 100644 index 0000000000..c70980544f --- /dev/null +++ b/doc/data/messages/b/bad-dunder-name/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.dunder diff --git a/doc/data/messages/b/bad-except-order/bad.py b/doc/data/messages/b/bad-except-order/bad.py new file mode 100644 index 0000000000..482b5154dd --- /dev/null +++ b/doc/data/messages/b/bad-except-order/bad.py @@ -0,0 +1,8 @@ +try: + 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 diff --git a/doc/data/messages/b/bad-except-order/good.py b/doc/data/messages/b/bad-except-order/good.py new file mode 100644 index 0000000000..e9cd318371 --- /dev/null +++ b/doc/data/messages/b/bad-except-order/good.py @@ -0,0 +1,6 @@ +try: + print(int(input())) +except TypeError: + raise +except Exception: + raise diff --git a/doc/data/messages/b/bad-exception-cause/bad.py b/doc/data/messages/b/bad-exception-cause/bad.py new file mode 100644 index 0000000000..ad4228af82 --- /dev/null +++ b/doc/data/messages/b/bad-exception-cause/bad.py @@ -0,0 +1,8 @@ +def 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 diff --git a/doc/data/messages/b/bad-exception-cause/good.py b/doc/data/messages/b/bad-exception-cause/good.py new file mode 100644 index 0000000000..3ccc47ba89 --- /dev/null +++ b/doc/data/messages/b/bad-exception-cause/good.py @@ -0,0 +1,7 @@ +def 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 diff --git a/doc/data/messages/b/bad-exception-cause/related.rst b/doc/data/messages/b/bad-exception-cause/related.rst new file mode 100644 index 0000000000..a51de77a00 --- /dev/null +++ b/doc/data/messages/b/bad-exception-cause/related.rst @@ -0,0 +1,2 @@ +- `The raise statement `_ +- `Explicit Exception Chaining `_ per PEP 3134 diff --git a/doc/data/messages/b/bad-file-encoding/bad.py b/doc/data/messages/b/bad-file-encoding/bad.py new file mode 100644 index 0000000000..a4ab46ea39 --- /dev/null +++ b/doc/data/messages/b/bad-file-encoding/bad.py @@ -0,0 +1 @@ +# coding: latin_1 # [bad-file-encoding] diff --git a/pylint/test/data/__init__.py b/doc/data/messages/b/bad-file-encoding/good.py similarity index 100% rename from pylint/test/data/__init__.py rename to doc/data/messages/b/bad-file-encoding/good.py diff --git a/doc/data/messages/b/bad-format-character/bad.py b/doc/data/messages/b/bad-format-character/bad.py new file mode 100644 index 0000000000..3925849ca7 --- /dev/null +++ b/doc/data/messages/b/bad-format-character/bad.py @@ -0,0 +1 @@ +print("%s %z" % ("hello", "world")) # [bad-format-character] diff --git a/doc/data/messages/b/bad-format-character/details.rst b/doc/data/messages/b/bad-format-character/details.rst new file mode 100644 index 0000000000..94733967bd --- /dev/null +++ b/doc/data/messages/b/bad-format-character/details.rst @@ -0,0 +1,2 @@ +This check is currently only active for "old-style" string formatting as seen in the examples. +See `Issue #6085 `_ for more information. diff --git a/doc/data/messages/b/bad-format-character/good.py b/doc/data/messages/b/bad-format-character/good.py new file mode 100644 index 0000000000..d8791a7ede --- /dev/null +++ b/doc/data/messages/b/bad-format-character/good.py @@ -0,0 +1 @@ +print("%s %s" % ("hello", "world")) diff --git a/doc/data/messages/b/bad-format-character/related.rst b/doc/data/messages/b/bad-format-character/related.rst new file mode 100644 index 0000000000..b6aadf541e --- /dev/null +++ b/doc/data/messages/b/bad-format-character/related.rst @@ -0,0 +1,2 @@ +- `Format String Syntax `_ +- `PyFormat `_ diff --git a/doc/data/messages/b/bad-format-string-key/bad.py b/doc/data/messages/b/bad-format-string-key/bad.py new file mode 100644 index 0000000000..346d02d149 --- /dev/null +++ b/doc/data/messages/b/bad-format-string-key/bad.py @@ -0,0 +1 @@ +print("%(one)d" % {"one": 1, 2: 2}) # [bad-format-string-key] diff --git a/doc/data/messages/b/bad-format-string-key/details.rst b/doc/data/messages/b/bad-format-string-key/details.rst new file mode 100644 index 0000000000..321b4a0baf --- /dev/null +++ b/doc/data/messages/b/bad-format-string-key/details.rst @@ -0,0 +1,6 @@ +This 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. diff --git a/doc/data/messages/b/bad-format-string-key/good.py b/doc/data/messages/b/bad-format-string-key/good.py new file mode 100644 index 0000000000..db7cfde04a --- /dev/null +++ b/doc/data/messages/b/bad-format-string-key/good.py @@ -0,0 +1 @@ +print("%(one)d, %(two)d" % {"one": 1, "two": 2}) diff --git a/doc/data/messages/b/bad-format-string/bad.py b/doc/data/messages/b/bad-format-string/bad.py new file mode 100644 index 0000000000..4cb811261d --- /dev/null +++ b/doc/data/messages/b/bad-format-string/bad.py @@ -0,0 +1 @@ +print("{a[0] + a[1]}".format(a=[0, 1])) # [bad-format-string] diff --git a/doc/data/messages/b/bad-format-string/good.py b/doc/data/messages/b/bad-format-string/good.py new file mode 100644 index 0000000000..10475fd67f --- /dev/null +++ b/doc/data/messages/b/bad-format-string/good.py @@ -0,0 +1 @@ +print("{a[0]} + {a[1]}".format(a=[0, 1])) diff --git a/doc/data/messages/b/bad-format-string/related.rst b/doc/data/messages/b/bad-format-string/related.rst new file mode 100644 index 0000000000..b6aadf541e --- /dev/null +++ b/doc/data/messages/b/bad-format-string/related.rst @@ -0,0 +1,2 @@ +- `Format String Syntax `_ +- `PyFormat `_ diff --git a/doc/data/messages/b/bad-indentation/bad.py b/doc/data/messages/b/bad-indentation/bad.py new file mode 100644 index 0000000000..dd5a8d90de --- /dev/null +++ b/doc/data/messages/b/bad-indentation/bad.py @@ -0,0 +1,2 @@ +if input(): + print('yes') # [bad-indentation] diff --git a/doc/data/messages/b/bad-indentation/details.rst b/doc/data/messages/b/bad-indentation/details.rst new file mode 100644 index 0000000000..1403e99336 --- /dev/null +++ b/doc/data/messages/b/bad-indentation/details.rst @@ -0,0 +1 @@ +The option ``--indent-string`` can be used to set the indentation unit for this check. diff --git a/doc/data/messages/b/bad-indentation/good.py b/doc/data/messages/b/bad-indentation/good.py new file mode 100644 index 0000000000..e7ba80a569 --- /dev/null +++ b/doc/data/messages/b/bad-indentation/good.py @@ -0,0 +1,2 @@ +if input(): + print("yes") diff --git a/doc/data/messages/b/bad-inline-option/bad.py b/doc/data/messages/b/bad-inline-option/bad.py new file mode 100644 index 0000000000..b244da97a2 --- /dev/null +++ b/doc/data/messages/b/bad-inline-option/bad.py @@ -0,0 +1,2 @@ +# 2:[bad-inline-option] +# pylint: disable line-too-long diff --git a/doc/data/messages/b/bad-inline-option/good.py b/doc/data/messages/b/bad-inline-option/good.py new file mode 100644 index 0000000000..9799fff2ce --- /dev/null +++ b/doc/data/messages/b/bad-inline-option/good.py @@ -0,0 +1 @@ +# pylint: disable=line-too-long diff --git a/doc/data/messages/b/bad-mcs-classmethod-argument/bad.py b/doc/data/messages/b/bad-mcs-classmethod-argument/bad.py new file mode 100644 index 0000000000..1cc79be7ea --- /dev/null +++ b/doc/data/messages/b/bad-mcs-classmethod-argument/bad.py @@ -0,0 +1,4 @@ +class Meta(type): + @classmethod + def foo(some): # [bad-mcs-classmethod-argument] + pass diff --git a/doc/data/messages/b/bad-mcs-classmethod-argument/good.py b/doc/data/messages/b/bad-mcs-classmethod-argument/good.py new file mode 100644 index 0000000000..544fd54513 --- /dev/null +++ b/doc/data/messages/b/bad-mcs-classmethod-argument/good.py @@ -0,0 +1,4 @@ +class Meta(type): + @classmethod + def foo(mcs): + pass diff --git a/doc/data/messages/b/bad-mcs-method-argument/bad.py b/doc/data/messages/b/bad-mcs-method-argument/bad.py new file mode 100644 index 0000000000..4bf47b2768 --- /dev/null +++ b/doc/data/messages/b/bad-mcs-method-argument/bad.py @@ -0,0 +1,3 @@ +class Meta(type): + def func(some): # [bad-mcs-method-argument] + pass diff --git a/doc/data/messages/b/bad-mcs-method-argument/good.py b/doc/data/messages/b/bad-mcs-method-argument/good.py new file mode 100644 index 0000000000..2ba1252612 --- /dev/null +++ b/doc/data/messages/b/bad-mcs-method-argument/good.py @@ -0,0 +1,3 @@ +class Meta(type): + def func(cls): + pass diff --git a/doc/data/messages/b/bad-open-mode/bad.py b/doc/data/messages/b/bad-open-mode/bad.py new file mode 100644 index 0000000000..59ad392c48 --- /dev/null +++ b/doc/data/messages/b/bad-open-mode/bad.py @@ -0,0 +1,3 @@ +def open_and_get_content(file_path): + with open(file_path, "rwx") as file: # [bad-open-mode] + return file.read() diff --git a/doc/data/messages/b/bad-open-mode/good.py b/doc/data/messages/b/bad-open-mode/good.py new file mode 100644 index 0000000000..b892c03c92 --- /dev/null +++ b/doc/data/messages/b/bad-open-mode/good.py @@ -0,0 +1,3 @@ +def open_and_get_content(file_path): + with open(file_path, "r") as file: + return file.read() diff --git a/doc/data/messages/b/bad-plugin-value/details.rst b/doc/data/messages/b/bad-plugin-value/details.rst new file mode 100644 index 0000000000..5beb0bdef6 --- /dev/null +++ b/doc/data/messages/b/bad-plugin-value/details.rst @@ -0,0 +1,14 @@ +One 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. diff --git a/doc/data/messages/b/bad-reversed-sequence/bad.py b/doc/data/messages/b/bad-reversed-sequence/bad.py new file mode 100644 index 0000000000..19c5d1a8a5 --- /dev/null +++ b/doc/data/messages/b/bad-reversed-sequence/bad.py @@ -0,0 +1 @@ +reversed({1, 2, 3, 4}) # [bad-reversed-sequence] diff --git a/doc/data/messages/b/bad-reversed-sequence/good.py b/doc/data/messages/b/bad-reversed-sequence/good.py new file mode 100644 index 0000000000..d39621893b --- /dev/null +++ b/doc/data/messages/b/bad-reversed-sequence/good.py @@ -0,0 +1 @@ +reversed([1, 2, 3, 4]) diff --git a/doc/data/messages/b/bad-staticmethod-argument/bad.py b/doc/data/messages/b/bad-staticmethod-argument/bad.py new file mode 100644 index 0000000000..a46d65a48a --- /dev/null +++ b/doc/data/messages/b/bad-staticmethod-argument/bad.py @@ -0,0 +1,4 @@ +class Wolf: + @staticmethod + def eat(self): # [bad-staticmethod-argument] + pass diff --git a/doc/data/messages/b/bad-staticmethod-argument/good.py b/doc/data/messages/b/bad-staticmethod-argument/good.py new file mode 100644 index 0000000000..7ad83f4929 --- /dev/null +++ b/doc/data/messages/b/bad-staticmethod-argument/good.py @@ -0,0 +1,4 @@ +class Wolf: + @staticmethod + def eat(sheep): + pass diff --git a/doc/data/messages/b/bad-str-strip-call/bad/hello_world.py b/doc/data/messages/b/bad-str-strip-call/bad/hello_world.py new file mode 100644 index 0000000000..606ce7766c --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/bad/hello_world.py @@ -0,0 +1,2 @@ +"Hello World".strip("Hello") # [bad-str-strip-call] +# >>> ' World' diff --git a/doc/data/messages/b/bad-str-strip-call/bad/remove_abc_from_both_side.py b/doc/data/messages/b/bad-str-strip-call/bad/remove_abc_from_both_side.py new file mode 100644 index 0000000000..e2d5f2c4be --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/bad/remove_abc_from_both_side.py @@ -0,0 +1,2 @@ +"abcbc def bacabc".strip("abcbc ") # [bad-str-strip-call] +# >>> 'def' diff --git a/doc/data/messages/b/bad-str-strip-call/details.rst b/doc/data/messages/b/bad-str-strip-call/details.rst new file mode 100644 index 0000000000..b2cc942d2a --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/details.rst @@ -0,0 +1,7 @@ +A 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. diff --git a/doc/data/messages/b/bad-str-strip-call/good/hello_world.py b/doc/data/messages/b/bad-str-strip-call/good/hello_world.py new file mode 100644 index 0000000000..f96344f50c --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/good/hello_world.py @@ -0,0 +1,2 @@ +"Hello World".strip("Helo") +# >>> ' World' diff --git a/doc/data/messages/b/bad-str-strip-call/good/remove_abc_from_both_side.py b/doc/data/messages/b/bad-str-strip-call/good/remove_abc_from_both_side.py new file mode 100644 index 0000000000..fea23df9ec --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/good/remove_abc_from_both_side.py @@ -0,0 +1,2 @@ +"abcbc def bacabc".strip("abc ") +# >>> 'def' diff --git a/doc/data/messages/b/bad-str-strip-call/related.rst b/doc/data/messages/b/bad-str-strip-call/related.rst new file mode 100644 index 0000000000..db9ab44201 --- /dev/null +++ b/doc/data/messages/b/bad-str-strip-call/related.rst @@ -0,0 +1 @@ +- Documentation: `str.strip([chars]) `_ diff --git a/doc/data/messages/b/bad-string-format-type/bad.py b/doc/data/messages/b/bad-string-format-type/bad.py new file mode 100644 index 0000000000..a58a5ba7b5 --- /dev/null +++ b/doc/data/messages/b/bad-string-format-type/bad.py @@ -0,0 +1 @@ +print("%d" % "1") # [bad-string-format-type] diff --git a/doc/data/messages/b/bad-string-format-type/details.rst b/doc/data/messages/b/bad-string-format-type/details.rst new file mode 100644 index 0000000000..c60738410d --- /dev/null +++ b/doc/data/messages/b/bad-string-format-type/details.rst @@ -0,0 +1,2 @@ +This check is currently only active for "old-style" string formatting as seen in the examples. +See `Issue #6085 `_ for more information. diff --git a/doc/data/messages/b/bad-string-format-type/good.py b/doc/data/messages/b/bad-string-format-type/good.py new file mode 100644 index 0000000000..00ee8aff79 --- /dev/null +++ b/doc/data/messages/b/bad-string-format-type/good.py @@ -0,0 +1 @@ +print("%d" % 1) diff --git a/doc/data/messages/b/bad-string-format-type/related.rst b/doc/data/messages/b/bad-string-format-type/related.rst new file mode 100644 index 0000000000..b6aadf541e --- /dev/null +++ b/doc/data/messages/b/bad-string-format-type/related.rst @@ -0,0 +1,2 @@ +- `Format String Syntax `_ +- `PyFormat `_ diff --git a/doc/data/messages/b/bad-super-call/bad.py b/doc/data/messages/b/bad-super-call/bad.py new file mode 100644 index 0000000000..625a70e6f9 --- /dev/null +++ b/doc/data/messages/b/bad-super-call/bad.py @@ -0,0 +1,12 @@ +class Animal: + pass + + +class Tree: + pass + + +class Cat(Animal): + def __init__(self): + super(Tree, self).__init__() # [bad-super-call] + super(Animal, self).__init__() diff --git a/doc/data/messages/b/bad-super-call/details.rst b/doc/data/messages/b/bad-super-call/details.rst new file mode 100644 index 0000000000..e5b0ab5c7d --- /dev/null +++ b/doc/data/messages/b/bad-super-call/details.rst @@ -0,0 +1,7 @@ +In 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()``. diff --git a/doc/data/messages/b/bad-super-call/good.py b/doc/data/messages/b/bad-super-call/good.py new file mode 100644 index 0000000000..66152bc73e --- /dev/null +++ b/doc/data/messages/b/bad-super-call/good.py @@ -0,0 +1,11 @@ +class Animal: + pass + + +class Tree: + pass + + +class Cat(Animal): + def __init__(self): + super(Animal, self).__init__() diff --git a/doc/data/messages/b/bad-super-call/related.rst b/doc/data/messages/b/bad-super-call/related.rst new file mode 100644 index 0000000000..5189197dd0 --- /dev/null +++ b/doc/data/messages/b/bad-super-call/related.rst @@ -0,0 +1 @@ +- `Documentation for super() `_ diff --git a/doc/data/messages/b/bad-thread-instantiation/bad.py b/doc/data/messages/b/bad-thread-instantiation/bad.py new file mode 100644 index 0000000000..20fa72f5a7 --- /dev/null +++ b/doc/data/messages/b/bad-thread-instantiation/bad.py @@ -0,0 +1,9 @@ +import threading + + +def thread_target(n): + print(n**2) + + +thread = threading.Thread(lambda: None) # [bad-thread-instantiation] +thread.start() diff --git a/doc/data/messages/b/bad-thread-instantiation/good.py b/doc/data/messages/b/bad-thread-instantiation/good.py new file mode 100644 index 0000000000..0dce7c342c --- /dev/null +++ b/doc/data/messages/b/bad-thread-instantiation/good.py @@ -0,0 +1,9 @@ +import threading + + +def thread_target(n): + print(n**2) + + +thread = threading.Thread(target=thread_target, args=(10,)) +thread.start() diff --git a/doc/data/messages/b/bare-except/bad.py b/doc/data/messages/b/bare-except/bad.py new file mode 100644 index 0000000000..33dea31287 --- /dev/null +++ b/doc/data/messages/b/bare-except/bad.py @@ -0,0 +1,4 @@ +try: + import platform_specific_module +except: # [bare-except] + platform_specific_module = None diff --git a/doc/data/messages/b/bare-except/details.rst b/doc/data/messages/b/bare-except/details.rst new file mode 100644 index 0000000000..e93c7ea01c --- /dev/null +++ b/doc/data/messages/b/bare-except/details.rst @@ -0,0 +1,3 @@ +A 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. diff --git a/doc/data/messages/b/bare-except/good.py b/doc/data/messages/b/bare-except/good.py new file mode 100644 index 0000000000..24baac945b --- /dev/null +++ b/doc/data/messages/b/bare-except/good.py @@ -0,0 +1,4 @@ +try: + import platform_specific_module +except ImportError: + platform_specific_module = None diff --git a/doc/data/messages/b/bare-except/related.rst b/doc/data/messages/b/bare-except/related.rst new file mode 100644 index 0000000000..978b57937a --- /dev/null +++ b/doc/data/messages/b/bare-except/related.rst @@ -0,0 +1 @@ +- `Programming recommendation in PEP8 `_ diff --git a/doc/data/messages/b/bidirectional-unicode/bad.py b/doc/data/messages/b/bidirectional-unicode/bad.py new file mode 100644 index 0000000000..52f3070747 --- /dev/null +++ b/doc/data/messages/b/bidirectional-unicode/bad.py @@ -0,0 +1,2 @@ +# +1: [bidirectional-unicode] +example = "xโ€" * 100 # "โ€x" is assigned diff --git a/doc/data/messages/b/bidirectional-unicode/good.py b/doc/data/messages/b/bidirectional-unicode/good.py new file mode 100644 index 0000000000..4a625ddb2f --- /dev/null +++ b/doc/data/messages/b/bidirectional-unicode/good.py @@ -0,0 +1 @@ +example = "x[U+2194]" * 100 diff --git a/doc/data/messages/b/binary-op-exception/bad.py b/doc/data/messages/b/binary-op-exception/bad.py new file mode 100644 index 0000000000..8ffd1ded97 --- /dev/null +++ b/doc/data/messages/b/binary-op-exception/bad.py @@ -0,0 +1,4 @@ +try: + 1 / 0 +except ZeroDivisionError or ValueError: # [binary-op-exception] + pass diff --git a/doc/data/messages/b/binary-op-exception/good.py b/doc/data/messages/b/binary-op-exception/good.py new file mode 100644 index 0000000000..945e422fb5 --- /dev/null +++ b/doc/data/messages/b/binary-op-exception/good.py @@ -0,0 +1,4 @@ +try: + 1 / 0 +except (ZeroDivisionError, ValueError): + pass diff --git a/doc/data/messages/b/boolean-datetime/bad.py b/doc/data/messages/b/boolean-datetime/bad.py new file mode 100644 index 0000000000..c36abd1b12 --- /dev/null +++ b/doc/data/messages/b/boolean-datetime/bad.py @@ -0,0 +1,8 @@ +import datetime + +if datetime.time(): # [boolean-datetime] + print("It is time.") + + +if datetime.datetime.now().time(): # [boolean-datetime] + print("Now or never.") diff --git a/doc/data/messages/b/boolean-datetime/good.py b/doc/data/messages/b/boolean-datetime/good.py new file mode 100644 index 0000000000..b846e0bd32 --- /dev/null +++ b/doc/data/messages/b/boolean-datetime/good.py @@ -0,0 +1,9 @@ +import 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!") diff --git a/doc/data/messages/b/boolean-datetime/pylintrc b/doc/data/messages/b/boolean-datetime/pylintrc new file mode 100644 index 0000000000..8429adcfd4 --- /dev/null +++ b/doc/data/messages/b/boolean-datetime/pylintrc @@ -0,0 +1,2 @@ +[main] +py-version=3.4 diff --git a/doc/data/messages/b/boolean-datetime/related.rst b/doc/data/messages/b/boolean-datetime/related.rst new file mode 100644 index 0000000000..5841313565 --- /dev/null +++ b/doc/data/messages/b/boolean-datetime/related.rst @@ -0,0 +1 @@ +- `Python bug tracker `_ diff --git a/doc/data/messages/b/broad-exception-caught/bad.py b/doc/data/messages/b/broad-exception-caught/bad.py new file mode 100644 index 0000000000..67d5d7b493 --- /dev/null +++ b/doc/data/messages/b/broad-exception-caught/bad.py @@ -0,0 +1,4 @@ +try: + import platform_specific_module +except Exception: # [broad-exception-caught] + platform_specific_module = None diff --git a/doc/data/messages/b/broad-exception-caught/details.rst b/doc/data/messages/b/broad-exception-caught/details.rst new file mode 100644 index 0000000000..ae7f1638cd --- /dev/null +++ b/doc/data/messages/b/broad-exception-caught/details.rst @@ -0,0 +1,3 @@ +For 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. diff --git a/doc/data/messages/b/broad-exception-caught/good.py b/doc/data/messages/b/broad-exception-caught/good.py new file mode 100644 index 0000000000..24baac945b --- /dev/null +++ b/doc/data/messages/b/broad-exception-caught/good.py @@ -0,0 +1,4 @@ +try: + import platform_specific_module +except ImportError: + platform_specific_module = None diff --git a/doc/data/messages/b/broad-exception-caught/related.rst b/doc/data/messages/b/broad-exception-caught/related.rst new file mode 100644 index 0000000000..23c74d2ac3 --- /dev/null +++ b/doc/data/messages/b/broad-exception-caught/related.rst @@ -0,0 +1 @@ +- `Should I always specify an exception type in 'except' statements? `_ diff --git a/doc/data/messages/b/broad-exception-raised/bad.py b/doc/data/messages/b/broad-exception-raised/bad.py new file mode 100644 index 0000000000..4c8ff3b5a3 --- /dev/null +++ b/doc/data/messages/b/broad-exception-raised/bad.py @@ -0,0 +1,4 @@ +def small_apple(apple, length): + if len(apple) < length: + raise Exception("Apple is too small!") # [broad-exception-raised] + print(f"{apple} is proper size.") diff --git a/doc/data/messages/b/broad-exception-raised/good.py b/doc/data/messages/b/broad-exception-raised/good.py new file mode 100644 index 0000000000..a63b1b3560 --- /dev/null +++ b/doc/data/messages/b/broad-exception-raised/good.py @@ -0,0 +1,4 @@ +def small_apple(apple, length): + if len(apple) < length: + raise ValueError("Apple is too small!") + print(f"{apple} is proper size.") diff --git a/doc/data/messages/b/broad-exception-raised/related.rst b/doc/data/messages/b/broad-exception-raised/related.rst new file mode 100644 index 0000000000..978b57937a --- /dev/null +++ b/doc/data/messages/b/broad-exception-raised/related.rst @@ -0,0 +1 @@ +- `Programming recommendation in PEP8 `_ diff --git a/doc/data/messages/b/broken-collections-callable/bad.py b/doc/data/messages/b/broken-collections-callable/bad.py new file mode 100644 index 0000000000..a90a992206 --- /dev/null +++ b/doc/data/messages/b/broken-collections-callable/bad.py @@ -0,0 +1,6 @@ +from collections.abc import Callable +from typing import Optional + + +def func() -> Optional[Callable[[int], None]]: # [broken-collections-callable] + ... diff --git a/doc/data/messages/b/broken-collections-callable/good.py b/doc/data/messages/b/broken-collections-callable/good.py new file mode 100644 index 0000000000..c89d593cc2 --- /dev/null +++ b/doc/data/messages/b/broken-collections-callable/good.py @@ -0,0 +1,4 @@ +from typing import Callable, Optional + + +def func() -> Optional[Callable[[int], None]]: ... diff --git a/doc/data/messages/b/broken-collections-callable/pylintrc b/doc/data/messages/b/broken-collections-callable/pylintrc new file mode 100644 index 0000000000..d075a593ef --- /dev/null +++ b/doc/data/messages/b/broken-collections-callable/pylintrc @@ -0,0 +1,3 @@ +[main] +py-version=3.9 +load-plugins=pylint.extensions.typing diff --git a/doc/data/messages/b/broken-collections-callable/related.rst b/doc/data/messages/b/broken-collections-callable/related.rst new file mode 100644 index 0000000000..b93a3d9615 --- /dev/null +++ b/doc/data/messages/b/broken-collections-callable/related.rst @@ -0,0 +1 @@ +- `bpo-42965 `_ diff --git a/doc/data/messages/b/broken-noreturn/bad.py b/doc/data/messages/b/broken-noreturn/bad.py new file mode 100644 index 0000000000..77baf763bf --- /dev/null +++ b/doc/data/messages/b/broken-noreturn/bad.py @@ -0,0 +1,5 @@ +from typing import NoReturn, Union + + +def exploding_apple(apple) -> Union[None, NoReturn]: # [broken-noreturn] + print(f"{apple} is about to explode") diff --git a/doc/data/messages/b/broken-noreturn/good.py b/doc/data/messages/b/broken-noreturn/good.py new file mode 100644 index 0000000000..ce4dc6e988 --- /dev/null +++ b/doc/data/messages/b/broken-noreturn/good.py @@ -0,0 +1,6 @@ +from typing import NoReturn + + +def exploding_apple(apple) -> NoReturn: + print(f"{apple} is about to explode") + raise Exception("{apple} exploded !") diff --git a/doc/data/messages/b/broken-noreturn/pylintrc b/doc/data/messages/b/broken-noreturn/pylintrc new file mode 100644 index 0000000000..eb28fc75b9 --- /dev/null +++ b/doc/data/messages/b/broken-noreturn/pylintrc @@ -0,0 +1,3 @@ +[main] +py-version=3.7 +load-plugins=pylint.extensions.typing diff --git a/doc/data/messages/c/c-extension-no-member/details.rst b/doc/data/messages/c/c-extension-no-member/details.rst new file mode 100644 index 0000000000..3f19677ff4 --- /dev/null +++ b/doc/data/messages/c/c-extension-no-member/details.rst @@ -0,0 +1,4 @@ +``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``. diff --git a/doc/data/messages/c/c-extension-no-member/good.py b/doc/data/messages/c/c-extension-no-member/good.py new file mode 100644 index 0000000000..c40beb573f --- /dev/null +++ b/doc/data/messages/c/c-extension-no-member/good.py @@ -0,0 +1 @@ +# This is a placeholder for correct code for this message. diff --git a/doc/data/messages/c/catching-non-exception/bad.py b/doc/data/messages/c/catching-non-exception/bad.py new file mode 100644 index 0000000000..86fa07b8a8 --- /dev/null +++ b/doc/data/messages/c/catching-non-exception/bad.py @@ -0,0 +1,8 @@ +class FooError: + pass + + +try: + 1 / 0 +except FooError: # [catching-non-exception] + pass diff --git a/doc/data/messages/c/catching-non-exception/good.py b/doc/data/messages/c/catching-non-exception/good.py new file mode 100644 index 0000000000..342fadab0e --- /dev/null +++ b/doc/data/messages/c/catching-non-exception/good.py @@ -0,0 +1,8 @@ +class FooError(Exception): + pass + + +try: + 1 / 0 +except FooError: + pass diff --git a/doc/data/messages/c/cell-var-from-loop/bad.py b/doc/data/messages/c/cell-var-from-loop/bad.py new file mode 100644 index 0000000000..c8b9e92924 --- /dev/null +++ b/doc/data/messages/c/cell-var-from-loop/bad.py @@ -0,0 +1,23 @@ +def 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!" diff --git a/doc/data/messages/c/cell-var-from-loop/good/functools.partial.py b/doc/data/messages/c/cell-var-from-loop/good/functools.partial.py new file mode 100644 index 0000000000..596909e52f --- /dev/null +++ b/doc/data/messages/c/cell-var-from-loop/good/functools.partial.py @@ -0,0 +1,23 @@ +import 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!" diff --git a/doc/data/messages/c/cell-var-from-loop/good/new_function.py b/doc/data/messages/c/cell-var-from-loop/good/new_function.py new file mode 100644 index 0000000000..002eca2cdb --- /dev/null +++ b/doc/data/messages/c/cell-var-from-loop/good/new_function.py @@ -0,0 +1,17 @@ +def 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!" diff --git a/doc/data/messages/c/cell-var-from-loop/related.rst b/doc/data/messages/c/cell-var-from-loop/related.rst new file mode 100644 index 0000000000..41129e5037 --- /dev/null +++ b/doc/data/messages/c/cell-var-from-loop/related.rst @@ -0,0 +1 @@ +- `Stackoverflow discussion `_ diff --git a/doc/data/messages/c/chained-comparison/bad.py b/doc/data/messages/c/chained-comparison/bad.py new file mode 100644 index 0000000000..b04c92772c --- /dev/null +++ b/doc/data/messages/c/chained-comparison/bad.py @@ -0,0 +1,5 @@ +a = int(input()) +b = int(input()) +c = int(input()) +if a < b and b < c: # [chained-comparison] + pass diff --git a/doc/data/messages/c/chained-comparison/good.py b/doc/data/messages/c/chained-comparison/good.py new file mode 100644 index 0000000000..9c4abff8ac --- /dev/null +++ b/doc/data/messages/c/chained-comparison/good.py @@ -0,0 +1,5 @@ +a = int(input()) +b = int(input()) +c = int(input()) +if a < b < c: + pass diff --git a/doc/data/messages/c/class-variable-slots-conflict/bad.py b/doc/data/messages/c/class-variable-slots-conflict/bad.py new file mode 100644 index 0000000000..7705669620 --- /dev/null +++ b/doc/data/messages/c/class-variable-slots-conflict/bad.py @@ -0,0 +1,15 @@ +class 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}.") diff --git a/doc/data/messages/c/class-variable-slots-conflict/good.py b/doc/data/messages/c/class-variable-slots-conflict/good.py new file mode 100644 index 0000000000..2428f78662 --- /dev/null +++ b/doc/data/messages/c/class-variable-slots-conflict/good.py @@ -0,0 +1,13 @@ +class 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}.") diff --git a/doc/data/messages/c/comparison-of-constants/bad.py b/doc/data/messages/c/comparison-of-constants/bad.py new file mode 100644 index 0000000000..2ea0c42231 --- /dev/null +++ b/doc/data/messages/c/comparison-of-constants/bad.py @@ -0,0 +1,2 @@ +def is_the_answer() -> bool: + return 42 == 42 # [comparison-of-constants] diff --git a/doc/data/messages/c/comparison-of-constants/good.py b/doc/data/messages/c/comparison-of-constants/good.py new file mode 100644 index 0000000000..731bb16123 --- /dev/null +++ b/doc/data/messages/c/comparison-of-constants/good.py @@ -0,0 +1,2 @@ +def is_the_answer(meaning_of_life: int) -> bool: + return meaning_of_life == 42 diff --git a/doc/data/messages/c/comparison-with-callable/bad.py b/doc/data/messages/c/comparison-with-callable/bad.py new file mode 100644 index 0000000000..1dbdad07c7 --- /dev/null +++ b/doc/data/messages/c/comparison-with-callable/bad.py @@ -0,0 +1,7 @@ +def function_returning_a_fruit() -> str: + return "orange" + + +def is_an_orange(fruit: str = "apple"): + # apple == + return fruit == function_returning_a_fruit # [comparison-with-callable] diff --git a/doc/data/messages/c/comparison-with-callable/good.py b/doc/data/messages/c/comparison-with-callable/good.py new file mode 100644 index 0000000000..a490071284 --- /dev/null +++ b/doc/data/messages/c/comparison-with-callable/good.py @@ -0,0 +1,7 @@ +def function_returning_a_fruit() -> str: + return "orange" + + +def is_an_orange(fruit: str = "apple"): + # apple == orange + return fruit == function_returning_a_fruit() diff --git a/doc/data/messages/c/comparison-with-itself/bad.py b/doc/data/messages/c/comparison-with-itself/bad.py new file mode 100644 index 0000000000..77794bc5c9 --- /dev/null +++ b/doc/data/messages/c/comparison-with-itself/bad.py @@ -0,0 +1,3 @@ +def is_an_orange(fruit): + an_orange = "orange" + return fruit == fruit # [comparison-with-itself] diff --git a/doc/data/messages/c/comparison-with-itself/good.py b/doc/data/messages/c/comparison-with-itself/good.py new file mode 100644 index 0000000000..b2b4296502 --- /dev/null +++ b/doc/data/messages/c/comparison-with-itself/good.py @@ -0,0 +1,3 @@ +def is_an_orange(fruit): + an_orange = "orange" + return an_orange == fruit diff --git a/doc/data/messages/c/condition-evals-to-constant/bad.py b/doc/data/messages/c/condition-evals-to-constant/bad.py new file mode 100644 index 0000000000..f52b24fc01 --- /dev/null +++ b/doc/data/messages/c/condition-evals-to-constant/bad.py @@ -0,0 +1,2 @@ +def is_a_fruit(fruit): + return bool(fruit in {"apple", "orange"} or True) # [condition-evals-to-constant] diff --git a/doc/data/messages/c/condition-evals-to-constant/good.py b/doc/data/messages/c/condition-evals-to-constant/good.py new file mode 100644 index 0000000000..37e9754910 --- /dev/null +++ b/doc/data/messages/c/condition-evals-to-constant/good.py @@ -0,0 +1,2 @@ +def is_a_fruit(fruit): + return fruit in {"apple", "orange"} diff --git a/doc/data/messages/c/config-parse-error/details.rst b/doc/data/messages/c/config-parse-error/details.rst new file mode 100644 index 0000000000..4fc0fe0768 --- /dev/null +++ b/doc/data/messages/c/config-parse-error/details.rst @@ -0,0 +1 @@ +This is a message linked to a problem in your configuration not your code. diff --git a/doc/data/messages/c/confusing-consecutive-elif/bad.py b/doc/data/messages/c/confusing-consecutive-elif/bad.py new file mode 100644 index 0000000000..93e1e2dee8 --- /dev/null +++ b/doc/data/messages/c/confusing-consecutive-elif/bad.py @@ -0,0 +1,6 @@ +def 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.") diff --git a/doc/data/messages/c/confusing-consecutive-elif/details.rst b/doc/data/messages/c/confusing-consecutive-elif/details.rst new file mode 100644 index 0000000000..bd2ecc4ee5 --- /dev/null +++ b/doc/data/messages/c/confusing-consecutive-elif/details.rst @@ -0,0 +1 @@ +Creating 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. diff --git a/doc/data/messages/c/confusing-consecutive-elif/good.py b/doc/data/messages/c/confusing-consecutive-elif/good.py new file mode 100644 index 0000000000..1722a6bfa6 --- /dev/null +++ b/doc/data/messages/c/confusing-consecutive-elif/good.py @@ -0,0 +1,22 @@ +# 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.") diff --git a/doc/data/messages/c/confusing-consecutive-elif/pylintrc b/doc/data/messages/c/confusing-consecutive-elif/pylintrc new file mode 100644 index 0000000000..6ceabfd962 --- /dev/null +++ b/doc/data/messages/c/confusing-consecutive-elif/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.confusing_elif diff --git a/doc/data/messages/c/confusing-with-statement/bad.py b/doc/data/messages/c/confusing-with-statement/bad.py new file mode 100644 index 0000000000..e6570a5aa1 --- /dev/null +++ b/doc/data/messages/c/confusing-with-statement/bad.py @@ -0,0 +1,2 @@ +with open("file.txt", "w") as fh1, fh2: # [confusing-with-statement] + pass diff --git a/doc/data/messages/c/confusing-with-statement/good.py b/doc/data/messages/c/confusing-with-statement/good.py new file mode 100644 index 0000000000..bcedaafa6f --- /dev/null +++ b/doc/data/messages/c/confusing-with-statement/good.py @@ -0,0 +1,3 @@ +with open("file.txt", "w", encoding="utf8") as fh1: + with open("file.txt", "w", encoding="utf8") as fh2: + pass diff --git a/doc/data/messages/c/consider-alternative-union-syntax/bad.py b/doc/data/messages/c/consider-alternative-union-syntax/bad.py new file mode 100644 index 0000000000..ea31c5f8aa --- /dev/null +++ b/doc/data/messages/c/consider-alternative-union-syntax/bad.py @@ -0,0 +1,3 @@ +from typing import Union + +cats: Union[int, str] # [consider-alternative-union-syntax] diff --git a/doc/data/messages/c/consider-alternative-union-syntax/good.py b/doc/data/messages/c/consider-alternative-union-syntax/good.py new file mode 100644 index 0000000000..07eb1d6aa9 --- /dev/null +++ b/doc/data/messages/c/consider-alternative-union-syntax/good.py @@ -0,0 +1 @@ +cats: int | str diff --git a/doc/data/messages/c/consider-alternative-union-syntax/pylintrc b/doc/data/messages/c/consider-alternative-union-syntax/pylintrc new file mode 100644 index 0000000000..0c377b2d30 --- /dev/null +++ b/doc/data/messages/c/consider-alternative-union-syntax/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins = pylint.extensions.typing diff --git a/doc/data/messages/c/consider-iterating-dictionary/bad.py b/doc/data/messages/c/consider-iterating-dictionary/bad.py new file mode 100644 index 0000000000..eb5a97ab41 --- /dev/null +++ b/doc/data/messages/c/consider-iterating-dictionary/bad.py @@ -0,0 +1,5 @@ +FRUITS = {"apple": 1, "pear": 5, "peach": 10} + + +for fruit in FRUITS.keys(): # [consider-iterating-dictionary] + print(fruit) diff --git a/doc/data/messages/c/consider-iterating-dictionary/good.py b/doc/data/messages/c/consider-iterating-dictionary/good.py new file mode 100644 index 0000000000..c67b3997c8 --- /dev/null +++ b/doc/data/messages/c/consider-iterating-dictionary/good.py @@ -0,0 +1,5 @@ +FRUITS = {"apple": 1, "pear": 5, "peach": 10} + + +for fruit in FRUITS: + print(fruit) diff --git a/doc/data/messages/c/consider-merging-isinstance/bad.py b/doc/data/messages/c/consider-merging-isinstance/bad.py new file mode 100644 index 0000000000..c7b059cb46 --- /dev/null +++ b/doc/data/messages/c/consider-merging-isinstance/bad.py @@ -0,0 +1,6 @@ +from typing import Any + + +def is_number(value: Any) -> bool: + # +1: [consider-merging-isinstance] + return isinstance(value, int) or isinstance(value, float) diff --git a/doc/data/messages/c/consider-merging-isinstance/good.py b/doc/data/messages/c/consider-merging-isinstance/good.py new file mode 100644 index 0000000000..993f69035e --- /dev/null +++ b/doc/data/messages/c/consider-merging-isinstance/good.py @@ -0,0 +1,5 @@ +from typing import Any + + +def is_number(value: Any) -> bool: + return isinstance(value, (int, float)) diff --git a/doc/data/messages/c/consider-refactoring-into-while-condition/bad.py b/doc/data/messages/c/consider-refactoring-into-while-condition/bad.py new file mode 100644 index 0000000000..edb6fe31d2 --- /dev/null +++ b/doc/data/messages/c/consider-refactoring-into-while-condition/bad.py @@ -0,0 +1,7 @@ +fruit_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") diff --git a/doc/data/messages/c/consider-refactoring-into-while-condition/good.py b/doc/data/messages/c/consider-refactoring-into-while-condition/good.py new file mode 100644 index 0000000000..900b9c6131 --- /dev/null +++ b/doc/data/messages/c/consider-refactoring-into-while-condition/good.py @@ -0,0 +1,5 @@ +fruit_basket = ["apple", "orange", "banana", "cherry", "guava"] + +while len(fruit_basket) != 0: + fruit = fruit_basket.pop() + print(f"We removed {fruit} from the basket") diff --git a/doc/data/messages/c/consider-refactoring-into-while-condition/pylintrc b/doc/data/messages/c/consider-refactoring-into-while-condition/pylintrc new file mode 100644 index 0000000000..7625181398 --- /dev/null +++ b/doc/data/messages/c/consider-refactoring-into-while-condition/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.consider_refactoring_into_while_condition diff --git a/doc/data/messages/c/consider-swap-variables/bad.py b/doc/data/messages/c/consider-swap-variables/bad.py new file mode 100644 index 0000000000..2092c993d5 --- /dev/null +++ b/doc/data/messages/c/consider-swap-variables/bad.py @@ -0,0 +1,6 @@ +a = 1 +b = 2 + +temp = a # [consider-swap-variables] +a = b +b = temp diff --git a/doc/data/messages/c/consider-swap-variables/good.py b/doc/data/messages/c/consider-swap-variables/good.py new file mode 100644 index 0000000000..1b92dcb6b0 --- /dev/null +++ b/doc/data/messages/c/consider-swap-variables/good.py @@ -0,0 +1,4 @@ +a = 1 +b = 2 + +a, b = b, a diff --git a/doc/data/messages/c/consider-ternary-expression/bad.py b/doc/data/messages/c/consider-ternary-expression/bad.py new file mode 100644 index 0000000000..126b92b0ed --- /dev/null +++ b/doc/data/messages/c/consider-ternary-expression/bad.py @@ -0,0 +1,5 @@ +x, y = input(), input() +if x >= y: # [consider-ternary-expression] + maximum = x +else: + maximum = y diff --git a/doc/data/messages/c/consider-ternary-expression/good.py b/doc/data/messages/c/consider-ternary-expression/good.py new file mode 100644 index 0000000000..117324054c --- /dev/null +++ b/doc/data/messages/c/consider-ternary-expression/good.py @@ -0,0 +1,2 @@ +x, y = input(), input() +maximum = x if x >= y else y diff --git a/doc/data/messages/c/consider-ternary-expression/pylintrc b/doc/data/messages/c/consider-ternary-expression/pylintrc new file mode 100644 index 0000000000..20f7725cd7 --- /dev/null +++ b/doc/data/messages/c/consider-ternary-expression/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.consider_ternary_expression diff --git a/doc/data/messages/c/consider-using-alias/bad.py b/doc/data/messages/c/consider-using-alias/bad.py new file mode 100644 index 0000000000..e3d0785935 --- /dev/null +++ b/doc/data/messages/c/consider-using-alias/bad.py @@ -0,0 +1,3 @@ +import typing + +cats: typing.Dict[str, int] # [consider-using-alias] diff --git a/doc/data/messages/c/consider-using-alias/good.py b/doc/data/messages/c/consider-using-alias/good.py new file mode 100644 index 0000000000..4277488db2 --- /dev/null +++ b/doc/data/messages/c/consider-using-alias/good.py @@ -0,0 +1,3 @@ +import typing + +cats: typing.cast(dict[str, int], "string") diff --git a/doc/data/messages/c/consider-using-alias/pylintrc b/doc/data/messages/c/consider-using-alias/pylintrc new file mode 100644 index 0000000000..038a94c774 --- /dev/null +++ b/doc/data/messages/c/consider-using-alias/pylintrc @@ -0,0 +1,4 @@ +[main] +load-plugins = pylint.extensions.typing +py-version = 3.7 +runtime-typing=no diff --git a/doc/data/messages/c/consider-using-any-or-all/bad/all_even.py b/doc/data/messages/c/consider-using-any-or-all/bad/all_even.py new file mode 100644 index 0000000000..53ef5403d1 --- /dev/null +++ b/doc/data/messages/c/consider-using-any-or-all/bad/all_even.py @@ -0,0 +1,6 @@ +def 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 diff --git a/doc/data/messages/c/consider-using-any-or-all/bad/any_even.py b/doc/data/messages/c/consider-using-any-or-all/bad/any_even.py new file mode 100644 index 0000000000..a98467409d --- /dev/null +++ b/doc/data/messages/c/consider-using-any-or-all/bad/any_even.py @@ -0,0 +1,6 @@ +def 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 diff --git a/doc/data/messages/c/consider-using-any-or-all/good/all_even.py b/doc/data/messages/c/consider-using-any-or-all/good/all_even.py new file mode 100644 index 0000000000..1fd24ee28c --- /dev/null +++ b/doc/data/messages/c/consider-using-any-or-all/good/all_even.py @@ -0,0 +1,3 @@ +def all_even(items): + """Return True if the list contains all even numbers""" + return all(item % 2 == 0 for item in items) diff --git a/doc/data/messages/c/consider-using-any-or-all/good/any_even.py b/doc/data/messages/c/consider-using-any-or-all/good/any_even.py new file mode 100644 index 0000000000..e26db4fef9 --- /dev/null +++ b/doc/data/messages/c/consider-using-any-or-all/good/any_even.py @@ -0,0 +1,3 @@ +def any_even(items): + """Return True if the list contains any even numbers""" + return any(item % 2 == 0 for item in items) diff --git a/doc/data/messages/c/consider-using-any-or-all/pylintrc b/doc/data/messages/c/consider-using-any-or-all/pylintrc new file mode 100644 index 0000000000..2fc8207935 --- /dev/null +++ b/doc/data/messages/c/consider-using-any-or-all/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.for_any_all diff --git a/doc/data/messages/c/consider-using-assignment-expr/bad.py b/doc/data/messages/c/consider-using-assignment-expr/bad.py new file mode 100644 index 0000000000..a700537fa9 --- /dev/null +++ b/doc/data/messages/c/consider-using-assignment-expr/bad.py @@ -0,0 +1,4 @@ +apples = 2 + +if apples: # [consider-using-assignment-expr] + print("God apples!") diff --git a/doc/data/messages/c/consider-using-assignment-expr/good.py b/doc/data/messages/c/consider-using-assignment-expr/good.py new file mode 100644 index 0000000000..a1e402701d --- /dev/null +++ b/doc/data/messages/c/consider-using-assignment-expr/good.py @@ -0,0 +1,2 @@ +if apples := 2: + print("God apples!") diff --git a/doc/data/messages/c/consider-using-assignment-expr/pylintrc b/doc/data/messages/c/consider-using-assignment-expr/pylintrc new file mode 100644 index 0000000000..14b316d488 --- /dev/null +++ b/doc/data/messages/c/consider-using-assignment-expr/pylintrc @@ -0,0 +1,3 @@ +[MAIN] +py-version=3.8 +load-plugins=pylint.extensions.code_style diff --git a/doc/data/messages/c/consider-using-augmented-assign/bad.py b/doc/data/messages/c/consider-using-augmented-assign/bad.py new file mode 100644 index 0000000000..90b8931a66 --- /dev/null +++ b/doc/data/messages/c/consider-using-augmented-assign/bad.py @@ -0,0 +1,2 @@ +x = 1 +x = x + 1 # [consider-using-augmented-assign] diff --git a/doc/data/messages/c/consider-using-augmented-assign/good.py b/doc/data/messages/c/consider-using-augmented-assign/good.py new file mode 100644 index 0000000000..3e34f6b266 --- /dev/null +++ b/doc/data/messages/c/consider-using-augmented-assign/good.py @@ -0,0 +1,2 @@ +x = 1 +x += 1 diff --git a/doc/data/messages/c/consider-using-augmented-assign/pylintrc b/doc/data/messages/c/consider-using-augmented-assign/pylintrc new file mode 100644 index 0000000000..5846022946 --- /dev/null +++ b/doc/data/messages/c/consider-using-augmented-assign/pylintrc @@ -0,0 +1,3 @@ +[MAIN] +load-plugins=pylint.extensions.code_style +enable=consider-using-augmented-assign diff --git a/doc/data/messages/c/consider-using-dict-comprehension/bad.py b/doc/data/messages/c/consider-using-dict-comprehension/bad.py new file mode 100644 index 0000000000..d9b02c71b0 --- /dev/null +++ b/doc/data/messages/c/consider-using-dict-comprehension/bad.py @@ -0,0 +1,4 @@ +NUMBERS = [1, 2, 3] + +# +1: [consider-using-dict-comprehension] +DOUBLED_NUMBERS = dict([(number, number * 2) for number in NUMBERS]) diff --git a/doc/data/messages/c/consider-using-dict-comprehension/details.rst b/doc/data/messages/c/consider-using-dict-comprehension/details.rst new file mode 100644 index 0000000000..f23dba1e8e --- /dev/null +++ b/doc/data/messages/c/consider-using-dict-comprehension/details.rst @@ -0,0 +1,4 @@ +pyupgrade_ or ruff_ can fix this issue automatically. + +.. _pyupgrade: https://github.com/asottile/pyupgrade +.. _ruff: https://docs.astral.sh/ruff/ diff --git a/doc/data/messages/c/consider-using-dict-comprehension/good.py b/doc/data/messages/c/consider-using-dict-comprehension/good.py new file mode 100644 index 0000000000..5f91d561a8 --- /dev/null +++ b/doc/data/messages/c/consider-using-dict-comprehension/good.py @@ -0,0 +1,3 @@ +NUMBERS = [1, 2, 3] + +DOUBLED_NUMBERS = {number: number * 2 for number in NUMBERS} diff --git a/doc/data/messages/c/consider-using-dict-items/bad.py b/doc/data/messages/c/consider-using-dict-items/bad.py new file mode 100644 index 0000000000..ce8d4d4cb8 --- /dev/null +++ b/doc/data/messages/c/consider-using-dict-items/bad.py @@ -0,0 +1,10 @@ +ORCHESTRA = { + "violin": "strings", + "oboe": "woodwind", + "tuba": "brass", + "gong": "percussion", +} + + +for instrument in ORCHESTRA: # [consider-using-dict-items] + print(f"{instrument}: {ORCHESTRA[instrument]}") diff --git a/doc/data/messages/c/consider-using-dict-items/good.py b/doc/data/messages/c/consider-using-dict-items/good.py new file mode 100644 index 0000000000..f719b1a525 --- /dev/null +++ b/doc/data/messages/c/consider-using-dict-items/good.py @@ -0,0 +1,10 @@ +ORCHESTRA = { + "violin": "strings", + "oboe": "woodwind", + "tuba": "brass", + "gong": "percussion", +} + + +for instrument, section in ORCHESTRA.items(): + print(f"{instrument}: {section}") diff --git a/doc/data/messages/c/consider-using-enumerate/bad.py b/doc/data/messages/c/consider-using-enumerate/bad.py new file mode 100644 index 0000000000..0beee2ecd5 --- /dev/null +++ b/doc/data/messages/c/consider-using-enumerate/bad.py @@ -0,0 +1,4 @@ +seasons = ["Spring", "Summer", "Fall", "Winter"] + +for i in range(len(seasons)): # [consider-using-enumerate] + print(i, seasons[i]) diff --git a/doc/data/messages/c/consider-using-enumerate/good.py b/doc/data/messages/c/consider-using-enumerate/good.py new file mode 100644 index 0000000000..b078e48cb3 --- /dev/null +++ b/doc/data/messages/c/consider-using-enumerate/good.py @@ -0,0 +1,4 @@ +seasons = ["Spring", "Summer", "Fall", "Winter"] + +for i, season in enumerate(seasons): + print(i, season) diff --git a/doc/data/messages/c/consider-using-f-string/bad.py b/doc/data/messages/c/consider-using-f-string/bad.py new file mode 100644 index 0000000000..26da6a1667 --- /dev/null +++ b/doc/data/messages/c/consider-using-f-string/bad.py @@ -0,0 +1,16 @@ +from 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] +) diff --git a/doc/data/messages/c/consider-using-f-string/details.rst b/doc/data/messages/c/consider-using-f-string/details.rst new file mode 100644 index 0000000000..6b2d0e48ba --- /dev/null +++ b/doc/data/messages/c/consider-using-f-string/details.rst @@ -0,0 +1,7 @@ +Formatted 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. diff --git a/doc/data/messages/c/consider-using-f-string/good.py b/doc/data/messages/c/consider-using-f-string/good.py new file mode 100644 index 0000000000..f7913fa44d --- /dev/null +++ b/doc/data/messages/c/consider-using-f-string/good.py @@ -0,0 +1,3 @@ +menu = ("eggs", "spam", 42.4) + +f_string_order = f"{menu[0]} and {menu[1]}: {menu[2]:0.2f} ยค" diff --git a/doc/data/messages/c/consider-using-from-import/bad.py b/doc/data/messages/c/consider-using-from-import/bad.py new file mode 100644 index 0000000000..ff2f48913f --- /dev/null +++ b/doc/data/messages/c/consider-using-from-import/bad.py @@ -0,0 +1 @@ +import os.path as path # [consider-using-from-import] diff --git a/doc/data/messages/c/consider-using-from-import/good.py b/doc/data/messages/c/consider-using-from-import/good.py new file mode 100644 index 0000000000..cfd7c6825b --- /dev/null +++ b/doc/data/messages/c/consider-using-from-import/good.py @@ -0,0 +1 @@ +from os import path diff --git a/doc/data/messages/c/consider-using-generator/bad.py b/doc/data/messages/c/consider-using-generator/bad.py new file mode 100644 index 0000000000..260ec97d32 --- /dev/null +++ b/doc/data/messages/c/consider-using-generator/bad.py @@ -0,0 +1,5 @@ +list([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] diff --git a/doc/data/messages/c/consider-using-generator/details.rst b/doc/data/messages/c/consider-using-generator/details.rst new file mode 100644 index 0000000000..ab7a90e8bb --- /dev/null +++ b/doc/data/messages/c/consider-using-generator/details.rst @@ -0,0 +1,5 @@ +Removing ``[]`` 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. diff --git a/doc/data/messages/c/consider-using-generator/good.py b/doc/data/messages/c/consider-using-generator/good.py new file mode 100644 index 0000000000..667416784d --- /dev/null +++ b/doc/data/messages/c/consider-using-generator/good.py @@ -0,0 +1,5 @@ +list(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))) diff --git a/doc/data/messages/c/consider-using-generator/related.rst b/doc/data/messages/c/consider-using-generator/related.rst new file mode 100644 index 0000000000..24727cf258 --- /dev/null +++ b/doc/data/messages/c/consider-using-generator/related.rst @@ -0,0 +1,3 @@ +- `PEP 289 `_ +- `Benchmark and discussion for any/all/list/tuple `_ +- `Benchmark and discussion for sum/max/min `_ diff --git a/doc/data/messages/c/consider-using-get/bad.py b/doc/data/messages/c/consider-using-get/bad.py new file mode 100644 index 0000000000..b820c5698a --- /dev/null +++ b/doc/data/messages/c/consider-using-get/bad.py @@ -0,0 +1,6 @@ +knights = {"Gallahad": "the pure", "Robin": "the brave"} + +if "Gallahad" in knights: # [consider-using-get] + DESCRIPTION = knights["Gallahad"] +else: + DESCRIPTION = "" diff --git a/doc/data/messages/c/consider-using-get/good.py b/doc/data/messages/c/consider-using-get/good.py new file mode 100644 index 0000000000..eba9976afa --- /dev/null +++ b/doc/data/messages/c/consider-using-get/good.py @@ -0,0 +1,3 @@ +knights = {"Gallahad": "the pure", "Robin": "the brave"} + +description = knights.get("Gallahad", "") diff --git a/doc/data/messages/c/consider-using-in/bad.py b/doc/data/messages/c/consider-using-in/bad.py new file mode 100644 index 0000000000..81eddb7f36 --- /dev/null +++ b/doc/data/messages/c/consider-using-in/bad.py @@ -0,0 +1,3 @@ +def fruit_is_round(fruit): + # +1: [consider-using-in] + return fruit == "apple" or fruit == "orange" or fruit == "melon" diff --git a/doc/data/messages/c/consider-using-in/good.py b/doc/data/messages/c/consider-using-in/good.py new file mode 100644 index 0000000000..bc308fa647 --- /dev/null +++ b/doc/data/messages/c/consider-using-in/good.py @@ -0,0 +1,2 @@ +def fruit_is_round(fruit): + return fruit in {"apple", "orange", "melon"} diff --git a/doc/data/messages/c/consider-using-join/bad.py b/doc/data/messages/c/consider-using-join/bad.py new file mode 100644 index 0000000000..5d5a32fb78 --- /dev/null +++ b/doc/data/messages/c/consider-using-join/bad.py @@ -0,0 +1,8 @@ +def 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"])) diff --git a/doc/data/messages/c/consider-using-join/good.py b/doc/data/messages/c/consider-using-join/good.py new file mode 100644 index 0000000000..1ee43ed6b8 --- /dev/null +++ b/doc/data/messages/c/consider-using-join/good.py @@ -0,0 +1 @@ +print("".join(["apple", "pear", "peach"])) diff --git a/doc/data/messages/c/consider-using-max-builtin/bad.py b/doc/data/messages/c/consider-using-max-builtin/bad.py new file mode 100644 index 0000000000..3e66cee96e --- /dev/null +++ b/doc/data/messages/c/consider-using-max-builtin/bad.py @@ -0,0 +1,7 @@ +def get_max(value1, value2): + if value1 < value2: # [consider-using-max-builtin] + value1 = value2 + return value1 + + +print(get_max(1, 2)) diff --git a/doc/data/messages/c/consider-using-max-builtin/good.py b/doc/data/messages/c/consider-using-max-builtin/good.py new file mode 100644 index 0000000000..90af411bfa --- /dev/null +++ b/doc/data/messages/c/consider-using-max-builtin/good.py @@ -0,0 +1 @@ +print(max(1, 2)) diff --git a/doc/data/messages/c/consider-using-min-builtin/bad.py b/doc/data/messages/c/consider-using-min-builtin/bad.py new file mode 100644 index 0000000000..007371a5db --- /dev/null +++ b/doc/data/messages/c/consider-using-min-builtin/bad.py @@ -0,0 +1,7 @@ +def get_min(value1, value2): + if value1 > value2: # [consider-using-min-builtin] + value1 = value2 + return value1 + + +print(get_min(1, 2)) diff --git a/doc/data/messages/c/consider-using-min-builtin/good.py b/doc/data/messages/c/consider-using-min-builtin/good.py new file mode 100644 index 0000000000..19951295ac --- /dev/null +++ b/doc/data/messages/c/consider-using-min-builtin/good.py @@ -0,0 +1 @@ +print(min(1, 2)) diff --git a/doc/data/messages/c/consider-using-namedtuple-or-dataclass/bad.py b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/bad.py new file mode 100644 index 0000000000..d1f3ebab23 --- /dev/null +++ b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/bad.py @@ -0,0 +1,14 @@ +FELIDAES = { # [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, + }, +} diff --git a/doc/data/messages/c/consider-using-namedtuple-or-dataclass/good.py b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/good.py new file mode 100644 index 0000000000..b13713f597 --- /dev/null +++ b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/good.py @@ -0,0 +1,18 @@ +from 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" + ), +} diff --git a/doc/data/messages/c/consider-using-namedtuple-or-dataclass/pylintrc b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/pylintrc new file mode 100644 index 0000000000..8663ab085d --- /dev/null +++ b/doc/data/messages/c/consider-using-namedtuple-or-dataclass/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.code_style diff --git a/doc/data/messages/c/consider-using-set-comprehension/bad.py b/doc/data/messages/c/consider-using-set-comprehension/bad.py new file mode 100644 index 0000000000..ffdc9e526f --- /dev/null +++ b/doc/data/messages/c/consider-using-set-comprehension/bad.py @@ -0,0 +1,4 @@ +NUMBERS = [1, 2, 2, 3, 4, 4] + +# +1: [consider-using-set-comprehension] +UNIQUE_EVEN_NUMBERS = set([number for number in NUMBERS if number % 2 == 0]) diff --git a/doc/data/messages/c/consider-using-set-comprehension/details.rst b/doc/data/messages/c/consider-using-set-comprehension/details.rst new file mode 100644 index 0000000000..f23dba1e8e --- /dev/null +++ b/doc/data/messages/c/consider-using-set-comprehension/details.rst @@ -0,0 +1,4 @@ +pyupgrade_ or ruff_ can fix this issue automatically. + +.. _pyupgrade: https://github.com/asottile/pyupgrade +.. _ruff: https://docs.astral.sh/ruff/ diff --git a/doc/data/messages/c/consider-using-set-comprehension/good.py b/doc/data/messages/c/consider-using-set-comprehension/good.py new file mode 100644 index 0000000000..4914fc2b00 --- /dev/null +++ b/doc/data/messages/c/consider-using-set-comprehension/good.py @@ -0,0 +1,3 @@ +NUMBERS = [1, 2, 2, 3, 4, 4] + +UNIQUE_EVEN_NUMBERS = {number for number in NUMBERS if number % 2 == 0} diff --git a/doc/data/messages/c/consider-using-sys-exit/bad.py b/doc/data/messages/c/consider-using-sys-exit/bad.py new file mode 100644 index 0000000000..1acc22a158 --- /dev/null +++ b/doc/data/messages/c/consider-using-sys-exit/bad.py @@ -0,0 +1,4 @@ +if __name__ == "__main__": + user = input("Enter user name: ") + print(f"Hello, {user}") + exit(0) # [consider-using-sys-exit] diff --git a/doc/data/messages/c/consider-using-sys-exit/good.py b/doc/data/messages/c/consider-using-sys-exit/good.py new file mode 100644 index 0000000000..acacd343a6 --- /dev/null +++ b/doc/data/messages/c/consider-using-sys-exit/good.py @@ -0,0 +1,6 @@ +import sys + +if __name__ == "__main__": + user = input("Enter user name: ") + print(f"Hello, {user}") + sys.exit(0) diff --git a/doc/data/messages/c/consider-using-ternary/bad.py b/doc/data/messages/c/consider-using-ternary/bad.py new file mode 100644 index 0000000000..bd69aa99e7 --- /dev/null +++ b/doc/data/messages/c/consider-using-ternary/bad.py @@ -0,0 +1,2 @@ +x, y = 1, 2 +maximum = x >= y and x or y # [consider-using-ternary] diff --git a/doc/data/messages/c/consider-using-ternary/good.py b/doc/data/messages/c/consider-using-ternary/good.py new file mode 100644 index 0000000000..bcb8446bce --- /dev/null +++ b/doc/data/messages/c/consider-using-ternary/good.py @@ -0,0 +1,2 @@ +x, y = 1, 2 +maximum = x if x >= y else y diff --git a/doc/data/messages/c/consider-using-tuple/bad.py b/doc/data/messages/c/consider-using-tuple/bad.py new file mode 100644 index 0000000000..099efb93e7 --- /dev/null +++ b/doc/data/messages/c/consider-using-tuple/bad.py @@ -0,0 +1,2 @@ +for i in [1, 2, 3]: # [consider-using-tuple] + print(i) diff --git a/doc/data/messages/c/consider-using-tuple/good.py b/doc/data/messages/c/consider-using-tuple/good.py new file mode 100644 index 0000000000..c0e2e70049 --- /dev/null +++ b/doc/data/messages/c/consider-using-tuple/good.py @@ -0,0 +1,2 @@ +for i in (1, 2, 3): + print(i) diff --git a/doc/data/messages/c/consider-using-tuple/pylintrc b/doc/data/messages/c/consider-using-tuple/pylintrc new file mode 100644 index 0000000000..8663ab085d --- /dev/null +++ b/doc/data/messages/c/consider-using-tuple/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.code_style diff --git a/doc/data/messages/c/consider-using-with/bad/close.py b/doc/data/messages/c/consider-using-with/bad/close.py new file mode 100644 index 0000000000..b3fddc1320 --- /dev/null +++ b/doc/data/messages/c/consider-using-with/bad/close.py @@ -0,0 +1,3 @@ +file = open("apple.txt", "r", encoding="utf8") # [consider-using-with] +contents = file.read() +file.close() diff --git a/doc/data/messages/c/consider-using-with/bad/not_even_close.py b/doc/data/messages/c/consider-using-with/bad/not_even_close.py new file mode 100644 index 0000000000..a0b51f0109 --- /dev/null +++ b/doc/data/messages/c/consider-using-with/bad/not_even_close.py @@ -0,0 +1 @@ +contents = open("apple.txt", "r", encoding="utf8").read() # [consider-using-with] diff --git a/doc/data/messages/c/consider-using-with/details.rst b/doc/data/messages/c/consider-using-with/details.rst new file mode 100644 index 0000000000..58d763fa4a --- /dev/null +++ b/doc/data/messages/c/consider-using-with/details.rst @@ -0,0 +1,10 @@ +Calling ``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 diff --git a/doc/data/messages/c/consider-using-with/good.py b/doc/data/messages/c/consider-using-with/good.py new file mode 100644 index 0000000000..3994259fc5 --- /dev/null +++ b/doc/data/messages/c/consider-using-with/good.py @@ -0,0 +1,2 @@ +with open("apple.txt", "r", encoding="utf8") as file: + contents = file.read() diff --git a/doc/data/messages/c/consider-using-with/related.rst b/doc/data/messages/c/consider-using-with/related.rst new file mode 100644 index 0000000000..a2a209ca0d --- /dev/null +++ b/doc/data/messages/c/consider-using-with/related.rst @@ -0,0 +1,4 @@ +- `Python doc: Reading and writing files `_ +- `PEP 343 `_ +- `Context managers in Python `_ by John Lekberg +- `Rationale `_ diff --git a/doc/data/messages/c/contextmanager-generator-missing-cleanup/bad.py b/doc/data/messages/c/contextmanager-generator-missing-cleanup/bad.py new file mode 100644 index 0000000000..b2072f7b19 --- /dev/null +++ b/doc/data/messages/c/contextmanager-generator-missing-cleanup/bad.py @@ -0,0 +1,14 @@ +import 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 diff --git a/doc/data/messages/c/contextmanager-generator-missing-cleanup/details.rst b/doc/data/messages/c/contextmanager-generator-missing-cleanup/details.rst new file mode 100644 index 0000000000..50b948fb54 --- /dev/null +++ b/doc/data/messages/c/contextmanager-generator-missing-cleanup/details.rst @@ -0,0 +1,31 @@ +Instantiating 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 diff --git a/doc/data/messages/c/contextmanager-generator-missing-cleanup/good.py b/doc/data/messages/c/contextmanager-generator-missing-cleanup/good.py new file mode 100644 index 0000000000..2287e86a59 --- /dev/null +++ b/doc/data/messages/c/contextmanager-generator-missing-cleanup/good.py @@ -0,0 +1,61 @@ +import 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 diff --git a/doc/data/messages/c/contextmanager-generator-missing-cleanup/related.rst b/doc/data/messages/c/contextmanager-generator-missing-cleanup/related.rst new file mode 100644 index 0000000000..aacc968cd5 --- /dev/null +++ b/doc/data/messages/c/contextmanager-generator-missing-cleanup/related.rst @@ -0,0 +1,2 @@ +- `Rationale `_ +- `CPython Issue `_ diff --git a/doc/data/messages/c/continue-in-finally/bad.py b/doc/data/messages/c/continue-in-finally/bad.py new file mode 100644 index 0000000000..190463f5a0 --- /dev/null +++ b/doc/data/messages/c/continue-in-finally/bad.py @@ -0,0 +1,5 @@ +while True: + try: + pass + finally: + continue # [continue-in-finally] diff --git a/doc/data/messages/c/continue-in-finally/details.rst b/doc/data/messages/c/continue-in-finally/details.rst new file mode 100644 index 0000000000..2d9044ee1a --- /dev/null +++ b/doc/data/messages/c/continue-in-finally/details.rst @@ -0,0 +1 @@ +Note this message can't be emitted when using Python version 3.8 or greater. diff --git a/doc/data/messages/c/continue-in-finally/good.py b/doc/data/messages/c/continue-in-finally/good.py new file mode 100644 index 0000000000..6b14ef4462 --- /dev/null +++ b/doc/data/messages/c/continue-in-finally/good.py @@ -0,0 +1,7 @@ +while True: + try: + pass + except ValueError: + pass + else: + continue diff --git a/doc/data/messages/c/continue-in-finally/pylintrc b/doc/data/messages/c/continue-in-finally/pylintrc new file mode 100644 index 0000000000..b7a429f3d4 --- /dev/null +++ b/doc/data/messages/c/continue-in-finally/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +py-version=3.7 diff --git a/pylint/test/extensions/__init__.py b/doc/data/messages/c/cyclic-import/bad/__init__.py similarity index 100% rename from pylint/test/extensions/__init__.py rename to doc/data/messages/c/cyclic-import/bad/__init__.py diff --git a/doc/data/messages/c/cyclic-import/bad/bad.py b/doc/data/messages/c/cyclic-import/bad/bad.py new file mode 100644 index 0000000000..75e5e2bce0 --- /dev/null +++ b/doc/data/messages/c/cyclic-import/bad/bad.py @@ -0,0 +1,8 @@ +def count_to_one(): + return 1 + + +def count_to_three(): + from .bad2 import count_to_two + + return count_to_two() + 1 diff --git a/doc/data/messages/c/cyclic-import/bad/bad2.py b/doc/data/messages/c/cyclic-import/bad/bad2.py new file mode 100644 index 0000000000..23417a821c --- /dev/null +++ b/doc/data/messages/c/cyclic-import/bad/bad2.py @@ -0,0 +1,5 @@ +from .bad import count_to_one # [cyclic-import] + + +def count_to_two(): + return count_to_one() + 1 diff --git a/doc/data/messages/c/cyclic-import/details.rst b/doc/data/messages/c/cyclic-import/details.rst new file mode 100644 index 0000000000..5db72735cf --- /dev/null +++ b/doc/data/messages/c/cyclic-import/details.rst @@ -0,0 +1,3 @@ +The 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. diff --git a/doc/data/messages/c/cyclic-import/good.py b/doc/data/messages/c/cyclic-import/good.py new file mode 100644 index 0000000000..7924246ef8 --- /dev/null +++ b/doc/data/messages/c/cyclic-import/good.py @@ -0,0 +1,10 @@ +def count_to_one(): + return 1 + + +def count_to_two(): + return count_to_one() + 1 + + +def count_to_three(): + return count_to_two() + 1 diff --git a/doc/data/messages/d/dangerous-default-value/bad.py b/doc/data/messages/d/dangerous-default-value/bad.py new file mode 100644 index 0000000000..6ce1223c97 --- /dev/null +++ b/doc/data/messages/d/dangerous-default-value/bad.py @@ -0,0 +1,3 @@ +def whats_on_the_telly(penguin=[]): # [dangerous-default-value] + penguin.append("property of the zoo") + return penguin diff --git a/doc/data/messages/d/dangerous-default-value/details.rst b/doc/data/messages/d/dangerous-default-value/details.rst new file mode 100644 index 0000000000..2b9a2e672c --- /dev/null +++ b/doc/data/messages/d/dangerous-default-value/details.rst @@ -0,0 +1,7 @@ +With 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"] diff --git a/doc/data/messages/d/dangerous-default-value/good.py b/doc/data/messages/d/dangerous-default-value/good.py new file mode 100644 index 0000000000..605c3cec39 --- /dev/null +++ b/doc/data/messages/d/dangerous-default-value/good.py @@ -0,0 +1,5 @@ +def whats_on_the_telly(penguin=None): + if penguin is None: + penguin = [] + penguin.append("property of the zoo") + return penguin diff --git a/doc/data/messages/d/declare-non-slot/bad.py b/doc/data/messages/d/declare-non-slot/bad.py new file mode 100644 index 0000000000..5e39d47953 --- /dev/null +++ b/doc/data/messages/d/declare-non-slot/bad.py @@ -0,0 +1,5 @@ +class Student: + __slots__ = ("name",) + + name: str + surname: str # [declare-non-slot] diff --git a/doc/data/messages/d/declare-non-slot/good.py b/doc/data/messages/d/declare-non-slot/good.py new file mode 100644 index 0000000000..1ca1de19c1 --- /dev/null +++ b/doc/data/messages/d/declare-non-slot/good.py @@ -0,0 +1,5 @@ +class Student: + __slots__ = ("name", "surname") + + name: str + surname: str diff --git a/doc/data/messages/d/deprecated-argument/bad.py b/doc/data/messages/d/deprecated-argument/bad.py new file mode 100644 index 0000000000..d0b0c257ef --- /dev/null +++ b/doc/data/messages/d/deprecated-argument/bad.py @@ -0,0 +1 @@ +int(x=1) # [deprecated-argument] diff --git a/doc/data/messages/d/deprecated-argument/details.rst b/doc/data/messages/d/deprecated-argument/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-argument/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-argument/good.py b/doc/data/messages/d/deprecated-argument/good.py new file mode 100644 index 0000000000..8269369594 --- /dev/null +++ b/doc/data/messages/d/deprecated-argument/good.py @@ -0,0 +1 @@ +int(1) diff --git a/pylint/test/functional/__init__.py b/doc/data/messages/d/deprecated-argument/pylintrc similarity index 100% rename from pylint/test/functional/__init__.py rename to doc/data/messages/d/deprecated-argument/pylintrc diff --git a/doc/data/messages/d/deprecated-attribute/bad.py b/doc/data/messages/d/deprecated-attribute/bad.py new file mode 100644 index 0000000000..ccd4090b56 --- /dev/null +++ b/doc/data/messages/d/deprecated-attribute/bad.py @@ -0,0 +1,4 @@ +from configparser import ParsingError + +err = ParsingError("filename") +source = err.filename # [deprecated-attribute] diff --git a/doc/data/messages/d/deprecated-attribute/details.rst b/doc/data/messages/d/deprecated-attribute/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-attribute/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-attribute/good.py b/doc/data/messages/d/deprecated-attribute/good.py new file mode 100644 index 0000000000..492cd8087a --- /dev/null +++ b/doc/data/messages/d/deprecated-attribute/good.py @@ -0,0 +1,4 @@ +from configparser import ParsingError + +err = ParsingError("filename") +source = err.source diff --git a/doc/data/messages/d/deprecated-class/bad.py b/doc/data/messages/d/deprecated-class/bad.py new file mode 100644 index 0000000000..ab96b50a75 --- /dev/null +++ b/doc/data/messages/d/deprecated-class/bad.py @@ -0,0 +1 @@ +from collections import Iterable # [deprecated-class] diff --git a/doc/data/messages/d/deprecated-class/details.rst b/doc/data/messages/d/deprecated-class/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-class/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-class/good.py b/doc/data/messages/d/deprecated-class/good.py new file mode 100644 index 0000000000..775057c7a4 --- /dev/null +++ b/doc/data/messages/d/deprecated-class/good.py @@ -0,0 +1 @@ +from collections.abc import Iterable diff --git a/doc/data/messages/d/deprecated-decorator/bad.py b/doc/data/messages/d/deprecated-decorator/bad.py new file mode 100644 index 0000000000..afae4c7cd4 --- /dev/null +++ b/doc/data/messages/d/deprecated-decorator/bad.py @@ -0,0 +1,7 @@ +import abc + + +class Animal: + @abc.abstractclassmethod # [deprecated-decorator] + def breath(cls): + pass diff --git a/doc/data/messages/d/deprecated-decorator/details.rst b/doc/data/messages/d/deprecated-decorator/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-decorator/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-decorator/good.py b/doc/data/messages/d/deprecated-decorator/good.py new file mode 100644 index 0000000000..3388fde7a5 --- /dev/null +++ b/doc/data/messages/d/deprecated-decorator/good.py @@ -0,0 +1,8 @@ +import abc + + +class Animal: + @abc.classmethod + @abc.abstractmethod + def breath(cls): + pass diff --git a/doc/data/messages/d/deprecated-decorator/pylintrc b/doc/data/messages/d/deprecated-decorator/pylintrc new file mode 100644 index 0000000000..ca649e602c --- /dev/null +++ b/doc/data/messages/d/deprecated-decorator/pylintrc @@ -0,0 +1,2 @@ +[main] +py-version = 3.3 diff --git a/doc/data/messages/d/deprecated-method/bad.py b/doc/data/messages/d/deprecated-method/bad.py new file mode 100644 index 0000000000..78870f3c39 --- /dev/null +++ b/doc/data/messages/d/deprecated-method/bad.py @@ -0,0 +1,3 @@ +import logging + +logging.warn("I'm coming, world !") # [deprecated-method] diff --git a/doc/data/messages/d/deprecated-method/details.rst b/doc/data/messages/d/deprecated-method/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-method/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-method/good.py b/doc/data/messages/d/deprecated-method/good.py new file mode 100644 index 0000000000..e54ea0ef96 --- /dev/null +++ b/doc/data/messages/d/deprecated-method/good.py @@ -0,0 +1,3 @@ +import logging + +logging.warning("I'm coming, world !") diff --git a/doc/data/messages/d/deprecated-module/bad.py b/doc/data/messages/d/deprecated-module/bad.py new file mode 100644 index 0000000000..fd17f13451 --- /dev/null +++ b/doc/data/messages/d/deprecated-module/bad.py @@ -0,0 +1,3 @@ +import distutils # [deprecated-module] + +import whatever_you_want # [deprecated-module] diff --git a/doc/data/messages/d/deprecated-module/details.rst b/doc/data/messages/d/deprecated-module/details.rst new file mode 100644 index 0000000000..46294b9d57 --- /dev/null +++ b/doc/data/messages/d/deprecated-module/details.rst @@ -0,0 +1,2 @@ +The actual replacement needs to be studied on a case by case basis +by reading the deprecation warning or the release notes. diff --git a/doc/data/messages/d/deprecated-module/good.py b/doc/data/messages/d/deprecated-module/good.py new file mode 100644 index 0000000000..014a76cb58 --- /dev/null +++ b/doc/data/messages/d/deprecated-module/good.py @@ -0,0 +1,2 @@ +import setuptools +import whatever_replacement_you_want diff --git a/doc/data/messages/d/deprecated-module/pylintrc b/doc/data/messages/d/deprecated-module/pylintrc new file mode 100644 index 0000000000..c72ab2495c --- /dev/null +++ b/doc/data/messages/d/deprecated-module/pylintrc @@ -0,0 +1,3 @@ +[main] +py-version=3.7 +deprecated-modules=whatever_you_want diff --git a/doc/data/messages/d/deprecated-pragma/bad.py b/doc/data/messages/d/deprecated-pragma/bad.py new file mode 100644 index 0000000000..133bf89706 --- /dev/null +++ b/doc/data/messages/d/deprecated-pragma/bad.py @@ -0,0 +1 @@ +# pylint: disable-msg=eval-used # [deprecated-pragma] diff --git a/doc/data/messages/d/deprecated-pragma/good.py b/doc/data/messages/d/deprecated-pragma/good.py new file mode 100644 index 0000000000..8aebe0b1f5 --- /dev/null +++ b/doc/data/messages/d/deprecated-pragma/good.py @@ -0,0 +1 @@ +# pylint: disable = eval-used diff --git a/doc/data/messages/d/deprecated-typing-alias/bad.py b/doc/data/messages/d/deprecated-typing-alias/bad.py new file mode 100644 index 0000000000..cde5564077 --- /dev/null +++ b/doc/data/messages/d/deprecated-typing-alias/bad.py @@ -0,0 +1,3 @@ +import typing + +item_to_number_of_item: typing.Dict[str, int] # [deprecated-typing-alias] diff --git a/doc/data/messages/d/deprecated-typing-alias/good.py b/doc/data/messages/d/deprecated-typing-alias/good.py new file mode 100644 index 0000000000..951fa52353 --- /dev/null +++ b/doc/data/messages/d/deprecated-typing-alias/good.py @@ -0,0 +1 @@ +item_to_number_of_item: dict[str, int] diff --git a/doc/data/messages/d/deprecated-typing-alias/pylintrc b/doc/data/messages/d/deprecated-typing-alias/pylintrc new file mode 100644 index 0000000000..62d313658f --- /dev/null +++ b/doc/data/messages/d/deprecated-typing-alias/pylintrc @@ -0,0 +1,2 @@ +[main] +load-plugins = pylint.extensions.typing diff --git a/doc/data/messages/d/dict-init-mutate/bad.py b/doc/data/messages/d/dict-init-mutate/bad.py new file mode 100644 index 0000000000..d7db9c5286 --- /dev/null +++ b/doc/data/messages/d/dict-init-mutate/bad.py @@ -0,0 +1,3 @@ +fruit_prices = {} # [dict-init-mutate] +fruit_prices["apple"] = 1 +fruit_prices["banana"] = 10 diff --git a/doc/data/messages/d/dict-init-mutate/good.py b/doc/data/messages/d/dict-init-mutate/good.py new file mode 100644 index 0000000000..02137f2879 --- /dev/null +++ b/doc/data/messages/d/dict-init-mutate/good.py @@ -0,0 +1 @@ +fruit_prices = {"apple": 1, "banana": 10} diff --git a/doc/data/messages/d/dict-init-mutate/pylintrc b/doc/data/messages/d/dict-init-mutate/pylintrc new file mode 100644 index 0000000000..bbe6bd1f78 --- /dev/null +++ b/doc/data/messages/d/dict-init-mutate/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.dict_init_mutate, diff --git a/doc/data/messages/d/dict-iter-missing-items/bad.py b/doc/data/messages/d/dict-iter-missing-items/bad.py new file mode 100644 index 0000000000..52efa3ad79 --- /dev/null +++ b/doc/data/messages/d/dict-iter-missing-items/bad.py @@ -0,0 +1,3 @@ +data = {"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}.") diff --git a/doc/data/messages/d/dict-iter-missing-items/good.py b/doc/data/messages/d/dict-iter-missing-items/good.py new file mode 100644 index 0000000000..3eb97f9e21 --- /dev/null +++ b/doc/data/messages/d/dict-iter-missing-items/good.py @@ -0,0 +1,3 @@ +data = {"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}.") diff --git a/doc/data/messages/d/differing-param-doc/bad.py b/doc/data/messages/d/differing-param-doc/bad.py new file mode 100644 index 0000000000..2a48d82c5c --- /dev/null +++ b/doc/data/messages/d/differing-param-doc/bad.py @@ -0,0 +1,8 @@ +def add(x, y): # [differing-param-doc] + """Add two numbers. + + :param int x: x value. + :param int z: z value. + """ + + return x + y diff --git a/doc/data/messages/d/differing-param-doc/good.py b/doc/data/messages/d/differing-param-doc/good.py new file mode 100644 index 0000000000..8deac67a20 --- /dev/null +++ b/doc/data/messages/d/differing-param-doc/good.py @@ -0,0 +1,8 @@ +def add(x, y): + """Add two numbers. + + :param int x: x value. + :param int y: y value. + """ + + return x + y diff --git a/doc/data/messages/d/differing-param-doc/pylintrc b/doc/data/messages/d/differing-param-doc/pylintrc new file mode 100644 index 0000000000..4547f98117 --- /dev/null +++ b/doc/data/messages/d/differing-param-doc/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins = pylint.extensions.docparams diff --git a/doc/data/messages/d/differing-type-doc/bad.py b/doc/data/messages/d/differing-type-doc/bad.py new file mode 100644 index 0000000000..18d41a9d2d --- /dev/null +++ b/doc/data/messages/d/differing-type-doc/bad.py @@ -0,0 +1,8 @@ +def add(x: int, y: int): # [differing-type-doc] + """Add two numbers. + + :param int xy: x value. + :param str y: y value. + """ + + return x + y diff --git a/doc/data/messages/d/differing-type-doc/good.py b/doc/data/messages/d/differing-type-doc/good.py new file mode 100644 index 0000000000..8deac67a20 --- /dev/null +++ b/doc/data/messages/d/differing-type-doc/good.py @@ -0,0 +1,8 @@ +def add(x, y): + """Add two numbers. + + :param int x: x value. + :param int y: y value. + """ + + return x + y diff --git a/doc/data/messages/d/differing-type-doc/pylintrc b/doc/data/messages/d/differing-type-doc/pylintrc new file mode 100644 index 0000000000..4547f98117 --- /dev/null +++ b/doc/data/messages/d/differing-type-doc/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins = pylint.extensions.docparams diff --git a/doc/data/messages/d/disallowed-name/bad.py b/doc/data/messages/d/disallowed-name/bad.py new file mode 100644 index 0000000000..d28892db31 --- /dev/null +++ b/doc/data/messages/d/disallowed-name/bad.py @@ -0,0 +1,2 @@ +def foo(): # [disallowed-name] + print("apples") diff --git a/doc/data/messages/d/disallowed-name/good.py b/doc/data/messages/d/disallowed-name/good.py new file mode 100644 index 0000000000..b584b631fd --- /dev/null +++ b/doc/data/messages/d/disallowed-name/good.py @@ -0,0 +1,2 @@ +def print_fruit(): + print("apples") diff --git a/doc/data/messages/d/disallowed-name/pylintrc b/doc/data/messages/d/disallowed-name/pylintrc new file mode 100644 index 0000000000..5e073119d8 --- /dev/null +++ b/doc/data/messages/d/disallowed-name/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +bad-names=foo,bar,baz diff --git a/doc/data/messages/d/docstring-first-line-empty/bad.py b/doc/data/messages/d/docstring-first-line-empty/bad.py new file mode 100644 index 0000000000..3085bb0697 --- /dev/null +++ b/doc/data/messages/d/docstring-first-line-empty/bad.py @@ -0,0 +1,10 @@ +def 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 + """ diff --git a/doc/data/messages/d/docstring-first-line-empty/good.py b/doc/data/messages/d/docstring-first-line-empty/good.py new file mode 100644 index 0000000000..16fdd55b2f --- /dev/null +++ b/doc/data/messages/d/docstring-first-line-empty/good.py @@ -0,0 +1,8 @@ +def 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 + """ diff --git a/doc/data/messages/d/docstring-first-line-empty/pylintrc b/doc/data/messages/d/docstring-first-line-empty/pylintrc new file mode 100644 index 0000000000..c41e215503 --- /dev/null +++ b/doc/data/messages/d/docstring-first-line-empty/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins = pylint.extensions.docstyle diff --git a/doc/data/messages/d/duplicate-argument-name/bad.py b/doc/data/messages/d/duplicate-argument-name/bad.py new file mode 100644 index 0000000000..4c9c5859a1 --- /dev/null +++ b/doc/data/messages/d/duplicate-argument-name/bad.py @@ -0,0 +1,2 @@ +def get_fruits(apple, banana, apple): # [duplicate-argument-name] + pass diff --git a/doc/data/messages/d/duplicate-argument-name/good.py b/doc/data/messages/d/duplicate-argument-name/good.py new file mode 100644 index 0000000000..9fe6d73e57 --- /dev/null +++ b/doc/data/messages/d/duplicate-argument-name/good.py @@ -0,0 +1,2 @@ +def get_fruits(apple, banana, orange): + pass diff --git a/doc/data/messages/d/duplicate-bases/bad.py b/doc/data/messages/d/duplicate-bases/bad.py new file mode 100644 index 0000000000..a68e3903df --- /dev/null +++ b/doc/data/messages/d/duplicate-bases/bad.py @@ -0,0 +1,6 @@ +class Animal: + pass + + +class Cat(Animal, Animal): # [duplicate-bases] + pass diff --git a/doc/data/messages/d/duplicate-bases/good.py b/doc/data/messages/d/duplicate-bases/good.py new file mode 100644 index 0000000000..8ed25950c2 --- /dev/null +++ b/doc/data/messages/d/duplicate-bases/good.py @@ -0,0 +1,10 @@ +class Animal: + pass + + +class Bird(Animal): + pass + + +class Cat(Animal): + pass diff --git a/pylint/test/functional/assignment_from_no_return_py3.txt b/doc/data/messages/d/duplicate-code/bad/__init__.py similarity index 100% rename from pylint/test/functional/assignment_from_no_return_py3.txt rename to doc/data/messages/d/duplicate-code/bad/__init__.py diff --git a/doc/data/messages/d/duplicate-code/bad/apple.py b/doc/data/messages/d/duplicate-code/bad/apple.py new file mode 100644 index 0000000000..10de7e6d4a --- /dev/null +++ b/doc/data/messages/d/duplicate-code/bad/apple.py @@ -0,0 +1,14 @@ +class 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.") diff --git a/doc/data/messages/d/duplicate-code/bad/orange.py b/doc/data/messages/d/duplicate-code/bad/orange.py new file mode 100644 index 0000000000..9be3c7b404 --- /dev/null +++ b/doc/data/messages/d/duplicate-code/bad/orange.py @@ -0,0 +1,16 @@ +class 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.") diff --git a/doc/data/messages/d/duplicate-code/details.rst b/doc/data/messages/d/duplicate-code/details.rst new file mode 100644 index 0000000000..07f5c72fac --- /dev/null +++ b/doc/data/messages/d/duplicate-code/details.rst @@ -0,0 +1,9 @@ +If 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. diff --git a/pylint/test/functional/control_pragmas.txt b/doc/data/messages/d/duplicate-code/good/__init__.py similarity index 100% rename from pylint/test/functional/control_pragmas.txt rename to doc/data/messages/d/duplicate-code/good/__init__.py diff --git a/doc/data/messages/d/duplicate-code/good/apple.py b/doc/data/messages/d/duplicate-code/good/apple.py new file mode 100644 index 0000000000..2d8cb72a0f --- /dev/null +++ b/doc/data/messages/d/duplicate-code/good/apple.py @@ -0,0 +1,4 @@ +from fruit import Fruit + + +class Apple(Fruit): ... diff --git a/doc/data/messages/d/duplicate-code/good/fruit.py b/doc/data/messages/d/duplicate-code/good/fruit.py new file mode 100644 index 0000000000..ecbd7ed955 --- /dev/null +++ b/doc/data/messages/d/duplicate-code/good/fruit.py @@ -0,0 +1,14 @@ +class 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.") diff --git a/doc/data/messages/d/duplicate-code/good/orange.py b/doc/data/messages/d/duplicate-code/good/orange.py new file mode 100644 index 0000000000..7b5421a8b4 --- /dev/null +++ b/doc/data/messages/d/duplicate-code/good/orange.py @@ -0,0 +1,8 @@ +from 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) diff --git a/doc/data/messages/d/duplicate-except/bad.py b/doc/data/messages/d/duplicate-except/bad.py new file mode 100644 index 0000000000..e50b4231c8 --- /dev/null +++ b/doc/data/messages/d/duplicate-except/bad.py @@ -0,0 +1,6 @@ +try: + 1 / 0 +except ZeroDivisionError: + pass +except ZeroDivisionError: # [duplicate-except] + pass diff --git a/doc/data/messages/d/duplicate-except/good.py b/doc/data/messages/d/duplicate-except/good.py new file mode 100644 index 0000000000..b02b365b06 --- /dev/null +++ b/doc/data/messages/d/duplicate-except/good.py @@ -0,0 +1,4 @@ +try: + 1 / 0 +except ZeroDivisionError: + pass diff --git a/doc/data/messages/d/duplicate-key/bad.py b/doc/data/messages/d/duplicate-key/bad.py new file mode 100644 index 0000000000..cfd1b59113 --- /dev/null +++ b/doc/data/messages/d/duplicate-key/bad.py @@ -0,0 +1 @@ +test_score = {"Mathematics": 85, "Biology": 90, "Mathematics": 75} # [duplicate-key] diff --git a/doc/data/messages/d/duplicate-key/good.py b/doc/data/messages/d/duplicate-key/good.py new file mode 100644 index 0000000000..75447ce12f --- /dev/null +++ b/doc/data/messages/d/duplicate-key/good.py @@ -0,0 +1 @@ +test_score = {"Mathematics": 85, "Biology": 90, "History": 75} diff --git a/doc/data/messages/d/duplicate-key/related.rst b/doc/data/messages/d/duplicate-key/related.rst new file mode 100644 index 0000000000..76391ea339 --- /dev/null +++ b/doc/data/messages/d/duplicate-key/related.rst @@ -0,0 +1,2 @@ +- `Python Dictionaries `_ +- `Mapping Types โ€” dict `_ diff --git a/doc/data/messages/d/duplicate-string-formatting-argument/bad.py b/doc/data/messages/d/duplicate-string-formatting-argument/bad.py new file mode 100644 index 0000000000..23d8aae4d9 --- /dev/null +++ b/doc/data/messages/d/duplicate-string-formatting-argument/bad.py @@ -0,0 +1,26 @@ +# 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, +) diff --git a/doc/data/messages/d/duplicate-string-formatting-argument/good.py b/doc/data/messages/d/duplicate-string-formatting-argument/good.py new file mode 100644 index 0000000000..088c7151a3 --- /dev/null +++ b/doc/data/messages/d/duplicate-string-formatting-argument/good.py @@ -0,0 +1,13 @@ +# 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 +) diff --git a/doc/data/messages/d/duplicate-value/bad.py b/doc/data/messages/d/duplicate-value/bad.py new file mode 100644 index 0000000000..975eebdaea --- /dev/null +++ b/doc/data/messages/d/duplicate-value/bad.py @@ -0,0 +1 @@ +incorrect_set = {"value1", 23, 5, "value1"} # [duplicate-value] diff --git a/doc/data/messages/d/duplicate-value/good.py b/doc/data/messages/d/duplicate-value/good.py new file mode 100644 index 0000000000..beeeb39b9b --- /dev/null +++ b/doc/data/messages/d/duplicate-value/good.py @@ -0,0 +1 @@ +correct_set = {"value1", 23, 5} diff --git a/doc/data/messages/e/else-if-used/bad.py b/doc/data/messages/e/else-if-used/bad.py new file mode 100644 index 0000000000..55cf422ac7 --- /dev/null +++ b/doc/data/messages/e/else-if-used/bad.py @@ -0,0 +1,7 @@ +if input(): + pass +else: + if len(input()) >= 10: # [else-if-used] + pass + else: + pass diff --git a/doc/data/messages/e/else-if-used/good.py b/doc/data/messages/e/else-if-used/good.py new file mode 100644 index 0000000000..39eb3ba757 --- /dev/null +++ b/doc/data/messages/e/else-if-used/good.py @@ -0,0 +1,6 @@ +if input(): + pass +elif len(input()) >= 10: + pass +else: + pass diff --git a/doc/data/messages/e/else-if-used/pylintrc b/doc/data/messages/e/else-if-used/pylintrc new file mode 100644 index 0000000000..5c438919e4 --- /dev/null +++ b/doc/data/messages/e/else-if-used/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.check_elif diff --git a/doc/data/messages/e/empty-comment/bad.py b/doc/data/messages/e/empty-comment/bad.py new file mode 100644 index 0000000000..f9d7f8e57f --- /dev/null +++ b/doc/data/messages/e/empty-comment/bad.py @@ -0,0 +1,5 @@ +# +1:[empty-comment] +# + +# +1:[empty-comment] +x = 0 # diff --git a/doc/data/messages/e/empty-comment/good.py b/doc/data/messages/e/empty-comment/good.py new file mode 100644 index 0000000000..f05c63d9d0 --- /dev/null +++ b/doc/data/messages/e/empty-comment/good.py @@ -0,0 +1,3 @@ +# comment + +x = 0 # comment diff --git a/doc/data/messages/e/empty-comment/pylintrc b/doc/data/messages/e/empty-comment/pylintrc new file mode 100644 index 0000000000..a773b55678 --- /dev/null +++ b/doc/data/messages/e/empty-comment/pylintrc @@ -0,0 +1,2 @@ +[main] +load-plugins=pylint.extensions.empty_comment diff --git a/doc/data/messages/e/empty-docstring/bad.py b/doc/data/messages/e/empty-docstring/bad.py new file mode 100644 index 0000000000..33dbb5f881 --- /dev/null +++ b/doc/data/messages/e/empty-docstring/bad.py @@ -0,0 +1,2 @@ +def foo(): # [empty-docstring] + """""" diff --git a/doc/data/messages/e/empty-docstring/good.py b/doc/data/messages/e/empty-docstring/good.py new file mode 100644 index 0000000000..b587ca4c6c --- /dev/null +++ b/doc/data/messages/e/empty-docstring/good.py @@ -0,0 +1,2 @@ +def foo(): + """A dummy description.""" diff --git a/doc/data/messages/e/eq-without-hash/bad.py b/doc/data/messages/e/eq-without-hash/bad.py new file mode 100644 index 0000000000..42df9e8f10 --- /dev/null +++ b/doc/data/messages/e/eq-without-hash/bad.py @@ -0,0 +1,6 @@ +class 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 diff --git a/doc/data/messages/e/eq-without-hash/good.py b/doc/data/messages/e/eq-without-hash/good.py new file mode 100644 index 0000000000..bf62450734 --- /dev/null +++ b/doc/data/messages/e/eq-without-hash/good.py @@ -0,0 +1,9 @@ +class 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) diff --git a/doc/data/messages/e/eq-without-hash/pylintrc b/doc/data/messages/e/eq-without-hash/pylintrc new file mode 100644 index 0000000000..6e2e015a49 --- /dev/null +++ b/doc/data/messages/e/eq-without-hash/pylintrc @@ -0,0 +1,2 @@ +[MAIN] +load-plugins=pylint.extensions.eq_without_hash, diff --git a/doc/data/messages/e/eval-used/bad.py b/doc/data/messages/e/eval-used/bad.py new file mode 100644 index 0000000000..db26f17296 --- /dev/null +++ b/doc/data/messages/e/eval-used/bad.py @@ -0,0 +1 @@ +eval("[1, 2, 3]") # [eval-used] diff --git a/doc/data/messages/e/eval-used/good.py b/doc/data/messages/e/eval-used/good.py new file mode 100644 index 0000000000..094ecae214 --- /dev/null +++ b/doc/data/messages/e/eval-used/good.py @@ -0,0 +1,3 @@ +from ast import literal_eval + +literal_eval("[1, 2, 3]") diff --git a/doc/data/messages/e/exec-used/bad.py b/doc/data/messages/e/exec-used/bad.py new file mode 100644 index 0000000000..72514e3b72 --- /dev/null +++ b/doc/data/messages/e/exec-used/bad.py @@ -0,0 +1,4 @@ +username = "Ada" +code_to_execute = f"""input('Enter code to be executed please, {username}: ')""" +program = exec(code_to_execute) # [exec-used] +exec(program) # [exec-used] diff --git a/doc/data/messages/e/exec-used/details.rst b/doc/data/messages/e/exec-used/details.rst new file mode 100644 index 0000000000..246857f32d --- /dev/null +++ b/doc/data/messages/e/exec-used/details.rst @@ -0,0 +1,10 @@ +The 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. For example, consider the following call +that writes a file to the user's system: + +.. code-block:: python + + exec("""\nwith open("file.txt", "w", encoding="utf-8") as file:\n file.write("# code as nefarious as imaginable")\n""") diff --git a/doc/data/messages/e/exec-used/good.py b/doc/data/messages/e/exec-used/good.py new file mode 100644 index 0000000000..f3e1dd7b7f --- /dev/null +++ b/doc/data/messages/e/exec-used/good.py @@ -0,0 +1,9 @@ +def get_user_code(name): + return input(f"Enter code to be executed please, {name}: ") + + +username = "Ada" +allowed_globals = {"__builtins__": None} +allowed_locals = {"print": print} +# pylint: disable-next=exec-used +exec(get_user_code(username), allowed_globals, allowed_locals) diff --git a/doc/data/messages/e/exec-used/related.rst b/doc/data/messages/e/exec-used/related.rst new file mode 100644 index 0000000000..d840db050e --- /dev/null +++ b/doc/data/messages/e/exec-used/related.rst @@ -0,0 +1 @@ +- `Be careful with exec and eval in Python `_ diff --git a/doc/data/messages/e/expression-not-assigned/bad.py b/doc/data/messages/e/expression-not-assigned/bad.py new file mode 100644 index 0000000000..fa696d41a2 --- /dev/null +++ b/doc/data/messages/e/expression-not-assigned/bad.py @@ -0,0 +1 @@ +str(42) == "42" # [expression-not-assigned] diff --git a/doc/data/messages/e/expression-not-assigned/good.py b/doc/data/messages/e/expression-not-assigned/good.py new file mode 100644 index 0000000000..fda04a837c --- /dev/null +++ b/doc/data/messages/e/expression-not-assigned/good.py @@ -0,0 +1 @@ +are_equal: bool = str(42) == "42" diff --git a/doc/data/messages/f/f-string-without-interpolation/bad.py b/doc/data/messages/f/f-string-without-interpolation/bad.py new file mode 100644 index 0000000000..a31779832b --- /dev/null +++ b/doc/data/messages/f/f-string-without-interpolation/bad.py @@ -0,0 +1,3 @@ +x = 1 +y = 2 +print(f"x + y = x + y") # [f-string-without-interpolation] diff --git a/doc/data/messages/f/f-string-without-interpolation/good.py b/doc/data/messages/f/f-string-without-interpolation/good.py new file mode 100644 index 0000000000..9af2f979b9 --- /dev/null +++ b/doc/data/messages/f/f-string-without-interpolation/good.py @@ -0,0 +1,3 @@ +x = 1 +y = 2 +print(f"{x} + {y} = {x + y}") diff --git a/doc/data/messages/f/fatal/details.rst b/doc/data/messages/f/fatal/details.rst new file mode 100644 index 0000000000..1c43031371 --- /dev/null +++ b/doc/data/messages/f/fatal/details.rst @@ -0,0 +1 @@ +This is a message linked to an internal problem in pylint. There's nothing to change in your code. diff --git a/doc/data/messages/f/file-ignored/bad.py b/doc/data/messages/f/file-ignored/bad.py new file mode 100644 index 0000000000..ce04564850 --- /dev/null +++ b/doc/data/messages/f/file-ignored/bad.py @@ -0,0 +1,2 @@ +# pylint: skip-file +# -1: [file-ignored] diff --git a/doc/data/messages/f/file-ignored/details.rst b/doc/data/messages/f/file-ignored/details.rst new file mode 100644 index 0000000000..c979ac7165 --- /dev/null +++ b/doc/data/messages/f/file-ignored/details.rst @@ -0,0 +1 @@ +There's no checks at all for a file if it starts by ``# pylint: skip-file``. diff --git a/pylint/test/functional/crash_missing_module_type.txt b/doc/data/messages/f/file-ignored/good.py similarity index 100% rename from pylint/test/functional/crash_missing_module_type.txt rename to doc/data/messages/f/file-ignored/good.py diff --git a/doc/data/messages/f/fixme/bad.py b/doc/data/messages/f/fixme/bad.py new file mode 100644 index 0000000000..47955d70ce --- /dev/null +++ b/doc/data/messages/f/fixme/bad.py @@ -0,0 +1 @@ +# TODO: We should fix this at some point # [fixme] diff --git a/doc/data/messages/f/fixme/details.rst b/doc/data/messages/f/fixme/details.rst new file mode 100644 index 0000000000..7f073bf5b9 --- /dev/null +++ b/doc/data/messages/f/fixme/details.rst @@ -0,0 +1,2 @@ +You can use regular expressions and the ``notes-rgx`` option to create some constraints for this message. +See `the following issue `_ for some examples. diff --git a/doc/data/messages/f/fixme/good/bug_tracker.py b/doc/data/messages/f/fixme/good/bug_tracker.py new file mode 100644 index 0000000000..b7e08f2511 --- /dev/null +++ b/doc/data/messages/f/fixme/good/bug_tracker.py @@ -0,0 +1 @@ +# The issue was added to the bug tracker: no longer need the comment diff --git a/doc/data/messages/f/fixme/good/fixed.py b/doc/data/messages/f/fixme/good/fixed.py new file mode 100644 index 0000000000..8d5a485579 --- /dev/null +++ b/doc/data/messages/f/fixme/good/fixed.py @@ -0,0 +1 @@ +# The issue was fixed: no longer need the comment diff --git a/doc/data/messages/f/fixme/good/no_fix.py b/doc/data/messages/f/fixme/good/no_fix.py new file mode 100644 index 0000000000..3f2f3af982 --- /dev/null +++ b/doc/data/messages/f/fixme/good/no_fix.py @@ -0,0 +1 @@ +# We no longer want to fix this: no longer need the comment diff --git a/doc/data/messages/f/forgotten-debug-statement/bad.py b/doc/data/messages/f/forgotten-debug-statement/bad.py new file mode 100644 index 0000000000..e37185371b --- /dev/null +++ b/doc/data/messages/f/forgotten-debug-statement/bad.py @@ -0,0 +1,17 @@ +import 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) diff --git a/doc/data/messages/f/forgotten-debug-statement/good.py b/doc/data/messages/f/forgotten-debug-statement/good.py new file mode 100644 index 0000000000..7896ff50eb --- /dev/null +++ b/doc/data/messages/f/forgotten-debug-statement/good.py @@ -0,0 +1,13 @@ +def 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) diff --git a/doc/data/messages/f/format-combined-specification/bad.py b/doc/data/messages/f/format-combined-specification/bad.py new file mode 100644 index 0000000000..f530aa0d58 --- /dev/null +++ b/doc/data/messages/f/format-combined-specification/bad.py @@ -0,0 +1 @@ +print("{} {1}".format("hello", "world")) # [format-combined-specification] diff --git a/doc/data/messages/f/format-combined-specification/good/index_formatting.py b/doc/data/messages/f/format-combined-specification/good/index_formatting.py new file mode 100644 index 0000000000..e8c1033b27 --- /dev/null +++ b/doc/data/messages/f/format-combined-specification/good/index_formatting.py @@ -0,0 +1 @@ +print("{0} {1}".format("hello", "world")) diff --git a/doc/data/messages/f/format-combined-specification/good/order_formatting.py b/doc/data/messages/f/format-combined-specification/good/order_formatting.py new file mode 100644 index 0000000000..bbfb2109b9 --- /dev/null +++ b/doc/data/messages/f/format-combined-specification/good/order_formatting.py @@ -0,0 +1 @@ +print("{} {}".format("hello", "world")) diff --git a/doc/data/messages/f/format-needs-mapping/bad.py b/doc/data/messages/f/format-needs-mapping/bad.py new file mode 100644 index 0000000000..b265ccdb94 --- /dev/null +++ b/doc/data/messages/f/format-needs-mapping/bad.py @@ -0,0 +1 @@ +print("%(x)d %(y)d" % [1, 2]) # [format-needs-mapping] diff --git a/doc/data/messages/f/format-needs-mapping/good.py b/doc/data/messages/f/format-needs-mapping/good.py new file mode 100644 index 0000000000..bed0122e33 --- /dev/null +++ b/doc/data/messages/f/format-needs-mapping/good.py @@ -0,0 +1 @@ +print("%(x)d %(y)d" % {"x": 1, "y": 2}) diff --git a/doc/data/messages/f/format-string-without-interpolation/bad.py b/doc/data/messages/f/format-string-without-interpolation/bad.py new file mode 100644 index 0000000000..a5ff6406dd --- /dev/null +++ b/doc/data/messages/f/format-string-without-interpolation/bad.py @@ -0,0 +1 @@ +print("number".format(1)) # [format-string-without-interpolation] diff --git a/doc/data/messages/f/format-string-without-interpolation/good.py b/doc/data/messages/f/format-string-without-interpolation/good.py new file mode 100644 index 0000000000..097f79662c --- /dev/null +++ b/doc/data/messages/f/format-string-without-interpolation/good.py @@ -0,0 +1 @@ +print("number: {}".format(1)) diff --git a/doc/data/messages/f/function-redefined/bad.py b/doc/data/messages/f/function-redefined/bad.py new file mode 100644 index 0000000000..0e3c3085f7 --- /dev/null +++ b/doc/data/messages/f/function-redefined/bad.py @@ -0,0 +1,6 @@ +def get_email(): + pass + + +def get_email(): # [function-redefined] + pass diff --git a/doc/data/messages/f/function-redefined/good.py b/doc/data/messages/f/function-redefined/good.py new file mode 100644 index 0000000000..96efb4b79f --- /dev/null +++ b/doc/data/messages/f/function-redefined/good.py @@ -0,0 +1,2 @@ +def get_email(): + pass diff --git a/doc/data/messages/g/global-at-module-level/bad.py b/doc/data/messages/g/global-at-module-level/bad.py new file mode 100644 index 0000000000..e38da258b4 --- /dev/null +++ b/doc/data/messages/g/global-at-module-level/bad.py @@ -0,0 +1,2 @@ +price = 25 +global price # [global-at-module-level] diff --git a/doc/data/messages/g/global-at-module-level/good.py b/doc/data/messages/g/global-at-module-level/good.py new file mode 100644 index 0000000000..4f372961fa --- /dev/null +++ b/doc/data/messages/g/global-at-module-level/good.py @@ -0,0 +1 @@ +price = 25 diff --git a/doc/data/messages/g/global-at-module-level/related.rst b/doc/data/messages/g/global-at-module-level/related.rst new file mode 100644 index 0000000000..62033562f7 --- /dev/null +++ b/doc/data/messages/g/global-at-module-level/related.rst @@ -0,0 +1,3 @@ +- `Official Python FAQ - global and local `_ +- `PEP 3104 - Access to Names in Outer Scopes `_ +- `Python global statement `_ diff --git a/doc/data/messages/g/global-statement/bad.py b/doc/data/messages/g/global-statement/bad.py new file mode 100644 index 0000000000..aca1dabd24 --- /dev/null +++ b/doc/data/messages/g/global-statement/bad.py @@ -0,0 +1,11 @@ +var = 1 + + +def foo(): + global var # [global-statement] + var = 10 + print(var) + + +foo() +print(var) diff --git a/doc/data/messages/g/global-statement/good.py b/doc/data/messages/g/global-statement/good.py new file mode 100644 index 0000000000..34958b5fe1 --- /dev/null +++ b/doc/data/messages/g/global-statement/good.py @@ -0,0 +1,10 @@ +var = 1 + + +def foo(): + print(var) + return 10 + + +var = foo() +print(var) diff --git a/doc/data/messages/g/global-variable-not-assigned/bad.py b/doc/data/messages/g/global-variable-not-assigned/bad.py new file mode 100644 index 0000000000..d1d907544f --- /dev/null +++ b/doc/data/messages/g/global-variable-not-assigned/bad.py @@ -0,0 +1,6 @@ +TOMATO = "black cherry" + + +def update_tomato(): + global TOMATO # [global-variable-not-assigned] + print(TOMATO) diff --git a/doc/data/messages/g/global-variable-not-assigned/good.py b/doc/data/messages/g/global-variable-not-assigned/good.py new file mode 100644 index 0000000000..0736bb4c7b --- /dev/null +++ b/doc/data/messages/g/global-variable-not-assigned/good.py @@ -0,0 +1,6 @@ +TOMATO = "black cherry" + + +def update_tomato(): + global TOMATO + TOMATO = "moneymaker" diff --git a/doc/data/messages/g/global-variable-undefined/bad.py b/doc/data/messages/g/global-variable-undefined/bad.py new file mode 100644 index 0000000000..44e4f3a2f8 --- /dev/null +++ b/doc/data/messages/g/global-variable-undefined/bad.py @@ -0,0 +1,3 @@ +def update_tomato(): + global TOMATO # [global-variable-undefined] + TOMATO = "moneymaker" diff --git a/doc/data/messages/g/global-variable-undefined/good.py b/doc/data/messages/g/global-variable-undefined/good.py new file mode 100644 index 0000000000..0736bb4c7b --- /dev/null +++ b/doc/data/messages/g/global-variable-undefined/good.py @@ -0,0 +1,6 @@ +TOMATO = "black cherry" + + +def update_tomato(): + global TOMATO + TOMATO = "moneymaker" diff --git a/doc/data/messages/i/implicit-flag-alias/bad.py b/doc/data/messages/i/implicit-flag-alias/bad.py new file mode 100644 index 0000000000..1d12e4fb4b --- /dev/null +++ b/doc/data/messages/i/implicit-flag-alias/bad.py @@ -0,0 +1,7 @@ +from enum import IntFlag + + +class FilePermissions(IntFlag): + READ = 1 + WRITE = 2 + EXECUTE = 3 # [implicit-flag-alias] diff --git a/doc/data/messages/i/implicit-flag-alias/good.py b/doc/data/messages/i/implicit-flag-alias/good.py new file mode 100644 index 0000000000..78847d102f --- /dev/null +++ b/doc/data/messages/i/implicit-flag-alias/good.py @@ -0,0 +1,7 @@ +from enum import IntFlag + + +class FilePermissions(IntFlag): + READ = 1 + WRITE = 2 + EXECUTE = 4 diff --git a/doc/data/messages/i/implicit-str-concat/bad/list.py b/doc/data/messages/i/implicit-str-concat/bad/list.py new file mode 100644 index 0000000000..8d3180e159 --- /dev/null +++ b/doc/data/messages/i/implicit-str-concat/bad/list.py @@ -0,0 +1 @@ +x = ["a" "b"] # [implicit-str-concat] diff --git a/doc/data/messages/i/implicit-str-concat/bad/open.py b/doc/data/messages/i/implicit-str-concat/bad/open.py new file mode 100644 index 0000000000..7cb4d06239 --- /dev/null +++ b/doc/data/messages/i/implicit-str-concat/bad/open.py @@ -0,0 +1,2 @@ +with open("hello.txt" "r") as f: # [implicit-str-concat] + print(f.read()) diff --git a/doc/data/messages/i/implicit-str-concat/details.rst b/doc/data/messages/i/implicit-str-concat/details.rst new file mode 100644 index 0000000000..6b3f2c32f5 --- /dev/null +++ b/doc/data/messages/i/implicit-str-concat/details.rst @@ -0,0 +1,39 @@ +By 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, + ) diff --git a/doc/data/messages/i/implicit-str-concat/good/list.py b/doc/data/messages/i/implicit-str-concat/good/list.py new file mode 100644 index 0000000000..54572735ec --- /dev/null +++ b/doc/data/messages/i/implicit-str-concat/good/list.py @@ -0,0 +1 @@ +x = ["a", "b"] diff --git a/doc/data/messages/i/implicit-str-concat/good/open.py b/doc/data/messages/i/implicit-str-concat/good/open.py new file mode 100644 index 0000000000..c5a337f3de --- /dev/null +++ b/doc/data/messages/i/implicit-str-concat/good/open.py @@ -0,0 +1,2 @@ +with open("hello.txt", "r") as f: + print(f.read()) diff --git a/doc/data/messages/i/import-error/bad.py b/doc/data/messages/i/import-error/bad.py new file mode 100644 index 0000000000..672564c1e8 --- /dev/null +++ b/doc/data/messages/i/import-error/bad.py @@ -0,0 +1 @@ +from patlib import Path # [import-error] diff --git a/doc/data/messages/i/import-error/details.rst b/doc/data/messages/i/import-error/details.rst new file mode 100644 index 0000000000..aaa3edc118 --- /dev/null +++ b/doc/data/messages/i/import-error/details.rst @@ -0,0 +1,3 @@ +This 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. diff --git a/doc/data/messages/i/import-error/good.py b/doc/data/messages/i/import-error/good.py new file mode 100644 index 0000000000..2bb88df4d4 --- /dev/null +++ b/doc/data/messages/i/import-error/good.py @@ -0,0 +1 @@ +from pathlib import Path diff --git a/doc/data/messages/i/import-outside-toplevel/bad.py b/doc/data/messages/i/import-outside-toplevel/bad.py new file mode 100644 index 0000000000..5262ba7709 --- /dev/null +++ b/doc/data/messages/i/import-outside-toplevel/bad.py @@ -0,0 +1,4 @@ +def print_python_version(): + import sys # [import-outside-toplevel] + + print(sys.version_info) diff --git a/doc/data/messages/i/import-outside-toplevel/good.py b/doc/data/messages/i/import-outside-toplevel/good.py new file mode 100644 index 0000000000..d77c91ab39 --- /dev/null +++ b/doc/data/messages/i/import-outside-toplevel/good.py @@ -0,0 +1,5 @@ +import sys + + +def print_python_version(): + print(sys.version_info) diff --git a/doc/data/messages/i/import-private-name/bad.py b/doc/data/messages/i/import-private-name/bad.py new file mode 100644 index 0000000000..e562e49289 --- /dev/null +++ b/doc/data/messages/i/import-private-name/bad.py @@ -0,0 +1,8 @@ +from argparse import _AttributeHolder, _SubParsersAction # [import-private-name] + +attr_holder = _AttributeHolder() + + +def add_sub_parser(sub_parsers: _SubParsersAction): + sub_parsers.add_parser("my_subparser") + # ... diff --git a/doc/data/messages/i/import-private-name/details.rst b/doc/data/messages/i/import-private-name/details.rst new file mode 100644 index 0000000000..48c1089842 --- /dev/null +++ b/doc/data/messages/i/import-private-name/details.rst @@ -0,0 +1,2 @@ +Using private imports expose you to unexpected breaking changes for any version +bump of your dependencies, even in patch versions. diff --git a/doc/data/messages/i/import-private-name/good.py b/doc/data/messages/i/import-private-name/good.py new file mode 100644 index 0000000000..810005feab --- /dev/null +++ b/doc/data/messages/i/import-private-name/good.py @@ -0,0 +1,8 @@ +"""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") + # ... diff --git a/doc/data/messages/i/import-private-name/pylintrc b/doc/data/messages/i/import-private-name/pylintrc new file mode 100644 index 0000000000..09cf103b68 --- /dev/null +++ b/doc/data/messages/i/import-private-name/pylintrc @@ -0,0 +1,2 @@ +[main] +load-plugins = pylint.extensions.private_import diff --git a/doc/data/messages/i/import-self/details.rst b/doc/data/messages/i/import-self/details.rst new file mode 100644 index 0000000000..47711bc362 --- /dev/null +++ b/doc/data/messages/i/import-self/details.rst @@ -0,0 +1,12 @@ +Say 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 diff --git a/doc/data/messages/i/inconsistent-mro/bad.py b/doc/data/messages/i/inconsistent-mro/bad.py new file mode 100644 index 0000000000..93f9aa55d4 --- /dev/null +++ b/doc/data/messages/i/inconsistent-mro/bad.py @@ -0,0 +1,10 @@ +class A: + pass + + +class B(A): + pass + + +class C(A, B): # [inconsistent-mro] + pass diff --git a/doc/data/messages/i/inconsistent-mro/good.py b/doc/data/messages/i/inconsistent-mro/good.py new file mode 100644 index 0000000000..5fccd63c03 --- /dev/null +++ b/doc/data/messages/i/inconsistent-mro/good.py @@ -0,0 +1,10 @@ +class A: + pass + + +class B(A): + pass + + +class C(B): # or 'B, A' or 'A' but not 'A, B' + pass diff --git a/doc/data/messages/i/inconsistent-quotes/bad.py b/doc/data/messages/i/inconsistent-quotes/bad.py new file mode 100644 index 0000000000..2a18366821 --- /dev/null +++ b/doc/data/messages/i/inconsistent-quotes/bad.py @@ -0,0 +1,3 @@ +import datetime + +print('Current year: ', datetime.date.today().strftime("%Y")) # [inconsistent-quotes] diff --git a/doc/data/messages/i/inconsistent-quotes/good.py b/doc/data/messages/i/inconsistent-quotes/good.py new file mode 100644 index 0000000000..87431bc305 --- /dev/null +++ b/doc/data/messages/i/inconsistent-quotes/good.py @@ -0,0 +1,3 @@ +import datetime + +print("Current year: ", datetime.date.today().strftime("%Y")) diff --git a/doc/data/messages/i/inconsistent-quotes/pylintrc b/doc/data/messages/i/inconsistent-quotes/pylintrc new file mode 100644 index 0000000000..5d2f27f9c2 --- /dev/null +++ b/doc/data/messages/i/inconsistent-quotes/pylintrc @@ -0,0 +1,2 @@ +[main] +check-quote-consistency=yes diff --git a/doc/data/messages/i/inconsistent-return-statements/bad.py b/doc/data/messages/i/inconsistent-return-statements/bad.py new file mode 100644 index 0000000000..32bf9480d4 --- /dev/null +++ b/doc/data/messages/i/inconsistent-return-statements/bad.py @@ -0,0 +1,3 @@ +def get_the_answer(value: str) -> str | None: # [inconsistent-return-statements] + if value: + return value diff --git a/doc/data/messages/i/inconsistent-return-statements/good.py b/doc/data/messages/i/inconsistent-return-statements/good.py new file mode 100644 index 0000000000..991527b0ea --- /dev/null +++ b/doc/data/messages/i/inconsistent-return-statements/good.py @@ -0,0 +1,4 @@ +def get_the_answer(value: str) -> str | None: + if value: + return value + return None diff --git a/doc/data/messages/i/inherit-non-class/bad.py b/doc/data/messages/i/inherit-non-class/bad.py new file mode 100644 index 0000000000..4a7926c0c2 --- /dev/null +++ b/doc/data/messages/i/inherit-non-class/bad.py @@ -0,0 +1,2 @@ +class Fruit(bool): # [inherit-non-class] + pass diff --git a/doc/data/messages/i/inherit-non-class/good.py b/doc/data/messages/i/inherit-non-class/good.py new file mode 100644 index 0000000000..dc48bd017f --- /dev/null +++ b/doc/data/messages/i/inherit-non-class/good.py @@ -0,0 +1,3 @@ +class Fruit: + def __bool__(self): + pass diff --git a/doc/data/messages/i/init-is-generator/bad.py b/doc/data/messages/i/init-is-generator/bad.py new file mode 100644 index 0000000000..415b94c4dd --- /dev/null +++ b/doc/data/messages/i/init-is-generator/bad.py @@ -0,0 +1,6 @@ +class Fruit: + def __init__(self, worms): # [init-is-generator] + yield from worms + + +apple = Fruit(["Fahad", "Anisha", "Tabatha"]) diff --git a/doc/data/messages/i/init-is-generator/good.py b/doc/data/messages/i/init-is-generator/good.py new file mode 100644 index 0000000000..1f5bf0047d --- /dev/null +++ b/doc/data/messages/i/init-is-generator/good.py @@ -0,0 +1,11 @@ +class 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 diff --git a/doc/data/messages/i/invalid-all-format/bad.py b/doc/data/messages/i/invalid-all-format/bad.py new file mode 100644 index 0000000000..c891377344 --- /dev/null +++ b/doc/data/messages/i/invalid-all-format/bad.py @@ -0,0 +1,3 @@ +__all__ = "CONST" # [invalid-all-format] + +CONST = 42 diff --git a/doc/data/messages/i/invalid-all-format/good.py b/doc/data/messages/i/invalid-all-format/good.py new file mode 100644 index 0000000000..bb64b60723 --- /dev/null +++ b/doc/data/messages/i/invalid-all-format/good.py @@ -0,0 +1,3 @@ +__all__ = ("CONST",) + +CONST = 42 diff --git a/doc/data/messages/i/invalid-all-object/bad.py b/doc/data/messages/i/invalid-all-object/bad.py new file mode 100644 index 0000000000..04509727b8 --- /dev/null +++ b/doc/data/messages/i/invalid-all-object/bad.py @@ -0,0 +1,13 @@ +__all__ = ( + None, # [invalid-all-object] + Fruit, + Worm, +) + + +class Fruit: + pass + + +class Worm: + pass diff --git a/doc/data/messages/i/invalid-all-object/details.rst b/doc/data/messages/i/invalid-all-object/details.rst new file mode 100644 index 0000000000..db3d100aa4 --- /dev/null +++ b/doc/data/messages/i/invalid-all-object/details.rst @@ -0,0 +1,2 @@ +From `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." diff --git a/doc/data/messages/i/invalid-all-object/good.py b/doc/data/messages/i/invalid-all-object/good.py new file mode 100644 index 0000000000..351cfa1c64 --- /dev/null +++ b/doc/data/messages/i/invalid-all-object/good.py @@ -0,0 +1,9 @@ +__all__ = ["Fruit", "Worm"] + + +class Fruit: + pass + + +class Worm: + pass diff --git a/doc/data/messages/i/invalid-all-object/related.rst b/doc/data/messages/i/invalid-all-object/related.rst new file mode 100644 index 0000000000..fff337eb9c --- /dev/null +++ b/doc/data/messages/i/invalid-all-object/related.rst @@ -0,0 +1 @@ +- `PEP 8 โ€“ Style Guide for Python Code `_ diff --git a/doc/data/messages/i/invalid-bool-returned/bad.py b/doc/data/messages/i/invalid-bool-returned/bad.py new file mode 100644 index 0000000000..74c0000f5f --- /dev/null +++ b/doc/data/messages/i/invalid-bool-returned/bad.py @@ -0,0 +1,5 @@ +class CustomBool: + """__bool__ returns an int""" + + def __bool__(self): # [invalid-bool-returned] + return 1 diff --git a/doc/data/messages/i/invalid-bool-returned/good.py b/doc/data/messages/i/invalid-bool-returned/good.py new file mode 100644 index 0000000000..9bca165968 --- /dev/null +++ b/doc/data/messages/i/invalid-bool-returned/good.py @@ -0,0 +1,5 @@ +class CustomBool: + """__bool__ returns `bool`""" + + def __bool__(self): + return True diff --git a/doc/data/messages/i/invalid-bytes-returned/bad.py b/doc/data/messages/i/invalid-bytes-returned/bad.py new file mode 100644 index 0000000000..e20e5902f3 --- /dev/null +++ b/doc/data/messages/i/invalid-bytes-returned/bad.py @@ -0,0 +1,5 @@ +class CustomBytes: + """__bytes__ returns """ + + def __bytes__(self): # [invalid-bytes-returned] + return "123" diff --git a/doc/data/messages/i/invalid-bytes-returned/good.py b/doc/data/messages/i/invalid-bytes-returned/good.py new file mode 100644 index 0000000000..548303d955 --- /dev/null +++ b/doc/data/messages/i/invalid-bytes-returned/good.py @@ -0,0 +1,5 @@ +class CustomBytes: + """__bytes__ returns """ + + def __bytes__(self): + return b"some bytes" diff --git a/doc/data/messages/i/invalid-character-backspace/bad.py b/doc/data/messages/i/invalid-character-backspace/bad.py new file mode 100644 index 0000000000..ac9ed67a36 --- /dev/null +++ b/doc/data/messages/i/invalid-character-backspace/bad.py @@ -0,0 +1 @@ +STRING = "Invalid character backspace " # [invalid-character-backspace] diff --git a/doc/data/messages/i/invalid-character-backspace/good.py b/doc/data/messages/i/invalid-character-backspace/good.py new file mode 100644 index 0000000000..3381c5fc2f --- /dev/null +++ b/doc/data/messages/i/invalid-character-backspace/good.py @@ -0,0 +1 @@ +STRING = "Valid character backspace \b" diff --git a/doc/data/messages/i/invalid-character-carriage-return/details.rst b/doc/data/messages/i/invalid-character-carriage-return/details.rst new file mode 100644 index 0000000000..283e7b5e8a --- /dev/null +++ b/doc/data/messages/i/invalid-character-carriage-return/details.rst @@ -0,0 +1,5 @@ +This 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. diff --git a/doc/data/messages/i/invalid-character-carriage-return/good.py b/doc/data/messages/i/invalid-character-carriage-return/good.py new file mode 100644 index 0000000000..ae08661aff --- /dev/null +++ b/doc/data/messages/i/invalid-character-carriage-return/good.py @@ -0,0 +1 @@ +STRING = "Valid carriage return: \r" diff --git a/doc/data/messages/i/invalid-character-esc/bad.py b/doc/data/messages/i/invalid-character-esc/bad.py new file mode 100644 index 0000000000..0d50cab427 --- /dev/null +++ b/doc/data/messages/i/invalid-character-esc/bad.py @@ -0,0 +1 @@ +STRING = "Invalid escape character " # [invalid-character-esc] diff --git a/doc/data/messages/i/invalid-character-esc/good.py b/doc/data/messages/i/invalid-character-esc/good.py new file mode 100644 index 0000000000..64431d167d --- /dev/null +++ b/doc/data/messages/i/invalid-character-esc/good.py @@ -0,0 +1 @@ +STRING = "Valid escape character \x1B" diff --git a/doc/data/messages/i/invalid-character-nul/details.rst b/doc/data/messages/i/invalid-character-nul/details.rst new file mode 100644 index 0000000000..c131132bf5 --- /dev/null +++ b/doc/data/messages/i/invalid-character-nul/details.rst @@ -0,0 +1,2 @@ +There's no need to use end-of-string characters. String objects maintain their +own length. diff --git a/doc/data/messages/i/invalid-character-nul/good.py b/doc/data/messages/i/invalid-character-nul/good.py new file mode 100644 index 0000000000..97e1a3bcf3 --- /dev/null +++ b/doc/data/messages/i/invalid-character-nul/good.py @@ -0,0 +1 @@ +STRING = "Valid nul terminator: \x00" diff --git a/doc/data/messages/i/invalid-character-nul/related.rst b/doc/data/messages/i/invalid-character-nul/related.rst new file mode 100644 index 0000000000..2f08c333e7 --- /dev/null +++ b/doc/data/messages/i/invalid-character-nul/related.rst @@ -0,0 +1 @@ +- `Null terminator in python `_ diff --git a/doc/data/messages/i/invalid-character-sub/bad.py b/doc/data/messages/i/invalid-character-sub/bad.py new file mode 100644 index 0000000000..313066d3b8 --- /dev/null +++ b/doc/data/messages/i/invalid-character-sub/bad.py @@ -0,0 +1 @@ +STRING = "Invalid character sub " # [invalid-character-sub] diff --git a/doc/data/messages/i/invalid-character-sub/good.py b/doc/data/messages/i/invalid-character-sub/good.py new file mode 100644 index 0000000000..5dd4aa4fb8 --- /dev/null +++ b/doc/data/messages/i/invalid-character-sub/good.py @@ -0,0 +1 @@ +STRING = "Valid character sub x1A" diff --git a/doc/data/messages/i/invalid-character-zero-width-space/bad.py b/doc/data/messages/i/invalid-character-zero-width-space/bad.py new file mode 100644 index 0000000000..99160fc8f8 --- /dev/null +++ b/doc/data/messages/i/invalid-character-zero-width-space/bad.py @@ -0,0 +1 @@ +STRING = "Invalid character zero-width-space โ€‹" # [invalid-character-zero-width-space] diff --git a/doc/data/messages/i/invalid-character-zero-width-space/good.py b/doc/data/messages/i/invalid-character-zero-width-space/good.py new file mode 100644 index 0000000000..391bcf0987 --- /dev/null +++ b/doc/data/messages/i/invalid-character-zero-width-space/good.py @@ -0,0 +1 @@ +STRING = "Valid character zero-width-space u200B" diff --git a/doc/data/messages/i/invalid-characters-in-docstring/details.rst b/doc/data/messages/i/invalid-characters-in-docstring/details.rst new file mode 100644 index 0000000000..9977db1445 --- /dev/null +++ b/doc/data/messages/i/invalid-characters-in-docstring/details.rst @@ -0,0 +1,2 @@ +This 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. diff --git a/doc/data/messages/i/invalid-class-object/bad.py b/doc/data/messages/i/invalid-class-object/bad.py new file mode 100644 index 0000000000..5c6a6f8df7 --- /dev/null +++ b/doc/data/messages/i/invalid-class-object/bad.py @@ -0,0 +1,5 @@ +class Apple: + pass + + +Apple.__class__ = 1 # [invalid-class-object] diff --git a/doc/data/messages/i/invalid-class-object/good.py b/doc/data/messages/i/invalid-class-object/good.py new file mode 100644 index 0000000000..3b50097f1c --- /dev/null +++ b/doc/data/messages/i/invalid-class-object/good.py @@ -0,0 +1,9 @@ +class Apple: + pass + + +class RedDelicious: + pass + + +Apple.__class__ = RedDelicious diff --git a/doc/data/messages/i/invalid-enum-extension/bad.py b/doc/data/messages/i/invalid-enum-extension/bad.py new file mode 100644 index 0000000000..2a2a01040a --- /dev/null +++ b/doc/data/messages/i/invalid-enum-extension/bad.py @@ -0,0 +1,10 @@ +from enum import Enum + + +class Color(Enum): + ORANGE = 1 + CHERRY = 2 + + +class Fruit(Color): # [invalid-enum-extension] + APPLE = 3 diff --git a/doc/data/messages/i/invalid-enum-extension/good.py b/doc/data/messages/i/invalid-enum-extension/good.py new file mode 100644 index 0000000000..80a4115b71 --- /dev/null +++ b/doc/data/messages/i/invalid-enum-extension/good.py @@ -0,0 +1,12 @@ +from enum import Enum + + +class Color(Enum): + ORANGE = 1 + CHERRY = 2 + + +class Fruit(Enum): + ORANGE = 1 + CHERRY = 2 + APPLE = 3 diff --git a/doc/data/messages/i/invalid-envvar-default/bad.py b/doc/data/messages/i/invalid-envvar-default/bad.py new file mode 100644 index 0000000000..9b564b9c8c --- /dev/null +++ b/doc/data/messages/i/invalid-envvar-default/bad.py @@ -0,0 +1,3 @@ +import os + +env = os.getenv("SECRET_KEY", 1) # [invalid-envvar-default] diff --git a/doc/data/messages/i/invalid-envvar-default/good.py b/doc/data/messages/i/invalid-envvar-default/good.py new file mode 100644 index 0000000000..103925941e --- /dev/null +++ b/doc/data/messages/i/invalid-envvar-default/good.py @@ -0,0 +1,3 @@ +import os + +env = os.getenv("SECRET_KEY", "1") diff --git a/doc/data/messages/i/invalid-envvar-value/bad.py b/doc/data/messages/i/invalid-envvar-value/bad.py new file mode 100644 index 0000000000..56e60fe700 --- /dev/null +++ b/doc/data/messages/i/invalid-envvar-value/bad.py @@ -0,0 +1,3 @@ +import os + +os.getenv(1) # [invalid-envvar-value] diff --git a/doc/data/messages/i/invalid-envvar-value/good.py b/doc/data/messages/i/invalid-envvar-value/good.py new file mode 100644 index 0000000000..fd082ecfd8 --- /dev/null +++ b/doc/data/messages/i/invalid-envvar-value/good.py @@ -0,0 +1,3 @@ +import os + +os.getenv("1") diff --git a/doc/data/messages/i/invalid-field-call/bad.py b/doc/data/messages/i/invalid-field-call/bad.py new file mode 100644 index 0000000000..56e357598b --- /dev/null +++ b/doc/data/messages/i/invalid-field-call/bad.py @@ -0,0 +1,16 @@ +from 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] diff --git a/doc/data/messages/i/invalid-field-call/good.py b/doc/data/messages/i/invalid-field-call/good.py new file mode 100644 index 0000000000..8a8d891c52 --- /dev/null +++ b/doc/data/messages/i/invalid-field-call/good.py @@ -0,0 +1,17 @@ +from 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 diff --git a/doc/data/messages/i/invalid-format-index/bad.py b/doc/data/messages/i/invalid-format-index/bad.py new file mode 100644 index 0000000000..74e6502a16 --- /dev/null +++ b/doc/data/messages/i/invalid-format-index/bad.py @@ -0,0 +1,2 @@ +not_enough_fruits = ["apple"] +print('The second fruit is a {fruits[1]}'.format(fruits=not_enough_fruits)) # [invalid-format-index] diff --git a/doc/data/messages/i/invalid-format-index/good.py b/doc/data/messages/i/invalid-format-index/good.py new file mode 100644 index 0000000000..69557980bc --- /dev/null +++ b/doc/data/messages/i/invalid-format-index/good.py @@ -0,0 +1,2 @@ +enough_fruits = ["apple", "banana"] +print("The second fruit is a {fruits[1]}".format(fruits=enough_fruits)) diff --git a/doc/data/messages/i/invalid-format-returned/bad.py b/doc/data/messages/i/invalid-format-returned/bad.py new file mode 100644 index 0000000000..8281084a1b --- /dev/null +++ b/doc/data/messages/i/invalid-format-returned/bad.py @@ -0,0 +1,5 @@ +class CustomFormat: + """__format__ returns """ + + def __format__(self, format_spec): # [invalid-format-returned] + return 1 diff --git a/doc/data/messages/i/invalid-format-returned/good.py b/doc/data/messages/i/invalid-format-returned/good.py new file mode 100644 index 0000000000..66b13cc874 --- /dev/null +++ b/doc/data/messages/i/invalid-format-returned/good.py @@ -0,0 +1,5 @@ +class CustomFormat: + """__format__ returns """ + + def __format__(self, format_spec): + return "hello!" diff --git a/doc/data/messages/i/invalid-getnewargs-ex-returned/bad.py b/doc/data/messages/i/invalid-getnewargs-ex-returned/bad.py new file mode 100644 index 0000000000..e07bdd7eac --- /dev/null +++ b/doc/data/messages/i/invalid-getnewargs-ex-returned/bad.py @@ -0,0 +1,5 @@ +class CustomGetNewArgsEx: + """__getnewargs_ex__ returns tuple with incorrect arg length""" + + def __getnewargs_ex__(self): # [invalid-getnewargs-ex-returned] + return (tuple(1), dict(x="y"), 1) diff --git a/doc/data/messages/i/invalid-getnewargs-ex-returned/good.py b/doc/data/messages/i/invalid-getnewargs-ex-returned/good.py new file mode 100644 index 0000000000..9d6e31c28c --- /dev/null +++ b/doc/data/messages/i/invalid-getnewargs-ex-returned/good.py @@ -0,0 +1,5 @@ +class CustomGetNewArgsEx: + """__getnewargs_ex__ returns """ + + def __getnewargs_ex__(self): + return ((1,), {"2": 2}) diff --git a/doc/data/messages/i/invalid-getnewargs-returned/bad.py b/doc/data/messages/i/invalid-getnewargs-returned/bad.py new file mode 100644 index 0000000000..e82523b357 --- /dev/null +++ b/doc/data/messages/i/invalid-getnewargs-returned/bad.py @@ -0,0 +1,5 @@ +class CustomGetNewArgs: + """__getnewargs__ returns an integer""" + + def __getnewargs__(self): # [invalid-getnewargs-returned] + return 1 diff --git a/doc/data/messages/i/invalid-getnewargs-returned/good.py b/doc/data/messages/i/invalid-getnewargs-returned/good.py new file mode 100644 index 0000000000..e61376c849 --- /dev/null +++ b/doc/data/messages/i/invalid-getnewargs-returned/good.py @@ -0,0 +1,5 @@ +class CustomGetNewArgs: + """__getnewargs__ returns """ + + def __getnewargs__(self): + return (1, 2) diff --git a/doc/data/messages/i/invalid-hash-returned/bad.py b/doc/data/messages/i/invalid-hash-returned/bad.py new file mode 100644 index 0000000000..2c4508f1e8 --- /dev/null +++ b/doc/data/messages/i/invalid-hash-returned/bad.py @@ -0,0 +1,5 @@ +class CustomHash: + """__hash__ returns dict""" + + def __hash__(self): # [invalid-hash-returned] + return {} diff --git a/doc/data/messages/i/invalid-hash-returned/good.py b/doc/data/messages/i/invalid-hash-returned/good.py new file mode 100644 index 0000000000..b18ebc14f7 --- /dev/null +++ b/doc/data/messages/i/invalid-hash-returned/good.py @@ -0,0 +1,5 @@ +class CustomHash: + """__hash__ returns `int`""" + + def __hash__(self): + return 19 diff --git a/doc/data/messages/i/invalid-index-returned/bad.py b/doc/data/messages/i/invalid-index-returned/bad.py new file mode 100644 index 0000000000..922abdf06f --- /dev/null +++ b/doc/data/messages/i/invalid-index-returned/bad.py @@ -0,0 +1,5 @@ +class CustomIndex: + """__index__ returns a dict""" + + def __index__(self): # [invalid-index-returned] + return {"19": "19"} diff --git a/doc/data/messages/i/invalid-index-returned/good.py b/doc/data/messages/i/invalid-index-returned/good.py new file mode 100644 index 0000000000..3b166be40a --- /dev/null +++ b/doc/data/messages/i/invalid-index-returned/good.py @@ -0,0 +1,5 @@ +class CustomIndex: + """__index__ returns """ + + def __index__(self): + return 19 diff --git a/doc/data/messages/i/invalid-length-hint-returned/bad.py b/doc/data/messages/i/invalid-length-hint-returned/bad.py new file mode 100644 index 0000000000..ef33425b68 --- /dev/null +++ b/doc/data/messages/i/invalid-length-hint-returned/bad.py @@ -0,0 +1,5 @@ +class CustomLengthHint: + """__length_hint__ returns non-int""" + + def __length_hint__(self): # [invalid-length-hint-returned] + return 3.0 diff --git a/doc/data/messages/i/invalid-length-hint-returned/good.py b/doc/data/messages/i/invalid-length-hint-returned/good.py new file mode 100644 index 0000000000..8c80a29b70 --- /dev/null +++ b/doc/data/messages/i/invalid-length-hint-returned/good.py @@ -0,0 +1,5 @@ +class CustomLengthHint: + """__length_hint__ returns """ + + def __length_hint__(self): + return 10 diff --git a/doc/data/messages/i/invalid-length-returned/bad.py b/doc/data/messages/i/invalid-length-returned/bad.py new file mode 100644 index 0000000000..2ae1396c38 --- /dev/null +++ b/doc/data/messages/i/invalid-length-returned/bad.py @@ -0,0 +1,6 @@ +class FruitBasket: + def __init__(self, fruits): + self.fruits = ["Apple", "Banana", "Orange"] + + def __len__(self): # [invalid-length-returned] + return -len(self.fruits) diff --git a/doc/data/messages/i/invalid-length-returned/good.py b/doc/data/messages/i/invalid-length-returned/good.py new file mode 100644 index 0000000000..1af71890fb --- /dev/null +++ b/doc/data/messages/i/invalid-length-returned/good.py @@ -0,0 +1,6 @@ +class FruitBasket: + def __init__(self, fruits): + self.fruits = ["Apple", "Banana", "Orange"] + + def __len__(self): + return len(self.fruits) diff --git a/doc/data/messages/i/invalid-metaclass/bad.py b/doc/data/messages/i/invalid-metaclass/bad.py new file mode 100644 index 0000000000..301b4f20ec --- /dev/null +++ b/doc/data/messages/i/invalid-metaclass/bad.py @@ -0,0 +1,2 @@ +class Apple(metaclass=int): # [invalid-metaclass] + pass diff --git a/doc/data/messages/i/invalid-metaclass/good.py b/doc/data/messages/i/invalid-metaclass/good.py new file mode 100644 index 0000000000..07c907f10c --- /dev/null +++ b/doc/data/messages/i/invalid-metaclass/good.py @@ -0,0 +1,6 @@ +class Plant: + pass + + +class Apple(Plant): + pass diff --git a/doc/data/messages/i/invalid-name/bad.py b/doc/data/messages/i/invalid-name/bad.py new file mode 100644 index 0000000000..b40ee47469 --- /dev/null +++ b/doc/data/messages/i/invalid-name/bad.py @@ -0,0 +1,7 @@ +class 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] diff --git a/doc/data/messages/i/invalid-name/details.rst b/doc/data/messages/i/invalid-name/details.rst new file mode 100644 index 0000000000..7cbf756380 --- /dev/null +++ b/doc/data/messages/i/invalid-name/details.rst @@ -0,0 +1,200 @@ +Pylint 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 variable defined at module level that is not bound to a class object. | ++--------------------+---------------------------------------------------------------------------------------------------+ +| ``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. | ++--------------------+---------------------------------------------------------------------------------------------------+ +| ``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``. | ++--------------------+---------------------------------------------------------------------------------------------------+ +| ``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 + +Following options are exposed: + +.. option:: --module-naming-style=