Skip to content

Incompatible config file options for naming hints in pylint 2.14.0 #6931

@andy-maier

Description

@andy-maier

Bug description

Pylint 2.14.0 rejects config files that worked before.

The problem with that is that we test our projects with many different Python versions, usually 2.7 and 3.5 and higher. Some minimum version requirements for pylint we define plus the supported Python versions of pylint itself usually result in the following Pylint versions that are used:

  • Python 2.7: pylint>=1.6.4,<2.0.0
  • Python 3.5: pylint>=2.5.2,<2.7.0
  • Python 3.6: pylint>=2.10.0,<2.14.0
  • Python 3.7: pylint>=2.10.0
  • Python 3.8: pylint>=2.10.0
  • Python 3.9: pylint>=2.10.0

Now pylint 2.14.0 requires to change the config file in a way that is no longer supported by earlier pylint versions.

Besides pinning pylint to <2.14.0, the other solution would be to start maintaining different versions of pylint config files, one for pylint <2.14, and one for pylint >=2.14 (plus to increase the minimum version of pylint to >=2.14.0 for Python >=3.7).

We are not really happy about the second option.

More specifically about the errors we get with pylint 2.14.1 and the older config files:

  • Several occurrences of E0015: Unrecognized option found on the config file:
    • optimize-ast, files-output, bad-functions, no-space-check - I could live with removing those in order to get to a compatible config file.
    • function-name-hint, variable-name-hint, const-name-hint, attr-name-hint, argument-name-hint, class-attribute-name-hint, inlinevar-name-hint, class-name-hint, module-name-hint, method-name-hint - This is where the incompatibility is: The old option names are rejected by pylint 2.14, and the new option names are rejected by older pylint versions.
  • One occurrence of W0012: Unknown option value for '--disable' on the config file:
    • locally-enabled - I can live with removing that in order to get to a compatible config file.
  • Several occurrences of W0012: Unknown option value for 'disable' on source code:
    • no-self-use - I can live with removing that in order to get to a compatible config file.

An additional issue is that I could not find these incompatibilities in the change log of 2.14.0. Specifically, I did not find anything in the change log about how to transform the old naming hint options to the new ones, or even what the names of the new ones are.

Configuration

# .pylintrc file from https://github.com/zhmcclient/zhmc-prometheus-exporter project:

#
# PyLint configuration file for the zhmc-prometheus-exporter project
#
# Originally generated by pylint 1.5.4, now manually maintained.
#


[MASTER]

# Specify a configuration file.
#rcfile=

# Python code to execute, usually for sys.path manipulation such as
# pygtk.require().
#init-hook=

# Add files or directories to the blacklist. They should be base names, not
# paths.
ignore=.svn,.git

# Pickle collected data for later comparisons.
persistent=yes

# List of plugins (as comma separated values of python modules names) to load,
# usually to register additional checkers.
load-plugins=

# Use multiple processes to speed up Pylint.
jobs=1

# Allow loading of arbitrary C extensions. Extensions are imported into the
# active Python interpreter and may run arbitrary code.
unsafe-load-any-extension=no

# A comma-separated list of package or module names from where C extensions may
# be loaded. Extensions are loading into the active Python interpreter and may
# run arbitrary code
extension-pkg-whitelist=


[MESSAGES CONTROL]

# Only show warnings with the listed confidence levels. Leave empty to show
# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED
confidence=

# 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. See also the "--disable" option for examples.
#enable=

# 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 reenable 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=I0011,
        too-many-locals, too-many-branches, too-many-statements,
        too-many-lines, too-many-public-methods,
        too-many-nested-blocks, too-many-return-statements, too-many-arguments,
        wildcard-import, unused-wildcard-import,
        locally-enabled, superfluous-parens, useless-object-inheritance,
        consider-using-set-comprehension, unnecessary-pass, useless-return,
        raise-missing-from, consider-using-f-string

# Note: The too-many-* messages are excluded temporarily, and should be dealt
#       with at some point.

# Note: wildcard related messages are excluded because the original external
#       interface uses wildcard imports and we cannot change that without
#       breaking compatibility. We could move the message control statements
#       into the source code, though.

# Note: messages are described here: http://pylint-messages.wikidot.com/all-messages


[REPORTS]

# Set the output format. Available formats are text, parseable, colorized, msvs
# (visual studio) and html. You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=text

# Tells whether to display a full report or only the messages
reports=no

