Skip to content

Commit

Permalink
[DOCS] Sphinx -- Introduce alias detection. (apache#4954)
Browse files Browse the repository at this point in the history
* [DOCS] Sphinx -- Introduce alias detection.

Background: some of our namespaces import function from another
namespace. For example tvm.te imports most of the operators from tvm.tir.

Previously we manually exclude these aliases from the doc.
However that means we can not link them by the alias name.

This PR adds a sphinx callback plugin to detect such aliases, and create a rubric block
on the button of its current docstring `Alias of the original class`.
It is done in a way so that we can refer to the generated docs.

We also fixed a few docs errors.

* Fix most of the issues
  • Loading branch information
tqchen authored and zhiics committed Apr 17, 2020
1 parent 0a9291d commit 68eb95b
Show file tree
Hide file tree
Showing 13 changed files with 99 additions and 164 deletions.
1 change: 0 additions & 1 deletion docs/api/python/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ Python API
.. toctree::
:maxdepth: 2

tvm
runtime
ndarray
error
Expand Down
39 changes: 4 additions & 35 deletions docs/api/python/relay/op.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,38 +18,7 @@
tvm.relay.op
------------
.. automodule:: tvm.relay.op
:members:

.. autofunction:: tvm.relay.op.Op

.. autofunction:: tvm.relay.op.OpPattern

.. autofunction:: tvm.relay.op.get

.. autofunction:: tvm.relay.op.register

.. autofunction:: tvm.relay.op.register_schedule

.. autofunction:: tvm.relay.op.register_pattern

.. autofunction:: tvm.relay.op.register_compute

.. autofunction:: tvm.relay.op.register_gradient

.. autofunction:: tvm.relay.op.register_alter_op_layout

.. autofunction:: tvm.relay.op.schedule_injective

.. autofunction:: tvm.relay.op.debug

.. automodule:: tvm.relay.op.reduce
:members:

.. automodule:: tvm.relay.op.tensor
:members:

.. automodule:: tvm.relay.op.transform
:members:

.. automodule:: tvm.relay.op.nn
:members:
:members:
:imported-members:
:exclude-members: Tuple
:autosummary:
6 changes: 0 additions & 6 deletions docs/api/python/te.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,4 @@ tvm.te
.. automodule:: tvm.te
:members:
:imported-members:
:exclude-members:
any, all, min_value, max_value, trace,
exp, erf, tanh, sigmoid, log, cos, sin, atan, sqrt, rsqrt, floor, ceil,
trunc, abs, round, nearbyint, isnan, power, popcount, fmod, if_then_else,
div, indexdiv, indexmod, truncdiv, truncmod, floordiv, floormod,
comm_reducer, min, max, sum
:autosummary:
76 changes: 0 additions & 76 deletions docs/api/python/tvm.rst

This file was deleted.

104 changes: 79 additions & 25 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import inspect
import os, subprocess
import shlex
import recommonmark
Expand Down Expand Up @@ -183,19 +184,6 @@
author, 'manual'),
]

# hook for doxygen
def run_doxygen(folder):
"""Run the doxygen make command in the designated folder."""
try:
#retcode = subprocess.call("cd %s; make doc" % folder, shell=True)
retcode = subprocess.call("rm -rf _build/html/doxygen", shell=True)
retcode = subprocess.call("mkdir -p _build/html", shell=True)
retcode = subprocess.call("cp -rf doxygen/html _build/html/doxygen", shell=True)
if retcode < 0:
sys.stderr.write("doxygen terminated by signal %s" % (-retcode))
except OSError as e:
sys.stderr.write("doxygen execution failed: %s" % e)

