From 458518d0bc84f207c1b77f0e9b4e0a495e281dbf Mon Sep 17 00:00:00 2001 From: James Booth Date: Wed, 23 Nov 2016 14:01:04 +0000 Subject: [PATCH] initial attempt at menpo3d doc inclusion --- docs/.gitignore | 1 + docs/Makefile | 65 +++++++ docs/generate_rst.py | 87 ++++++++++ docs/rtd_environment.yml | 12 ++ docs/source/_static/rtd_hack.css | 31 ++++ docs/source/conf.py | 286 +++++++++++++++++++++++++++++++ docs/sphinxext/__init__.py | 1 + docs/sphinxext/ref_prettify.py | 22 +++ docs/sphinxext/theme_hack.py | 4 + docs/xref_map.py | 3 + readthedocs.yml | 9 + 11 files changed, 521 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100755 docs/generate_rst.py create mode 100644 docs/rtd_environment.yml create mode 100644 docs/source/_static/rtd_hack.css create mode 100644 docs/source/conf.py create mode 100644 docs/sphinxext/__init__.py create mode 100644 docs/sphinxext/ref_prettify.py create mode 100644 docs/sphinxext/theme_hack.py create mode 100644 docs/xref_map.py create mode 100644 readthedocs.yml diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000..88f9974 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +_build/* diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..096f1b9 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,65 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +N_CORES = $(shell getconf _NPROCESSORS_ONLN) +SPHINXOPTS = -j $(N_CORES) +SPHINXBUILD = sphinx-build +PAPER = +SRC_DIR = source +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRC_DIR) + +.PHONY: help clean html changes linkcheck + +default: html + +help: + @echo "Please use \`make ' where is one of" + @echo " html standalone HTML files" + @echo " changes an overview over all changed/added/deprecated items" + @echo " linkcheck check all external links for integrity (takes a long time)" + @echo + @echo "Compound utility targets:" + @echo "pdf latex and then runs the PDF generation" + @echo "all html and pdf" + @echo "dist all, and then puts the results in dist/" + +clean: + -rm -rf $(BUILDDIR)/* + +pdf: latex + cd $(BUILDDIR)/latex && make all-pdf + +all: html pdf + +html: + mkdir -p $(BUILDDIR)/html $(BUILDDIR)/doctrees + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +latex: + mkdir -p $(BUILDDIR)/latex $(BUILDDIR)/doctrees + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + mkdir -p $(BUILDDIR)/changes $(BUILDDIR)/doctrees + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + mkdir -p $(BUILDDIR)/linkcheck $(BUILDDIR)/doctrees + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.rst." diff --git a/docs/generate_rst.py b/docs/generate_rst.py new file mode 100755 index 0000000..91eae1a --- /dev/null +++ b/docs/generate_rst.py @@ -0,0 +1,87 @@ +from inspect import isclass, isfunction, ismodule +from functools import partial + +is_func_or_partial = lambda f: isfunction(f) or isinstance(f, partial) + + +def write_docs_for_module(module, path, modules_to_skip=None, + generate_index=False): + if modules_to_skip is None: + modules_to_skip = {} + module_name = module.__name__ + doc_dir = path / module_name + if not doc_dir.is_dir(): + doc_dir.mkdir() + for k, v in module.__dict__.items(): + if ismodule(v): + print('Writing module {}'.format(module_name)) + file_to_doc = docs_for_module(k, v, module_name, + generate_index=generate_index) + if len(file_to_doc) == 0 or k in modules_to_skip: + continue + mod_dir = doc_dir / k + if not mod_dir.is_dir(): + mod_dir.mkdir() + for f_name in file_to_doc: + doc_file = mod_dir / (f_name + '.rst') + with open(str(doc_file), 'wb') as f: + f.write(file_to_doc[f_name]) + + +def docs_for_module(module_name, module, package_name, generate_index=False): + file_to_doc = {} + for k, v in module.__dict__.items(): + if isclass(v): + file_to_doc[k] = generate_class_rst(module_name, k, + module.__name__, package_name) + elif is_func_or_partial(v): + file_to_doc[k] = generate_function_rst(module_name, k, + module.__name__, + package_name) + # only make an index if there is something to index + if generate_index and len(file_to_doc) > 0: + file_to_doc['index'] = generate_module_index(module_name, module) + return file_to_doc + + +def generate_module_index(module_name, module): + breadcrumb = '.. _api-{}-index:\n\n'.format(module_name) + title = ":mod:`{}`".format(module.__name__) + title = "{}\n{}\n".format(title, '=' * len(title)) + toctree = "\n.. toctree::\n :maxdepth: 1\n\n " + items = [i for i, v in module.__dict__.items() if isclass(v) or + is_func_or_partial(v)] + return breadcrumb + title + toctree + "\n ".join(items) + + +def generate_class_rst(module_name, class_name, module, package_name): + breadcrumb = '.. _{}-{}-{}:\n\n'.format(package_name, module_name, + class_name) + current_module = '.. currentmodule:: {}\n\n'.format(module) + title = "{}\n{}\n".format(class_name, '=' * len(class_name)) + body = (".. autoclass:: {}\n :members:\n :inherited-members:" + "\n :show-inheritance:\n".format(class_name)) + return breadcrumb + current_module + title + body + + +def generate_function_rst(module_name, function_name, module, package_name): + breadcrumb = '.. _{}-{}-{}:\n\n'.format(package_name, module_name, + function_name) + current_module = '.. currentmodule:: {}\n\n'.format(module) + title = "{}\n{}\n".format(function_name, '=' * len(function_name)) + body = ".. autofunction:: {}\n".format(function_name) + return breadcrumb + current_module + title + body + + + +if __name__ == '__main__': + from pathlib import Path + import menpo3d + + path = Path(__file__).parent / 'source' / 'api' + print('Writing to {}'.format(path)) + + # Flip generate_index to True to make index.rst files too! + write_docs_for_module(menpo3d, path, generate_index=False, + modules_to_skip={'_version'}) + diff --git a/docs/rtd_environment.yml b/docs/rtd_environment.yml new file mode 100644 index 0000000..725a71a --- /dev/null +++ b/docs/rtd_environment.yml @@ -0,0 +1,12 @@ +name: menpofit_rtd +channels: + - menpo +dependencies: + - python + - setuptools + + - menpo >=0.7,<0.8 + - pip: + - sphinx + - sphinx_rtd_theme + - sphinxmapxrefrole>0.2 diff --git a/docs/source/_static/rtd_hack.css b/docs/source/_static/rtd_hack.css new file mode 100644 index 0000000..71f6cb8 --- /dev/null +++ b/docs/source/_static/rtd_hack.css @@ -0,0 +1,31 @@ +/* Code References (using the class or map commands) */ +a>code.xref.py.py-class.docutils.literal,a>code.xref.py.py-function.docutils.literal { + color: #2980B9; + font-weight: bold; + padding: 0; + font-size: 90%; +} +a:hover>code.xref.py.py-class.docutils.literal,a:hover>code.xref.py.py-function.docutils.literal { + color: purple; +} +/* Class names */ +code.descclassname, code.descname { + background-color: transparent; + font-size: 100% !important; + border: none; + padding: 0; + color: #000000; +} +/* Inline Code */ +code.docutils.literal { + color: #000000; + font-weight: bold; +} +/* Inline Code Links e.g. for module links*/ +a>code.docutils.literal { + color: gray; + font-weight: bold; + border: none; + background: transparent; + font-size: 80%; +} diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..4795dfc --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,286 @@ +import sys +import os + + +# on_rtd is whether we are on readthedocs.org, +# this line of code grabbed from docs.readthedocs.org +on_rtd = os.environ.get('READTHEDOCS', None) == 'True' + +# Add the folder above so we can grab the sphinx extensions +sys.path.insert(0, os.path.abspath('..')) + +if not on_rtd: + # Add the menpo3d root so we can grab the version + sys.path.insert(0, os.path.abspath('../../')) + +import menpo3d + +# add an up to date mathjax path +mathjax_path = 'https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML' + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +needs_sphinx = '1.3' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.mathjax', + 'sphinx.ext.viewcode', + 'sphinx.ext.autosummary', + 'sphinx.ext.napoleon', + 'sphinxext.ref_prettify', + 'sphinxext.theme_hack', + 'sphinxmapxrefrole'] + +# Import the mapping dictionary and set it for sphinxmapxrefrole +from xref_map import xref_map +xref_mapping_dict = xref_map + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] +html_static_path = ['_static'] + +# Otherwise Sphinx emits thousands of warnings +napoleon_include_special_with_doc = False +napoleon_numpy_docstring = True +napoleon_use_rtype = False +napoleon_use_ivar = False +napoleon_use_param = True +napoleon_use_admonition_for_examples = True +napoleon_use_admonition_for_notes = True +napoleon_use_admonition_for_references = True + +# The suffix of source filenames. +#source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# Sort attributes by type (functions separate from properties) +autodoc_member_order = 'groupwise' + +# General information about the project. +project = u'Menpo3D' +authors = (u'Joan Alabort-i-Medina, Epameinondas Antonakos, James Booth,' + u' Patrick Snape, and Stefanos Zafeiriou') +copyright = u'2016, ' + authors + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = menpo3d.__version__ +# The full version, including alpha/beta/rc tags. +release = menpo3d.__version__ + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build', '**/test/**'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +#pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +if not on_rtd: # only import and set the theme if we're building docs locally + import sphinx_rtd_theme + + html_theme = 'sphinx_rtd_theme' + html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +#html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'Menpo3Ddoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_preamble = """ +\usepackage{enumitem} +\setlistdepth{999} +""" +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + 'preamble': latex_preamble +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'Menpo3D.tex', u'Menpo3D Documentation', + authors, 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'menpo3d', u'Menpo3D Documentation', + [authors], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'Menpo3D', u'Menpo3D Documentation', + authors, + 'Menpo3D', 'Python framework for fitting and training deformable models.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False diff --git a/docs/sphinxext/__init__.py b/docs/sphinxext/__init__.py new file mode 100644 index 0000000..07206d8 --- /dev/null +++ b/docs/sphinxext/__init__.py @@ -0,0 +1 @@ +from . import ref_prettify diff --git a/docs/sphinxext/ref_prettify.py b/docs/sphinxext/ref_prettify.py new file mode 100644 index 0000000..c56048d --- /dev/null +++ b/docs/sphinxext/ref_prettify.py @@ -0,0 +1,22 @@ +from sphinx.domains.python import PyXRefRole + + +def setup(app): + """ + Any time a python class is referenced, make it a pretty link that doesn't + include the full package path. This makes the base classes much prettier. + """ + app.add_role_to_domain('py', 'class', truncate_class_role) + return {'parallel_read_safe': True} + + +def truncate_class_role(name, rawtext, text, lineno, inliner, + options={}, content=[]): + if '<' not in rawtext: + text = '{} <{}>'.format(text.split('.')[-1], text) + rawtext = ':{}:`{}`'.format(name, text) + + # Return a python x-reference + py_xref = PyXRefRole() + return py_xref('py:class', rawtext, text, lineno, + inliner, options=options, content=content) diff --git a/docs/sphinxext/theme_hack.py b/docs/sphinxext/theme_hack.py new file mode 100644 index 0000000..dc1c804 --- /dev/null +++ b/docs/sphinxext/theme_hack.py @@ -0,0 +1,4 @@ +def setup(app): + app.add_stylesheet('rtd_hack.css') + + return {'parallel_read_safe': True, 'parallel_write_safe': True} diff --git a/docs/xref_map.py b/docs/xref_map.py new file mode 100644 index 0000000..8abbebf --- /dev/null +++ b/docs/xref_map.py @@ -0,0 +1,3 @@ +xref_map = { +'non_rigid_icp': ('function', 'menpo3d.correspond.nicp.non_rigid_icp') +} diff --git a/readthedocs.yml b/readthedocs.yml new file mode 100644 index 0000000..a5149d8 --- /dev/null +++ b/readthedocs.yml @@ -0,0 +1,9 @@ +formats: + - pdf + +conda: + file: docs/rtd_environment.yml + +python: + setup_py_install: true +