# Python expression which should return a note less than 10 (10 is the highest
# note). You have access to the variables errors warning, statement which
# respectively contain the number of errors / warnings messages and the total
# number of statements analyzed. This is used by the global evaluation report
# (RP0004).
evaluation=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:
# http://docs.pylint.org/output.html#reports-section
# Note: This format only affects output format text, but not html.
# Note: The vim quickfix support by default recognizes the following format:
#   {path}:{line}: ...
#   {path}:{line}: {msg_id} {obj}: {msg}
# Note: Eclipse needs the following format:
#   {C}:{line:3d},{column:2d}: {msg} ({symbol})
# However, some messages show the source code in additional lines, as
# part of the {msg} field, and this causes Eclipse by mistake to suppress
# the entire message. So for now, we omit the {msg} field, for Eclipse:
#   '{C}:{line:3d},{column:2d}: ({symbol})'
# Note: The default format is:
#   {C}:{line:3d},{column:2d}: {msg} ({symbol})
# Note: Usage with geany editor
#   use output-format=parseable
#   No special message format.
#msg-template='{C}:{line:3d},{column:2d}: {msg} ({symbol})'


[VARIABLES]

# Tells whether we should check for unused import in __init__ files.
init-import=no

# A regular expression matching the name of dummy variables (i.e. expectedly
# not used).
dummy-variables-rgx=_$|dummy_|unused_

# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
additional-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


[BASIC]

# Good variable names which should always be accepted, separated by a comma
# TODO KS: Move i,... to local var and inline var; move _ to arg and local var and inline var.
good-names=_,f,i,j,k,m,n,__all__,__name__,__version__

# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata,l,O,I

# Colon-delimited sets of names that determine each other's naming style when
# the name regexes allow several styles.
name-group=

# Include a hint for the correct naming format with invalid-name
include-naming-hint=no

