├── common ├── __init__.py ├── init.py ├── themes │ ├── sage │ │ ├── static │ │ │ ├── favicon.ico │ │ │ ├── sageicon.png │ │ │ ├── sagelogo.png │ │ │ ├── mathjax_sage.js_t │ │ │ └── sage.css_t │ │ ├── theme.conf │ │ ├── search.html │ │ └── layout.html │ └── sageref │ │ ├── static │ │ ├── favicon.ico │ │ ├── mathjax_sage.js_t │ │ └── sage.css_t │ │ ├── theme.conf │ │ └── layout.html └── conf.py ├── developer ├── static │ ├── flowchart.dia │ ├── meld-screenshot.png │ └── flowchart.svg ├── sagenb │ ├── pull_button.png │ ├── branch_dropdown.png │ ├── forking_button.png │ ├── links.inc │ ├── this_project.inc │ ├── github_development.rst │ ├── following_latest.rst │ ├── forking_hell.rst │ ├── known_projects.inc │ ├── index.rst │ ├── set_up_fork.rst │ ├── maintainer_workflow.rst │ ├── git_links.inc │ ├── patching.rst │ └── development_workflow.rst ├── conf.py ├── index.rst ├── git_setup.rst ├── workflows.rst ├── git_background.rst ├── sage_manuals.rst ├── packaging.rst ├── advanced_git.rst ├── walk_through.rst ├── coding_in_cython.rst └── coding_in_python.rst ├── .gitmodules ├── LICENSE ├── auto-build ├── .gitignore ├── README.md └── publish /common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /common/init.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /developer/static/flowchart.dia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/developer/static/flowchart.dia -------------------------------------------------------------------------------- /developer/sagenb/pull_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/developer/sagenb/pull_button.png -------------------------------------------------------------------------------- /developer/sagenb/branch_dropdown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/developer/sagenb/branch_dropdown.png -------------------------------------------------------------------------------- /developer/sagenb/forking_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/developer/sagenb/forking_button.png -------------------------------------------------------------------------------- /developer/static/meld-screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/developer/static/meld-screenshot.png -------------------------------------------------------------------------------- /common/themes/sage/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/common/themes/sage/static/favicon.ico -------------------------------------------------------------------------------- /common/themes/sage/static/sageicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/common/themes/sage/static/sageicon.png -------------------------------------------------------------------------------- /common/themes/sage/static/sagelogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/common/themes/sage/static/sagelogo.png -------------------------------------------------------------------------------- /common/themes/sageref/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sagemath/git-developer-guide/master/common/themes/sageref/static/favicon.ico -------------------------------------------------------------------------------- /developer/sagenb/links.inc: -------------------------------------------------------------------------------- 1 | .. compiling links file 2 | .. include:: known_projects.inc 3 | .. include:: this_project.inc 4 | .. include:: git_links.inc 5 | -------------------------------------------------------------------------------- /developer/sagenb/this_project.inc: -------------------------------------------------------------------------------- 1 | .. Sage Notebook 2 | .. _`Sage Notebook`: http://nb.sagemath.org 3 | .. _`Sage Notebook github`: http://github.com/sagemath/sagenb 4 | 5 | .. _`Sage Notebook mailing list`: http://groups.google.com/group/sage-notebook 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "sage-developer-git"] 2 | path = sage-developer-git 3 | url = git@github.com:vbraun/sage-developer-git.git 4 | branch = gh-pages 5 | [submodule "gh-pages"] 6 | path = gh-pages 7 | url = git@github.com:sagemath/git-developer-guide.git 8 | branch = gh-pages 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. -------------------------------------------------------------------------------- /developer/sagenb/github_development.rst: -------------------------------------------------------------------------------- 1 | .. _github-development: 2 | 3 | ===================== 4 | Git for development 5 | ===================== 6 | 7 | Contents: 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | forking_hell 13 | set_up_fork 14 | development_workflow 15 | maintainer_workflow 16 | -------------------------------------------------------------------------------- /auto-build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo "Watching for changes in developer/" 4 | 5 | while true ; do 6 | inotifywait -e close_write "developer/" 7 | if [ $? -ne 0 ] ; then 8 | echo "Error $? occured, exiting..." 9 | exit 1 10 | fi 11 | echo "Detected file save to $@" 12 | rm -rf html 13 | ./build 14 | done 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs 2 | *~ 3 | .\#* 4 | \#*\# 5 | 6 | html/ 7 | gh-pages/ 8 | 9 | *.py[cod] 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Packages 15 | *.egg 16 | *.egg-info 17 | dist 18 | eggs 19 | parts 20 | bin 21 | var 22 | sdist 23 | develop-eggs 24 | .installed.cfg 25 | lib 26 | lib64 27 | 28 | # Installer logs 29 | pip-log.txt 30 | 31 | # Unit test / coverage reports 32 | .coverage 33 | .tox 34 | nosetests.xml 35 | 36 | # Translations 37 | *.mo 38 | 39 | # Mr Developer 40 | .mr.developer.cfg 41 | .project 42 | .pydevproject 43 | -------------------------------------------------------------------------------- /common/themes/sage/static/mathjax_sage.js_t: -------------------------------------------------------------------------------- 1 | MathJax.Hub.Config({ 2 | imageFont: null, 3 | tex2jax: { 4 | inlineMath: [['$','$'],['\\(','\\)']], 5 | processEscapes: true, 6 | }, 7 | styles: { 8 | ".MathJax .mo, .MathJax .mi": { 9 | color: "inherit ! important" 10 | } 11 | }, 12 | TeX: { 13 | Macros: { 14 | {{ theme_mathjax_macros|join(',\n') }} 15 | } 16 | } 17 | }); 18 | 19 | // This path is a little funny because we have to load our local 20 | // config file as '../mathjax_sage' in the theme conf.py 21 | MathJax.Ajax.loadComplete("[MathJax]/config/../mathjax_sage.js") 22 | -------------------------------------------------------------------------------- /common/themes/sageref/static/mathjax_sage.js_t: -------------------------------------------------------------------------------- 1 | MathJax.Hub.Config({ 2 | imageFont: null, 3 | tex2jax: { 4 | inlineMath: [['$','$'],['\\(','\\)']], 5 | processEscapes: true, 6 | }, 7 | styles: { 8 | ".MathJax .mo, .MathJax .mi": { 9 | color: "inherit ! important" 10 | } 11 | }, 12 | TeX: { 13 | Macros: { 14 | {{ theme_mathjax_macros|join(',\n') }} 15 | } 16 | } 17 | }); 18 | 19 | // This path is a little funny because we have to load our local 20 | // config file as '../mathjax_sage' in the theme conf.py 21 | MathJax.Ajax.loadComplete("[MathJax]/config/../mathjax_sage.js") 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Git Version of the Sage Developer Manual 2 | ======================================== 3 | 4 | See the current documentation at http://sagemath.github.io/git-developer-guide/ 5 | 6 | 7 | Prerequisites 8 | ------------- 9 | 10 | To build the manual you need Python and Sphinx installed. If you have 11 | Sage, you can use a Sage shell (run `sage -sh`). 12 | 13 | 14 | 15 | Usage 16 | ----- 17 | 18 | * The developer manual is in the `/developer` directory in the 19 | repository root. Edit files there to modify the docs. 20 | 21 | * Use the `build` script to build the html documentation. 22 | 23 | * Use the `publish` script to copy the documentation to the github 24 | pages (the web page hosted on github). 25 | 26 | * Sphinx uses caching to only rebuild pages as necessary. Sometimes, 27 | you can get problems with stale caches. It is safe to delete the 28 | `/html` directory and then rebuild all docs with `./build`. 29 | -------------------------------------------------------------------------------- /developer/sagenb/following_latest.rst: -------------------------------------------------------------------------------- 1 | .. _following-latest: 2 | 3 | ============================= 4 | Following the latest source 5 | ============================= 6 | 7 | These are the instructions if you just want to follow the latest 8 | *Sage Notebook* source, but you don't need to do any development for now. 9 | 10 | The steps are: 11 | 12 | * :ref:`section-git-install` 13 | * get local copy of the `Sage Notebook github`_ git repository 14 | * update local copy from time to time 15 | 16 | Get the local copy of the code 17 | ============================== 18 | 19 | From the command line:: 20 | 21 | git clone git://github.com/sagemath/sagenb.git 22 | 23 | You now have a copy of the code tree in the new ``sagenb`` directory. 24 | 25 | Updating the code 26 | ================= 27 | 28 | From time to time you may want to pull down the latest code. Do this with:: 29 | 30 | cd sagenb 31 | git pull 32 | 33 | The tree in ``sagenb`` will now have the latest changes from the initial 34 | repository. 35 | 36 | .. include:: links.inc 37 | -------------------------------------------------------------------------------- /publish: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import os, shutil, subprocess, sys 4 | 5 | HTML_DIR = 'html' 6 | GH_PAGES_DIR = 'gh-pages' 7 | 8 | if not os.path.isdir(GH_PAGES_DIR): 9 | print 'Create a submodule in the gh-pages directory that contains the gh-pages branch' 10 | print 'For example:' 11 | print ' git submodule add -b gh-pages git@github.com:sagemath/git-developer-guide.git gh-pages' 12 | sys.exit(1) 13 | 14 | for src in os.listdir(HTML_DIR): 15 | src_file = os.path.join(HTML_DIR, src) 16 | dst_file = os.path.join(GH_PAGES_DIR, src) 17 | if os.path.isdir(src_file): 18 | if os.path.exists(dst_file): 19 | shutil.rmtree(dst_file) 20 | shutil.copytree(src_file, dst_file) 21 | else: 22 | shutil.copyfile(src_file, dst_file) 23 | 24 | 25 | os.chdir(GH_PAGES_DIR) 26 | subprocess.check_output(['git', 'add', '--all']) 27 | subprocess.check_output(['git', 'commit', '-m', '"Updated documentation"']) 28 | subprocess.check_output(['git', 'push', 'origin', 'HEAD:gh-pages']) 29 | 30 | 31 | -------------------------------------------------------------------------------- /developer/sagenb/forking_hell.rst: -------------------------------------------------------------------------------- 1 | .. _forking: 2 | 3 | ====================================================== 4 | Making your own copy (fork) of Sage Notebook 5 | ====================================================== 6 | 7 | You need to do this only once. The instructions here are very similar 8 | to the instructions at http://help.github.com/forking/ |emdash| please see 9 | that page for more detail. We're repeating some of it here just to give the 10 | specifics for the `Sage Notebook`_ project, and to suggest some default names. 11 | 12 | Set up and configure a github account 13 | ===================================== 14 | 15 | If you don't have a github account, go to the github page, and make one. 16 | 17 | You then need to configure your account to allow write access |emdash| see 18 | the ``Generating SSH keys`` help on `github help`_. 19 | 20 | Create your own forked copy of `Sage Notebook`_ 21 | ====================================================== 22 | 23 | #. Log into your github account. 24 | #. Go to the `Sage Notebook`_ github home at `Sage Notebook github`_. 25 | #. Click on the *fork* button: 26 | 27 | .. image:: forking_button.png 28 | 29 | Now, after a short pause, you should find yourself at the home 30 | page for your own forked copy of `Sage Notebook`_. 31 | 32 | .. include:: links.inc 33 | 34 | -------------------------------------------------------------------------------- /developer/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Sage Developer's Guide documentation build configuration file, created by 4 | # sphinx-quickstart on Sun Sep 14 01:32:19 2008. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # The contents of this file are pickled, so don't put values in the namespace 9 | # that aren't pickleable (module imports are okay, they're removed automatically). 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | sys.path.append(os.environ['SAGE_DOC']) 16 | from common.conf import * 17 | 18 | # General information about the project. 19 | project = u"Sage Developer's Guide" 20 | 21 | # The name for this set of Sphinx documents. If None, it defaults to 22 | # " v documentation". 23 | html_title = project + " v"+release 24 | name = 'developer' 25 | 26 | html_short_title = u"Developer's Guide v" + release 27 | 28 | # Output file base name for HTML help builder. 29 | htmlhelp_basename = name 30 | 31 | # Grouping the document tree into LaTeX files. List of tuples 32 | # (source start file, target name, title, author, document class [howto/manual]). 33 | latex_documents = [ 34 | ('index', name+'.tex', u'Sage Developer\'s Guide', 35 | u'The Sage Development Team', 'manual'), 36 | ] 37 | 38 | -------------------------------------------------------------------------------- /developer/sagenb/known_projects.inc: -------------------------------------------------------------------------------- 1 | .. Known projects 2 | 3 | .. PROJECTNAME placeholders 4 | .. _PROJECTNAME: http://neuroimaging.scipy.org 5 | .. _`PROJECTNAME github`: http://github.com/nipy 6 | .. _`PROJECTNAME mailing list`: http://projects.scipy.org/mailman/listinfo/nipy-devel 7 | 8 | .. numpy 9 | .. _numpy: hhttp://numpy.scipy.org 10 | .. _`numpy github`: http://github.com/numpy/numpy 11 | .. _`numpy mailing list`: http://mail.scipy.org/mailman/listinfo/numpy-discussion 12 | 13 | .. scipy 14 | .. _scipy: http://www.scipy.org 15 | .. _`scipy github`: http://github.com/scipy/scipy 16 | .. _`scipy mailing list`: http://mail.scipy.org/mailman/listinfo/scipy-dev 17 | 18 | .. nipy 19 | .. _nipy: http://nipy.org/nipy 20 | .. _`nipy github`: http://github.com/nipy/nipy 21 | .. _`nipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel 22 | 23 | .. ipython 24 | .. _ipython: http://ipython.scipy.org 25 | .. _`ipython github`: http://github.com/ipython/ipython 26 | .. _`ipython mailing list`: http://mail.scipy.org/mailman/listinfo/IPython-dev 27 | 28 | .. dipy 29 | .. _dipy: http://nipy.org/dipy 30 | .. _`dipy github`: http://github.com/Garyfallidis/dipy 31 | .. _`dipy mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel 32 | 33 | .. nibabel 34 | .. _nibabel: http://nipy.org/nibabel 35 | .. _`nibabel github`: http://github.com/nipy/nibabel 36 | .. _`nibabel mailing list`: http://mail.scipy.org/mailman/listinfo/nipy-devel 37 | 38 | .. marsbar 39 | .. _marsbar: http://marsbar.sourceforge.net 40 | .. _`marsbar github`: http://github.com/matthew-brett/marsbar 41 | .. _`MarsBaR mailing list`: https://lists.sourceforge.net/lists/listinfo/marsbar-users 42 | -------------------------------------------------------------------------------- /developer/index.rst: -------------------------------------------------------------------------------- 1 | 2 | ====================================== 3 | Welcome to the Sage Developer's Guide! 4 | ====================================== 5 | 6 | Everybody who uses Sage is encouraged to contribute something back to 7 | Sage at some point. Implement a new function, add examples to the 8 | documentation, find bugs and typos, fix a bug, create a new class, 9 | create a fast new C library, etc. This document describes how to write 10 | programs using Sage, how to modify and extend the core Sage libraries, 11 | and how to modify Sage's documentation. We also discuss how to share 12 | your new and modified code with other Sage users around the globe. 13 | 14 | .. toctree:: 15 | :maxdepth: 3 16 | 17 | walk_through 18 | git_setup 19 | trac 20 | 21 | 22 | Writing Code for Sage 23 | ===================== 24 | 25 | .. toctree:: 26 | :maxdepth: 3 27 | 28 | coding_basics 29 | coding_in_python 30 | coding_in_cython 31 | coding_in_other 32 | packaging 33 | packaging_old_spkgs 34 | doctesting 35 | sage_manuals 36 | 37 | 38 | 39 | Git and Sage Development 40 | ======================== 41 | 42 | .. toctree:: 43 | :maxdepth: 3 44 | 45 | git_background 46 | manual_git 47 | advanced_git 48 | workflows 49 | 50 | 51 | Sage Notebook Developer Guide 52 | ============================= 53 | 54 | .. toctree:: 55 | :maxdepth: 3 56 | 57 | sagenb/index 58 | 59 | 60 | Indices and tables 61 | ================== 62 | 63 | * :ref:`genindex` 64 | * :ref:`modindex` 65 | * :ref:`search` 66 | 67 | This work is licensed under a `Creative Commons Attribution-Share Alike 68 | 3.0 License `_. 69 | 70 | 71 | -------------------------------------------------------------------------------- /common/conf.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | 3 | extensions = ['sphinx.ext.inheritance_diagram', 'sphinx.ext.todo', 4 | 'sphinx.ext.extlinks', 'sphinx.ext.mathjax'] 5 | templates_path = [os.path.join(os.getcwd(), '..', 'common', 'themes'), 'templates'] 6 | # The suffix of source filenames. 7 | source_suffix = '.rst' 8 | # The master toctree document. 9 | master_doc = 'index' 10 | # General information about the project. 11 | project = u"" 12 | copyright = u'2013, The Sage Development Team' 13 | release = '1.0' 14 | default_role = 'math' 15 | pygments_style = 'sphinx' 16 | todo_include_todos = True 17 | 18 | pythonversion = sys.version.split(' ')[0] 19 | # Python and Sage trac ticket shortcuts. For example, :trac:`7549` . 20 | 21 | # Sage trac ticket shortcuts. For example, :trac:`7549` . 22 | extlinks = { 23 | 'python': ('http://docs.python.org/release/'+pythonversion+'/%s', ''), 24 | 'trac': ('http://trac.sagemath.org/%s', 'trac ticket #'), 25 | 'wikipedia': ('http://en.wikipedia.org/wiki/%s', 'Wikipedia article '), 26 | 'arxiv': ('http://arxiv.org/abs/%s', 'Arxiv '), 27 | 'oeis': ('http://oeis.org/%s', 'OEIS sequence '), 28 | 'doi': ('http://dx.doi.org/%s', 'doi:'), 29 | 'mathscinet': ('http://www.ams.org/mathscinet-getitem?mr=%s', 'MathSciNet ') 30 | } 31 | html_theme = 'sage' 32 | 33 | # Theme options are theme-specific and customize the look and feel of 34 | # a theme further. For a list of options available for each theme, 35 | # see the documentation. 36 | html_theme_options = {} 37 | html_favicon = 'favicon.ico' 38 | 39 | # Add any paths that contain custom themes here, relative to this directory. 40 | html_theme_path = [os.path.join(os.getcwd(), '..', 'common', 'themes')] 41 | 42 | -------------------------------------------------------------------------------- /common/themes/sage/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = default 3 | stylesheet = sage.css 4 | pygments_style = sphinx 5 | 6 | [options] 7 | # Custom Sage theme options 8 | 9 | # MathJax settings filled in by conf.py 10 | mathjax_macros = 11 | 12 | # Sphinx default theme options 13 | 14 | #nosidebar = false 15 | #rightsidebar = false 16 | #stickysidebar = false 17 | 18 | # Background color for the footer line: pale, light grayish blue (CSS color): 19 | footerbgcolor = #B8B9F6 20 | # Text color for the footer line: black (CSS color): 21 | footertextcolor = #000000 22 | # Background color for the sidebar: light bluish gray (CSS color): 23 | sidebarbgcolor = #EAEAF8 24 | # Text color for the sidebar: black (CSS color): 25 | sidebartextcolor = #000000 26 | # Link color for the sidebar: dark blue (CSS color): 27 | sidebarlinkcolor = #090999 28 | # Background color for the relation bar: pale, light grayish blue (CSS color): 29 | relbarbgcolor = #B8B9F6 30 | # Text color for the relation bar: black (CSS color): 31 | relbartextcolor = #000000 32 | # Link color for the relation bar: dark blue (CSS color): 33 | relbarlinkcolor = #090999 34 | # Body background color (CSS color): 35 | #bgcolor = #ffffff 36 | # Body text color: black (CSS color): 37 | textcolor = #000000 38 | # Background color for headings: light bluish gray (CSS color): 39 | headbgcolor = #EAEAF8 40 | # Text color for headings (CSS color): 41 | #headtextcolor = #20435c 42 | # Link color for headings (CSS color): 43 | #headlinkcolor = #c60f0f 44 | # Body link color: dark greenish blue (CSS color): 45 | linkcolor = #45529B 46 | # Background color for code blocks: very pale yellow (CSS color): 47 | codebgcolor = #FFFFE5 48 | # Default text color for code blocks, if not set differently by the highlighting style (CSS color): 49 | #codetextcolor = #333333 50 | 51 | # Font for normal text (CSS font-family): 52 | #bodyfont = sans-serif 53 | # Font for headings (CSS font-family): 54 | #headfont = 'Trebuchet MS', sans-serif 55 | -------------------------------------------------------------------------------- /common/themes/sageref/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = default 3 | stylesheet = sage.css 4 | pygments_style = sphinx 5 | 6 | [options] 7 | # Custom Sage theme options 8 | 9 | # MathJax settings filled in by conf.py 10 | mathjax_macros = 11 | 12 | # Sphinx default theme options 13 | 14 | #nosidebar = false 15 | #rightsidebar = false 16 | #stickysidebar = false 17 | 18 | # Background color for the footer line: pale, light grayish blue (CSS color): 19 | footerbgcolor = #B8B9F6 20 | # Text color for the footer line: black (CSS color): 21 | footertextcolor = #000000 22 | # Background color for the sidebar: light bluish gray (CSS color): 23 | sidebarbgcolor = #EAEAF8 24 | # Text color for the sidebar: black (CSS color): 25 | sidebartextcolor = #000000 26 | # Link color for the sidebar: dark blue (CSS color): 27 | sidebarlinkcolor = #090999 28 | # Background color for the relation bar: pale, light grayish blue (CSS color): 29 | relbarbgcolor = #B8B9F6 30 | # Text color for the relation bar: black (CSS color): 31 | relbartextcolor = #000000 32 | # Link color for the relation bar: dark blue (CSS color): 33 | relbarlinkcolor = #090999 34 | # Body background color (CSS color): 35 | #bgcolor = #ffffff 36 | # Body text color: black (CSS color): 37 | textcolor = #000000 38 | # Background color for headings: light bluish gray (CSS color): 39 | headbgcolor = #EAEAF8 40 | # Text color for headings (CSS color): 41 | #headtextcolor = #20435c 42 | # Link color for headings (CSS color): 43 | #headlinkcolor = #c60f0f 44 | # Body link color: dark greenish blue (CSS color): 45 | linkcolor = #45529B 46 | # Background color for code blocks: very pale yellow (CSS color): 47 | codebgcolor = #FFFFE5 48 | # Default text color for code blocks, if not set differently by the highlighting style (CSS color): 49 | #codetextcolor = #333333 50 | 51 | # Font for normal text (CSS font-family): 52 | #bodyfont = sans-serif 53 | # Font for headings (CSS font-family): 54 | #headfont = 'Trebuchet MS', sans-serif 55 | -------------------------------------------------------------------------------- /developer/sagenb/index.rst: -------------------------------------------------------------------------------- 1 | .. _sagenb: 2 | 3 | ============================= 4 | Sage Notebook Developer Guide 5 | ============================= 6 | 7 | 8 | Development of the Sage notebook currently occurs on Github using the 9 | Git revision control system. The development model for the `Sage 10 | Notebook`_ project is a `git `_ and github_ 11 | workflow. 12 | 13 | To update to the latest development source, run the commands below, 14 | where ``SAGE_ROOT`` is the root directory of the Sage installation, 15 | and where ``hackdir`` is a directory you create for working on code 16 | changes (it need not have the name or location given below). 17 | 18 | .. warning:: This will create a new sagenb repository ignoring any 19 | changes you have made to the files. 20 | 21 | :: 22 | 23 | mkdir ~/hackdir 24 | cd ~/hackdir 25 | git clone git://github.com/sagemath/sagenb.git sagenb-git 26 | cd SAGE_ROOT/devel 27 | rm sagenb 28 | ln -s ~/hackdir/sagenb sagenb 29 | cd sagenb 30 | ../../sage setup.py develop 31 | 32 | What this has done is to create a new directory, move to that 33 | directory, and create a clone of the most up-to-date version of 34 | the upstream notebook sources there. Then we remove a symbolic 35 | link ``sagenb`` in the Sage folder and replace it with a link 36 | to your clone of upstream, finally making sure that the notebook 37 | has the correct dependencies. 38 | 39 | An advantage of having the separate directory for sagenb is that 40 | you would later be able to keep it and do development work in it 41 | even when you upgrade Sage, or even if you accidentally destroy your 42 | Sage installation somehow. 43 | 44 | The rest of these instructions is some very generic documentation, 45 | slightly adapted to help develop the notebook using Git and Github. 46 | 47 | The most important section involves how to update your new sagenb 48 | source repository and create a "fork" of the master copy, so that you 49 | will be able to request your changes to be merged in the Sage notebook, 50 | called a "pull request"; see :ref:`github-development`. 51 | 52 | 53 | .. toctree:: 54 | :maxdepth: 2 55 | 56 | following_latest 57 | patching 58 | github_development 59 | 60 | 61 | .. include:: links.inc 62 | -------------------------------------------------------------------------------- /common/themes/sage/search.html: -------------------------------------------------------------------------------- 1 | {# 2 | basic/search.html 3 | ~~~~~~~~~~~~~~~~~ 4 | 5 | Template for the search page. 6 | 7 | :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. 8 | :license: BSD, see LICENSE for details. 9 | #} 10 | {% extends "layout.html" %} 11 | {% set title = _('Search') %} 12 | {% set script_files = script_files + ['_static/searchtools.js'] %} 13 | {% block extrahead %} 14 | 17 | {{ super() }} 18 | {% endblock %} 19 | {% block body %} 20 |

