summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAshley Whetter <AWhetter@users.noreply.github.com>2017-07-12 05:45:16 +0100
committerGitHub <noreply@github.com>2017-07-12 05:45:16 +0100
commit9f7797ae15bd5e4e5c4ad320afcc15eeb4cdae82 (patch)
treea3316d20d3be3ce78f0aed8b1e39ade7f75176bc
parent6794b421d0004c593748df850083914049f11a98 (diff)
downloadpylint-git-9f7797ae15bd5e4e5c4ad320afcc15eeb4cdae82.tar.gz
Expanded documentation for new contributors (#1569)
-rw-r--r--.gitignore4
-rw-r--r--doc/conf.py16
-rw-r--r--doc/development_guide/contribute.rst43
-rwxr-xr-xdoc/exts/pylint_extensions.py2
-rwxr-xr-xdoc/exts/pylint_features.py2
-rw-r--r--doc/how_tos/custom_checkers.rst284
-rw-r--r--doc/how_tos/index.rst10
-rw-r--r--doc/how_tos/plugins.rst (renamed from doc/reference_guide/plugins.rst)25
-rw-r--r--doc/how_tos/transform_plugins.rst (renamed from doc/reference_guide/transform_plugins.rst)0
-rw-r--r--doc/index.rst3
-rw-r--r--doc/reference_guide/custom_checkers.rst61
-rw-r--r--doc/reference_guide/index.rst11
-rw-r--r--doc/technical_reference/checkers.rst7
-rw-r--r--doc/technical_reference/index.rst19
-rw-r--r--doc/technical_reference/startup.rst22
-rw-r--r--doc/whatsnew/index.rst1
-rw-r--r--examples/custom.py56
17 files changed, 456 insertions, 110 deletions
diff --git a/.gitignore b/.gitignore
index 9d9ec161c..8170446b5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/doc/conf.py b/doc/conf.py
index ce9aa94ef..7e21fd473 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -25,9 +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',
- 'sphinx.ext.autosectionlabel']
+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']
@@ -43,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
@@ -216,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),
+}
diff --git a/doc/development_guide/contribute.rst b/doc/development_guide/contribute.rst
index 924979900..e367a42de 100644
--- a/doc/development_guide/contribute.rst
+++ b/doc/development_guide/contribute.rst
@@ -39,6 +39,8 @@ Archives before April 2013 are available at
http://lists.logilab.org/pipermail/python-projects/
+.. _repository:
+
Repository
----------
@@ -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
@@ -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`_.
diff --git a/doc/exts/pylint_extensions.py b/doc/exts/pylint_extensions.py
index a371cd275..eeb8d6026 100755
--- a/doc/exts/pylint_extensions.py
+++ b/doc/exts/pylint_extensions.py
@@ -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")
diff --git a/doc/exts/pylint_features.py b/doc/exts/pylint_features.py
index 5322c27cb..fcb2d10e1 100755
--- a/doc/exts/pylint_features.py
+++ b/doc/exts/pylint_features.py
@@ -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")
diff --git a/doc/how_tos/custom_checkers.rst b/doc/how_tos/custom_checkers.rst
new file mode 100644
index 000000000..abafb91fa
--- /dev/null
+++ b/doc/how_tos/custom_checkers.rst
@@ -0,0 +1,284 @@
+.. _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 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!
+
+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.
diff --git a/doc/how_tos/index.rst b/doc/how_tos/index.rst
new file mode 100644
index 000000000..7ec3a2f36
--- /dev/null
+++ b/doc/how_tos/index.rst
@@ -0,0 +1,10 @@
+How To Guides
+=============
+
+.. toctree::
+ :maxdepth: 2
+ :titlesonly:
+
+ custom_checkers
+ plugins
+ transform_plugins
diff --git a/doc/reference_guide/plugins.rst b/doc/how_tos/plugins.rst
index 21926dbdb..abbf2bdcb 100644
--- a/doc/reference_guide/plugins.rst
+++ b/doc/how_tos/plugins.rst
@@ -1,13 +1,14 @@
.. -*- 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``,
@@ -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 _`write_a_checker`.
diff --git a/doc/reference_guide/transform_plugins.rst b/doc/how_tos/transform_plugins.rst
index 39db6c2b1..39db6c2b1 100644
--- a/doc/reference_guide/transform_plugins.rst
+++ b/doc/how_tos/transform_plugins.rst
diff --git a/doc/index.rst b/doc/index.rst
index c27f062f5..57e194eef 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -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
diff --git a/doc/reference_guide/custom_checkers.rst b/doc/reference_guide/custom_checkers.rst
deleted file mode 100644
index 800006b0f..000000000
--- a/doc/reference_guide/custom_checkers.rst
+++ /dev/null
@@ -1,61 +0,0 @@
-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
diff --git a/doc/reference_guide/index.rst b/doc/reference_guide/index.rst
deleted file mode 100644
index d17868992..000000000
--- a/doc/reference_guide/index.rst
+++ /dev/null
@@ -1,11 +0,0 @@
-
-Reference Guide
-===============
-
-.. toctree::
- :maxdepth: 2
- :titlesonly:
-
- plugins
- extensions
- features \ No newline at end of file
diff --git a/doc/technical_reference/checkers.rst b/doc/technical_reference/checkers.rst
new file mode 100644
index 000000000..d59e316c6
--- /dev/null
+++ b/doc/technical_reference/checkers.rst
@@ -0,0 +1,7 @@
+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`.
diff --git a/doc/technical_reference/index.rst b/doc/technical_reference/index.rst
new file mode 100644
index 000000000..5e603f90d
--- /dev/null
+++ b/doc/technical_reference/index.rst
@@ -0,0 +1,19 @@
+.. _technical-reference:
+
+Technical Reference
+===================
+
+.. TODO Configuration
+
+.. TODO Messages
+
+.. TODO Reports
+
+.. toctree::
+ :maxdepth: 2
+ :titlesonly:
+
+ startup
+ checkers
+ extensions
+ features
diff --git a/doc/technical_reference/startup.rst b/doc/technical_reference/startup.rst
new file mode 100644
index 000000000..5a2063d4a
--- /dev/null
+++ b/doc/technical_reference/startup.rst
@@ -0,0 +1,22 @@
+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.
diff --git a/doc/whatsnew/index.rst b/doc/whatsnew/index.rst
index 17f395ebc..8c8bb0ac2 100644
--- a/doc/whatsnew/index.rst
+++ b/doc/whatsnew/index.rst
@@ -9,6 +9,7 @@ High level descriptions of the most important changes between major Pylint versi
.. toctree::
:maxdepth: 1
+ 1.8.rst
1.7.rst
1.6.rst
diff --git a/examples/custom.py b/examples/custom.py
index ee4ed65cf..54c2937b1 100644
--- a/examples/custom.py
+++ b/examples/custom.py
@@ -3,38 +3,68 @@ import astroid
from pylint.interfaces import IAstroidChecker
from pylint.checkers import BaseChecker
+
+# This is our checker class.
+# Checkers should always inherit from `BaseChecker`.
class MyAstroidChecker(BaseChecker):
- """add member attributes defined using my own "properties" function
- to the class locals dictionary
- """
-
+ """Add class member attributes to the class locals dictionary."""
+
+ # This class variable defines the type of checker that we are implementing.
+ # In this case, we are implementing an AST checker.
__implements__ = IAstroidChecker
+ # The name defines a custom section of the config for this checker.
name = 'custom'
+ # The priority indicates the order that pylint will run the checkers.
+ priority = -1
+ # This class variable declares the messages (ie the warnings and errors)
+ # that the checker can emit.
msgs = {
+ # Each message has a code, a message that the user will see,
+ # a unique symbol that identifies the message,
+ # and a detailed help message
+ # that will be included in the documentation.
'W0001': ('Message that will be emitted',
'message-symbol',
'Message help')
}
- options = ()
- # this is important so that your checker is executed before others
- priority = -1
+ # This class variable declares the options
+ # that are configurable by the user.
+ options = (
+ # Each option definition has a name which is used on the command line
+ # and in config files, and a dictionary of arguments
+ # (similar to those to those to
+ # argparse.ArgumentParser.add_argument).
+ ('store-locals-indicator',
+ {'default': 'properties',
+ 'help': ('The expression name that indicates that the locals should '
+ 'be stored'),
+ },
+ ),
+ )
def visit_call(self, node):
- """called when a Call node is encountered.
+ """Called when a :class:`.astroid.node_classes.Call` node is visited.
+
+ See :mod:`astroid` for the description of available nodes.
- See astroid for the description of available nodes."""
+ :param node: The node to check.
+ :type node: astroid.node_classes.Call
+ """
if not (isinstance(node.func, astroid.Attribute)
and isinstance(node.func.expr, astroid.Name)
- and node.func.expr.name == 'properties'
+ and node.func.expr.name == self.config.store_locals_indicator
and node.func.attrname == 'create'):
return
in_class = node.frame()
for param in node.args:
in_class.locals[param.name] = node
-
+
def register(linter):
- """required method to auto register this checker"""
+ """This required method auto registers the checker.
+
+ :param linter: The linter to register the checker to.
+ :type linter: pylint.lint.PyLinter
+ """
linter.register_checker(MyAstroidChecker(linter))
-