.. _chapter-code-basics: =================== General Conventions =================== There are many ways to contribute to Sage including sharing scripts and Sage worksheets that implement new functionality using Sage, improving to the Sage library, or to working on the many underlying libraries distributed with Sage [1]_. This guide focuses on editing the Sage library itself. Sage is not just about gathering together functionality. It is about providing a clear, systematic and consistent way to access a large number of algorithms, in a coherent framework that makes sense mathematically. In the design of Sage, the semantics of objects, the definitions, etc., are informed by how the corresponding objects are used in everyday mathematics. .. [1] See http://www.sagemath.org/links-components.html for a full list of packages shipped with every copy of Sage To meet the goal of making Sage easy to read, maintain, and improve, all Python/Cython code that is included with Sage should adhere to the style conventions discussed in this chapter. .. _section-coding-python: Python Code Style ================= Follow the standard Python formatting rules when writing code for Sage, as explained at the following URLs: * http://www.python.org/dev/peps/pep-0008 * http://www.python.org/dev/peps/pep-0257 In particular, - Use 4 spaces for indentation levels. Do not use tabs as they can result in indentation confusion. Most editors have a feature that will insert 4 spaces when the tab key is hit. Also, many editors will automatically search/replace leading tabs with 4 spaces. - Whitespace before and after assignment and binary operator of the lowest priority in the expression:: i = i + 1 c = (a+b) * (a-b) - No whitespace before or after the = sign if it is used for keyword arguments:: def complex(real, imag=0.0): return magic(r=real, i=imag) - No whitespace immediately inside parenthesis, brackets, and braces:: spam(ham[1], {eggs: 2}) [i^2 for i in range(3)] - Use all lowercase function names with words separated by underscores. For example, you are encouraged to write Python functions using the naming convention:: def set_some_value(): return 1 Note, however, that some functions do have uppercase letters where it makes sense. For instance, the function for lattice reduction by the LLL algorithm is called Matrix_integer_dense.LLL. - Use CamelCase for class names:: class SomeValue(object): def __init__(self, x): self._x = 1 and factory functions that mimic object constructors, for example PolynomialRing or:: def SomeIdentityValue(x): return SomeValue(1) .. _chapter-directory-structure: Files and Directory Structure ============================= Roughly, the Sage directory tree is layout like this. Note that we use SAGE_ROOT in the following as a shortcut for the (arbitrary) name of the directory containing the Sage sources:: SAGE_ROOT/ sage # the Sage launcher Makefile # top level Makefile build/ # sage's build system deps install ... pkgs/ # install, patch, and metadata from spkgs src/ setup.py module_list.py ... sage/ # sage library (formerly devel/sage-main/sage) ext/ # extra sage resources (formerly devel/ext-main) mac-app/ # would no longer have to awkwardly be in extcode bin/ # the scripts in local/bin that are tracked upstream/ # tarballs of upstream sources local/ # installed binaries Python Sage library code goes into src/ and uses the following conventions. Directory names may be plural (e.g. rings) and file names are almost always singular (e.g. polynomial_ring.py). Note that the file polynomial_ring.py might still contain definitions of several different types of polynomial rings. .. NOTE:: You are encouraged to include miscellaneous notes, emails, design discussions, etc., in your package. Make these plain text files (with extension .txt) in a subdirectory called notes. For example, see SAGE_ROOT/src/sage/ext/notes/. If you want to create a new directory in the Sage library SAGE_ROOT/src/sage (say, measure_theory), that directory should contain a file __init__.py that contains the single line import all in addition to whatever files you want to add (say, borel_measure.py and banach_tarski.py), and also a file all.py listing imports from that directory that are important enough to be in the Sage’s global namespace at startup. The file all.py might look like this:: from borel_measure import BorelMeasure from banach_tarski import BanachTarskiParadox but it is generally better to use the lazy import framework:: from sage.misc.lazy_import import lazy_import lazy_import('sage.measure_theory.borel_measue', 'BorelMeasure') lazy_import('sage.measure_theory.banach_tarski', 'BanachTarskiParadox') Then in the file SAGE_ROOT/src/sage/all.py, add a line :: from sage.measure_theory.all import * Learn by copy/paste =================== For all of the conventions discussed here, you can find many examples in the Sage library. Browsing through the code is helpful, but so is searching: the functions search_src, search_def, and search_doc are worth knowing about. Briefly, from the "sage:" prompt, search_src(string) searches Sage library code for the string string. The command search_def(string) does a similar search, but restricted to function definitions, while search_doc(string) searches the Sage documentation. See their docstrings for more information and more options. Headings of Sage Library Code Files =================================== The top of each Sage code file should follow this format:: r""" AUTHORS: - YOUR NAME (2005-01-03): initial version - person (date in ISO year-month-day format): short desc EXAMPLES:: """ #***************************************************************************** # Copyright (C) 2013 YOUR NAME # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** As an example, see SAGE_ROOT/src/sage/rings/integer.pyx which contains the implementation for \ZZ. The AUTHORS: section is redundant, the authoritative log for who wrote what is always the git repository (see the output of git blame). Nevertheless, it is sometimes useful to have a very rough overview over the history, especially if a lot of people have been working on that source file. All code included with Sage must be licensed under the GPLv2+ or a compatible, that is, less restrictive license (e.g. the BSD license). .. _section-docstrings: Documentation Strings ===================== .. _section-docstring-function: The docstring of a function: content ------------------------------------- **Every** function must have a docstring that includes the following information. You can use the existing functions of Sage as templates. - A **one-sentence description** of the function. It must be followed by a blank line and end in a period. It describes the function or method's effect as a command ("Do this", "Return that"), not as a description like "Returns the pathname ...". - An **INPUT** and an **OUTPUT** block describing the input/output of the function. This is not optional. The INPUT block describes all arguments that the function accepts, and the OUTPUT section describes its expected output. 1. The type names should be descriptive, but do not have to represent the exact Sage/Python types. For example, use "integer" for anything that behaves like an integer, rather than int. 2. Mention the default values of the input arguments when applicable. Example:: INPUT: - p -- (default: 2) a positive prime integer. OUTPUT: A 5-tuple consisting of integers in this order: 1. the smallest primitive root modulo p 2. the smallest prime primitive root modulo p 3. the largest primitive root modulo p 4. the largest prime primitive root modulo p 5. total number of prime primitive roots modulo p You can start the OUTPUT block with a dash if you prefer:: OUTPUT: - The plaintext resulting from decrypting the ciphertext C using the Blum-Goldwasser decryption algorithm. - An **EXAMPLES** block for examples. This is not optional. These examples are used both for: 1. Documentation 2. Automatic testing before each release. They should have good coverage of the functionality in question. - A **SEEALSO** block (optional) with links to related parts of Sage. :: .. SEEALSO:: :ref:chapter-sage_manuals_links See :ref:chapter-sage_manuals_links for details on how to setup link in Sage. - An **ALGORITHM** block (optional). It indicates what algorithm and/or what software is used, e.g. ALGORITHM: Uses Pari. Here's a longer example with a bibliographical reference:: ALGORITHM: The following algorithm is adapted from page 89 of [Nat2000]_. Let p be an odd (positive) prime and let g be a generator modulo p. Then g^k is a generator modulo p if and only if \gcd(k, p-1) = 1. Since p is an odd prime and positive, then p - 1 is even so that any even integer between 1 and p - 1, inclusive, is not relatively prime to p - 1. We have now narrowed our search to all odd integers k between 1 and p - 1, inclusive. So now start with a generator g modulo an odd (positive) prime p. For any odd integer k between 1 and p - 1, inclusive, g^k is a generator modulo p if and only if \gcd(k, p-1) = 1. REFERENCES: .. [Nat2000] M.B. Nathanson. Elementary Methods in Number Theory. Springer, 2000. - A **NOTE** block for tips/tricks (optional). :: .. NOTE:: You should note that this sentence is indented at least 4 spaces. Never use the tab character. - A **WARNING** block for critical information about your code (optional). For example known situations for which the code breaks, or anything that the user should be aware of. :: .. WARNING:: Whenever you edit the Sage documentation, make sure that the edited version still builds. That is, you need to ensure that you can still build the HTML and PDF versions of the updated documentation. If the edited documentation fails to build, it is very likely that you would be requested to change your patch. - A **TODO** block for future improvements (optional). It can contain disabled doctests to demonstrate the desired feature. Here's an example of a TODO block:: .. TODO:: Add to have_fresh_beers an interface with the faster algorithm "Buy a Better Fridge" (BaBF):: sage: have_fresh_beers('Bière de l\'Yvette', algorithm="BaBF") # not implemented Enjoy ! - A **PLOT** block to illustrate with pictures the output of a function. Generate with Sage code an object g with a .plot method, then call sphinx_plot(g):: .. PLOT:: g = graphs.PetersenGraph() sphinx_plot(g) - A **REFERENCES** block to list related books or papers (optional) It should cite the books/research papers relevant to the code, e.g. the source of the algorithm that it implements. :: This docstring is referencing [SC]_. Just remember that references are global, so we can also reference to [Nat2000]_ in the ALGORITHM block, even if it is in a separate file. However we would not include the reference here since it would cause a conflict. REFERENCES: .. [SC] Conventions for coding in sage. http://www.sagemath.org/doc/developer/conventions.html. See the Sphinx/ReST markup for citations _. For links toward trac tickets or wikipedia, see :ref:chapter-sage_manuals_links. - A **TESTS** block (optional) Formatted just like EXAMPLES, containing tests that are not relevant to users. Template ^^^^^^^^ Use the following template when documenting functions. Note the indentation: .. skip # do not doctest :: def point(self, x=1, y=2): r""" Return the point (x^5,y). INPUT: - x -- integer (default: 1) the description of the argument x goes here. If it contains multiple lines, all the lines after the first need to begin at the same indentation as the backtick. - y -- integer (default: 2) the ... OUTPUT: The point as a tuple. .. SEEALSO:: :func:line EXAMPLES: This example illustrates ... :: sage: A = ModuliSpace() sage: A.point(2,3) xxx We now ... :: sage: B = A.point(5,6) sage: xxx It is an error to ...:: sage: C = A.point('x',7) Traceback (most recent call last): ... TypeError: unable to convert 'r' to an integer .. NOTE:: This function uses the algorithm of [BCDT]_ to determine whether an elliptic curve E over Q is modular. ... REFERENCES: .. [BCDT] Breuil, Conrad, Diamond, Taylor, "Modularity ...." """ You are strongly encouraged to: - Use LaTeX typesetting (see :ref:section-latex-typeset). - Liberally describe what the examples do. .. NOTE:: There must be a blank line after the example code and before the explanatory text for the next example (indentation is not enough). - Illustrate the exceptions raised by the function with examples (as given above: "It is an error to [..]", ...) - Include many examples. They are helpful for the users, and are crucial for the quality and adaptability of Sage. Without such examples, small changes to one part of Sage that break something else might not go seen until much later when someone uses the system, which is unacceptable. Private functions ^^^^^^^^^^^^^^^^^ Functions whose names start with an underscore are considered private. They do not appear in the reference manual, and their docstring should not contain any information that is crucial for Sage users. You can make their docstrings be part of the documentation of another method. For example:: class Foo(SageObject): def f(self): """ .. automethod:: _f """ return self._f() def _f(self): """ This would be hidden without the .. automethod:: """ Private functions should contain an EXAMPLES (or TESTS) block. A special case is the constructor __init__: due to its special status the __init__ docstring is used as the class docstring if there is not one already. That is, you can do the following:: sage: class Foo(SageObject): ....: # no class docstring ....: def __init__(self): ....: """Construct a Foo.""" sage: foo = Foo() sage: from sage.misc.sageinspect import sage_getdoc sage: sage_getdoc(foo) # class docstring 'Construct a Foo.\n' sage: sage_getdoc(foo.__init__) # constructor docstring 'Construct a Foo.\n' .. _section-latex-typeset: LaTeX Typesetting ----------------- In Sage's documentation LaTeX code is allowed and is marked with **backticks or dollar signs**: x^2 + y^2 = 1 and $x^2 + y^2 = 1$ both yield x^2 + y^2 = 1. **Backslashes:** For LaTeX commands containing backslashes, either use double backslashes or begin the docstring with a r""" instead of """. Both of the following are valid:: def cos(x): """ Return \\cos(x). """ def sin(x): r""" Return $\sin(x)$. """ **MATH block:** This is similar to the LaTeX syntax \[