summaryrefslogtreecommitdiff
path: root/doc/manual.txt
blob: baa28d38167e7e4e8b172dbbcbe407606fcba4d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
==================
Pylint User Manual
==================

:Author: Sylvain Thénault
:Author: Alexandre Fayolle
:Organization: Logilab

.. contents::


This document is meant to be the reference user manual for Pylint_.  This is a
work in progress so some sections or parts may be missing (sometimes marked by a
XXX).  If you think it's lacking some important information, please talk about
it on the python-projects mailing list (see the `Mailing lists`_ section for
more information about the list).

.. _Pylint: http://www.pylint.org


Introduction
============

What is pylint?
---------------

Pylint is a tool that checks for errors in python code, tries to enforce a
coding standard and looks for smelling code. This is similar but nevertheless
different from what pychecker_ provides, especially since pychecker explicitly
does not bother with coding style. The default coding style used by Pylint is
close to `PEP 008`_ (aka `Guido's style guide`_). For more information about
code smells, refer to Martin Fowler's `refactoring book`_

One important thing to note is that Pylint isn't smarter than you are: it may
warn you about things that you have conscientiously done. That's for example
because it tries to detect things that may be dangerous in a context, but maybe
not in others, or because it checks for some things that you don't care
about. Generally, you shouldn't expect Pylint to be totally quiet about your
code, so don't necessarily be alarmed if it gives you a hell lot of messages for
your proudly(XXX) project ;)

Pylint will display a number of messages as it analyzes the code, as well as
some statistics about the number of warnings and errors found in different
files. The messages are classified under various categories such as errors and
warnings (more below). If you run pylint twice, it will display the statistics
from the previous run together with the ones from the current run, so that you
can see if the code has improved or not.

Last but not least, the code is given an overall mark, based on the number an
severity of the warnings and errors. This has proven to be very motivating for
programmers.

.. _pychecker: http://pychecker.sf.net
.. _`PEP 008`: http://www.python.org/dev/peps/pep-0008/
.. _`Guido's style guide`: http://www.python.org/doc/essays/styleguide.html
.. _`refactoring book`: http://www.refactoring.com/

Installation
------------

Dependencies
''''''''''''
Pylint requires the latest `logilab-astng`_ and `logilab-common`_
packages. It should be compatible with any python version >= 2.5.

.. _`logilab-astng`: http://www.logilab.org/project/name/astng
.. _`logilab-common`: http://www.logilab.org/project/name/common


Distributions
'''''''''''''
The source tarball is available at http://download.logilab.org/pub/pylint.

You may apt-get a well-tested Debian or Ubuntu package by adding one of::

    deb http://download.logilab.org/production unstable/
    deb http://download.logilab.org/production sid/
    deb http://download.logilab.org/production squeeze/
    deb http://download.logilab.org/production lenny/

to your */etc/apt/sources.list* file. Pylint is also available in the
standard Debian distribution (but add our public Debian repository
anyway if you want to get the latest releases and upgrades earlier)

Pylint is also available in Gentoo, Fedora 4, Ubuntu, FreeBSD, Darwin
(and maybe others, if you know about more OSes, please drop us a note!).


Source distribution installation
''''''''''''''''''''''''''''''''
From the source distribution, extract the tarball, go to the extracted
directory and simply run ::

    python setup.py install

You'll have to install dependencies in a similar way.

Windows users may get valuable information about Pylint installation on
`this page`_.

.. _`this page`: http://thinkhole.org/wp/2006/01/16/installing-pylint-on-windows/


