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 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818
|
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Twisted Documentation: Twisted Coding Standard</title>
<link href="../../howto/stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body bgcolor="white">
<h1 class="title">Twisted Coding Standard</h1>
<div class="toc"><ol><li><a href="#auto0">Naming</a></li><li><a href="#auto1">Testing</a></li><ul><li><a href="#auto2">Overview</a></li><li><a href="#auto3">Test Suite</a></li></ul><li><a href="#auto4">Copyright Header</a></li><li><a href="#auto5">Whitespace</a></li><li><a href="#auto6">Modules</a></li><li><a href="#auto7">Packages</a></li><li><a href="#auto8">String Formatting Operations</a></li><li><a href="#auto9">Docstrings</a></li><li><a href="#auto10">Comments</a></li><li><a href="#auto11">Versioning</a></li><li><a href="#auto12">Scripts</a></li><li><a href="#auto13">Examples</a></li><li><a href="#auto14">Standard Library Extension Modules</a></li><li><a href="#auto15">Classes</a></li><ul><li><a href="#auto16">New-style Classes</a></li></ul><li><a href="#auto17">Methods</a></li><li><a href="#auto18">Callback Arguments</a></li><li><a href="#auto19">Special Methods</a></li><li><a href="#auto20">Functions</a></li><li><a href="#auto21">Attributes</a></li><li><a href="#auto22">Database</a></li><li><a href="#auto23">C Code</a></li><li><a href="#auto24">Commit Messages</a></li><li><a href="#auto25">Source Control</a></li><li><a href="#auto26">Fallback</a></li><li><a href="#auto27">Recommendations</a></li></ol></div>
<div class="content">
<span/>
<h2>Naming<a name="auto0"/></h2>
<p>Try to choose names which are both easy to remember and
meaningful. Some silliness is OK at the module naming level
(see <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.spread.html" title="twisted.spread">twisted.spread</a></code>...) but when
choosing class names, be as precise as possible.</p>
<p>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
<q>handler</q>, <q>processor</q>, <q>engine</q>, <q>manager</q>
and <q>component</q> don't really indicate what something does,
only that it does <em>something</em>.</p>
<p>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.</p>
<h2>Testing<a name="auto1"/></h2>
<h3>Overview<a name="auto2"/></h3>
<p>Twisted development should always be
<a href="http://en.wikipedia.org/wiki/Test-driven_development" shape="rect">
test-driven</a>. The complete test suite in the head of the SVN trunk is required to
be passing on <a href="http://buildbot.twistedmatrix.com/supported" shape="rect">
supported platforms</a> at all times. Regressions in the test suite
are addressed by reverting whatever revisions introduced them. For
complete documentation about testing Twisted itself, refer to the
<a href="test-standard.html" shape="rect">Test Standard</a>. What follows is
intended to be a synopsis of the most important points.</p>
<h3>Test Suite<a name="auto3"/></h3>
<p>The Twisted test suite is spread across many subpackages of the
<code>twisted</code> package. Many older tests are in
<code>twisted.test</code>. Others can be found at places such as
<code>twisted.web.test</code> (for <code>twisted.web</code> tests)
or <code>twisted.internet.test</code> (for <code>twisted.internet</code>
tests). The latter arrangement, <code>twisted.somepackage.test</code>,
is preferred for new tests except when a test module already exists in
<code>twisted.test</code>.
</p>
<p>
Parts of the Twisted test suite may serve as good examples of how to
write tests for Twisted or for Twisted-based libraries (newer parts of
the test suite are generally better examples than older parts - check
when the code you are looking at was written before you use it as an
example of what you should write). The names of test modules should
begin with <code>test_</code> so that they are automatically discoverable by
test runners such as Trial. Twisted's unit tests are written using
<code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.trial.html" title="twisted.trial">twisted.trial</a></code>, an xUnit library which has been
extensively customized for use in testing Twisted and Twisted-based
libraries.</p>
<p>Implementation (ie, non-test) source files should begin with a
<code>test-case-name</code> tag which gives the name of any test
modules or packages which exercise them. This lets tools discover a
subset of the entire test suite which they can run first to find tests
which might be broken by a particular change.</p>
<p>It is strongly suggested that developers learn to use Emacs, and use
the <code>twisted-dev.el</code> file included in
<a href="http://launchpad.net/twisted-emacs" shape="rect">twisted-emacs</a>
to bind the F9 key to <q>run unit tests</q> and bang on it
frequently. Support for other editors is unavailable at this time but
we would love to provide it.</p>
<p>To run the whole Twisted test without using emacs, use trial:</p>
<pre class="shell" xml:space="preserve">
$ bin/trial twisted
</pre>
<p>To run an individual test module, such as
<code>twisted/mail/test/test_pop3.py</code>, specify the module
name:</p>
<pre class="shell" xml:space="preserve">
$ bin/trial twisted.mail.test.test_pop3
</pre>
<p>To run the tests associated with a particular implementation file,
such as <code>twisted/mail/pop3.py</code>, use the
<code>testmodule</code> option:</p>
<pre class="shell" xml:space="preserve">
$ bin/trial twisted/mail/pop3.py
</pre>
<p>All unit test methods should have docstrings specifying at a high
level the intent of the test. That is, a description that users of the
method would understand.</p>
<p>If you modify, or write a new, HOWTO, please read the <a href="http://twistedmatrix.com/trac/wiki/TwistedLore" shape="rect">Lore</a>
documentation to learn how to format the docs.</p>
<h2>Copyright Header<a name="auto4"/></h2>
<p>Whenever a new file is added to the repository, add the following
license header at the top of the file:</p>
<pre class="python"><p class="py-linenumber">1
2
</p><span class="py-src-comment"># Copyright (c) Twisted Matrix Laboratories.</span>
<span class="py-src-comment"># See LICENSE for details.</span>
</pre>
<p>When you update existing files, if there is no copyright header, add
one.</p>
<h2>Whitespace<a name="auto5"/></h2>
<p>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.</p>
<p>Lines are flowed at 79 columns. They must not have trailing
whitespace. Long lines must be wrapped using implied line continuation
inside parentheses; backslashes aren't allowed. To handle long import
lines, please repeat the import like this:</p>
<pre class="python"><p class="py-linenumber">1
2
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">very</span>.<span class="py-src-variable">long</span>.<span class="py-src-variable">package</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">foo</span>, <span class="py-src-variable">bar</span>, <span class="py-src-variable">baz</span>
<span class="py-src-keyword">from</span> <span class="py-src-variable">very</span>.<span class="py-src-variable">long</span>.<span class="py-src-variable">package</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">qux</span>, <span class="py-src-variable">quux</span>, <span class="py-src-variable">quuux</span>
</pre>
<p>Top-level classes and functions must be separated with 3 blank lines,
and class-level functions with 2 blank lines. The control-L (i.e. ^L) form
feed character must not be used.</p>
<h2>Modules<a name="auto6"/></h2>
<p>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.</p>
<p>Modules must have a copyright message, a docstring and a
reference to a test module that contains the bulk of its tests.
Use this template:</p>
<div class="py-listing"><pre><p class="py-linenumber"> 1
2
3
4
5
6
7
8
9
10
11
12
</p><span class="py-src-comment"># -*- test-case-name: <test module> -*-</span>
<span class="py-src-comment"># Copyright (c) Twisted Matrix Laboratories.</span>
<span class="py-src-comment"># See LICENSE for details.</span>
<span class="py-src-string">"""
Docstring goes here.
"""</span>
<span class="py-src-variable">__all__</span> = []
</pre><div class="caption">Source listing - <a href="../listings/new_module_template.py"><span class="filename">../listings/new_module_template.py</span></a></div></div>
<p>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.</p>
<p>Depending on the situation, it is acceptable to have imports that
look like this:
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span>.<span class="py-src-variable">defer</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Deferred</span>
</pre>
or like this:
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
</pre>
That is, modules should import <em>modules</em> or <em>classes and
functions</em>, but not <em>packages</em>.</p>
<p>Wildcard import syntax may not be used by code in Twisted. These
imports lead to code which is difficult to read and maintain by
introducing complexity which strains human readers and automated tools
alike. If you find yourself with many imports to make from a single
module and wish to save typing, consider importing the module itself,
rather than its attributes.</p>
<p><em>Relative imports</em> (or <em>sibling imports</em>) may not be
used by code in Twisted. Relative imports allow certain circularities
to be introduced which can ultimately lead to unimportable modules or
duplicate instances of a single module. Relative imports also make the
task of refactoring more difficult.</p>
<p>In case of local names conflicts due to import, use the <code>as</code>
syntax, for example:
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">trial</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">util</span> <span class="py-src-keyword">as</span> <span class="py-src-variable">trial_util</span>
</pre></p>
<p>The encoding must always be ASCII, so no coding cookie is necessary.</p>
<h2>Packages<a name="auto7"/></h2>
<p>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.</p>
<p><code>__init__.py</code> must never contain anything other than a
docstring and (optionally) an <code>__all__</code> 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.</p>
<p>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,</p>
<pre class="python"><p class="py-linenumber">1
2
3
4
5
6
7
8
9
</p><span class="py-src-comment"># parent/</span>
<span class="py-src-comment"># --- __init__.py ---</span>
<span class="py-src-keyword">import</span> <span class="py-src-variable">child</span>
<span class="py-src-comment"># --- child.py ---</span>
<span class="py-src-keyword">import</span> <span class="py-src-variable">parent</span>
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Foo</span>:
<span class="py-src-keyword">pass</span>
<span class="py-src-variable">parent</span>.<span class="py-src-variable">Foo</span> = <span class="py-src-variable">Foo</span>
</pre>
<p>Every package should be added to the list in
<code class="shell">setup.py</code>.</p>
<p>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
<code>twisted.python</code> deserves particular attention, as it may
not depend on any other Twisted package.</p>
<h2>String Formatting Operations<a name="auto8"/></h2>
<p>When using <a href="http://docs.python.org/lib/typesseq-strings.html" shape="rect">string formatting
operations</a> like <code>formatString % values</code> you should always
use a tuple if you're using non-mapping <code>values</code>. This is to
avoid unexpected behavior when you think you're passing in a single value,
but the value is unexpectedly a tuple, e.g.:</p>
<pre class="python"><p class="py-linenumber">1
2
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">foo</span>(<span class="py-src-parameter">x</span>):
<span class="py-src-keyword">return</span> <span class="py-src-string">"Hi %s\n"</span> % <span class="py-src-variable">x</span>
</pre>
<p>The example shows you can pass in <code>foo("foo")</code> or
<code>foo(3)</code> fine, but if you pass in <code>foo((1,2))</code>,
it raises a <code>TypeError</code>. You should use this instead:</p>
<pre class="python"><p class="py-linenumber">1
2
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">foo</span>(<span class="py-src-parameter">x</span>):
<span class="py-src-keyword">return</span> <span class="py-src-string">"Hi %s\n"</span> % (<span class="py-src-variable">x</span>,)
</pre>
<h2>Docstrings<a name="auto9"/></h2>
<p>Docstrings should always be used to describe the
purpose of methods, functions, classes, and modules.</p>
<p>Docstrings are <em>never</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).</p>
<p>Docstrings should be indented to the level of the code they
are documenting.</p>
<p>Docstrings should be triple-quoted. The opening and the closing of the
docstrings should be on a line by themselves. For example:
<pre class="python"><p class="py-linenumber">1
2
3
4
5
6
7
8
</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">Ninja</span>(<span class="py-src-parameter">object</span>):
<span class="py-src-string">"""
A L{Ninja} is a warrior specializing in various unorthodox arts of war.
"""</span>
<span class="py-src-keyword">def</span> <span class="py-src-identifier">attack</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">someone</span>):
<span class="py-src-string">"""
Attack C{someone} with this L{Ninja}'s shuriken.
"""</span>
</pre>
</p>
<p>Docstrings should be written in epytext format; more
documentation is available in the
<a href="http://epydoc.sourceforge.net/manual-epytext.html" shape="rect">Epytext Markup Language documentation</a>.</p>
<p>Additionally, to accommodate emacs users, 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.</p>
<p>For example,</p>
<pre class="python"><p class="py-linenumber"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">foo2bar</span>(<span class="py-src-parameter">f</span>):
<span class="py-src-string">"""
Convert L{foo}s to L{bar}s.
A function that should be used when you have a C{foo} but you want a
C{bar}; note that this is a non-destructive operation. If this method
can't convert the C{foo} to a C{bar} it will raise a L{FooException}.
@param f: C{foo}
@type f: str
For example::
import wombat
def sample(something):
f = something.getFoo()
f.doFooThing()
b = wombat.foo2bar(f)
b.doBarThing()
return b
"""</span>
<span class="py-src-comment"># Optionally, actual code can go here.</span>
</pre>
<h2>Comments<a name="auto10"/></h2>
<p>Comments marked with XXX or TODO must contain a reference to the
associated ticket.</p>
<h2>Versioning<a name="auto11"/></h2>
<p>The API documentation should be marked up with version information.
When a new API is added the class should be marked with the epytext
<code class="shell">@since:</code> field including the version number when
the change was introduced, eg. <code class="shell">@since: 8.1</code>.</p>
<h2>Scripts<a name="auto12"/></h2>
<p>For each <q>script</q>, that is, a program you expect a Twisted user
to run from the command-line, the following things must be done:</p>
<ol>
<li>Write a module in <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.scripts.html" title="twisted.scripts">twisted.scripts</a></code>
which contains a callable global named <code>run</code>. This
will be called by the command line part with no arguments (it
will usually read <code>sys.argv</code>). Feel free to write more
functions or classes in this module, if you feel they are useful
to others.</li>
<li>Create a file which contains a shebang line for Python. For Twisted
Core, this file should be placed in the <code>bin/</code> directory; for
example, <code>bin/twistd</code>. For sub-projects, it should be placed
in <code>bin/<subproject></code>; for example, the key-generation tool
for the Conch sub-project is in <code>bin/conch/ckeygen</code>.
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-comment">#!/usr/bin/env python</span>
</pre></li>
<p>To make sure that the script is portable across different UNIX like
operating systems we use the <code>/usr/bin/env</code> command. The env
command allows you to run a program in a modified environment. That way
you don't have to search for a program via the <code>PATH</code> environment
variable. This makes the script more portable but note that it is not a
foolproof method. Always make sure that <code>/usr/bin/env</code> exists or
use a softlink/symbolic link to point it to the correct path. Python's
distutils will rewrite the shebang line upon installation so this policy
only covers the source files in version control.</p>
<li>For core scripts, add this Twisted running-from-SVN header:
<pre class="python"><p class="py-linenumber">1
2
3
4
5
</p><span class="py-src-keyword">import</span> <span class="py-src-variable">sys</span>
<span class="py-src-keyword">try</span>:
<span class="py-src-keyword">import</span> <span class="py-src-variable">_preamble</span>
<span class="py-src-keyword">except</span> <span class="py-src-variable">ImportError</span>:
<span class="py-src-variable">sys</span>.<span class="py-src-variable">clear_exc</span>()
</pre>
Or for sub-project scripts, add a modified version which also adjusts <code>sys.path</code>:
<pre class="python"><p class="py-linenumber">1
2
3
4
5
6
7
8
</p><span class="py-src-keyword">import</span> <span class="py-src-variable">sys</span>, <span class="py-src-variable">os</span>
<span class="py-src-variable">extra</span> = <span class="py-src-variable">os</span>.<span class="py-src-variable">path</span>.<span class="py-src-variable">dirname</span>(<span class="py-src-variable">os</span>.<span class="py-src-variable">path</span>.<span class="py-src-variable">dirname</span>(<span class="py-src-variable">sys</span>.<span class="py-src-variable">argv</span>[<span class="py-src-number">0</span>]))
<span class="py-src-variable">sys</span>.<span class="py-src-variable">path</span>.<span class="py-src-variable">insert</span>(<span class="py-src-number">0</span>, <span class="py-src-variable">extra</span>)
<span class="py-src-keyword">try</span>:
<span class="py-src-keyword">import</span> <span class="py-src-variable">_preamble</span>
<span class="py-src-keyword">except</span> <span class="py-src-variable">ImportError</span>:
<span class="py-src-variable">sys</span>.<span class="py-src-variable">clear_exc</span>()
<span class="py-src-variable">sys</span>.<span class="py-src-variable">path</span>.<span class="py-src-variable">remove</span>(<span class="py-src-variable">extra</span>)
</pre></li>
<li>And end with:
<pre class="python"><p class="py-linenumber">1
2
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">scripts</span>.<span class="py-src-variable">yourmodule</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">run</span>
<span class="py-src-variable">run</span>()
</pre></li>
<li>Write a manpage and add it to the <code class="shell">man</code> folder
of a subproject's <code class="shell">doc</code> folder. On Debian systems
you can find a skeleton example of a manpage in
<code>/usr/share/doc/man-db/examples/manpage.example</code>.</li>
</ol>
<p>This will insure your program will work correctly for users of SVN,
Windows releases and Debian packages.</p>
<h2>Examples<a name="auto13"/></h2>
<p>For example scripts you expect a Twisted user
to run from the command-line, add this Python shebang line at the top
of the file:</p>
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-comment">#!/usr/bin/env python</span>
</pre>
<h2>Standard Library Extension Modules<a name="auto14"/></h2>
<p>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:
<pre class="python"><p class="py-linenumber">1
2
3
4
</p><span class="py-src-keyword">try</span>:
<span class="py-src-keyword">import</span> <span class="py-src-variable">cPickle</span> <span class="py-src-keyword">as</span> <span class="py-src-variable">pickle</span>
<span class="py-src-keyword">except</span> <span class="py-src-variable">ImportError</span>:
<span class="py-src-keyword">import</span> <span class="py-src-variable">pickle</span>
</pre>
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.</p>
<p>Some modules don't exist across all supported Python versions. For
example, Python 2.3's <code>sets</code> module was deprecated in Python 2.6
in favor of the <code>set</code> and <code>frozenset</code> builtins. When
you need to use sets or frozensets in your code, please use
the <code>set</code> and <code>frozenset</code> provided
by <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.python.compat.html" title="twisted.python.compat">twisted.python.compat</a></code>. There are some
differences between <code>sets.Set</code> and <code>set</code>, that are
explained in the <a href="http://www.python.org/dev/peps/pep-0218/" shape="rect">set
PEP</a>. Please be sure to not rely on the behavior of one or the other
implementation.</p>
<h2>Classes<a name="auto15"/></h2>
<p>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:</p>
<ul>
<li>twisted.spread.pb.ViewPoint</li>
<li>twisted.parser.patterns.Pattern</li>
</ul>
<p>Examples of classes <strong>not</strong> meeting this criteria:</p>
<ul>
<li>event.EventHandler</li>
<li>main.MainGadget</li>
</ul>
<p>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 <em>(see above)</em> the classes may be
imported directly into the user's namespace and not cause
confusion.</p>
<h3>New-style Classes<a name="auto16"/></h3>
<p>Classes and instances in Python come in two flavors: old-style or
classic, and new-style. Up to Python 2.1, old-style classes were the
only flavour available to the user, new-style classes were introduced
in Python 2.2 to unify classes and types. All classes added to Twisted
should be written as new-style classes. If <code class="python">x</code>
is an instance of a new-style class, then <code class="python">type(x)</code>
is the same as <code class="python">x.__class__</code>.</p>
<h2>Methods<a name="auto17"/></h2>
<p>Methods should be in mixed case, with the first letter lower
case, each word separated by having its first letter
capitalized. For example, <code>someMethodName</code>,
<code>method</code>.</p>
<p>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, <code>get_someAttribute</code>.
Underscores in method names in twisted code are therefore
expected to have some semantic associated with them.</p>
<p>Some methods, in particular <code>addCallback</code> 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:</p>
<pre class="python"><p class="py-linenumber">1
2
3
4
</p><span class="py-src-keyword">return</span> (<span class="py-src-variable">foo</span>()
.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">bar</span>)
.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">thud</span>)
.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">wozers</span>))
</pre>
<h2>Callback Arguments<a name="auto18"/></h2>
<p>There are several methods whose purpose is to help the user set up
callback functions, for example <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.internet.defer.Deferred.addCallback.html" title="twisted.internet.defer.Deferred.addCallback">Deferred.addCallback</a></code> or the
reactor's <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.internet.base.ReactorBase.callLater.html" title="twisted.internet.base.ReactorBase.callLater">callLater</a></code> method. To make
access to the callback as transparent as possible, most of these methods
use <code class="python">**kwargs</code> 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.</p>
<p>In these methods, take care to not have other argument names that will
<q>steal</q> the user's callback's arguments. When sensible, prefix these
<q>internal</q> argument names with an underscore. For example, <code class="API"><a href="http://twistedmatrix.com/documents/12.0.0/api/twisted.spread.pb.RemoteReference.callRemote.html" title="twisted.spread.pb.RemoteReference.callRemote">RemoteReference.callRemote</a></code> is
meant to be called like this:</p>
<pre class="python"><p class="py-linenumber">1
2
3
4
5
</p><span class="py-src-variable">myref</span>.<span class="py-src-variable">callRemote</span>(<span class="py-src-string">"addUser"</span>, <span class="py-src-string">"bob"</span>, <span class="py-src-string">"555-1212"</span>)
<span class="py-src-comment"># on the remote end, the following method is invoked:</span>
<span class="py-src-keyword">def</span> <span class="py-src-identifier">addUser</span>(<span class="py-src-parameter">name</span>, <span class="py-src-parameter">phone</span>):
...
</pre>
<p>where <q>addUser</q> is the remote method name. The user might also
choose to call it with named parameters like this:</p>
<pre class="python"><p class="py-linenumber">1
</p><span class="py-src-variable">myref</span>.<span class="py-src-variable">callRemote</span>(<span class="py-src-string">"addUser"</span>, <span class="py-src-variable">name</span>=<span class="py-src-string">"bob"</span>, <span class="py-src-variable">phone</span>=<span class="py-src-string">"555-1212"</span>)
</pre>
<p>In this case, <code>callRemote</code> (and any code that uses the
<code class="python">**kwargs</code> syntax) must be careful to not use
<q>name</q>, <q>phone</q>, or any other name that might overlap with
a user-provided named parameter. Therefore, <code>callRemote</code> is
implemented with the following signature:</p>
<pre class="python"><p class="py-linenumber">1
2
3
</p><span class="py-src-keyword">class</span> <span class="py-src-identifier">SomeClass</span>(<span class="py-src-parameter">object</span>):
<span class="py-src-keyword">def</span> <span class="py-src-identifier">callRemote</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">_name</span>, *<span class="py-src-parameter">args</span>, **<span class="py-src-parameter">kw</span>):
...
</pre>
<p>Do whatever you can to reduce user confusion. It may also be
appropriate to <code class="python">assert</code> that the kwargs
dictionary does not contain parameters with names that will eventually
cause problems.</p>
<h2>Special Methods<a name="auto19"/></h2>
<p>The augmented assignment protocol, defined by <code class="python">__iadd__</code> 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.</p>
<h2>Functions<a name="auto20"/></h2>
<p>Functions should be named similiarly to methods.</p>
<p>Functions or methods which are responding to events to
complete a callback or errback should be named <code>_cbMethodName</code> or
<code>_ebMethodName</code>, in order to distinguish them from normal
methods.</p>
<h2>Attributes<a name="auto21"/></h2>
<p>Attributes should be named similarly to functions and
methods. Attributes should be named descriptively; attribute
names like <code>mode</code>, <code>type</code>, and
<code>buf</code> are generally discouraged. Instead, use
<code>displayMode</code>, <code>playerType</code>, or
<code>inputBuffer</code>.</p>
<p>Do not use Python's <q>private</q> 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.</p>
<p>An attribute (or function, method or class) should be
considered private when one or more of the following conditions
are true:</p>
<ul>
<li>The attribute represents intermediate state which is not
always kept up-to-date.</li>
<li>Referring to the contents of the attribute or otherwise
maintaining a reference to it may cause resources to
leak.</li>
<li>Assigning to the attribute will break internal
assumptions.</li>
<li>The attribute is part of a known-to-be-sub-optimal
interface and will certainly be removed in a future
release.</li>
</ul>
<h2>Database<a name="auto22"/></h2>
<p>Database tables will be named with plural nouns.</p>
<p>Database columns will be named with underscores between
words, all lower case, since most databases do not distinguish
between case.</p>
<p>Any attribute, method argument, or method name that
corresponds <em>directly</em> to a column in the database will
be named exactly the same as that column, regardless of other
coding conventions surrounding that circumstance.</p>
<p>All SQL keywords should be in upper case.</p>
<h2>C Code<a name="auto23"/></h2>
<p>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
<strong>must</strong> 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.</p>
<p>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.</p>
<h2 id="commits">Commit Messages<a name="auto24"/></h2>
<p>The commit messages are being distributed in a myriad of ways. Because
of that, you need to observe a few simple rules when writing a commit
message.</p>
<p>The first line of the message is being used as both the subject of
the commit email 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 <em>hard line breaks</em> into
short lines (< 70 characters). This is free-format, so you can do
whatever you like here.</p>
<p>Commit messages should be about <em>what</em>, not <em>how</em>: we can
get how from SVN diff. Explain reasons for commits, and what they
affect.</p>
<p>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.</p>
<h2>Source Control<a name="auto25"/></h2>
<p>Twisted currently uses Subversion for source control. All
development <strong>should</strong> occur using branches; when a task is
considered complete another Twisted developer may review it and if no
problems are found, it may be merged into trunk. The Twisted wiki has <a href="http://twistedmatrix.com/trac/wiki/TwistedDevelopment" shape="rect">a start</a>.
Branches <strong>must</strong> be used for major development. Branches
should be managed using <a href="http://divmod.org/trac/wiki/DivmodCombinator" shape="rect">Combinator</a> (but
if you can manage them in some other way without anyone noticing, knock
yourself out).</p>
<p>Certain features of Subversion should be avoided.</p>
<ul>
<li>
<p>Do not set the <code class="shell">svn:ignore</code> property on any
file or directory. What you wish to ignore, others may wish to examine.
What others may wish you ignore, <em>you</em> may wish you examine.
<code class="shell"> svn:ignore </code> will affect everyone who uses
the repository, and so it is not the right mechanism to express personal
preferences.</p>
<p>If you wish to ignore certain files use the <code class="shell">
global-ignores </code> feature of <code class="shell">
~/.subversion/config </code>, for example:</p>
<pre class="shell" xml:space="preserve">
[miscellany]
global-ignores = dropin.cache *.pyc *.pyo *.o *.lo *.la #*# .*.rej *.rej .*~
</pre>
</li>
</ul>
<h2>Fallback<a name="auto26"/></h2>
<p>In case of conventions not enforced in this document, the reference
documents to use in fallback is
<a href="http://www.python.org/dev/peps/pep-0008/" shape="rect">PEP 8</a> for Python
code and <a href="http://www.python.org/dev/peps/pep-0007/" shape="rect">PEP 7</a> for
C code. For example, the paragraph <strong>Whitespace in Expressions and
Statements</strong> in PEP 8 describes what should be done in Twisted
code.</p>
<h2>Recommendations<a name="auto27"/></h2>
<p>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.</p>
<p>If you're going to work on a fragment of the Twisted
codebase, please consider finding a way that you would <em>use</em>
such a fragment in daily life. Using a Twisted Web server on your
website encourages you to actively maintain and improve your code,
as the little everyday issues with using it become apparent.</p>
<p>Twisted is a <strong>big</strong> 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.</p>
</div>
<p><a href="../../howto/index.html">Index</a></p>
<span class="version">Version: 12.0.0</span>
</body>
</html>
|