summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorDan Goldsmith <djgoldsmith@googlemail.com>2014-04-11 16:22:29 +0100
committerDan Goldsmith <djgoldsmith@googlemail.com>2014-04-11 16:22:29 +0100
commitfe36ec0486cfc9aba10d8d87b0f42077ad1e78db (patch)
tree046fbf0baf2ae392120ed930aeafe63a6df83cb2 /doc
parent3804162e9a3f0e320867ffb45e09a43f9d0156c2 (diff)
parent3965c47e53a1c06c709048d932fe01dcf947c032 (diff)
downloadpylint-fe36ec0486cfc9aba10d8d87b0f42077ad1e78db.tar.gz
Merge with trunk
Diffstat (limited to 'doc')
-rw-r--r--doc/faq.rst27
-rw-r--r--doc/index.rst8
-rw-r--r--doc/options.rst139
-rw-r--r--doc/plugins.rst122
-rw-r--r--doc/run.rst9
5 files changed, 284 insertions, 21 deletions
diff --git a/doc/faq.rst b/doc/faq.rst
index ce5102d..e3cd73e 100644
--- a/doc/faq.rst
+++ b/doc/faq.rst
@@ -123,7 +123,7 @@ the rc file
For example::
- pylint --disable=W0702,C0103 --class-rgx='[A-Z][a-z]+' --generate-rcfile
+ pylint --disable=bare-except,invalid-name --class-rgx='[A-Z][a-z]+' --generate-rcfile
3.4 I'd rather not run Pylint from the command line. Can I integrate it with my editor?
---------------------------------------------------------------------------------------
@@ -137,7 +137,7 @@ Much probably. Read http://docs.pylint.org/ide-integration
-----------------------------------------------------------
Yes, this feature has been added in Pylint 0.11. This may be done by
-adding "#pylint: disable=W0123,E4567" at the desired block level
+adding "#pylint: disable=some-message,another-one" at the desired block level
or at the end of the desired line of code
4.2 Is there a way to disable a message for a particular module only?
@@ -147,8 +147,8 @@ Yes, you can disable or enable (globally disabled) messages at the
module level by adding the corresponding option in a comment at the
top of the file: ::
- # pylint: disable=W0401, E0202
- # pylint: enable=C0302
+ # pylint: disable=wildcard-import, method-hidden
+ # pylint: enable=too-many-lines
4.3 How can I tell Pylint to never check a given module?
--------------------------------------------------------
@@ -158,9 +158,9 @@ module. Pylint 0.26.1 and up have renamed that directive to
"#pylint: skip-file" (but the first version will be kept for backward
compatibility).
-In order to ease finding which modules are ignored a Information-level
-message I0013 is emited. With recent versions of Pylint, if you use
-the old syntax, an additional I0014 message is emited.
+In order to ease finding which modules are ignored a Information-level message
+`file-ignored` is emited. With recent versions of Pylint, if you use the old
+syntax, an additional `deprecated-disable-all` message is emited.
4.4 Do I have to remember all these numbers?
--------------------------------------------
@@ -182,12 +182,15 @@ variable for unused argument ("_" and "dummy" by default).
4.6 What is the format of the configuration file?
---------------------------------------------------
-Pylint uses ConfigParser from the standard library to parse the configuration file.
-It means that if you need to disable a lot of messages, you can use tricks like: ::
+Pylint uses ConfigParser from the standard library to parse the configuration
+file. It means that if you need to disable a lot of messages, you can use
+tricks like: ::
- disable= W0401, # because I do not want it
- E0202, # I have a good reason, trust me
- C0302 # that's it
+ # disable wildcard-import, method-hidden and too-many-lines because I do
+ # not want it
+ disable= wildcard-import,
+ method-hidden,
+ too-many-lines
4.7 Why do I get a lot of spurious "unused variables messages" when using psyobj from psyco_?
----------------------------------------------------------------------------------------------
diff --git a/doc/index.rst b/doc/index.rst
index 790ff93..7b8725c 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -13,8 +13,10 @@ https://bitbucket.org/logilab/pylint
output
message-control
features
+ options
extend
ide-integration
+ plugins
contribute
tutorial
@@ -29,12 +31,6 @@ Content wanted
It would be nice to include in the documentation the following information:
-- pylint plugins (how to write one, how to install a 3rd party plugin, how to
- configure Pylint to run it)
-
- pylint brain project : what it is, how to install it...
Please send your pull requests via bitbucket if you can help with the above.
-
-
-
diff --git a/doc/options.rst b/doc/options.rst
new file mode 100644
index 0000000..4a159f2
--- /dev/null
+++ b/doc/options.rst
@@ -0,0 +1,139 @@
+.. -*- coding: utf-8 -*-
+
+===============
+ Configuration
+===============
+
+Naming Styles
+-------------
+
+PyLint recognizes a number of different name types internally. With a few
+exceptions, the type of the name is governed by the location the assignment to a
+name is found in, and not the type of object assigned.
+
+``module``
+ Module and package names, same as the file names.
+``const``
+ Module-level constants, any variable defined at module level that is not bound to a class object.
+``class``
+ Names in ``class`` statements, as well as names bound to class objects at module level.
+``function``
+ Functions, toplevel or nested in functions or methods.
+``method``
+ Methods, functions defined in class bodies. Includes static and class methods.
+``attr``
+ Attributes created on class instances inside methods.
+``argument``
+ Arguments to any function type, including lambdas.
+``variable``
+ Local variables in function scopes.
+``class-attribute``
+ Attributes defined in class bodies.
+``inlinevar``
+ Loop variables in list comprehensions and generator expressions.
+
+For each naming style, a separate regular expression matching valid names of
+this type can be defined. By default, the regular expressions will enforce PEP8
+names.
+
+Regular expressions for the names are anchored at the beginning, any anchor for
+the end must be supplied explicitly. Any name not matching the regular
+expression will lead to an instance of ``invalid-name``.
+
+
+.. option:: --module-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --const-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --class-rgx=<regex>
+
+ Default value: ``'[A-Z_][a-zA-Z0-9]+$``
+
+.. option:: --function-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --method-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --attr-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --argument-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --variable-rgx=<regex>
+
+ Default value: ``[a-z_][a-z0-9_]{2,30}$``
+
+.. option:: --class-attribute-rgx=<regex>
+
+ Default value: ``([A-Za-z_][A-Za-z0-9_]{2,30}|(__.*__))$``
+
+.. option:: --inlinevar-rgx=<regex>
+
+ Default value: ``[A-Za-z_][A-Za-z0-9_]*$``
+
+Multiple Naming Styles
+^^^^^^^^^^^^^^^^^^^^^^
+
+Large code bases that have been worked on for multiple years often exhibit an
+evolution in style as well. In some cases, modules can be in the same package,
+but still have different naming style based on the stratum they belong to.
+However, intra-module consistency should still be required, to make changes
+inside a single file easier. For this case, PyLint supports regular expression
+with several named capturing group.
+
+The capturing group of the first valid match taints the module and enforces the
+same group to be triggered on every subsequent occurrence of this name.
+
+Consider the following (simplified) example::
+
+ pylint --function-rgx='(?:(?P<snake>[a-z_]+)|(?P<camel>_?[A-Z]+))$' sample.py
+
+The regular expression defines two naming styles, ``snake`` for snake-case
+names, and ``camel`` for camel-case names.
+
+In ``sample.py``, the function name on line 1 will taint the module and enforce
+the match of named group ``snake`` for the remainder of the module::
+
+ def trigger_snake_case(arg):
+ ...
+
+ def InvalidCamelCase(arg):
+ ...
+
+ def valid_snake_case(arg):
+ ...
+
+Because of this, the name on line 4 will trigger an ``invalid-name`` warning,
+even though the name matches the given regex.
+
+Matches named ``exempt`` or ``ignore`` can be used for non-tainting names, to
+prevent built-in or interface-dictated names to trigger certain naming styles.
+
+.. option:: --name-group=<name1:name2:...,...>
+
+ Default value: empty
+
+ Format: comma-separated groups of colon-separated names.
+
+ This option can be used to combine name styles. For example, ``function:method`` enforces that functions and methods use the same style, and a style triggered by either name type carries over to the other. This requires that the regular expression for the combined name types use the same group names.
+
+Name Hints
+^^^^^^^^^^
+
+.. option:: --include-naming-hint=y|n
+
+ Default: off
+
+ Include a hint for the correct name format with every ``invalid-name`` warning.
+
+ Name hints default to the regular expression, but can be separately configured with the ``--<name-type>-hint`` options.
diff --git a/doc/plugins.rst b/doc/plugins.rst
new file mode 100644
index 0000000..052c13f
--- /dev/null
+++ b/doc/plugins.rst
@@ -0,0 +1,122 @@
+.. -*- coding: utf-8 -*-
+
+=======
+Plugins
+=======
+
+Why write a plugin?
+-------------------
+
+Pylint is a static analysis tool and Python is a dynamically typed language.
+So there will be cases where Pylint cannot analyze files properly (this problem
+can happen in statically typed languages also if reflection or dynamic
+evaluation is used). Plugin is a way to tell Pylint how to handle such cases,
+since only the user would know what needs to be done.
+
+Example
+-------
+
+Let us run Pylint on a module from the Python source: `warnings.py`_ and see what happens:
+
+.. sourcecode:: bash
+
+ amitdev$ pylint -E Lib/warnings.py
+ E:297,36: Instance of 'WarningMessage' has no 'message' member (no-member)
+ E:298,36: Instance of 'WarningMessage' has no 'filename' member (no-member)
+ E:298,51: Instance of 'WarningMessage' has no 'lineno' member (no-member)
+ E:298,64: Instance of 'WarningMessage' has no 'line' member (no-member)
+
+
+Did we catch a genuine error? Let's open the code and look at ``WarningMessage`` class:
+
+.. sourcecode:: python
+
+ class WarningMessage(object):
+
+ """Holds the result of a single showwarning() call."""
+
+ _WARNING_DETAILS = ("message", "category", "filename", "lineno", "file",
+ "line")
+
+ def __init__(self, message, category, filename, lineno, file=None,
+ line=None):
+ local_values = locals()
+ for attr in self._WARNING_DETAILS:
+ setattr(self, attr, local_values[attr])
+ self._category_name = category.__name__ if category else None
+
+ def __str__(self):
+ ...
+
+Ah, the fields (``message``, ``category`` etc) are not defined statically on the class.
+Instead they are added using ``setattr``. Pylint would have a tough time figuring
+this out.
+
+Enter Plugin
+------------
+
+We can write a plugin to tell Pylint about how to analyze this properly. A
+plugin is a module which should have a function ``register`` and takes the
+`lint`_ module as input. So a basic hello-world plugin can be implemented as:
+
+.. sourcecode:: python
+
+ # Inside hello_plugin.py
+ def register(linter):
+ print 'Hello world'
+
+We can run this plugin by placing this module in the PYTHONPATH and invoking as:
+
+.. sourcecode:: bash
+
+ amitdev$ pylint -E --load-plugins hello_plugin foo.py
+ Hello world
+
+Back to our example: one way to fix that would be to transform the ``WarningMessage`` class
+and set the attributes using a plugin so that Pylint can see them. This can be done by
+registering a transform function. We can transform any node in the parsed AST like
+Module, Class, Function etc. In our case we need to transform a class. It can be done so:
+
+.. sourcecode:: python
+
+ from astroid import MANAGER
+ from astroid import scoped_nodes
+
+ def register(linter):
+ pass
+
+ def transform(cls):
+ if cls.name == 'WarningMessage':
+ import warnings
+ for f in warnings.WarningMessage._WARNING_DETAILS:
+ cls.locals[f] = [scoped_nodes.Class(f, None)]
+
+ MANAGER.register_transform(scoped_nodes.Class, transform)
+
+Let's go through the plugin. First, we need to register a class transform, which
+is done via the ``register_transform`` function in ``MANAGER``. It takes the node
+type and function as parameters. We need to change a class, so we use ``scoped_nodes.Class``.
+We also pass a ``transform`` function which does the actual transformation.
+
+``transform`` function is simple as well. If the class is ``WarningMessage`` then we
+add the attributes to its locals (we are not bothered about type of attributes, so setting
+them as class will do. But we could set them to any type we want). That's it.
+
+Note: We don't need to do anything in the ``register`` function of the plugin since we
+are not modifying anything in the linter itself.
+
+Lets run Pylint with this plugin and see:
+
+.. sourcecode:: bash
+
+ amitdev$ pylint -E --load-plugins warning_plugin Lib/warnings.py
+ amitdev$
+
+All the false positives associated with ``WarningMessage`` are now gone. This is just
+an example, any code transformation can be done by plugins. See `nodes`_ and `scoped_nodes`_
+for details about all node types that can be transformed.
+
+.. _`warnings.py`: http://hg.python.org/cpython/file/2.7/Lib/warnings.py
+.. _`scoped_nodes`: https://bitbucket.org/logilab/astroid/src/64026ffc0d94fe09e4bdc2bf5efaab29444645e7/scoped_nodes.py?at=default
+.. _`nodes`: https://bitbucket.org/logilab/astroid/src/64026ffc0d94fe09e4bdc2bf5efaab29444645e7/nodes.py?at=default
+.. _`lint`: https://bitbucket.org/logilab/pylint/src/f2acea7b640def0237513f66e3de5fa3de73f2de/lint.py?at=default \ No newline at end of file
diff --git a/doc/run.rst b/doc/run.rst
index 1fb95cd..4e752b0 100644
--- a/doc/run.rst
+++ b/doc/run.rst
@@ -99,9 +99,12 @@ configuration file in the following order and uses the first one it finds:
basis. Of course, a directory is judged to be a Python module if it \
contains an ``__init__.py`` file.
#. The file named by environment variable ``PYLINTRC``
-#. ``.pylintrc`` in your home directory, unless you have no home directory or \
- your home directory is ``/root``
-#. ``.pylintrc`` in the current working directory
+#. if you have a home directory which isn't ``/root``:
+
+ #. ``.pylintrc`` in your home directory
+ #. ``.config/pylintrc`` in your home directory
+
+ else, ``.pylintrc`` in the current working directory
#. ``/etc/pylintrc``
The ``--generate-rcfile`` option will generate a commented configuration file