Note for Windows users
''''''''''''''''''''''

On Windows, once you have installed Pylint, the command line usage is ::

  pylint.bat [options] module_or_package

But this will only work if *pylint.bat* is either in the current
directory, or on your system path. (*setup.py* install install *python.bat*
to the *Scripts* subdirectory of your Python installation -- e.g.
C:\Python24\Scripts.) You can do any of the following to solve this:

1. change to the appropriate directory before running pylint.bat

2. add the Scripts directory to your path statement in your autoexec.bat
   file (this file is found in the root directory of your boot-drive)

3. create a 'redirect' batch file in a directory actually on your
   systems path

To effect (2), simply append the appropriate directory name to the PATH=
statement in autoexec.bat. Be sure to use the Windows directory
separator of ';' between entries. Then, once you have rebooted (this is
necessary so that the new path statement will take effect when
autoexec.bat is run), you will be able to invoke Pylint with
pylint.bat on the command line.

(3) is the best solution. Once done, you can call pylint at the command
line without the .bat, just as do non-Windows users by typing: ::

  pylint [options] module_or_package

To effect option (3), simply create a plain text file pylint.bat with
the single line: ::

  C:\PythonDirectory\Scripts\pylint.bat

(where PythonDirectory is replaced by the actual Python installation
directory on your system -- e.g. C:\Python24\Scripts\pylint.bat).


Invoking pylint
---------------

Pylint is meant to be called from the command line. The usage is ::

   pylint [options] module_or_package

You should give pylint the name of a Python package or module. Pylint
will ``import`` this package or module, so you should pay attention to
your ``PYTHONPATH``, since it is a common error to analyze an
installed version of a module instead of the development version.

It is also possible to analyze python files, with a few
restriction. The thing to keep in mind is that Pylint will try to
convert the file name to a module name, and only be able to process
the file if it succeeds.  ::

  pylint mymodule.py

should always work since the current working
directory is automatically added on top of the python path ::

  pylint directory/mymodule.py

will work if "directory" is a python package (i.e. has an __init__.py
file) or if "directory" is in the python path.

For more details on this see the Frequently Asked Questions.

You can also start a thin gui around Pylint (require TkInter) by
typing ::

  pylint-gui

This should open a window where you can enter the name of the package
or module to check, at Pylint messages will be displayed in the user
interface.

It is also possible to call Pylint from an other Python program,
thanks to ``py_run()`` function in ``lint`` module,
assuming Pylint options are stored in ``pylint_options`` string, as ::

  from pylint import epylint as lint
  lint.py_run( pylint_options)

To silently run Pylint on a ``module_name.py`` module,
and get its standart output and error::

  from pylint import epylint as lint
  (pylint_stdout, pylint_stderr) = lint.py_run( 'module_name.py', True)


Pylint output
-------------

The default format for the output is raw text. But passing pylint the
``--output-format=html`` or ``-f html`` option will produce an HTML document.

There are several sections in Pylint's output.

Source code analysis section
''''''''''''''''''''''''''''
For each python module,
Pylint will first display a few '*' characters followed by the name
of the module. Then, a number of messages with the following
format: ::

  MESSAGE_TYPE: LINE_NUM:[OBJECT:] MESSAGE

You can get another output format, useful since it's recognized by
most editors or other development tools using the ``--output-format=parseable``
option.

The message type can be:

  * [R]efactor for a "good practice" metric violation
  * [C]onvention for coding standard violation
  * [W]arning for stylistic problems, or minor programming issues
  * [E]rror for important programming issues (i.e. most probably bug)
  * [F]atal for errors which prevented further processing

Sometimes the line of code which caused the error is displayed with
a caret pointing to the error. This may be generalized in future
versions of Pylint.

Example (extracted from a run of Pylint on itself...):

::

  ************* Module pylint.checkers.format
  W: 50: Too long line (86/80)
  W:108: Operator not followed by a space
       print >>sys.stderr, 'Unable to match %r', line
              ^
  W:141: Too long line (81/80)
  W: 74:searchall: Unreachable code
  W:171:FormatChecker.process_tokens: Redefining built-in (type)
  W:150:FormatChecker.process_tokens: Too many local variables (20/15)
  W:150:FormatChecker.process_tokens: Too many branches (13/12)


