Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • pycqa/pylint
1 result
Show changes
Commits on Source (98)
Showing
with 560 additions and 97 deletions
Loading
Loading
@@ -9,8 +9,8 @@
/pylint.egg-info/
.tox
*.sw[a-z]
doc/extensions.rst
doc/features.rst
doc/technical_reference/extensions.rst
doc/technical_reference/features.rst
pyve
build-stamp
debian/files
Loading
Loading
Loading
Loading
@@ -5,6 +5,9 @@ matrix:
include:
- python: 2.7
env: TOXENV=py27
- python: 2.7.6
env: TOXENV=py27
# This is used by Ubuntu Trusty
- python: 3.3
env: TOXENV=py33
- python: 3.4
Loading
Loading
@@ -24,6 +27,7 @@ before_install:
- sudo apt-get -qq update
- sudo apt-get install -y enchant
install:
- pip install -U setuptools
- pip install tox coverage coveralls
- virtualenv --version
- easy_install --version
Loading
Loading
@@ -33,8 +37,6 @@ install:
script:
# Test install with current version of setuptools
- pip install .
# Run the tests with newest version of setuptools
- pip install -U setuptools
- tox -e coverage-erase,$TOXENV
after_success:
- tox -e coveralls
Loading
Loading
Loading
Loading
@@ -135,3 +135,9 @@ Order doesn't matter (not that much, at least ;)
* Petr Pulc: require whitespace around annotations
 
* John Paraskevopoulos: add 'differing-param-doc' and 'differing-type-doc'
* Martin von Gagern (Google): Added 'raising-format-tuple' warning.
* Ahirnish Pareek, 'keyword-arg-before-var-arg' check
* Guillaume Peillex: contributor.
Loading
Loading
@@ -4,6 +4,57 @@ Pylint's ChangeLog
What's New in Pylint 1.8?
=========================
 
* Fixing u'' string in superfluous-parens message
Close #1420
* `abstract-class-instantiated` is now emitted for all inference paths.
Close #1673
* Add set of predefined naming style to ease configuration of checking
naming conventions.
Closes #1013
* Added a new check, ``keyword-arg-before-vararg``
This is emitted for function definitions
in which keyword arguments are placed before variable
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.
* The `invalid-name` check contains the name of the template that caused the failure
Close #1176
* Using the -j flag won't start more child linters than needed.
Contributed by Roman Ivanov in #1614
* Fix a false positive with bad-python3-import on relative imports
Close #1608
* Added a new Python 3 check, ``non-ascii-bytes-literals``
Close #1545
* Added a couple of new Python 3 checks for accessing dict methods in non-iterable context
* Protocol checks (not-a-mapping, not-an-iterable and co.) aren't emitted on classes with dynamic getattr
* Added a new warning, '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.
Close #1327
* In non-quiet mode, absolute path of used config file is logged to
standard error.
Close #1519
Loading
Loading
@@ -24,10 +75,70 @@ What's New in Pylint 1.8?
* Added a new Python 3 check for declaring a method ``next`` that would have
been treated as an iterator in Python 2 but a normal function in Python 3.
 
* Added a new key-value pair in json output. The key is ``message-id``
and the value is the message id.
Close #1512
* Added a new Python 3.0 check for raising a StopIteration inside a generator.
The check about raising a StopIteration inside a generator is also valid if the exception
raised inherit from StopIteration.
Close #1385
* Added a new warning, ``raising-format-tuple``, to detect multi-argument
exception construction instead of message string formatting.
* Added a new check for method of logging module that concatenate string via + operator
Close #1479
* Added parameter for limiting number of suggestions in spellchecking checkers
* Fix a corner-case in ``consider-using-ternary`` checker.
When object ``A`` used in ``X and A or B`` was falsy in boolean context,
Pylint incorrectly emitted non-equivalent ternary-based suggestion.
After a change message is correctly not emitted for this case.
Close #1559
* Added ``suggestion-mode`` configuration flag. When flag is enabled, informational
message is emitted instead of cryptic error message for attributes accessed on
c-extensions.
Close #1466
* Fix a false positive ``useless-super-delegation`` message when
parameters default values are different from those used in the base class.
Close #1085
* Disabling 'wrong-import-order', 'wrong-import-position', or
'ungrouped-imports' for a single line now prevents that line from
triggering violations on subsequent lines.
Close #1336
* Added a new Python check for inconsistent return statements inside method or function.
Close #1267
* Fix ``superfluous-parens`` false positive related to handling logical statements
involving ``in`` operator.
Close #574
* ``function-redefined`` message is no longer emitted for functions and
methods which names matches dummy variable name regular expression.
Close #1369
* Fix ``missing-param-doc`` and ``missing-type-doc`` false positives when
mixing ``Args`` and ``Keyword Args`` in Google docstring.
Close #1409
* Fix ``useless-else-on-loop`` false positives when break statements are
deeply nested inside loop.
Close #1661
What's New in Pylint 1.7.1?
=========================
 
