coding-standard.tex   [plain text]


\section{Twisted Coding Standard\label{doc/howto/policy/coding-standard.xhtml}}


\subsection{Naming}


Try to choose names which are both easy to remember and     meaningful. Some silliness is OK at the module naming level     (see \texttt{twisted.\linebreak[1]spread}...) but when     choosing class names, be as precise as possible. Write code     with a dictionary and thesaurus open on the table next to     you.

Try to avoid overloaded terms. This rule is often broken,     since it is incredibly difficult, as most normal words have     already been taken by some other software. More importantly,     try to avoid meaningless words. In particular, words like     ``handler'', ``processor'', ``engine'', ``manager''     and ``component'' don't really indicate what something does,     only that it does     \begin{em}something\end{em}.

Use American spelling in both names and docstrings.  For compound      technical terms such as 'filesystem', use a non-hyphenated spelling in      both docstrings and code in order to avoid unnecessary      capitalization. 

\subsection{Testing}


Unit tests are written using the \texttt{twisted.\linebreak[1]trial} framework. Many examples are in the     \texttt{twisted.\linebreak[1]test} package. Test modules should start     with 'test\_' in their name. Source files should have \textit{\texttt{test-case-name}}\loreref{doc/howto/policy/test-standard.xhtml} tags that     point to their related tests.

Acceptance tests are all automated by the admin/accepttests     script currently. (TODO: real acceptance tests strategy!)

Run the unit tests tests before you check anything in.

Let me repeat that, for emphasis: \begin{em}run the unit tests before you         check \begin{em}anything\end{em} in\end{em}.  Code which breaks      functionality is unfortunate and unavoidable.  The acceptance tests     are highly nonportable and sometimes a pain to run, so this is pardonable.     Code which breaks the unit tests in a way that you could have prevented      by running them yourself, however, may be grounds for anything from      merciless taunting through revertion of the breakage to revocation      of cvs commit privileges.

It is strongly suggested that developers learn to use Emacs, and use      the \texttt{twisted-dev.\linebreak[1]el} file included in the TwistedEmacs      package to bind the F9 key to ``run unit tests'' and bang on it      frequently.  Support for other editors is unavailable at this time     but we would love to provide it.

If you modify, or write a new, HOWTO, please read the \textit{Lore documentation}\loreref{doc/howto/lore.xhtml} to learn the format the docs.

\subsection{Whitespace}


Indentation is 4 spaces per indent. Tabs are not allowed. It     is preferred that every block appear on a new line, so that     control structure indentation is always visible.

\subsection{Modules}


Modules must be named in all lower-case, preferably short,     single words. If a module name contains multiple words, they     may be separated by underscores or not separated at all.

In most cases, modules should contain more than one class,     function, or method; if a module contains only one object,     consider refactoring to include more related functionality in     that module.

Depending on the situation, it is acceptable to have imports that        look like this:        \begin{verbatim}
from twisted.internet.defer import Deferred
\end{verbatim}
        or like this:         \begin{verbatim}
from twisted.internet import defer
\end{verbatim}
         That is, modules should import \begin{em}modules\end{em} or         \begin{em}classes and functions\end{em}, but not \begin{em}packages\end{em}.

\subsection{Packages}


Package names should follow the same conventions as module     names. All modules must be encapsulated in some package. Nested     packages may be used to further organize related modules.

\texttt{\_\_init\_\_.\linebreak[1]py} must never contain anything other than a     docstring and (optionally) an \texttt{\_\_all\_\_} attribute. Packages are     not modules and should be treated differently. This rule may be     broken to preserve backwards compatibility if a module is made     into a nested package as part of a refactoring.

If you wish to promote code from a module to a package, for     example, to break a large module out into several smaller     files, the accepted way to do this is to promote from within     the module. For example,\begin{verbatim}
# parent/
# --- __init__.py ---
import child

# --- child.py ---
import parent
class Foo:
    pass
parent.Foo = Foo
\end{verbatim}