Reports section
'''''''''''''''
Following the analysis message, Pylint will display a set of reports,
each one focusing on a particular aspect of the project, such as number
of messages by categories, modules dependencies...

For instance, the metrics report displays summaries gathered from the
current run.

  * the number of processed modules
  * for each module, the percentage of errors and warnings
  * the total number of errors and warnings
  * percentage of classes, functions and modules with docstrings, and
    a comparison from the previous run
  * percentage of classes, functions and modules with correct name
    (according to the coding standard), and a comparison from the
    previous run
  * a list of external dependencies found in the code, and where they appear

Also, a global evaluation for the code is computed, and an
optional witty comment is displayed (if ``--comment=y`` was
specified on the command line).



Command line options
--------------------

First of all, we have two basic (but useful) options.

--version             show program's version number and exit
-h, --help            show help about the command line options

Pylint is architectured around several checkers. By default all
checkers are enabled. You can disable a specific checker or some of its
messages or messages categories by specifying
``--disable=<id>``. A more general disable can be enabled with
or disable all checkers using
``--enable=w<id>``. See the list of available features_ for a
description of provided checkers with their functionalities.
The ``--disable`` and ``--enable`` options can be used with comma separated lists
mixing checkers, message ids and categories like ``-d C,W,E0611,design``

It is possible to disable all messages with ``--disable=all``. This is
useful to enable only a few checkers or a few messages by first
disabling everything, and then re-enabling only what you need. 

Each checker has some specific options, which can take either a yes/no
value, an integer, a python regular expression, or a comma separated
list of values (which are generally used to override a regular
expression in special cases). For a full list of options, use ``--help``

Specifying all the options suitable for your setup and coding
standards can be tedious, so it is possible to use a rc file to
specify the default values. Pylint looks for /etc/pylintrc and
~/.pylintrc. The ``--generate-rcfile`` option will generate a
commented configuration file according to the current configuration on
standard output and exit. You can put other options before this one to
use them in the configuration, or start with the default values and
hand tune the configuration.

Other useful global options include:

--zope                  Initialize Zope products before starting
--ignore=file           Add <file> (may be a directory) to the black
                          list. It should be a base name, not a path.
                          You may set this option multiple times.
--statistics=y_or_n     Compute statistics on collected data.
--persistent=y_or_n     Pickle collected data for later comparisons.
--comment=y_or_n        Add a comment according to your evaluation note.
--parseable=y_or_n      Use a parseable output format.
--html=y_or_n           Use HTML as output format instead of text.
--list-msgs             Generate pylint's messages.
--full-documentation    Generate pylint's full documentation, in reST format.
--include_ids=y_or_n    Show numeric ids of messages (like 'C0301')
--symbols=y_or_n        Show symbolic ids of messsages (like 'line-too-long')

.. _features: features.html

Daily Pylint usage
------------------
What Pylint says is not to be taken as gospel. While getting as
few false positives for errors as possible is a goal for us -- and
python makes it hard enough, it is not the case for warnings.

:Quoting Alexandre Fayolle:
  My usage pattern for Pylint is to generally run `pylint -e` quite often to
  get stupid errors flagged before launching an application (or before
  committing). I generally run pylint with all the bells and whistles
  activated some time before a release, when I want to cleanup the code.
  And when I do that I simply ignore tons of the false warnings (and I
  can do that without being driven mad by this dumb program which is not
  smart enough to understand the dynamicity of Python because I only run
  it once or twice a week in this mode)

:Quoting Marteen Ter Huurne:
  In our project we just accepted that we have to make some modifications in our
  code to please Pylint:

  - stick to more naming conventions (unused variables ending in underscores,
    mix-in class names ending in "Mixin")
  - making all abstract methods explicit (rather than just not defining them in
    the superclass)
  - for messages which are useful in general, but not in a specific case: add "#
    pylint: disable=X0123" comments
  - for Pylint bugs: add "#pylint: disable=X0123" comments
  - for Pylint limitations: add "#pylint: disable=X0123" comments
    (for instance Twisted's modules create a lot of definitions dynamically so
    Pylint does not know about them)

  The effort is worth it, since Pylint helps us a lot in keeping the code clean
  and finding errors early. Although most errors found by Pylint would also be
  found by the regression tests, by fixing them before committing, we save time.
  And our regression tests do not cover all code either, just the most complex
  parts.


Bug reports, feedback
---------------------
You think you have found a bug in Pylint? Well, this may be the case
since Pylint is under development. Please take the time to send a bug
report to python-projects@logilab.org if you've not found it already reported on
the `tracker page`_. This mailing list is also a nice place to
discuss Pylint issues, see below for more information about Pylint's related
lists.

You can check for already reported bugs, planned features on pylint's tracker
web page: http://www.logilab.org/project/name/pylint

Notice that if you don't find something you have expected in Pylint's
tracker page, it may be on the tracker page of one of its dependencies, namely
astng and common:

* http://www.logilab.org/project/name/logilab-astng
* http://www.logilab.org/project/name/logilab-common

.. _`tracker page`: http://www.logilab.org/project/name/pylint

Mailing lists
-------------
Use the python-projects@logilab.org mailing list for anything related
to Pylint. This is in most cases better than sending an email directly
to the author, since others will benefit from the exchange, and you'll
be more likely answered by someone subscribed to the list. This is a
moderated mailing list, so if you're not subscribed email you send will have to
be validated first before actually being sent on the list.

You can subscribe to this mailing list at
http://lists.logilab.org/mailman/listinfo/python-projects

Archives are available at
http://lists.logilab.org/pipermail/python-projects/

If you prefer speaking French instead of English, you can use the
generic forum-fr@logilab.org mailing list:

* (un)subscribe: http://lists.logilab.org/mailman/listinfo/forum-fr
* archives: http://lists.logilab.org/pipermail/forum-fr

Notice though that this list has a very low traffic since most Pylint related
discussions are done on the python-projects mailing list.



Advanced usage
==============

Base configuration
------------------

To be written...

Environment
-----------

To be written...

Messages control
----------------

An example available from the examples directory:

.. sourcecode:: python

    """pylint option block-disable"""

    __revision__ = None

    class Foo(object):
        """block-disable test"""

        def __init__(self):
            pass

        def meth1(self, arg):
            """this issues a message"""
            print self

        def meth2(self, arg):
            """and this one not"""
            # pylint: disable=W0613
            print self\
                  + "foo"

        def meth3(self):
            """test one line disabling"""
            # no error
            print self.bla # pylint: disable=E1101
            # error
            print self.blop

        def meth4(self):
            """test re-enabling"""
            # pylint: disable=E1101
            # no error
            print self.bla
            print self.blop
            # pylint: enable=E1101
            # error
            print self.blip

        def meth5(self):
            """test IF sub-block re-enabling"""
            # pylint: disable=E1101
            # no error
            print self.bla
            if self.blop:
                # pylint: enable=E1101
                # error
                print self.blip
            else:
                # no error
                print self.blip
            # no error
            print self.blip

        def meth6(self):
            """test TRY/EXCEPT sub-block re-enabling"""
            # pylint: disable=E1101
            # no error
            print self.bla
            try:
                 pylint: enable=E1101
                # error
                print self.blip
            except UndefinedName: # pylint: disable=E0602
                # no error
                print self.blip
            # no error
            print self.blip

        def meth7(self):
            """test one line block opening disabling"""
            if self.blop: # pylint: disable=E1101
                # error
                print self.blip
            else:
                # error
                print self.blip
            # error
            print self.blip


        def meth8(self):
            """test late disabling"""
            # error
            print self.blip
            # pylint: disable=E1101
            # no error
            print self.bla
            print self.blop



About analysis
==============

Pylint heuristics
-----------------

To be written...

About astng inference
---------------------

To be written...



Enhancing Pylint
================

Writing your own checker
------------------------
You can find some simple examples in the examples
directory of the distribution (custom.py and custom_raw.py). I'll try to
quickly explain the essentials here.

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 `compiler 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>` and/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 `compiler.ast documentation`.
Checkers are ordered by priority. For each module, pylint's engine:

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 living_<> on the back traversal

Notice that the source code is probably the best source of
documentation, it should be clear and well documented. Don't hesitate to
ask for any information on the python-projects mailing list.

.. _`compiler package`: http://docs.python.org/library/compiler
.. _`compiler.ast documentation`: http://docs.python.org/library/compiler#module-compiler.ast


Contribute !
------------
All our software is developped using the mercurial_ version control
system. This is a very cool distributed vcs and its usage is very similar to
other ones such as cvs or subversion (though the distributed feature introduced
some different usage patterns). See mercurial home page for installation on
your computer and basic usage. Note that it's very easy to send us patches using
`hg email` command ;).

You can get the in-development pylint source code from our public mercurial_
repository:

http://www.logilab.org/src/pylint

The same is true for Pylint dependencies (if you use Pylint code from the
repository, you should usually use code from the repository as well for astng
and common):

http://www.logilab.org/src/logilab/astng
http://www.logilab.org/src/logilab/common

.. _mercurial: http://www.selenic.com/mercurial/

Contribution Instructions
--------------------------

Got a patch for Pylint?  There a few steps you must take to make sure your
patch gets accepted.

* Test your code
    * Pylint keeps a set of unit tests in the /test directory. To get your
      patch accepted you must write (or change) a test input file and message
      file in the appropriate input and messages folders.
    * In the test folder of pylint run ./fulltest.sh (python version), make sure
      all tests pass before submitting a patch

* Create a diff file
    * To create a diff from the command line invoke (from a directory under
      version control) ::

            hg diff  > <yourname>.diff

* E-mail the mailing list with your diff file

Other information
=================

IDE integration
---------------

To use Pylint with emacs, see http://www.emacswiki.org/emacs/PythonProgrammingInEmacs#toc8

To use Pylint with vim, see
http://www.vim.org/scripts/script.php?script_id=891

To use Pylint with eclipse, see http://pydev.org

To use Pylint with komodo_, see
http://mateusz.loskot.net/2006/01/15/running-pylint-from-komodo/

To use Pylint with gedit_, see
http://live.gnome.org/Gedit/PylintPlugin

To use Pylint with WingIDE_, see
http://www.wingware.com/doc/edit/pylint

Pylint is integrated in Eric_ IDE, see the `Project > Check` menu.

Pylint is integrated in spyder_, see http://packages.python.org/spyder/pylint.html

Pylint is integrated in pyscripter_, see the `Tool -> Tools` menu.

.. _Eric: http://eric-ide.python-projects.org/
.. _pyscripter: http://code.google.com/p/pyscripter/
.. _pydev: http://pydev.org
.. _komodo: http://www.activestate.com/Products/Komodo/
.. _gedit: http://www.gnome.org/projects/gedit/
.. _WingIDE: http://www.wingware.com/
.. _spyder: http://code.google.com/p/spyderlib/


Some projects using Pylint
--------------------------
The following projects are known to use Pylint to help develop better
code:

* OSAF Chandler (http://www.osafoundation.org/)
* Xen (http://www.xensource.com/)
* CPS (http://www.nuxeo.org)
* ERP5 (http://www.erp5.org/)
* pyxmpp (http://pyxmpp.jabberstudio.org/)
* mercurial
* eXe (http://exelearning.org/)
* PrimaGIS (http://www.primagis.org)
* python-cdd (https://projetos.ossystems.com.br/projects/python-cdd)
* CDSWare (http://cdsware.cern.ch/)
* ASE (http://dcwww.camp.dtu.dk/campos/ASE/intro.html)
* RunJob (http://projects.fnal.gov/runjob/)
* Slugathon (http://slugathon.python-hosting.com/)
* Topographica (http://topographica.org/Home/index.html) (at least they intend to do so)
* http://browsershots.org
* many more...

Also notice that the CheeseCake_ kwalitee reporting tool uses Pylint to
analyze the source code.

.. _CheeseCake: http://cheesecake.sourceforge.net/