Subsections

2. How to create a SAGE module

2.1 Overview

  1. Think about what your program will do and how that fits into the structure of SAGE. In particular, much of SAGE is implemented in the object-oriented language Python, and there is a hierachy of classes that organize code and functionality. It is surprisingly painful and difficult to create some Python classes, then realize that much functionality should be factored out into base classes, and to do it. So try to get the structure right the first time. For example, if you implement elements of a ring yoru class should derive from sage.structure.element.RingElement.

  2. Code it up, following the conventions in Chapter 3. Make the basic structure and interface for what you're doing in Python. You can use any of the following languages to implement the hard parts: Python, C/C++, Pyrex, GAP, Singular, and GP/PARI. You can also use the mwrank, NTL, and PARI C libraries. (And if you are OK with your code depending on optional SAGE packages, you can use Maxima, Octave, or even Magma, Mathematica, or Maple.) For readability and usability it is best to use SAGE when possible, but for efficiency reasons it is often crucial to use a compiled language or an existing library or program--do not reinvent the wheel or write code that is so slow as to be only a toy.

  3. Document every Python function that you've defined, and liberally include examples in your source code. See Chapter 4 for more on automated testing of examples.

  4. (Optional) Write a file that randomly tries to test (and break!) your code.

  5. (Optional) Send your package to me (wstein@gmail.com) for inclusion in SAGE, or make a standalone spkg (see Chapter 9).

2.2 Source Code Documentation

Use LaTeX formatting in the documentation string. If you wish to use backslashes in the documentation string, place an r right before the first triple opening quote, or use double backslashes. For example,
def sin(x):
    r"""
    Return $\sin(x)$.
    """

def cos(x):
    """
    Return $\\cos(x)$.
    """

The non-standard macros that are used when typesetting the documentation are defined in $SAGE_ROOT/doc/commontex/macros.tex. If you need to add more, add them there and send me (William Stein) an email so I can include them in the next version of SAGE.

The first line two or three lines of the docstring should briefly summarize what the function does, e.g., ``Returns X'' or ``Computes X'', or ``Creates a new X''. Next describe the input and output of the function using the following notation:

INPUT:
    var1 -- <type> (default: ...) description
    var2 -- <type> (default: ...) description
    etc.

OUTPUT: 
    <type> -- description of return value 1
    <type> -- description of return value 2
    etc.
For consistency you should use the above format, which is used throughout the system. Do not just describe the input and output in long sentences. For methods of a class, whether or not to describe self is up to you; this can be useful if self must have some special properties. Also, you do not have to specify the types of the input and output arguments precisely; e.g., use ``integer'' for an int or long or SAGE Integer.

Every function should have at least one, and preferably many, examples that illustrates its usage. These examples must exactly match the output of an actual running copy of Python. To test whether this is the case, run the program sage -t with your Python or Pyrex file as unique argument (see Chapter 4 for more details).

For more details, see Section 3.3.

2.3 Extra Documentation

You might also write additional documentation in LaTeX, which is not be part of any source code file. The examples in this documentation should be contained in verbatim environments. The examples should be tested using sage-testtex, which you run on the LaTeX file. Put %skip on the line proceeding the environment to skip testing of an example.

Note that sage-testtex is completely different than sage-doctest. It extracts the documentation and feeds it to a running instance of SAGE.

2.4 Randomized Testing

In addition to all the examples, which serve as both demonstrations and tests of your code, you should also create a test suite. Think of this as a program that will run for a while and ``tries'' to randomly crash your code. Your test code should define a class Test with a random() method that runs random tests. These are all assembled together later, and each test is run for a certain amount of time on a regular basis.

See About this document... for information on suggesting changes.