Documentation is one of the most important things to consider when you are creating software. It is important to have a well-written document that can be used by other developers to aid them in their work. There are different forms of documentation, and one of them is Python code documentation format.
Documentation is important to writing efficient and high-quality code. A poorly documented piece of code leaves room for ambiguity, confusion, and bugs. It also makes it much more difficult for future programmers to understand your code, or even what the code is intended to do. A great way to avoid any problems related to documentation is to describe everything the user needs to know about a particular piece of data or program through properly written documentation.
When we write code for a project, or are tasked with reviewing other’s code and providing suggestions for improvements, it is important to also include good documentation. The code must be clean. The variable names should be descriptive to help the other developers looking at the code understand at a quick glance exactly what it is doing.
Documenting your code is all about making it easier to use and understand by humans. The primary target of our writing is beginners to the topic, and we expect to have a lot of readers who will probably browse our docs and pick a few examples to copy/paste, rather than reading everything.
How to Set Up Your Python Project Docs for Success
Automate your document creation workflow with Sphinx and Read the Docs
You made an awesome piece of Python software and released it to the public. Great!Unfortunately, that’s not enough. ️You need documentation!
Good documentation is vital to adoption. Making clear docs is one of the nicest thing you can do for your current and future package users.
Docs don’t write themselves, but you can get part way there with Read the Docs, Sphinx, and some tears. Just kidding, there might be some complications, but hopefully, there won’t be any tears.
Setting up docs to build automatically on each new release can be confusing. In this article, I’ll show you how to set up your docs so you can give your project the best chance of success. Let’s go!
If you don’t have a basic working Python package, check out my guide to making one here. Then read the next article to learn how to add tests, Travis, Coveralls, Black, and PyUp so that you have more faith your code won’t break.
The example project I’ll use in this article is pybraries, a wrapper I made for the libraries.io API. You can use it to subscribe to email alerts for new versions of open source packages. You can also use it to find information about many aspects of open source packages and repositories. Here are the docs. Let’s see how to build them!
Step 1: Set up Read the Docs
Read the Docs (RTD) hosts open source project docs for free! It’s very cool.
Set up your Read the Docs account at https://readthedocs.org.
Then do the following:
- Import your GitHub repository manually if you don’t see it listed as available to access on RTD.
- Once you are in your project on RTD, enter the relevant information and check the box for Edit advanced project options.
- On the next screen choose Python for your Programming Language.
- Click Finish. Then Admin. Then Advanced Settings.
- Check the box for Install your project inside a virtualenv using setup.py install and enter
requirements_dev.txt
in the Requirements file field (assuming that’s the name of your requirements file. Save. Alternatively, you can create a readthedocs.yml configuration file as explained here.
6. Click on the Builds tab. You should see that a build is in progress or completed.
7. When the build is completed, click on View Docs. These docs aren’t showing much info specific to our package yet — we’ll work on that in a moment.
When you push to GitHub your docs will build automatically if a webhoook is configured. If you automatically connected your repo to GitHub, you may not need to configure anything else for auto-builds.
If you manually imported your repo, you’ll need to set up a webhook. Instructions can be found here. I made minor improvements to these docs, so if you think something is unclear, improve them with a PR. Here’s how to add a webhook:
In your GitHub repo, go to Settings -> Webhooks -> Add webhook. You should see a form like the one below.
For Payload URL, go to RTD’s Integrations setting and copy the webhook information. Prepend it with https://
. You can leave everything else alone and click Add webhook. Or choose Let me select individual events if you want to trigger RTD doc builds in response to other GitHub events beyond pushes to the repo. FYI, I had to delete my webhook on RTD and GitHub and redo re-add the webhook to make it work.
Next time you push your code to GitHub and merge the PR, head to RTD. You should see that your docs were rebuilt automatically! Give it a few minutes if you don’t see changes right away.
Cool! Now let’s set up Sphinx to generate our documents for RTD.
Step 2: Install and Configure Sphinx
Sphinx claims to make it easy to create intelligent and beautiful Python documents. I don’t know that I’d say it’s a snap, but Sphinx is pretty cool. Features include syntax highlighting, themes, and easy document linking. Here’s the Sphinx getting started guide for reference.
Add sphinx==3.03
to requirements_dev.txt and install it with pip install -r requirements_dev.txt
.
Create a docs directory in the top level of your project directory. In that directory, run sphinx-quickstart
from the command line.
You will be asked a few questions. Enter the project name and author name when prompted. Generally the defaults are what you want.
The following files will be generated automatically:
- index.rst
- conf.py
- Makefile
conf.py
conf.py controls how Sphinx runs when the docs are built. In it, you configure project documentation settings. Let’s make a few changes to conf.py to make Sphinx create better docs. Uncomment and adjust the section so the abspath is ..
import os
import sys
sys.path.insert(0, os.path.abspath('..'))
Insert the following into the list of extensions:
extensions = [
'sphinx.ext.napoleon',
'sphinx.ext.autodoc',
'sphinx.ext.viewcode',
'sphinx.ext.coverage',
]
I’m not a fan of the alabaster template, so I added sphinx_rtd_theme==0.4.3
to my requirement_dev.py file and installed it.
If you do the same thing, change the line about html_theme in conf.py to this:
html_theme = ‘sphinx_rtd_theme’
Make
Make is a build automation tool. The Makefile that was generated by Sphinx controls how shortcut commands that start with make
operate. Learn more about makefiles here. You can probably get by without digging deeply into Make.
Run make html
from the command line to create your docs with this one shortcut command. Then, in your docs->build_->html directory you should see index.html. Open the file in your browser and you should see your bare-bones docs.
To check for any undocumented functions and classes, add the following lines to your Makefile.
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -b coverage
The line-b coverage
appended creates a coverage report so that can tell you how much of your code is documented. Now when you run make html
, the html folder will contain a text file named python.txt. That will show you where you need some documentation.
Commit and continue on to make your doc files.
Step 3: Create Doc Files
You can choose whether to write your files in Markdown (hereinafter md) or reStructuredText (hereinafter rst). Md is closer to regular prose and faster to learn. However, rst allows you to use more of Sphinx’s powerful features. Here’s the GitHub guide to md and here’s the Sphinx guide to rst.
It’s your choice whether to invest the time in learning rst. There are about a billion other things you could learn, so if it isn’t at the top of your list, I get it. However, many project’s docs are written in rst, so it’s nice to know.
You can convert between snippets of md and rst quickly with this online pandoc converter. You can use it to copy-paste from one format to the other. CloudConvert does the same with whole files. CloudConvert starts charging after 25 minutes of use per day.
If you are going the rst route, switch your README file extension to .rst.
Also, setup.py will need the README name and long_description_content_type switched to rst.
I’m going to use rst. If you’re using md, change the file extensions below to .md.
Create the following files:
- CODE_OF_CONDUCT.rst
- CONTRIBUTING.rst
- HISTORY.rst
- README.rst
CODE_OF_CONDUCT.rst
Here’s GitHub info with a template code of conduct. The code of conduct explains how folks are expected to conduct themselves with regard to collaborating on your project and what to do if individuals are not acting appropriately. Add your email where the template has a place for it. If you want to copy the GitHub markdown template into rst, you can use one of the converters mentioned above.
CONTRIBUTING.rst
Make it easy for people who want to contribute to your project to do so. Put clear instructions in your contributing file. Feel free to use my file as a base.
HISTORY.rst
History will contain your changelog. It is helpful for package users. You can also use the contents in your release info on GitHub.
In history.rst add the following.
=======
History
=======0.0.1 (2020–05–15)
— — — — — — — — -* First release on PyPI.
Update the date to the appropriate date and add any other relevant bullet points. You’ll append the file as you make release new versions of your package.
README.rst
Your README should include install and basic use information. I suggest you point users to the full docs on RTD.
You can add other documents to your project, but make sure you put the file names in your index.rst’s TOC. Then they will show up and be linked to in your built docs.
Now let’s make sure our users can get help understanding what your functions and classes do.
Step 4: Add Docstrings
Docstrings are a method of communicating to your user how a class or function works. The docstrings will show up in your users’s code when they ask for help. Sphinx will take your docstrings and automatically make them usable in your docs on RTD, too.
Write your Docstrings in your code, immediately after the first line of your class or function. Docstrings start with triple quotes and should include any info your user might need, including information about parameters and return values.
Python doesn’t have one obvious way to format docstrings. Pick one way to write docstrings so they look neat and no one has to ask or think about how to do things.
I suggest using Google style — which is recommended for ease of writing and reading. A good discussion of docstring formatting can be found here.
Make sure you let your contributors know about your chosen docstring format by including instructions in your contributing file.
When you have docstrings in you code, you can then build your docs locally and see your docstrings in your browser. When the local version looks good, commit, push, and merge your PR to see your docstrings on RTD at your module page.
If things don’t work as expected, here are some suggestions to get you back on track:
Troubleshooting
Sphinx and RTD can break or cause docs to look different than expected for many reasons. Check the build logs in RTD to find errors.
Common problems include:
- If you docs are not building and you are using rst files, there is likely invalid rst somewhere. To find invalid rst, run file contents through one of the rst checkers mentioned above.
- If your docs build but your modules aren’t displaying, check the raw output logs on RTD for hints.
- Make sure your setup.py and requirements_dev.txt files are correct.
- If you need an environment variable for things to run add it in the RTD settings.
The RTD and Sphinx docs and Stack Overflow are helpful, but I’ve found this troubleshooting cumbersome. I feel your pain.
Now let’s look at a nicer topic — communicating information to prospective users via badges.
Step 5: Add Badges to README
Badges provide at-a-glance information to people interested in your project. Badges can instill confidence and legitimacy. Here’s an example of the badges that can sit atop your README:
Many badges are available at https://shields.io/ and https://badgen.net/. I added some of mine from shields.io. To get the badge code, don’t just copy the url next to the badge. Click on the URL. Then append your package name. See the example below for the wheel badge.
Then copy the md or rst code from the dropdown and paste it into your README.
Many badges are available at the website of the relevant app. PyUp, Travis, and Coveralls have badge code you can grab. For PyUp, if you click on the badge on your PyUp dashboard, you’ll then see the code you can copy and embed in your README.
Here’s RTD’s info on badges.
Cool! We’re badged. Finally, let’s look at facilitating collaboration.
Step 6: Create Issue and PR Templates
Help from the larger community is a great benefit available to an open source project. You want to make it easy for your users to report bugs and feature requests with relevant information. A great first step is providing a clear issue template.
Issue Templates
In your browser, go to your GitHub repo ->Settings -> Options. Under Features, click the Green Set up templates button.
You can add a custom issue template or use one of the default templates from GitHub.
Pull request templates are similarly helpful. GitHub has a good guide to making one here.
Now it’ll be easier for your to get help with your open source project!
Project Documentation
A README
file at the root directory should give general information to both users and maintainers of a project. It should be raw text or written in some very easy to read markup, such as reStructuredText or Markdown. It should contain a few lines explaining the purpose of the project or library (without assuming the user knows anything about the project), the URL of the main source for the software, and some basic credit information. This file is the main entry point for readers of the code.
An INSTALL
file is less necessary with Python. The installation instructions are often reduced to one command, such as pip install module
or python setup.py install
, and added to the README
file.
A LICENSE
file should always be present and specify the license under which the software is made available to the public.
A TODO
file or a TODO
section in README
should list the planned development for the code.
A CHANGELOG
file or section in README
should compile a short overview of the changes in the code base for the latest versions.
Automatic Python API documentation generation tools
- autosummary, an extension for the Sphinx documentation tool.
- autodoc, a Sphinx-based processor that processes/allows reST doc strings.
- pdoc, a simple Python 3 command line tool and library to auto-generate API documentation for Python modules. Supports Numpydoc / Google-style docstrings, doctests, reST directives, PEP 484 type annotations, custom templates …
- pdoc3, a fork of pdoc for Python 3 with support for Numpydoc / Google-style docstrings, doctests, LaTeX math, reST directives, PEP 484 type annotations, custom templates …
- PyDoc, a documentation browser (in HTML) and/or an off-line reference manual. Also in the standard library as pydoc.
- pydoctor, a replacement for now inactive Epydoc, born for the needs of Twisted project.
- Doxygen can create documentation in various formats (HTML, LaTeX, PDF, …) and you can include formulas in your documentation (great for technical/mathematical software). Together with Graphviz, it can create diagrams of your code (inhertance diagram, call graph, …). Another benefit is that it handles not only Python, but also several other programming languages like C, C++, Java, etc.
Conclusion
Documentation is a very important part of any software. But writing documentation is something quite different than technical writing. Python has made it easier than ever to document your code so that your users can understand how to use it. This process of making the code more understandable and easily digestible put extra budget on programmers when they want to write python documentation, which makes sense.
Python code documentation is one of the most basic things in any project. It is not the most obvious thing for a new programmer, because it does not create the code, but describes it. It seems that writing software code and its documentation means splitting your time. However, there is a solution — using Software Documentation Generator (also known as Swagger or Radoc) if you are working with Python. It allows creating beautiful and comprehensive documentation without interrupting your work on the project itself.