##// END OF EJS Templates
Merge branch 'docs-build'
Thomas Kluyver -
r3329:33e87e7e merge
parent child Browse files
Show More
@@ -1,165 +1,168 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """Script to commit the doc build outputs into the github-pages repo.
2 """Script to commit the doc build outputs into the github-pages repo.
3
3
4 Use:
4 Use:
5
5
6 gh-pages.py [tag]
6 gh-pages.py [tag]
7
7
8 If no tag is given, the current output of 'git describe' is used. If given,
8 If no tag is given, the current output of 'git describe' is used. If given,
9 that is how the resulting directory will be named.
9 that is how the resulting directory will be named.
10
10
11 In practice, you should use either actual clean tags from a current build or
11 In practice, you should use either actual clean tags from a current build or
12 something like 'current' as a stable URL for the most current version of the """
12 something like 'current' as a stable URL for the most current version of the """
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 import os
17 import os
18 import re
18 import re
19 import shutil
19 import shutil
20 import sys
20 import sys
21 from os import chdir as cd
21 from os import chdir as cd
22 from os.path import join as pjoin
22 from os.path import join as pjoin
23
23
24 from subprocess import Popen, PIPE, CalledProcessError, check_call
24 from subprocess import Popen, PIPE, CalledProcessError, check_call
25
25
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27 # Globals
27 # Globals
28 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
29
29
30 pages_dir = 'gh-pages'
30 pages_dir = 'gh-pages'
31 html_dir = 'build/html'
31 html_dir = 'build/html'
32 pdf_dir = 'build/latex'
32 pdf_dir = 'build/latex'
33 pages_repo = 'git@github.com:ipython/ipython-doc.git'
33 pages_repo = 'git@github.com:ipython/ipython-doc.git'
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Functions
36 # Functions
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38 def sh(cmd):
38 def sh(cmd):
39 """Execute command in a subshell, return status code."""
39 """Execute command in a subshell, return status code."""
40 return check_call(cmd, shell=True)
40 return check_call(cmd, shell=True)
41
41
42
42
43 def sh2(cmd):
43 def sh2(cmd):
44 """Execute command in a subshell, return stdout.
44 """Execute command in a subshell, return stdout.
45
45
46 Stderr is unbuffered from the subshell.x"""
46 Stderr is unbuffered from the subshell.x"""
47 p = Popen(cmd, stdout=PIPE, shell=True)
47 p = Popen(cmd, stdout=PIPE, shell=True)
48 out = p.communicate()[0]
48 out = p.communicate()[0]
49 retcode = p.returncode
49 retcode = p.returncode
50 if retcode:
50 if retcode:
51 raise CalledProcessError(retcode, cmd)
51 raise CalledProcessError(retcode, cmd)
52 else:
52 else:
53 return out.rstrip()
53 return out.rstrip()
54
54
55
55
56 def sh3(cmd):
56 def sh3(cmd):
57 """Execute command in a subshell, return stdout, stderr
57 """Execute command in a subshell, return stdout, stderr
58
58
59 If anything appears in stderr, print it out to sys.stderr"""
59 If anything appears in stderr, print it out to sys.stderr"""
60 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
60 p = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
61 out, err = p.communicate()
61 out, err = p.communicate()
62 retcode = p.returncode
62 retcode = p.returncode
63 if retcode:
63 if retcode:
64 raise CalledProcessError(retcode, cmd)
64 raise CalledProcessError(retcode, cmd)
65 else:
65 else:
66 return out.rstrip(), err.rstrip()
66 return out.rstrip(), err.rstrip()
67
67
68
68
69 def init_repo(path):
69 def init_repo(path):
70 """clone the gh-pages repo if we haven't already."""
70 """clone the gh-pages repo if we haven't already."""
71 sh("git clone %s %s"%(pages_repo, path))
71 sh("git clone %s %s"%(pages_repo, path))
72 here = os.getcwd()
72 here = os.getcwd()
73 cd(path)
73 cd(path)
74 sh('git checkout gh-pages')
74 sh('git checkout gh-pages')
75 cd(here)
75 cd(here)
76
76
77
77
78 def render_rstindex(fname, tag, desc=None):
78 def render_rstindex(fname, tag, desc=None):
79 if desc is None:
79 if desc is None:
80 desc = tag
80 desc = tag
81
81
82 rel = '* {d}: `HTML <{t}/index.html>`_ and `PDF <{t}/ipython.pdf>`_.'.format(t=tag,d=desc)
82 rel = '* {d}: `HTML <{t}/index.html>`_ and `PDF <{t}/ipython.pdf>`_.'.format(t=tag,d=desc)
83 rep = re.compile(r'\.\. release')
83 rep = re.compile(r'\.\. release')
84 out = []
84 out = []
85 with file(fname) as f:
85 with file(fname) as f:
86 contents = f.read()
86 contents = f.read()
87 lines = contents.splitlines()
87 lines = contents.splitlines()
88 if rel in contents:
88 if rel in contents:
89 out = lines
89 out = lines
90 else:
90 else:
91 for line in lines:
91 for line in lines:
92 out.append(line)
92 out.append(line)
93 if rep.search(line):
93 if rep.search(line):
94 out.append(rep.sub(rel, line))
94 out.append(rep.sub(rel, line))
95 return '\n'.join(out)+'\n'
95 return '\n'.join(out)+'\n'
96
96
97
97
98 def new_rstindex(fname, tag, desc=None):
98 def new_rstindex(fname, tag, desc=None):
99 new_page = render_rstindex(fname, tag, desc)
99 new_page = render_rstindex(fname, tag, desc)
100 os.rename(fname, fname+'~')
100 os.rename(fname, fname+'~')
101 with file(fname, 'w') as f:
101 with file(fname, 'w') as f:
102 f.write(new_page)
102 f.write(new_page)
103
103
104
104
105 #-----------------------------------------------------------------------------
105 #-----------------------------------------------------------------------------
106 # Script starts
106 # Script starts
107 #-----------------------------------------------------------------------------
107 #-----------------------------------------------------------------------------
108 if __name__ == '__main__':
108 if __name__ == '__main__':
109 # The tag can be given as a positional argument
109 # The tag can be given as a positional argument
110 try:
110 try:
111 tag = sys.argv[1]
111 tag = sys.argv[1]
112 except IndexError:
112 except IndexError:
113 tag = sh2('git describe')
113 try:
114 tag = sh2('git describe')
115 except CalledProcessError:
116 tag = "dev" # Fallback
114
117
115 try:
118 try:
116 desc = sys.argv[2]
119 desc = sys.argv[2]
117 except IndexError:
120 except IndexError:
118 desc="Release (%s)"%tag
121 desc="Release (%s)"%tag
119
122
120 startdir = os.getcwd()
123 startdir = os.getcwd()
121 if not os.path.exists(pages_dir):
124 if not os.path.exists(pages_dir):
122 # init the repo
125 # init the repo
123 init_repo(pages_dir)
126 init_repo(pages_dir)
124 else:
127 else:
125 # ensure up-to-date before operating
128 # ensure up-to-date before operating
126 cd(pages_dir)
129 cd(pages_dir)
127 sh('git checkout gh-pages')
130 sh('git checkout gh-pages')
128 sh('git pull')
131 sh('git pull')
129 cd(startdir)
132 cd(startdir)
130
133
131 dest = pjoin(pages_dir, tag)
134 dest = pjoin(pages_dir, tag)
132
135
133 # don't `make html` here, because gh-pages already depends on html in Makefile
136 # don't `make html` here, because gh-pages already depends on html in Makefile
134 # sh('make html')
137 # sh('make html')
135
138
136 # This is pretty unforgiving: we unconditionally nuke the destination
139 # This is pretty unforgiving: we unconditionally nuke the destination
137 # directory, and then copy the html tree in there
140 # directory, and then copy the html tree in there
138 shutil.rmtree(dest, ignore_errors=True)
141 shutil.rmtree(dest, ignore_errors=True)
139 shutil.copytree(html_dir, dest)
142 shutil.copytree(html_dir, dest)
140 shutil.copy(pjoin(pdf_dir, 'ipython.pdf'), pjoin(dest, 'ipython.pdf'))
143 shutil.copy(pjoin(pdf_dir, 'ipython.pdf'), pjoin(dest, 'ipython.pdf'))
141
144
142 try:
145 try:
143 cd(pages_dir)
146 cd(pages_dir)
144 status = sh2('git status | head -1')
147 status = sh2('git status | head -1')
145 branch = re.match('\# On branch (.*)$', status).group(1)
148 branch = re.match('\# On branch (.*)$', status).group(1)
146 if branch != 'gh-pages':
149 if branch != 'gh-pages':
147 e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir,
150 e = 'On %r, git branch is %r, MUST be "gh-pages"' % (pages_dir,
148 branch)
151 branch)
149 raise RuntimeError(e)
152 raise RuntimeError(e)
150
153
151 sh('git add %s' % tag)
154 sh('git add %s' % tag)
152 new_rstindex('index.rst', tag, desc)
155 new_rstindex('index.rst', tag, desc)
153 sh('python build_index.py')
156 sh('python build_index.py')
154 sh('git add index.rst index.html')
157 sh('git add index.rst index.html')
155 sh('git commit -m"Created new doc release, named: %s"' % tag)
158 sh('git commit -m"Created new doc release, named: %s"' % tag)
156 print
159 print
157 print 'Most recent 3 commits:'
160 print 'Most recent 3 commits:'
158 sys.stdout.flush()
161 sys.stdout.flush()
159 sh('git --no-pager log --oneline HEAD~3..')
162 sh('git --no-pager log --oneline HEAD~3..')
160 finally:
163 finally:
161 cd(startdir)
164 cd(startdir)
162
165
163 print
166 print
164 print 'Now verify the build in: %r' % dest
167 print 'Now verify the build in: %r' % dest
165 print "If everything looks good, 'git push'"
168 print "If everything looks good, 'git push'"
@@ -1,143 +1,165 b''
1 .. _documenting-ipython:
1 .. _documenting-ipython:
2
2
3 =====================
3 =====================
4 Documenting IPython
4 Documenting IPython
5 =====================
5 =====================
6
6
7 When contributing code to IPython, you should strive for clarity and
7 When contributing code to IPython, you should strive for clarity and
8 consistency, without falling prey to a style straitjacket. Basically,
8 consistency, without falling prey to a style straitjacket. Basically,
9 'document everything, try to be consistent, do what makes sense.'
9 'document everything, try to be consistent, do what makes sense.'
10
10
11 By and large we follow existing Python practices in major projects like Python
11 By and large we follow existing Python practices in major projects like Python
12 itself or NumPy, this document provides some additional detail for IPython.
12 itself or NumPy, this document provides some additional detail for IPython.
13
13
14
14
15 Standalone documentation
15 Standalone documentation
16 ========================
16 ========================
17
17
18 All standalone documentation should be written in plain text (``.txt``) files
18 All standalone documentation should be written in plain text (``.txt``) files
19 using reStructuredText [reStructuredText]_ for markup and formatting. All such
19 using reStructuredText [reStructuredText]_ for markup and formatting. All such
20 documentation should be placed in the directory :file:`docs/source` of the
20 documentation should be placed in the directory :file:`docs/source` of the
21 IPython source tree. Or, when appropriate, a suitably named subdirectory
21 IPython source tree. Or, when appropriate, a suitably named subdirectory
22 should be used. The documentation in this location will serve as the main
22 should be used. The documentation in this location will serve as the main
23 source for IPython documentation.
23 source for IPython documentation.
24
24
25 The actual HTML and PDF docs are built using the Sphinx [Sphinx]_
25 The actual HTML and PDF docs are built using the Sphinx [Sphinx]_
26 documentation generation tool. Once you have Sphinx installed, you can build
26 documentation generation tool. Once you have Sphinx installed, you can build
27 the html docs yourself by doing:
27 the html docs yourself by doing:
28
28
29 .. code-block:: bash
29 .. code-block:: bash
30
30
31 $ cd ipython-mybranch/docs
31 $ cd ipython-mybranch/docs
32 $ make html
32 $ make html
33
33
34 Our usage of Sphinx follows that of matplotlib [Matplotlib]_ closely. We are
34 Our usage of Sphinx follows that of matplotlib [Matplotlib]_ closely. We are
35 using a number of Sphinx tools and extensions written by the matplotlib team
35 using a number of Sphinx tools and extensions written by the matplotlib team
36 and will mostly follow their conventions, which are nicely spelled out in
36 and will mostly follow their conventions, which are nicely spelled out in
37 their documentation guide [MatplotlibDocGuide]_. What follows is thus a
37 their documentation guide [MatplotlibDocGuide]_. What follows is thus a
38 abridged version of the matplotlib documentation guide, taken with permission
38 abridged version of the matplotlib documentation guide, taken with permission
39 from the matplotlib team.
39 from the matplotlib team.
40
40
41 If you are reading this in a web browser, you can click on the "Show Source"
41 If you are reading this in a web browser, you can click on the "Show Source"
42 link to see the original reStricturedText for the following examples.
42 link to see the original reStricturedText for the following examples.
43
43
44 A bit of Python code::
44 A bit of Python code::
45
45
46 for i in range(10):
46 for i in range(10):
47 print i,
47 print i,
48 print "A big number:",2**34
48 print "A big number:",2**34
49
49
50 An interactive Python session::
50 An interactive Python session::
51
51
52 >>> from IPython.utils.path import get_ipython_dir
52 >>> from IPython.utils.path import get_ipython_dir
53 >>> get_ipython_dir()
53 >>> get_ipython_dir()
54 '/home/fperez/.ipython'
54 '/home/fperez/.ipython'
55
55
56 An IPython session:
56 An IPython session:
57
57
58 .. code-block:: ipython
58 .. code-block:: ipython
59
59
60 In [7]: import IPython
60 In [7]: import IPython
61
61
62 In [8]: print "This IPython is version:",IPython.__version__
62 In [8]: print "This IPython is version:",IPython.__version__
63 This IPython is version: 0.9.1
63 This IPython is version: 0.9.1
64
64
65 In [9]: 2+4
65 In [9]: 2+4
66 Out[9]: 6
66 Out[9]: 6
67
67
68
68
69 A bit of shell code:
69 A bit of shell code:
70
70
71 .. code-block:: bash
71 .. code-block:: bash
72
72
73 cd /tmp
73 cd /tmp
74 echo "My home directory is: $HOME"
74 echo "My home directory is: $HOME"
75 ls
75 ls
76
76
77 Docstring format
77 Docstring format
78 ================
78 ================
79
79
80 Good docstrings are very important. Unfortunately, Python itself only provides
80 Good docstrings are very important. Unfortunately, Python itself only provides
81 a rather loose standard for docstrings [PEP257]_, and there is no universally
81 a rather loose standard for docstrings [PEP257]_, and there is no universally
82 accepted convention for all the different parts of a complete docstring.
82 accepted convention for all the different parts of a complete docstring.
83 However, the NumPy project has established a very reasonable standard, and has
83 However, the NumPy project has established a very reasonable standard, and has
84 developed some tools to support the smooth inclusion of such docstrings in
84 developed some tools to support the smooth inclusion of such docstrings in
85 Sphinx-generated manuals. Rather than inventing yet another pseudo-standard,
85 Sphinx-generated manuals. Rather than inventing yet another pseudo-standard,
86 IPython will be henceforth documented using the NumPy conventions; we carry
86 IPython will be henceforth documented using the NumPy conventions; we carry
87 copies of some of the NumPy support tools to remain self-contained, but share
87 copies of some of the NumPy support tools to remain self-contained, but share
88 back upstream with NumPy any improvements or fixes we may make to the tools.
88 back upstream with NumPy any improvements or fixes we may make to the tools.
89
89
90 The NumPy documentation guidelines [NumPyDocGuide]_ contain detailed
90 The NumPy documentation guidelines [NumPyDocGuide]_ contain detailed
91 information on this standard, and for a quick overview, the NumPy example
91 information on this standard, and for a quick overview, the NumPy example
92 docstring [NumPyExampleDocstring]_ is a useful read.
92 docstring [NumPyExampleDocstring]_ is a useful read.
93
93
94
94
95 For user-facing APIs, we try to be fairly strict about following the above
95 For user-facing APIs, we try to be fairly strict about following the above
96 standards (even though they mean more verbose and detailed docstrings).
96 standards (even though they mean more verbose and detailed docstrings).
97 Wherever you can reasonably expect people to do introspection with::
97 Wherever you can reasonably expect people to do introspection with::
98
98
99 In [1]: some_function?
99 In [1]: some_function?
100
100
101 the docstring should follow the NumPy style and be fairly detailed.
101 the docstring should follow the NumPy style and be fairly detailed.
102
102
103 For purely internal methods that are only likely to be read by others extending
103 For purely internal methods that are only likely to be read by others extending
104 IPython itself we are a bit more relaxed, especially for small/short methods
104 IPython itself we are a bit more relaxed, especially for small/short methods
105 and functions whose intent is reasonably obvious. We still expect docstrings
105 and functions whose intent is reasonably obvious. We still expect docstrings
106 to be written, but they can be simpler. For very short functions with a
106 to be written, but they can be simpler. For very short functions with a
107 single-line docstring you can use something like::
107 single-line docstring you can use something like::
108
108
109 def add(a, b):
109 def add(a, b):
110 """The sum of two numbers.
110 """The sum of two numbers.
111 """
111 """
112 code
112 code
113
113
114 and for longer multiline strings::
114 and for longer multiline strings::
115
115
116 def add(a, b):
116 def add(a, b):
117 """The sum of two numbers.
117 """The sum of two numbers.
118
118
119 Here is the rest of the docs.
119 Here is the rest of the docs.
120 """
120 """
121 code
121 code
122
122
123
123
124 Here are two additional PEPs of interest regarding documentation of code.
124 Here are two additional PEPs of interest regarding documentation of code.
125 While both of these were rejected, the ideas therein form much of the basis of
125 While both of these were rejected, the ideas therein form much of the basis of
126 docutils (the machinery to process reStructuredText):
126 docutils (the machinery to process reStructuredText):
127
127
128 * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_
128 * `Docstring Processing System Framework <http://www.python.org/peps/pep-0256.html>`_
129 * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_
129 * `Docutils Design Specification <http://www.python.org/peps/pep-0258.html>`_
130
130
131 .. note::
131 .. note::
132
132
133 In the past IPython used epydoc so currently many docstrings still use
133 In the past IPython used epydoc so currently many docstrings still use
134 epydoc conventions. We will update them as we go, but all new code should
134 epydoc conventions. We will update them as we go, but all new code should
135 be documented using the NumPy standard.
135 be documented using the NumPy standard.
136
137 Building and uploading
138 ======================
139 The built docs are stored in a separate repository. Through some github magic,
140 they're automatically exposed as a website. It works like this:
141
142 * You will need to have sphinx and latex installed. In Ubuntu, install
143 ``texlive-latex-recommended texlive-latex-extra texlive-fonts-recommended``.
144 Install the latest version of sphinx from PyPI (``pip install sphinx``).
145 * Ensure that the development version of IPython is the first in your system
146 path. You can either use a virtualenv, or modify your PYTHONPATH.
147 * Switch into the docs directory, and run ``make gh-pages``. This will build
148 your updated docs as html and pdf, then automatically check out the latest
149 version of the docs repository, copy the built docs into it, and commit your
150 changes.
151 * Open the built docs in a web browser, and check that they're as expected.
152 * (If rebuilding the docs for the development version, it may have duplicated
153 the link to the development version in the homepage. Remove this from
154 index.rst, then run ``python build_index.py`` to update index.html. Commit the
155 change.)
156 * Upload the docs with ``git push``. This only works if you have write access to
157 the docs repository.
136
158
137 .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html
159 .. [reStructuredText] reStructuredText. http://docutils.sourceforge.net/rst.html
138 .. [Sphinx] Sphinx. http://sphinx.pocoo.org/
160 .. [Sphinx] Sphinx. http://sphinx.pocoo.org/
139 .. [MatplotlibDocGuide] http://matplotlib.sourceforge.net/devel/documenting_mpl.html
161 .. [MatplotlibDocGuide] http://matplotlib.sourceforge.net/devel/documenting_mpl.html
140 .. [PEP257] PEP 257. http://www.python.org/peps/pep-0257.html
162 .. [PEP257] PEP 257. http://www.python.org/peps/pep-0257.html
141 .. [NumPyDocGuide] NumPy documentation guide. http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines
163 .. [NumPyDocGuide] NumPy documentation guide. http://projects.scipy.org/numpy/wiki/CodingStyleGuidelines
142 .. [NumPyExampleDocstring] NumPy example docstring. http://projects.scipy.org/numpy/browser/trunk/doc/EXAMPLE_DOCSTRING.txt
164 .. [NumPyExampleDocstring] NumPy example docstring. http://projects.scipy.org/numpy/browser/trunk/doc/EXAMPLE_DOCSTRING.txt
143
165
General Comments 0
You need to be logged in to leave comments. Login now