# Regular expression matching correct function names.
#
# The expression below allows "lower_case_with_underscores" and
# "mixedCaseWithoutUnderscores"; leading underscores for privacy as well as
# double trailing underscores are allowed.
# Names matching this expression are compatible with PEP-8.
function-rgx=_{0,2}([a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{1,39})(__){0,1}$
# TODO AM: Verify whether two leading underscores are allowed / supported with name mangling.

# Naming hint for function names
function-name-hint=_{0,2}([a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{1,39})(__){0,1}$

# Regular expression matching correct variable names.
#
# The expression below allows "UPPER_CASE_WITH_UNDERSCORES" for constants,
# and "lower_case_with_underscores" and "mixedCaseWithoutUnderscores" for
# other variables; one leading underscore is allowed, and one trailing
# underscore is allowed to avoid conflists with built-in names.
# Names matching this expression are compatible with PEP-8.
variable-rgx=_{0,1}([A-Z]([A-Z0-9_]{0,38}[A-Z0-9])?|[a-z]([a-z0-9_]{0,38}[a-z0-9])?|[a-z]([a-zA-Z0-9]{1,39})?)_{0,1}$

# Naming hint for variable names
variable-name-hint=_{0,1}([A-Z]([A-Z0-9_]{0,38}[A-Z0-9])?|[a-z]([a-z0-9_]{0,38}[a-z0-9])?|[a-z]([a-zA-Z0-9]{1,39})?)_{0,1}$

# Regular expression matching correct constant names.
#
# The expression below allows "UPPER_CASE_WITH_UNDERSCORES"; leading underscores
# for privacy are allowed.
# Names matching this expression are compatible with PEP-8.
const-rgx=(_{0,1}[A-Z][A-Z0-9_]{0,38}[A-Z0-9]|(__.*__))$

# Naming hint for constant names
const-name-hint=(_{0,1}[A-Z][A-Z0-9_]{0,38}[A-Z0-9]|(__.*__))$

# Regular expression matching correct attribute names.
#
# The expression below allows "lower_case_with_underscores" and
# "mixedCaseWithoutUnderscores"; leading underscores for privacy are allowed.
# Names matching this expression are compatible with PEP-8.
attr-rgx=_{0,2}([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{1,29})$

# Naming hint for attribute names
attr-name-hint=_{0,2}([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{1,29})$

# Regular expression matching correct argument names.
#
# The expression below allows "lower_case_with_underscores" and
# "mixedCaseWithoutUnderscores"; leading underscores are NOT allowed,
# but one trailing underscore is allowed to avoid conflists with built-in
# names.
# Names matching this expression are compatible with PEP-8.
argument-rgx=([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{1,29})_{0,1}$

# Naming hint for argument names
argument-name-hint=([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{1,29})_{0,1}$

# Regular expression matching correct class attribute names.
#
# The expression below allows "UPPER_CASE_WITH_UNDERSCORES" for constants,
# and "lower_case_with_underscores" and "mixedCaseWithoutUnderscores" for
# other variables; leading underscores for privacy are allowed.
# Names matching this expression are compatible with PEP-8.
class-attribute-rgx=_{0,2}([A-Z][A-Z0-9_]{0,38}[A-Z0-9]|[a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{0,39}|(__.*__))$

# Naming hint for class attribute names
class-attribute-name-hint=_{0,2}([A-Z][A-Z0-9_]{0,38}[A-Z0-9]|[a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{0,39}|(__.*__))$

# Regular expression matching correct inline iteration names.
#
# The expression below allows "lower_case_with_underscores" and
# "mixedCaseWithoutUnderscores"; leading underscores for privacy are allowed.
inlinevar-rgx=_{0,1}([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{0,29})$

# Naming hint for inline iteration names
inlinevar-name-hint=_{0,1}([a-z][a-z0-9_]{0,28}[a-z0-9]|[a-z][a-zA-Z0-9]{0,29})$

# Regular expression matching correct class names.
#
# The expression below allows "CamelCaseWithoutUnderscores"; leading underscores
# for privacy are allowed.
# Names matching this expression are compatible with PEP-8, but PEP-8 also
# allows that class names for callable classes can use function name syntax.
# This is not reflected in this regexp; callable classes that follow that
# convention should disable PyLint message C0103.
class-rgx=_{0,1}[A-Z][a-zA-Z0-9]{1,39}$

# Naming hint for class names
class-name-hint=_{0,1}[A-Z][a-zA-Z0-9]{1,39}$

# Regular expression matching correct module names.
#
# The expression below allows "lower_case_with_underscores"; leading underscores
# for privacy as well as double trailing underscores are allowed.
# Names matching this expression are compatible with PEP-8.
module-rgx=_{0,2}[a-z][a-z0-9_]{0,28}[a-z0-9](__){0,1}$

# Naming hint for module names
module-name-hint=_{0,2}[a-z][a-z0-9_]{0,28}[a-z0-9](__){0,1}$

# Regular expression matching correct method names.
#
# The expression below allows "lower_case_with_underscores" and
# "mixedCaseWithoutUnderscores"; leading underscores for privacy as well as
# double trailing underscores are allowed.
# Names matching this expression are compatible with PEP-8.
method-rgx=_{0,2}([a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{1,39})(__){0,1}$

# Naming hint for method names
method-name-hint=_{0,2}([a-z][a-z0-9_]{0,38}[a-z0-9]|[a-z][a-zA-Z0-9]{1,39})(__){0,1}$

# Regular expression which should only match function or class names that do
# not require a docstring.
no-docstring-rgx=__.*__

# Minimum line length for functions/classes that require docstrings, shorter
# ones are exempt.
docstring-min-length=-1


[ELIF]

# Maximum number of nested blocks for function / method body
max-nested-blocks=5


[TYPECHECK]

# Tells whether missing members accessed in mixin class should be ignored. A
# mixin class is detected if its name ends with "mixin" (case insensitive).
ignore-mixin-members=yes

# List of module names for which member attributes should not be checked
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
#
# Modules that create modules at run time cauase pylint to raise
# "no-name-in-module" and/or "import-error". Such modules can be put
# on the module ignore list. For details, see
# https://bitbucket.org/logilab/pylint/issues/223/ignored-modules-should-turn-no-name-in
ignored-modules=distutils,six,builtins,urllib,
                lxml,lxml.etree,ssl,

# List of classes names for which member attributes should not be checked
# (useful for classes with attributes dynamically set). This supports can work
# with qualified names.
ignored-classes=SQLObject

# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=REQUEST,acl_users,aq_parent


[SPELLING]

# Spelling dictionary name. Available dictionaries: none. To make it working
# install python-enchant package.
spelling-dict=

# List of comma separated words that should not be checked.
spelling-ignore-words=

# A path to a file that contains private dictionary; one word per line.
spelling-private-dict-file=

# Tells whether to store unknown words to indicated private dictionary in
# --spelling-private-dict-file option instead of raising a message.
spelling-store-unknown-words=no


[LOGGING]

# Logging modules to check that the string format arguments are in logging
# function parameter format
logging-modules=logging


[SIMILARITIES]

# Minimum lines number of a similarity.
min-similarity-lines=20

# Ignore comments when computing similarities.
ignore-comments=yes

# Ignore docstrings when computing similarities.
ignore-docstrings=yes

# Ignore imports when computing similarities.
ignore-imports=yes


[FORMAT]

# Maximum number of characters on a single line.
max-line-length=80

# Regexp for a line that is allowed to be longer than the limit.
ignore-long-lines=^\s*(# )?<?https?://\S+>?$

# Allow the body of an if to be on the same line as the test if there is no
# else.
single-line-if-stmt=no

# List of optional constructs for which whitespace checking is disabled. `dict-
# separator` is used to allow tabulation in dicts, etc.: {1  : 1,\n222: 2}.
# `trailing-comma` allows a space between comma and closing bracket: (a, ).
# `empty-line` allows space-only lines.
no-space-check=trailing-comma,dict-separator

# Maximum number of lines in a module
max-module-lines=1000

# String used as indentation unit. This is usually "    " (4 spaces) or "\t" (1
# tab).
indent-string='    '

# Number of spaces of indent required inside a hanging  or continued line.
indent-after-paren=4

# Expected format of line ending, e.g. empty (any line ending), LF or CRLF.
expected-line-ending-format=


[MISCELLANEOUS]

# List of note tags to take in consideration, separated by a comma.
notes=FIXME,XXX,TODO


[CLASSES]

# List of method names used to declare (i.e. assign) instance attributes.
defining-attr-methods=__init__,__new__,setUp

# 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=mcs

# List of member names, which should be excluded from the protected access
# warning.
exclude-protected=_asdict,_fields,_replace,_source,_make


[DESIGN]

# Maximum number of arguments for function / method
max-args=8

# Argument names that match this expression will be ignored. Default to name
# with leading underscore
ignored-argument-names=_.*

# Maximum number of locals for function / method body
max-locals=20

# Maximum number of return / yield for function / method body
max-returns=6

# Maximum number of branch for function / method body
max-branches=15

# Maximum number of statements in function / method body
# TODO AM: What counts as a statement?
max-statements=50

# Maximum number of parents for a class (see R0901).
max-parents=7

# Maximum number of attributes for a class (see R0902).
# TODO AM: Are these just variables, without methods? class & instance? including private? including inherited?
max-attributes=15

# Minimum number of public methods for a class (see R0903).
# TODO AM: including inherited?
min-public-methods=2

# Maximum number of public methods for a class (see R0904).
max-public-methods=20

# Maximum number of boolean expressions in a if statement
max-bool-expr=5


[IMPORTS]

# Deprecated modules which should not be used, separated by a comma
deprecated-modules=regsub,TERMIOS,Bastion,rexec

# Create a graph of every (i.e. internal and external) dependencies in the
# given file (report RP0402 must not be disabled)
import-graph=

# Create a graph of external dependencies in the given file (report RP0402 must
# not be disabled)
ext-import-graph=

# Create a graph of internal dependencies in the given file (report RP0402 must
# not be disabled)
int-import-graph=


[EXCEPTIONS]

# Exceptions that will emit a warning when being caught. Defaults to
# "Exception"
overgeneral-exceptions=Exception

Command used

# In https://github.com/zhmcclient/zhmc-prometheus-exporter project:

pylint --rcfile=.pylintrc --disable=fixme zhmc_prometheus_exporter/_version.py zhmc_prometheus_exporter/__init__.py zhmc_prometheus_exporter/zhmc_prometheus_exporter.py   tests/test_all.py   setup.py docs/conf.py

Pylint output

# From https://github.com/zhmcclient/zhmc-prometheus-exporter project:

************* Module .pylintrc
.pylintrc:1:0: E0015: Unrecognized option found: optimize-ast, files-output, bad-functions, function-name-hint, variable-name-hint, const-name-hint, attr-name-hint, argument-name-hint, class-attribute-name-hint, inlinevar-name-hint, class-name-hint, module-name-hint, method-name-hint, no-space-check (unrecognized-option)
.pylintrc:1:0: W0012: Unknown option value for '--disable', expected a valid pylint message and got 'locally-enabled' (unknown-option-value)
************* Module test_all
tests/test_all.py:207:0: W0012: Unknown option value for 'disable', expected a valid pylint message and got 'no-self-use' (unknown-option-value)
tests/test_all.py:277:0: W0012: Unknown option value for 'disable', expected a valid pylint message and got 'no-self-use' (unknown-option-value)
tests/test_all.py:468:0: W0012: Unknown option value for 'disable', expected a valid pylint message and got 'no-self-use' (unknown-option-value)

Expected behavior

A new pylint version may remove old options, but not incompatibly change old options (like the ones for naming hints). In case of the naming hint options, the new version of pylint could have introduced the new options and still supported the old options for compatibility.

Pylint version

pylint 2.13.4
astroid 2.11.2
Python 3.9.12 (main, Mar 26 2022, 15:52:10) 
[Clang 13.0.0 (clang-1300.0.29.30)]

OS / Environment

macOS 11.6.4

Additional dependencies

N/A

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions