What's New in Pylint 2.0
************************

Release:
   2.0

Date:
   2018-07-15


Summary -- Release highlights
=============================

* Dropped support for Python 2. This release will work only on Python
  3.4+.

  If you need to use "pylint" with Python 2, you can use Pylint 1.9+.
  We'll continue to do bug releases until 2020, when Python 2 goes
  officially EOL. "pylint" will gain the ability to analyze Python 2
  files, but some checks might not work as they will assume that their
  running environment is Python 2.

* Given the dropping of Python 2, the Python 3 porting mode (enabled
  via "--py3k") can now also run with Python 3.

  The porting mode used to be a no-op on Python 3, but most of the
  messages can now be emitted when the running interpreter is Python
  3. The only messages that won't be emitted are those that rely on a
  particular syntax specific to Python 2, for instance "print" as a
  statement.


New checkers
============

* A new check was added, "useless-object-inheritance".

  This refactoring message is emitted when pylint detects that a class
  inherits from object, which is redundant as in Python 3, every class
  implicitly inherits from object.

     class A(object):
         pass

     class A:    # better
         pass

* A new check was added, "comparison-with-callable".

  This refactoring message is emitted when pylint detects that a
  comparison with a callable was made, which might suggest that some
  parenthesis were omitted, resulting in potential unwanted behaviour.

     def foo():
         return None

     def goo():
         return None

     if foo == 786:  # bad
         pass

     if foo() == 786:    # good
         pass

* A new check was added, "chained-comparison".

  This refactoring message is emitted if a boolean operation can be
  simplified by chaining some of its operations. check below example:

     if a < b and b < c:
         pass

     if a < b < c:   # better
         pass

* A new check was added, "useless-import-alias".

  This refactoring message is emitted when an import alias does not
  rename the original package.

     import numpy as numpy # bad
     import numpy as np # good
     from collection import OrderedDict as OrderedDict # bad
     from collection import OrderedDict as ordered_dict # good

* A new check was added, "comparison-with-itself".

  This refactoring message is emitted when a variable is compared
  against itself.

     if variable == variable:  # bad
         pass

* A new check was added, "consider-using-in".

  This refactoring message is emitted when a variable is compared
  against multiple values concatenated by ors instead of using the
  faster, more idiomatic "in" check.

     if variable == 1 or variable == 2 or variable == 3:  # bad
         pass

     if variable in (1, 2, 3):  # good
         pass

* A new check was added, "consider-using-get".

  This refactoring message is emitted when manually checking if a key
  is in a dictionary and getting its value if it is (and optionally a
  default if not) instead of the more idiomatic dict.get.

     if 'key' in dictionary:  # bad
         variable = dictionary['key']
     else:
         variable = 'default'

     variable = dictionary.get('key', 'default')  # good

* A new check was added, "consider-using-join".

  This refactoring message is emitted when using a for loop over an
  iterable to join strings instead of the faster, less memory
  consuming and more idiomatic str.join(sequence).

     result = ''  # bad
     for number in ['1', '2', '3']:
         result += number

     result = ''.join(['1', '2', '3'])  # good

* 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.

* New "use-symbolic-message-instead" message when a message is
  activated or deactivated by id instead of symbol. The use of symbol
  is more explicit and easier to remind.

* A new check was added, "consider-swap-variables".

  This refactoring message is emitted when using a temporary variable
  in order to swap the values of two variables instead of the shorter,
  more idiomatic approach with tuple-unpacking.

  Instead of a temporary variable, the one-line syntax with commas
  should be used.

  See this style guide document or this swap values presentation for
  details.

     temp = a  # the wrong way
     a = b
     b = temp

     a, b = b, a  # the right way

* Two new checks, "invalid-envvar-value" and "invalid-envvar-default",
  were added.

  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.

* A new check was added, "subprocess-popen-preexec-fn",

  This refactoring message is emitted when using the keyword argument
  preexec_fn when creating subprocess.Popen instances which may be
  unsafe when used in the presence of threads.

  See subprocess.Popen for full warning details.

* New "try-except-raise" message when an except handler block has a
  bare "raise" statement as its first operator or the exception type
  being raised is the same as the one being handled.

* New "possibly-unused-variable" check added.

   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.

   For instance, the following code will now trigger this new error:

      def func():
          some_value = some_call()
          return locals()

* New "unhashable-dict-key" check added to detect dict lookups using
  unhashable keys such as lists or dicts.

* New "self-cls-assignment" warning check added.

  This is warning if the first argument of an instance/ class method
  gets assigned

     class Foo(object):
         def foo(self, bar):
             self = bar

