coding_guide.txt
123 lines
| 5.0 KiB
| text/plain
|
TextLexer
Brian Granger
|
r2277 | ============ | ||
Coding guide | ||||
============ | ||||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | General coding conventions | ||
========================== | ||||
Fernando Perez
|
r1754 | |||
In general, we'll try to follow the standard Python style conventions as | ||||
Brian Granger
|
r2277 | described in Python's PEP 8 [PEP8]_, the official Python Style Guide. | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | Other general comments: | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | * In a large file, top level classes and functions should be separated by 2 | ||
Fernando Perez
|
r1754 | lines to make it easier to separate them visually. | ||
Brian Granger
|
r2277 | * Use 4 spaces for indentation, **never** use hard tabs. | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | * Keep the ordering of methods the same in classes that have the same methods. | ||
Fernando Perez
|
r1754 | This is particularly true for classes that implement similar interfaces and | ||
for interfaces that are similar. | ||||
Naming conventions | ||||
Brian Granger
|
r2277 | ================== | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | In terms of naming conventions, we'll follow the guidelines of PEP 8 [PEP8]_. | ||
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: | ||||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | * All ``lowercase`` module names. | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | * ``CamelCase`` for class names. | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | * ``lowercase_with_underscores`` for methods, functions, variables and | ||
Fernando Perez
|
r1754 | 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: | ||||
Brian Granger
|
r2276 | * 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 | ||||
Brian Granger
|
r2277 | ``_single_underscore_prefix``. Names with a leading double underscore will | ||
Brian Granger
|
r2276 | *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 | ||||
Brian Granger
|
r2277 | something else. However, if a prefix seems absolutely necessary the more | ||
Brian Granger
|
r2276 | specific ``IPY`` or ``ipy`` are preferred. | ||
Fernando Perez
|
r1754 | |||
Brian Granger
|
r2277 | .. [PEP8] Python Enhancement Proposal 8. http://www.python.org/peps/pep-0008.html | ||
Brian Granger
|
r2275 | |||
Fernando Perez
|
r2359 | Attribute declarations for objects | ||
================================== | ||||
In general, objects should declare in their *class* all attributes the object | ||||
is meant to hold throughout its life. While Python allows you to add an | ||||
attribute to an instance at any point in time, this makes the code harder to | ||||
read and requires methods to constantly use checks with hasattr() or try/except | ||||
calls. By declaring all attributes of the object in the class header, there is | ||||
a single place one can refer to for understanding the object's data interface, | ||||
where comments can explain the role of each variable and when possible, | ||||
sensible deafaults can be assigned. | ||||
.. Warning:: | ||||
If an attribute is meant to contain a mutable object, it should be set to | ||||
``None`` in the class and its mutable value should be set in the object's | ||||
constructor. Since class attributes are shared by all instances, failure | ||||
to do this can lead to difficult to track bugs. But you should still set | ||||
it in the class declaration so the interface specification is complete and | ||||
documdented in one place. | ||||
A simple example:: | ||||
class foo: | ||||
# X does..., sensible default given: | ||||
x = 1 | ||||
# y does..., default will be set by constructor | ||||
y = None | ||||
# z starts as an empty list, must be set in constructor | ||||
z = None | ||||
def __init__(self, y): | ||||
self.y = y | ||||
self.z = [] | ||||
Fernando Perez
|
r3206 | |||
New files | ||||
========= | ||||
When starting a new file for IPython, you can use the following template as a | ||||
starting point that has a few common things pre-written for you. The template | ||||
is included in the documentation sources as | ||||
:file:`docs/sources/development/template.py`: | ||||
.. literalinclude:: template.py | ||||