{{ _('Search') }}

21 |
22 | 23 |

24 | {% trans %}Please activate JavaScript to enable the search 25 | functionality.{% endtrans %} 26 |

27 |
28 |

29 | {% trans %}From here you can search these documents. Enter your search 30 | words into the box below and click "search". Note that the search 31 | function will automatically search for all of the words. Pages 32 | containing fewer words won't appear in the result list.{% endtrans %} 33 |

34 |

35 | {% trans %}Note also that you can also call "search_src(...)" 36 | while running Sage to search Sage's source code. You can also 37 | browse Sage's source code by calling "hg_sage.serve()" while running 38 | Sage.{% endtrans %} 39 |

40 |
41 | 42 | 43 | 44 |
45 | {% if search_performed %} 46 |

{{ _('Search Results') }}

47 | {% if not search_results %} 48 |

{{ _('Your search did not match any results.') }}

49 | {% endif %} 50 | {% endif %} 51 |
52 | {% if search_results %} 53 |
    54 | {% for href, caption, context in search_results %} 55 |
  • {{ caption }} 56 |
    {{ context|e }}
    57 |
  • 58 | {% endfor %} 59 |
60 | {% endif %} 61 |
62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /developer/sagenb/set_up_fork.rst: -------------------------------------------------------------------------------- 1 | .. _set-up-fork: 2 | 3 | ================== 4 | Set up your fork 5 | ================== 6 | 7 | First you follow the instructions for :ref:`forking`. 8 | 9 | Overview 10 | ======== 11 | 12 | :: 13 | 14 | git clone git@github.com:your-user-name/sagenb.git 15 | cd sagenb 16 | git remote add upstream git://github.com/sagemath/sagenb.git 17 | 18 | In detail 19 | ========= 20 | 21 | Clone your fork 22 | --------------- 23 | 24 | #. Clone your fork to the local computer with ``git clone 25 | git@github.com:your-user-name/sagenb.git`` 26 | #. Investigate. Change directory to your new repo: ``cd sagenb``. Then 27 | ``git branch -a`` to show you all branches. You'll get something 28 | like:: 29 | 30 | * master 31 | remotes/origin/master 32 | 33 | This tells you that you are currently on the ``master`` branch, and 34 | that you also have a ``remote`` connection to ``origin/master``. 35 | What remote repository is ``remote/origin``? Try ``git remote -v`` to 36 | see the URLs for the remote. They will point to your github fork. 37 | 38 | Now you want to connect to the upstream `Sage Notebook github`_ repository, so 39 | you can merge in changes from trunk. 40 | 41 | .. _linking-to-upstream: 42 | 43 | Linking your repository to the upstream repo 44 | -------------------------------------------- 45 | 46 | :: 47 | 48 | cd sagenb 49 | git remote add upstream git://github.com/sagemath/sagenb.git 50 | 51 | ``upstream`` here is just the arbitrary name we're using to refer to the 52 | main `Sage Notebook`_ repository at `Sage Notebook github`_. 53 | 54 | Note that we've used ``git://`` for the URL rather than ``git@``. The 55 | ``git://`` URL is read only. This means we that we can't accidentally 56 | (or deliberately) write to the upstream repo, and we are only going to 57 | use it to merge into our own code. 58 | 59 | Just for your own satisfaction, show yourself that you now have a new 60 | 'remote', with ``git remote -v show``, giving you something like:: 61 | 62 | upstream git://github.com/sagemath/sagenb.git (fetch) 63 | upstream git://github.com/sagemath/sagenb.git (push) 64 | origin git@github.com:your-user-name/sagenb.git (fetch) 65 | origin git@github.com:your-user-name/sagenb.git (push) 66 | 67 | .. include:: links.inc 68 | 69 | -------------------------------------------------------------------------------- /developer/git_setup.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-git-setup: 2 | 3 | ============== 4 | Setting Up Git 5 | ============== 6 | 7 | To work on the Sage source code, you need 8 | 9 | * a working git installation, see :ref:`section-git-install`. Sage 10 | actually comes with git, see below. However, it is recommended that 11 | you have a system-wide install if only to save you some typing. 12 | 13 | * configure git to use your name and email address for commits, see 14 | :ref:`section-git-setup-name`. The Sage development scripts will 15 | prompt you if you don't. But, especially if you use git for other 16 | projects in the future as well, you really should configure git. 17 | 18 | The :ref:`chapter-git-background` chapter contains further information 19 | about git that might be useful to some but are not required. 20 | 21 | 22 | .. _section-git-install: 23 | 24 | Installing Git 25 | -------------- 26 | 27 | First, try ``git`` on the command line. Most distributions will have 28 | it installed by default if other development tools are installed. If 29 | that fails, use the following to install git: 30 | 31 | Debian / Ubuntu 32 | ``sudo apt-get install git-core`` 33 | 34 | Fedora 35 | ``sudo yum install git-core`` 36 | 37 | Windows 38 | Download and install `msysGit 39 | `_ 40 | 41 | OS X 42 | Use the `git OSX installer 43 | `_ 44 | 45 | Finally, Sage includes git. Obviously there is a chicken-and-egg 46 | problem to checkout the Sage source code from its git repository, but 47 | one can always download a Sage source tarball or binary 48 | distribution. You can then run git via the ``sage -git`` command line 49 | switch. So, for example, ``git help`` becomes ``sage -git help`` and 50 | so on. Note that the examples in the developer guide will assume that 51 | you have a system-wide git installation. 52 | 53 | Some further resources for installation help are: 54 | 55 | * `Chapter 2 of the git book 56 | `_ 57 | 58 | * The `git homepage `_ for the most recent 59 | information. 60 | 61 | * `Github install help pages `_ 62 | 63 | 64 | .. _section-git-setup-name: 65 | 66 | Your Name and Email 67 | ------------------- 68 | 69 | The commit message of any change contains your name and email address 70 | to acknowledge your contribution and to have a point of contact if 71 | there are questions in the future; Filling it in is required if you 72 | want to share your changes. The simplest way to do this is from the 73 | command line:: 74 | 75 | [user@localhost ~] git config --global user.name "Your Name" 76 | [user@localhost ~] git config --global user.email you@yourdomain.example.com 77 | 78 | This will write the settings into your :ref:`git configuration file 79 | ` with your name and email:: 80 | 81 | [user] 82 | name = Your Name 83 | email = you@yourdomain.example.com 84 | 85 | Of course you'll need to replace ``Your Name`` and ``you@yourdomain.example.com`` 86 | with your actual name and email address. 87 | -------------------------------------------------------------------------------- /developer/sagenb/maintainer_workflow.rst: -------------------------------------------------------------------------------- 1 | .. _maintainer-workflow: 2 | 3 | ################### 4 | Maintainer workflow 5 | ################### 6 | 7 | This page is for maintainers |emdash| those of us who merge our own or other 8 | peoples' changes into the upstream repository. 9 | 10 | Being as how you're a maintainer, you are completely on top of the basic stuff 11 | in :ref:`development-workflow`. 12 | 13 | The instructions in :ref:`linking-to-upstream` add a remote that has read-only 14 | access to the upstream repo. Being a maintainer, you've got read-write access. 15 | 16 | It's good to have your upstream remote have a scary name, to remind you that 17 | it's a read-write remote:: 18 | 19 | git remote add upstream-rw git@github.com:sagemath/sagenb.git 20 | git fetch upstream-rw 21 | 22 | ******************* 23 | Integrating changes 24 | ******************* 25 | 26 | Let's say you have some changes that need to go into trunk 27 | (``upstream-rw/master``). 28 | 29 | The changes are in some branch that you are currently on. For example, you are 30 | looking at someone's changes like this:: 31 | 32 | git remote add someone git://github.com/someone/sagenb.git 33 | git fetch someone 34 | git branch cool-feature --track someone/cool-feature 35 | git checkout cool-feature 36 | 37 | So now you are on the branch with the changes to be incorporated upstream. The 38 | rest of this section assumes you are on this branch. 39 | 40 | A few commits 41 | ============= 42 | 43 | If there are only a few commits, consider rebasing to upstream:: 44 | 45 | # Fetch upstream changes 46 | git fetch upstream-rw 47 | # rebase 48 | git rebase upstream-rw/master 49 | 50 | Remember that, if you do a rebase, and push that, you'll have to close any 51 | github pull requests manually, because github will not be able to detect the 52 | changes have already been merged. 53 | 54 | A long series of commits 55 | ======================== 56 | 57 | If there are a longer series of related commits, consider a merge instead:: 58 | 59 | git fetch upstream-rw 60 | git merge --no-ff upstream-rw/master 61 | 62 | The merge will be detected by github, and should close any related pull requests 63 | automatically. 64 | 65 | Note the ``--no-ff`` above. This forces git to make a merge commit, rather than 66 | doing a fast-forward, so that these set of commits branch off trunk then rejoin 67 | the main history with a merge, rather than appearing to have been made directly 68 | on top of trunk. 69 | 70 | Check the history 71 | ================= 72 | 73 | Now, in either case, you should check that the history is sensible and you have 74 | the right commits:: 75 | 76 | git log --oneline --graph 77 | git log -p upstream-rw/master.. 78 | 79 | The first line above just shows the history in a compact way, with a text 80 | representation of the history graph. The second line shows the log of commits 81 | excluding those that can be reached from trunk (``upstream-rw/master``), and 82 | including those that can be reached from current HEAD (implied with the ``..`` 83 | at the end). So, it shows the commits unique to this branch compared to trunk. 84 | The ``-p`` option shows the diff for these commits in patch form. 85 | 86 | Push to trunk 87 | ============= 88 | 89 | :: 90 | 91 | git push upstream-rw my-new-feature:master 92 | 93 | This pushes the ``my-new-feature`` branch in this repository to the ``master`` 94 | branch in the ``upstream-rw`` repository. 95 | 96 | .. include:: links.inc 97 | -------------------------------------------------------------------------------- /developer/sagenb/git_links.inc: -------------------------------------------------------------------------------- 1 | .. This (-*- rst -*-) format file contains commonly used link targets 2 | and name substitutions. It may be included in many files, 3 | therefore it should only contain link targets and name 4 | substitutions. Try grepping for "^\.\. _" to find plausible 5 | candidates for this list. 6 | 7 | .. NOTE: reST targets are 8 | __not_case_sensitive__, so only one target definition is needed for 9 | nipy, NIPY, Nipy, etc... 10 | 11 | .. git stuff 12 | .. _github: http://github.com 13 | .. _github help: http://help.github.com 14 | .. _msysgit: http://code.google.com/p/msysgit/downloads/list 15 | .. _git-osx-installer: http://code.google.com/p/git-osx-installer/downloads/list 16 | .. _subversion: http://subversion.tigris.org/ 17 | .. _git cheat sheet: http://github.com/guides/git-cheat-sheet 18 | .. _pro git book: http://progit.org/ 19 | .. _git svn crash course: http://git-scm.com/course/svn.html 20 | .. _learn.github: http://learn.github.com/ 21 | .. _network graph visualizer: http://github.com/blog/39-say-hello-to-the-network-graph-visualizer 22 | .. _git user manual: http://schacon.github.com/git/user-manual.html 23 | .. _git tutorial: http://schacon.github.com/git/gittutorial.html 24 | .. _git community book: http://book.git-scm.com/ 25 | .. _git ready: http://www.gitready.com/ 26 | .. _git casts: http://www.gitcasts.com/ 27 | .. _Fernando's git page: http://www.fperez.org/py4science/git.html 28 | .. _git magic: http://www-cs-students.stanford.edu/~blynn/gitmagic/index.html 29 | .. _git concepts: http://www.eecs.harvard.edu/~cduan/technical/git/ 30 | .. _git clone: http://schacon.github.com/git/git-clone.html 31 | .. _git checkout: http://schacon.github.com/git/git-checkout.html 32 | .. _git commit: http://schacon.github.com/git/git-commit.html 33 | .. _git push: http://schacon.github.com/git/git-push.html 34 | .. _git pull: http://schacon.github.com/git/git-pull.html 35 | .. _git add: http://schacon.github.com/git/git-add.html 36 | .. _git status: http://schacon.github.com/git/git-status.html 37 | .. _git diff: http://schacon.github.com/git/git-diff.html 38 | .. _git log: http://schacon.github.com/git/git-log.html 39 | .. _git branch: http://schacon.github.com/git/git-branch.html 40 | .. _git remote: http://schacon.github.com/git/git-remote.html 41 | .. _git rebase: http://schacon.github.com/git/git-rebase.html 42 | .. _git config: http://schacon.github.com/git/git-config.html 43 | .. _why the -a flag?: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html 44 | .. _git staging area: http://www.gitready.com/beginner/2009/01/18/the-staging-area.html 45 | .. _tangled working copy problem: http://tomayko.com/writings/the-thing-about-git 46 | .. _git management: http://kerneltrap.org/Linux/Git_Management 47 | .. _linux git workflow: http://www.mail-archive.com/dri-devel@lists.sourceforge.net/msg39091.html 48 | .. _git parable: http://tom.preston-werner.com/2009/05/19/the-git-parable.html 49 | .. _git foundation: http://matthew-brett.github.com/pydagogue/foundation.html 50 | .. _deleting master on github: http://matthew-brett.github.com/pydagogue/gh_delete_master.html 51 | .. _rebase without tears: http://matthew-brett.github.com/pydagogue/rebase_without_tears.html 52 | .. _resolving a merge: http://schacon.github.com/git/user-manual.html#resolving-a-merge 53 | .. _ipython git workflow: http://mail.scipy.org/pipermail/ipython-dev/2010-October/006746.html 54 | 55 | .. other stuff 56 | .. _python: http://www.python.org 57 | 58 | .. |emdash| unicode:: U+02014 59 | 60 | .. vim: ft=rst 61 | -------------------------------------------------------------------------------- /developer/sagenb/patching.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | Making a patch 3 | ================ 4 | 5 | You've discovered a bug or something else you want to change 6 | in `Sage Notebook`_ |emdash| excellent! 7 | 8 | You've worked out a way to fix it |emdash| even better! 9 | 10 | You want to tell us about it |emdash| best of all! 11 | 12 | The easiest way is to make a *patch* or set of patches. Here 13 | we explain how. 14 | 15 | Making a patch is simple and quick, but it is not part of our 16 | normal workflow. So if you are going to be doing anything more 17 | than a once-off patch one time, please consider following the 18 | :ref:`github-development` model instead. See especially the part 19 | about "pull requests" at :ref:`edit-flow`. 20 | 21 | .. _making-patches: 22 | 23 | Making patches 24 | ============== 25 | 26 | Overview 27 | -------- 28 | 29 | :: 30 | 31 | # tell git who you are 32 | git config --global user.email you@yourdomain.example.com 33 | git config --global user.name "Your Name Comes Here" 34 | # get the repository if you don't have it 35 | git clone git://github.com/sagemath/sagenb.git 36 | # make a branch for your patching 37 | cd sagenb 38 | git branch the-fix-im-thinking-of 39 | git checkout the-fix-im-thinking-of 40 | # hack, hack, hack 41 | # Tell git about any new files you've made 42 | git add somewhere/tests/test_my_bug.py 43 | # commit work in progress as you go 44 | git commit -am 'BF - added tests for Funny bug' 45 | # hack hack, hack 46 | git commit -am 'BF - added fix for Funny bug' 47 | # make the patch files 48 | git format-patch -M -C master 49 | 50 | You may attach a short generated patch file to the `Sage Notebook 51 | mailing list`_ or better, open an issue at the `Sage Notebook github`_ 52 | site (see :ref:`github-development`) and cut and paste your patch in a 53 | comment there. In either case we will thank you warmly. 54 | 55 | In detail 56 | --------- 57 | 58 | #. Tell git who you are so it can label the commits you've 59 | made:: 60 | 61 | git config --global user.email you@yourdomain.example.com 62 | git config --global user.name "Your Name Comes Here" 63 | 64 | #. If you don't already have one, clone a copy of the 65 | `Sage Notebook`_ repository:: 66 | 67 | git clone git://github.com/sagemath/sagenb.git 68 | cd sagenb 69 | 70 | #. Make a 'feature branch'. This will be where you work on 71 | your bug fix. It's nice and safe and leaves you with 72 | access to an unmodified copy of the code in the main 73 | branch:: 74 | 75 | git branch the-fix-im-thinking-of 76 | git checkout the-fix-im-thinking-of 77 | 78 | #. Do some edits, and commit them as you go:: 79 | 80 | # hack, hack, hack 81 | # Tell git about any new files you've made 82 | git add somewhere/tests/test_my_bug.py 83 | # commit work in progress as you go 84 | git commit -am 'BF - added tests for Funny bug' 85 | # hack hack, hack 86 | git commit -am 'BF - added fix for Funny bug' 87 | 88 | Note the ``-am`` options to ``commit``. The ``m`` flag just 89 | signals that you're going to type a message on the command 90 | line. The ``a`` flag |emdash| you can just take on faith |emdash| 91 | or see `why the -a flag?`_. 92 | 93 | #. When you have finished, check you have committed all your 94 | changes:: 95 | 96 | git status 97 | 98 | #. Finally, make your commits into patches. You want all the 99 | commits since you branched from the ``master`` branch:: 100 | 101 | git format-patch -M -C master 102 | 103 | You will now have several files named for the commits:: 104 | 105 | 0001-BF-added-tests-for-Funny-bug.patch 106 | 0002-BF-added-fix-for-Funny-bug.patch 107 | 108 | Although some projects would have you send these files to 109 | the `Sage Notebook mailing list`_, we prefer submitting an issue 110 | request at the web interface to the `Sage Notebook github`_ 111 | page. See :ref:`edit-flow` for how to create a "pull request" once you 112 | have created a Github account. 113 | 114 | When you are done, to switch back to the main copy of the 115 | code, just return to the ``master`` branch:: 116 | 117 | git checkout master 118 | 119 | Moving from patching to development 120 | =================================== 121 | 122 | If you find you have done some patches, and you have one or 123 | more feature branches, you will probably want to switch to 124 | development mode. You can do this with the repository you 125 | have. 126 | 127 | Fork the `Sage Notebook`_ repository on github |emdash| :ref:`forking`. 128 | Then:: 129 | 130 | # checkout and refresh master branch from main repo 131 | git checkout master 132 | git pull origin master 133 | # rename pointer to main repository to 'upstream' 134 | git remote rename origin upstream 135 | # point your repo to default read / write to your fork on github 136 | git remote add origin git@github.com:your-user-name/sagenb.git 137 | # push up any branches you've made and want to keep 138 | git push origin the-fix-im-thinking-of 139 | 140 | Then you can, if you want, follow the 141 | :ref:`development-workflow`. 142 | 143 | .. include:: links.inc 144 | -------------------------------------------------------------------------------- /common/themes/sageref/static/sage.css_t: -------------------------------------------------------------------------------- 1 | /** 2 | * Sage stylesheet theme. This stylesheet is heavily borrowed from the 3 | * Sphinx stylesheet default theme distributed as the file 4 | * themes/default/static/default.css_t in Sphinx 0.6.3. 5 | */ 6 | 7 | @import url("basic.css"); 8 | 9 | /* -- page layout ----------------------------------------------------------- */ 10 | 11 | body { 12 | font-family: {{ theme_bodyfont }}; 13 | font-size: 100%; 14 | background-color: {{ theme_footerbgcolor }}; 15 | color: #000; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | div.document { 21 | background-color: {{ theme_sidebarbgcolor }}; 22 | } 23 | 24 | div.documentwrapper { 25 | float: left; 26 | width: 100%; 27 | } 28 | 29 | div.bodywrapper { 30 | margin: 0 0 0 230px; 31 | } 32 | 33 | div.body { 34 | background-color: {{ theme_bgcolor }}; 35 | color: {{ theme_textcolor }}; 36 | padding: 0 20px 30px 20px; 37 | } 38 | 39 | {%- if theme_rightsidebar|tobool %} 40 | div.bodywrapper { 41 | margin: 0 230px 0 0; 42 | } 43 | {%- endif %} 44 | 45 | div.footer { 46 | color: {{ theme_footertextcolor }}; 47 | width: 100%; 48 | padding: 9px 0 9px 0; 49 | text-align: center; 50 | font-size: 75%; 51 | } 52 | 53 | div.footer a { 54 | color: {{ theme_footertextcolor }}; 55 | text-decoration: underline; 56 | } 57 | 58 | div.related { 59 | background-color: {{ theme_relbarbgcolor }}; 60 | line-height: 30px; 61 | color: {{ theme_relbartextcolor }}; 62 | } 63 | 64 | div.related a { 65 | color: {{ theme_relbarlinkcolor }}; 66 | } 67 | 68 | div.sphinxsidebar { 69 | {%- if theme_stickysidebar|tobool %} 70 | top: 30px; 71 | margin: 0; 72 | position: fixed; 73 | overflow: auto; 74 | height: 100%; 75 | {%- endif %} 76 | {%- if theme_rightsidebar|tobool %} 77 | float: right; 78 | {%- if theme_stickysidebar|tobool %} 79 | right: 0; 80 | {%- endif %} 81 | {%- endif %} 82 | } 83 | 84 | {%- if theme_stickysidebar|tobool %} 85 | /* this is nice, but it it leads to hidden headings when jumping 86 | to an anchor */ 87 | /* 88 | div.related { 89 | position: fixed; 90 | } 91 | 92 | div.documentwrapper { 93 | margin-top: 30px; 94 | } 95 | */ 96 | {%- endif %} 97 | 98 | div.sphinxsidebar h3 { 99 | font-family: {{ theme_headfont }}; 100 | color: {{ theme_sidebartextcolor }}; 101 | font-size: 1.4em; 102 | font-weight: normal; 103 | margin: 0; 104 | padding: 0; 105 | } 106 | 107 | div.sphinxsidebar h3 a { 108 | color: {{ theme_sidebartextcolor }}; 109 | } 110 | 111 | div.sphinxsidebar h4 { 112 | font-family: {{ theme_headfont }}; 113 | color: {{ theme_sidebartextcolor }}; 114 | font-size: 1.3em; 115 | font-weight: normal; 116 | margin: 5px 0 0 0; 117 | padding: 0; 118 | } 119 | 120 | div.sphinxsidebar p { 121 | color: {{ theme_sidebartextcolor }}; 122 | } 123 | 124 | div.sphinxsidebar p.topless { 125 | margin: 5px 10px 10px 10px; 126 | } 127 | 128 | div.sphinxsidebar ul { 129 | margin: 10px; 130 | padding: 0; 131 | color: {{ theme_sidebartextcolor }}; 132 | } 133 | 134 | div.sphinxsidebar a { 135 | color: {{ theme_sidebarlinkcolor }}; 136 | } 137 | 138 | div.sphinxsidebar input { 139 | border: 1px solid {{ theme_sidebarlinkcolor }}; 140 | font-family: sans-serif; 141 | font-size: 1em; 142 | } 143 | 144 | /* -- body styles ----------------------------------------------------------- */ 145 | 146 | a { 147 | color: {{ theme_linkcolor }}; 148 | text-decoration: none; 149 | } 150 | 151 | a:hover { 152 | text-decoration: underline; 153 | } 154 | 155 | div.body p, div.body dd, div.body li { 156 | text-align: justify; 157 | line-height: 130%; 158 | } 159 | 160 | div.body h1, 161 | div.body h2, 162 | div.body h3, 163 | div.body h4, 164 | div.body h5, 165 | div.body h6 { 166 | font-family: {{ theme_headfont }}; 167 | background-color: {{ theme_headbgcolor }}; 168 | font-weight: normal; 169 | color: {{ theme_headtextcolor }}; 170 | border-bottom: 1px solid #ccc; 171 | margin: 20px -20px 10px -20px; 172 | padding: 3px 0 3px 10px; 173 | } 174 | 175 | div.body h1 { margin-top: 0; font-size: 200%; } 176 | div.body h2 { font-size: 160%; } 177 | div.body h3 { font-size: 140%; } 178 | div.body h4 { font-size: 120%; } 179 | div.body h5 { font-size: 110%; } 180 | div.body h6 { font-size: 100%; } 181 | 182 | a.headerlink { 183 | color: {{ theme_headlinkcolor }}; 184 | font-size: 0.8em; 185 | padding: 0 4px 0 4px; 186 | text-decoration: none; 187 | } 188 | 189 | a.headerlink:hover { 190 | background-color: {{ theme_headlinkcolor }}; 191 | color: white; 192 | } 193 | 194 | div.body p, div.body dd, div.body li { 195 | text-align: justify; 196 | line-height: 130%; 197 | } 198 | 199 | div.admonition p.admonition-title + p { 200 | display: inline; 201 | } 202 | 203 | div.note { 204 | background-color: #eee; 205 | border: 1px solid #ccc; 206 | } 207 | 208 | div.seealso { 209 | background-color: #ffc; 210 | border: 1px solid #ff6; 211 | } 212 | 213 | div.topic { 214 | background-color: #eee; 215 | } 216 | 217 | div.warning { 218 | background-color: #ffe4e4; 219 | border: 1px solid #f66; 220 | } 221 | 222 | p.admonition-title { 223 | display: inline; 224 | } 225 | 226 | p.admonition-title:after { 227 | content: ":"; 228 | } 229 | 230 | /** 231 | * Code block. 232 | * The border colour should be a darker shade of the background colour. 233 | * The hex code #E8D898 used below is a pale, light grayish amber. 234 | */ 235 | pre { 236 | padding: 5px; 237 | background-color: {{ theme_codebgcolor }}; 238 | color: {{ theme_codetextcolor }}; 239 | line-height: 120%; 240 | border: 1px solid #E8D898; 241 | border-left: none; 242 | border-right: none; 243 | } 244 | 245 | /** 246 | * Commands or code within text. The hex code #EAEAF8 used below is a 247 | * pale, light grayish blue. 248 | */ 249 | tt { 250 | background-color: #EAEAF8; 251 | padding: 0 1px 0 1px; 252 | font-size: 0.95em; 253 | } 254 | -------------------------------------------------------------------------------- /common/themes/sage/static/sage.css_t: -------------------------------------------------------------------------------- 1 | /** 2 | * Sage stylesheet theme. This stylesheet is heavily borrowed from the 3 | * Sphinx stylesheet default theme distributed as the file 4 | * themes/default/static/default.css_t in Sphinx 0.6.3. 5 | */ 6 | 7 | @import url("basic.css"); 8 | 9 | /* -- page layout ----------------------------------------------------------- */ 10 | 11 | body { 12 | font-family: {{ theme_bodyfont }}; 13 | font-size: 100%; 14 | background-color: {{ theme_footerbgcolor }}; 15 | color: #000; 16 | margin: 0; 17 | padding: 0; 18 | } 19 | 20 | div.document { 21 | background-color: {{ theme_sidebarbgcolor }}; 22 | } 23 | 24 | div.documentwrapper { 25 | float: left; 26 | width: 100%; 27 | } 28 | 29 | div.bodywrapper { 30 | margin: 0 0 0 230px; 31 | } 32 | 33 | div.body { 34 | background-color: {{ theme_bgcolor }}; 35 | color: {{ theme_textcolor }}; 36 | padding: 0 20px 30px 20px; 37 | } 38 | 39 | {%- if theme_rightsidebar|tobool %} 40 | div.bodywrapper { 41 | margin: 0 230px 0 0; 42 | } 43 | {%- endif %} 44 | 45 | div.footer { 46 | color: {{ theme_footertextcolor }}; 47 | width: 100%; 48 | padding: 9px 0 9px 0; 49 | text-align: center; 50 | font-size: 75%; 51 | } 52 | 53 | div.footer a { 54 | color: {{ theme_footertextcolor }}; 55 | text-decoration: underline; 56 | } 57 | 58 | div.related { 59 | background-color: {{ theme_relbarbgcolor }}; 60 | line-height: 30px; 61 | color: {{ theme_relbartextcolor }}; 62 | } 63 | 64 | div.related a { 65 | color: {{ theme_relbarlinkcolor }}; 66 | } 67 | 68 | div.sphinxsidebar { 69 | {%- if theme_stickysidebar|tobool %} 70 | top: 30px; 71 | margin: 0; 72 | position: fixed; 73 | overflow: auto; 74 | height: 100%; 75 | {%- endif %} 76 | {%- if theme_rightsidebar|tobool %} 77 | float: right; 78 | {%- if theme_stickysidebar|tobool %} 79 | right: 0; 80 | {%- endif %} 81 | {%- endif %} 82 | } 83 | 84 | {%- if theme_stickysidebar|tobool %} 85 | /* this is nice, but it it leads to hidden headings when jumping 86 | to an anchor */ 87 | /* 88 | div.related { 89 | position: fixed; 90 | } 91 | 92 | div.documentwrapper { 93 | margin-top: 30px; 94 | } 95 | */ 96 | {%- endif %} 97 | 98 | div.sphinxsidebar h3 { 99 | font-family: {{ theme_headfont }}; 100 | color: {{ theme_sidebartextcolor }}; 101 | font-size: 1.4em; 102 | font-weight: normal; 103 | margin: 0; 104 | padding: 0; 105 | } 106 | 107 | div.sphinxsidebar h3 a { 108 | color: {{ theme_sidebartextcolor }}; 109 | } 110 | 111 | div.sphinxsidebar h4 { 112 | font-family: {{ theme_headfont }}; 113 | color: {{ theme_sidebartextcolor }}; 114 | font-size: 1.3em; 115 | font-weight: normal; 116 | margin: 5px 0 0 0; 117 | padding: 0; 118 | } 119 | 120 | div.sphinxsidebar p { 121 | color: {{ theme_sidebartextcolor }}; 122 | } 123 | 124 | div.sphinxsidebar p.topless { 125 | margin: 5px 10px 10px 10px; 126 | } 127 | 128 | div.sphinxsidebar ul { 129 | margin: 10px; 130 | padding: 0; 131 | color: {{ theme_sidebartextcolor }}; 132 | } 133 | 134 | div.sphinxsidebar a { 135 | color: {{ theme_sidebarlinkcolor }}; 136 | } 137 | 138 | div.sphinxsidebar input { 139 | border: 1px solid {{ theme_sidebarlinkcolor }}; 140 | font-family: sans-serif; 141 | font-size: 1em; 142 | } 143 | 144 | /* -- body styles ----------------------------------------------------------- */ 145 | 146 | a { 147 | color: {{ theme_linkcolor }}; 148 | text-decoration: none; 149 | } 150 | 151 | a:hover { 152 | text-decoration: underline; 153 | } 154 | 155 | div.body p, div.body dd, div.body li { 156 | text-align: justify; 157 | line-height: 130%; 158 | } 159 | 160 | div.body h1, 161 | div.body h2, 162 | div.body h3, 163 | div.body h4, 164 | div.body h5, 165 | div.body h6 { 166 | font-family: {{ theme_headfont }}; 167 | background-color: {{ theme_headbgcolor }}; 168 | font-weight: normal; 169 | color: {{ theme_headtextcolor }}; 170 | border-bottom: 1px solid #ccc; 171 | margin: 20px -20px 10px -20px; 172 | padding: 3px 0 3px 10px; 173 | } 174 | 175 | div.body h1 { margin-top: 0; font-size: 200%; } 176 | div.body h2 { font-size: 160%; } 177 | div.body h3 { font-size: 140%; } 178 | div.body h4 { font-size: 120%; } 179 | div.body h5 { font-size: 110%; } 180 | div.body h6 { font-size: 100%; } 181 | 182 | a.headerlink { 183 | color: {{ theme_headlinkcolor }}; 184 | font-size: 0.8em; 185 | padding: 0 4px 0 4px; 186 | text-decoration: none; 187 | } 188 | 189 | a.headerlink:hover { 190 | background-color: {{ theme_headlinkcolor }}; 191 | color: white; 192 | } 193 | 194 | div.body p, div.body dd, div.body li { 195 | text-align: justify; 196 | line-height: 130%; 197 | } 198 | 199 | div.admonition p.admonition-title + p { 200 | display: inline; 201 | } 202 | 203 | div.note { 204 | background-color: #eee; 205 | border: 1px solid #ccc; 206 | } 207 | 208 | div.admonition-todo { 209 | background-color: #eee; 210 | border: 1px solid #ccc; 211 | } 212 | 213 | div.seealso { 214 | background-color: #ffc; 215 | border: 1px solid #ff6; 216 | } 217 | 218 | div.topic { 219 | background-color: #eee; 220 | } 221 | 222 | div.warning { 223 | background-color: #ffe4e4; 224 | border: 1px solid #f66; 225 | } 226 | 227 | p.admonition-title { 228 | display: inline; 229 | } 230 | 231 | p.admonition-title:after { 232 | content: ":"; 233 | } 234 | 235 | /** 236 | * Code block. 237 | * The border colour should be a darker shade of the background colour. 238 | * The hex code #E8D898 used below is a pale, light grayish amber. 239 | */ 240 | pre { 241 | padding: 5px; 242 | background-color: {{ theme_codebgcolor }}; 243 | color: {{ theme_codetextcolor }}; 244 | line-height: 120%; 245 | border: 1px solid #E8D898; 246 | border-left: none; 247 | border-right: none; 248 | } 249 | 250 | /** 251 | * Commands or code within text. The hex code #EAEAF8 used below is a 252 | * pale, light grayish blue. 253 | */ 254 | tt { 255 | background-color: #EAEAF8; 256 | padding: 0 1px 0 1px; 257 | font-size: 0.95em; 258 | } 259 | -------------------------------------------------------------------------------- /developer/workflows.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-workflows: 2 | 3 | ======================= 4 | Distributed Development 5 | ======================= 6 | 7 | Git is a tool to exchange commits (organized into branches) with other 8 | developers. As a distributed revision control system, it does not have 9 | the notion of a central server; The Sage trac server is just one of 10 | many possible remote repositories from your point of view. This lets 11 | you use and experiment with different ways to interact with other 12 | developers. In this chapter, we describe some common ways to develop 13 | for Sage. 14 | 15 | For simplicity, let us assume two developers (Alice and Bob) are 16 | collaborating on a ticket. The first step of opening the ticket is 17 | always the same, and could be performed by either Alice or Bob or a 18 | third person. 19 | 20 | 21 | 22 | 23 | 24 | Simple Workflow 25 | =============== 26 | 27 | .. image:: static/flowchart.svg 28 | :align: center 29 | 30 | 31 | 1. Alice creates a :ref:`new local branch ` and 32 | :ref:`commits ` changes to the Sage sources. 33 | 34 | 2. Alice :ref:`uploads her branch ` to the trac 35 | server and fills in the "Branch:" field with her remote branch name 36 | ``u/alice/description``. 37 | 38 | 3. Bob :ref:`downloads Alice's branch `, looks 39 | through the source, and leaves a comment on the ticket about a 40 | mistake in Alice's code. 41 | 42 | 4. Alice fixes the bug on top of her current branch, and uploads the 43 | updated branch. 44 | 45 | 5. Bob :ref:`retrieves Alice's updates ` and reviews 46 | the changes. 47 | 48 | 6. Once Bob is satisfied, he sets the ticket to positive review. The 49 | "Author:" field is set to Alice's full name, and the "Reviewer:" 50 | field is set to Bob's full name. 51 | 52 | Alternatively, Bob might want to make some changes himself. Then, 53 | instead, we would have 54 | 55 | 3. Bob :ref:`downloads Alice's branch `, makes 56 | changes, and :ref:`commits ` them to his local 57 | branch. 58 | 59 | 4. Bob :ref:`uploads his branch ` to the trac server 60 | and fills in the "Branch:" field with his remote branch name 61 | ``u/bob/description``. 62 | 63 | 5. Alice :ref:`downloads Bob's branch ` and 64 | reviews his changes. 65 | 66 | 6. Once Alice is satisfied, she sets the ticket to positive review. If 67 | both contributions are of comparable size, then the "Author:" and 68 | "Reviewer:" fields are set to both Alice's and Bob's full name. 69 | 70 | 71 | 72 | 73 | Public Repository 74 | ================= 75 | 76 | In addition to the user branches (``u//`` on the 77 | Sage trac server with ```` replaced by your trac user name) that 78 | only you can write to, you can also create a public branch that 79 | everybody with a trac account can write to. These start with 80 | ``public/`` plus some description. To avoid branch name collisions it 81 | is a good idea to include your trac user name in the branch name, so 82 | it is recommended that you use ``public//`` as the 83 | branch name. Now all ticket authors push to the same remote branch. 84 | 85 | 1. Alice creates a :ref:`new local branch ` and 86 | :ref:`commits ` some changes to the Sage library. 87 | 88 | 2. Alice :ref:`uploads her branch ` as a public 89 | branch to the trac server and fills in the "Branch:" field with her 90 | remote branch name ``public/alice/description``. 91 | 92 | 3. Bob :ref:`downloads Alice's branch ` and 93 | makes changes to his local copy. 94 | 95 | 4. Bob :ref:`commits ` changes to his local branch 96 | of the Sage sources. 97 | 98 | 5. Bob uploads his changes to the joint remote repository:: 99 | 100 | [bob@localhost sage]$ git push local_branch:public/alice/description 101 | 102 | 6. Alice :ref:`retrieves Bob's updates `, makes 103 | more changes, commits, and pushes them to trac. 104 | 105 | 7. Charly reviews the final version, and then sets the ticket to 106 | positive review. The "Author:" field is set to Alice's and Bob's 107 | full name, and the "Reviewer:" field is set to Charly's full name. 108 | 109 | 110 | 111 | 112 | GitHub 113 | ====== 114 | 115 | Yet another possible workflow is to use GitHub (or any other 116 | third-party git repository) to collaboratively edit your new branch, 117 | and only push the result to trac once you and your ticket co-authors 118 | are satisfied. 119 | 120 | 121 | Fork 122 | ---- 123 | 124 | The first step is to create your own fork of the Sage repository; 125 | simply click "Fork" on the `Sage GitHub repository 126 | `_. Then add it as one of the 127 | remotes to your local Sage repository. In the following, we will use 128 | the label "github" for this remote repository, though you are of 129 | course free to use a different one:: 130 | 131 | $ git remote add github git@github.com:github_user_name/sage.git 132 | $ git remote -v 133 | github git@github.com:github_user_name/sage.git (fetch) 134 | github git@github.com:github_user_name/sage.git (push) 135 | trac git@trac.sagemath.org:sage.git (fetch) 136 | trac git@trac.sagemath.org:sage.git (push) 137 | $ git fetch github 138 | remote: Counting objects: 107, done. 139 | remote: Compressing objects: 100% (63/63), done. 140 | remote: Total 74 (delta 41), reused 40 (delta 10) 141 | Unpacking objects: 100% (74/74), done. 142 | From github.com:github_user_name/sage 143 | * [new branch] master -> github/master 144 | 145 | 146 | Develop 147 | ------- 148 | 149 | You now use the github repository to develop your ticket branch; First 150 | create a new branch:: 151 | 152 | $ git checkout -b my_branch --track github/master 153 | Branch my_branch set up to track remote branch master from github. 154 | Switched to a new branch 'my_branch' 155 | $ git push github my_branch 156 | Total 0 (delta 0), reused 0 (delta 0) 157 | To git@github.com:github_user_name/sage.git 158 | * [new branch] my_branch -> my_branch 159 | 160 | Because of the ``--track`` option, the ``git pull`` command will 161 | default to downloading your coauthor 's changes from your github 162 | branch. Alternatively, you can create a new branch on your fork's 163 | GitHub webpage. 164 | 165 | At this point you can use the GitHub workflow that you prefer. In 166 | particular, your choices are 167 | 168 | * Give your coauthors write permissions to your github fork. Every 169 | author edits/commits to their own local copy and they jointly push 170 | to your github branch. 171 | 172 | * Have every coauthor create their own fork and send you (the lead 173 | author) pull requests to your GitHub fork. 174 | 175 | * Use the GitHub web page editing & commiting feature, that way you 176 | can make changes without ever using your local machine. 177 | 178 | 179 | Push to Trac 180 | ------------ 181 | 182 | When you are satisfied with your branch, you push it to the Sage trac 183 | server:: 184 | 185 | $ git push trac u/user/description 186 | 187 | and then fill in the "Branch" field in the trac ticket description as 188 | explained in :ref:`section-git-push`. 189 | 190 | -------------------------------------------------------------------------------- /common/themes/sage/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | 3 | {% block rootrellink %} 4 | {% if docstitle.startswith('Sage Documentation') %} 5 | 6 | {% else %} 7 | {% if pathto(master_doc).endswith('.html') %} 8 | 9 | {% else %} 10 | 11 | {% endif %} 12 | {% endif %} 13 | {{ super() }} 14 | {% endblock %} 15 | 16 | {% block extrahead %} 17 | 18 | {% endblock %} 19 | 20 | {%- block footer %} 21 | {{ super() }} 22 | 111 | {%- endblock %} 112 | 113 | 114 | 115 | 116 | {%- macro sidebar() %} 117 | {%- if not embedded %}{% if not theme_nosidebar|tobool %} 118 |
119 |
120 | {%- block sidebarlogo %} 121 | {%- if logo %} 122 | 125 | {%- endif %} 126 | {%- endblock %} 127 | {%- block sidebartoc %} 128 | {%- if display_toc %} 129 |

