Try to choose names which are both easy to remember and
meaningful. Some silliness is OK at the module naming level
(see twisted.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
something.
Unit tests are written using the PyUnit framework. Many
examples are in the twisted.test
package, and all tests should be integrated through the main
test suite builder in twisted.test.test_all
.
Acceptance tests are all automated by the bin/accepttests script currently. (TODO: real acceptance tests strategy!)
Run the unit tests tests before you check anything in.
Let me repeat that, for emphasis: run the unit tests before you check anything in. 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
twisted-dev.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 run
admin/generate-domdocs
and check the output is all right.
Also, it is useful to run bin/hlint
on any howto you may have
modified. There should never be any warnings -- if you're having problems,
you can always explicitly silence warnings by using hlint="off"
(though please do this sparingly).
If you modify the quotes file, run strfile(1)
to check you
did not harm it. In particular, if the shortest string
is too short, you
might have trailing empty lines.
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.
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 look like this:
from twisted.internet.defer import Deferredor like this:
from twisted.internet import deferThat is, modules should import modules or classes and functions, but not 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.
__init__.py
must never contain anything other than a
docstring and (optionally) an __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,
# parent/ # --- __init__.py --- import child # --- child.py --- import parent class Foo: pass parent.Foo = Foo
Every package should be added to the list in
setup.py
.
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 ("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 never 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.
Additionally, to accommodate emacs users:
For example,
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.
For each script
, that is, a program you expect a Twisted user
to run from the command-line, the following things must be done:
twisted.scripts
which contains
a callable global named run
. This will be called by the
command line part with no arguments (it will usually read
sys.argv
). Feel free to write more functions or classes in this
module, if you feel they are useful to others.bin/
which contains the
Twisted running-from-CVS header, and ending with
from twisted.scripts.yourmodule import run run()
doc/man
.
On debian systems you can find a skeleton example of a manpage in
/usr/share/doc/man-db/examples/manpage.example
.setup.py
.This will insure your program will work correctly for users of CVS, Windows releases and Debian packages.
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 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
admin/change
script to add a properly-formatted entry.
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:
Examples of classes not meeting this criteria:
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 (see above) the classes may be imported directly into the user's namespace and not cause confusion.
Methods should be in mixed case, with the first letter lower
case, each word separated by having its first letter
capitalized. For example, someMethodName
, 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, get_someAttribute
.
Underscores in method names in twisted code are therefore
expected to have some semantic associated with them.
Functions should be named similiarly to methods.
Functions or methods which are responding to events to
complete a callback or errback should be named _cbMethodName
or
_ebMethodName
, in order to distinguish them from normal
methods.
Attributes should be named similarly to functions and
methods. Attributes should be named descriptively; attribute
names like mode
, type
, and
buf
are generally discouraged. Instead, use
displayMode
, playerType
, or
inputBuffer
.
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:
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 directly 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.
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 must 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.
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 hard line breaks into short lines (< 70 characters). This is free-format, so you can do whatever you like here.
Checkin messages should be about what, not how: 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.
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 use 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 big 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.