Every package should be added to the list in     \texttt{setup.\linebreak[1]py}.

Packages must not depend circularly upon each other.  To simplify     maintaining this state, packages must also not import each other     circularly.  While this applies to all packages within Twisted, one     \texttt{twisted.\linebreak[1]python} deserves particular attention, as it may     not depend on any other Twisted package.

\subsection{Docstrings}


Wherever possible, docstrings should be used to describe the     purpose of methods, functions, classes, and modules. In cases     where it's desirable to avoid documenting thoroughly -- for     example, and evolving interface -- insert a placeholder     docstring (\texttt{"UNDOCUMENTED"} is preferred),     so that the     auto-generated API documentation will not pick up an extraneous     comment as the documentation for that     module/class/function.

Docstrings are \begin{em}never\end{em} to be used to provide semantic     information about an object; this rule may be violated if the     code in question is to be used in a system where this is a     requirement (such as Zope).

Docstrings should be indented to the level of the code they     are documenting.

Docstrings should be triple-quoted.

Docstrings should be written in epytext format; more     documentation is available in the     Epytext Markup Language documentation\footnote{http://epydoc.sourceforge.net/epytext.html}.

Additionally, to accommodate emacs users:\begin{itemize}
\item Single quotes of the type of the docstring's triple-quote       should be escaped. This will prevent font-lock from       accidentally fontifying large portions of the file as a       string.
\item Code examples in docstrings should be prefixed by the |       character. This will prevent IM-Python from regarding sample       code as real functions, methods, and classes.
\end{itemize}


For example,\begin{verbatim}
def foo2bar(f):
    """I am a function to convert foos to bars.

    I should be used when you have a foo but you want a bar; note that this is
    a non-destructive operation.  If I can\'t convert the foo to a bar I will
    raise a FooException().

    For example::

      |  import wombat
      |  def sample(something):
      |      f = something.getFoo()
      |      f.doFooThing()
      |      b = wombat.foo2bar(f)
      |      b.doBarThing()
      |      return b

    """
    # Optionally, actual code can go here.
\end{verbatim}


\subsection{Scripts}


For each ``script'', that is, a program you expect a Twisted user     to run from the command-line, the following things must be done:\begin{enumerate}
\item Write a module in \texttt{twisted.\linebreak[1]scripts}        which contains a callable global named \texttt{run}. This        will be called by the command line part with no arguments (it        will usually read \texttt{sys.\linebreak[1]argv}). Feel free to write more        functions or classes in this module, if you feel they are useful        to others.
\item Write a file in \texttt{bin/} which contains the           Twisted running-from-CVS header, and ending with   \begin{verbatim}
from twisted.scripts.yourmodule import run
run()
\end{verbatim}

\item Write a manpage in \texttt{doc/man}.       On debian systems you can find a skeleton example of a manpage in       \texttt{/usr/share/doc/man-db/examples/manpage.\linebreak[1]example}.
\item Add your script to the script list in       \texttt{setup.\linebreak[1]py}.
\end{enumerate}


This will insure your program will work correctly for users of CVS,     Windows releases and Debian packages.

\subsection{Standard Library Extension Modules}


When using the extension version of a module for which there is also     a Python version, place the import statement inside a try/except block,     and import the Python version if the import fails.  This allows code to     work on platforms where the extension version is not available.  For     example:  \begin{verbatim}
try:
    import cPickle as pickle
except ImportError:
    import pickle
\end{verbatim}
      Use the "as" syntax of the import statement as well, to set     the name of the extension module to the name of the Python module.

\subsection{ChangeLog}


All changes that will affect the way end-users see Twisted should come     with an appropriate entry in the ChangeLog that summarizes that impact.

The correct format for the ChangeLog is GNU changelog format.  There is     an emacs mode for editing this, use \texttt{M-x add-change-log-entry}.     If you are, for whatever absurd reason, using an editor other than emacs      to edit Twisted, you can use Moshe Zadka's helpfully provided     \texttt{admin/change} script to add a properly-formatted entry.

\subsection{Classes}


Classes are to be named in mixed case, with the first letter     capitalized; each word separated by having its first letter     capitalized. Acronyms should be capitalized in their entirety.     Class names should not be prefixed with the name of the module they are     in. Examples of classes meeting this criteria:\begin{itemize}
\item twisted.spread.pb.ViewPoint
\item twisted.parser.patterns.Pattern
\end{itemize}


Examples of classes \begin{em}not\end{em} meeting this criteria:\begin{itemize}
\item event.EventHandler
\item main.MainGadget
\end{itemize}


An effort should be made to prevent class names from clashing     with each other between modules, to reduce the need for     qualification when importing. For example, a Service subclass     for Forums might be named twisted.forum.service.ForumService,     and a Service subclass for Words might be     twisted.words.service.WordsService. Since neither of these     modules are volatile \begin{em}(see above)\end{em} the classes may be     imported directly into the user's namespace and not cause     confusion.

\subsection{Methods}


Methods should be in mixed case, with the first letter lower     case, each word separated by having its first letter     capitalized. For example, \texttt{some\linebreak[1]Method\linebreak[1]Name},      \texttt{method}.

Sometimes, a class will dispatch to a specialized sort of     method using its name; for example, twisted.reflect.Accessor.     In those cases, the type of method should be a prefix in all     lower-case with a trailing underscore, so method names will     have an underscore in them. For example, \texttt{get\_some\linebreak[1]Attribute}.     Underscores in method names in twisted code are therefore     expected to have some semantic associated with them.

Some methods, in particular \texttt{add\linebreak[1]Callback} and its     cousins return self to allow for chaining calls.  In this case,     wrap the chain in parenthesis, and start each chained call on     a separate line, for example:\begin{verbatim}
    return (foo()
            .addCallback(bar)
            .addCallback(thud)
            .addCallback(wozers))
\end{verbatim}


\subsection{Callback Arguments}


There are several methods whose purpose is to help the user set up     callback functions, for example \texttt{Deferred.\linebreak[1]add\linebreak[1]Callback} or the     reactor's \texttt{call\linebreak[1]Later} method. To make     access to the callback as transparent as possible, most of these methods     use \texttt{**kwargs} to capture arbitrary arguments     that are destined for the user's callback. This allows the call to the     setup function to look very much like the eventual call to the target     callback function.

In these methods, take care to not have other argument names that will     ``steal'' the user's callback's arguments. When sensible, prefix these     ``internal'' argument names with an underscore. For example, \texttt{Remote\linebreak[1]Reference.\linebreak[1]call\linebreak[1]Remote} is     meant to be called like this:\begin{verbatim}
myref.callRemote("addUser", "bob", "555-1212")

# on the remote end, the following method is invoked:
def addUser(name, phone):
    ...
\end{verbatim}


where ``addUser'' is the remote method name. The user might also     choose to call it with named parameters like this:\begin{verbatim}
myref.callRemote("addUser", name="bob", phone="555-1212")
\end{verbatim}


In this case, \texttt{call\linebreak[1]Remote} (and any code that uses the     **kwargs syntax) must be careful to not use ``name'', ``phone'', or     any other name that might overlap with a user-provided named parameter.     Therefore, \texttt{call\linebreak[1]Remote} is implemented with the following     signature:\begin{verbatim}
def callRemote(self, _name, *args, **kw):
   ...
\end{verbatim}


Do whatever you can to reduce user confusion. It may also be     appropriate to \texttt{assert} that the kwargs     dictionary does not contain parameters with names that will eventually     cause problems.

\subsection{Special Methods}


The augmented assignment protocol, defined by \_\_iadd\_\_ and other     similarly named methods, can be used to allow objects to be modified in     place or to rebind names if an object is immutable -- both through use     of the same operator.  This can lead to confusing code, which in turn     leads to buggy code.  For this reason, methods of the augmented     assignment protocol should not be used in Twisted.

\subsection{Functions}


Functions should be named similiarly to methods.

Functions or methods which are responding to events to     complete a callback or errback should be named \texttt{\_cb\linebreak[1]Method\linebreak[1]Name} or     \texttt{\_eb\linebreak[1]Method\linebreak[1]Name}, in order to distinguish them from normal     methods.

\subsection{Attributes}


Attributes should be named similarly to functions and     methods. Attributes should be named descriptively; attribute     names like \texttt{mode}, \texttt{type}, and     \texttt{buf} are generally discouraged. Instead, use     \texttt{display\linebreak[1]Mode}, \texttt{player\linebreak[1]Type}, or     \texttt{input\linebreak[1]Buffer}.

Do not use Python's ``private'' attribute syntax; prefix     non-public attributes with a single leading underscore. Since     several classes have the same name in Twisted, and they are     distinguished by which package they come from, Python's     double-underscore name mangling will not work reliably in some     cases. Also, name-mangled private variables are more difficult     to address when unit testing or persisting a class.

An attribute (or function, method or class) should be     considered private when one or more of the following conditions     are true:\begin{itemize}
\item The attribute represents intermediate state which is not       always kept up-to-date.
\item Referring to the contents of the attribute or otherwise       maintaining a reference to it may cause resources to       leak.
\item Assigning to the attribute will break internal       assumptions.
\item The attribute is part of a known-to-be-sub-optimal       interface and will certainly be removed in a future       release.
\end{itemize}


\subsection{Database}


Database tables will be named with plural nouns.

Database columns will be named with underscores between     words, all lower case, since most databases do not distinguish     between case.

Any attribute, method argument, or method name that     corresponds \begin{em}directly\end{em} to a column in the database will     be named exactly the same as that column, regardless of other     coding conventions surrounding that circumstance.

All SQL keywords should be in upper case.

\subsection{C Code}


Wherever possible, C code should be optional, and the     default python implementation should be maintained in tandem     with it. C code should be strict ANSI C, and     \begin{em}must\end{em} build using GCC as well as Visual Studio     for Windows, and really shouldn't have any problems with other     compilers either. Don't do anything tricky.

C code should only be used for efficiency, not for binding     to external libraries. If your particular code is not     frequently run, write it in Python. If you require the use of     an external library, develop a separate, external bindings     package and make your twisted code depend on it.

\subsection{Checkin Messages}


Thanks to CVSToys, the checkin messages are being used in a myriad     of ways. Because of that, you need to observe a few simple rules when     writing a checkin message.

The first line of the message is being used as both the subject of     the commit e-mail and the announcement on \#twisted. Therefore, it should     be short (aim for $<$ 80 characters) and descriptive -- and must be     able to stand alone (it is best if it is a complete sentence). The rest     of the e-mail should be separated with \begin{em}hard line breaks\end{em} into     short lines ($<$ 70 characters). This is free-format, so you can do     whatever you like here.

Checkin messages should be about \begin{em}what\end{em}, not \begin{em}how\end{em}: we     can get how from CVS diff. Explain reasons for checkins, and what they     affect.

Each commit should be a single logical change, which is internally     consistent. If you can't summarize your changes in one short line, this     is probably a sign that they should be broken into multiple checkins.

\subsection{Recommendations}


These things aren't necessarily standardizeable (in that     code can't be easily checked for compliance) but are a good     idea to keep in mind while working on Twisted.

If you're going to work on a fragment of the Twisted     codebase, please consider finding a way that you would \begin{em}use\end{em}     such a fragment in daily life. I use the Twisted Web server on     the main TML website, and aside from being good PR, this     encourages you to actively maintain and improve your code, as     the little everyday issues with using it become apparent.

Twisted is a \begin{em}big\end{em} codebase! If you're     refactoring something, please make sure to recursively grep for     the names of functions you're changing. You may be surprised to     learn where something is called. Especially if you are moving     or renaming a function, class, method, or module, make sure     that it won't instantly break other code.