Summary -- Release highlights¶
None so far
New checkers¶
A new check was added,
shallow-copy-environ
.This warning message is emitted when shallow copy of os.environ is created. 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.
import copy import os wrong_env_copy = copy.copy(os.environ) # will emit pylint warning wrong_env_copy['ENV_VAR'] = 'new_value' # changes os.environ assert os.environ['ENV_VAR'] == 'new_value' good_env_copy = dict(os.environ) # the right way good_env_copy['ENV_VAR'] = 'different_value' # doesn't change os.environ assert os.environ['ENV_VAR'] == 'new_value'
A new check was added,
keyword-arg-before-vararg
.This warning message is emitted when a function is defined with a keyword argument appearing before variable-length 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.
def foo(a, b=3, *args): print(a, b, args) # Case1: a=0, b=2, args=(4,5) foo(0,2,4,5) # 0 2 (4,5) ==> Observed values are same as expected values # Case2: a=0, b=<default_value>, args=(4,5) foo(0,4,5) # 0 4 (5,) ==> args list got modified as well as the observed value of b # Case3: Syntax Error if tried as follows foo(0,b=2,4,5) # syntax error
A new check was added,
simplify-boolean-expression
.This message is emitted when
consider-using-ternary
check would emit not equivalent code, due to truthy element being falsy in boolean context.value = condition and False or other_value
This flawed construct may be simplified to:
value = other_value
A new check was added,
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.
In the following example, the instantiation will fail, which is definitely not desired:
import threading threading.Thread(lambda: print(1)) # Oups, this is the group parameter
A new Python 3 checker was added to warn about accessing functions that have been removed from the itertools module
izip
,imap
,iflter
,izip_longest
, andifilterfalse
.from itertools import izip print(list(izip([1, 2], [3])))
Instead use
six.moves
to import a Python 2 and Python 3 compatible function:from six.moves import zip print(list(zip([1, 2], [3])))
A new Python 3 checker was added to warn about accessing deprecated fields from the types module like
ListType
orIntType
from types import ListType print(isinstance([], ListType))
Instead use the declarations in the builtin namespace:
print(isinstance([], list))
A new Python 3 checker was added to warn about declaring a
next
method that would have implemented theIterator
protocol in Python 2 but is now a normal method in Python 3.class Foo(object): def next(self): return 42
Instead implement a
__next__
method and usesix.Iterator
as a base class or aliasnext
to__next__
:class Foo(object): def __next__(self): return 42 next = __next__
Three new Python 3 checkers were added to warn about using dictionary methods in non-iterating contexts.
For example, the following are returning iterators in Python 3:
.. code-block:: python
d = {} d.keys()[0] d.items()[0] d.values() + d.keys()
A new Python 3 porting check was added,
non-ascii-bytes-literals
This message is emitted whenever we detect that a bytes string contain non-ASCII characters, which results in a SyntaxError on Python 3.
A new warning,
raising-format-tuple
, will catch situations where the intent was likely raising an exception with a formatted message string, but the actual code did omit the formatting and instead passes template string and value parameters as separate arguments to the exception constructor. So it detects things likeraise SomeError('message about %s', foo) raise SomeError('message about {}', foo)
which likely were meant instead as
raise SomeError('message about %s' % foo) raise SomeError('message about {}'.format(foo))
This warning can be ignored on projects which deliberately use lazy formatting of messages in all user-facing exception handlers.
Following the recommendations of PEP479 ,a new Python 3.0 checker was added to warn about raising a
StopIteration
inside a generator. Raising aStopIteration
inside a generator may be due a direct call toraise StopIteration
:def gen_stopiter(): yield 1 yield 2 yield 3 raise StopIteration
Instead use a simple
return
statementdef gen_stopiter(): yield 1 yield 2 yield 3 return
Raising a
StopIteration
may also be due to the call tonext
function with a generator as argument:def gen_next_raises_stopiter(): g = gen_ok() while True: yield next(g)
In this case, surround the call to
next
with a try/except block:def gen_next_raises_stopiter(): g = gen_ok() while True: try: yield next(g) except StopIteration: return
The check about raising a StopIteration inside a generator is also valid if the exception raised inherit from StopIteration.
Closes #1385
A new Python checker was added to warn about using a
+
operator inside call of logging methods when one of the operands is a literal string:import logging var = "123" logging.log(logging.INFO, "Var: " + var)
Instead use formatted string and positional arguments :
import logging var = "123" logging.log(logging.INFO, "Var: %s", var)
A new Python checker was added to warn about
inconsistent-return-statements
. A function or a method has inconsistent return statements if it returns both explicit and implicit values :def mix_implicit_explicit_returns(arg): if arg < 10: return True elif arg < 20: return
According to PEP8, if any return statement returns an expression, any return statements where no value is returned should explicitly state this as return None, and an explicit return statement should be present at the end of the function (if reachable). Thus, the previous function should be written:
def mix_implicit_explicit_returns(arg): if arg < 10: return True elif arg < 20: return None
Closes #1267
Other Changes¶
Fixing u'' string in superfluous-parens message.
Configuration options of invalid name checker are significantly redesigned. Predefined rules for common naming styles were introduced. For typical setups, user friendly options like
--function-naming-style=camelCase
may be used in place of hand-written regular expressions. Default linter config enforce PEP8-compatible naming style. See documentation for details.Raise meaningful exception in case of invalid reporter class (output format) being selected.
The docparams extension now allows a property docstring to document both the property and the setter. Therefore setters can also have no docstring.
The docparams extension now understands property type syntax.
class Foo(object): @property def foo(self): """My Sphinx style docstring description. :type: int """ return 10
class Foo(object): @property def foo(self): """int: My Numpy and Google docstring style description.""" return 10
In case of
--output-format=json
, the dictionary returned holds a new key-value pair. The key ismessage-id
and the value the message id.Spelling checker has a new configuration parameter
max-spelling-suggestions
, which affects maximum count of suggestions included in emitted message.The invalid-name check contains the name of the template that caused the failure.
For the given code, pylint used to emit
invalid-name
in the formInvalid constant name var
, without offering any context whyvar
is not such a good name.With this change, it is now more clear what should be improved for a name to be accepted according to its corresponding template.
New configuration flag,
suggestion-mode
was introduced. When enabled, pylint would attempt to emit user-friendly suggestions instead of spurious errors for some known false-positive scenarios. Flag is enabled by default.superfluous-parens
is no longer wrongly emitted for logical statements involvingin
operator (see example below for what used to be false-positive).foo = None if 'bar' in (foo or {}): pass
Redefinition of dummy function is now possible.
function-redefined
message won't be emitted anymore when dummy functions are redefined.missing-param-doc
andmissing-type-doc
are no longer emitted whenArgs
andKeyword Args
are mixed in Google docstring.Fix of false positive
useless-super-delegation
message when parameters default values are different from those used in the base class.Fix of false positive
useless-else-on-loop
message when break statements are deeply nested inside loop.The Python 3 porting checker no longer emits multiple
no-absolute-import
per file.The Python 3 porting checker respects disabled checkers found in the config file.
Modules, classes, or methods consist of compound statements that exceed the
docstring-min-length
are now correctly emittingmissing-docstring
Fix no
wrong-import-order
message emitted on ordering of first and third party libraries. With this fix, pylint distinguishes first and third party modules when checking import order.Fix the ignored
pylint disable=fixme
directives for comments following the last statement in a file.Fix
line-too-long
message deactivated by wrong disable directive. The directivedisable=fixme
doesn't deactivate anymore the emission ofline-too-long
message for long commented lines.If the rcfile specified on the command line doesn't exist, then an IOError exception is raised.
Fix the wrong scope of
disable=
directive after a commented line. For example when adisable=line-too-long
directive is at the end of a long commented line, it no longer disables the emission ofline-too-long
message for lines that follow.