From 24a91e41156e68a2f77b089afa7f0dc73e75fce8 Mon Sep 17 00:00:00 2001 From: Richard Zou Date: Wed, 27 Oct 2021 10:36:38 -0400 Subject: [PATCH] [functorch] Docs build (pytorch/functorch#227) cd into docs/ and run `make html` and view the html in build/html --- functorch/.gitignore | 4 + functorch/docs/.gitignore | 4 + functorch/docs/Makefile | 39 ++ functorch/docs/requirements.txt | 6 + .../docs/source/_static/css/copybutton.css | 81 ++++ functorch/docs/source/_static/css/jit.css | 4 + .../docs/source/_static/css/pytorch_theme.css | 118 ++++++ .../source/_templates/autosummary/class.rst | 12 + .../docs/source/_templates/classtemplate.rst | 14 + functorch/docs/source/_templates/layout.html | 30 ++ functorch/docs/source/conf.py | 348 ++++++++++++++++++ functorch/docs/source/functorch.rst | 13 + functorch/docs/source/index.rst | 37 ++ functorch/docs/source/install.rst | 4 + 14 files changed, 714 insertions(+) create mode 100644 functorch/docs/.gitignore create mode 100644 functorch/docs/Makefile create mode 100644 functorch/docs/requirements.txt create mode 100644 functorch/docs/source/_static/css/copybutton.css create mode 100644 functorch/docs/source/_static/css/jit.css create mode 100644 functorch/docs/source/_static/css/pytorch_theme.css create mode 100644 functorch/docs/source/_templates/autosummary/class.rst create mode 100644 functorch/docs/source/_templates/classtemplate.rst create mode 100644 functorch/docs/source/_templates/layout.html create mode 100644 functorch/docs/source/conf.py create mode 100644 functorch/docs/source/functorch.rst create mode 100644 functorch/docs/source/index.rst create mode 100644 functorch/docs/source/install.rst diff --git a/functorch/.gitignore b/functorch/.gitignore index 3a270fd761ef..c8d3aa177317 100644 --- a/functorch/.gitignore +++ b/functorch/.gitignore @@ -9,3 +9,7 @@ t.py .vscode/ ccache.sh *.ipynb +docs/build +docs/src +docs/source/generated +.DS_Store diff --git a/functorch/docs/.gitignore b/functorch/docs/.gitignore new file mode 100644 index 000000000000..7fc077fafdb1 --- /dev/null +++ b/functorch/docs/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +package-lock.json +package.json +yarn.lock diff --git a/functorch/docs/Makefile b/functorch/docs/Makefile new file mode 100644 index 000000000000..d9c471093ac9 --- /dev/null +++ b/functorch/docs/Makefile @@ -0,0 +1,39 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS ?= -j auto -WT --keep-going +SPHINXBUILD ?= sphinx-build +SPHINXPROJ ?= functorch +SOURCEDIR ?= source +BUILDDIR ?= build +PYCMD ?= python + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +docset: html + doc2dash --name $(SPHINXPROJ) --icon $(SOURCEDIR)/_static/img/pytorch-logo-flame.png --enable-js --online-redirect-url https://pytorch.org/docs/ --force $(BUILDDIR)/html/ + + # Manually fix because Zeal doesn't deal well with `icon.png`-only at 2x resolution. + cp $(SPHINXPROJ).docset/icon.png $(SPHINXPROJ).docset/icon@2x.png + convert $(SPHINXPROJ).docset/icon@2x.png -resize 16x16 $(SPHINXPROJ).docset/icon.png + +html-stable: + # stable differs from `make html` in two ways: + # 1) The stable logo is used instead of the unstable logo + # 2) There will not be a link to the stable docs. + # See conf.py for more details. + RELEASE=1 make html + +.PHONY: help Makefile docset + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +clean: + @echo "Removing everything under 'build' and 'source/generated'.." + @rm -rf $(BUILDDIR)/html/ $(BUILDDIR)/doctrees $(SOURCEDIR)/generated diff --git a/functorch/docs/requirements.txt b/functorch/docs/requirements.txt new file mode 100644 index 000000000000..18c66addd496 --- /dev/null +++ b/functorch/docs/requirements.txt @@ -0,0 +1,6 @@ +sphinx==3.5.4 +docutils==0.16 +-e git+https://github.com/pytorch/pytorch_sphinx_theme.git#egg=pytorch_sphinx_theme +-e git://github.com/readthedocs/sphinx_rtd_theme.git#egg=sphinx_rtd_theme +sphinxcontrib.katex +sphinx_copybutton diff --git a/functorch/docs/source/_static/css/copybutton.css b/functorch/docs/source/_static/css/copybutton.css new file mode 100644 index 000000000000..bc084b0194a2 --- /dev/null +++ b/functorch/docs/source/_static/css/copybutton.css @@ -0,0 +1,81 @@ +/* Copy buttons */ +button.copybtn { + position: absolute; + display: flex; + top: .3em; + right: .5em; + width: 1.7em; + height: 1.7em; + opacity: 1; + transition: opacity 0.3s, border .3s, background-color .3s; + user-select: none; + padding: 0; + border: none; + outline: none; + border-radius: 0.4em; + border: #e1e1e1 1px solid; + background-color: rgb(245, 245, 245); +} + +button.copybtn.success { + border-color: #22863a; +} + +button.copybtn img { + width: 100%; + padding: .2em; +} + +div.highlight { + position: relative; +} + +.highlight button.copybtn { + opacity: 1; +} + +.highlight button.copybtn:hover { + background-color: rgb(235, 235, 235); +} + +.highlight button.copybtn:active { + background-color: rgb(187, 187, 187); +} + +/** + * A minimal CSS-only tooltip copied from: + * https://codepen.io/mildrenben/pen/rVBrpK + * + * To use, write HTML like the following: + * + *

Short

+ */ + .o-tooltip--left { + position: relative; + } + + .o-tooltip--left:after { + opacity: 1; + visibility: visible; + position: absolute; + content: attr(data-tooltip); + padding: .2em; + font-size: .8em; + left: -.2em; + background: grey; + color: white; + white-space: nowrap; + z-index: 2; + border-radius: 2px; + transform: translateX(-102%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); +} + +.o-tooltip--left:hover:after { + display: block; + opacity: 1; + visibility: visible; + transform: translateX(-100%) translateY(0); + transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1); + transition-delay: .5s; +} diff --git a/functorch/docs/source/_static/css/jit.css b/functorch/docs/source/_static/css/jit.css new file mode 100644 index 000000000000..0ac75807e484 --- /dev/null +++ b/functorch/docs/source/_static/css/jit.css @@ -0,0 +1,4 @@ +.codeblock-height-limiter { + max-height: 500px; + overflow: scroll; +} diff --git a/functorch/docs/source/_static/css/pytorch_theme.css b/functorch/docs/source/_static/css/pytorch_theme.css new file mode 100644 index 000000000000..0e54497643ce --- /dev/null +++ b/functorch/docs/source/_static/css/pytorch_theme.css @@ -0,0 +1,118 @@ +body { + font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif; +} + +/* Default header fonts are ugly */ +h1, h2, .rst-content .toctree-wrapper p.caption, h3, h4, h5, h6, legend, p.caption { + font-family: "Lato","proxima-nova","Helvetica Neue",Arial,sans-serif; +} + +/* Use white for docs background */ +.wy-side-nav-search { + background-color: #fff; +} + +.wy-nav-content-wrap, .wy-menu li.current > a { + background-color: #fff; +} + +@media screen and (min-width: 1400px) { + .wy-nav-content-wrap { + background-color: rgba(0, 0, 0, 0.0470588); + } + + .wy-nav-content { + background-color: #fff; + } +} + +/* Fixes for mobile */ +.wy-nav-top { + background-color: #fff; + background-image: url('../img/pytorch-logo-dark.svg'); + background-repeat: no-repeat; + background-position: center; + padding: 0; + margin: 0.4045em 0.809em; + color: #333; +} + +.wy-nav-top > a { + display: none; +} + +@media screen and (max-width: 768px) { + .wy-side-nav-search>a img.logo { + height: 60px; + } +} + +/* This is needed to ensure that logo above search scales properly */ +.wy-side-nav-search a { + display: block; +} + +/* This ensures that multiple constructors will remain in separate lines. */ +.rst-content dl:not(.docutils) dt { + display: table; +} + +/* Use our red for literals (it's very similar to the original color) */ +.rst-content tt.literal, .rst-content tt.literal, .rst-content code.literal { + color: #F05732; +} + +.rst-content tt.xref, a .rst-content tt, .rst-content tt.xref, +.rst-content code.xref, a .rst-content tt, a .rst-content code { + color: #404040; +} + +/* Change link colors (except for the menu) */ + +a { + color: #F05732; +} + +a:hover { + color: #F05732; +} + + +a:visited { + color: #D44D2C; +} + +.wy-menu a { + color: #b3b3b3; +} + +.wy-menu a:hover { + color: #b3b3b3; +} + +/* Default footer text is quite big */ +footer { + font-size: 80%; +} + +footer .rst-footer-buttons { + font-size: 125%; /* revert footer settings - 1/80% = 125% */ +} + +footer p { + font-size: 100%; +} + +/* For hidden headers that appear in TOC tree */ +/* see http://stackoverflow.com/a/32363545/3343043 */ +.rst-content .hidden-section { + display: none; +} + +nav .hidden-section { + display: inherit; +} + +.wy-side-nav-search>div.version { + color: #000; +} diff --git a/functorch/docs/source/_templates/autosummary/class.rst b/functorch/docs/source/_templates/autosummary/class.rst new file mode 100644 index 000000000000..f581ac9d42ea --- /dev/null +++ b/functorch/docs/source/_templates/autosummary/class.rst @@ -0,0 +1,12 @@ +.. role:: hidden + :class: hidden-section +.. currentmodule:: {{ module }} + + +{{ name | underline}} + +.. autoclass:: {{ name }} + :inherited-members: + :members: + +.. autogenerated from source/_templates/autosummary/class.rst diff --git a/functorch/docs/source/_templates/classtemplate.rst b/functorch/docs/source/_templates/classtemplate.rst new file mode 100644 index 000000000000..4f74842394ec --- /dev/null +++ b/functorch/docs/source/_templates/classtemplate.rst @@ -0,0 +1,14 @@ +.. role:: hidden + :class: hidden-section +.. currentmodule:: {{ module }} + + +{{ name | underline}} + +.. autoclass:: {{ name }} + :members: + + +.. + autogenerated from source/_templates/classtemplate.rst + note it does not have :inherited-members: diff --git a/functorch/docs/source/_templates/layout.html b/functorch/docs/source/_templates/layout.html new file mode 100644 index 000000000000..0de779ef3d85 --- /dev/null +++ b/functorch/docs/source/_templates/layout.html @@ -0,0 +1,30 @@ +{% extends "!layout.html" %} + + +{% block extrahead %} +{% if release == "master" %} + + +{% endif %} +{% endblock %} + +{% block menu %} +{{ super() }} +{% endblock %} + +{% block sidebartitle %} + {% include "searchbox.html" %} +{% endblock %} + + +{% block footer %} +{{ super() }} + + + +{% endblock %} diff --git a/functorch/docs/source/conf.py b/functorch/docs/source/conf.py new file mode 100644 index 000000000000..4cf41dc0a4ff --- /dev/null +++ b/functorch/docs/source/conf.py @@ -0,0 +1,348 @@ +# -*- coding: utf-8 -*- +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +import os +# import sys + +# source code directory, relative to this file, for sphinx-autobuild +# sys.path.insert(0, os.path.abspath('../..')) + +import torch +import functorch + +RELEASE = os.environ.get('RELEASE', False) + +import pytorch_sphinx_theme +import sphinx_rtd_theme + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +# +needs_sphinx = '3.1.2' + +# 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.autosummary', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.napoleon', + 'sphinx.ext.viewcode', + 'sphinxcontrib.katex', + 'sphinx.ext.autosectionlabel', + 'sphinx_copybutton', +] + +# build the templated autosummary files +# autosummary_generate = True +numpydoc_show_class_members = False + +# autosectionlabel throws warnings if section names are duplicated. +# The following tells autosectionlabel to not throw a warning for +# duplicated section names that are in different documents. +autosectionlabel_prefix_document = True + +# katex options +# +# + +katex_prerender = True + +napoleon_use_ivar = True + +# build the templated autosummary files +autosummary_generate = True + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = 'functorch' +copyright = 'functorch Contributors' +author = 'functorch Contributors' +torch_version = str(torch.__version__) + +# 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. +# TODO: change to [:2] at v1.0 +version = 'preview (' + torch_version + ' )' +# The full version, including alpha/beta/rc tags. +# TODO: verify this works as expected +release = 'preview' + +# Customized html_title here. +# Default is " ".join(project, release, "documentation") if not set +if RELEASE: + # remove hash (start with 'a') from version number if any + version_end = torch_version.find('a') + if version_end == -1: + html_title = " ".join((project, torch_version, "documentation")) + version = torch_version + else: + html_title = " ".join((project, torch_version[:version_end], "documentation")) + version = torch_version[:version_end] + release = version + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This patterns also effect to html_static_path and html_extra_path +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + +# Disable docstring inheritance +autodoc_inherit_docstrings = False + +# Disable displaying type annotations, these can be very verbose +autodoc_typehints = 'none' + +# Enable overriding of function signatures in the first line of the docstring. +autodoc_docstring_signature = True + +# -- katex javascript in header +# +# def setup(app): +# app.add_javascript("https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.js") + + +# -- Options for HTML output ---------------------------------------------- +# +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +# +# + +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 = { + 'collapse_navigation': False, + 'display_version': True, +} + +html_context = { + 'css_files': [ + 'https://fonts.googleapis.com/css?family=Lato', + '_static/css/pytorch_theme.css' + ], +} + +# html_theme = 'pytorch_sphinx_theme' +# html_theme_path = [pytorch_sphinx_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 = { +# 'collapse_navigation': False, +# 'display_version': True, +# 'logo_only': True, +# 'analytics_id': 'UA-117752657-2', +# } + +# html_logo = '_static/img/pytorch-logo-dark-unstable.png' +# if RELEASE: +# html_logo = '_static/img/pytorch-logo-dark.svg' + + +# 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'] + +html_css_files = [ + 'css/jit.css', +] + + +# Called automatically by Sphinx, making this `conf.py` an "extension". +def setup(app): + # NOTE: in Sphinx 1.8+ `html_css_files` is an official configuration value + # and can be moved outside of this function (and the setup(app) function + # can be deleted). + html_css_files = [ + 'https://cdn.jsdelivr.net/npm/katex@0.10.0-beta/dist/katex.min.css' + ] + + # In Sphinx 1.8 it was renamed to `add_css_file`, 1.7 and prior it is + # `add_stylesheet` (deprecated in 1.8). + add_css = getattr(app, 'add_css_file', app.add_stylesheet) + for css_file in html_css_files: + add_css(css_file) + +# -- Options for HTMLHelp output ------------------------------------------ + +# Output file base name for HTML help builder. +htmlhelp_basename = 'PyTorchdoc' + + +# -- Options for LaTeX output --------------------------------------------- + +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 figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'pytorch.tex', 'PyTorch Documentation', + 'Torch Contributors', 'manual'), +] + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'PyTorch', 'PyTorch Documentation', + [author], 1) +] + + +# -- 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 = [ + (master_doc, 'PyTorch', 'PyTorch Documentation', + author, 'PyTorch', 'One line description of project.', + 'Miscellaneous'), +] + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = { + 'python': ('https://docs.python.org/3', None), + 'numpy': ('https://numpy.org/doc/stable', None), +} + +# -- A patch that prevents Sphinx from cross-referencing ivar tags ------- +# See http://stackoverflow.com/a/41184353/3343043 + +from docutils import nodes +from sphinx.util.docfields import TypedField +from sphinx import addnodes +import sphinx.ext.doctest + +# Without this, doctest adds any example with a `>>>` as a test +doctest_test_doctest_blocks = '' +doctest_default_flags = sphinx.ext.doctest.doctest.ELLIPSIS +doctest_global_setup = ''' +import torch +try: + import torchvision +except ImportError: + torchvision = None +''' + + +def patched_make_field(self, types, domain, items, **kw): + # `kw` catches `env=None` needed for newer sphinx while maintaining + # backwards compatibility when passed along further down! + + # type: (List, unicode, Tuple) -> nodes.field + def handle_item(fieldarg, content): + par = nodes.paragraph() + par += addnodes.literal_strong('', fieldarg) # Patch: this line added + # par.extend(self.make_xrefs(self.rolename, domain, fieldarg, + # addnodes.literal_strong)) + if fieldarg in types: + par += nodes.Text(' (') + # NOTE: using .pop() here to prevent a single type node to be + # inserted twice into the doctree, which leads to + # inconsistencies later when references are resolved + fieldtype = types.pop(fieldarg) + if len(fieldtype) == 1 and isinstance(fieldtype[0], nodes.Text): + typename = u''.join(n.astext() for n in fieldtype) + typename = typename.replace('int', 'python:int') + typename = typename.replace('long', 'python:long') + typename = typename.replace('float', 'python:float') + typename = typename.replace('bool', 'python:bool') + typename = typename.replace('type', 'python:type') + par.extend(self.make_xrefs(self.typerolename, domain, typename, + addnodes.literal_emphasis, **kw)) + else: + par += fieldtype + par += nodes.Text(')') + par += nodes.Text(' -- ') + par += content + return par + + fieldname = nodes.field_name('', self.label) + if len(items) == 1 and self.can_collapse: + fieldarg, content = items[0] + bodynode = handle_item(fieldarg, content) + else: + bodynode = self.list_type() + for fieldarg, content in items: + bodynode += nodes.list_item('', handle_item(fieldarg, content)) + fieldbody = nodes.field_body('', bodynode) + return nodes.field('', fieldname, fieldbody) + +TypedField.make_field = patched_make_field + +copybutton_prompt_text = r'>>> |\.\.\. ' +copybutton_prompt_is_regexp = True diff --git a/functorch/docs/source/functorch.rst b/functorch/docs/source/functorch.rst new file mode 100644 index 000000000000..6dc1fed01fa6 --- /dev/null +++ b/functorch/docs/source/functorch.rst @@ -0,0 +1,13 @@ +functorch API Reference +======================= + +.. currentmodule:: functorch + +.. autosummary:: + :toctree: generated + :nosignatures: + + grad + grad_and_value + jacrev + vmap diff --git a/functorch/docs/source/index.rst b/functorch/docs/source/index.rst new file mode 100644 index 000000000000..ef4c8ca4e1ba --- /dev/null +++ b/functorch/docs/source/index.rst @@ -0,0 +1,37 @@ +:github_url: https://github.com/pytorch/functorch + +functorch +=================================== + +functorch is `JAX-like `_ composable function transforms for PyTorch. + +It aims to provide composable vmap and grad transforms that work with PyTorch modules +and PyTorch autograd with good eager-mode performance. + +**This library is currently under heavy development - if you have suggestions on the API or use-cases you'd like to be covered, please open an github issue or reach out. We'd love to hear about how you're using the library.** + +Why composable function transforms? +----------------------------------- + +There are a number of use cases that are tricky to do in PyTorch today: + +- computing per-sample-gradients (or other per-sample quantities) +- running ensembles of models on a single machine +- efficiently batching together tasks in the inner-loop of MAML +- efficiently computing Jacobians and Hessians +- efficiently computing batched Jacobians and Hessians + +Composing `vmap`, `grad`, and `vjp` transforms allows us to express the above without designing a separate subsystem for each. +This idea of composable function transforms comes from the `JAX framework `_. + +Read More +--------- + +For a whirlwind tour of how to use the transforms, please check out `this section in our README `_. For installation instructions or the API reference, please check below. + + +.. toctree:: + :maxdepth: 1 + + Install + functorch API Reference diff --git a/functorch/docs/source/install.rst b/functorch/docs/source/install.rst new file mode 100644 index 000000000000..be01f342c572 --- /dev/null +++ b/functorch/docs/source/install.rst @@ -0,0 +1,4 @@ +Install +========= + +Check out `the instructions at our GitHub `_.