Release date: |TBA|
Release date: 2017-04-17
 
* Fix a false positive which occurred when an exception was reraised
 
Loading
Loading
@@ -2156,7 +2267,7 @@ Release date: 2009-12-18
 
* include James Lingard string format checker
 
* include simple message (ids) listing by Vincent Férotin (#9791)
* include simple message (ids) listing by Vincent Ferotin (#9791)
 
* --errors-only does not hide fatal error anymore
 
Loading
Loading
@@ -2179,7 +2290,7 @@ Release date: 2009-12-18
 
* fix test/fulltest.sh
 
* #5821 added a utility function to run pylint in another process (patch provide by Vincent Férotin)
* #5821 added a utility function to run pylint in another process (patch provide by Vincent Ferotin)
 
 
What's New in Pylint 0.18.0?
Loading
Loading
Loading
Loading
@@ -25,7 +25,12 @@ sys.path.append(os.path.abspath('exts'))
 
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['pylint_features', 'pylint_extensions']
extensions = [
'pylint_features',
'pylint_extensions',
'sphinx.ext.autosectionlabel',
'sphinx.ext.intersphinx',
]
 
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
Loading
Loading
@@ -41,7 +46,7 @@ master_doc = 'index'
 
# General information about the project.
project = u'Pylint'
copyright = u'2003-2016, Logilab, PyCQA and contributors'
copyright = u'2003-2017, Logilab, PyCQA and contributors'
 
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
Loading
Loading
@@ -214,3 +219,8 @@ man_pages = [
('index', 'pylint', u'Pylint Documentation',
[u'Logilab, PyCQA and contributors'], 1)
]
intersphinx_mapping = {
'astroid': ('http://astroid.readthedocs.io/en/latest/', None),
'python': ('https://docs.python.org/3', None),
}
Loading
Loading
@@ -39,6 +39,8 @@ Archives before April 2013 are available at
http://lists.logilab.org/pipermail/python-projects/
 
 
.. _repository:
Repository
----------
 
Loading
Loading
@@ -91,7 +93,9 @@ your patch gets accepted.
about this topic)
 
 
Functional tests
.. _functional_tests:
Functional Tests
----------------
 
These are residing under '/test/functional' and they are formed of multiple
Loading
Loading
@@ -128,3 +132,40 @@ current environment in order to have faster feedback. Run with::
.. _`Closing issues via commit messages`: https://help.github.com/articles/closing-issues-via-commit-messages/
.. _`About pull requests`: https://help.github.com/articles/using-pull-requests/
.. _tox: http://tox.readthedocs.io/en/latest/
Tips for Getting Started with Pylint Development
------------------------------------------------
* Read the :ref:`technical-reference`. It gives a short walkthrough of the pylint
codebase and will help you identify where you will need to make changes
for what you are trying to implement.
* :func:`astroid.extract_node` is your friend. Most checkers are AST based,
so you will likely need to interact with :mod:`astroid`.
A short example of how to use :func:`astroid.extract_node` is given
:ref:`here <astroid_extract_node>`.
* When fixing a bug for a specific check, search the code for the warning
message to find where the warning is raised,
and therefore where the logic for that code exists.
A Typical Development Workflow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#. Create a virtualenv in which to work::
$ tox
#. Write the tests. See :ref:`functional_tests`.
#. Check that the tests fail::
$ tox
#. Fix pylint!
#. Make sure your tests pass::
$ tox
It is also possible to give tox a `pytest specifier <https://docs.pytest.org/en/latest/usage.html#specifying-tests-selecting-tests>`_
to run only your test::
$ tox pylint/test/test_functional.py::test_functional
#. Package up and submit your changes as outlined in `repository`_.
Loading
Loading
@@ -48,7 +48,7 @@ def builder_inited(app):
linter = PyLinter()
linter.load_plugin_modules(modules)
 
extensions_doc = os.path.join(base_path, 'doc', 'reference_guide', 'extensions.rst')
extensions_doc = os.path.join(base_path, 'doc', 'technical_reference', 'extensions.rst')
with open(extensions_doc, 'w') as stream:
stream.write("Optional Pylint checkers in the extensions module\n")
stream.write("=================================================\n\n")
Loading
Loading
Loading
Loading
@@ -18,7 +18,7 @@ def builder_inited(app):
linter = PyLinter()
linter.load_default_plugins()
 
features = os.path.join(base_path, 'doc', 'reference_guide', 'features.rst')
features = os.path.join(base_path, 'doc', 'technical_reference', 'features.rst')
with open(features, 'w') as stream:
stream.write("Pylint features\n")
stream.write("===============\n\n")
Loading
Loading
Loading
Loading
@@ -25,7 +25,7 @@ standard, and tries to enforce a coding style.
2.1 How do I install Pylint?
----------------------------
 
Everything should be explained on http://pylint.readthedocs.io/en/latest/installation
Everything should be explained on :ref:`installation`.
 
2.2 What kind of versioning system does Pylint use?
---------------------------------------------------
Loading
Loading
@@ -118,7 +118,7 @@ For example::
3.4 I'd rather not run Pylint from the command line. Can I integrate it with my editor?
---------------------------------------------------------------------------------------
 
Much probably. Read http://pylint.readthedocs.io/en/latest/ide-integration
Much probably. Read :ref:`ide-integration`
 
4. Message Control
==================
Loading
Loading
@@ -228,9 +228,9 @@ above expression.
6.2 I think I found a bug in Pylint. What should I do?
-------------------------------------------------------
 
Read http://pylint.readthedocs.io/en/latest/contribute#bug-reports-feedback
Read :ref:`Bug reports, feedback`
 
6.3 I have a question about Pylint that isn't answered here.
------------------------------------------------------------
 
Read http://pylint.readthedocs.io/en/latest/contribute#mailing-lists
Read :ref:`Mailing lists`
.. _write_a_checker:
How to Write a Checker
======================
You can find some simple examples in the distribution
(`custom.py <https://github.com/PyCQA/pylint/blob/master/examples/custom.py>`_
and
`custom_raw.py <https://github.com/PyCQA/pylint/blob/master/examples/custom_raw.py>`_).
.. TODO Create custom_token.py
There are three kinds of checkers:
* Raw checkers, which analyse each module as a raw file stream.
* Token checkers, which analyse a file using the list of tokens that
represent the source code in the file.
* AST checkers, which work on an AST representation of the module.
The AST representation is provided by the :mod:`astroid` library.
:mod:`astroid` adds additional information and methods
over :mod:`ast` in the standard library,
to make tree navigation and code introspection easier.
.. TODO Writing a Raw Checker
.. TODO Writing a Token Checker
Writing an AST Checker
----------------------
Let's implement a checker to make sure that all ``return`` nodes in a function
return a unique constant.
Firstly we will need to fill in some required boilerplate:
.. code-block:: python
import astroid
from pylint.checkers import BaseChecker
from pylint.interfaces import IAstroidChecker
class UniqueReturnChecker(BaseChecker):
__implements__ = IAstroidChecker
name = 'unique-returns'
priority = -1
msgs = {
'W0001': (
'Returns a non-unique constant.',
'non-unique-returns',
'All constants returned in a function should be unique.'
),
}
options = (
(
'ignore-ints',
{
'default': False, 'type': 'yn', 'metavar' : '<y_or_n>',
'help': 'Allow returning non-unique integers',
}
),
)
So far we have defined the following required components of our checker:
* A name. The name is used to generate a special configuration
section for the checker, when options have been provided.
* A priority. This must be to be lower than 0. The checkers are ordered by
the priority when run, from the most negative to the most positive.
* A message dictionary. Each checker is being used for finding problems
in your code, the problems being displayed to the user through **messages**.
The message dictionary should specify what messages the checker is
going to emit. It has the following format::
msgs = {
'message-id': (
'displayed-message', 'message-symbol', 'message-help'
)
}
* The ``message-id`` should be a 5-digit number,
prefixed with a **message category**.
There are multiple message categories,
these being ``C``, ``W``, ``E``, ``F``, ``R``,
standing for ``Convention``, ``Warning``, ``Error``, ``Fatal`` and ``Refactoring``.
The rest of the 5 digits should not conflict with existing checkers
and they should be consistent across the checker.
For instance,
the first two digits should not be different across the checker.
* The ``displayed-message`` is used for displaying the message to the user,
once it is emitted.
* The ``message-symbol`` is an alias of the message id
and it can be used wherever the message id can be used.
* The ``message-help`` is used when calling ``pylint --help-msg``.
We have also defined an optional component of the checker.
The options list defines any user configurable options.
It has the following format::
options = (
'option-symbol': {'argparse-like-kwarg': 'value'},
)
* The ``option-symbol`` is a unique name for the option.
This is used on the command line and in config files.
The hyphen is replaced by an underscore when used in the checker,
similarly to how you would use :class:`argparse.Namespace`.
Next we'll track when we enter and leave a function.
.. code-block:: python
def __init__(self, linter=None):
super(UniqueReturnChecker, self).__init__(linter)
self._function_stack = []
def visit_functiondef(self, node):
self._function_stack.append([])
def leave_functiondef(self, node):
self._function_stack.pop()
In the constructor we initialise a stack to keep a list of return nodes
for each function.
An AST checker is a visitor, and should implement
``visit_<lowered class name>`` or ``leave_<lowered class name>``
methods for the nodes it's interested in.
In this case we have implemented ``visit_functiondef`` and ``leave_functiondef``
to add a new list of return nodes for this function,
and to remove the list of return nodes when we leave the function.
Finally we'll implement the check.
We will define a ``visit_return`` function,
which is called with a :class:`.astroid.node_classes.Return` node.
.. _astroid_extract_node:
.. TODO We can shorten/remove this bit once astroid has API docs.
We'll need to be able to figure out what attributes a
:class:`.astroid.node_classes.Return` node has available.
We can use :func:`astroid.extract_node` for this::
>>> node = astroid.extract_node("return 5")
>>> node
<Return l.1 at 0x7efe62196390>
>>> help(node)
>>> node.value
<Const.int l.1 at 0x7efe62196ef0>
We could also construct a more complete example::
>>> node_a, node_b = astroid.extract_node("""
... def test():
... if True:
... return 5 #@
... return 5 #@
""")
>>> node_a.value
<Const.int l.4 at 0x7efe621a74e0>
>>> node_a.value.value
5
>>> node_a.value.value == node_b.value.value
True
For :func:`astroid.extract_node`, you can use ``#@`` at the end of a line to choose which statements will be extracted into nodes.
For more information on :func:`astroid.extract_node`,
see the `astroid documentation <http://astroid.readthedocs.io/en/latest/>`_.
Now we know how to use the astroid node, we can implement our check.
.. code-block:: python
def visit_return(self, node):
if not isinstance(node.value, astroid.node_classes.Const):
return
for other_return in self._function_stack[-1]:
if (node.value.value == other_return.value.value and
not (self.config.ignore_ints and node.value.pytype() == int)):
self.add_message(
'non-unique-returns', node=node,
)
self._function_stack[-1].append(node)
Once we have established that the source code has failed our check,
we use :func:`~.BaseChecker.add_message` to emit our failure message.
Finally, we need to register the checker with pylint.
Add the ``register`` function to the top level of the file.
.. code-block:: python
def register(linter):
linter.register_checker(UniqueReturnChecker(linter))
We are now ready to debug and test our checker!
Debugging a Checker
-------------------
It is very simple to get to a point where we can use :mod:`pdb`.
We'll need a small test case.
Put the following into a Python file:
.. code-block:: python
def test():
if True:
return 5
return 5
def test2():
if True:
return 1
return 5
After inserting pdb into our checker and installing it,
we can run pylint with only our checker::
$ pylint --load-plugins=my_plugin --disable=all --enable=non-unique-returns test.py
(Pdb)
Now we can debug our checker!
.. Note::
``my_plugin`` refers to a module called ``my_plugin.py``.
This module can be made available to pylint by putting this
module's parent directory in your ``PYTHONPATH``
environment variable or by adding the ``my_plugin.py``
file to the ``pylint/checkers`` directory if running from source.
Testing a Checker
-----------------
Pylint is very well suited to test driven development.
You can implement the template of the checker,
produce all of your test cases and check that they fail,
implement the checker,
then check that all of your test cases work.
Pylint provides a :class:`pylint.testutils.CheckerTestCase`
to make test cases very simple.
We can use the example code that we used for debugging as our test cases.
.. code-block:: python
import my_plugin
import pylint.testutils
class TestUniqueReturnChecker(pylint.testutils.CheckerTestCase):
CHECKER_CLASS = my_plugin.UniqueReturnChecker
def test_finds_non_unique_ints(self):
func_node, return_node_a, return_node_b = astroid.extract_node("""
def test(): #@
if True:
return 5 #@
return 5 #@
""")
self.checker.visit_functiondef(func_node)
self.checker.visit_return(return_node_a)
with self.assertAddsMessages(
pylint.testutils.Message(
msg_id='non-unique-returns',
node=return_node_b,
),
):
self.checker.visit_return(return_node_b)
def test_ignores_unique_ints(self):
func_node, return_node_a, return_node_b = astroid.extract_node("""
def test(): #@
if True:
return 1 #@
return 5 #@
""")
with self.assertNoMessages():
self.checker.visit_functiondef(func_node)
self.checker.visit_return(return_node_a)
self.checker.visit_return(return_node_b)
Once again we are using :func:`astroid.extract_node` to
construct our test cases.
:class:`pylint.testutils.CheckerTestCase` has created the linter and checker for us,
we simply simulate a traversal of the AST tree
using the nodes that we are interested in.
Reference Guide
===============
How To Guides
=============
 
.. toctree::
:maxdepth: 2
:titlesonly:
 
custom_checkers
plugins
extensions
features
\ No newline at end of file
transform_plugins
.. -*- coding: utf-8 -*-
================
Extending Pylint
================
Pylint provides support for writing two types of extensions. First, there
is the concept of **checkers**, which can be used for finding problems in your
code. Secondly, there is also the concept of **transform plugin**, which represents a
way through which the inference and the capabilities of Pylint can be enhanced
How To Write a Pylint Plugin
============================
Pylint provides support for writing two types of extensions.
First, there is the concept of **checkers**,
which can be used for finding problems in your code.
Secondly, there is also the concept of **transform plugin**,
which represents a way through which the inference and
the capabilities of Pylint can be enhanced
and tailored to a particular module, library of framework.
In general, a plugin is a module which should have a function ``register``,
Loading
Loading
@@ -36,10 +37,4 @@ object, by calling the following inside the ``register`` function::
linter.register_checker(OurChecker(linter))
.. toctree::
:maxdepth: 2
:titlesonly:
custom_checkers
transform_plugins
For more information on writing a checker see :ref:`write_a_checker`.
Loading
Loading
@@ -103,4 +103,7 @@ Lets run Pylint with this plugin and see:
All the false positives associated with ``WarningMessage`` are now gone. This is just
an example, any code transformation can be done by plugins.
 
See `astroid/brain`_ for real life examples of transform plugins.
.. _`warnings.py`: http://hg.python.org/cpython/file/2.7/Lib/warnings.py
.. _`astroid/brain`: https://github.com/PyCQA/astroid/tree/master/astroid/brain
Loading
Loading
@@ -10,7 +10,8 @@ Pylint User Manual
tutorial
 
user_guide/index.rst
reference_guide/index.rst
how_tos/index.rst
technical_reference/index.rst
development_guide/index.rst
 
faq
Loading
Loading
Custom checkers
^^^^^^^^^^^^^^^
Writing your own checker
------------------------
You can find some simple examples in the examples
directory of the distribution (custom.py and custom_raw.py).
First, there are two kinds of checkers:
* raw checkers, which are analysing each module as a raw file stream
* AST checkers, which are working on an AST representation of the module
The AST representation used is an extension of the one provided with the
standard Python distribution in the `ast package`_. The extension
adds additional information and methods on the tree nodes to ease
navigation and code introspection.
An AST checker is a visitor, and should implement
`visit_<lowered class name>` or `leave_<lowered class name>`
methods for the nodes it's interested in. To get description of the different
classes used in an ast tree, look at the `ast package`_ documentation.
For each module, Pylint's engine is doing the following:
1. give the module source file as a stream to raw checkers
2. get an AST representation for the module
3. make a depth first descent of the tree, calling ``visit_<>`` on each AST
checker when entering a node, and ``leave_<>`` on the back traversal
A checker is composed from multiple components, which needs to be given
in order for it to work properly:
1. a name. The name is internally for a couple of things, one of them
being used for generating a special configuration
section of the checker, in case in has provided options.
2. a priority that needs to be lower than 0. The checkers are ordered by
the priority, from the most negative to the most positive.
3. a message dictionary. Each checker is being used for finding problems
in your code, the problems being displayed to the user through **messages**.
The message dictionary should specify what messages the said checker is
going to emit. It has the following format::
msgs = {'message-id': ('displayed-message', 'message-symbol', 'message-help')}
The ``message id`` should be a 5-digits number, prefixed with a **message category**.
There are multiple message categories, these being ``C``, ``W``, ``E``, ``F``, ``R``,
standing for ``Convention``, ``Warning``, ``Error``, ``Fatal`` and ``Refactoring``.
The rest of the 5 digits should not conflict with existing checkers and they should
be consistent across the checker. For instance, the first two digits should not be
different across the checker.
The displayed message is used for displaying the message to the user, once it is emitted.
The message symbol is an alias of the message id and it can be used wherever the message id
can be used. The message help is used when calling ``pylint --help-msg``.
4. An options list (optional)
.. _`ast package`: http://docs.python.org/2/library/ast
Loading
Loading
@@ -57,9 +57,10 @@ Pre-release
https://github.com/PyCQA/pylint
 
 
Release by running:
Release by running the following:
$ git clean -fd && find . -name '*.pyc' -delete
$ python setup.py sdist --formats=gztar bdist_wheel
$ twine upload dist/*
$ python setup.py register sdist --formats=gztar bdist_wheel upload
to release a new version to PyPI.
Checkers
--------
All of the default pylint checkers exist in ``pylint.checkers``.
This is where most of pylint's brains exist.
Most checkers are AST based and so use :mod:`astroid`.
``pylint.checkers.utils`` provides a large number of utility methods for
dealing with :mod:`astroid`.
.. _technical-reference:
Technical Reference
===================
.. TODO Configuration
.. TODO Messages
.. TODO Reports
.. toctree::
:maxdepth: 2
:titlesonly:
startup
checkers
extensions
features
Startup and the Linter Class
----------------------------
The two main classes in :mod:`pylint.lint` are
:class:`.pylint.lint.Run` and :class:`.pylint.lint.PyLinter`.
The :class:`.pylint.lint.Run` object is responsible for starting up pylint.
It does some basic checking of the given command line options to
find the initial hook to run,
find the config file to use,
and find which plugins have been specified.
It can then create the master :class:`.pylint.lint.PyLinter` instance
and initialise it with the config file and plugins that were discovered
when preprocessing the command line options.
Finally the :class:`.pylint.lint.Run` object launches any child linters
for parallel jobs, and starts the linting process.
The :class:`.pylint.lint.PyLinter` is responsible for coordinating the
linting process.
It parses the configuration and provides it for the checkers and other plugins,
it handles the messages emitted by the checkers,
it handles the output reporting,
and it launches the checkers.
.. _ide-integration:
 
###########################
Editor and IDE integration
Loading
Loading