summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Mueller <30130371+cdce8p@users.noreply.github.com>2022-10-21 23:16:06 +0200
committerGitHub <noreply@github.com>2022-10-21 23:16:06 +0200
commitbb17694867b1668db0cd3ae00c8a960d7f4b9868 (patch)
treef2650ed29d5d74dc99a923c8475b65c140f8318e
parent20af036e38c8cb8c16df4a12307319d6df4bee54 (diff)
parentfc7dc5eed76757e1beaa9525ef918a4eaf79eb38 (diff)
downloadpylint-git-bb17694867b1668db0cd3ae00c8a960d7f4b9868.tar.gz
Merge pull request #7660 from cdce8p/release-2.15.5v2.15.5
Release 2.15.5
-rw-r--r--.github/workflows/changelog.yml2
-rw-r--r--.github/workflows/checks.yaml2
-rw-r--r--.github/workflows/primer-test.yaml2
-rw-r--r--.github/workflows/primer_comment.yaml2
-rw-r--r--.github/workflows/primer_run_main.yaml2
-rw-r--r--.github/workflows/primer_run_pr.yaml2
-rw-r--r--.github/workflows/tests.yaml2
-rw-r--r--CONTRIBUTORS.txt3
-rw-r--r--doc/whatsnew/2/2.15/index.rst48
-rw-r--r--examples/pylintrc516
-rw-r--r--pylint/__pkginfo__.py2
-rw-r--r--pylint/checkers/dunder_methods.py4
-rw-r--r--pylint/checkers/refactoring/refactoring_checker.py11
-rw-r--r--pylint/checkers/typecheck.py31
-rw-r--r--pylint/checkers/utils.py51
-rw-r--r--pylint/config/arguments_manager.py7
-rw-r--r--pylint/lint/pylinter.py12
-rw-r--r--pyproject.toml2
-rw-r--r--requirements_test_min.txt2
-rw-r--r--script/.contributors_aliases.json6
-rw-r--r--script/create_contributor_list.py7
-rw-r--r--tbump.toml2
-rw-r--r--tests/functional/r/regression_02/regression_no_member_7631.py16
-rw-r--r--tests/functional/t/ternary.py32
-rw-r--r--tests/functional/t/ternary.txt16
-rw-r--r--tests/functional/u/unnecessary/unnecessary_dunder_call.py6
-rw-r--r--tests/test_check_parallel.py19
27 files changed, 477 insertions, 330 deletions
diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index 730f3dd08..87cdf278a 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -6,7 +6,7 @@ on:
env:
# Also change CACHE_VERSION in the other workflows
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
DEFAULT_PYTHON: "3.10"
jobs:
diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml
index 6cdca8fda..72c2ba1e5 100644
--- a/.github/workflows/checks.yaml
+++ b/.github/workflows/checks.yaml
@@ -8,7 +8,7 @@ on:
pull_request: ~
env:
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
DEFAULT_PYTHON: "3.10"
PRE_COMMIT_CACHE: ~/.cache/pre-commit
diff --git a/.github/workflows/primer-test.yaml b/.github/workflows/primer-test.yaml
index a865b1875..da1808abe 100644
--- a/.github/workflows/primer-test.yaml
+++ b/.github/workflows/primer-test.yaml
@@ -13,7 +13,7 @@ on:
- ".github/workflows/primer-test.yaml"
env:
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
diff --git a/.github/workflows/primer_comment.yaml b/.github/workflows/primer_comment.yaml
index a15c7aea3..1d4292ad0 100644
--- a/.github/workflows/primer_comment.yaml
+++ b/.github/workflows/primer_comment.yaml
@@ -14,7 +14,7 @@ on:
env:
# This needs to be the SAME as in the Main and PR job
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
permissions:
contents: read
diff --git a/.github/workflows/primer_run_main.yaml b/.github/workflows/primer_run_main.yaml
index 7b8609a6f..862ef1aa0 100644
--- a/.github/workflows/primer_run_main.yaml
+++ b/.github/workflows/primer_run_main.yaml
@@ -16,7 +16,7 @@ concurrency:
env:
# This needs to be the SAME as in the PR and comment job
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
jobs:
run-primer:
diff --git a/.github/workflows/primer_run_pr.yaml b/.github/workflows/primer_run_pr.yaml
index 22ba26dd5..7124b1d16 100644
--- a/.github/workflows/primer_run_pr.yaml
+++ b/.github/workflows/primer_run_pr.yaml
@@ -25,7 +25,7 @@ concurrency:
env:
# This needs to be the SAME as in the Main and comment job
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
jobs:
run-primer:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index 03643f90d..f03f685e8 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -10,7 +10,7 @@ on:
- doc/data/messages/**
env:
- CACHE_VERSION: 28
+ CACHE_VERSION: 31
jobs:
tests-linux:
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 9464d72ef..e7d4f8f3a 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -185,7 +185,7 @@ contributors:
- Marco Forte <fortemarco.irl@gmail.com>
- Ionel Maries Cristian <contact@ionelmc.ro>
- Gergely Kalmár <gergely.kalmar@logikal.jp>
-- Drummond Ogilvie <me@daogilvie.com>
+- Drum Ogilvie <me@daogilvie.com>
- Daniel Harding <dharding@gmail.com>
- Damien Baty <damien.baty@polyconseil.fr>
- Benjamin Drung <benjamin.drung@profitbricks.com>: contributing Debian Developer
@@ -499,6 +499,7 @@ contributors:
- Daniele Procida <daniele@vurt.org>
- Daniela Plascencia <daplascen@gmail.com>
- Daniel R. Neal <dan.r.neal@gmail.com> (danrneal)
+- Daniel Mouritzen <dmrtzn@gmail.com>
- Daniel Draper <Germandrummer92@users.noreply.github.com>
- Daniel Dorani <ddandd@gmail.com> (doranid)
- Daniel Brookman <53625739+dbrookman@users.noreply.github.com>
diff --git a/doc/whatsnew/2/2.15/index.rst b/doc/whatsnew/2/2.15/index.rst
index 5896de210..48c4479ba 100644
--- a/doc/whatsnew/2/2.15/index.rst
+++ b/doc/whatsnew/2/2.15/index.rst
@@ -29,6 +29,54 @@ Marc Byrne became a maintainer, welcome to the team !
.. towncrier release notes start
+What's new in Pylint 2.15.5?
+----------------------------
+Release date: 2022-10-21
+
+
+False Positives Fixed
+---------------------
+
+- Fix a false positive for ``simplify-boolean-expression`` when multiple values
+ are inferred for a constant.
+
+ Closes #7626 (`#7626 <https://github.com/PyCQA/pylint/issues/7626>`_)
+
+
+
+Other Bug Fixes
+---------------
+
+- Remove ``__index__`` dunder method call from ``unnecessary-dunder-call``
+ check.
+
+ Closes #6795 (`#6795 <https://github.com/PyCQA/pylint/issues/6795>`_)
+
+- Fixed a multi-processing crash that prevents using any more than 1 thread on
+ MacOS.
+
+ The returned module objects and errors that were cached by the linter plugin
+ loader
+ cannot be reliably pickled. This means that ``dill`` would throw an error
+ when
+ attempting to serialise the linter object for multi-processing use.
+
+ Closes #7635. (`#7635 <https://github.com/PyCQA/pylint/issues/7635>`_)
+
+
+
+Other Changes
+-------------
+
+- Add a keyword-only ``compare_constants`` argument to ``safe_infer``.
+
+ Refs #7626 (`#7626 <https://github.com/PyCQA/pylint/issues/7626>`_)
+
+- Sort ``--generated-rcfile`` output.
+
+ Refs #7655 (`#7655 <https://github.com/PyCQA/pylint/issues/7655>`_)
+
+
What's new in Pylint 2.15.4?
----------------------------
Release date: 2022-10-10
diff --git a/examples/pylintrc b/examples/pylintrc
index a955c56ed..a461b24d5 100644
--- a/examples/pylintrc
+++ b/examples/pylintrc
@@ -101,196 +101,6 @@ unsafe-load-any-extension=no
#verbose=
-[REPORTS]
-
-# Python expression which should return a score less than or equal to 10. You
-# have access to the variables 'fatal', 'error', 'warning', 'refactor',
-# 'convention', and 'info' which contain the number of messages in each
-# category, as well as 'statement' which is the total number of statements
-# analyzed. This score is used by the global evaluation report (RP0004).
-evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
-
-# Template used to display messages. This is a python new-style format string
-# used to format the message information. See doc for all details.
-msg-template=
-
-# Set the output format. Available formats are text, parseable, colorized, json
-# and msvs (visual studio). You can also give a reporter class, e.g.
-# mypackage.mymodule.MyReporterClass.
-#output-format=
-
-# Tells whether to display a full report or only the messages.
-reports=no
-
-# Activate the evaluation score.
-score=yes
-
-
-[MESSAGES CONTROL]
-
-# Only show warnings with the listed confidence levels. Leave empty to show
-# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
-# UNDEFINED.
-confidence=HIGH,
- CONTROL_FLOW,
- INFERENCE,
- INFERENCE_FAILURE,
- UNDEFINED
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifiers separated by comma (,) or put this
-# option multiple times (only on the command line, not in the configuration
-# file where it should appear only once). You can also use "--disable=all" to
-# disable everything first and then re-enable specific checks. For example, if
-# you want to run only the similarities checker, you can use "--disable=all
-# --enable=similarities". If you want to run only the classes checker, but have
-# no Warning level messages displayed, use "--disable=all --enable=classes
-# --disable=W".
-disable=raw-checker-failed,
- bad-inline-option,
- locally-disabled,
- file-ignored,
- suppressed-message,
- useless-suppression,
- deprecated-pragma,
- use-symbolic-message-instead
-
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once). See also the "--disable" option for examples.
-enable=c-extension-no-member
-
-
-[METHOD_ARGS]
-
-# List of qualified names (i.e., library.method) which require a timeout
-# parameter e.g. 'requests.api.get,requests.api.post'
-timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when caught.
-overgeneral-exceptions=BaseException,
- Exception
-
-
-[REFACTORING]
-
-# Maximum number of nested blocks for function / method body
-max-nested-blocks=5
-
-# Complete name of functions that never returns. When checking for
-# inconsistent-return-statements if a never returning function is called then
-# it will be considered as an explicit return statement and no message will be
-# printed.
-never-returning-functions=sys.exit,argparse.parse_error
-
-
-[DESIGN]
-
-# List of regular expressions of class ancestor names to ignore when counting
-# public methods (see R0903)
-exclude-too-few-public-methods=
-
-# List of qualified class names to ignore when counting class parents (see
-# R0901)
-ignored-parents=
-
-# Maximum number of arguments for function / method.
-max-args=5
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=7
-
-# Maximum number of boolean expressions in an if statement (see R0916).
-max-bool-expr=5
-
-# Maximum number of branch for function / method body.
-max-branches=12
-
-# Maximum number of locals for function / method body.
-max-locals=15
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=20
-
-# Maximum number of return / yield for function / method body.
-max-returns=6
-
-# Maximum number of statements in function / method body.
-max-statements=50
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=2
-
-
-[IMPORTS]
-
-# List of modules that can be imported at any level, not just the top level
-# one.
-allow-any-import-level=
-
-# Allow wildcard imports from modules that define __all__.
-allow-wildcard-with-all=no
-
-# Deprecated modules which should not be used, separated by a comma.
-deprecated-modules=
-
-# Output a graph (.gv or any supported image format) of external dependencies
-# to the given file (report RP0402 must not be disabled).
-ext-import-graph=
-
-# Output a graph (.gv or any supported image format) of all (i.e. internal and
-# external) dependencies to the given file (report RP0402 must not be
-# disabled).
-import-graph=
-
-# Output a graph (.gv or any supported image format) of internal dependencies
-# to the given file (report RP0402 must not be disabled).
-int-import-graph=
-
-# Force import order to recognize a module as part of the standard
-# compatibility libraries.
-known-standard-library=
-
-# Force import order to recognize a module as part of a third party library.
-known-third-party=enchant
-
-# Couples of modules and preferred modules, separated by a comma.
-preferred-modules=
-
-
-[CLASSES]
-
-# Warn about protected attribute access inside special methods
-check-protected-access-in-special-methods=no
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,
- __new__,
- setUp,
- __post_init__
-
-# List of member names, which should be excluded from the protected access
-# warning.
-exclude-protected=_asdict,
- _fields,
- _replace,
- _source,
- _make
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-# List of valid names for the first argument in a metaclass class method.
-valid-metaclass-classmethod-first-arg=cls
-
-
[BASIC]
# Naming style matching correct argument names.
@@ -427,89 +237,78 @@ variable-naming-style=snake_case
#variable-rgx=
-[SIMILARITIES]
-
-# Comments are removed from the similarity computation
-ignore-comments=yes
-
-# Docstrings are removed from the similarity computation
-ignore-docstrings=yes
-
-# Imports are removed from the similarity computation
-ignore-imports=yes
-
-# Signatures are removed from the similarity computation
-ignore-signatures=yes
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
+[CLASSES]
+# Warn about protected attribute access inside special methods
+check-protected-access-in-special-methods=no
-[LOGGING]
+# List of method names used to declare (i.e. assign) instance attributes.
+defining-attr-methods=__init__,
+ __new__,
+ setUp,
+ __post_init__
-# The type of string formatting that logging methods do. `old` means using %
-# formatting, `new` is for `{}` formatting.
-logging-format-style=old
+# List of member names, which should be excluded from the protected access
+# warning.
+exclude-protected=_asdict,
+ _fields,
+ _replace,
+ _source,
+ _make
-# Logging modules to check that the string format arguments are in logging
-# function parameter format.
-logging-modules=logging
+# List of valid names for the first argument in a class method.
+valid-classmethod-first-arg=cls
+# List of valid names for the first argument in a metaclass class method.
+valid-metaclass-classmethod-first-arg=cls
-[VARIABLES]
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid defining new builtins when possible.
-additional-builtins=
+[DESIGN]
-# Tells whether unused global variables should be treated as a violation.
-allow-global-unused-variables=yes
+# List of regular expressions of class ancestor names to ignore when counting
+# public methods (see R0903)
+exclude-too-few-public-methods=
-# List of names allowed to shadow builtins
-allowed-redefined-builtins=
+# List of qualified class names to ignore when counting class parents (see
+# R0901)
+ignored-parents=
-# List of strings which can identify a callback function by name. A callback
-# name must start or end with one of those strings.
-callbacks=cb_,
- _cb
+# Maximum number of arguments for function / method.
+max-args=5
-# A regular expression matching the name of dummy variables (i.e. expected to
-# not be used).
-dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+# Maximum number of attributes for a class (see R0902).
+max-attributes=7
-# Argument names that match this expression will be ignored.
-ignored-argument-names=_.*|^ignored_|^unused_
+# Maximum number of boolean expressions in an if statement (see R0916).
+max-bool-expr=5
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
+# Maximum number of branch for function / method body.
+max-branches=12
-# List of qualified module names which can have objects that can redefine
-# builtins.
-redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
+# Maximum number of locals for function / method body.
+max-locals=15
+# Maximum number of parents for a class (see R0901).
+max-parents=7
-[SPELLING]
+# Maximum number of public methods for a class (see R0904).
+max-public-methods=20
-# Limits count of emitted suggestions for spelling mistakes.
-max-spelling-suggestions=4
+# Maximum number of return / yield for function / method body.
+max-returns=6
-# Spelling dictionary name. Available dictionaries: en (aspell), en_AU
-# (aspell), en_CA (aspell), en_GB (aspell), en_US (aspell).
-spelling-dict=
+# Maximum number of statements in function / method body.
+max-statements=50
-# List of comma separated words that should be considered directives if they
-# appear at the beginning of a comment and should not be checked.
-spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
+# Minimum number of public methods for a class (see R0903).
+min-public-methods=2
-# List of comma separated words that should not be checked.
-spelling-ignore-words=
-# A path to a file that contains the private dictionary; one word per line.
-spelling-private-dict-file=
+[EXCEPTIONS]
-# Tells whether to store unknown words to the private dictionary (see the
-# --spelling-private-dict-file option) instead of raising a message.
-spelling-store-unknown-words=no
+# Exceptions that will emit a warning when caught.
+overgeneral-exceptions=BaseException,
+ Exception
[FORMAT]
@@ -542,6 +341,96 @@ single-line-class-stmt=no
single-line-if-stmt=no
+[IMPORTS]
+
+# List of modules that can be imported at any level, not just the top level
+# one.
+allow-any-import-level=
+
+# Allow wildcard imports from modules that define __all__.
+allow-wildcard-with-all=no
+
+# Deprecated modules which should not be used, separated by a comma.
+deprecated-modules=
+
+# Output a graph (.gv or any supported image format) of external dependencies
+# to the given file (report RP0402 must not be disabled).
+ext-import-graph=
+
+# Output a graph (.gv or any supported image format) of all (i.e. internal and
+# external) dependencies to the given file (report RP0402 must not be
+# disabled).
+import-graph=
+
+# Output a graph (.gv or any supported image format) of internal dependencies
+# to the given file (report RP0402 must not be disabled).
+int-import-graph=
+
+# Force import order to recognize a module as part of the standard
+# compatibility libraries.
+known-standard-library=
+
+# Force import order to recognize a module as part of a third party library.
+known-third-party=enchant
+
+# Couples of modules and preferred modules, separated by a comma.
+preferred-modules=
+
+
+[LOGGING]
+
+# The type of string formatting that logging methods do. `old` means using %
+# formatting, `new` is for `{}` formatting.
+logging-format-style=old
+
+# Logging modules to check that the string format arguments are in logging
+# function parameter format.
+logging-modules=logging
+
+
+[MESSAGES CONTROL]
+
+# Only show warnings with the listed confidence levels. Leave empty to show
+# all. Valid levels: HIGH, CONTROL_FLOW, INFERENCE, INFERENCE_FAILURE,
+# UNDEFINED.
+confidence=HIGH,
+ CONTROL_FLOW,
+ INFERENCE,
+ INFERENCE_FAILURE,
+ UNDEFINED
+
+# Disable the message, report, category or checker with the given id(s). You
+# can either give multiple identifiers separated by comma (,) or put this
+# option multiple times (only on the command line, not in the configuration
+# file where it should appear only once). You can also use "--disable=all" to
+# disable everything first and then re-enable specific checks. For example, if
+# you want to run only the similarities checker, you can use "--disable=all
+# --enable=similarities". If you want to run only the classes checker, but have
+# no Warning level messages displayed, use "--disable=all --enable=classes
+# --disable=W".
+disable=raw-checker-failed,
+ bad-inline-option,
+ locally-disabled,
+ file-ignored,
+ suppressed-message,
+ useless-suppression,
+ deprecated-pragma,
+ use-symbolic-message-instead
+
+# Enable the message, report, category or checker with the given id(s). You can
+# either give multiple identifier separated by comma (,) or put this option
+# multiple time (only on the command line, not in the configuration file where
+# it should appear only once). See also the "--disable" option for examples.
+enable=c-extension-no-member
+
+
+[METHOD_ARGS]
+
+# List of qualified names (i.e., library.method) which require a timeout
+# parameter e.g. 'requests.api.get,requests.api.post'
+timeout-methods=requests.api.delete,requests.api.get,requests.api.head,requests.api.options,requests.api.patch,requests.api.post,requests.api.put,requests.api.request
+
+
[MISCELLANEOUS]
# List of note tags to take in consideration, separated by a comma.
@@ -553,6 +442,96 @@ notes=FIXME,
notes-rgx=
+[REFACTORING]
+
+# Maximum number of nested blocks for function / method body
+max-nested-blocks=5
+
+# Complete name of functions that never returns. When checking for
+# inconsistent-return-statements if a never returning function is called then
+# it will be considered as an explicit return statement and no message will be
+# printed.
+never-returning-functions=sys.exit,argparse.parse_error
+
+
+[REPORTS]
+
+# Python expression which should return a score less than or equal to 10. You
+# have access to the variables 'fatal', 'error', 'warning', 'refactor',
+# 'convention', and 'info' which contain the number of messages in each
+# category, as well as 'statement' which is the total number of statements
+# analyzed. This score is used by the global evaluation report (RP0004).
+evaluation=max(0, 0 if fatal else 10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10))
+
+# Template used to display messages. This is a python new-style format string
+# used to format the message information. See doc for all details.
+msg-template=
+
+# Set the output format. Available formats are text, parseable, colorized, json
+# and msvs (visual studio). You can also give a reporter class, e.g.
+# mypackage.mymodule.MyReporterClass.
+#output-format=
+
+# Tells whether to display a full report or only the messages.
+reports=no
+
+# Activate the evaluation score.
+score=yes
+
+
+[SIMILARITIES]
+
+# Comments are removed from the similarity computation
+ignore-comments=yes
+
+# Docstrings are removed from the similarity computation
+ignore-docstrings=yes
+
+# Imports are removed from the similarity computation
+ignore-imports=yes
+
+# Signatures are removed from the similarity computation
+ignore-signatures=yes
+
+# Minimum lines number of a similarity.
+min-similarity-lines=4
+
+
+[SPELLING]
+
+# Limits count of emitted suggestions for spelling mistakes.
+max-spelling-suggestions=4
+
+# Spelling dictionary name. Available dictionaries: en (aspell), en_AU
+# (aspell), en_CA (aspell), en_GB (aspell), en_US (aspell).
+spelling-dict=
+
+# List of comma separated words that should be considered directives if they
+# appear at the beginning of a comment and should not be checked.
+spelling-ignore-comment-directives=fmt: on,fmt: off,noqa:,noqa,nosec,isort:skip,mypy:
+
+# List of comma separated words that should not be checked.
+spelling-ignore-words=
+
+# A path to a file that contains the private dictionary; one word per line.
+spelling-private-dict-file=
+
+# Tells whether to store unknown words to the private dictionary (see the
+# --spelling-private-dict-file option) instead of raising a message.
+spelling-store-unknown-words=no
+
+
+[STRING]
+
+# This flag controls whether inconsistent-quotes generates a warning when the
+# character used as a quote delimiter is used inconsistently within a module.
+check-quote-consistency=no
+
+# This flag controls whether the implicit-str-concat should generate a warning
+# on implicit string concatenation in sequences defined over several lines.
+check-str-concat-over-line-jumps=no
+
+
[TYPECHECK]
# List of decorators that produce context managers, such as
@@ -607,12 +586,33 @@ mixin-class-rgx=.*[Mm]ixin
signature-mutators=
-[STRING]
+[VARIABLES]
-# This flag controls whether inconsistent-quotes generates a warning when the
-# character used as a quote delimiter is used inconsistently within a module.
-check-quote-consistency=no
+# List of additional names supposed to be defined in builtins. Remember that
+# you should avoid defining new builtins when possible.
+additional-builtins=
-# This flag controls whether the implicit-str-concat should generate a warning
-# on implicit string concatenation in sequences defined over several lines.
-check-str-concat-over-line-jumps=no
+# Tells whether unused global variables should be treated as a violation.
+allow-global-unused-variables=yes
+
+# List of names allowed to shadow builtins
+allowed-redefined-builtins=
+
+# List of strings which can identify a callback function by name. A callback
+# name must start or end with one of those strings.
+callbacks=cb_,
+ _cb
+
+# A regular expression matching the name of dummy variables (i.e. expected to
+# not be used).
+dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_
+
+# Argument names that match this expression will be ignored.
+ignored-argument-names=_.*|^ignored_|^unused_
+
+# Tells whether we should check for unused import in __init__ files.
+init-import=no
+
+# List of qualified module names which can have objects that can redefine
+# builtins.
+redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io
diff --git a/pylint/__pkginfo__.py b/pylint/__pkginfo__.py
index 189471a6d..07f0cd7c0 100644
--- a/pylint/__pkginfo__.py
+++ b/pylint/__pkginfo__.py
@@ -9,7 +9,7 @@ It's updated via tbump, do not modify.
from __future__ import annotations
-__version__ = "2.15.4"
+__version__ = "2.15.5"
def get_numversion_from_version(v: str) -> tuple[int, int, int]:
diff --git a/pylint/checkers/dunder_methods.py b/pylint/checkers/dunder_methods.py
index 1b61be7d4..2e5e54a57 100644
--- a/pylint/checkers/dunder_methods.py
+++ b/pylint/checkers/dunder_methods.py
@@ -100,7 +100,6 @@ DUNDER_METHODS: dict[tuple[int, int], dict[str, str]] = {
"__complex__": "Use complex built-in function",
"__int__": "Use int built-in function",
"__float__": "Use float built-in function",
- "__index__": "Use index method",
"__round__": "Use round built-in function",
"__trunc__": "Use math.trunc function",
"__floor__": "Use math.floor function",
@@ -125,7 +124,8 @@ class DunderCallChecker(BaseChecker):
We exclude __new__, __subclasses__, __init_subclass__, __set_name__,
__class_getitem__, __missing__, __exit__, __await__,
__aexit__, __getnewargs_ex__, __getnewargs__, __getstate__,
- __setstate__, __reduce__, __reduce_ex__
+ __setstate__, __reduce__, __reduce_ex__,
+ and __index__ (see https://github.com/PyCQA/pylint/issues/6795)
since these either have no alternative method of being called or
have a genuine use case for being called manually.
diff --git a/pylint/checkers/refactoring/refactoring_checker.py b/pylint/checkers/refactoring/refactoring_checker.py
index 3a59b3d82..005f0e03c 100644
--- a/pylint/checkers/refactoring/refactoring_checker.py
+++ b/pylint/checkers/refactoring/refactoring_checker.py
@@ -21,7 +21,7 @@ from astroid.util import Uninferable
from pylint import checkers
from pylint.checkers import utils
from pylint.checkers.utils import node_frame_class
-from pylint.interfaces import HIGH
+from pylint.interfaces import HIGH, INFERENCE
if TYPE_CHECKING:
from pylint.lint import PyLinter
@@ -1493,11 +1493,10 @@ class RefactoringChecker(checkers.BaseTokenChecker):
):
return
- inferred_truth_value = utils.safe_infer(truth_value)
+ inferred_truth_value = utils.safe_infer(truth_value, compare_constants=True)
if inferred_truth_value is None or inferred_truth_value == astroid.Uninferable:
- truth_boolean_value = True
- else:
- truth_boolean_value = inferred_truth_value.bool_value()
+ return
+ truth_boolean_value = inferred_truth_value.bool_value()
if truth_boolean_value is False:
message = "simplify-boolean-expression"
@@ -1505,7 +1504,7 @@ class RefactoringChecker(checkers.BaseTokenChecker):
else:
message = "consider-using-ternary"
suggestion = f"{truth_value.as_string()} if {cond.as_string()} else {false_value.as_string()}"
- self.add_message(message, node=node, args=(suggestion,))
+ self.add_message(message, node=node, args=(suggestion,), confidence=INFERENCE)
def _append_context_managers_to_stack(self, node: nodes.Assign) -> None:
if _is_inside_context_manager(node):
diff --git a/pylint/checkers/typecheck.py b/pylint/checkers/typecheck.py
index f2518beae..d97f352f6 100644
--- a/pylint/checkers/typecheck.py
+++ b/pylint/checkers/typecheck.py
@@ -6,7 +6,6 @@
from __future__ import annotations
-import fnmatch
import heapq
import itertools
import operator
@@ -14,7 +13,6 @@ import re
import shlex
import sys
import types
-from collections import deque
from collections.abc import Callable, Iterator, Sequence
from functools import singledispatch
from re import Pattern
@@ -36,6 +34,7 @@ from pylint.checkers.utils import (
is_inside_abstract_class,
is_iterable,
is_mapping,
+ is_module_ignored,
is_node_in_type_annotation_context,
is_overload_stub,
is_postponed_evaluation_enabled,
@@ -116,32 +115,8 @@ def _is_owner_ignored(owner, attrname, ignored_classes, ignored_modules):
matches any name from the *ignored_classes* or if its qualified
name can be found in *ignored_classes*.
"""
- ignored_modules = set(ignored_modules)
- module_name = owner.root().name
- module_qname = owner.root().qname()
-
- for ignore in ignored_modules:
- # Try to match the module name / fully qualified name directly
- if module_qname in ignored_modules or module_name in ignored_modules:
- return True
-
- # Try to see if the ignores pattern match against the module name.
- if fnmatch.fnmatch(module_qname, ignore):
- return True
-
- # Otherwise, we might have a root module name being ignored,
- # and the qualified owner has more levels of depth.
- parts = deque(module_name.split("."))
- current_module = ""
-
- while parts:
- part = parts.popleft()
- if not current_module:
- current_module = part
- else:
- current_module += f".{part}"
- if current_module in ignored_modules:
- return True
+ if is_module_ignored(owner.root(), ignored_modules):
+ return True
# Match against ignored classes.
ignored_classes = set(ignored_classes)
diff --git a/pylint/checkers/utils.py b/pylint/checkers/utils.py
index d00b8a653..b7e0596d1 100644
--- a/pylint/checkers/utils.py
+++ b/pylint/checkers/utils.py
@@ -7,11 +7,13 @@
from __future__ import annotations
import builtins
+import fnmatch
import itertools
import numbers
import re
import string
import warnings
+from collections import deque
from collections.abc import Iterable, Iterator
from functools import lru_cache, partial
from re import Match
@@ -1331,12 +1333,18 @@ def _get_python_type_of_node(node: nodes.NodeNG) -> str | None:
@lru_cache(maxsize=1024)
def safe_infer(
- node: nodes.NodeNG, context: InferenceContext | None = None
+ node: nodes.NodeNG,
+ context: InferenceContext | None = None,
+ *,
+ compare_constants: bool = False,
) -> InferenceResult | None:
"""Return the inferred value for the given node.
Return None if inference failed or if there is some ambiguity (more than
one node has been inferred of different types).
+
+ If compare_constants is True and if multiple constants are inferred,
+ unequal inferred values are also considered ambiguous and return None.
"""
inferred_types: set[str | None] = set()
try:
@@ -1356,6 +1364,13 @@ def safe_infer(
if inferred_type not in inferred_types:
return None # If there is ambiguity on the inferred node.
if (
+ compare_constants
+ and isinstance(inferred, nodes.Const)
+ and isinstance(value, nodes.Const)
+ and inferred.value != value.value
+ ):
+ return None
+ if (
isinstance(inferred, nodes.FunctionDef)
and inferred.args.args is not None
and isinstance(value, nodes.FunctionDef)
@@ -1952,3 +1967,37 @@ def is_hashable(node: nodes.NodeNG) -> bool:
return False
except astroid.InferenceError:
return True
+
+
+def is_module_ignored(
+ module: nodes.Module,
+ ignored_modules: Iterable[str],
+) -> bool:
+ ignored_modules = set(ignored_modules)
+ module_name = module.name
+ module_qname = module.qname()
+
+ for ignore in ignored_modules:
+ # Try to match the module name / fully qualified name directly
+ if module_qname in ignored_modules or module_name in ignored_modules:
+ return True
+
+ # Try to see if the ignores pattern match against the module name.
+ if fnmatch.fnmatch(module_qname, ignore):
+ return True
+
+ # Otherwise, we might have a root module name being ignored,
+ # and the qualified owner has more levels of depth.
+ parts = deque(module_name.split("."))
+ current_module = ""
+
+ while parts:
+ part = parts.popleft()
+ if not current_module:
+ current_module = part
+ else:
+ current_module += f".{part}"
+ if current_module in ignored_modules:
+ return True
+
+ return False
diff --git a/pylint/config/arguments_manager.py b/pylint/config/arguments_manager.py
index eda1a583d..40058071c 100644
--- a/pylint/config/arguments_manager.py
+++ b/pylint/config/arguments_manager.py
@@ -437,7 +437,10 @@ class _ArgumentsManager:
)
options_by_section = {}
sections = []
- for group in self._arg_parser._action_groups:
+ for group in sorted(
+ self._arg_parser._action_groups,
+ key=lambda x: (x.title != "Main", x.title),
+ ):
group_name = group.title
assert group_name
if group_name in skipsections:
@@ -449,7 +452,7 @@ class _ArgumentsManager:
for i in group._group_actions
if not isinstance(i, argparse._SubParsersAction)
]
- for opt in option_actions:
+ for opt in sorted(option_actions, key=lambda x: x.option_strings[0][2:]):
if "--help" in opt.option_strings:
continue
diff --git a/pylint/lint/pylinter.py b/pylint/lint/pylinter.py
index cb528c5df..47d5baaf5 100644
--- a/pylint/lint/pylinter.py
+++ b/pylint/lint/pylinter.py
@@ -296,7 +296,7 @@ class PyLinter(
str, list[checkers.BaseChecker]
] = collections.defaultdict(list)
"""Dictionary of registered and initialized checkers."""
- self._dynamic_plugins: dict[str, ModuleType | ModuleNotFoundError] = {}
+ self._dynamic_plugins: dict[str, ModuleType | ModuleNotFoundError | bool] = {}
"""Set of loaded plugin names."""
# Attributes related to registering messages and their handling
@@ -400,7 +400,15 @@ class PyLinter(
"bad-plugin-value", args=(modname, module_or_error), line=0
)
elif hasattr(module_or_error, "load_configuration"):
- module_or_error.load_configuration(self)
+ module_or_error.load_configuration(self) # type: ignore[union-attr]
+
+ # We re-set all the dictionary values to True here to make sure the dict
+ # is pickle-able. This is only a problem in multiprocessing/parallel mode.
+ # (e.g. invoking pylint -j 2)
+ self._dynamic_plugins = {
+ modname: not isinstance(val, ModuleNotFoundError)
+ for modname, val in self._dynamic_plugins.items()
+ }
def _load_reporters(self, reporter_names: str) -> None:
"""Load the reporters if they are available on _reporters."""
diff --git a/pyproject.toml b/pyproject.toml
index b6a494af8..6e542d48a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -38,7 +38,7 @@ dependencies = [
# github actions if you are bumping astroid.
# Pinned to dev of second minor update to allow editable installs and fix primer issues,
# see https://github.com/PyCQA/astroid/issues/1341
- "astroid>=2.12.11,<=2.14.0-dev0",
+ "astroid>=2.12.12,<=2.14.0-dev0",
"isort>=4.2.5,<6",
"mccabe>=0.6,<0.8",
"tomli>=1.1.0;python_version<'3.11'",
diff --git a/requirements_test_min.txt b/requirements_test_min.txt
index 6b2dcdf2a..2a3e043a4 100644
--- a/requirements_test_min.txt
+++ b/requirements_test_min.txt
@@ -1,7 +1,7 @@
-e .[testutils,spelling]
# astroid dependency is also defined in pyproject.toml
# You need to increment the CACHE_VERSION in github actions too
-astroid==2.12.11 # Pinned to a specific version for tests
+astroid==2.12.12 # Pinned to a specific version for tests
typing-extensions~=4.3
pytest~=7.1
pytest-benchmark~=3.4
diff --git a/script/.contributors_aliases.json b/script/.contributors_aliases.json
index 95808f651..6563c71d4 100644
--- a/script/.contributors_aliases.json
+++ b/script/.contributors_aliases.json
@@ -261,6 +261,10 @@
"name": "Dimitri Prybysh",
"team": "Maintainers"
},
+ "dmrtzn@gmail.com": {
+ "mails": ["dmrtzn@gmail.com"],
+ "name": "Daniel Mouritzen"
+ },
"drewrisinger@users.noreply.github.com": {
"mails": ["drewrisinger@users.noreply.github.com"],
"name": "Drew Risinger"
@@ -438,7 +442,7 @@
},
"me@daogilvie.com": {
"mails": ["me@daogilvie.com", "drum.ogilvie@ovo.com"],
- "name": "Drummond Ogilvie"
+ "name": "Drum Ogilvie"
},
"me@the-compiler.org": {
"mails": [
diff --git a/script/create_contributor_list.py b/script/create_contributor_list.py
index 9b336a01b..7db3923f5 100644
--- a/script/create_contributor_list.py
+++ b/script/create_contributor_list.py
@@ -6,9 +6,10 @@ from pathlib import Path
from contributors_txt import create_contributors_txt
-BASE_DIRECTORY = Path(__file__).parent.parent
-ALIASES_FILE = BASE_DIRECTORY / "script/.contributors_aliases.json"
-DEFAULT_CONTRIBUTOR_PATH = BASE_DIRECTORY / "CONTRIBUTORS.txt"
+CWD = Path(".").absolute()
+BASE_DIRECTORY = Path(__file__).parent.parent.absolute()
+ALIASES_FILE = (BASE_DIRECTORY / "script/.contributors_aliases.json").relative_to(CWD)
+DEFAULT_CONTRIBUTOR_PATH = (BASE_DIRECTORY / "CONTRIBUTORS.txt").relative_to(CWD)
def main():
diff --git a/tbump.toml b/tbump.toml
index 3a7cfaa9b..ed6d6d5f3 100644
--- a/tbump.toml
+++ b/tbump.toml
@@ -1,7 +1,7 @@
github_url = "https://github.com/PyCQA/pylint"
[version]
-current = "2.15.4"
+current = "2.15.5"
regex = '''
^(?P<major>0|[1-9]\d*)
\.
diff --git a/tests/functional/r/regression_02/regression_no_member_7631.py b/tests/functional/r/regression_02/regression_no_member_7631.py
new file mode 100644
index 000000000..758aad057
--- /dev/null
+++ b/tests/functional/r/regression_02/regression_no_member_7631.py
@@ -0,0 +1,16 @@
+"""Regression test from https://github.com/PyCQA/pylint/issues/7631
+The following code should NOT raise no-member.
+"""
+# pylint: disable=missing-docstring,too-few-public-methods
+
+class Base:
+ attr: int = 2
+
+class Parent(Base):
+ attr: int
+
+class Child(Parent):
+ attr = 2
+
+ def __init__(self):
+ self.attr = self.attr | 4
diff --git a/tests/functional/t/ternary.py b/tests/functional/t/ternary.py
index 58171942f..48f97ffd9 100644
--- a/tests/functional/t/ternary.py
+++ b/tests/functional/t/ternary.py
@@ -1,18 +1,23 @@
"""Test for old ternary constructs"""
-from UNINFERABLE import condition, true_value, false_value, some_callable # pylint: disable=import-error
+from UNINFERABLE import condition, some_callable, maybe_true, maybe_false # pylint: disable=import-error
-SOME_VALUE1 = true_value if condition else false_value
-SOME_VALUE2 = condition and true_value or false_value # [consider-using-ternary]
+TRUE_VALUE = True
+FALSE_VALUE = False
+
+SOME_VALUE1 = TRUE_VALUE if condition else FALSE_VALUE
+SOME_VALUE2 = condition and TRUE_VALUE or FALSE_VALUE # [consider-using-ternary]
+NOT_SIMPLIFIABLE_1 = maybe_true if condition else maybe_false
+NOT_SIMPLIFIABLE_2 = condition and maybe_true or maybe_false
SOME_VALUE3 = condition
def func1():
"""Ternary return value correct"""
- return true_value if condition else false_value
+ return TRUE_VALUE if condition else FALSE_VALUE
def func2():
"""Ternary return value incorrect"""
- return condition and true_value or false_value # [consider-using-ternary]
+ return condition and TRUE_VALUE or FALSE_VALUE # [consider-using-ternary]
SOME_VALUE4 = some_callable(condition) and 'ERROR' or 'SUCCESS' # [consider-using-ternary]
@@ -30,10 +35,23 @@ IS_LEAP_YEAR = YEAR % 4 == 0 and YEAR % 100 != 0 or YEAR % 400 == 0
def func4():
""""Using a Name as a condition but still emits"""
truth_value = 42
- return condition and truth_value or false_value # [consider-using-ternary]
+ return condition and truth_value or FALSE_VALUE # [consider-using-ternary]
def func5():
""""Using a Name that infers to False as a condition does not emit"""
falsy_value = False
- return condition and falsy_value or false_value # [simplify-boolean-expression]
+ return condition and falsy_value or FALSE_VALUE # [simplify-boolean-expression]
+
+
+def func_control_flow():
+ """Redefining variables should invalidate simplify-boolean-expression."""
+ flag_a = False
+ flag_b = False
+ for num in range(2):
+ if num == 1:
+ flag_a = True
+ else:
+ flag_b = True
+ multiple = (flag_a and flag_b) or func5()
+ return multiple
diff --git a/tests/functional/t/ternary.txt b/tests/functional/t/ternary.txt
index bdec7bcc4..ca93acd2f 100644
--- a/tests/functional/t/ternary.txt
+++ b/tests/functional/t/ternary.txt
@@ -1,8 +1,8 @@
-consider-using-ternary:5:0:5:53::Consider using ternary (true_value if condition else false_value):UNDEFINED
-consider-using-ternary:15:4:15:50:func2:Consider using ternary (true_value if condition else false_value):UNDEFINED
-consider-using-ternary:18:0:18:63::Consider using ternary ('ERROR' if some_callable(condition) else 'SUCCESS'):UNDEFINED
-consider-using-ternary:19:0:19:60::Consider using ternary ('greater' if SOME_VALUE1 > 3 else 'not greater'):UNDEFINED
-consider-using-ternary:20:0:20:67::Consider using ternary ('both' if SOME_VALUE2 > 4 and SOME_VALUE3 else 'not'):UNDEFINED
-simplify-boolean-expression:23:0:23:50::Boolean expression may be simplified to SOME_VALUE2:UNDEFINED
-consider-using-ternary:33:4:33:51:func4:Consider using ternary (truth_value if condition else false_value):UNDEFINED
-simplify-boolean-expression:39:4:39:51:func5:Boolean expression may be simplified to false_value:UNDEFINED
+consider-using-ternary:8:0:8:53::Consider using ternary (TRUE_VALUE if condition else FALSE_VALUE):INFERENCE
+consider-using-ternary:20:4:20:50:func2:Consider using ternary (TRUE_VALUE if condition else FALSE_VALUE):INFERENCE
+consider-using-ternary:23:0:23:63::Consider using ternary ('ERROR' if some_callable(condition) else 'SUCCESS'):INFERENCE
+consider-using-ternary:24:0:24:60::Consider using ternary ('greater' if SOME_VALUE1 > 3 else 'not greater'):INFERENCE
+consider-using-ternary:25:0:25:67::Consider using ternary ('both' if SOME_VALUE2 > 4 and SOME_VALUE3 else 'not'):INFERENCE
+simplify-boolean-expression:28:0:28:50::Boolean expression may be simplified to SOME_VALUE2:INFERENCE
+consider-using-ternary:38:4:38:51:func4:Consider using ternary (truth_value if condition else FALSE_VALUE):INFERENCE
+simplify-boolean-expression:44:4:44:51:func5:Boolean expression may be simplified to FALSE_VALUE:INFERENCE
diff --git a/tests/functional/u/unnecessary/unnecessary_dunder_call.py b/tests/functional/u/unnecessary/unnecessary_dunder_call.py
index cd1f21286..18e4ef855 100644
--- a/tests/functional/u/unnecessary/unnecessary_dunder_call.py
+++ b/tests/functional/u/unnecessary/unnecessary_dunder_call.py
@@ -122,3 +122,9 @@ INSTANTIATED_SELF = int("1").__add__(1) # [unnecessary-dunder-call]
# since we can't apply alternate operators/functions here.
a = [1, 2, 3]
assert super(type(a), a).__str__() == "[1, 2, 3]"
+
+class MyString(str):
+ """Custom str implementation"""
+ def rjust(self, width, fillchar= ' '):
+ """Acceptable call to __index__"""
+ width = width.__index__()
diff --git a/tests/test_check_parallel.py b/tests/test_check_parallel.py
index 3b6d82e04..a7fb5c158 100644
--- a/tests/test_check_parallel.py
+++ b/tests/test_check_parallel.py
@@ -11,6 +11,7 @@ from __future__ import annotations
import argparse
import multiprocessing
import os
+from pickle import PickleError
import dill
import pytest
@@ -231,6 +232,24 @@ class TestCheckParallelFramework:
assert stats.statement == 18
assert stats.warning == 0
+ def test_linter_with_unpickleable_plugins_is_pickleable(self) -> None:
+ """The linter needs to be pickle-able in order to be passed between workers"""
+ linter = PyLinter(reporter=Reporter())
+ # We load an extension that we know is not pickle-safe
+ linter.load_plugin_modules(["pylint.extensions.overlapping_exceptions"])
+ try:
+ dill.dumps(linter)
+ assert False, "Plugins loaded were pickle-safe! This test needs altering"
+ except (KeyError, TypeError, PickleError, NotImplementedError):
+ pass
+
+ # And expect this call to make it pickle-able
+ linter.load_plugin_configuration()
+ try:
+ dill.dumps(linter)
+ except KeyError:
+ assert False, "Cannot pickle linter when using non-pickleable plugin"
+
def test_worker_check_sequential_checker(self) -> None:
"""Same as test_worker_check_single_file_no_checkers with SequentialTestChecker."""
linter = PyLinter(reporter=Reporter())