提交 27cf8541 编写于 作者: HansBug's avatar HansBug 😆

doc(hansbug): Add autodoc into the api doc part

上级 97511ca7
......@@ -1207,4 +1207,5 @@ fabric.properties
/docs/source/**/*.sh.txt
/docs/source/**/*.sh.err
/docs/source/**/*.sh.exitcode
/docs/source/**/*.dat.*
\ No newline at end of file
/docs/source/**/*.dat.*
/docs/source/**/*.auto.rst
\ No newline at end of file
......@@ -13,6 +13,8 @@ GRAPHVIZ_MK := ${SOURCEDIR}/graphviz.mk
GRAPHVIZ := $(MAKE) -f "${GRAPHVIZ_MK}" SOURCE=${SOURCEDIR}
DEMOS_MK := ${SOURCEDIR}/demos.mk
DEMOS := $(MAKE) -f "${DEMOS_MK}" SOURCE=${SOURCEDIR}
APIDOC_MK := ${SOURCEDIR}/apidoc.mk
APIDOC := $(MAKE) -f "${APIDOC_MK}" SOURCE=${SOURCEDIR}
_CURRENT_PATH := ${PATH}
_PROJ_DIR := $(shell readlink -f ${CURDIR}/..)
......@@ -34,6 +36,7 @@ help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
contents:
@$(APIDOC) build
@$(DIAGRAMS) build
@$(GRAPHVIZ) build
@$(DEMOS) build
......@@ -50,6 +53,7 @@ clean:
@$(DIAGRAMS) clean
@$(GRAPHVIZ) clean
@$(DEMOS) clean
@$(APIDOC) clean
@$(SPHINXBUILD) -M clean "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
sourcedir:
......
treetensor.common
=====================
.. toctree::
:maxdepth: 3
trees.auto
wrappers.auto
treetensor.common.trees
\ No newline at end of file
treetensor.common.wrappers
\ No newline at end of file
treetensor.tensor.funcs
\ No newline at end of file
treetensor.tensor
=====================
.. toctree::
:maxdepth: 3
funcs.auto
size.auto
tensor.auto
treetensor.tensor.size
\ No newline at end of file
treetensor.tensor.tensor
\ No newline at end of file
PYTHON := $(shell which python)
SOURCE ?= .
RSTC_FILES := $(shell find ${SOURCE} -name *.rstc)
RST_RESULTS := $(addsuffix .auto.rst, $(basename ${RSTC_FILES}))
APIDOC_GEN_PY := $(shell readlink -f ${SOURCE}/apidoc_gen.py)
%.auto.rst: %.rstc ${APIDOC_GEN_PY}
cd "$(shell dirname $(shell readlink -f $<))" && \
PYTHONPATH="$(shell dirname $(shell readlink -f $<)):${PYTHONPATH}" \
cat "$(shell readlink -f $<)" | $(PYTHON) "${APIDOC_GEN_PY}" > "$(shell readlink -f $@)"
build: ${RST_RESULTS}
all: build
clean:
rm -rf \
$(shell find ${SOURCE} -name *.auto.rst)
import importlib
import types
from typing import List
_DOC_TAG = '__doc_names__'
def _is_tagged_name(clazz, name):
return name in set(getattr(clazz, _DOC_TAG, set()))
def _find_class_members(clazz: type) -> List[str]:
members = []
for name in dir(clazz):
item = getattr(clazz, name)
if _is_tagged_name(clazz, name) and \
getattr(item, '__name__', None) == name: # should be public or protected
members.append(name)
return members
if __name__ == '__main__':
package_name = input().strip()
_module = importlib.import_module(package_name)
_alls = getattr(_module, '__all__')
print(package_name)
print('=' * (len(package_name) + 5))
print()
print(f'.. automodule:: {package_name}')
print()
for _name in sorted(_alls):
print(_name)
print('-' * (len(_name) + 5))
print()
_item = getattr(_module, _name)
if isinstance(_item, types.FunctionType):
print(f'.. autofunction:: {package_name}.{_name}')
print()
elif isinstance(_item, type):
print(f'.. autoclass:: {package_name}.{_name}')
print(f' :members: {", ".join(sorted(_find_class_members(_item)))}')
print()
else:
print(f'.. autodata:: {package_name}.{_name}')
print(f' :annotation:')
print()
......@@ -58,6 +58,12 @@ if not os.environ.get("NO_CONTENTS_BUILD"):
if pip_docs.wait() != 0:
raise ChildProcessError("Pip docs install failed with %d." % (pip.returncode,))
apidoc_cmd = (where.first('make'), '-f', "apidoc.mk", "build")
print("Building apidoc {cmd} at {cp}...".format(cmd=repr(apidoc_cmd), cp=repr(_DOC_PATH)))
apidoc = Popen(apidoc_cmd, stdout=sys.stdout, stderr=sys.stderr, env=_env, cwd=_DOC_PATH)
if apidoc.wait() != 0:
raise ChildProcessError("Diagrams failed with %d." % (apidoc.returncode,))
diagrams_cmd = (where.first('make'), '-f', "diagrams.mk", "build")
print("Building diagrams {cmd} at {cp}...".format(cmd=repr(diagrams_cmd), cp=repr(_DOC_PATH)))
diagrams = Popen(diagrams_cmd, stdout=sys.stdout, stderr=sys.stderr, env=_env, cwd=_DOC_PATH)
......
......@@ -19,7 +19,9 @@ module.
:maxdepth: 2
:caption: API Documentation
api_doc/common/index
api_doc/config/index
api_doc/tensor/index
.. toctree::
......
......@@ -2,6 +2,8 @@ from abc import ABCMeta
from treevalue import general_tree_value, method_treelize
from ..utils import tag_names
__all__ = [
'BaseTreeStruct', "TreeData", 'TreeObject',
]
......@@ -15,6 +17,7 @@ class BaseTreeStruct(general_tree_value(), metaclass=ABCMeta):
pass
@tag_names(['__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__'])
class TreeData(BaseTreeStruct, metaclass=ABCMeta):
"""
Overview:
......
......@@ -2,12 +2,15 @@ import numpy as np
from treevalue import method_treelize
from ..common import TreeObject, TreeData, ireduce
from ..utils import inherit_names, current_names
__all__ = [
'TreeNumpy'
]
@current_names()
@inherit_names(TreeData)
class TreeNumpy(TreeData):
"""
Overview:
......
......@@ -6,6 +6,7 @@ from treevalue.utils import pre_process
from .size import TreeSize
from ..common import TreeObject, TreeData, ireduce
from ..numpy import TreeNumpy
from ..utils import inherit_names, current_names
__all__ = [
'TreeTensor'
......@@ -16,6 +17,8 @@ tireduce = pre_process(lambda rfunc: ((_reduce_tensor_wrap(rfunc),), {}))(ireduc
# noinspection PyTypeChecker,PyShadowingBuiltins,PyArgumentList
@current_names()
@inherit_names(TreeData)
class TreeTensor(TreeData):
@method_treelize(return_type=TreeNumpy)
def numpy(self: torch.Tensor) -> np.ndarray:
......
from .func import replaceable_partial
from .clazz import *
from .func import *
import types
from functools import reduce
from operator import __or__
from typing import Iterable, TypeVar
__all__ = [
'tag_names', 'inherit_names', 'current_names',
]
_DOC_TAG = '__doc_names__'
_CLS_TYPE = TypeVar('_CLS_TYPE', bound=type)
def _get_names(clazz: type):
return set(getattr(clazz, _DOC_TAG, set()))
def _set_names(clazz: type, names: Iterable[str]):
setattr(clazz, _DOC_TAG, set(names))
def tag_names(names: Iterable[str], keep: bool = True):
def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE:
_old_names = _get_names(cls) if keep else set()
_set_names(cls, set(names) | _old_names)
return cls
return _decorator
def inherit_names(*clazzes: type, keep: bool = True):
def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE:
_old_names = _get_names(cls) if keep else set()
_set_names(cls, reduce(__or__, [_old_names, *map(_get_names, clazzes)]))
return cls
return _decorator
class _TempClazz:
@property
def prop(self):
return None
PropertyType = type(_TempClazz.prop)
# noinspection PyTypeChecker
def _is_func_property(clazz, name):
func = getattr(clazz, name)
return isinstance(func, (types.FunctionType, PropertyType)) and (
not hasattr(clazz.__base__, name) or getattr(clazz.__base__, name) is not func
)
def _is_classmethod(clazz, name):
method = getattr(clazz, name)
return isinstance(method, types.MethodType) and (
not hasattr(clazz.__base__, name) or getattr(clazz.__base__, name).__func__ is not method.__func__
)
def current_names(keep: bool = True):
def _decorator(cls: _CLS_TYPE) -> _CLS_TYPE:
members = set()
for name in dir(cls):
item = getattr(cls, name)
if (_is_func_property(cls, name) or _is_classmethod(cls, name)) and \
getattr(item, '__name__', None) == name: # should be public or protected
members.add(name)
_old_names = _get_names(cls) if keep else set()
_set_names(cls, _old_names | set(members))
return cls
return _decorator
__all__ = [
'replaceable_partial',
]
def replaceable_partial(func, **kws):
def _new_func(*args, **kwargs):
return func(*args, **{**kws, **kwargs})
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册