├── .gitignore ├── README.rst ├── handout ├── Makefile ├── api.rst ├── conf.py ├── guide.rst ├── handout.pdf ├── index.rst ├── make.bat ├── quick-rst.rst ├── quick-sphinx.rst ├── tutorial.rst ├── using-sphinx.rst ├── writing-api.rst ├── writing-guide.rst └── writing-tutorial.rst ├── requirements.txt ├── show.sh ├── slides.txt ├── texts ├── guide.txt └── tutorial.txt ├── thumbdrive-setup.sh ├── todo.txt └── triangle-project ├── setup.py └── trianglelib ├── __init__.py ├── shape.py ├── tests.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.egg-info 2 | *.pyc 3 | _build 4 | usb 5 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | 2 | ====================================== 3 | Documenting Your Project With Sphinx 4 | ====================================== 5 | 6 | Welcome! 7 | 8 | This repository contains all of the course materials 9 | that support the tutorial that Brandon Rhodes presented at PyCon 10 | every year from 2010 through 2013. 11 | 12 | The final 2013 version of the tutorial was recorded 13 | and can be watched in its entirety at the pyvideo.org: 14 | 15 | http://pyvideo.org/video/1660/documenting-your-project-in-sphinx 16 | -------------------------------------------------------------------------------- /handout/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = letter 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/trianglelib.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/trianglelib.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/trianglelib" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/trianglelib" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /handout/api.rst: -------------------------------------------------------------------------------- 1 | 2 | Example: api.rst — The trianglelib API reference 3 | ================================================ 4 | 5 | .. automodule:: trianglelib 6 | :members: 7 | 8 | The “shape” module 9 | ------------------ 10 | 11 | .. module:: trianglelib.shape 12 | 13 | .. autoclass:: Triangle 14 | :members: is_equilateral, is_isosceles, is_similar, 15 | perimeter, area, scale 16 | 17 | You instantiate a ``Triangle`` 18 | by providing exactly three lengths ``a``, ``b``, and ``c``. 19 | They can either be intergers or floating-point numbers, 20 | and should be listed clockwise around the triangle. 21 | If the three lengths *cannot* make a valid triangle, 22 | then ``ValueError`` will be raised instead. 23 | 24 | >>> from trianglelib.shape import Triangle 25 | >>> t = Triangle(3, 4, 5) 26 | >>> print t.is_equilateral() 27 | False 28 | >>> print t.area() 29 | 6.0 30 | 31 | Triangles support the following attributes, operators, and methods. 32 | 33 | .. attribute:: a 34 | b 35 | c 36 | 37 | The three side lengths provided during instantiation. 38 | 39 | .. index:: pair: equality; triangle 40 | .. method:: triangle1 == triangle2 41 | 42 | Returns true if the two triangles have sides of the same lengths, 43 | in the same order. 44 | Note that it is okay if the two triangles 45 | happen to start their list of sides at a different corner; 46 | ``3,4,5`` is the same triangle as ``4,5,3`` 47 | but neither of these are the same triangle 48 | as their mirror image ``5,4,3``. 49 | 50 | The “utils” module 51 | ------------------ 52 | 53 | .. automodule:: trianglelib.utils 54 | :members: 55 | -------------------------------------------------------------------------------- /handout/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Sphinx Tutorial documentation build configuration file, created by 4 | # sphinx-quickstart on Wed Feb 27 14:16:34 2013. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 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 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | sys.path.insert(0, os.path.abspath('../triangle-project')) 21 | 22 | # -- General configuration ----------------------------------------------------- 23 | 24 | # If your documentation needs a minimal Sphinx version, state it here. 25 | #needs_sphinx = '1.0' 26 | 27 | # Add any Sphinx extension module names here, as strings. They can be extensions 28 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 29 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.mathjax', 'sphinx.ext.viewcode'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | templates_path = ['_templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.rst' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8-sig' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = u'sphinx-tutorial' 45 | copyright = u'2013, Brandon Rhodes' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '1.0' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '2013.0' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | exclude_patterns = ['_build'] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | 91 | # -- Options for HTML output --------------------------------------------------- 92 | 93 | # The theme to use for HTML and HTML Help pages. See the documentation for 94 | # a list of builtin themes. 95 | html_theme = 'default' 96 | 97 | # Theme options are theme-specific and customize the look and feel of a theme 98 | # further. For a list of options available for each theme, see the 99 | # documentation. 100 | #html_theme_options = {} 101 | 102 | # Add any paths that contain custom themes here, relative to this directory. 103 | #html_theme_path = [] 104 | 105 | # The name for this set of Sphinx documents. If None, it defaults to 106 | # " v documentation". 107 | #html_title = None 108 | 109 | # A shorter title for the navigation bar. Default is the same as html_title. 110 | #html_short_title = None 111 | 112 | # The name of an image file (relative to this directory) to place at the top 113 | # of the sidebar. 114 | #html_logo = None 115 | 116 | # The name of an image file (within the static path) to use as favicon of the 117 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 118 | # pixels large. 119 | #html_favicon = None 120 | 121 | # Add any paths that contain custom static files (such as style sheets) here, 122 | # relative to this directory. They are copied after the builtin static files, 123 | # so a file named "default.css" will overwrite the builtin "default.css". 124 | html_static_path = ['_static'] 125 | 126 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 127 | # using the given strftime format. 128 | #html_last_updated_fmt = '%b %d, %Y' 129 | 130 | # If true, SmartyPants will be used to convert quotes and dashes to 131 | # typographically correct entities. 132 | #html_use_smartypants = True 133 | 134 | # Custom sidebar templates, maps document names to template names. 135 | #html_sidebars = {} 136 | 137 | # Additional templates that should be rendered to pages, maps page names to 138 | # template names. 139 | #html_additional_pages = {} 140 | 141 | # If false, no module index is generated. 142 | #html_domain_indices = True 143 | 144 | # If false, no index is generated. 145 | #html_use_index = True 146 | 147 | # If true, the index is split into individual pages for each letter. 148 | #html_split_index = False 149 | 150 | # If true, links to the reST sources are added to the pages. 151 | #html_show_sourcelink = True 152 | 153 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 154 | #html_show_sphinx = True 155 | 156 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 157 | #html_show_copyright = True 158 | 159 | # If true, an OpenSearch description file will be output, and all pages will 160 | # contain a tag referring to it. The value of this option must be the 161 | # base URL from which the finished HTML is served. 162 | #html_use_opensearch = '' 163 | 164 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 165 | #html_file_suffix = None 166 | 167 | # Output file base name for HTML help builder. 168 | htmlhelp_basename = 'sphinx-tutorial-doc' 169 | 170 | 171 | # -- Options for LaTeX output -------------------------------------------------- 172 | 173 | latex_elements = { 174 | # The paper size ('letterpaper' or 'a4paper'). 175 | #'papersize': 'letterpaper', 176 | 177 | # The font size ('10pt', '11pt' or '12pt'). 178 | #'pointsize': '10pt', 179 | 'pointsize': '12pt', 180 | 181 | # Additional stuff for the LaTeX preamble. 182 | #'preamble': '', 183 | 184 | # Eliminate blank pages per http://stackoverflow.com/questions/5422997/ 185 | 'babel' : r'\usepackage[english]{babel}', 186 | 'classoptions': ',openany,oneside', 187 | 'fncychap': r'\usepackage[Lenny]{fncychap}', 188 | } 189 | 190 | # Grouping the document tree into LaTeX files. List of tuples 191 | # (source start file, target name, title, author, documentclass [howto/manual]). 192 | latex_documents = [ 193 | ('index', 'sphinx-tutorial.tex', u"Brandon's Sphinx Tutorial", 194 | u'Brandon Rhodes', 'manual'), 195 | ] 196 | 197 | # The name of an image file (relative to this directory) to place at the top of 198 | # the title page. 199 | #latex_logo = None 200 | 201 | # For "manual" documents, if this is true, then toplevel headings are parts, 202 | # not chapters. 203 | #latex_use_parts = False 204 | 205 | # If true, show page references after internal links. 206 | #latex_show_pagerefs = False 207 | 208 | # If true, show URL addresses after external links. 209 | #latex_show_urls = False 210 | 211 | # Documents to append as an appendix to all manuals. 212 | #latex_appendices = [] 213 | 214 | # If false, no module index is generated. 215 | #latex_domain_indices = True 216 | 217 | 218 | # -- Options for manual page output -------------------------------------------- 219 | 220 | # One entry per manual page. List of tuples 221 | # (source start file, name, description, authors, manual section). 222 | man_pages = [ 223 | ('index', 'sphinx-tutorial', u"Brandon's Sphinx Tutorial", 224 | [u'Brandon Rhodes'], 1) 225 | ] 226 | 227 | # If true, show URL addresses after external links. 228 | #man_show_urls = False 229 | 230 | 231 | # -- Options for Texinfo output ------------------------------------------------ 232 | 233 | # Grouping the document tree into Texinfo files. List of tuples 234 | # (source start file, target name, title, author, 235 | # dir menu entry, description, category) 236 | texinfo_documents = [ 237 | ('index', 'sphinx-tutorial', u'Sphinx Tutorial', 238 | u'Brandon Rhodes', 'sphinx-tutorial', 'One line description of project.', 239 | 'Miscellaneous'), 240 | ] 241 | 242 | # Documents to append as an appendix to all manuals. 243 | #texinfo_appendices = [] 244 | 245 | # If false, no module index is generated. 246 | #texinfo_domain_indices = True 247 | texinfo_domain_indices = False 248 | 249 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 250 | #texinfo_show_urls = 'footnote' 251 | -------------------------------------------------------------------------------- /handout/guide.rst: -------------------------------------------------------------------------------- 1 | 2 | Example: guide.rst — The trianglelib guide 3 | ========================================== 4 | 5 | Whether you need to test the properties of triangles, 6 | or learn their dimensions, :mod:`trianglelib` does it all! 7 | 8 | Special triangles 9 | ----------------- 10 | 11 | There are two special kinds of triangle 12 | for which :mod:`trianglelib` offers special support. 13 | 14 | *Equilateral triangle* 15 | All three sides are of equal length. 16 | 17 | *Isosceles triangle* 18 | Has at least two sides that are of equal length. 19 | 20 | These are supported both by simple methods 21 | that are available in the :mod:`trianglelib.utils` module, 22 | and also by a pair of methods of the main 23 | :class:`~trianglelib.shape.Triangle` class itself. 24 | 25 | .. _triangle-dimensions: 26 | 27 | Triangle dimensions 28 | ------------------- 29 | 30 | The library can compute triangle perimeter, area, 31 | and can also compare two triangles for equality. 32 | Note that it does not matter which side you start with, 33 | so long as two triangles have the same three sides in the same order! 34 | 35 | >>> from trianglelib.shape import Triangle 36 | >>> t1 = Triangle(3, 4, 5) 37 | >>> t2 = Triangle(4, 5, 3) 38 | >>> t3 = Triangle(3, 4, 6) 39 | >>> print t1 == t2 40 | True 41 | >>> print t1 == t3 42 | False 43 | >>> print t1.area() 44 | 6.0 45 | >>> print t1.scale(2.0).area() 46 | 24.0 47 | 48 | Valid triangles 49 | --------------- 50 | 51 | Many combinations of three numbers cannot be the sides of a triangle. 52 | Even if all three numbers are positive instead of negative or zero, 53 | one of the numbers can still be so large 54 | that the shorter two sides 55 | could not actually meet to make a closed figure. 56 | If :math:`c` is the longest side, then a triangle is only possible if: 57 | 58 | .. math:: 59 | 60 | a + b > c 61 | 62 | While the documentation 63 | for each function in the :mod:`~trianglelib.utils` module 64 | simply specifies a return value for cases that are not real triangles, 65 | the :class:`~trianglelib.shape.Triangle` class is more strict 66 | and raises an exception if your sides lengths are not appropriate: 67 | 68 | >>> from trianglelib.shape import Triangle 69 | >>> Triangle(1, 1, 3) 70 | Traceback (most recent call last): 71 | ... 72 | ValueError: one side is too long to make a triangle 73 | 74 | If you are not sanitizing your user input 75 | to verify that the three side lengths they are giving you are safe, 76 | then be prepared to trap this exception 77 | and report the error to your user. 78 | -------------------------------------------------------------------------------- /handout/handout.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brandon-rhodes/sphinx-tutorial/dbfc1351ac2adcecfbd8ba76f231329e5bad369b/handout/handout.pdf -------------------------------------------------------------------------------- /handout/index.rst: -------------------------------------------------------------------------------- 1 | .. trianglelib documentation master file, created by 2 | sphinx-quickstart on Wed Feb 27 14:16:34 2013. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Welcome to the Sphinx Tutorial! 7 | =============================== 8 | 9 | | PyCon 2013 10 | | San Jose, California 11 | | Thursday morning 12 | | March 14th 13 | 14 | :: 15 | 16 | 9:00pm – 10:30pm First Half of Tutorial 17 | Break (refreshments served) 18 | 10:50pm – 12:20pm Conclusion of Tutorial 19 | 20 | Welcome to my Sphinx tutorial, 21 | which is now in its fourth year at PyCon. 22 | Sphinx has come a long way since this tutorial was first offered 23 | back on a cold February day in 2010, 24 | when the most recent version available was 0.6.4. 25 | Sphinx has now reached 1.1.3, 26 | and I have worked to keep this tutorial up to date 27 | with all of the most recent features in Sphinx. 28 | I hope you enjoy it with me! 29 | 30 | .. toctree:: 31 | :maxdepth: 2 32 | 33 | using-sphinx 34 | quick-rst 35 | quick-sphinx 36 | writing-api 37 | writing-tutorial 38 | writing-guide 39 | tutorial 40 | guide 41 | api 42 | -------------------------------------------------------------------------------- /handout/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. linkcheck to check all external links for integrity 37 | echo. doctest to run all doctests embedded in the documentation if enabled 38 | goto end 39 | ) 40 | 41 | if "%1" == "clean" ( 42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 43 | del /q /s %BUILDDIR%\* 44 | goto end 45 | ) 46 | 47 | if "%1" == "html" ( 48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 49 | if errorlevel 1 exit /b 1 50 | echo. 51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 52 | goto end 53 | ) 54 | 55 | if "%1" == "dirhtml" ( 56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 57 | if errorlevel 1 exit /b 1 58 | echo. 59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 60 | goto end 61 | ) 62 | 63 | if "%1" == "singlehtml" ( 64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 68 | goto end 69 | ) 70 | 71 | if "%1" == "pickle" ( 72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished; now you can process the pickle files. 76 | goto end 77 | ) 78 | 79 | if "%1" == "json" ( 80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished; now you can process the JSON files. 84 | goto end 85 | ) 86 | 87 | if "%1" == "htmlhelp" ( 88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can run HTML Help Workshop with the ^ 92 | .hhp project file in %BUILDDIR%/htmlhelp. 93 | goto end 94 | ) 95 | 96 | if "%1" == "qthelp" ( 97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 98 | if errorlevel 1 exit /b 1 99 | echo. 100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 101 | .qhcp project file in %BUILDDIR%/qthelp, like this: 102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\trianglelib.qhcp 103 | echo.To view the help file: 104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\trianglelib.ghc 105 | goto end 106 | ) 107 | 108 | if "%1" == "devhelp" ( 109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished. 113 | goto end 114 | ) 115 | 116 | if "%1" == "epub" ( 117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 121 | goto end 122 | ) 123 | 124 | if "%1" == "latex" ( 125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 129 | goto end 130 | ) 131 | 132 | if "%1" == "text" ( 133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The text files are in %BUILDDIR%/text. 137 | goto end 138 | ) 139 | 140 | if "%1" == "man" ( 141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 145 | goto end 146 | ) 147 | 148 | if "%1" == "texinfo" ( 149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 150 | if errorlevel 1 exit /b 1 151 | echo. 152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 153 | goto end 154 | ) 155 | 156 | if "%1" == "gettext" ( 157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 158 | if errorlevel 1 exit /b 1 159 | echo. 160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 161 | goto end 162 | ) 163 | 164 | if "%1" == "changes" ( 165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 166 | if errorlevel 1 exit /b 1 167 | echo. 168 | echo.The overview file is in %BUILDDIR%/changes. 169 | goto end 170 | ) 171 | 172 | if "%1" == "linkcheck" ( 173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 174 | if errorlevel 1 exit /b 1 175 | echo. 176 | echo.Link check complete; look for any errors in the above output ^ 177 | or in %BUILDDIR%/linkcheck/output.txt. 178 | goto end 179 | ) 180 | 181 | if "%1" == "doctest" ( 182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Testing of doctests in the sources finished, look at the ^ 186 | results in %BUILDDIR%/doctest/output.txt. 187 | goto end 188 | ) 189 | 190 | :end 191 | -------------------------------------------------------------------------------- /handout/quick-rst.rst: -------------------------------------------------------------------------------- 1 | 2 | RST Quick Reference 3 | =================== 4 | 5 | :: 6 | 7 | Underline titles with punctuation 8 | ================================= 9 | 10 | For subtitles, switch to another punctuation mark 11 | ------------------------------------------------- 12 | 13 | *Italic* **bold** ``name`` ``function()`` ``expression = 3 + 3`` 14 | `Hyperlink `_ `Link`_ 15 | 16 | .. _Link: http://en.wikipedia.org/wiki/Link_(The_Legend_of_Zelda) 17 | .. image:: images/python-logo.png 18 | .. A comment block starts with two periods, can continue indented. 19 | 20 | A paragraph is one or more lines of un-indented text, separated 21 | from the material above and below by blank lines. 22 | 23 | “Block quotes look like paragraphs, but are indented with 24 | one or more spaces.” 25 | 26 | | Because of the pipe characters, this will become one line, 27 | | And this will become another line, like in poetry. 28 | 29 | term 30 | Definition for the “term”, indented beneath it. 31 | another term 32 | And its definition; any of these definitions can continue on for 33 | several lines by — you guessed it! — being similarly indented. 34 | 35 | * Each item in a list starts with an asterisk (or “1.”, “a.”, etc). 36 | * List items can go on for several lines as long as you remember to 37 | keep the rest of the list item indented. 38 | 39 | Code blocks are introduced by a double-colon and are indented:: 40 | 41 | import docutils 42 | print help(docutils) 43 | 44 | >>> print 'But doctests start with ">>>" and need no indentation.' 45 | -------------------------------------------------------------------------------- /handout/quick-sphinx.rst: -------------------------------------------------------------------------------- 1 | 2 | Sphinx Quick Reference 3 | ====================== 4 | 5 | :: 6 | 7 | .. note:: 8 | 9 | Your note should consist of one or more paragraphs, all indented 10 | so that they clearly belong to the note and not to the text or 11 | directive that follows. 12 | 13 | Many other directives are also supported, including: warning, 14 | versionadded, versionchanged, seealso, deprecated, rubric, 15 | centered, hlist, glossary, productionlist. 16 | 17 | .. code-block:: c 18 | 19 | /* Or say "highlight::" once to set the language for all of the 20 | code blocks that follow it. Options include ":linenos:", 21 | ":linenothreshold:", and ":emphasize-lines: 1,2,3". */ 22 | 23 | char s[] = "You can also say 'python', 'ruby', ..., or 'guess'!"; 24 | 25 | .. literalinclude:: example.py 26 | :lines: 10-20 27 | :emphasize-lines: 15,16 28 | 29 | .. module:: httplib 30 | 31 | .. class:: Request 32 | 33 | Zero or more paragraphs of introductory material for the class. 34 | 35 | .. method:: send() 36 | 37 | Description of the send() method. 38 | 39 | .. attribute:: url 40 | 41 | Description of the url attribute. 42 | 43 | Many more members are possible than just method and attribute, 44 | and non-Python languages are supported too; see the Sphinx docs 45 | for more possibilities! 46 | 47 | .. testcode:: 48 | 49 | print 'The doctest extension supports code without >>> prompts!' 50 | 51 | .. testoutput:: 52 | 53 | The doctest extension supports code without >>> prompts! 54 | 55 | .. _custom-label: 56 | .. index:: single: paragraph, targeted paragraph, indexed paragraph 57 | 58 | This paragraph can be targeted with :ref:`custom-label`, and will also 59 | be the :index:`target` of several index entries! 60 | 61 | .. index:: pair: copper, wire 62 | 63 | This paragraph will be listed in the index under both “wire, copper” 64 | and “copper, wire.” See the Sphinx documentation for even more complex 65 | ways of building index entries. 66 | 67 | Many kinds of cross-reference can be used inside of a paragraph: 68 | 69 | :ref:`custom-label` :class:`~module.class` 70 | :doc:`quick-sphinx` :attr:`~module.class.method()` 71 | :mod:`module` :attr: `~module.class.attribute` 72 | 73 | (See the Sphinx “Inline Markup” chapter for MANY more examples!) 74 | -------------------------------------------------------------------------------- /handout/tutorial.rst: -------------------------------------------------------------------------------- 1 | 2 | Example: tutorial.rst — The trianglelib tutorial 3 | ================================================ 4 | 5 | .. index:: single: Euclid 6 | 7 | *“There is no royal road to geometry.”* — Euclid 8 | 9 | This module makes triangle processing fun! 10 | The beginner will enjoy how the :mod:`~trianglelib.utils` module 11 | lets you get started quickly. 12 | 13 | >>> from trianglelib import utils 14 | >>> utils.is_isosceles(5, 5, 7) 15 | True 16 | 17 | But fancier programmers can use the :class:`~trianglelib.shape.Triangle` 18 | class to create an actual triangle *object* 19 | upon which they can then perform lots of operations. 20 | For example, consider this Python program: 21 | 22 | .. testcode:: 23 | 24 | from trianglelib.shape import Triangle 25 | t = Triangle(5, 5, 5) 26 | print 'Equilateral?', t.is_equilateral() 27 | print 'Isosceles?', t.is_isosceles() 28 | 29 | Since methods like :meth:`~trianglelib.shape.Triangle.is_equilateral()` 30 | return Boolean values, this program will produce the following output: 31 | 32 | .. testoutput:: 33 | 34 | Equilateral? True 35 | Isosceles? True 36 | 37 | Read :doc:`guide` to learn more! 38 | 39 | .. warning:: 40 | 41 | This module only handles three-sided polygons; 42 | five-sided figures are right out. 43 | -------------------------------------------------------------------------------- /handout/using-sphinx.rst: -------------------------------------------------------------------------------- 1 | 2 | Notes on Using Sphinx 3 | ===================== 4 | 5 | Here are some quick notes on running Sphinx successfully. 6 | Each topic will be elaborated upon at the right point 7 | during our class. 8 | 9 | Starting a Sphinx project 10 | ------------------------- 11 | 12 | The wonder of a properly designed framework 13 | is that it begins by positioning you at a working starting point 14 | instead of leaving you to wander endlessly through a ``README`` 15 | that, after dozens of steps, leaves you guessing which step 16 | you did improperly to have wound up with a broken install. 17 | 18 | Sphinx gets you started with ``sphinx-quickstart``. 19 | Here is how a quick-start session will look, 20 | paying attention only to its prompts and how you should respond 21 | (which is mostly by pressing Return over and over), 22 | when you use it to create a new project:: 23 | 24 | $ sphinx-quickstart 25 | Welcome to the Sphinx quickstart utility... 26 | 27 | > Root path for the documentation [.]: doc 28 | > Separate source and build directories (y/N) [n]: 29 | > Name prefix for templates and static dir [_]: 30 | > Project name: trianglelib 31 | > Author name(s): Brandon 32 | > Project version: 1.0 33 | > Project release [1.0]: 34 | > Project language [en]: 35 | > Source file suffix [.rst]: .rst 36 | > Name of your master document (without suffix) [index]: index 37 | > Do you want to use the epub builder (y/N) [n]: n 38 | > autodoc: automatically insert docstrings ... (y/N) [n]: y 39 | > doctest: automatically test code snippets ... (y/N) [n]: y 40 | > intersphinx: ... (y/N) [n]: 41 | > todo: ... (y/N) [n]: 42 | > coverage: ... (y/N) [n]: 43 | > imgmath: ... (y/N) [n]: 44 | > mathjax: ... (y/N) [n]: y 45 | > ifconfig: ... (y/N) [n]: 46 | > viewcode: include links to the source code ... (y/N) [n]: y 47 | > githubpages: ... (y/n) [n]: 48 | > Create Makefile? (Y/n) [y]: y 49 | > Create Windows command file? (Y/n) [y]: y 50 | 51 | Sphinx layout 52 | ------------- 53 | 54 | After you have succeeded in quick-starting, 55 | your project should look something like this, 56 | if we imagine that you created your ``doc`` Sphinx directory 57 | right next to your ``trianglelib`` Python package directory:: 58 | 59 | your-project/ 60 | |-- doc/ 61 | | |-- Makefile 62 | | |-- _build/ 63 | | |-- _static/ 64 | | |-- _templates/ 65 | | |-- conf.py 66 | | |-- index.rst 67 | | `-- make.bat 68 | |-- setup.py 69 | `-- trianglelib/ 70 | |-- __init__.py 71 | |-- shape.py 72 | `-- utils.py 73 | 74 | The ``index.rst`` is your initial documentation file, 75 | whose table of contents you will expand 76 | as you add additional ``.rst`` files to this directory. 77 | 78 | Hints 79 | ----- 80 | 81 | Here are a few adjustments you can make to a Sphinx project 82 | once you have its files laid out and set up. 83 | 84 | * Sphinx is sensitive to indentation — 85 | blocks and code snippets end when the indentation level 86 | returns to its previous level — 87 | but Sphinx is usually forgiving about how far exactly you indent; 88 | you can generally choose freely how far to indent, 89 | so long as you are then consistent about sticking to that level. 90 | Sphinx is much like Python in this regard, 91 | but without a strong community preference for a particular 92 | number of spaces per indentation level. 93 | 94 | * Build your documentation by changing directory 95 | to the directory that contains the ``Makefile`` and then running:: 96 | 97 | make html 98 | 99 | * You can view the documentation by running Python's built-in 100 | web server, opening ``http://localhost:8000/`` in your web browser, 101 | and navigating into the ``_build/html`` directory:: 102 | 103 | python -m SimpleHTTPServer 104 | 105 | * Feel free to create directories beneath ``doc`` 106 | for groups of ``.rst`` files that do not belong at the top level. 107 | Simply refer to such files in your ``index.rst`` table of contents 108 | using a ``dir/filename`` syntax so that Sphinx can find them. 109 | 110 | * You can get rid of the line that says “Contents:” in ``index.rst`` 111 | since it causes a bizarre blank page in the PDF output. 112 | 113 | * To make prettier PDFs, remove the whole section in ``index.rst`` 114 | named “Indices and tables.” 115 | 116 | * Do not despair if you realize later that you need an extension 117 | that you failed to answer ``y`` to during the quick-start; 118 | simply go into the ``conf.py`` and add the extension to the 119 | ``extensions`` list and make any other changes the extension needs. 120 | You can always simply re-run the quick start to make a new project 121 | with the extension active, then run ``diff`` between your own 122 | ``Makefile`` and the new one to see what the differences are. 123 | 124 | * You can use Semantic Newlines to be friendly to your version control. 125 | 126 | * Here is a small diagram of how I think of documentation, 127 | which we will use as a rough guide during class:: 128 | 129 | developer developer 130 | new user writing new code reading code 131 | | | | 132 | v v v 133 | tutorial <--> topical guides <--> API reference 134 | 135 | Helping autodoc find your package 136 | --------------------------------- 137 | 138 | In order to run ``autodoc`` directives on your package, 139 | the Python interpreter that is running Sphinx for you 140 | needs to be able to import your package. 141 | You can test whether Python can see your package 142 | by testing whether this command returns without error:: 143 | 144 | python -c 'import your_package' 145 | 146 | There are three general approaches 147 | to making your package available to ``autodoc``. 148 | 149 | 1. Have your package's top-level directory 150 | sit right next to your Sphinx ``Makefile`` and ``conf.py`` 151 | and all of your top-level RST text files. 152 | When you type ``make`` inside this directory 153 | and it goes off and runs Sphinx, 154 | your package will be visible 155 | because it is sitting in the current working directory. 156 | 157 | *The downside:* you usually want your package 158 | sitting out by itself in your source distribution, 159 | not mixed in or sitting beneath its own documentation. 160 | 161 | 2. Set the Python path environment variable 162 | to point to the directory containing your package. 163 | You can do this with an ``export`` statement 164 | that you run before you start building your documentation:: 165 | 166 | export PYTHONPATH=/home/brandon/trianglelib 167 | 168 | Or you can set the Python path only for the build command itself, 169 | leaving your shell variable settings pristine:: 170 | 171 | PYTHONPATH=/home/brandon/triangle-project make html 172 | 173 | *The downside:* You either have to remember to manually 174 | set this environment variable each time you run Sphinx, 175 | or you have to create and maintain a small shell script 176 | as a separate file that will remember to set the path and run Sphinx. 177 | 178 | 3. If you have installed Sphinx inside a virtual environment — 179 | which is a really, really great idea — 180 | then you can install your under-development package there too 181 | by using the pip ``--editable`` flag:: 182 | 183 | pip install -e /home/brandon/triangle-project 184 | 185 | Once you have run this command, the Python running 186 | inside of this virtual environment is permanently able 187 | to ``import`` ``trianglelib`` without further ado. 188 | (Assuming that you do not remove the project from your filesystem!) 189 | 190 | *The downside:* When you check the project out 191 | on to a fresh machine, you either have to always remember 192 | to manually set up the virtual environment the right way, 193 | or you have to keep a shell script in the repository 194 | that sets it up for you each time. 195 | (Even though that is a good idea anyway.) 196 | 197 | 4. Assuming that your package and its documentation 198 | are part of the same source repository — as they should be — 199 | they will always have the same relative position on the filesystem. 200 | In this case, you can simply edit the Sphinx ``conf.py`` 201 | so that its ``sys.path`` configuration entry 202 | points at the relative position of your package:: 203 | 204 | sys.path.append(os.path.abspath('../triangle-project')) 205 | 206 | *All upside:* this is, in my opinion, the best approach, 207 | as it always goes along for the ride with your repository, 208 | and works immediately upon repository check-out 209 | without having to rely on any intermediate setup steps. 210 | 211 | Deployment 212 | ---------- 213 | 214 | We will discuss this topic in depth, 215 | but here are some links for your further reference 216 | when the class is complete: 217 | 218 | * It should be possible to export the contents of ``_build/html`` 219 | to any file-system-based web service and serve it as static content. 220 | 221 | * You can package the documentation in a ZIP file 222 | and upload it using the “edit” page for your Python package, 223 | and it will appear at the URL: 224 | 225 | ``http://pythonhosted.org/`` 226 | 227 | Detailed instructions for this procedure live at: 228 | 229 | http://pythonhosted.org/ 230 | 231 | * The powerful and popular Read the Docs service 232 | lets you configure your GitHub repository 233 | so that every time you push a new version of your software, 234 | the documentation gets automatically rebuilt 235 | and made available at: 236 | 237 | ``https://readthedocs.org/projects//`` 238 | 239 | Read the Docs also supports custom host names 240 | if you want your documentation to appear beneath your own 241 | project sub-domain. 242 | More information is available at: 243 | 244 | https://readthedocs.org/ 245 | 246 | * Creating a PDF is nearly as simple as running:: 247 | 248 | make html 249 | 250 | Except that you have to have the Latex typesetting system installed, 251 | which is a daunting task on many platforms and operating systems. 252 | On my own Ubuntu Linux laptops, 253 | I need to install several packages before even attempting it:: 254 | 255 | texlive-fonts-recommended 256 | texlive-latex-recommended 257 | texlive-latex-extra 258 | 259 | * See the Sphinx documentation for several other supported formats! 260 | 261 | * We will tackle simple theming tasks during the tutorial's 262 | second half; remember that the PyEphem project is a good living 263 | example of how to completely replace the Sphinx HTML themes 264 | with one of your own, so that you are essentially using Sphinx 265 | to build your own web site. 266 | -------------------------------------------------------------------------------- /handout/writing-api.rst: -------------------------------------------------------------------------------- 1 | 2 | Writing ‘api.rst’ 3 | ================= 4 | 5 | Your first assignment is to create your own ``api.rst`` document 6 | whose output looks just like the chapter 7 | “The trianglelib API reference” at the end of this handout! 8 | 9 | Approach this task as three smaller steps. 10 | For your first try, just use three plain autodoc directives 11 | to generate your entire chapter from the contents 12 | of the ``trianglelib`` docstrings. 13 | Separate the three ``autodoc`` directives 14 | with sub-titles to make the chapter more organized:: 15 | 16 | The trianglelib API reference 17 | ============================= 18 | 19 | .. automodule:: trianglelib 20 | :members: 21 | 22 | The “shape” module 23 | ------------------ 24 | 25 | .. automodule:: trianglelib.shape 26 | :members: 27 | 28 | The “utils” module 29 | ------------------ 30 | 31 | .. automodule:: trianglelib.utils 32 | :members: 33 | 34 | Add ``api`` to the list of chapters in your table of contents 35 | in the ``index.rst`` file, and then build the resulting document. 36 | Note that you will get errors 37 | if Sphinx cannot find the ``trianglelib`` Python module, 38 | in which case you should consult the solutions 39 | in the :doc:`using-sphinx` chapter of this document. 40 | 41 | Once your build is successful, take a look at your output document. 42 | It should already contain most of the information that you need! 43 | Compare the output carefully with the corresponding example 44 | bound with this documentation. 45 | What changes will you have to learn how to make 46 | in order to get the two documents to match? 47 | 48 | For example: 49 | where is the text describing how to instantiate ``Triangle``? 50 | You will need to add it manually, 51 | because ``autodoc`` does not pull that information from your code. 52 | So you will need to take control of that class's presentation. 53 | To take control, 54 | switch ``shape`` from the using the ``automodule::`` directive 55 | to using the plain old ``module::`` directive, 56 | which produces *no output* of its own 57 | but makes you explicitly provide its contents yourself. 58 | This frees you up to build your own version of ``Triangle`` 59 | that includes some introductory text before getting to work 60 | on its members: 61 | 62 | :: 63 | 64 | .. module:: trianglelib.shape 65 | 66 | .. autoclass:: Triangle 67 | :members: 68 | 69 | 70 | 71 | Note that the name of the class ``Triangle`` 72 | does not have to be prefixed with ``trianglelib.shape.`` 73 | because the ``module::`` directive 74 | had already told Sphinx about where to look 75 | for the classes and methods that you describe in this file. 76 | 77 | You are getting closer, 78 | but the documentation still does not look exactly the same. 79 | For one thing, the first method shown right now is ``area()`` 80 | since functions and attributes 81 | are shown in alphabetical order by default. 82 | Try each of the following directives in turn 83 | to achieve some other possible orderings:: 84 | 85 | :member-order: bysource 86 | 87 | :member-order: groupwise 88 | 89 | :members: is_equilateral, is_isosceles, ... 90 | 91 | Note that you can also say ``:exclude-members:`` 92 | followed by the names of methods to leave out. 93 | 94 | At that point your API chapter 95 | will begin to strongly resemble the printed one! 96 | Here are further bonus goals in case you finish early: 97 | 98 | 1. How can you display the attributes ``a``, ``b``, and ``c`` 99 | as presented in the printed document? 100 | 101 | 2. The printed chapter describes the triangle ``__eq__()`` method 102 | by actually showing two triangles compared with the ``==`` operator; 103 | can you get your version of the document to show the same thing? 104 | 105 | 3. If you have not done so already, add in the example doctest 106 | that stands just beneath the instantiation instructions 107 | in the printed version of the chapter. 108 | 109 | 4. Try running ``make`` ``doctest`` — are your code samples correct? 110 | Add some deliberate errors into the code to see what the output 111 | looks like when doctests fail. 112 | 113 | 5. Create example doctests for a few of the functions in ``utils`` 114 | by turning off ``automodule`` for the ``utils`` module, 115 | explicitly autodoc'ing each of its five functions 116 | to pull them back into your documentation, 117 | and adding example code beneath each one. 118 | -------------------------------------------------------------------------------- /handout/writing-guide.rst: -------------------------------------------------------------------------------- 1 | 2 | Writing ‘guide.rst’ 3 | =================== 4 | 5 | Given how much markup you have already learned, 6 | you will probably find marking up the Guide 7 | to be a more modest challenge than those you have enjoyed so far. 8 | Once you have it marked up and looking good, 9 | here is a list of bonus challenges you might try out: 10 | 11 | 1. Make all of the references to function, class, and method names 12 | turn into real hyperlinks into the API chapter. 13 | 14 | 2. In accomplishing the first goal, 15 | you probably had to use the package name ``trianglelib`` 16 | quite a lot, which involves a quite depressing amount of repetition. 17 | While you cannot use the ``module::`` directive here, 18 | since this is not the API documentation, try using the directive 19 | ``currentmodule::`` ``trianglelib`` at the top of the Guide 20 | and verify that you can then remove the module name 21 | from the beginning of all of your cross references. 22 | 23 | 3. Are the doctests in the guide really running 24 | every time you type ``make`` ``doctest``? 25 | Try ending the paragraph that precedes them with ``:`` 26 | and then with ``::`` and observe the difference in results. 27 | 28 | 4. Note the three periods that form an ellipsis ``"..."`` 29 | in the traceback shown in the guide. 30 | This is a standard established long ago 31 | by the Python Standard Library's doctest module 32 | that lets you avoid including the whole ugly traceback — 33 | which you would then have to edit and correct 34 | every time a line number changed in one of your source files! 35 | Try removing the ellipsis to confirm that ``make`` ``doctest`` 36 | indeed fails if it is asked to literally match 37 | the contents of the traceback. 38 | 39 | 5. I have grown to dislike doctests more and more over the years, 40 | most recently because users cannot easily cut-and-paste doctest code 41 | into their own programs without then having to manually backspace 42 | over all of the ``>>>`` prompts that get pasted in with the code. 43 | Convert the example in the :ref:`triangle-dimensions` section 44 | into a ``testcode::`` block and a ``testoutput::`` block instead, 45 | and confirm that the block is getting detected, executed, and 46 | tested when you run ``make`` ``doctest``. 47 | 48 | 6. If you are able to access the Sphinx documentation 49 | during the tutorial, look up the ``math`` Sphinx extension 50 | and try to figure out how I made the inequality equation 51 | so very pretty. 52 | As a super bonus, see if you can replace the inequality 53 | with this equivalent expression: 54 | 55 | .. math:: 56 | 57 | {a + b \over c} > 1 58 | -------------------------------------------------------------------------------- /handout/writing-tutorial.rst: -------------------------------------------------------------------------------- 1 | 2 | Writing ‘tutorial.rst’ 3 | ====================== 4 | 5 | Having written our low-level API documentation, 6 | we are now going to turn to the first thing a new user reads: 7 | your tutorial! 8 | 9 | The tutorial is short to keep this tutorial from going too long, 10 | but it does try to both serve the real purpose of a tutorial, 11 | which is to show users how to get started with your library, 12 | and it also should help you practice reStructuredText. 13 | 14 | Remember to add your tutorial document's filename 15 | to the table of contents in your ``index.rst`` file! 16 | 17 | While plain ``names`` and ``attributes`` are simply 18 | displayed in a typewriter font, ``functions()`` and ``methods()`` 19 | should be followed by a pair of parenthesis to make them look right. 20 | 21 | Your task is to make the tutorial's text look as pretty 22 | as it does in the printed copy here in this handout. 23 | Here are some bonus goals if you finish early: 24 | 25 | 1. Do you know whether the sample program really works? 26 | Add a deliberate mistake to it and try running ``make`` ``doctest`` 27 | to see if you really get presented with an error. 28 | If no error appears, then consult the previous :doc:`quick-sphinx` 29 | chapter and try to figure out how to mark up the code and output 30 | so that they get tested. 31 | 32 | 2. Whenever a module, class, or function is mentioned 33 | in the text, you should mark it to create a cross-reference 34 | into the API document you have already written. 35 | Try out the following two styles of cross-reference 36 | and see what difference they make in your formatted output:: 37 | 38 | the :class:`trianglelib.shape.Triangle` class 39 | the :class:`~trianglelib.shape.Triangle` class 40 | 41 | 3. If you managed to get the quote from Euclid to appear 42 | at the top of your tutorial, how might you make it appear 43 | in the index under the entry “Euclid”? 44 | 45 | 4. In the sentence “Read *The trianglelib guide* to learn more”, 46 | we want the phrase “The trianglelib guide” to become 47 | an actual hyperlink to the guide itself. 48 | Create a nearly empty ``guide.rst`` document that consists 49 | of just an underlined title for right now, 50 | add it to your table of contents, 51 | and see whether you can make the cross reference a clickable link. 52 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | -------------------------------------------------------------------------------- /show.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # For a completely white background: -bg "#ffffff" 3 | 4 | exec xterm -geometry 60x22 \ 5 | -T "Emacs" -fa "Inconsolata" -fs 24 -fg black \ 6 | -e 'exec emacs -nw slides.txt' 7 | -------------------------------------------------------------------------------- /slides.txt: -------------------------------------------------------------------------------- 1 | 2 | *** The Sphinx Tutorial *** 3 | 4 | Brandon Rhodes 5 | PyCon 2013 6 | Santa Clara, California 7 | 8 | ----------------------------------------------------------- 9 | 10 | 11 | 12 | 13 | * Please make sure Python is installed on your laptop. 14 | * Then install Sphinx! Two approaches: 15 | 16 | $ pip install sphinx 17 | -- OR -- 18 | From the thumb drive "packages/" installing: 19 | docutils, Pygments, Jinja2, Sphinx 20 | 21 | 22 | 23 | 24 | 25 | * Writing documentation 26 | 27 | - Automatic API documentation 28 | - Hand-crafted API documentation 29 | - Tutorial introduction 30 | - Topical guides 31 | 32 | 33 | * Deploying documentation 34 | 35 | - Serving as static HTML 36 | - Hosting on Read The Docs 37 | - Storing in version control 38 | - Theming the HTML version 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Community Hosting 48 | ----------------- 49 | 50 | 51 | 52 | * pythonhosted.org 53 | * ReadTheDocs.com 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | pythonhosted.org 64 | ---------------- 65 | 66 | 67 | * Used to be named packages.python.org 68 | 69 | * Inconvenient: requires ZIP file upload 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | ReadTheDocs.com 80 | --------------- 81 | 82 | * Popular, well supported, awesome 83 | 84 | * First written at the 2010 Django Dash 85 | 86 | http://www.slideshare.net/ericholscher 87 | /the-story-and-tech-of-read-the-docs 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | Deploying to Read the Docs 98 | 99 | 100 | 101 | 102 | (A story, in four images) 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | https://brandons-sphinx-tutorial.readthedocs.org/ 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | Staying up to date on Read the Docs 126 | 127 | 128 | 129 | 130 | (A story, in two lines of code and three images) 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | Create a tag in your version control 141 | 142 | 143 | 144 | $ git tag -a v0.1 -m 'Tagged v0.1' 145 | $ git push --tags 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | NOTHING HAPPENED 157 | 158 | 159 | 160 | 161 | I had forgotten the service hook! 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | Then: RTD Admin 175 | » Versions 176 | » Choose Active Versions 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | Version Control 186 | --------------- 187 | 188 | 189 | 190 | - Semantic newlines can keep diffs simple 191 | See my blog post "Semantic Linefeeds" 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | Theming 202 | ------- 203 | 204 | 205 | 206 | * Choosing a different theme 207 | * Customizing a theme 208 | * Taking control of your own 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | Local variables: 222 | mode:text 223 | mode:page 224 | fill-column:59 225 | End: 226 | -------------------------------------------------------------------------------- /texts/guide.txt: -------------------------------------------------------------------------------- 1 | 2 | Example: guide.rst — The trianglelib guide 3 | 4 | Whether you need to test the properties of triangles, 5 | or learn their dimensions, trianglelib does it all! 6 | 7 | Special triangles 8 | 9 | There are two special kinds of triangle 10 | for which trianglelib offers special support. 11 | 12 | Equilateral triangle 13 | All three sides are of equal length. 14 | 15 | Isosceles triangle 16 | Has at least two sides that are of equal length. 17 | 18 | These are supported both by simple methods 19 | that are available in the trianglelib.utils module, 20 | and also by a pair of methods of the main 21 | Triangle class itself. 22 | 23 | Triangle dimensions 24 | 25 | The library can compute triangle perimeter, area, 26 | and can also compare two triangles for equality. 27 | Note that it does not matter which side you start with, 28 | so long as two triangles have the same three sides in the same order! 29 | 30 | >>> from trianglelib.shape import Triangle 31 | >>> t1 = Triangle(3, 4, 5) 32 | >>> t2 = Triangle(4, 5, 3) 33 | >>> t3 = Triangle(3, 4, 6) 34 | >>> print t1 == t2 35 | True 36 | >>> print t1 == t3 37 | False 38 | >>> print t1.area() 39 | 6.0 40 | >>> print t1.scale(2.0).area() 41 | 24.0 42 | 43 | Valid triangles 44 | 45 | Many combinations of three numbers cannot be the sides of a triangle. 46 | Even if all three numbers are positive instead of negative or zero, 47 | one of the numbers can still be so large 48 | that the shorter two sides 49 | could not actually meet to make a closed figure. 50 | If c is the longest side, then a triangle is only possible if: 51 | 52 | a + b > c 53 | 54 | While the documentation 55 | for each function in the utils module 56 | simply specifies a return value for cases that are not real triangles, 57 | the Triangle class is more strict 58 | and raises an exception if your sides lengths are not appropriate: 59 | 60 | >>> from trianglelib.shape import Triangle 61 | >>> Triangle(1, 1, 3) 62 | Traceback (most recent call last): 63 | ... 64 | ValueError: one side is too long to make a triangle 65 | 66 | If you are not sanitizing your user input 67 | to verify that the three side lengths they are giving you are safe, 68 | then be prepared to trap this exception 69 | and report the error to your user. 70 | -------------------------------------------------------------------------------- /texts/tutorial.txt: -------------------------------------------------------------------------------- 1 | 2 | Example: tutorial.rst — The trianglelib tutorial 3 | 4 | “There is no royal road to geometry.” — Euclid 5 | 6 | This module makes triangle processing fun! 7 | The beginner will enjoy how the utils module 8 | lets you get started quickly. 9 | 10 | >>> from trianglelib import utils 11 | >>> utils.is_isosceles(5, 5, 7) 12 | True 13 | 14 | But fancier programmers can use the Triangle 15 | class to create an actual triangle object 16 | upon which they can then perform lots of operations. 17 | For example, consider this Python program: 18 | 19 | from trianglelib.shape import Triangle 20 | t = Triangle(5, 5, 5) 21 | print 'Equilateral?', t.is_equilateral() 22 | print 'Isosceles?', t.is_isosceles() 23 | 24 | Since methods like is_equilateral() 25 | return Boolean values, this program will produce the following output: 26 | 27 | Equilateral? True 28 | Isosceles? True 29 | 30 | Read the Guide to learn more! 31 | 32 | This module only handles three-sided polygons; 33 | five-sided figures are right out. 34 | -------------------------------------------------------------------------------- /thumbdrive-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | mkdir -p usb 6 | 7 | cd usb 8 | 9 | mkdir -p Mac 10 | mkdir -p Windows 11 | 12 | cd Mac 13 | wget -c http://www.python.org/ftp/python/2.7.3/python-2.7.3-macosx10.6.dmg 14 | wget -c http://www.python.org/ftp/python/2.7.3/python-2.7.3-macosx10.3.dmg 15 | cd .. 16 | 17 | cd Windows 18 | wget -c http://www.python.org/ftp/python/2.7.3/python-2.7.3.msi 19 | cd .. 20 | 21 | mkdir -p packages 22 | 23 | cd packages 24 | wget -c http://pypi.python.org/packages/2.6/S/Sphinx/Sphinx-1.1.3-py2.6.egg 25 | wget -c http://pypi.python.org/packages/2.7/S/Sphinx/Sphinx-1.1.3-py2.7.egg 26 | wget -c http://pypi.python.org/packages/source/S/Sphinx/Sphinx-1.1.3.tar.gz 27 | 28 | wget -c http://pypi.python.org/packages/source/P/Pygments/Pygments-1.6.tar.gz 29 | wget -c http://pypi.python.org/packages/2.7/P/Pygments/Pygments-1.6-py2.7.egg 30 | wget -c http://pypi.python.org/packages/2.6/P/Pygments/Pygments-1.6-py2.6.egg 31 | 32 | wget -c https://pypi.python.org/packages/source/J/Jinja2/Jinja2-2.6.tar.gz 33 | 34 | wget -c https://pypi.python.org/packages/source/d/docutils/docutils-0.10.tar.gz 35 | 36 | wget -c http://pypi.python.org/packages/source/v/virtualenv/virtualenv-1.9.1.tar.gz 37 | 38 | tar xvfz virtualenv-1.9.1.tar.gz 39 | cd virtualenv-1.9.1 40 | cp virtualenv.py .. 41 | cp -r virtualenv_support .. 42 | cd .. 43 | rm -rf virtualenv-1.9.1 44 | cd .. 45 | 46 | cd Sphinx-Tutorial 47 | if [ ! -d triangle-project ] 48 | then 49 | mkdir triangle-project 50 | fi 51 | 52 | cp -r ../../triangle-project/setup.py triangle-project 53 | cp -r ../../triangle-project/trianglelib triangle-project 54 | cp -r ../../triangle-project/texts triangle-project 55 | 56 | find triangle-project -name '*.pyc' | xargs rm 57 | 58 | echo Done building! 59 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | instructions on web site 2 | email to people? 3 | look over build.sh from old tutorial? 4 | build vagrant box? 5 | mention that the way you import should create a best-practice; show options 6 | what to do with "Indices and tables" section? create some advice. 7 | explain conf.py 8 | tour the Sphinx documentation 9 | *n*\ th 10 | small steps 11 | jim fulton structured text -> david goodger rst -> georg brandl sphinx 12 | semantic newlines 13 | indentation sensitive 14 | title underlines are arbitrary punctuation 15 | indentation levels are often arbitrary 16 | subtitle just has to be different; no punctuation is registered as "bigger" 17 | bullets can be + or - as well 18 | blockquoting a bulleted list by mistake 19 | show search engine 20 | -------------------------------------------------------------------------------- /triangle-project/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | import trianglelib 3 | 4 | setup( 5 | name='trianglelib', 6 | description=trianglelib.__doc__.splitlines()[0], 7 | author='Brandon Rhodes', 8 | author_email='brandon@rhodesmill.org', 9 | py_modules=['trianglelib'], 10 | ) 11 | -------------------------------------------------------------------------------- /triangle-project/trianglelib/__init__.py: -------------------------------------------------------------------------------- 1 | """Routines for working with triangles. 2 | 3 | The two modules inside of this package are packed with useful features 4 | for the programmer who needs to support triangles: 5 | 6 | ``shape`` 7 | This module provides a full-fledged `Triangle` object that can be 8 | instantiated and then asked to provide all sorts of information 9 | about its properties. 10 | 11 | ``utils`` 12 | For the programmer in a hurry, this module offers quick functions 13 | that take as arguments the three side lengths of a triangle, and 14 | perform a quick computation without the programmer having to make 15 | the extra step of creating an object. 16 | 17 | """ 18 | -------------------------------------------------------------------------------- /triangle-project/trianglelib/shape.py: -------------------------------------------------------------------------------- 1 | """Use the triangle class to represent triangles.""" 2 | 3 | from math import sqrt 4 | 5 | class Triangle(object): 6 | """A triangle is a three-sided polygon.""" 7 | 8 | def __init__(self, a, b, c): 9 | """Create a triangle with sides of lengths `a`, `b`, and `c`. 10 | 11 | Raises `ValueError` if the three length values provided cannot 12 | actually form a triangle. 13 | 14 | """ 15 | self.a, self.b, self.c = float(a), float(b), float(c) 16 | if any( s <= 0 for s in (a, b, c) ): 17 | raise ValueError('side lengths must all be positive') 18 | if any( a >= b + c for a, b, c in self._rotations() ): 19 | raise ValueError('one side is too long to make a triangle') 20 | 21 | def _rotations(self): 22 | """Return each of the three ways of rotating our sides.""" 23 | return ((self.a, self.b, self.c), 24 | (self.c, self.a, self.b), 25 | (self.b, self.c, self.a)) 26 | 27 | def __eq__(self, other): 28 | """Return whether this triangle equals another triangle.""" 29 | sides = (self.a, self.b, self.c) 30 | return any( sides == rotation for rotation in other._rotations() ) 31 | 32 | def is_similar(self, triangle): 33 | """Return whether this triangle is similar to another triangle.""" 34 | return any( (self.a / a == self.b / b == self.c / c) 35 | for a, b, c in triangle._rotations() ) 36 | 37 | def is_equilateral(self): 38 | """Return whether this triangle is equilateral.""" 39 | return self.a == self.b == self.c 40 | 41 | def is_isosceles(self): 42 | """Return whether this triangle is isoceles.""" 43 | return any( a == b for a, b, c, in self._rotations() ) 44 | 45 | def perimeter(self): 46 | """Return the perimeter of this triangle.""" 47 | return self.a + self.b + self.c 48 | 49 | def area(self): 50 | """Return the area of this triangle.""" 51 | s = self.perimeter() / 2.0 52 | return sqrt(s * (s - self.a) * (s - self.b) * (s - self.c)) 53 | 54 | def scale(self, factor): 55 | """Return a new triangle, `factor` times the size of this one.""" 56 | return Triangle(self.a * factor, self.b * factor, self.c * factor) 57 | -------------------------------------------------------------------------------- /triangle-project/trianglelib/tests.py: -------------------------------------------------------------------------------- 1 | from unittest import TestCase 2 | from trianglelib import shape, utils 3 | 4 | class TestShape(TestCase): 5 | 6 | def test_rotations(self): 7 | t = shape.Triangle(4, 5, 6) 8 | assert t._rotations() == ((4, 5, 6), (6, 4, 5), (5, 6, 4)) 9 | 10 | def test_eq(self): 11 | t = shape.Triangle(4, 5, 6) 12 | assert t == shape.Triangle(4, 5, 6) 13 | assert t == shape.Triangle(6, 4, 5) 14 | assert t == shape.Triangle(5, 6, 4) 15 | 16 | def test_is_similar(self): 17 | t = shape.Triangle(4, 5, 6) 18 | assert t.is_similar(shape.Triangle(4, 5, 6)) 19 | assert t.is_similar(shape.Triangle(10, 12, 8)) 20 | 21 | def test_is_equilateral(self): 22 | assert shape.Triangle(4, 5, 6).is_equilateral() is False 23 | assert shape.Triangle(4, 4, 4).is_equilateral() is True 24 | 25 | def test_is_isosceles(self): 26 | assert shape.Triangle(4, 5, 6).is_isosceles() is False 27 | assert shape.Triangle(4, 5, 5).is_isosceles() is True 28 | 29 | def test_perimeter(self): 30 | assert shape.Triangle(4, 5, 6).perimeter() == 15 31 | assert shape.Triangle(30, 40, 50).perimeter() == 120 32 | 33 | def test_area(self): 34 | assert shape.Triangle(3, 4, 5).area() == 6 35 | assert shape.Triangle(30, 40, 50).area() == 600 36 | 37 | def test_scale(self): 38 | assert shape.Triangle(3, 4, 5).scale(10) == shape.Triangle(30, 40, 50) 39 | 40 | class TestUtils(TestCase): 41 | 42 | def test_is_triangle(self): 43 | assert utils.is_triangle(4, 5, 6) is True 44 | assert utils.is_triangle(10, 20, 40) is False 45 | 46 | def test_is_equilateral(self): 47 | assert utils.is_equilateral(4, 5, 60) is False 48 | assert utils.is_equilateral(4, 5, 6) is False 49 | assert utils.is_equilateral(6, 6, 6) is True 50 | 51 | def test_is_isosceles(self): 52 | assert utils.is_isosceles(6, 6, 70) is False 53 | assert utils.is_isosceles(4, 5, 6) is False 54 | assert utils.is_isosceles(6, 6, 7) is True 55 | 56 | def test_compute_perimeter(self): 57 | assert utils.compute_perimeter(6, 6, 70) == 0 58 | assert utils.compute_perimeter(4, 5, 6) == 15 59 | assert utils.compute_perimeter(6, 6, 7) == 19 60 | 61 | def test_compute_area(self): 62 | assert utils.compute_area(6, 6, 70) == 0 63 | assert utils.compute_area(3, 4, 5) == 6 64 | assert utils.compute_area(30, 40, 50) == 600 65 | -------------------------------------------------------------------------------- /triangle-project/trianglelib/utils.py: -------------------------------------------------------------------------------- 1 | """Routines to test triangle properties without explicit instantiation.""" 2 | 3 | from trianglelib.shape import Triangle 4 | 5 | def _make_triangle(a, b, c): 6 | try: 7 | return Triangle(a, b, c) 8 | except ValueError: 9 | return None 10 | 11 | def is_triangle(a, b, c): 12 | """Return whether lengths `a`, `b`, `c` can be the sides of a triangle.""" 13 | t = _make_triangle(a, b, c) 14 | return (t is not None) 15 | 16 | def is_equilateral(a, b, c): 17 | """Return whether lengths `a`, `b`, and `c` are an equilateral triangle.""" 18 | t = _make_triangle(a, b, c) 19 | return (t is not None) and t.is_equilateral() 20 | 21 | def is_isosceles(a, b, c): 22 | """Return whether lengths `a`, `b`, and `c` are an isosceles triangle.""" 23 | t = _make_triangle(a, b, c) 24 | return (t is not None) and t.is_isosceles() 25 | 26 | def compute_perimeter(a, b, c): 27 | """Return the perimeer of the triangle with side lengths `a`, `b`, and `c`. 28 | 29 | If the three lengths provided cannot be the sides of a triangle, 30 | then the perimeter 0 is returned. 31 | 32 | """ 33 | t = _make_triangle(a, b, c) 34 | return 0 if (t is None) else t.perimeter() 35 | 36 | def compute_area(a, b, c): 37 | """Return the area of the triangle with side lengths `a`, `b`, and `c`. 38 | 39 | If the three lengths provided cannot be the sides of a triangle, 40 | then the area 0 is returned. 41 | 42 | """ 43 | t = _make_triangle(a, b, c) 44 | return 0 if (t is None) else t.area() 45 | --------------------------------------------------------------------------------