{{ _('Table Of Contents') }}

130 | {{ toc }} 131 | {%- endif %} 132 | {%- endblock %} 133 | {%- block sidebarrel %} 134 | {%- if prev %} 135 |

{{ _('Previous topic') }}

136 |

{{ prev.title }}

138 | {%- endif %} 139 | {%- if next %} 140 |

{{ _('Next topic') }}

141 |

{{ next.title }}

143 | {%- endif %} 144 | {%- endblock %} 145 | {%- block sidebarsourcelink %} 146 | {%- if show_source and has_source and sourcename %} 147 |

{{ _('This Page') }}

148 | 152 | {%- endif %} 153 | {%- endblock %} 154 | {%- if customsidebar %} 155 | {% include customsidebar %} 156 | {%- endif %} 157 | {%- block sidebarsearch %} 158 | {%- if pagename != "search" %} 159 | 175 | 176 | {%- endif %} 177 | {%- endblock %} 178 |
179 |
180 | {%- endif %}{% endif %} 181 | {%- endmacro %} 182 | -------------------------------------------------------------------------------- /common/themes/sageref/layout.html: -------------------------------------------------------------------------------- 1 | {% extends "basic/layout.html" %} 2 | 3 | {% block rootrellink %} 4 | {% if docstitle.startswith('Sage Documentation') %} 5 | 6 | {% else %} 7 | {% if pathto(master_doc).endswith('.html') %} 8 | 9 | {% else %} 10 | 11 | Sage Reference Manual » 12 | {% endif %} 13 | {% endif %} 14 | {{ super() }} 15 | {% endblock %} 16 | 17 | {% block extrahead %} 18 | 19 | {% endblock %} 20 | 21 | {%- block footer %} 22 | {{ super() }} 23 | 112 | {%- endblock %} 113 | 114 | 115 | 116 | 117 | {%- macro sidebar() %} 118 | {%- if not embedded %}{% if not theme_nosidebar|tobool %} 119 |
120 |
121 | {%- block sidebarlogo %} 122 | {%- if logo %} 123 | 126 | {%- endif %} 127 | {%- endblock %} 128 | {%- block sidebartoc %} 129 | {%- if display_toc %} 130 |