intersphinx_mapping = {
'python': ('https://docs.python.org/{.major}'.format(sys.version_info), None),
'numpy': ('https://docs.scipy.org/doc/numpy/', None),
Expand Down Expand Up @@ -224,18 +212,6 @@ def generate_doxygen_xml(app):
"""Run the doxygen make commands if we're on the ReadTheDocs server"""
run_doxygen('..')

def setup(app):
# Add hook for building doxygen xml when needed
# no c++ API for now
app.connect("builder-inited", generate_doxygen_xml)
app.add_stylesheet('css/tvm_theme.css')
app.add_config_value('recommonmark_config', {
'url_resolver': lambda url: github_doc_root + url,
'auto_doc_ref': True
}, True)
app.add_transform(AutoStructify)


sphinx_gallery_conf = {
'backreferences_dir': 'gen_modules/backreferences',
'doc_module': ('tvm', 'numpy'),
Expand All @@ -255,3 +231,81 @@ def setup(app):
autodoc_default_options = {
'member-order': 'bysource',
}

# hook for doxygen
def run_doxygen(folder):
"""Run the doxygen make command in the designated folder."""
try:
#retcode = subprocess.call("cd %s; make doc" % folder, shell=True)
retcode = subprocess.call("rm -rf _build/html/doxygen", shell=True)
retcode = subprocess.call("mkdir -p _build/html", shell=True)
retcode = subprocess.call("cp -rf doxygen/html _build/html/doxygen", shell=True)
if retcode < 0:
sys.stderr.write("doxygen terminated by signal %s" % (-retcode))
except OSError as e:
sys.stderr.write("doxygen execution failed: %s" % e)

# Maps the original namespace to list of potential modules
# that we can import alias from.
tvm_alias_check_map = {
"tvm.te": ["tvm.tir"],
"tvm.tir": ["tvm.ir", "tvm.runtime"],
}

def update_alias_docstring(name, obj, lines):
"""Update the docstring of alias functions.
This function checks if the obj is an alias of another documented object
in a different module.
If it is an alias, then it will append the alias information to the docstring.
Parameters
----------
name : str
The full name of the object in the doc.
obj : object
The original object.
lines : list
The docstring lines, need to be modified inplace.
"""
arr = name.rsplit(".", 1)
if len(arr) != 2:
return
target_mod, target_name = arr

if target_mod not in tvm_alias_check_map:
return
if not hasattr(obj, "__module__"):
return
obj_mod = obj.__module__

for amod in tvm_alias_check_map[target_mod]:
if not obj_mod.startswith(amod):
continue

if hasattr(sys.modules[amod], target_name):
obj_type = ":py:func" if callable(obj) else ":py:class"
lines.append(
".. rubric:: Alias of %s:`%s.%s`" % (obj_type, amod, target_name))


def process_docstring(app, what, name, obj, options, lines):
"""Sphinx callback to process docstring"""
if callable(obj) or inspect.isclass(obj):
update_alias_docstring(name, obj, lines)


def setup(app):
# Add hook for building doxygen xml when needed
# no c++ API for now
app.connect("builder-inited", generate_doxygen_xml)
app.connect('autodoc-process-docstring', process_docstring)
app.add_stylesheet('css/tvm_theme.css')
app.add_config_value('recommonmark_config', {
'url_resolver': lambda url: github_doc_root + url,
'auto_doc_ref': True
}, True)
app.add_transform(AutoStructify)
12 changes: 6 additions & 6 deletions python/tvm/ir/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ def astext(self, show_meta_data=True, annotate=None):
Optionally annotate function to provide additional
information in the comment block.
.. note::
The meta data section is necessary to fully parse the text format.
However, it can contain dumps that are big (e.g constant weights),
so it can be helpful to skip printing the meta data section.
Returns
-------
text : str
The text format of the expression.
Notes
-----
The meta data section is necessary to fully parse the text format.
However, it can contain dumps that are big (e.g constant weights),
so it can be helpful to skip printing the meta data section.
"""
return _ffi_api.AsText(self, show_meta_data, annotate)

Expand Down
13 changes: 7 additions & 6 deletions python/tvm/relay/op/transform.py
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,6 @@ def tile(data, reps):
reps : tuple of int
The number of times repeating the tensor data.
.. note::
Each dim size of reps must be a positive integer. If reps has length d,
the result will have dimension of max(d, data.ndim); If data.ndim < d,
data is promoted to be d-dimensional by prepending new axes.
If data.ndim >= d, reps is promoted to a.ndim by pre-pending 1's to it.
Returns
-------
ret : relay.Expr
Expand All @@ -442,6 +436,13 @@ def tile(data, reps):
relay.tile(x, reps=(2,)) = [[1., 2., 1., 2.],
[3., 4., 3., 4.]]
Notes
-----
Each dim size of reps must be a positive integer. If reps has length d,
the result will have dimension of max(d, data.ndim); If data.ndim < d,
data is promoted to be d-dimensional by prepending new axes.
If data.ndim >= d, reps is promoted to a.ndim by pre-pending 1's to it.
"""

return _make.tile(data, reps)
Expand Down
2 changes: 0 additions & 2 deletions python/tvm/relay/op/vision/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
# under the License.
# pylint: disable=wildcard-import
"""Vision network related operators."""
from __future__ import absolute_import as _abs

from .multibox import *
from .nms import *
from .rcnn import *
Expand Down
1 change: 0 additions & 1 deletion python/tvm/relay/op/vision/multibox.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.
"""Multibox operations."""
from __future__ import absolute_import as _abs
from . import _make
from ...expr import TupleWrapper

Expand Down
1 change: 0 additions & 1 deletion python/tvm/relay/op/vision/nms.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
# specific language governing permissions and limitations
# under the License.
"""Non-maximum suppression operations."""
from __future__ import absolute_import as _abs
from . import _make
from ...expr import TupleWrapper

Expand Down
2 changes: 0 additions & 2 deletions python/tvm/target/generic_func.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,6 @@ def override_native_generic_func(func_name):
.. code-block:: python
import tvm
from tvm import te
# wrap function as target generic
@tvm.target.override_native_generic_func("my_func")
def my_func(a):
Expand Down Expand Up @@ -211,7 +210,6 @@ def generic_func(fdefault):
.. code-block:: python
import tvm
from tvm import te
# wrap function as target generic
@tvm.target.generic_func
def my_func(a):
Expand Down
4 changes: 2 additions & 2 deletions tutorials/language/intrin_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
# TVM intrinsic provides the user a mechanism to achieve this, and this
# is the recommended way to solve the problem.
# The following code use te.exp instead, which create an intrinsic call
# :any:`te.exp` to do the exponential.
# :py::func:`tvm.te.exp` to do the exponential.
#
n = te.var("n")
A = te.placeholder((n,), name='A')
Expand All @@ -88,7 +88,7 @@
######################################################################
# Intrinsic Lowering Rule
# -----------------------
# When :any:`te.exp` is called, TVM creates an intrinsic Call Expr.
# When :py:func:`tvm.te.exp` is called, TVM creates an intrinsic Call Expr.
# TVM uses transformation rules to transform the intrinsic
# call to device specific extern calls.
#
Expand Down
2 changes: 1 addition & 1 deletion vta/tutorials/frontend/deploy_detection.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
# under the License.
"""
Deploy Pretrained Vision Detection Model from Darknet on VTA
================================================
============================================================
**Author**: `Hua Jiang <https://github.com/huajsj>`_
This tutorial provides an end-to-end demo, on how to run Darknet YoloV3-tiny
Expand Down

0 comments on commit 68eb95b

Please sign in to comment.