coding_guide.txt
141 lines
| 6.1 KiB
| text/plain
|
TextLexer
Fernando Perez
|
r1754 | ============== | ||
Coding guide | ||||
============== | ||||
Coding conventions | ||||
================== | ||||
In general, we'll try to follow the standard Python style conventions as | ||||
described in Python's `PEP 8`_, the official Python Style Guide. | ||||
.. _PEP 8: http://www.python.org/peps/pep-0008.html | ||||
Other comments: | ||||
- In a large file, top level classes and functions should be separated by 2-3 | ||||
lines to make it easier to separate them visually. | ||||
- Use 4 spaces for indentation, *never* use hard tabs. | ||||
- Keep the ordering of methods the same in classes that have the same methods. | ||||
This is particularly true for classes that implement similar interfaces and | ||||
for interfaces that are similar. | ||||
Naming conventions | ||||
------------------ | ||||
In terms of naming conventions, we'll follow the guidelines of PEP 8. Some of | ||||
the existing code doesn't honor this perfectly, but for all new IPython code | ||||
(and much existing code is being refactored), we'll use: | ||||
- All ``lowercase`` module names. | ||||
- ``CamelCase`` for class names. | ||||
- ``lowercase_with_underscores`` for methods, functions, variables and | ||||
attributes. | ||||
This may be confusing as some of the existing codebase uses a different | ||||
convention (``lowerCamelCase`` for methods and attributes). Slowly, we will | ||||
move IPython over to the new convention, providing shadow names for backward | ||||
compatibility in public interfaces. | ||||
There are, however, some important exceptions to these rules. In some cases, | ||||
IPython code will interface with packages (Twisted, Wx, Qt) that use other | ||||
conventions. At some level this makes it impossible to adhere to our own | ||||
standards at all times. In particular, when subclassing classes that use other | ||||
naming conventions, you must follow their naming conventions. To deal with | ||||
cases like this, we propose the following policy: | ||||
- If you are subclassing a class that uses different conventions, use its | ||||
naming conventions throughout your subclass. Thus, if you are creating a | ||||
Twisted Protocol class, used Twisted's | ||||
``namingSchemeForMethodsAndAttributes.`` | ||||
- All IPython's official interfaces should use our conventions. In some cases | ||||
this will mean that you need to provide shadow names (first implement | ||||
``fooBar`` and then ``foo_bar = fooBar``). We want to avoid this at all | ||||
costs, but it will probably be necessary at times. But, please use this | ||||
sparingly! | ||||
Implementation-specific *private* methods will use | ||||
``_single_underscore_prefix``. Names with a leading double underscore will | ||||
*only* be used in special cases, as they makes subclassing difficult (such | ||||
names are not easily seen by child classes). | ||||
Occasionally some run-in lowercase names are used, but mostly for very short | ||||
names or where we are implementing methods very similar to existing ones in a | ||||
base class (like ``runlines()`` where ``runsource()`` and ``runcode()`` had | ||||
established precedent). | ||||
The old IPython codebase has a big mix of classes and modules prefixed with an | ||||
explicit ``IP``. In Python this is mostly unnecessary, redundant and frowned | ||||
upon, as namespaces offer cleaner prefixing. The only case where this approach | ||||
is justified is for classes which are expected to be imported into external | ||||
namespaces and a very generic name (like Shell) is too likely to clash with | ||||
something else. We'll need to revisit this issue as we clean up and refactor | ||||
the code, but in general we should remove as many unnecessary ``IP``/``ip`` | ||||
prefixes as possible. However, if a prefix seems absolutely necessary the more | ||||
specific ``IPY`` or ``ipy`` are preferred. | ||||
.. _devel-testing: | ||||
Testing system | ||||
============== | ||||
It is extremely important that all code contributed to IPython has tests. Tests | ||||
should be written as unittests, doctests or as entities that the `Nose`_ | ||||
testing package will find. Regardless of how the tests are written, we will use | ||||
`Nose`_ for discovering and running the tests. `Nose`_ will be required to run | ||||
the IPython test suite, but will not be required to simply use IPython. | ||||
.. _Nose: http://code.google.com/p/python-nose/ | ||||
Tests of `Twisted`__ using code should be written by subclassing the | ||||
``TestCase`` class that comes with ``twisted.trial.unittest``. When this is | ||||
done, `Nose`_ will be able to run the tests and the twisted reactor will be | ||||
handled correctly. | ||||
.. __: http://www.twistedmatrix.com | ||||
Each subpackage in IPython should have its own ``tests`` directory that | ||||
contains all of the tests for that subpackage. This allows each subpackage to | ||||
be self-contained. If a subpackage has any dependencies beyond the Python | ||||
standard library, the tests for that subpackage should be skipped if the | ||||
dependencies are not found. This is very important so users don't get tests | ||||
failing simply because they don't have dependencies. | ||||
We also need to look into use Noses ability to tag tests to allow a more | ||||
modular approach of running tests. | ||||
.. _devel-config: | ||||
Configuration system | ||||
==================== | ||||
IPython uses `.ini`_ files for configuration purposes. This represents a huge | ||||
improvement over the configuration system used in IPython. IPython works with | ||||
these files using the `ConfigObj`_ package, which IPython includes as | ||||
``ipython1/external/configobj.py``. | ||||
Currently, we are using raw `ConfigObj`_ objects themselves. Each subpackage of | ||||
IPython should contain a ``config`` subdirectory that contains all of the | ||||
configuration information for the subpackage. To see how configuration | ||||
information is defined (along with defaults) see at the examples in | ||||
``ipython1/kernel/config`` and ``ipython1/core/config``. Likewise, to see how | ||||
the configuration information is used, see examples in | ||||
``ipython1/kernel/scripts/ipengine.py``. | ||||
Eventually, we will add a new layer on top of the raw `ConfigObj`_ objects. We | ||||
are calling this new layer, ``tconfig``, as it will use a `Traits`_-like | ||||
validation model. We won't actually use `Traits`_, but will implement | ||||
something similar in pure Python. But, even in this new system, we will still | ||||
use `ConfigObj`_ and `.ini`_ files underneath the hood. Talk to Fernando if you | ||||
are interested in working on this part of IPython. The current prototype of | ||||
``tconfig`` is located in the IPython sandbox. | ||||
.. _.ini: http://docs.python.org/lib/module-ConfigParser.html | ||||
.. _ConfigObj: http://www.voidspace.org.uk/python/configobj.html | ||||
.. _Traits: http://code.enthought.com/traits/ | ||||