{{ _('Table Of Contents') }}

131 | {{ toc }} 132 | {%- endif %} 133 | {%- endblock %} 134 | {%- block sidebarrel %} 135 | {%- if prev %} 136 |

{{ _('Previous topic') }}

137 |

{{ prev.title }}

139 | {%- endif %} 140 | {%- if next %} 141 |

{{ _('Next topic') }}

142 |

{{ next.title }}

144 | {%- endif %} 145 | {%- endblock %} 146 | {%- block sidebarsourcelink %} 147 | {%- if show_source and has_source and sourcename %} 148 |

{{ _('This Page') }}

149 | 153 | {%- endif %} 154 | {%- endblock %} 155 | {%- if customsidebar %} 156 | {% include customsidebar %} 157 | {%- endif %} 158 | {%- block sidebarsearch %} 159 | {%- if pagename != "search" %} 160 | 176 | 177 | {%- endif %} 178 | {%- endblock %} 179 |
180 |
181 | {%- endif %}{% endif %} 182 | {%- endmacro %} 183 | -------------------------------------------------------------------------------- /developer/git_background.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-git-background: 2 | 3 | ============== 4 | Git Background 5 | ============== 6 | 7 | This chapter contains additional material about the git revision 8 | control system. It is not necessary if you stick with the Sage 9 | development scripts. See :ref:`chapter-git-setup` for the minimal 10 | steps needed for Sage development. 11 | 12 | 13 | 14 | 15 | 16 | 17 | .. _section-git-configuration: 18 | 19 | Configuration 20 | ============= 21 | 22 | Your personal git configurations are saved in the ``~/.gitconfig`` 23 | file in your home directory. Here is an example:: 24 | 25 | [user] 26 | name = Your Name 27 | email = you@yourdomain.example.com 28 | 29 | [core] 30 | editor = emacs 31 | 32 | You can edit this file directly or you can use git to make changes for 33 | you:: 34 | 35 | [user@localhost ~] git config --global user.name "Your Name" 36 | [user@localhost ~] git config --global user.email you@yourdomain.example.com 37 | [user@localhost ~] git config --global core.editor vim 38 | 39 | 40 | 41 | Aliases 42 | ------- 43 | 44 | Aliases are personal shortcuts for git commands. For example, you 45 | might want to be able to shorten ``git checkout`` to ``git co``. Or 46 | you may want to alias ``git diff --color-words`` (which gives a nicely 47 | formatted output of the diff) to ``git wdiff``. You can do this with:: 48 | 49 | [user@localhost ~] git config --global alias.ci "commit -a" 50 | [user@localhost ~] git config --global alias.co checkout 51 | [user@localhost ~] git config --global alias.st "status -a" 52 | [user@localhost ~] git config --global alias.stat "status -a" 53 | [user@localhost ~] git config --global alias.br branch 54 | [user@localhost ~] git config --global alias.wdiff "diff --color-words" 55 | 56 | will create an ``alias`` section in your ``.gitconfig`` file with contents 57 | like this:: 58 | 59 | [alias] 60 | ci = commit -a 61 | co = checkout 62 | st = status -a 63 | stat = status -a 64 | br = branch 65 | wdiff = diff --color-words 66 | 67 | 68 | Editor 69 | ------ 70 | 71 | To set the editor to use for editing commit messages, you can use:: 72 | 73 | [user@localhost ~] git config --global core.editor vim 74 | 75 | 76 | Merging 77 | ------- 78 | 79 | To enforce summaries when doing merges (``~/.gitconfig`` file again):: 80 | 81 | [merge] 82 | log = true 83 | 84 | Or from the command line:: 85 | 86 | [user@localhost ~] git config --global merge.log true 87 | 88 | 89 | .. _section-fancy-log: 90 | 91 | Fancy Log Output 92 | ---------------- 93 | 94 | Here is an alias to get a fancy log output; it should go in the 95 | ``alias`` section of your ``.gitconfig`` file:: 96 | 97 | lg = log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)[%an]%Creset' --abbrev-commit --date=relative 98 | 99 | Using this ``lg`` alias gives you the changelog with a colored ascii graph:: 100 | 101 | [user@localhost ~] git lg 102 | * 6d8e1ee - (HEAD, origin/my-fancy-feature, my-fancy-feature) NF - a fancy file (45 minutes ago) [Matthew Brett] 103 | * d304a73 - (origin/placeholder, placeholder) Merge pull request #48 from hhuuggoo/master (2 weeks ago) [Jonathan Terhorst] 104 | |\ 105 | | * 4aff2a8 - fixed bug 35, and added a test in test_bugfixes (2 weeks ago) [Hugo] 106 | |/ 107 | * a7ff2e5 - Added notes on discussion/proposal made during Data Array Summit. (2 weeks ago) [Corran Webster] 108 | * 68f6752 - Initial implimentation of AxisIndexer - uses 'index_by' which needs to be changed to a call on an Axes object - this is all very sketchy right now. (2 weeks ago) [Corr 109 | * 376adbd - Merge pull request #46 from terhorst/master (2 weeks ago) [Jonathan Terhorst] 110 | |\ 111 | | * b605216 - updated joshu example to current api (3 weeks ago) [Jonathan Terhorst] 112 | | * 2e991e8 - add testing for outer ufunc (3 weeks ago) [Jonathan Terhorst] 113 | | * 7beda5a - prevent axis from throwing an exception if testing equality with non-axis object (3 weeks ago) [Jonathan Terhorst] 114 | | * 65af65e - convert unit testing code to assertions (3 weeks ago) [Jonathan Terhorst] 115 | | * 956fbab - Merge remote-tracking branch 'upstream/master' (3 weeks ago) [Jonathan Terhorst] 116 | | |\ 117 | | |/ 118 | 119 | 120 | 121 | Tutorials and summaries 122 | ======================= 123 | 124 | * `Github help `_ has an excellent series of 125 | how-to guides. 126 | 127 | * `Learn.github `_ has an excellent series 128 | of tutorials. 129 | 130 | * The `pro git book `_ is a good in-depth book on git. 131 | 132 | * A `git cheat sheet `_ is a 133 | page giving summaries of common commands. 134 | 135 | * The `git user manual 136 | `_. 137 | 138 | * The `git tutorial `_. 139 | 140 | * The `git community book `_. 141 | 142 | * `Git ready `_ is a nice series of 143 | tutorials. 144 | 145 | * `Git casts `_ has video and screencasts 146 | for git. 147 | 148 | * `Git magic 149 | `_ 150 | is an extended introduction with intermediate detail. 151 | 152 | * The `git parable 153 | `_ is 154 | an easy read explaining the concepts behind git. 155 | 156 | * `Git foundation 157 | `_ 158 | expands on the `git parable`_. 159 | 160 | * `Fernando Perez' git page 161 | `_ contains many links 162 | and tips. 163 | 164 | * A good but technical page on `git concepts 165 | `_ 166 | 167 | * `Git svn crash course `_: git 168 | for those of us used to `subversion 169 | `_ 170 | 171 | 172 | Advanced git workflow 173 | ===================== 174 | 175 | There are many ways of working with git; here are some posts on the 176 | rules of thumb that other projects have come up with: 177 | 178 | * Linus Torvalds on `git management 179 | `_ 180 | 181 | * Linus Torvalds on `linux git workflow 182 | `_. Summary: 183 | use the git tools to make the history of your edits as clean as 184 | possible; merge from upstream edits as little as possible in 185 | branches where you are doing active development. 186 | 187 | 188 | Manual pages online 189 | =================== 190 | 191 | You can get these on your own machine with (e.g) ``git help push`` or 192 | (same thing) ``git push --help``, but, for convenience, here are the 193 | online manual pages for some common commands: 194 | 195 | * `git add `_ 196 | * `git branch `_ 197 | * `git checkout `_ 198 | * `git clone `_ 199 | * `git commit `_ 200 | * `git config `_ 201 | * `git diff `_ 202 | * `git log `_ 203 | * `git pull `_ 204 | * `git push `_ 205 | * `git remote `_ 206 | * `git status `_ 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /developer/sage_manuals.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-sage_manuals: 2 | 3 | ================ 4 | The Sage Manuals 5 | ================ 6 | 7 | This chapter describes how to modify the Sage manuals. Sage's manuals 8 | are written in ReST, otherwise known as `reStructuredText`__. To edit 9 | them, you just need to edit the appropriate file. The documentation 10 | builder is called `Sphinx`__. 11 | 12 | __ http://docutils.sourceforge.net/rst.html 13 | 14 | __ http://sphinx.pocoo.org 15 | 16 | Here is a list of the Sage manuals and the corresponding files to edit: 17 | 18 | - The Sage tutorial: ``SAGE_ROOT/src/doc/en/tutorial`` 19 | 20 | - The Sage developer's guide: 21 | ``SAGE_ROOT/src/doc/en/developer`` 22 | 23 | - Constructions in Sage: 24 | ``SAGE_ROOT/src/doc/en/constructions`` 25 | 26 | - The Sage installation guide: 27 | ``SAGE_ROOT/src/doc/en/installation`` 28 | 29 | - The Sage reference manual: some of this is contained in the file 30 | ``SAGE_ROOT/src/doc/en/reference``, but most of it is 31 | automatically generated from the Sage source code. 32 | 33 | - Additional, more specialized manuals can be found under 34 | ``SAGE_ROOT/src/doc/en`` as well. 35 | 36 | .. note:: 37 | 38 | You can edit manuals that have been translated into another language 39 | by replacing the ``en/`` above with the appropriate two letter 40 | language code. For example, the French tutorial is located in 41 | ``SAGE_ROOT/src/doc/fr/tutorial`` 42 | 43 | 44 | Editing the Manuals 45 | =================== 46 | 47 | If, for example, you want to change the Sage tutorial, then you should 48 | start by modifying the files in 49 | ``SAGE_ROOT/src/doc/en/tutorial/``. Then to build a PDF file 50 | with your changes, type:: 51 | 52 | sage --docbuild tutorial pdf 53 | 54 | You will get a file ``tutorial.pdf`` in 55 | ``SAGE_ROOT/src/doc/output/pdf/en/tutorial`` which you should 56 | inspect. You can build the HTML version of the tutorial by typing:: 57 | 58 | sage --docbuild tutorial html 59 | 60 | Once you have done this, you can access the new HTML version from the 61 | notebook interface to Sage by clicking the ``Help`` link, or you can 62 | open the file 63 | ``SAGE_ROOT/src/doc/output/html/en/tutorial/index.html`` in 64 | your web browser. For more detailed information about building the 65 | documentation, see :ref:`section-building-manuals`. 66 | 67 | You should also run:: 68 | 69 | sage -tp SAGE_ROOT/src/doc/en/tutorial/ 70 | 71 | to test all of the examples in the tutorial, see 72 | :ref:`chapter-testing` for more details. 73 | 74 | As noted above, the reference manual is mostly autogenerated from Sage 75 | source code. To build it, type:: 76 | 77 | sage -b 78 | sage --docbuild reference 79 | 80 | where ```` is the name of the repository you are using, and 81 | ```` is ``html``, ``pdf``, or any other supported format (as listed 82 | when you run ``sage --docbuild --formats``). 83 | 84 | 85 | .. _chapter-sage_manuals_links: 86 | 87 | Hyperlinks 88 | ========== 89 | 90 | You can link to doctstings of modules, classes, methods. In addition, 91 | you can link web pages like trac tickets and Wikipedia. For full 92 | documentation, refer to `inline markup`__ in the Sphinx 93 | documentation. Currently, there is no support for defining chapters 94 | and labels in the autogenerated documentation. However, it is possible 95 | to generate a link to the documentation for any module, class, method, 96 | function, etc. The syntax is 97 | 98 | __ http://sphinx.pocoo.org/markup/inline.html 99 | 100 | :: 101 | 102 | :role:`title ` 103 | 104 | or 105 | 106 | :: 107 | 108 | :role:`target` 109 | 110 | where 111 | 112 | - ``role`` is the kind of thing you want to link to (i.e. ``mod`` for 113 | module, ``class`` for classes, ``meth`` for methods, ``func`` for 114 | functions, etc; 115 | 116 | - ``target`` is the Python name of the object (class, module, method, 117 | etc.) which carries the documentation to be linked to; 118 | 119 | - ``title`` is the name of the link as shown in the browser. 120 | 121 | If you do not provide any title then target will be used. For example, 122 | to link to the ``dyck_word`` module, you would use 123 | ``:mod:`sage.combinat.dyck_word``` or if you prefer ``:mod:`Dyck 124 | words```. Note that, in the first case, the 125 | full qualified Python address is used which is usually too long. You 126 | can prefix it with a ``"~"`` to get only the final name. For example, 127 | in the huge link:: 128 | 129 | :meth:`~sage.combinat.non_decreasing_parking_function.NonDecreasingParkingFunction.to_dyck_word` 130 | 131 | only ``".to_dyck_word()"`` will appear. Note that the parentheses in 132 | the link are autogenerated. 133 | 134 | Local names are handled. That is, for example, in the definition of a 135 | class (and any of its members or methods), you can link to any member 136 | or method of the same class by simply giving the name of it prepended 137 | by a dot ``"."``. You do not need to give its full address. For 138 | example:: 139 | 140 | :meth:`.to_dyck_word` 141 | 142 | sets up a link to the ``.to_dyck_word()`` method of the current class 143 | if it exists. If not, the documentation builder searches by going up 144 | in the class/module hierarchy of Python until it finds an object with 145 | this name or reaches the top-level module without finding it. If the 146 | name cannot be found, the title is typeset in boldface without any 147 | link produced and also without any error or warning. Note that without 148 | the prepended dot, the object is searched starting from the top-level 149 | to the innermost module or class. 150 | 151 | You can also link, without giving the full path, to objects imported 152 | in a local module or imported by default in Sage. For example, the two 153 | following are equivalent, as :class:`Parent` is imported by default in 154 | Sage (using the ``all.py`` files):: 155 | 156 | :class:`Parent` 157 | :class:`~sage.structure.parent.Parent` 158 | 159 | Sage adds a special role to link to trac ticket. The code 160 | ``:trac:`12490``` link to the :trac:`12490`. When fixing a bug, you 161 | should add the link to the corresponding trac ticket in the ``TEST`` 162 | section. Here is an example:: 163 | 164 | TEST: 165 | 166 | We check for :trac:`5534`:: 167 | 168 | sage: w = ["a", "b", "c", "d"]; ww = ["b", "d"] 169 | sage: x = sage.combinat.subword.smallest_positions(w, ww); ww 170 | ['b', 'd'] 171 | 172 | In the same vein, you can also add external links of various kinds: 173 | 174 | - Wikipedia: ``:wikipedia:`Sage_(mathematics_software)``` adds the 175 | link :wikipedia:`Sage_(mathematics_software)`. 176 | 177 | - Arxiv: ``:arxiv:`1202.1506``` adds the link :arxiv:`1202.1506`. 178 | 179 | - On-Line Encyclopedia of Integer Sequences: ``:oeis:`A000081``` adds 180 | the link :oeis:`A000081`. 181 | 182 | - Digital Object Identifier: ``:doi:`10.2752/175303708X390473``` adds 183 | the link :doi:`10.2752/175303708X390473`. 184 | 185 | - MathSciNet: ``:mathscinet:`MR0100971``` adds the link 186 | :mathscinet:`MR0100971`. 187 | 188 | .. note:: 189 | 190 | Finally, you can check that all links are properly resolved by 191 | adding the argument ``--warn-links`` to the documentation build 192 | command as in:: 193 | 194 | sage -docbuild --warn-links reference html 195 | 196 | In this case, when a link is not resolved Sphinx will issue a 197 | warning. 198 | 199 | 200 | Adding a New File 201 | ================= 202 | 203 | If you write a new file, say, ``sage/combinat/family.py``, and you 204 | want your documentation to be added to the standard documentation, you 205 | have to add your file to the relevant ``index.rst`` file usually 206 | located in the tree:: 207 | 208 | SAGE_ROOT/src/doc/en/reference 209 | 210 | For this example, you would need to add to the file:: 211 | 212 | SAGE_ROOT/src/doc/en/reference/combinat/index.rst 213 | 214 | the following line:: 215 | 216 | Combinatorics 217 | ============= 218 | 219 | .. toctree:: 220 | :maxdepth: 2 221 | 222 | ../sage/combinat/combinat 223 | [...] 224 | ../sage/combinat/dyck_word 225 | + ../sage/combinat/family 226 | ../sage/combinat/finite_class 227 | [...] 228 | 229 | 230 | .. _section-building-manuals: 231 | 232 | Building the manuals 233 | ==================== 234 | 235 | All of the Sage manuals are built using the ``sage --docbuild`` 236 | script. The content of the ``sage --docbuild`` script is defined in 237 | ``SAGE_ROOT/src/doc/common/builder.py``. It is a thin wrapper around 238 | the ``sphinx-build`` script which does all of the real work. It is 239 | designed to be a replacement for the default Makefiles generated by 240 | the ``sphinx-quickstart`` script. The general form of the command 241 | is:: 242 | 243 | sage --docbuild 244 | 245 | as explained below. For more information, there are two help commands 246 | which give plenty of documentation for the ``sage --docbuild`` 247 | script:: 248 | 249 | sage --docbuild --help 250 | 251 | (or ``-h``) gives a basic listing of options and further 252 | help commands, while:: 253 | 254 | sage --docbuild --help-all 255 | 256 | (or ``-H``) shows a somewhat more comprehensive help message. 257 | 258 | 259 | Document names 260 | -------------- 261 | 262 | The ```` has the form:: 263 | 264 | lang/name 265 | 266 | where ``lang`` is a two-letter language code, and ``name`` is the 267 | descriptive name of the document. If the language is not specified, 268 | then it defaults to English (``en``). The following two commands do 269 | the exact same thing:: 270 | 271 | sage --docbuild tutorial html 272 | sage --docbuild en/tutorial html 273 | 274 | To specify the French version of the tutorial, you would simply run:: 275 | 276 | sage --docbuild fr/tutorial html 277 | 278 | 279 | Output Formats 280 | -------------- 281 | 282 | The Sage documentation build system currently supports all of the 283 | output formats that Sphinx does. For more detailed information, see 284 | the documentation on builders at http://sphinx.pocoo.org/builders.html 285 | . 286 | 287 | 288 | Syntax Highlighting Cython Code 289 | =============================== 290 | 291 | If you need to put :ref:`Cython ` code in a ReST file, 292 | you can either precede the code block by ``.. code-block:: cython`` instead 293 | of the usual ``::`` if you want to highlight one block of code in Cython, 294 | or you can use ``.. highlight:: cython`` for a whole file. 295 | 296 | The following example was generated by ``.. code-block:: cython``: 297 | 298 | .. code-block:: cython 299 | 300 | cdef extern from "descrobject.h": 301 | ctypedef struct PyMethodDef: 302 | void *ml_meth 303 | ctypedef struct PyMethodDescrObject: 304 | PyMethodDef *d_method 305 | void* PyCFunction_GET_FUNCTION(object) 306 | bint PyCFunction_Check(object) 307 | -------------------------------------------------------------------------------- /developer/packaging.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-packaging: 2 | 3 | ========================== 4 | Packaging Third-Party Code 5 | ========================== 6 | 7 | One of the mottoes of the Sage project is to not reinvent the 8 | wheel: If an algorithm is already implemented in a well-tested library 9 | then consider incorporating that library into Sage. The current list 10 | of available packages are the subdirectories of 11 | ``SAGE_ROOT/build/pkgs/``. 12 | 13 | Not all of these packages are built by default, they are divided into 14 | standard and optional ones. Standard packages are built by default and 15 | have much more stringent quality requirements. In addition, there are 16 | experimental spkgs (and some legacy optional spkgs) that are just 17 | tarballs containing build scripts. 18 | 19 | 20 | Inclusion Procedure for New Packages 21 | ==================================== 22 | 23 | For a package to become part of Sage's standard distribution, it 24 | must meet the following requirements: 25 | 26 | - **License**. For standard packages, the license must be compatible 27 | with the GNU General Public License, version 3. The Free Software 28 | Foundation maintains a long list of `licenses and comments about 29 | them `_. 30 | 31 | - **Build Support**. The code must build on all the `fully supported 32 | platforms 33 | `_. 34 | 35 | A standard package should also work on all the platforms where Sage 36 | is `expected to work 37 | `_ and 38 | on which Sage `almost works 39 | `_ but 40 | since we don't fully support these platforms and often lack the 41 | resources to test on them, you are not expected to confirm your 42 | packages works on those platforms. 43 | 44 | - **Quality**. The code should be "better" than any other available 45 | code (that passes the two above criteria), and the authors need to 46 | justify this. The comparison should be made to both Python and other 47 | software. Criteria in passing the quality test include: 48 | 49 | - Speed 50 | 51 | - Documentation 52 | 53 | - Usability 54 | 55 | - Absence of memory leaks 56 | 57 | - Maintainable 58 | 59 | - Portability 60 | 61 | - Reasonable build time, size, dependencies 62 | 63 | - **Previously an optional package**. A new standard package must have 64 | spent some time as an optional package. Or have a good reason why 65 | this is not possible. 66 | 67 | - **Refereeing**. The code must be refereed, as discussed in 68 | :ref:`chapter-sage-trac`. 69 | 70 | 71 | 72 | .. _section-directory-structure: 73 | 74 | Directory Structure 75 | =================== 76 | 77 | Third-party packages in Sage consists of two parts: 78 | 79 | #. The tarball as it is distributed by the third party, or as close as 80 | possible. Valid reasons for modifying the tarball are deleting 81 | unnecessary files to keeep the download size manageable or 82 | regenerating auto-generated files if necessary. But the actual code 83 | must be unmodified. See also :ref:`section-spkg-src`. 84 | 85 | #. The build scripts and associated files are in a subdirectory 86 | ``SAGE_ROOT/build/pkgs/package``, where you replace ``package`` 87 | with a lower-case version of the upstream project name. 88 | 89 | As an example, let us consider a hypothetical FoO project. They 90 | (upstream) distribute a tarball ``foo-1.3.tar.gz``. to package it in 91 | Sage, we create a subdirectory containing the following:: 92 | 93 | SAGE_ROOT/build/pkgs/foo 94 | |-- patches 95 | | |-- bar.patch 96 | | `-- baz.patch 97 | |-- checksums.ini 98 | |-- package-version.txt 99 | |-- spkg-check 100 | |-- spkg-install 101 | |-- spkg-src 102 | `-- SPKG.txt 103 | 104 | We discuss the individual files in the following. 105 | 106 | 107 | .. _section-spkg-install: 108 | 109 | Install Script 110 | -------------- 111 | 112 | The ``spkg-install`` file is a shell script installing the package, 113 | with ``PACKAGE_NAME`` replaced by the the package name. In the best 114 | case, the upstream project can simply be installed by the usual 115 | configure / make / make install steps. In that case, the build script 116 | would simply consist of:: 117 | 118 | #!/usr/bin/env bash 119 | 120 | cd src 121 | 122 | ./configure --prefix="$SAGE_LOCAL" --libdir="$SAGE_LOCAL/lib" 123 | if [ $? -ne 0 ]; then 124 | echo >&2 "Error configuring PACKAGE_NAME." 125 | exit 1 126 | fi 127 | 128 | $MAKE 129 | if [ $? -ne 0 ]; then 130 | echo >&2 "Error building PACKAGE_NAME." 131 | exit 1 132 | fi 133 | 134 | $MAKE -j1 install 135 | if [ $? -ne 0 ]; then 136 | echo >&2 "Error installing PACKAGE_NAME." 137 | exit 1 138 | fi 139 | 140 | 141 | Note that the top-level directory inside the tarball is renamed to 142 | ``src`` before calling the ``spkg-install`` script, so you can just 143 | use ``cd src`` instead of ``cd foo-1.3``. 144 | 145 | If there is any meaningful documentation included but not installed by 146 | ``make install``, then you can add something like the following to 147 | install it:: 148 | 149 | if [ "$SAGE_SPKG_INSTALL_DOCS" = yes ] ; then 150 | $MAKE doc 151 | if [ $? -ne 0 ]; then 152 | echo >&2 "Error building PACKAGE_NAME docs." 153 | exit 1 154 | fi 155 | mkdir -p "$SAGE_LOCAL/share/doc/PACKAGE_NAME" 156 | cp -R doc/* "$SAGE_ROOT/local/share/doc/PACKAGE_NAME" 157 | fi 158 | 159 | 160 | 161 | 162 | .. _section-spkg-check: 163 | 164 | Self-Tests 165 | ---------- 166 | 167 | The ``spkg-check`` file is an optional, but highly recommended, script 168 | to run self-tests of the package. It is run after building and 169 | installing if the ``SAGE_CHECK`` environment variable is set, see the 170 | Sage installation guide. Ideally, upstream has some sort of tests 171 | suite that can be run with the standard ``make check`` target. In that 172 | case, the ``spkg-check`` script would simply contain:: 173 | 174 | #!/usr/bin/env bash 175 | 176 | cd src 177 | $MAKE check 178 | 179 | 180 | .. _section-spkg-versioning: 181 | 182 | Package Versioning 183 | ------------------ 184 | 185 | The ``package-version.txt`` file containts just the version. So if 186 | upstream is ``foo-1.3.tar.gz`` then the package version file would 187 | only contain ``1.3``. 188 | 189 | If the upstream package is taken from some revision other than a 190 | stable version, you should use the date at which the revision is made, 191 | e.g. the Singular package ``20090818`` is made with the revision as of 192 | 2009-08-18. 193 | 194 | If you made any changes to the upstream tarball (see 195 | :ref:`section-directory-structure` for allowable changes) then you 196 | should append a ``.p1`` to the version. If you make further changes, 197 | increase the patch level as necessary. So the different versions would 198 | be ``1.3``, ``1.3.p1``, ``1.3.p2``, ... 199 | 200 | 201 | .. _section-spkg-SPKG-txt: 202 | 203 | The SPKG.txt File 204 | ----------------- 205 | 206 | The ``SPKG.txt`` file should follow this pattern:: 207 | 208 | = PACKAGE_NAME = 209 | 210 | == Description == 211 | 212 | What does the package do? 213 | 214 | == License == 215 | 216 | What is the license? If non-standard, is it GPLv3+ compatible? 217 | 218 | == SPKG Maintainers == 219 | 220 | * Mary Smith 221 | * Bill Jones 222 | * Leonhard Euler 223 | 224 | == Upstream Contact == 225 | 226 | Provide information for upstream contact. 227 | 228 | == Dependencies == 229 | 230 | Put a bulleted list of dependencies here: 231 | 232 | * python 233 | * readline 234 | 235 | == Special Update/Build Instructions == 236 | 237 | List patches that need to be applied and what they do. If the 238 | tarball was modified by hand and not via a spkg-src script, 239 | describe what was changed. 240 | 241 | 242 | with ``PACKAGE_NAME`` replaced by the the package name. Legacy 243 | ``SPKG.txt`` files have an additional changelog section, but this 244 | information is now kept in the git repository. 245 | 246 | 247 | .. _section-spkg-patching: 248 | 249 | Patching Sources 250 | ---------------- 251 | 252 | Actual changes to the source code must be via patches, which should be 253 | placed in the ``patches`` directory. GNU patch is distributed with 254 | Sage, so you can rely on it being available. All patches must be 255 | documented in ``SPKG.txt``, i.e. what they do, if they are platform 256 | specific, if they should be pushed upstream, etc. 257 | 258 | Patches to files in ``src/`` need to be applied in ``spkg-install``, 259 | that is, if there are any patches then your ``spkg-install`` script 260 | should contain a section like this:: 261 | 262 | for patch in ../patches/*.patch; do 263 | [ -r "$patch" ] || continue # Skip non-existing or non-readable patches 264 | patch -p1 <"$patch" 265 | if [ $? -ne 0 ]; then 266 | echo >&2 "Error applying '$patch'" 267 | exit 1 268 | fi 269 | done 270 | 271 | which applies the patches to the sources. 272 | 273 | 274 | .. _section-spkg-src: 275 | 276 | Modified Tarballs 277 | ----------------- 278 | 279 | The ``spkg-src`` file is optional and only to document how the 280 | upstream tarball was changed. Ideally it is not modified, then there 281 | would be no ``spkg-src`` file present either. 282 | 283 | However, if you really must modify the upstream tarball then it is 284 | recommended that you write a script, called ``spkg-src``, that makes 285 | the changes. This not only serves as documentation but also makes it 286 | easier to apply the same modifications to future versions. 287 | 288 | 289 | Checksums 290 | --------- 291 | 292 | The ``checksums.ini`` file contains checksums of the upstream 293 | tarball. It is autogenerated, so you just have to place the upstream 294 | tarball in the ``SAGE_ROOT/upstream/`` directory and run:: 295 | 296 | [user@localhost]$ sage -sh sage-fix-pkg-checksums 297 | 298 | 299 | Testing 300 | ======= 301 | 302 | If you have a new tarball that is not yet distributed with Sage, then 303 | you have to manually place it in the ``SAGE_ROOT/upstream/` 304 | directory. Then you can run the istallation via ``sage -f 305 | package_name``. If your package contains any 306 | :ref:`section-spkg-check`, run:: 307 | 308 | [user@localhost]$ SAGE_CHECK=yes sage -f package_name 309 | 310 | 311 | License information 312 | =================== 313 | 314 | If you are patching a standard Sage spkg, then you should make sure 315 | that the license information for that package is up-to-date, both in 316 | its ``SPKG.txt`` file and in the file ``SAGE_ROOT/COPYING.txt``. For 317 | example, if you are producing an spkg which upgrades the vanilla 318 | source to a new version, check whether the license changed between 319 | versions. 320 | -------------------------------------------------------------------------------- /developer/advanced_git.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-advanced-git: 2 | 3 | ============ 4 | Advanced Git 5 | ============ 6 | 7 | This chapter covers some advanced uses of git that go beyond what is 8 | required to work with branches. These features can be used in Sage 9 | development, but are not really necessary to contribute to Sage. If 10 | you are just getting started with Sage development, you should read 11 | :ref:`chapter-walk-through` instead. If you are new to git, please see 12 | :ref:`chapter-manual-git`. 13 | 14 | 15 | Detached Heads and Reviewing Tickets 16 | ==================================== 17 | 18 | Each commit is a snapshot of the Sage source tree at a certain 19 | point. So far, we always used commits organized in branches. But 20 | secretly the branch is just a shortcut for a particular commit, the 21 | head commit of the branch. But you can just go to a particular commit 22 | without a branch, this is called "detached head". If you have the 23 | commit already in your local history, you can directly check it 24 | out without requiring internet access:: 25 | 26 | [user@localhost sage]$ git checkout a63227d0636e29a8212c32eb9ca84e9588bbf80b 27 | Note: checking out 'a63227d0636e29a8212c32eb9ca84e9588bbf80b'. 28 | 29 | You are in 'detached HEAD' state. You can look around, make experimental 30 | changes and commit them, and you can discard any commits you make in this 31 | state without impacting any branches by performing another checkout. 32 | 33 | If you want to create a new branch to retain commits you create, you may 34 | do so (now or later) by using -b with the checkout command again. Example: 35 | 36 | git checkout -b new_branch_name 37 | 38 | HEAD is now at a63227d... Szekeres Snark Graph constructor 39 | 40 | If it is not stored in your local git repository, you need to download 41 | it from the trac server first:: 42 | 43 | [user@localhost sage]$ git fetch trac a63227d0636e29a8212c32eb9ca84e9588bbf80b 44 | From ssh://trac/sage 45 | * branch a63227d0636e29a8212c32eb9ca84e9588bbf80b -> FETCH_HEAD 46 | [user@localhost sage]$ git checkout FETCH_HEAD 47 | HEAD is now at a63227d... Szekeres Snark Graph constructor 48 | 49 | Either way, you end up with your current HEAD and working directory 50 | that is not associated to any local branch:: 51 | 52 | [user@localhost sage]$ git status 53 | # HEAD detached at a63227d 54 | nothing to commit, working directory clean 55 | 56 | This is perfectly fine. You can switch to an existing branch (with the 57 | usual ``git checkout my_branch``) and back to your detached head. 58 | 59 | Detached heads can be used to your advantage when reviewing 60 | tickets. Just check out the commit (look at the "Commit:" field on the 61 | trac ticket) that you are reviewing as a detached head. Then you can 62 | look at the changes and run tests in the detached head. When you are 63 | finished with the review, you just abandon the detached head. That way 64 | you never create a new local branch, so you don't have to type ``git 65 | branch -D my_branch`` at the end to delete the local branch that you 66 | created only to review the ticket. 67 | 68 | 69 | .. _section-git-recovery: 70 | 71 | Reset and Recovery 72 | ================== 73 | 74 | Git makes it very hard to truly mess up. Here is a short way to get 75 | back onto your feet, no matter what. First, if you just want to go 76 | back to a working Sage installation you can always abandon your 77 | working branch by switching to your local copy of the ``build_system`` 78 | branch:: 79 | 80 | [user@localhost sage]$ git checkout build_system 81 | 82 | As long as you did not make any changes to the ``build_system`` branch 83 | directly, this will give you back a working Sage. 84 | 85 | If you want to keep your branch but go back to a previous commit you 86 | can use the *reset* command. For this, look up the commit in the log 87 | which is some 40-digit hexadecimal number (the SHA1 hash). Then use 88 | ``git reset --hard`` to revert your files back to the previous state:: 89 | 90 | [user@localhost sage]$ git log 91 | ... 92 | commit eafaedad5b0ae2013f8ae1091d2f1df58b72bae3 93 | Author: First Last 94 | Date: Sat Jul 20 21:57:33 2013 -0400 95 | 96 | Commit message 97 | ... 98 | [user@localhost sage]$ git reset --hard eafae 99 | 100 | You only need to type the first couple of hex digits, git will 101 | complain if this does not uniquely specify a commit. Also, there is 102 | the useful abbreviation ``HEAD~`` for the previous commit and 103 | ``HEAD~n``, with some integer ``n``, for the n-th previous commit. 104 | 105 | Finally, perhaps the ultimate human error recovery tool is the 106 | reflog. This is a chronological history of git operations that you can 107 | undo if needed. For example, let us assume we messed up the *git 108 | reset* command and went back too far (say, 5 commits back). And, on 109 | top of that, deleted a file and committed that:: 110 | 111 | [user@localhost sage]$ git reset --hard HEAD~5 112 | [user@localhost sage]$ git rm sage 113 | [user@localhost sage]$ git commit -m "I shot myself into my foot" 114 | 115 | Now we cannot just checkout the repository from before the reset, 116 | because it is no longer in the history. However, here is the reflog:: 117 | 118 | [user@localhost sage]$ git reflog 119 | 2eca2a2 HEAD@{0}: commit: I shot myself into my foot 120 | b4d86b9 HEAD@{1}: reset: moving to HEAD~5 121 | af353bb HEAD@{2}: checkout: moving from some_branch to master 122 | 1142feb HEAD@{3}: checkout: moving from other_branch to some_branch 123 | ... 124 | 125 | The ``HEAD@{n}`` revisions are shortcuts for the history of git 126 | operations. Since we want to rewind to before the erroneous *git 127 | reset* command, we just have to reset back into the future:: 128 | 129 | [user@localhost sage]$ git reset --hard HEAD@{2} 130 | 131 | 132 | 133 | .. _section-git-rewriting-history: 134 | 135 | Rewriting History 136 | ================= 137 | 138 | Git allows you to rewrite history, but be careful: the SHA1 hash of a 139 | commit includes the parent's hash. This means that the hash really 140 | depends on the entire content of the working directory; every source 141 | file is in exactly the same state as when the hash was computed. This 142 | also means that you can't change history without modifying the 143 | hash. If others branched off your code and then you rewrite history, 144 | then the others are thoroughly screwed. So, ideally, you would only 145 | rewrite history on branches that you have not yet pushed to trac. 146 | 147 | As an advanced example, consider three commits A, B, C that were made 148 | on top of each other. For simplicity, we'll assume they just added a 149 | file named ``file_A.py``, ``file_B.py``, and ``file_C.py`` :: 150 | 151 | [user@localhost]$ git log --oneline 152 | 9621dae added file C 153 | 7873447 added file B 154 | bf817a5 added file A 155 | 5b5588e base commit 156 | 157 | Now, let's assume that the commit B was really independent and ought 158 | to be on a separate ticket. So we want to move it to a new branch, 159 | which we'll call ``second_branch``. First, branch off at the base 160 | commit before we added A:: 161 | 162 | [user@localhost]$ git checkout 5b5588e 163 | Note: checking out '5b5588e'. 164 | 165 | You are in 'detached HEAD' state. You can look around, make experimental 166 | changes and commit them, and you can discard any commits you make in this 167 | state without impacting any branches by performing another checkout. 168 | 169 | If you want to create a new branch to retain commits you create, you may 170 | do so (now or later) by using -b with the checkout command again. Example: 171 | 172 | git checkout -b new_branch_name 173 | 174 | HEAD is now at 5b5588e... base commit 175 | [user@localhost]$ git checkout -b second_branch 176 | Switched to a new branch 'second_branch' 177 | [user@localhost]$ git branch 178 | first_branch 179 | * second_branch 180 | [user@localhost]$ git log --oneline 181 | 5b5588e base commit 182 | 183 | Now, we make a copy of commit B in the current branch:: 184 | 185 | [user@localhost]$ git cherry-pick 7873447 186 | [second_branch 758522b] added file B 187 | 1 file changed, 1 insertion(+) 188 | create mode 100644 file_B.py 189 | [user@localhost]$ git log --oneline 190 | 758522b added file B 191 | 5b5588e base commit 192 | 193 | Note that this changes the SHA1 of the commit B, since its parent 194 | changed! Also, cherry-picking *copies* commits, it does not remove 195 | them from the source branch. So we now have to modify the first branch 196 | to exclude commit B, otherwise there will be two commits adding 197 | ``file_B.py`` and our two branches would conflict later when they are 198 | being merged into Sage. Hence, we first reset the first branch back to 199 | before B was added:: 200 | 201 | [user@localhost]$ git checkout first_branch 202 | Switched to branch 'first_branch' 203 | [user@localhost]$ git reset --hard bf817a5 204 | HEAD is now at bf817a5 added file A 205 | 206 | Now we still want commit C, so we cherry-pick it again. Note that this 207 | works even though commit C is, at this point, not included in any 208 | branch:: 209 | 210 | [user@localhost]$ git cherry-pick 9621dae 211 | [first_branch 5844535] added file C 212 | 1 file changed, 1 insertion(+) 213 | create mode 100644 file_C.py 214 | [user@localhost]$ git log --oneline 215 | 5844535 added file C 216 | bf817a5 added file A 217 | 5b5588e base commit 218 | 219 | And, again, we note that the SHA1 of commit C changed because its 220 | parent changed. Voila, now you have two branches where the first 221 | contains commits A, C and the second contains commit B. 222 | 223 | 224 | .. _section-git-interactive-rebase: 225 | 226 | Interactively Rebasing 227 | ====================== 228 | 229 | An alternative approach to :ref:`section-git-rewriting-history` is to 230 | use the interactive rebase feature. This will open an editor where you 231 | can modify the most recent commits. Again, this will naturally modify 232 | the hash of all changed commits and all of their children. 233 | 234 | Now we start by making an identical branch to the first branch:: 235 | 236 | [user@localhost]$ git log --oneline 237 | 9621dae added file C 238 | 7873447 added file B 239 | bf817a5 added file A 240 | 5b5588e base commit 241 | [user@localhost]$ git checkout -b second_branch 242 | Switched to a new branch 'second_branch' 243 | [user@localhost]$ git rebase -i HEAD~3 244 | 245 | This will open an editor with the last 3 (corresponding to ``HEAD~3``) 246 | commits and instuctions for how to modify them:: 247 | 248 | pick bf817a5 added file A 249 | pick 7873447 added file B 250 | pick 9621dae added file C 251 | 252 | # Rebase 5b5588e..9621dae onto 5b5588e 253 | # 254 | # Commands: 255 | # p, pick = use commit 256 | # r, reword = use commit, but edit the commit message 257 | # e, edit = use commit, but stop for amending 258 | # s, squash = use commit, but meld into previous commit 259 | # f, fixup = like "squash", but discard this commit's log message 260 | # x, exec = run command (the rest of the line) using shell 261 | # 262 | # These lines can be re-ordered; they are executed from top to bottom. 263 | # 264 | # If you remove a line here THAT COMMIT WILL BE LOST. 265 | # 266 | # However, if you remove everything, the rebase will be aborted. 267 | # 268 | # Note that empty commits are commented out 269 | 270 | To only use commit B, we delete the first and third line. Then save 271 | and edit your favorite editor, and your branch now consists only of 272 | the B commit. 273 | 274 | You still have to delete the B commit from the first branch, so you 275 | would go back (``git checkout first_branch``) and then run the same 276 | ``git rebase -i`` command and delete the B commit. 277 | 278 | -------------------------------------------------------------------------------- /developer/sagenb/development_workflow.rst: -------------------------------------------------------------------------------- 1 | .. _development-workflow: 2 | 3 | #################### 4 | Development workflow 5 | #################### 6 | 7 | You already have your own forked copy of the `Sage Notebook`_ repository, by 8 | following :ref:`forking`. You have :ref:`set-up-fork`. You have configured 9 | git by following :ref:`section-git-configuration`. Now you are ready for some real work. 10 | 11 | Workflow summary 12 | ================ 13 | 14 | In what follows we'll refer to the upstream Sage Notebook ``master`` branch, as 15 | "trunk". 16 | 17 | * Don't use your ``master`` branch for anything. Consider deleting it. 18 | * When you are starting a new set of changes, fetch any changes from trunk, 19 | and start a new *feature branch* from that. 20 | * Make a new branch for each separable set of changes |emdash| "one task, one 21 | branch" (`ipython git workflow`_). 22 | * Name your branch for the purpose of the changes - e.g. 23 | ``bugfix-for-issue-14`` or ``refactor-database-code``. 24 | * If you can possibly avoid it, avoid merging trunk or any other branches into 25 | your feature branch while you are working. 26 | * If you do find yourself merging from trunk, consider :ref:`rebase-on-trunk` 27 | * Ask on the `Sage Notebook mailing list`_ if you get stuck. 28 | * Ask for code review! 29 | 30 | This way of working helps to keep work well organized, with readable history. 31 | This in turn makes it easier for project maintainers (that might be you) to see 32 | what you've done, and why you did it. 33 | 34 | See `linux git workflow`_ and `ipython git workflow`_ for some explanation. 35 | 36 | Consider deleting your master branch 37 | ==================================== 38 | 39 | It may sound strange, but deleting your own ``master`` branch can help reduce 40 | confusion about which branch you are on. See `deleting master on github`_ for 41 | details. 42 | 43 | .. _update-mirror-trunk: 44 | 45 | Update the mirror of trunk 46 | ========================== 47 | 48 | First make sure you have done :ref:`linking-to-upstream`. 49 | 50 | From time to time you should fetch the upstream (trunk) changes from github:: 51 | 52 | git fetch upstream 53 | 54 | This will pull down any commits you don't have, and set the remote branches to 55 | point to the right commit. For example, 'trunk' is the branch referred to by 56 | (remote/branchname) ``upstream/master`` - and if there have been commits since 57 | you last checked, ``upstream/master`` will change after you do the fetch. 58 | 59 | .. _make-feature-branch: 60 | 61 | Make a new feature branch 62 | ========================= 63 | 64 | When you are ready to make some changes to the code, you should start a new 65 | branch. Branches that are for a collection of related edits are often called 66 | 'feature branches'. 67 | 68 | Making an new branch for each set of related changes will make it easier for 69 | someone reviewing your branch to see what you are doing. 70 | 71 | Choose an informative name for the branch to remind yourself and the rest of us 72 | what the changes in the branch are for. For example ``add-ability-to-fly``, or 73 | ``buxfix-for-issue-42``. 74 | 75 | :: 76 | 77 | # Update the mirror of trunk 78 | git fetch upstream 79 | # Make new feature branch starting at current trunk 80 | git branch my-new-feature upstream/master 81 | git checkout my-new-feature 82 | 83 | Generally, you will want to keep your feature branches on your public github_ 84 | fork of `Sage Notebook`_. To do this, you `git push`_ this new branch up to your 85 | github repo. Generally (if you followed the instructions in these pages, and by 86 | default), git will have a link to your github repo, called ``origin``. You push 87 | up to your own repo on github with:: 88 | 89 | git push origin my-new-feature 90 | 91 | In git >= 1.7 you can ensure that the link is correctly set by using the 92 | ``--set-upstream`` option:: 93 | 94 | git push --set-upstream origin my-new-feature 95 | 96 | From now on git will know that ``my-new-feature`` is related to the 97 | ``my-new-feature`` branch in the github repo. 98 | 99 | .. _edit-flow: 100 | 101 | The editing workflow 102 | ==================== 103 | 104 | Overview 105 | -------- 106 | 107 | :: 108 | 109 | # hack hack 110 | git add my_new_file 111 | git commit -am 'NF - some message' 112 | git push 113 | 114 | In more detail 115 | -------------- 116 | 117 | #. Make some changes 118 | #. See which files have changed with ``git status`` (see `git status`_). 119 | You'll see a listing like this one:: 120 | 121 | # On branch ny-new-feature 122 | # Changed but not updated: 123 | # (use "git add ..." to update what will be committed) 124 | # (use "git checkout -- ..." to discard changes in working directory) 125 | # 126 | # modified: README 127 | # 128 | # Untracked files: 129 | # (use "git add ..." to include in what will be committed) 130 | # 131 | # INSTALL 132 | no changes added to commit (use "git add" and/or "git commit -a") 133 | 134 | #. Check what the actual changes are with ``git diff`` (`git diff`_). 135 | #. Add any new files to version control ``git add new_file_name`` (see 136 | `git add`_). 137 | #. To commit all modified files into the local copy of your repo,, do 138 | ``git commit -am 'A commit message'``. Note the ``-am`` options to 139 | ``commit``. The ``m`` flag just signals that you're going to type a 140 | message on the command line. The ``a`` flag |emdash| you can just take on 141 | faith |emdash| or see `why the -a flag?`_ |emdash| and the helpful use-case 142 | description in the `tangled working copy problem`_. The `git commit`_ manual 143 | page might also be useful. 144 | #. To push the changes up to your forked repo on github, do a ``git 145 | push`` (see `git push`_). 146 | 147 | Ask for your changes to be reviewed or merged 148 | ============================================= 149 | 150 | When you are ready to ask for someone to review your code and consider a merge: 151 | 152 | #. Go to the URL of your forked repo, say 153 | ``http://github.com/your-user-name/sagenb``. 154 | #. Use the 'Switch Branches' dropdown menu near the top left of the page to 155 | select the branch with your changes: 156 | 157 | .. image:: branch_dropdown.png 158 | 159 | #. Click on the 'Pull request' button: 160 | 161 | .. image:: pull_button.png 162 | 163 | Enter a title for the set of changes, and some explanation of what you've 164 | done. Say if there is anything you'd like particular attention for - like a 165 | complicated change or some code you are not happy with. 166 | 167 | If you don't think your request is ready to be merged, just say so in your 168 | pull request message. This is still a good way of getting some preliminary 169 | code review. 170 | 171 | Some other things you might want to do 172 | ====================================== 173 | 174 | Delete a branch on github 175 | ------------------------- 176 | 177 | :: 178 | 179 | git checkout master 180 | # delete branch locally 181 | git branch -D my-unwanted-branch 182 | # delete branch on github 183 | git push origin :my-unwanted-branch 184 | 185 | (Note the colon ``:`` before ``test-branch``. See also: 186 | http://github.com/guides/remove-a-remote-branch 187 | 188 | Several people sharing a single repository 189 | ------------------------------------------ 190 | 191 | If you want to work on some stuff with other people, where you are all 192 | committing into the same repository, or even the same branch, then just 193 | share it via github. 194 | 195 | First fork Sage Notebook into your account, as from :ref:`forking`. 196 | 197 | Then, go to your forked repository github page, say 198 | ``http://github.com/your-user-name/sagenb`` 199 | 200 | Click on the 'Admin' button, and add anyone else to the repo as a 201 | collaborator: 202 | 203 | .. image:: pull_button.png 204 | 205 | Now all those people can do:: 206 | 207 | git clone git@githhub.com:your-user-name/sagenb.git 208 | 209 | Remember that links starting with ``git@`` use the ssh protocol and are 210 | read-write; links starting with ``git://`` are read-only. 211 | 212 | Your collaborators can then commit directly into that repo with the 213 | usual:: 214 | 215 | git commit -am 'ENH - much better code' 216 | git push origin master # pushes directly into your repo 217 | 218 | Explore your repository 219 | ----------------------- 220 | 221 | To see a graphical representation of the repository branches and 222 | commits:: 223 | 224 | gitk --all 225 | 226 | To see a linear list of commits for this branch:: 227 | 228 | git log 229 | 230 | You can also look at the `network graph visualizer`_ for your github 231 | repo. 232 | 233 | Finally the :ref:`section-fancy-log` ``lg`` alias will give you a 234 | reasonable text-based graph of the repository. 235 | 236 | .. _rebase-on-trunk: 237 | 238 | Rebasing on trunk 239 | ----------------- 240 | 241 | Let's say you thought of some work you'd like to do. You 242 | :ref:`update-mirror-trunk` and :ref:`make-feature-branch` called 243 | ``cool-feature``. At this stage trunk is at some commit, let's call it E. Now 244 | you make some new commits on your ``cool-feature`` branch, let's call them A, B, 245 | C. Maybe your changes take a while, or you come back to them after a while. In 246 | the meantime, trunk has progressed from commit E to commit (say) G:: 247 | 248 | A---B---C cool-feature 249 | / 250 | D---E---F---G trunk 251 | 252 | At this stage you consider merging trunk into your feature branch, and you 253 | remember that this here page sternly advises you not to do that, because the 254 | history will get messy. Most of the time you can just ask for a review, and not 255 | worry that trunk has got a little ahead. But sometimes, the changes in trunk 256 | might affect your changes, and you need to harmonize them. In this situation 257 | you may prefer to do a rebase. 258 | 259 | rebase takes your changes (A, B, C) and replays them as if they had been made to 260 | the current state of ``trunk``. In other words, in this case, it takes the 261 | changes represented by A, B, C and replays them on top of G. After the rebase, 262 | your history will look like this:: 263 | 264 | A'--B'--C' cool-feature 265 | / 266 | D---E---F---G trunk 267 | 268 | See `rebase without tears`_ for more detail. 269 | 270 | To do a rebase on trunk:: 271 | 272 | # Update the mirror of trunk 273 | git fetch upstream 274 | # go to the feature branch 275 | git checkout cool-feature 276 | # make a backup in case you mess up 277 | git branch tmp cool-feature 278 | # rebase cool-feature onto trunk 279 | git rebase --onto upstream/master upstream/master cool-feature 280 | 281 | In this situation, where you are already on branch ``cool-feature``, the last 282 | command can be written more succinctly as:: 283 | 284 | git rebase upstream/master 285 | 286 | When all looks good you can delete your backup branch:: 287 | 288 | git branch -D tmp 289 | 290 | If it doesn't look good you may need to have a look at 291 | :ref:`recovering-from-mess-up`. 292 | 293 | If you have made changes to files that have also changed in trunk, this may 294 | generate merge conflicts that you need to resolve - see the `git rebase`_ man 295 | page for some instructions at the end of the "Description" section. There is 296 | some related help on merging in the git user manual - see `resolving a merge`_. 297 | 298 | .. _recovering-from-mess-up: 299 | 300 | Recovering from mess-ups 301 | ------------------------ 302 | 303 | Sometimes, you mess up merges or rebases. Luckily, in git it is 304 | relatively straightforward to recover from such mistakes. 305 | 306 | If you mess up during a rebase:: 307 | 308 | git rebase --abort 309 | 310 | If you notice you messed up after the rebase:: 311 | 312 | # reset branch back to the saved point 313 | git reset --hard tmp 314 | 315 | If you forgot to make a backup branch:: 316 | 317 | # look at the reflog of the branch 318 | git reflog show cool-feature 319 | 320 | 8630830 cool-feature@{0}: commit: BUG: io: close file handles immediately 321 | 278dd2a cool-feature@{1}: rebase finished: refs/heads/my-feature-branch onto 11ee694744f2552d 322 | 26aa21a cool-feature@{2}: commit: BUG: lib: make seek_gzip_factory not leak gzip obj 323 | ... 324 | 325 | # reset the branch to where it was before the botched rebase 326 | git reset --hard cool-feature@{2} 327 | 328 | .. _rewriting-commit-history: 329 | 330 | Rewriting commit history 331 | ------------------------ 332 | 333 | .. note:: 334 | 335 | Do this only for your own feature branches. 336 | 337 | There's an embarassing typo in a commit you made? Or perhaps the you 338 | made several false starts you would like the posterity not to see. 339 | 340 | This can be done via *interactive rebasing*. 341 | 342 | Suppose that the commit history looks like this:: 343 | 344 | git log --oneline 345 | eadc391 Fix some remaining bugs 346 | a815645 Modify it so that it works 347 | 2dec1ac Fix a few bugs + disable 348 | 13d7934 First implementation 349 | 6ad92e5 * masked is now an instance of a new object, MaskedConstant 350 | 29001ed Add pre-nep for a copule of structured_array_extensions. 351 | ... 352 | 353 | and ``6ad92e5`` is the last commit in the ``cool-feature`` branch. Suppose we 354 | want to make the following changes: 355 | 356 | * Rewrite the commit message for ``13d7934`` to something more sensible. 357 | * Combine the commits ``2dec1ac``, ``a815645``, ``eadc391`` into a single one. 358 | 359 | We do as follows:: 360 | 361 | # make a backup of the current state 362 | git branch tmp HEAD 363 | # interactive rebase 364 | git rebase -i 6ad92e5 365 | 366 | This will open an editor with the following text in it:: 367 | 368 | pick 13d7934 First implementation 369 | pick 2dec1ac Fix a few bugs + disable 370 | pick a815645 Modify it so that it works 371 | pick eadc391 Fix some remaining bugs 372 | 373 | # Rebase 6ad92e5..eadc391 onto 6ad92e5 374 | # 375 | # Commands: 376 | # p, pick = use commit 377 | # r, reword = use commit, but edit the commit message 378 | # e, edit = use commit, but stop for amending 379 | # s, squash = use commit, but meld into previous commit 380 | # f, fixup = like "squash", but discard this commit's log message 381 | # 382 | # If you remove a line here THAT COMMIT WILL BE LOST. 383 | # However, if you remove everything, the rebase will be aborted. 384 | # 385 | 386 | To achieve what we want, we will make the following changes to it:: 387 | 388 | r 13d7934 First implementation 389 | pick 2dec1ac Fix a few bugs + disable 390 | f a815645 Modify it so that it works 391 | f eadc391 Fix some remaining bugs 392 | 393 | This means that (i) we want to edit the commit message for 394 | ``13d7934``, and (ii) collapse the last three commits into one. Now we 395 | save and quit the editor. 396 | 397 | Git will then immediately bring up an editor for editing the commit 398 | message. After revising it, we get the output:: 399 | 400 | [detached HEAD 721fc64] FOO: First implementation 401 | 2 files changed, 199 insertions(+), 66 deletions(-) 402 | [detached HEAD 0f22701] Fix a few bugs + disable 403 | 1 files changed, 79 insertions(+), 61 deletions(-) 404 | Successfully rebased and updated refs/heads/my-feature-branch. 405 | 406 | and the history looks now like this:: 407 | 408 | 0f22701 Fix a few bugs + disable 409 | 721fc64 ENH: Sophisticated feature 410 | 6ad92e5 * masked is now an instance of a new object, MaskedConstant 411 | 412 | If it went wrong, recovery is again possible as explained :ref:`above 413 | `. 414 | 415 | .. include:: links.inc 416 | -------------------------------------------------------------------------------- /developer/walk_through.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-walk-through: 2 | 3 | ======================== 4 | Sage Development Process 5 | ======================== 6 | 7 | This section is a concise overview of the Sage development process. In 8 | it, we will see how to make changes to the Sage source code and 9 | communicate these changes back to the Sage project. If you are a 10 | beginner to Sage development, this introductory guide is here to help 11 | you become familiar with the Sage development process. 12 | 13 | Sage comes with a set of developer scripts, which help you with common 14 | interactions with the bug tracker (see :ref:`chapter-sage-trac`) and 15 | with handling revisions of your code. The developer scripts use the 16 | git distributed revison control system under the hood which you'll 17 | have to install (see :ref:`chapter-git-setup`), but you do not need to 18 | know anything about it (see :ref:`chapter-manual-git` only if you want 19 | to). 20 | 21 | Most of the commands in the following section will not work unless you have an 22 | account on the bug tracker. If you want to contribute to Sage, it is a good 23 | idea to get an account now (see :ref:`section-trac-account`). 24 | 25 | We assume here that the ``sage`` executable of your development 26 | installation of Sage is in your ``PATH``. If this is not the case, you 27 | might have to replace ``sage`` by ``./sage`` or ``/path/to/sage`` in 28 | the following. You can also use the developer scripts from the Sage 29 | prompt. All commandline options to ``sage -dev`` are also available as 30 | methods of the ``dev`` object in a Sage session. That is, for example, 31 | to checkout a ticktet you can either run:: 32 | 33 | [user@localhost]$ sage -dev checkout --ticket 1729 34 | On ticket #1729 with associated local branch "ticket/1729". 35 | 36 | # Use "sage --dev merge" to include another ticket/branch. 37 | # Use "sage --dev commit" to save changes into a new commit. 38 | 39 | in a terminal or, equivalently, within Sage 40 | 41 | .. skip # don't actually doctest 42 | 43 | :: 44 | 45 | sage: dev.checkout(1729) 46 | On ticket #1729 with associated local branch "ticket/1729". 47 | 48 | # Use "dev.merge()" to include another ticket/branch. 49 | # Use "dev.commit()" to save changes in a new commit. 50 | 51 | Note that the number sign ``#`` (a.k.a. hash or pound sign) is the 52 | comment marker for both the shell and Python. So if you were to input 53 | ``#1729``, it will be interpreted as the comment "1729" and not passed 54 | to the development scripts. Always specify the ticket number as a 55 | plain number, without the number sign in front. 56 | 57 | .. warning:: 58 | 59 | During the transitional period it can happen that you end up 60 | on a branch where the developer scripts are not available or 61 | outdated. If this is the case, i.e., if ``sage -dev`` does not 62 | work properly anymore, run:: 63 | 64 | git pull git://trac.sagemath.org/sage.git master 65 | sage -b 66 | 67 | This will merge the latest version of the developer scripts 68 | with your current branch. After rebuilding the Sage library, 69 | the dev scripts will work again. 70 | 71 | 72 | .. _section-walkthrough-add: 73 | 74 | Contributing to the Sage Source Code 75 | ==================================== 76 | 77 | .. _section-walkthrough-add-create: 78 | 79 | Create a Ticket 80 | --------------- 81 | 82 | Suppose you have written an algorithm for calculating the last twin prime, and 83 | want to add it to Sage. You would first open a ticket for that:: 84 | 85 | [user@localhost]$ sage -dev create-ticket 86 | 87 | This will give you an editor in which you can give a summary and a 88 | description of what you want to do. If you are not sure which values 89 | to put for the other fields, you can leave the defaults or have a look 90 | at :ref:`section-trac-fields`. After you close the editor, a new 91 | ticket will be opened on the trac server. From that point on, everyone 92 | can see what you intend to do which lets us avoid duplicating work. If 93 | you want to cancel the creation of a ticket, then you can just save an 94 | empty file. This will abort the operation. 95 | 96 | Alternatively, you can use the `web interface to the Sage trac 97 | development server `_ to open a new ticket, 98 | just log in and click on "Create Ticket". 99 | 100 | 101 | .. _section-walkthrough-add-edit: 102 | 103 | Editing the Source Code 104 | ----------------------- 105 | 106 | If you want to work on a ticket which you or somebody else created, 107 | you first need to make a local "branch". The development scripts 108 | maintain a mapping between local branches and trac tickets. Creating a 109 | new local branch for a ticket is easy:: 110 | 111 | [user@localhost]$ sage -dev checkout --ticket 1729 112 | On ticket #1729 with associated local branch "ticket/1729". 113 | 114 | # Use "sage --dev merge" to include another ticket/branch. 115 | # Use "sage --dev commit" to save changes into a new commit. 116 | 117 | Essentially, a branch is a copy (except that it doesn't take up twice 118 | the space) of the Sage source code where you can store your 119 | modifications to the Sage source code and which you can upload to trac 120 | tickets. Your new branch is now called ``ticket/``. Unless 121 | you upload ("push") it, see below, it will only be on your local 122 | system and not visible to anyone else. 123 | 124 | At this point you can start editing the source code. The subsequent 125 | chapters of this developer guide explain how your code should look 126 | like to fit into Sage, and how we ensure high code quality 127 | throughout. Whenever you have reached one of your goals, you should 128 | make a *commit*. This takes a snapshot of the whole Sage source code 129 | that you have been working on and records the changes into your local 130 | branch:: 131 | 132 | [user@localhost]$ sage -dev commit 133 | Commit your changes to branch "ticket/1729"? [Yes/no] y 134 | 135 | # Use "sage --dev push" to push your commits to the trac server once you are 136 | # done. 137 | 138 | You will be asked to write a message describing your changes. It is 139 | common to write a one line summary, then a blank line, and then a 1-2 140 | paragraph explanation of your changes. If your changes are minor, then 141 | just the one-line summary can be enough. 142 | 143 | If you are working on a larger project, it can be useful to break up 144 | your work into multiple commits: Each commit is saved, enabling you to 145 | retrieve older versions of files from the repository. So, even if you 146 | accidentally delete something, you can get it back later. Also, if you 147 | find a mistake in one of your earlier commits, then you just correct 148 | it in the Sage source code and then add another commit on top. 149 | 150 | 151 | .. _section-walkthrough-add-push: 152 | 153 | Uploading Changes to Trac 154 | ------------------------- 155 | 156 | At some point, you may wish to share your changes with the rest of us: 157 | maybe it is ready for review, or maybe you are collaborating with 158 | someone and want to share your changes "up until now". This is simply 159 | done by:: 160 | 161 | [user@localhost]$ sage -dev push 162 | 163 | On trac, your remote branch will be called 164 | ``u//ticket/``. This name will automatically be 165 | added to the "Branch:" field on the ticket. Other developers then know 166 | where to find your work in the git repository. 167 | 168 | It is common to go through some iterations of ``sage -dev commit`` 169 | before you upload, and you will probably also have uploaded a few 170 | times before your changes are ready for review. 171 | 172 | If you are happy with the changes you uploaded, you want somebody else 173 | to review them, so they can be included into the next version of 174 | Sage. If your ticket is ready for review, you should set it to 175 | ``needs_review`` on the trac server. This can be done though the `web 176 | interface `_, or, alternatively, using the 177 | development scripts. For the latter, run:: 178 | 179 | [user@localhost]$ sage -dev edit-ticket 180 | 181 | This will give you an editor in which you can edit the ticket. Change the 182 | status to:: 183 | 184 | Status: needs_review 185 | 186 | And add yourself as an author for that ticket by inserting the following as the 187 | first line:: 188 | 189 | Authors: Your Real Name 190 | 191 | If you want to add an additional comment for potential reviewers, run:: 192 | 193 | [user@localhost]$ sage -dev comment 194 | 195 | 196 | .. _section-walkthrough-add-local: 197 | 198 | Starting Without a Ticket 199 | ------------------------- 200 | 201 | You might not want to create a trac ticket for your changes. For 202 | example, if you are only working on your own code or if you are making 203 | experimental changes that you are likely to throw away if they do not 204 | work out. In that case, you can also start a branch that only lives in 205 | your local repository. To do this, you use checkout but specify a 206 | branch name instead of the ticket number. For example, to create a new 207 | branch ``my_branch``, you would run:: 208 | 209 | [user@localhost]$ sage -dev checkout --branch my_branch 210 | 211 | This is assuming that you do not already have a local branch called 212 | ``my_branch``. If that were the case, you would just switch to the 213 | already-existing branch. Once on your branch, you can work with it as 214 | described in :ref:`section-walkthrough-add-edit`. 215 | 216 | You can upload your local branch later to an existing ticket. This 217 | works exactly like in the case where you started with a ticket, except 218 | that you have to specify the ticket number. That is:: 219 | 220 | [user@localhost]$ sage -dev push --ticket 221 | 222 | where you have to replace ```` with the number of the trac 223 | ticket. 224 | 225 | 226 | .. _section-walkthrough-merge: 227 | 228 | Merging 229 | ======= 230 | 231 | As soon as you are working on a bigger project that spans multiple 232 | tickets you will want to base your work on branches that have not been 233 | merged into Sage yet. This is natural in collaborative development, 234 | and in fact you are very much encouraged to split your work into 235 | logically different parts. Ideally, each part that is useful on its 236 | own and and can be reviewed independently should be a different 237 | ticket, instead of a huge patch bomb. 238 | 239 | For this purpose, you can incorporate branches from other tickets (or 240 | just other local branches) into your current branch. This is called 241 | merging, and all it does is include commits from other branches into 242 | your current branch. In particular, this is done when a new Sage 243 | release is made: the finished tickets are merged with the Sage master 244 | and the result is the next Sage version. Git is smart enough to not 245 | merge commits twice. In particular, it is possible to merge two 246 | branches, one of which had already merged the other branch. 247 | 248 | The syntax for merging is easy. If the code that you want to 249 | incorporate is on a trac ticket number ````, use:: 250 | 251 | [user@localhost]$ sage -dev merge --ticket 252 | 253 | Optionally, you can add the merged ticket to the trac "Dependency:" 254 | field. Note that the merged commits become part of the current branch, 255 | regardless of whether they are noted on trac. Adding a dependency 256 | implies that the dependency must be reviewed first. After the 257 | dependency is reviewed, the commits that came from the dependency are 258 | no longer listed in the output of ``sage -dev diff``. 259 | 260 | .. warning:: 261 | 262 | You should avoid merging tickets both ways. Once ticket A merged 263 | ticket B and ticket B merged ticket A, there is no way to 264 | distinguish commits that were originally made in ticket A or in 265 | ticket B. Effectively, merging both ways combines the branches and 266 | makes individual review impossible. Effectively, you should never 267 | merge unless one of the following holds: 268 | 269 | * Either two tickets conflict, then you have to merge one into the 270 | other in order to resolve the merge conflict. 271 | 272 | * Or you definitely need a feature that has been developed as part 273 | of another branch. 274 | 275 | A special case of merging is merging in the ``master`` branch. This 276 | brings your local branch up to date with the newest Sage version. The 277 | above warning against unnecessary merges still applies, though. Try to 278 | do all of your development with the Sage version that you originally 279 | started with. The only reason for merging in the master branch is if 280 | you need a new feature or if your branch conflicts. 281 | 282 | 283 | .. _section-walkthrough-review: 284 | 285 | Reviewing 286 | ========= 287 | 288 | Now suppose you want to review the existing work on a ticket, such as the one 289 | you created in the last section. For definiteness, suppose you want to review 290 | #12270. You would do that as follows:: 291 | 292 | [user@localhost]$ sage -dev checkout --ticket 12270 293 | 294 | This command will download the branch on Trac in case you do not have any local 295 | work on ticket 12270. (If you do, you may have to merge your changes; see 296 | below). You can now test the ticket; you'll probably want to call ``make`` or 297 | ``sage -b`` first to rebuild Sage with the changes. Another important 298 | command is:: 299 | 300 | [user@localhost]$ sage -dev diff 301 | 302 | which lists all souce code changes that are part of the current 303 | branch. That is, it lists the changes from the current master to the 304 | current branch. If the ticket were to be positively reviewed, this is 305 | the code that will be added to Sage. Note that there is no way to 306 | "exclude dependencies", just as there is no guarantee that unreviewed 307 | dependencies will become part of Sage. The best way to exclude 308 | dependencies from the diff output is to review them. Once the 309 | dependency becomes part of the master branch, they are automatically 310 | removed. 311 | 312 | Most likely, your will want to add a comment to the ticket as part of 313 | your review:: 314 | 315 | [user@localhost]$ sage -dev comment 316 | 317 | This will open a text editor in which you can type, and upload the 318 | result to Trac. 319 | 320 | It is also possible that you make some changes to the code as part of 321 | your review. After you have done that, you can upload your changes 322 | back to trac:: 323 | 324 | [user@localhost]$ sage -dev commit 325 | [user@localhost]$ sage -dev push 326 | 327 | This will update the ticket to now point to your branch, including 328 | your changes. Your branch is based on the original author's branch, so 329 | s/he can easily incorporate your changes into his/her own branch (see 330 | below). 331 | 332 | 333 | .. _section-walkthrough-collaborate: 334 | 335 | Collaboration 336 | ============= 337 | 338 | It is very easy to collaborate by just going through the above steps any number of times:: 339 | 340 | # developer 1 341 | 342 | sage -dev commit 343 | sage -dev push 344 | 345 | # developer 2 346 | sage -dev pull 347 | 348 | sage -dev commit 349 | sage -dev push 350 | 351 | # developer 1 352 | sage -dev pull 353 | 354 | sage -dev commit 355 | sage -dev push 356 | (etc) 357 | 358 | The obvious problem is when you both work on the same ticket simultaneously:: 359 | 360 | # developer 1 361 | 362 | sage -dev commit 363 | sage -dev push 364 | 365 | # developer 2 366 | 367 | sage -dev commit 368 | sage -dev push 369 | Changes not compatible with remote branch 370 | u//ticket/12270; consider 371 | downloading first. Are you sure you want to continue? 372 | 373 | Developer 2 should probably select ``No``, and do as suggested:: 374 | 375 | sage -dev pull 376 | 377 | This will try to merge the changes developer 1 made into the ones that 378 | developer 2 made. The latter should check whether all seems okay, and 379 | if so, upload the changes:: 380 | 381 | sage -dev push # works now 382 | 383 | It is possible that the changes cannot be automatically merged. In 384 | that case, developer 2 will have to do some manual fixup after 385 | downloading and before uploading:: 386 | 387 | 388 | sage -dev commit 389 | sage -dev push 390 | 391 | 392 | -------------------------------------------------------------------------------- /developer/static/flowchart.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | Open Ticket 21 | 22 | 23 | 24 | 25 | 26 | 27 | Create branch 28 | on trac 29 | 30 | 31 | 32 | 33 | 34 | 35 | Review 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | Fill in Author 53 | and Reviewer 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | Merge into Sage 78 | 79 | 80 | 81 | 82 | 83 | 84 | Who makes 85 | corrections? 86 | 87 | 88 | 89 | 90 | 91 | 92 | Comment 93 | 94 | 95 | 96 | 97 | 98 | 99 | Commit 100 | 101 | 102 | 103 | 104 | 105 | 106 | Upload 107 | 108 | 109 | 110 | 111 | 112 | 113 | Change "Branch" 114 | 115 | 116 | 117 | 118 | 119 | 120 | Commit response 121 | 122 | 123 | 124 | 125 | 126 | 127 | Upload 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 | Author/Reviewer 185 | switch roles 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | Author 195 | 196 | 197 | Author 198 | 199 | 200 | Reviewer 201 | 202 | 203 | Author 204 | 205 | 206 | Reviewer 207 | 208 | 209 | Release Manager 210 | 211 | 212 | Reviewer 213 | 214 | 215 | Reviewer 216 | 217 | 218 | Reviewer 219 | 220 | 221 | -------------------------------------------------------------------------------- /developer/coding_in_cython.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-cython: 2 | 3 | ================ 4 | Coding in Cython 5 | ================ 6 | 7 | This chapter discusses Cython, which is a compiled language based on 8 | Python. The major advantage it has over Python is that code can be 9 | much faster (sometimes orders of magnitude) and can directly call 10 | C and C++ code. As Cython is essentially a superset of the Python 11 | language, one often doesn’t make a distinction between Cython and 12 | Python code in Sage (e.g. one talks of the “Sage Python Library” 13 | and “Python Coding Conventions”). 14 | 15 | Python is an interpreted language and has no declared data types for 16 | variables. These features make it easy to write and debug, but Python 17 | code can sometimes be slow. Cython code can look a lot like Python, 18 | but it gets translated into C code (often very efficient C code) and 19 | then compiled. Thus it offers a language which is familiar to Python 20 | developers, but with the potential for much greater speed. Cython also 21 | allows Sage developers to interface with C and C++ much easier than 22 | using the Python C API directly. 23 | 24 | Cython is a compiled version of Python. It was originally based on 25 | Pyrex but has changed based on what Sage's developers needed; Cython 26 | has been developed in concert with Sage. However, it is an independent 27 | project now, which is used beyond the scope of Sage. As such, it is a 28 | young, but developing language, with young, but developing 29 | documentation. See its web page, http://www.cython.org/, for the most 30 | up-to-date information. 31 | 32 | 33 | 34 | Writing Cython Code in Sage 35 | =========================== 36 | 37 | There are several ways to create and build Cython code in Sage. 38 | 39 | #. In the Sage Notebook, begin any cell with ``%cython``. When you 40 | evaluate that cell, 41 | 42 | #. It is saved to a file. 43 | 44 | #. Cython is run on it with all the standard Sage libraries 45 | automatically linked if necessary. 46 | 47 | #. The resulting shared library file (``.so`` / ``.dll`` / 48 | ``.dylib``) is then loaded into your running instance of Sage. 49 | 50 | #. The functionality defined in that cell is now available for you 51 | to use in the notebook. Also, the output cell has a link to the C 52 | program that was compiled to create the ``.so`` file. 53 | 54 | #. A ``cpdef`` or ``def`` function, say ``testfunction``, defined in 55 | a ``%cython`` cell in a worksheet can be imported and made available 56 | in a different ``%cython`` cell within the same worksheet by 57 | importing it as shown below:: 58 | 59 | %cython 60 | from __main__ import testfunction 61 | 62 | #. Create an ``.spyx`` file and attach or load it from the command 63 | line. This is similar to creating a ``%cython`` cell in the 64 | notebook but works completely from the command line (and not from 65 | the notebook). 66 | 67 | #. Create a ``.pyx`` file and add it to the Sage library. 68 | 69 | #. First, add a listing for the Cython extension to the variable 70 | ``ext_modules`` in the file 71 | ``SAGE_ROOT/src/module_list.py``. See the 72 | ``distutils.extension.Extension`` class for more information on 73 | creating a new Cython extension. 74 | 75 | #. Run ``sage -b`` to rebuild Sage. 76 | 77 | For example, the file 78 | ``SAGE_ROOT/src/sage/graphs/chrompoly.pyx`` has the lines:: 79 | 80 | Extension('sage.graphs.chrompoly', 81 | sources = ['sage/graphs/chrompoly.pyx']), 82 | 83 | in ``module_list.py``. In addition, ``sage.graphs`` is included in 84 | the ``packages`` list under the Distutils section of ``setup.py`` 85 | since ``chrompoly.pyx`` is contained in the directory 86 | ``sage/graphs``. 87 | 88 | 89 | Special Pragmas 90 | =============== 91 | 92 | If Cython code is either attached or loaded as a ``.spyx`` file or 93 | loaded from the notebook as a ``%cython`` block, the following 94 | pragmas are available: 95 | 96 | * clang --- may be either c or c++ indicating whether a C or C++ 97 | compiler should be used. 98 | 99 | * clib --- additional libraries to be linked in, the space separated 100 | list is split and passed to distutils. 101 | 102 | * cinclude --- additional directories to search for header files. The 103 | space separated list is split and passed to distutils. 104 | 105 | * cfile -- additional C or C++ files to be compiled 106 | 107 | * cargs -- additional parameters passed to the compiler 108 | 109 | For example:: 110 | 111 | #clang C++ 112 | #clib givaro 113 | #cinclude /usr/local/include/ 114 | #cargs -ggdb 115 | #cfile foo.c 116 | 117 | 118 | Attaching or Loading .spyx Files 119 | ================================ 120 | 121 | The easiest way to try out Cython without having to learn anything 122 | about distutils, etc., is to create a file with the extension 123 | ``spyx``, which stands for "Sage Pyrex": 124 | 125 | #. Create a file ``power2.spyx``. 126 | 127 | #. Put the following in it:: 128 | 129 | def is2pow(n): 130 | while n != 0 and n%2 == 0: 131 | n = n >> 1 132 | return n == 1 133 | 134 | #. Start the Sage command line interpreter and load the ``spyx`` file 135 | (this will fail if you do not have a C compiler installed). 136 | 137 | .. skip 138 | 139 | :: 140 | 141 | sage: load "power2.spyx" 142 | Compiling power2.spyx... 143 | sage: is2pow(12) 144 | False 145 | 146 | Note that you can change ``power2.spyx``, then load it again and it 147 | will be recompiled on the fly. You can also attach ``power2.spyx`` so 148 | it is reloaded whenever you make changes: 149 | 150 | .. skip 151 | 152 | :: 153 | 154 | sage: attach "power2.spyx" 155 | 156 | Cython is used for its speed. Here is a timed test on a 2.6 GHz 157 | Opteron: 158 | 159 | .. skip 160 | 161 | :: 162 | 163 | sage: %time [n for n in range(10^5) if is2pow(n)] 164 | [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536] 165 | CPU times: user 0.60 s, sys: 0.00 s, total: 0.60 s 166 | Wall time: 0.60 s 167 | 168 | Now, the code in the file ``power2.spyx`` is valid Python, and if we 169 | copy this to a file ``powerslow.py`` and load that, we get the 170 | following: 171 | 172 | .. skip 173 | 174 | :: 175 | 176 | sage: load "powerslow.py" 177 | sage: %time [n for n in range(10^5) if is2pow(n)] 178 | [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768, 65536] 179 | CPU times: user 1.01 s, sys: 0.04 s, total: 1.05 s 180 | Wall time: 1.05 s 181 | 182 | By the way, we could gain even a little more speed with the Cython 183 | version with a type declaration, by changing ``def is2pow(n):`` to 184 | ``def is2pow(unsigned int n):``. 185 | 186 | 187 | .. _section_sig_on: 188 | 189 | Interrupt and Signal Handling 190 | ============================= 191 | 192 | When writing Cython code for Sage, special care must be taken to 193 | ensure the code can be interrupted with ``CTRL-C``. Since Cython 194 | optimizes for speed, Cython normally does not check for interrupts. 195 | For example, code like the following cannot be interrupted: 196 | 197 | .. skip 198 | 199 | :: 200 | 201 | sage: cython('while True: pass') # DON'T DO THIS 202 | 203 | While this is running, pressing ``CTRL-C`` has no effect. The only 204 | way out is to kill the Sage process. On certain systems, you can 205 | still quit Sage by typing ``CTRL-\`` (sending a Quit signal) instead 206 | of ``CTRL-C``. 207 | 208 | Using ``sig_on()`` and ``sig_off()`` 209 | ------------------------------------ 210 | 211 | .. highlight:: cython 212 | 213 | To enable interrupt handling, use the ``sig_on()`` and ``sig_off()`` functions. 214 | You should put ``sig_on()`` *before* and ``sig_off()`` *after* any Cython code 215 | which could potentially take a long time. 216 | These two *must always* be called in **pairs**, i.e. every 217 | ``sig_on()`` must be matched by a closing ``sig_off()``. 218 | 219 | In practice your function will probably look like:: 220 | 221 | def sig_example(): 222 | # (some harmless initialization) 223 | sig_on() 224 | # (a long computation here, potentially calling a C library) 225 | sig_off() 226 | # (some harmless post-processing) 227 | return something 228 | 229 | You can put ``sig_on()`` and ``sig_off()`` in all kinds of Cython 230 | functions: ``def``, ``cdef`` or ``cpdef``. You cannot put them in 231 | pure Python code (i.e. files with extension ``.py``). 232 | 233 | It is possible to put ``sig_on()`` and ``sig_off()`` in different 234 | functions, provided that ``sig_off()`` is called before the function 235 | which calls ``sig_on()`` returns. The following code is *invalid*:: 236 | 237 | # INVALID code because we return from function foo() 238 | # without calling sig_off() first. 239 | cdef foo(): 240 | sig_on() 241 | 242 | def f1(): 243 | foo() 244 | sig_off() 245 | 246 | But the following is valid since you cannot call ``foo`` 247 | interactively:: 248 | 249 | cdef int foo(): 250 | sig_off() 251 | return 2+2 252 | 253 | def f1(): 254 | sig_on() 255 | return foo() 256 | 257 | For clarity however, it is best to avoid this. One good example where 258 | the above makes sense is the ``new_gen()`` function in 259 | :ref:`section-pari-library`. 260 | 261 | A common mqistake is to put ``sig_off()`` towards the end of a 262 | function (before the ``return``) when the function has multiple 263 | ``return`` statements. So make sure there is a ``sig_off()`` before 264 | *every* ``return`` (and also before every ``raise``). 265 | 266 | .. WARNING:: 267 | 268 | The code inside ``sig_on()`` should be pure C or Cython code. If 269 | you call Python code, an interrupt is likely to mess up Python. 270 | 271 | Also, when an interrupt occurs inside ``sig_on()``, code execution 272 | immediately stops without cleaning up. For example, any memory 273 | allocated inside ``sig_on()`` is lost. See :ref:`advanced-sig` 274 | for ways to deal with this. 275 | 276 | When the user presses ``CTRL-C`` inside ``sig_on()``, execution will 277 | jump back to ``sig_on()`` (the first one if there is a stack) and 278 | ``sig_on()`` will raise ``KeyboardInterrupt``. These can be handled 279 | just like other Python exceptions:: 280 | 281 | def catch_interrupts(): 282 | try: 283 | sig_on() # This MUST be inside the try 284 | # (some long computation) 285 | sig_off() 286 | except KeyboardInterrupt: 287 | # (handle interrupt) 288 | 289 | Certain C libraries in Sage are written in a way that they will raise 290 | Python exceptions: NTL and PARI are examples of this. NTL can raise 291 | ``RuntimeError`` and PARI can raise ``PariError``. Since these use 292 | the ``sig_on()`` mechanism, these exceptions can be caught just like 293 | the ``KeyboardInterrupt`` in the example above. 294 | 295 | It is possible to stack ``sig_on()`` and ``sig_off()``. If you do 296 | this, the effect is exactly the same as if only the outer 297 | ``sig_on()``/``sig_off()`` was there. The inner ones will just change 298 | a reference counter and otherwise do nothing. Make sure that the 299 | number of ``sig_on()`` calls equal the number of ``sig_off()`` calls:: 300 | 301 | def stack_sig_on(): 302 | sig_on() 303 | sig_on() 304 | sig_on() 305 | # (some code) 306 | sig_off() 307 | sig_off() 308 | sig_off() 309 | 310 | Extra care must be taken with exceptions raised inside ``sig_on()``. 311 | The problem is that, if you do not do anything special, the 312 | ``sig_off()`` will never be called if there is an exception. If you 313 | need to *raise* an exception yourself, call a ``sig_off()`` before 314 | it:: 315 | 316 | def raising_an_exception(): 317 | sig_on() 318 | # (some long computation) 319 | if (something_failed): 320 | sig_off() 321 | raise RuntimeError("something failed") 322 | # (some more computation) 323 | sig_off() 324 | return something 325 | 326 | Alternatively, you can use ``try``/``finally`` which will also catch 327 | exceptions raised by subroutines inside the ``try``:: 328 | 329 | def try_finally_example(): 330 | sig_on() 331 | try: 332 | # (some long computation, potentially raising exceptions) 333 | finally: 334 | sig_off() 335 | return something 336 | 337 | 338 | Other signals 339 | ------------- 340 | 341 | Apart from handling interrupts, ``sig_on()`` provides more general 342 | signal handling. Indeed, if the code inside ``sig_on()`` would 343 | generate a segmentation fault or call the C function ``abort()`` (or 344 | more generally, raise any of SIGSEGV, SIGILL, SIGABRT, SIGFPE, 345 | SIGBUS), this is caught by the interrupt framework and a 346 | ``RuntimeError`` is raised:: 347 | 348 | cdef extern from 'stdlib.h': 349 | void abort() 350 | 351 | def abort_example(): 352 | sig_on() 353 | abort() 354 | sig_off() 355 | 356 | .. code-block:: python 357 | 358 | sage: abort_example() 359 | Traceback (most recent call last): 360 | ... 361 | RuntimeError: Aborted 362 | 363 | This exception can then be caught as explained above. This means that 364 | ``abort()`` can be used as an alternative to exceptions within 365 | ``sig_on()``/``sig_off()``. A segmentation fault unguarded by 366 | ``sig_on()`` would simply terminate Sage. 367 | 368 | Instead of ``sig_on()``, there is also a function ``sig_str(s)``, 369 | which takes a C string ``s`` as argument. It behaves the same as 370 | ``sig_on()``, except that the string ``s`` will be used as a string 371 | for the exception. ``sig_str(s)`` should still be closed by 372 | ``sig_off()``. Example Cython code:: 373 | 374 | cdef extern from 'stdlib.h': 375 | void abort() 376 | 377 | def abort_example_with_sig_str(): 378 | sig_str("custom error message") 379 | abort() 380 | sig_off() 381 | 382 | Executing this gives: 383 | 384 | .. code-block:: python 385 | 386 | sage: abort_example_with_sig_str() 387 | Traceback (most recent call last): 388 | ... 389 | RuntimeError: custom error message 390 | 391 | With regard to ordinary interrupts (i.e. SIGINT), ``sig_str(s)`` 392 | behaves the same as ``sig_on()``: a simple ``KeyboardInterrupt`` is 393 | raised. 394 | 395 | 396 | .. _advanced-sig: 397 | 398 | Advanced functions 399 | ------------------ 400 | 401 | There are several more specialized functions for dealing with 402 | interrupts. The function ``sig_check()`` behaves exactly as 403 | ``sig_on(); sig_off()`` (except that ``sig_check()`` is faster since 404 | it does not involve a ``setjmp()`` call). 405 | 406 | ``sig_check()`` can be used to check for pending interrupts. If an 407 | interrupt happens outside of a ``sig_on()``/``sig_off()`` block, it 408 | will be caught by the next ``sig_check()`` or ``sig_on()``. 409 | 410 | The typical use case for ``sig_check()`` is within tight loops doing 411 | complicated stuff (mixed Python and Cython code, potentially raising 412 | exceptions). It gives more control, because a ``KeyboardInterrupt`` 413 | can *only* be raised during ``sig_check()``:: 414 | 415 | def sig_check_example(): 416 | for x in foo: 417 | # (one loop iteration which does not take a long time) 418 | sig_check() 419 | 420 | As mentioned above, ``sig_on()`` makes no attempt to clean anything up 421 | (restore state or freeing memory) when an interrupt occurs. In fact, 422 | it would be impossible for ``sig_on()`` to do that. If you want to 423 | add some cleanup code, use ``sig_on_no_except()`` for this. This 424 | function behaves *exactly* like ``sig_on()``, except that any 425 | exception raised (either ``KeyboardInterrupt`` or ``RuntimeError``) is 426 | not yet passed to Python. Essentially, the exception is there, but we 427 | prevent Cython from looking for the exception. Then 428 | ``cython_check_exception()`` can be used to make Cython look for the 429 | exception. 430 | 431 | Normally, ``sig_on_no_except()`` returns 1. If a signal was caught 432 | and an exception raised, ``sig_on_no_except()`` instead returns 0. 433 | The following example shows how to use ``sig_on_no_except()``:: 434 | 435 | def no_except_example(): 436 | if not sig_on_no_except(): 437 | # (clean up messed up internal state) 438 | 439 | # Make Cython realize that there is an exception. 440 | # It will look like the exception was actually raised 441 | # by cython_check_exception(). 442 | cython_check_exception() 443 | # (some long computation, messing up internal state of objects) 444 | sig_off() 445 | 446 | There is also a function ``sig_str_no_except(s)`` which is analogous 447 | to ``sig_str(s)``. 448 | 449 | .. NOTE:: 450 | 451 | See the file :file:`SAGE_ROOT/src/sage/tests/interrupt.pyx` 452 | for more examples of how to use the various ``sig_*()`` functions. 453 | 454 | Testing interrupts 455 | ------------------ 456 | 457 | .. highlight:: python 458 | 459 | When writing :ref:`section-docstrings`, 460 | one sometimes wants to check that certain code can be interrupted in a clean way. 461 | In the module ``sage.tests.interrupt``, there is a function 462 | ``interrupt_after_delay(ms_delay = 500)`` which can be used to test interrupts. 463 | That function simulates a ``CTRL-C`` (by sending SIGINT) 464 | after ``ms_delay`` milliseconds. 465 | 466 | The following is an example of a doctest demonstrating that 467 | the function ``factor()`` can be interrupted:: 468 | 469 | sage: import sage.tests.interrupt 470 | sage: try: 471 | ... sage.tests.interrupt.interrupt_after_delay() 472 | ... factor(10^1000 + 3) 473 | ... except KeyboardInterrupt: 474 | ... print "ok!" 475 | ok! 476 | 477 | 478 | Unpickling Cython Code 479 | ====================== 480 | 481 | Pickling for python classes and extension classes, such as cython, is 482 | different. This is discussed in the `python pickling 483 | documentation`_. For the unpickling of extension classes you need to 484 | write a :meth:`__reduce__` method which typically returns a tuple 485 | ``(f, args,...)`` such that ``f(*args)`` returns (a copy of) the 486 | original object. As an example, the following code snippet is the 487 | :meth:`~sage.rings.integer.Integer.__reduce__` method from 488 | :class:`sage.rings.integer.Integer`:: 489 | 490 | def __reduce__(self): 491 | ''' 492 | This is used when pickling integers. 493 | 494 | EXAMPLES:: 495 | 496 | sage: n = 5 497 | sage: t = n.__reduce__(); t 498 | (, ('5',)) 499 | sage: t[0](*t[1]) 500 | 5 501 | sage: loads(dumps(n)) == n 502 | True 503 | ''' 504 | # This single line below took me HOURS to figure out. 505 | # It is the *trick* needed to pickle Cython extension types. 506 | # The trick is that you must put a pure Python function 507 | # as the first argument, and that function must return 508 | # the result of unpickling with the argument in the second 509 | # tuple as input. All kinds of problems happen 510 | # if we don't do this. 511 | return sage.rings.integer.make_integer, (self.str(32),) 512 | 513 | 514 | .. _python pickling documentation: http://docs.python.org/library/pickle.html#pickle-protocol 515 | 516 | -------------------------------------------------------------------------------- /developer/coding_in_python.rst: -------------------------------------------------------------------------------- 1 | .. _chapter-python: 2 | 3 | ========================= 4 | Coding in Python for Sage 5 | ========================= 6 | 7 | This chapter discusses some issues with, and advice for, coding in 8 | Sage. 9 | 10 | 11 | Design 12 | ====== 13 | 14 | If you are planning to develop some new code for Sage, design is 15 | important. So think about what your program will do and how that fits 16 | into the structure of Sage. In particular, much of Sage is implemented 17 | in the object-oriented language Python, and there is a hierarchy of 18 | classes that organize code and functionality. For example, if you 19 | implement elements of a ring, your class should derive from 20 | ``sage.structure.element.RingElement``, rather than starting from 21 | scratch. Try to figure out how your code should fit in with other Sage 22 | code, and design it accordingly. 23 | 24 | 25 | Special Sage Functions 26 | ====================== 27 | 28 | Functions with leading and trailing double underscores ``__XXX__`` are 29 | all predefined by Python. Functions with leading and trailing single 30 | underscores ``_XXX_`` are defined for Sage. Functions with a single 31 | leading underscore are meant to be semi-private, and those with a 32 | double leading underscore are considered really private. Users can 33 | create functions with leading and trailing underscores. 34 | 35 | Just as Python has many standard special methods for objects, Sage 36 | also has special methods. They are typically of the form ``_XXX_``. 37 | In a few cases, the trailing underscore is not included, but this will 38 | eventually be changed so that the trailing underscore is always 39 | included. This section describes these special methods. 40 | 41 | All objects in Sage should derive from the Cython extension class 42 | ``SageObject``:: 43 | 44 | from sage.ext.sage_object import SageObject 45 | 46 | class MyClass(SageObject,...): 47 | ... 48 | 49 | or from some other already existing Sage class:: 50 | 51 | from sage.rings.ring import Algebra 52 | 53 | class MyFavoriteAlgebra(Algebra): 54 | ... 55 | 56 | You should implement the ``_latex_`` and ``_repr_`` method for every 57 | object. The other methods depend on the nature of the object. 58 | 59 | 60 | LaTeX representation 61 | -------------------- 62 | 63 | Every object ``x`` in Sage should support the command ``latex(x)``, so 64 | that any Sage object can be easily and accurately displayed via 65 | LaTeX. Here is how to make a class (and therefore its instances) 66 | support the command ``latex``. 67 | 68 | #. Define a method ``_latex_(self)`` that returns a LaTeX 69 | representation of your object. It should be something that can be 70 | typeset correctly within math mode. Do not include opening and 71 | closing $'s. 72 | 73 | #. Often objects are built up out of other Sage objects, and these 74 | components should be typeset using the ``latex`` function. For 75 | example, if ``c`` is a coefficient of your object, and you want to 76 | typeset ``c`` using LaTeX, use ``latex(c)`` instead of 77 | ``c._latex_()``, since ``c`` might not have a ``_latex_`` method, 78 | and ``latex(c)`` knows how to deal with this. 79 | 80 | #. Do not forget to include a docstring and an example that 81 | illustrates LaTeX generation for your object. 82 | 83 | #. You can use any macros included in ``amsmath``, ``amssymb``, or 84 | ``amsfonts``, or the ones defined in 85 | ``SAGE_ROOT/doc/commontex/macros.tex``. 86 | 87 | An example template for a ``_latex_`` method follows: 88 | 89 | .. skip 90 | 91 | :: 92 | 93 | class X: 94 | ... 95 | def _latex_(self): 96 | r""" 97 | Return the LaTeX representation of X. 98 | 99 | EXAMPLES:: 100 | 101 | sage: a = X(1,2) 102 | sage: latex(a) 103 | '\\frac{1}{2}' 104 | """ 105 | return '\\frac{%s}{%s}'%(latex(self.numer), latex(self.denom)) 106 | 107 | As shown in the example, ``latex(a)`` will produce LaTeX code 108 | representing the object ``a``. Calling ``view(a)`` will display the 109 | typeset version of this. 110 | 111 | 112 | Print representation 113 | -------------------- 114 | 115 | The standard Python printing method is ``__repr__(self)``. In Sage, 116 | that is for objects that derive from ``SageObject`` (which is 117 | everything in Sage), instead define ``_repr_(self)``. This is 118 | preferable because if you only define ``_repr_(self)`` and not 119 | ``__repr__(self)``, then users can rename your object to print however 120 | they like. Also, some objects should print differently depending on 121 | the context. 122 | 123 | Here is an example of the ``_latex_`` and ``_repr_`` functions for the 124 | ``Pi`` class. It is from the file 125 | ``SAGE_ROOT/devel/sage/sage/functions/constants.py``:: 126 | 127 | class Pi(Constant): 128 | """ 129 | The ratio of a circle's circumference to its diameter. 130 | 131 | EXAMPLES:: 132 | 133 | sage: pi 134 | pi 135 | sage: float(pi) # rel tol 1e-10 136 | 3.1415926535897931 137 | """ 138 | ... 139 | def _repr_(self): 140 | return "pi" 141 | 142 | def _latex_(self): 143 | return "\\pi" 144 | 145 | 146 | Matrix or vector from object 147 | ---------------------------- 148 | 149 | Provide a ``_matrix_`` method for an object that can be coerced to a 150 | matrix over a ring `R`. Then the Sage function ``matrix`` will work 151 | for this object. 152 | 153 | The following is from 154 | ``SAGE_ROOT/devel/sage/sage/graphs/graph.py``:: 155 | 156 | class GenericGraph(SageObject): 157 | ... 158 | def _matrix_(self, R=None): 159 | if R is None: 160 | return self.am() 161 | else: 162 | return self.am().change_ring(R) 163 | 164 | 165 | def adjacency_matrix(self, sparse=None, boundary_first=False): 166 | ... 167 | 168 | Similarly, provide a ``_vector_`` method for an object that can be 169 | coerced to a vector over a ring `R`. Then the Sage function ``vector`` 170 | will work for this object. The following is from the file 171 | ``SAGE_ROOT/sage/sage/modules/free_module_element.pyx``:: 172 | 173 | cdef class FreeModuleElement(element_Vector): # abstract base class 174 | ... 175 | def _vector_(self, R): 176 | return self.change_ring(R) 177 | 178 | 179 | .. _section-preparsing: 180 | 181 | Sage Preparsing 182 | =============== 183 | 184 | To make Python even more usable interactively, there are a number of 185 | tweaks to the syntax made when you use Sage from the commandline or 186 | via the notebook (but not for Python code in the Sage 187 | library). Technically, this is implemented by a ``preparse()`` 188 | function that rewrites the input string. Most notably, the following 189 | replacements are made: 190 | 191 | - Sage supports a special syntax for generating rings or, more 192 | generally, parents with named generators:: 193 | 194 | sage: R. = QQ[] 195 | sage: preparse('R. = QQ[]') 196 | "R = QQ['x, y']; (x, y,) = R._first_ngens(2)" 197 | 198 | - Integer and real literals are Sage integers and Sage floating point 199 | numbers. For example, in pure Python these would be an attribute 200 | error:: 201 | 202 | sage: 16.sqrt() 203 | 4 204 | sage: 87.factor() 205 | 3 * 29 206 | 207 | - Raw literals are not preparsed, which can be useful from an 208 | efficiency point of view. Just like Python ints are denoted by an L, 209 | in Sage raw integer and floating literals are followed by an "r" (or 210 | "R") for raw, meaning not preparsed. For example:: 211 | 212 | sage: a = 393939r 213 | sage: a 214 | 393939 215 | sage: type(a) 216 | 217 | sage: b = 393939 218 | sage: type(b) 219 | 220 | sage: a == b 221 | True 222 | 223 | - Raw literals can be very useful in certain cases. For instance, 224 | Python integers can be more efficient than Sage integers when they 225 | are very small. Large Sage integers are much more efficient than 226 | Python integers since they are implemented using the GMP C library. 227 | 228 | Consult the file ``preparser.py`` for more details about Sage 229 | preparsing, more examples involving raw literals, etc. 230 | 231 | When a file ``foo.sage`` is loaded in a Sage session, a preparsed 232 | version of ``foo.sage`` is created and named ``foo.py``. The beginning 233 | of ``foo.py`` states:: 234 | 235 | This file was *autogenerated* from the file foo.sage. 236 | 237 | The following files are relevant to preparsing in Sage: 238 | 239 | #. ``SAGE_ROOT/spkg/bin/sage`` 240 | 241 | #. ``SAGE_ROOT/local/bin/sage-preparse`` 242 | 243 | #. ``SAGE_ROOT/devel/sage/sage/misc/preparser.py`` 244 | 245 | In particular, the file ``preparser.py`` contains the Sage preparser 246 | code. 247 | 248 | 249 | The Sage Coercion Model 250 | ======================= 251 | 252 | The primary goal of coercion is to be able to transparently do 253 | arithmetic, comparisons, etc. between elements of distinct sets. For 254 | example, when one writes `3 + 1/2`, one wants to perform arithmetic on 255 | the operands as rational numbers, despite the left term being an 256 | integer. This makes sense given the obvious and natural inclusion of 257 | the integers into the rational numbers. The goal of the coercion 258 | system is to facilitate this (and more complicated arithmetic) without 259 | having to explicitly map everything over into the same domain, and at 260 | the same time being strict enough to not resolve ambiguity or accept 261 | nonsense. 262 | 263 | The coercion model for Sage is described in detail, with examples, in 264 | the Coercion section of the Sage Reference Manual. 265 | 266 | 267 | Mutability 268 | ========== 269 | 270 | Parent structures (e.g. rings, fields, matrix spaces, etc.) should be 271 | immutable and globally unique whenever possible. Immutability means, 272 | among other things, that properties like generator labels and default 273 | coercion precision cannot be changed. 274 | 275 | Global uniqueness while not wasting memory is best implemented using 276 | the standard Python weakref module, a factory function, and module 277 | scope variable. 278 | 279 | .. {Rewrite. Difficult to parse. Make gentler} 280 | 281 | .. {Put a tutorial on this here} 282 | 283 | Certain objects, e.g. matrices, may start out mutable and become 284 | immutable later. See the file 285 | ``SAGE_ROOT/src/sage/structure/mutability.py``. 286 | 287 | 288 | The __hash__ Special Method 289 | ============================ 290 | 291 | Here is the definition of ``__hash__`` from the Python reference 292 | manual: 293 | 294 | Called by built-in function ``hash()`` and for operations on members of 295 | hashed collections including set, frozenset, and dict. ``__hash__()`` 296 | should return an integer. The only required property is that objects which 297 | compare equal have the same hash value; it is advised to somehow mix 298 | together (e.g. using exclusive or) the hash values for the components of 299 | the object that also play a part in comparison of objects. If a class does 300 | not define a 301 | ``__cmp__()`` method it should not define a 302 | ``__hash__()`` operation either; if it defines 303 | ``__cmp__()`` or ``__eq__()`` but not 304 | ``__hash__()``, its instances will not be usable as 305 | dictionary keys. If a class defines mutable objects and implements 306 | a ``__cmp__()`` or ``__eq__()`` method, it 307 | should not implement ``__hash__()``, since the dictionary 308 | implementation requires that a key's hash value is immutable (if 309 | the object's hash value changes, it will be in the wrong hash 310 | bucket). 311 | 312 | Notice the phrase, "The only required property is that objects which 313 | compare equal have the same hash value." This is an assumption made by 314 | the Python language, which in Sage we simply cannot make (!), and 315 | violating it has consequences. Fortunately, the consequences are 316 | pretty clearly defined and reasonably easy to understand, so if you 317 | know about them they do not cause you trouble. The following example 318 | illustrates them pretty well: 319 | 320 | :: 321 | 322 | sage: v = [Mod(2,7)] 323 | sage: 9 in v 324 | True 325 | sage: v = set([Mod(2,7)]) 326 | sage: 9 in v 327 | False 328 | sage: 2 in v 329 | True 330 | sage: w = {Mod(2,7):'a'} 331 | sage: w[2] 332 | 'a' 333 | sage: w[9] 334 | Traceback (most recent call last): 335 | ... 336 | KeyError: 9 337 | 338 | Here is another example: 339 | 340 | :: 341 | 342 | sage: R = RealField(10000) 343 | sage: a = R(1) + R(10)^-100 344 | sage: a == RDF(1) # because the a gets coerced down to RDF 345 | True 346 | 347 | but ``hash(a)`` should not equal ``hash(1)``. 348 | 349 | Unfortunately, in Sage we simply cannot require 350 | 351 | :: 352 | 353 | (#) "a == b ==> hash(a) == hash(b)" 354 | 355 | because serious mathematics is simply too complicated for this 356 | rule. For example, the equalities ``z == Mod(z, 2)`` and 357 | ``z == Mod(z, 3)`` would force ``hash()`` to be constant on the 358 | integers. 359 | 360 | The only way we could "fix" this problem for good would be to abandon 361 | using the ``==`` operator for "Sage equality", and implement Sage 362 | equality as a new method attached to each object. Then we could follow 363 | Python rules for ``==`` and our rules for everything else, and all 364 | Sage code would become completely unreadable (and for that matter 365 | unwritable). So we just have to live with it. 366 | 367 | So what is done in Sage is to attempt to satisfy ``(#)`` when it is 368 | reasonably easy to do so, but use judgment and not go overboard. 369 | For example, 370 | 371 | :: 372 | 373 | sage: hash(Mod(2,7)) 374 | 2 375 | 376 | The output 2 is better than some random hash that also involves the 377 | moduli, but it is of course not right from the Python point of view, 378 | since ``9 == Mod(2,7)``. The goal is to make a hash function that is 379 | fast, but within reason respects any obvious natural inclusions and 380 | coercions. 381 | 382 | 383 | Exceptions 384 | ========== 385 | 386 | Please avoid catch-all code like this:: 387 | 388 | try: 389 | some_code() 390 | except: # bad 391 | more_code() 392 | 393 | If you do not have any exceptions explicitly listed (as a tuple), your 394 | code will catch absolutely anything, including ``ctrl-C``, typos in 395 | the code, and alarms, and this will lead to confusion. Also, this 396 | might catch real errors which should be propagated to the user. 397 | 398 | To summarize, only catch specific exceptions as in the following 399 | example:: 400 | 401 | try: 402 | return self.__coordinate_ring 403 | except (AttributeError, OtherExceptions) as msg: # good 404 | more_code_to_compute_something() 405 | 406 | Note that the syntax in ``except`` is to list all the exceptions that 407 | are caught as a tuple, followed by an error message. 408 | 409 | 410 | Importing 411 | ========= 412 | 413 | We mention two issues with importing: circular imports and importing 414 | large third-party modules. 415 | 416 | First, you must avoid circular imports. For example, suppose that the 417 | file ``SAGE_ROOT/src/sage/algebras/steenrod_algebra.py`` 418 | started with a line:: 419 | 420 | from sage.sage.algebras.steenrod_algebra_bases import * 421 | 422 | and that the file 423 | ``SAGE_ROOT/src/sage/algebras/steenrod_algebra_bases.py`` 424 | started with a line:: 425 | 426 | from sage.sage.algebras.steenrod_algebra import SteenrodAlgebra 427 | 428 | This sets up a loop: loading one of these files requires the other, 429 | which then requires the first, etc. 430 | 431 | With this set-up, running Sage will produce an error:: 432 | 433 | Exception exceptions.ImportError: 'cannot import name SteenrodAlgebra' 434 | in 'sage.rings.polynomial.polynomial_element. 435 | Polynomial_generic_dense.__normalize' ignored 436 | ------------------------------------------------------------------- 437 | ImportError Traceback (most recent call last) 438 | 439 | ... 440 | ImportError: cannot import name SteenrodAlgebra 441 | 442 | Instead, you might replace the ``import *`` line at the top of the 443 | file by more specific imports where they are needed in the code. For 444 | example, the ``basis`` method for the class ``SteenrodAlgebra`` might 445 | look like this (omitting the documentation string):: 446 | 447 | def basis(self, n): 448 | from steenrod_algebra_bases import steenrod_algebra_basis 449 | return steenrod_algebra_basis(n, basis=self._basis_name, p=self.prime) 450 | 451 | Second, do not import at the top level of your module a third-party 452 | module that will take a long time to initialize (e.g. matplotlib). As 453 | above, you might instead import specific components of the module when 454 | they are needed, rather than at the top level of your file. 455 | 456 | It is important to try to make ``from sage.all import *`` as fast as 457 | possible, since this is what dominates the Sage startup time, and 458 | controlling the top-level imports helps to do this. One important 459 | mechanism in Sage are lazy imports, which don't actually perform the 460 | import but delay it until the object is actually used. See 461 | :mod:`sage.misc.lazy_import` for more details of lazy imports, and 462 | :ref:`chapter-directory-structure` for an example using lazy imports 463 | for a new module. 464 | 465 | 466 | Deprecation 467 | =========== 468 | 469 | Sooner or later you will find places in the Sage library that are, in 470 | hindsight, not designed as well as they could be. Of course you want 471 | to improve the overall state, but at the same time we don't want to 472 | pull out the carpet under our users' feet. The process of removing old 473 | code is called deprecation. 474 | 475 | .. note:: 476 | 477 | Before removing any functionality, you should keep a deprecation 478 | warning in place for at least one year (if possible). The 479 | deprecation must include the trac ticket number where it was 480 | introduced. 481 | 482 | For example, let's say you run across the following while working on a 483 | module in the Sage library:: 484 | 485 | class Foo(SageObject): 486 | def terrible_idea(self): 487 | return 1 488 | def bad_name(self): 489 | return 1 490 | def f(self, weird_keyword=True): 491 | return self._f_implementation(weird_keyword=weird_keyword) 492 | def _f_implementation(self, weird_keyword=True): 493 | return 1 494 | 495 | You note that the ``terrible_idea()`` method does not make any sense, 496 | and should be removed altogether. You open the trac ticket number 3333 497 | (say), and replace the code with:: 498 | 499 | def terrible_idea(self): 500 | from sage.misc.superseded import deprecation 501 | deprecation(3333, 'You can just call f() instead') 502 | return 1 503 | 504 | Later, you come up with a much better name for the second method. You 505 | open the trac ticket number 4444, and replace it with:: 506 | 507 | def much_better_name(self): 508 | return 1 509 | 510 | bad_name = deprecated_function_alias(4444, much_better_name) 511 | 512 | Finally, you like the ``f()`` method name but you don't like the 513 | ``weird_keyword`` name. You fix this by opening the trac ticket 5555, 514 | and replacing it with:: 515 | 516 | @rename_keyword(deprecation=5555, weird_keyword='nice_keyword') 517 | def f(self, nice_keyword=True): 518 | return self._f_implementation(nice_keyword=nice_keyword) 519 | 520 | def _f_implementation(self, nice_keyword=True): 521 | return 1 522 | 523 | Note that the underscore-method ``_f_implementation`` is, by 524 | convention, not something that ought to be used by others. So we do 525 | not need to deprecate anything when we change it. 526 | 527 | Now, any user that still relies on the deprecated functionality will 528 | be informed that this is about to change, yet the deprecated commands 529 | still work. With all necessary imports, the final result looks like 530 | this:: 531 | 532 | sage: from sage.misc.superseded import deprecation, deprecated_function_alias 533 | sage: from sage.misc.decorators import rename_keyword 534 | sage: class Foo(SageObject): 535 | ....: 536 | ....: def terrible_idea(self): 537 | ....: deprecation(3333, 'You can just call f() instead') 538 | ....: return 1 539 | ....: 540 | ....: def much_better_name(self): 541 | ....: return 1 542 | ....: 543 | ....: bad_name = deprecated_function_alias(4444, much_better_name) 544 | ....: 545 | ....: @rename_keyword(deprecation=5555, weird_keyword='nice_keyword') 546 | ....: def f(self, nice_keyword=True): 547 | ....: return self._f_implementation(nice_keyword=nice_keyword) 548 | ....: 549 | ....: def _f_implementation(self, nice_keyword=True): 550 | ....: return 1 551 | 552 | sage: foo = Foo() 553 | sage: foo.terrible_idea() 554 | doctest:...: DeprecationWarning: You can just call f() instead 555 | See http://trac.sagemath.org/3333 for details. 556 | 1 557 | 558 | sage: foo.bad_name() 559 | doctest:...: DeprecationWarning: bad_name is deprecated. Please use much_better_name instead. 560 | See http://trac.sagemath.org/4444 for details. 561 | 1 562 | 563 | sage: foo.f(weird_keyword=False) 564 | doctest:...: DeprecationWarning: use the option 'nice_keyword' instead of 'weird_keyword' 565 | See http://trac.sagemath.org/5555 for details. 566 | 1 567 | 568 | 569 | Using optional packages 570 | ======================= 571 | 572 | If a function requires an optional package, that function should fail 573 | gracefully---perhaps using a ``try``-``except`` block---when the 574 | optional package is not available, and should give a hint about how to 575 | install it. For example, typing ``sage -optional`` gives a list of all 576 | optional packages, so it might suggest to the user that they type 577 | that. The command ``optional_packages()`` from within Sage also 578 | returns this list. 579 | --------------------------------------------------------------------------------