* New verbose mode option "--verbose" to display of extra non-checker-
  related output. Disabled by default.

* Two new checks were added for recommending dict and set
  comprehensions where possible.

  These two checks are going to flag the following examples:

     dict([(k, v) for (k, v) in ...]) # better as {k: v for k, v in ...}
     set([k for k in ...]) # better as {k for k in ...}


Other Changes
=============

* A couple of performance improvements brought to "astroid" should
  make "pylint" should be a bit faster as well.

  We added a new flag, "max_inferable_values" on "astroid.MANAGER" for
  limitting the maximum amount of values that "astroid" can infer when
  inferring values. This change should improve the performance when
  dealing with large frameworks such as "django". You can also control
  this behaviour with "pylint --limit-inference-results"

  We also rewrote how "nodes_of_class" and "get_children" methods
  operate which should result in a performance boost for a couple of
  checks.

* Fix a false positive "inconsistent-return-statements" message when
  exception is raised inside an else statement.

* 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.

* Fix a false positive "inconsistent-return-statements" message when
  if statement is inside try/except.

* Fix a false positive "inconsistent-return-statements" message when
  "while" loop are used.

* Fix emission of false positive "no-member" message for class with
  "private" attributes whose name is mangled.

* Fix "unused-argument" false positives with overshadowed variable in
  dictionary comprehension.

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

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

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

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

* Suppress false-positive "not-callable" messages from certain
  staticmethod descriptors

* Expand "ignored-argument-names" include starred arguments and
  keyword arguments

* "singleton-comparison" will suggest better boolean conditions for
  negative conditions.

* "undefined-loop-variable" takes in consideration non-empty iterred
  objects before emitting.

  For instance, if the loop iterable is not empty, this check will no
  longer be emitted.

* Enum classes no longer trigger "too-few-methods"

* Special methods now count towards "too-few-methods", and are
  considered part of the public API. They are still not counted
  towards the number of methods for "too-many-methods".

* "docparams" extension allows abstract methods to document returns
  documentation even if the default implementation does not return
  something. They also no longer need to document raising a
  "NotImplementedError."

* Skip wildcard import check for "__init__.py".

* Don't warn 'useless-super-delegation' if the subclass method has
  different type annotations.

* Don't warn that a global variable is unused if it is defined by an
  import

     def func():
         global sys
         import sys

* Added basic support for postponed evaluation of function
  annotations.

  If "pylint" detects the corresponding "from __future__ import
  annotations" import, it will not emit "used-before-assignment" and
  "undefined-variable" in the cases triggered by the annotations.

  More details on the postponed evaluation of annotations can be read
  in PEP 563.

* A new command line option was added, "--exit-zero", for the use of
  continuous integration scripts which abort if a command returns a
  non-zero status code.  If the option is specified, and Pylint runs
  successfully, it will exit with 0 regardless of the number of lint
  issues detected.

  Configuration errors, parse errors, and calling Pylint with invalid
  command-line options all still return a non-zero error code, even if
  "--exit-zero" is specified.

* Don't emit "unused-import" anymore for typing imports used in type
  comments. For instance, in the following example pylint used to
  complain that "Any" and "List" are not used, while they should be
  considered used by a type checker.

     from typing import Any, List
     a = 1 # type: List[Any]

* Fix false positive "line-too-long" for commented lines at the end of
  module

* Fix emitting "useless-super-delegation" when changing the default
  value of keyword arguments.

* Support "typing.TYPE_CHECKING" for *unused-import* errors

  When modules are imported under "typing.TYPE_CHECKING" guard,
  "pylint" will no longer emit *unused-import*.

* Fix false positive "unused-variable" in lambda default arguments

* "assignment-from-no-return" considers methods as well as functions.

  If you have a method that doesn't return a value, but later on you
  assign a value to a function call to that method (so basically it
  will be "None"), then "pylint" is going to emit an "assignment-from-
  no-return" error.

* A new flag was added, "--ignore-none" which controls the "no-member"
  behaviour with respect to "None" values.

  Previously "pylint" was not emitting "no-member" if it inferred that
  the owner of an attribute access is a "None" value. In some cases,
  this might actually cause bugs, so if you want to check for "None"
  values as well, pass "--ignore-none=n" to pylint.

* Fix false-positive "bad-continuation" for with statements

* Fix false-positive "bad-whitespace" message for typing annoatations
  with ellipses in them

* Fix false-positive "undefined-variable" for nested lambdas
