What's New In Pylint 1.8
************************

Release:
   1.8

Date:
   2017-12-15


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 = os.environ.copy()  # 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", and "ifilterfalse".

     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" or "IntType"

     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 the "Iterator" 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 use "six.Iterator" as a
  base class or alias "next" 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 like

     raise 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 a "StopIteration" inside a generator may be due a
  direct call to "raise StopIteration":

     def gen_stopiter():
         yield 1
         yield 2
         yield 3
         raise StopIteration

  Instead use a simple "return" statement

     def gen_stopiter():
         yield 1
         yield 2
         yield 3
         return

  Raising a "StopIteration" may also be due to the call to "next"
  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. Close
  #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

  Close #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 is "message-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
  form "Invalid constant name var", without offering any context why
  "var" 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 involving "in" operator (see example below for what used
  to be false-postive).

     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" and "missing-type-doc" are no longer emitted
  when "Args" and "Keyword 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 emitting
  *missing-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 directive "disable=fixme" doesn't deactivate anymore the
  emission of "line-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 a false positive inconsistent-return-statements message when if
  statement is inside try/except. (backport from 2.0)

* Fix a false positive inconsistent-return-statements message when
  while loop are used. (backport from 2.0)

* Fix unused-argument false positives with overshadowed variable in
  dictionary comprehension. (backport from 2.0)

* Fixing false positive "inconsistent-return-statements" when never
  returning functions are used (i.e such as sys.exit). (backport from
  2.0)

* Fix false positive "inconsistent-return-statements" message when a
  function is defined under an if statement. (backport from 2.0)

* Fix false positive "inconsistent-return-statements" message by
  avoiding useless exception inference if the exception is not
  handled. (backport from 2.0)

* Fix false positive "undefined-variable" for lambda arguments in
     class definitions

* Fix false-positive "undefined-variable" for generated comprehension
  variables in function default arguments
