Skip to content

Commit 927a0d1

Browse files
committed
adds documentation module
1 parent 62e0800 commit 927a0d1

File tree

2 files changed

+376
-0
lines changed

2 files changed

+376
-0
lines changed

_quarto.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ website:
2424
- files-command-line.ipynb
2525
- packaging-distribution.ipynb
2626
- testing-continuous-integration.ipynb
27+
- documentation.ipynb
2728

2829
format:
2930
html:

documentation.ipynb

Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "raw",
5+
"metadata": {
6+
"vscode": {
7+
"languageId": "raw"
8+
}
9+
},
10+
"source": [
11+
"---\n",
12+
"title: \"Documentation\"\n",
13+
"author: \"Kyle Niemeyer\"\n",
14+
"date: \"5 February 2025\"\n",
15+
"institute: \"Oregon State University\"\n",
16+
"format:\n",
17+
" revealjs:\n",
18+
" output-file: documentation-revealjs.html\n",
19+
" incremental: true\n",
20+
" fig-align: center\n",
21+
" fig-responsive: true\n",
22+
" toc: false\n",
23+
" html: default\n",
24+
"jupyter: python3\n",
25+
"---"
26+
]
27+
},
28+
{
29+
"cell_type": "markdown",
30+
"metadata": {},
31+
"source": [
32+
"# Documenting code and building a documentation website with Sphinx\n",
33+
"\n",
34+
"## Documentation\n",
35+
"\n",
36+
"Professor Carole Goble in [\"Better Software, Better Research\"](https://doi.org/10.1109/MIC.2014.88):\n",
37+
"\n",
38+
"> One of my favorite #overlyhonestmethods tweets (a hashtag for lab scientists) is Ian Holmes's \"You can download our code from the URL supplied. Good luck downloading the only postdoc who can get it to run, though.\"\n",
39+
"\n",
40+
"## Value of documentation\n",
41+
"\n",
42+
"- The value and extent of your work is clearer if it can be understood by colleagues.\n",
43+
"- Documentation provides provenance for your scientific process, for your colleagues and yourself.\n",
44+
"- Documentation demonstrates your skill and professionalism.\n",
45+
"\n",
46+
"## Documentation is easier than you think.\n",
47+
"\n",
48+
"- Documentation pays for itself with the time it saves in the long run.\n",
49+
"- Documentation requires little effort beyond writing the software itself.\n",
50+
"\n",
51+
"## Types of documentation\n",
52+
"\n",
53+
"- Theory manuals\n",
54+
"- User and developer guides\n",
55+
"- Code comments\n",
56+
"- Self-documenting code\n",
57+
"- Generated API documentation\n",
58+
"\n",
59+
"## User and developer guides\n",
60+
"\n",
61+
"::: fragment\n",
62+
"`README`: sits in top-level directory and contains all the necessary information for installing, getting started with, and understanding the accompanying code.\n",
63+
":::\n",
64+
"\n",
65+
"::: fragment\n",
66+
"May be accompanied by other specific files: `LICENSE`, `INSTALL`, `CITATION`, `ABOUT`, `CHANGELOG`, `CONTRIBUTING`\n",
67+
"::: \n",
68+
"\n",
69+
"## README example {.smaller}\n",
70+
"\n",
71+
"``` text\n",
72+
"SQUIRREL, version 1.2 released on 2026-09-20\n",
73+
"\n",
74+
"# About\n",
75+
"\n",
76+
"The Spectral Q and U Imaging Radiation Replicating Experimental Library\n",
77+
"(SQUIRREL) is a library for replicating radiation sources with spectral details\n",
78+
"and Q and U polarizations of superman bubblegum.\n",
79+
"\n",
80+
"# Installation\n",
81+
"\n",
82+
"The SQUIRREL library relies on other libraries:\n",
83+
"\n",
84+
"- The ACORN library www.acorn.nutz\n",
85+
"- The TREEBRANCH database format API\n",
86+
"\n",
87+
"Install those before installing the SQUIRREL library. To install the SQUIRREL\n",
88+
"library:\n",
89+
"\n",
90+
"./configure\n",
91+
"make --prefix=/install/path\n",
92+
"make install\n",
93+
"...\n",
94+
"```\n",
95+
"\n",
96+
"## Comments\n",
97+
"\n",
98+
"Comments provide a way to insert metainformation about code intended for people, right next to the code:\n",
99+
"\n",
100+
"``` {.python .fragment}\n",
101+
"def the_function(var):\n",
102+
" \"\"\"This is a docstring, where a function definition might live\"\"\"\n",
103+
" a = 1 + var # this is a simple comment\n",
104+
" return a\n",
105+
"```\n",
106+
"\n",
107+
"## Bad comments\n",
108+
"\n",
109+
"Also possible to pollute code with unnecessary cruft:\n",
110+
"\n",
111+
"``` {.python .fragment}\n",
112+
"def decay(index, database):\n",
113+
" # first, retrieve the decay constants from the database\n",
114+
" mylist = database.decay_constants()\n",
115+
" # next, try to access an element of the list\n",
116+
" try:\n",
117+
" d = mylist[index] # gets decay constant at index in the list\n",
118+
" # if the index doesn't exist\n",
119+
" except IndexError:\n",
120+
" # throw an informative error message\n",
121+
" raise Exception(\"value not found in the list\")\n",
122+
" return d\n",
123+
"```\n",
124+
"\n",
125+
"## Useful comments\n",
126+
"\n",
127+
"Code written cleanly will have its own voice. Use intelligent naming to make most lines of code clear without comments, then use comments sparingly to help explain reasons or complicated sections:\n",
128+
"\n",
129+
"``` {.python .fragment}\n",
130+
"def get_decay(index, database):\n",
131+
" \"\"\"Returns decay constant at index in the database\"\"\"\n",
132+
" lambdas = database.decay_constants()\n",
133+
" try:\n",
134+
" lambda_i = lambdas[index] # gets decay constant at index in the list\n",
135+
" except IndexError:\n",
136+
" raise Exception(\"value not found in the list\")\n",
137+
" return lambda\n",
138+
"```\n",
139+
"\n",
140+
"## Self-documenting code\n",
141+
"\n",
142+
"::: fragment\n",
143+
"**Naming**: a class, variable, or function name should tell you why it exists, what it does, and how it is used.\n",
144+
":::\n",
145+
"\n",
146+
"::: fragment\n",
147+
"**Simple functions**: functions should be small to be understandable and testable; they should only do *one thing*.\n",
148+
":::\n",
149+
"\n",
150+
"::: fragment\n",
151+
"**Consistent style**: use a consistent, standardized style; e.g., select variable and function names according to the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/) for Python.\n",
152+
"::: \n",
153+
"\n",
154+
"## Guidelines for naming\n",
155+
"\n",
156+
"``` python\n",
157+
"# packages and modules are short and lowercase\n",
158+
"packages\n",
159+
"modules\n",
160+
"\n",
161+
"# other objects can be long\n",
162+
"ClassesUseCamelCase\n",
163+
"ExceptionsAreClassesToo\n",
164+
"functions_use_snake_case\n",
165+
"CONSTANTS_USE_ALL_CAPS\n",
166+
"\n",
167+
"# variable scope is *suggested* by style convention\n",
168+
"_single_leading_underscore_ # internal to module\n",
169+
"single_trailing_underscore_ # avoids conflicts with Python keywords\n",
170+
"__double_leading_trailing__ # these are magic, like __init__\n",
171+
"```\n",
172+
"\n",
173+
"## Docstrings\n",
174+
"\n",
175+
"::: fragment\n",
176+
"**docstring**: comment placed immediately after a function or class definition, typically enclosed by three pairs of double quotes:\n",
177+
":::\n",
178+
"\n",
179+
"``` {.python .fragment}\n",
180+
"def <name>(<args>):\n",
181+
" \"\"\"<docstring>\"\"\"\n",
182+
" <body>\n",
183+
"```\n",
184+
"\n",
185+
"::: fragment\n",
186+
"docstrings are available within Python via `help()` and iPython's magic command `?`, and Sphinx picks them up.\n",
187+
":::\n",
188+
"\n",
189+
"## Docstrings (more)\n",
190+
"\n",
191+
"::: fragment\n",
192+
"Make docstrings descriptive and concise; you can explain the arguments of a function, its behavior, and how you intend it to be used.\n",
193+
":::\n",
194+
"\n",
195+
"``` {.python .fragment}\n",
196+
"def power(base, x):\n",
197+
" \"\"\"Computes base^x. Both base and x should be integers,\n",
198+
" floats, or another numeric type.\n",
199+
" \"\"\"\n",
200+
" return base**x\n",
201+
"```"
202+
]
203+
},
204+
{
205+
"cell_type": "markdown",
206+
"metadata": {},
207+
"source": [
208+
"# Sphinx: automate generating documentation\n",
209+
"\n",
210+
"::: fragment\n",
211+
"Sphinx can be used to automate the generation of HTML documentation; we can even use it with GitHub Actions to automatically build and deploy the docs on GitHub Pages.\n",
212+
":::\n",
213+
"\n",
214+
"::: fragment\n",
215+
"For now, let's just make sure your docstrings are suitable for Sphinx.\n",
216+
":::\n",
217+
"\n",
218+
"## [Numpy-style docstrings](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html) {.smaller}\n",
219+
"\n",
220+
"``` {.python .fragment}\n",
221+
"def function_with_types_in_docstring(param1, param2):\n",
222+
" \"\"\"Example function with types documented in the docstring.\n",
223+
"\n",
224+
" `PEP 484`_ type annotations are supported. If attribute, parameter, and\n",
225+
" return types are annotated according to `PEP 484`_, they do not need to be\n",
226+
" included in the docstring:\n",
227+
"\n",
228+
" Parameters\n",
229+
" ----------\n",
230+
" param1 : int\n",
231+
" The first parameter.\n",
232+
" param2 : str\n",
233+
" The second parameter.\n",
234+
"\n",
235+
" Returns\n",
236+
" -------\n",
237+
" bool\n",
238+
" True if successful, False otherwise.\n",
239+
"\n",
240+
" .. _PEP 484:\n",
241+
" https://www.python.org/dev/peps/pep-0484/\n",
242+
"\n",
243+
" \"\"\"\n",
244+
"```\n",
245+
"\n",
246+
"## [Google-style docstrings](https://www.sphinx-doc.org/en/master/usage/extensions/example_google.html#example-google) {.smaller}\n",
247+
"\n",
248+
"``` {.python .fragment}\n",
249+
"def function_with_types_in_docstring(param1, param2):\n",
250+
" \"\"\"Example function with types documented in the docstring.\n",
251+
"\n",
252+
" `PEP 484`_ type annotations are supported. If attribute, parameter, and\n",
253+
" return types are annotated according to `PEP 484`_, they do not need to be\n",
254+
" included in the docstring:\n",
255+
"\n",
256+
" Args:\n",
257+
" param1 (int): The first parameter.\n",
258+
" param2 (str): The second parameter.\n",
259+
"\n",
260+
" Returns:\n",
261+
" bool: The return value. True for success, False otherwise.\n",
262+
"\n",
263+
" .. _PEP 484:\n",
264+
" https://www.python.org/dev/peps/pep-0484/\n",
265+
"\n",
266+
" \"\"\"\n",
267+
"```\n",
268+
"\n",
269+
"## Getting started with Sphinx\n",
270+
"\n",
271+
"1. `pip install sphinx myst-parser`\n",
272+
"2. `mkdir docs`\n",
273+
"3. `cd docs`\n",
274+
"4. `sphinx-quickstart` (accept defaults if unsure; answer \"yes\" for question about autodoc)\n",
275+
"5. `source` directory holds `.rst` and `.md` files for user guides, theory manuals, etc., separate from the autogenerated API documentation\n",
276+
"\n",
277+
"## Add content for Sphinx\n",
278+
"\n",
279+
"1. In the `docs\\source` directory, add an `installation.md` file (for example)\n",
280+
"2. Add `'myst_parser'` to `extensions` in `conf.py`\n",
281+
"2. Try building with `make html`\n",
282+
"3. Did sphinx find and automatically build docs for your modules? Look for `.md` files for each module.\n",
283+
"\n",
284+
"## Configuration (`conf.py`)\n",
285+
"\n",
286+
"- Add `'sphinx.ext.autodoc'` to `extensions` \n",
287+
"- In extensions, add `sphinx.ext.napoleon` (for Google/NumPy-style docstring reading) and `sphinx.ext.mathjax` (if you want LaTeX-based equations), and `sphinx.ext.intersphinx` for connections to other docs\n",
288+
"- Set `napoleon_numpy_docstring` and `napoleon_google_docstring` to `True`/`False` depending on your docstring style.\n",
289+
"- Add an `intersphinx_mapping` dict to connect to other docs\n",
290+
"\n",
291+
"## Configuration\n",
292+
"\n",
293+
"- In `conf.py`, add `autodoc_default_options = {'members': True}` and `autoclass_content = 'class'`\n",
294+
"- For each Python module, create a corresponding `[modulename].rst` file in the `docs\\source` directory. Add `.. automodule:: [packagename].[modulename]`\n",
295+
"- In `index.rst`, add `[modulename]` inside the `toctree` (table of contents) \n",
296+
"\n",
297+
"## `intersphinx_mapping`\n",
298+
"\n",
299+
"``` python\n",
300+
"intersphinx_mapping = {\n",
301+
" 'python': ('https://docs.python.org/3.11', None),\n",
302+
" 'pandas': ('http://pandas.pydata.org/pandas-docs/stable/', None),\n",
303+
" 'numpy': ('https://docs.scipy.org/doc/numpy/', None),\n",
304+
"}\n",
305+
"```\n",
306+
"\n",
307+
"## Other Sphinx goodness:\n",
308+
"- You can configure it to generate a LaTeX-based PDF (i.e., a single user manual)\n",
309+
"- You can have versioned documentation, and also simultaneously have \"devel\" docs for unreleased changes.\n",
310+
"\n",
311+
"## GitHub Actions to automate Sphinx {.smaller}\n",
312+
"\n",
313+
"``` yaml\n",
314+
"name: \"Sphinx: Render docs\"\n",
315+
"\n",
316+
"on: push\n",
317+
"\n",
318+
"jobs:\n",
319+
" build:\n",
320+
" runs-on: ubuntu-latest\n",
321+
" permissions:\n",
322+
" contents: write\n",
323+
" steps:\n",
324+
" - uses: actions/checkout@v4\n",
325+
" with:\n",
326+
" persist-credentials: false\n",
327+
" - name: Build HTML\n",
328+
" uses: ammaraskar/sphinx-action@master\n",
329+
" - name: Upload artifacts\n",
330+
" uses: actions/upload-artifact@v4\n",
331+
" with:\n",
332+
" name: html-docs\n",
333+
" path: docs/build/html/\n",
334+
" - name: Deploy\n",
335+
" uses: peaceiris/actions-gh-pages@v4\n",
336+
" if: github.ref == 'refs/heads/main'\n",
337+
" with:\n",
338+
" github_token: ${{ secrets.GITHUB_TOKEN }}\n",
339+
" publish_dir: docs/build/html\n",
340+
"```\n",
341+
"\n",
342+
"## GitHub Actions setup\n",
343+
"\n",
344+
"1. Add `sphinx.ext.githubpages` to `extensions` in `conf.py`\n",
345+
"2. Add a `docs/requirements.txt` file for any dependencies (e.g., `myst-parser`)\n",
346+
"3. On GitHub, Settings -> Pages -> select `gh-pages` branch in the \"Source\" dropdown\n",
347+
"\n",
348+
"::: fragment\n",
349+
"More on Sphinx - GitHub Actions here: <https://www.sphinx-doc.org/en/master/tutorial/deploying.html>\n",
350+
":::\n"
351+
]
352+
}
353+
],
354+
"metadata": {
355+
"kernelspec": {
356+
"display_name": ".venv",
357+
"language": "python",
358+
"name": "python3"
359+
},
360+
"language_info": {
361+
"codemirror_mode": {
362+
"name": "ipython",
363+
"version": 3
364+
},
365+
"file_extension": ".py",
366+
"mimetype": "text/x-python",
367+
"name": "python",
368+
"nbconvert_exporter": "python",
369+
"pygments_lexer": "ipython3",
370+
"version": "3.13.1"
371+
}
372+
},
373+
"nbformat": 4,
374+
"nbformat_minor": 2
375+
}

0 commit comments

Comments
 (0)