Removed support for documenting languages other than Python

For the reasons why, see #248
pull/398/head
Ashley Whetter 12 months ago
parent 7b90b43f94
commit a22ae9262a

@ -28,22 +28,6 @@ In contrast to the traditional `Sphinx autodoc <https://www.sphinx-doc.org/en/ma
which requires manual authoring and uses code imports,
AutoAPI finds and generates documentation by parsing source code.
Language Support
----------------
.. warning::
Support for all languages other than Python will be removed in the next major version!
========== ====== ==========================================================
Language Status Parser
========== ====== ==========================================================
Python Stable Custom using `astroid <https://github.com/PyCQA/astroid>`_
Go Alpha `godocjson <https://github.com/readthedocs/godocjson>`_
Javascript Alpha `jsdoc <https://jsdoc.app/>`_
.NET Alpha `docfx <https://dotnet.github.io/docfx/>`_
========== ====== ==========================================================
Getting Started
---------------
@ -62,29 +46,16 @@ AutoAPI can be installed through pip:
pip install sphinx-autoapi
Next, add and configure AutoAPI in your Sphinx project's `conf.py`.
Other languages may require
`further configuration <https://sphinx-autoapi.readthedocs.io/en/latest/tutorials.html#setting-up-automatic-api-documentation-generation>`_:
.. code-block:: python
extensions.append('autoapi.extension')
autoapi_type = 'python'
autoapi_dirs = ['path/to/source/files', 'src']
Where `autoapi_type` can be one of any of the supported languages:
========== ================
Language ``autoapi_type``
========== ================
Python ``'python'``
Go ``'go'``
Javascript ``'javascript'``
.NET ``'dotnet'``
========== ================
When the documentation is built,
AutoAPI will now generate API documentation into an `autoapi/` directory and add an entry to the documentation in your top level table of contents!
AutoAPI will now generate API documentation into an `autoapi/` directory
and add an entry to the documentation in your top level table of contents!
To configure AutoAPI behaviour further,
see the `Configuration documentation <https://sphinx-autoapi.readthedocs.io/en/latest/reference/config.html>`_.

@ -1,40 +0,0 @@
from typing import Dict, Sequence, Tuple
from .mappers import (
DotNetSphinxMapper,
PythonSphinxMapper,
GoSphinxMapper,
JavaScriptSphinxMapper,
)
DEFAULT_FILE_PATTERNS = {
"python": ["*.py", "*.pyi"],
"dotnet": ["project.json", "*.csproj", "*.vbproj"],
"go": ["*.go"],
"javascript": ["*.js"],
}
DEFAULT_IGNORE_PATTERNS = {
"dotnet": ["*toc.yml", "*index.yml"],
"python": ["*migrations*"],
"go": ["_test.go"],
}
LANGUAGE_MAPPERS = {
"python": PythonSphinxMapper,
"dotnet": DotNetSphinxMapper,
"go": GoSphinxMapper,
"javascript": JavaScriptSphinxMapper,
}
#: describes backend requirements in form
#: {'backend name': (('1st package name in pypi', '1st package import name'), ...)}
LANGUAGE_REQUIREMENTS: Dict[str, Sequence[Tuple[str, str]]] = {
"python": (),
"javascript": (),
"go": (("sphinxcontrib-golangdomain", "sphinxcontrib.golangdomain"),),
"dotnet": (("sphinxcontrib-dotnetdomain", "sphinxcontrib.dotnetdomain"),),
}

@ -5,7 +5,6 @@ This extension allows you to automagically generate API documentation from your
import io
import os
import shutil
import sys
from typing import Dict, Tuple
import warnings
@ -17,18 +16,15 @@ import sphinx.util.logging
from docutils.parsers.rst import directives
from . import documenters
from .backends import (
DEFAULT_FILE_PATTERNS,
DEFAULT_IGNORE_PATTERNS,
LANGUAGE_MAPPERS,
LANGUAGE_REQUIREMENTS,
)
from .directives import AutoapiSummary, NestedParse
from .inheritance_diagrams import AutoapiInheritanceDiagram
from .mappers import PythonSphinxMapper
from .settings import API_ROOT
LOGGER = sphinx.util.logging.getLogger(__name__)
_DEFAULT_FILE_PATTERNS = ["*.py", "*.pyi"]
_DEFAULT_IGNORE_PATTERNS = ["*migrations*"]
_DEFAULT_OPTIONS = [
"members",
"undoc-members",
@ -66,19 +62,6 @@ def _normalise_autoapi_dirs(autoapi_dirs, srcdir):
def run_autoapi(app): # pylint: disable=too-many-branches
"""Load AutoAPI data from the filesystem."""
if app.config.autoapi_type not in LANGUAGE_MAPPERS:
allowed = ", ".join(f'"{api_type}"' for api_type in sorted(LANGUAGE_MAPPERS))
raise ExtensionError(
f"Invalid autoapi_type setting, following values are allowed: {allowed}"
)
if app.config.autoapi_type != "python":
warnings.warn(
"Support for documenting languages other than Python "
"will be removed in AutoAPI v3.",
RemovedInAutoAPI3Warning,
)
if not app.config.autoapi_dirs:
raise ExtensionError("You must configure an autoapi_dirs setting")
@ -105,20 +88,6 @@ def run_autoapi(app): # pylint: disable=too-many-branches
)
url_root = os.path.join("/", app.config.autoapi_root)
if not all(
import_name in sys.modules
for _, import_name in LANGUAGE_REQUIREMENTS[app.config.autoapi_type]
):
packages = ", ".join(
f'{import_name} (available as "{pkg_name}" on PyPI)'
for pkg_name, import_name in LANGUAGE_REQUIREMENTS[app.config.autoapi_type]
)
raise ExtensionError(
f"AutoAPI of type `{app.config.autoapi_type}` requires following "
f"packages to be installed and included in extensions list: {packages}"
)
sphinx_mapper = LANGUAGE_MAPPERS[app.config.autoapi_type]
template_dir = app.config.autoapi_template_dir
if template_dir and not os.path.isabs(template_dir):
if not os.path.isdir(template_dir):
@ -130,17 +99,19 @@ def run_autoapi(app): # pylint: disable=too-many-branches
"relative to where sphinx-build is run\n",
RemovedInAutoAPI3Warning,
)
sphinx_mapper_obj = sphinx_mapper(app, template_dir=template_dir, url_root=url_root)
sphinx_mapper_obj = PythonSphinxMapper(
app, template_dir=template_dir, url_root=url_root
)
if app.config.autoapi_file_patterns:
file_patterns = app.config.autoapi_file_patterns
else:
file_patterns = DEFAULT_FILE_PATTERNS.get(app.config.autoapi_type, [])
file_patterns = _DEFAULT_FILE_PATTERNS
if app.config.autoapi_ignore:
ignore_patterns = app.config.autoapi_ignore
else:
ignore_patterns = DEFAULT_IGNORE_PATTERNS.get(app.config.autoapi_type, [])
ignore_patterns = _DEFAULT_IGNORE_PATTERNS
if ".rst" in app.config.source_suffix:
out_suffix = ".rst"
@ -171,10 +142,6 @@ def build_finished(app, exception):
)
shutil.rmtree(normalized_root)
sphinx_mapper = LANGUAGE_MAPPERS[app.config.autoapi_type]
if hasattr(sphinx_mapper, "build_finished"):
sphinx_mapper.build_finished(app, exception)
def source_read(app, docname, source): # pylint: disable=unused-argument
# temp_data is cleared after each source file has been processed,
@ -289,7 +256,6 @@ def setup(app):
app.connect("viewcode-find-source", viewcode_find)
if "viewcode-follow-imported" in app.events.events:
app.connect("viewcode-follow-imported", viewcode_follow_imported)
app.add_config_value("autoapi_type", "python", "html")
app.add_config_value("autoapi_root", API_ROOT, "html")
app.add_config_value("autoapi_ignore", [], "html")
app.add_config_value("autoapi_options", _DEFAULT_OPTIONS, "html")

@ -1,11 +1,3 @@
from .dotnet import DotNetSphinxMapper
from .python import PythonSphinxMapper
from .go import GoSphinxMapper
from .javascript import JavaScriptSphinxMapper
__all__ = (
"DotNetSphinxMapper",
"PythonSphinxMapper",
"GoSphinxMapper",
"JavaScriptSphinxMapper",
)
__all__ = ("PythonSphinxMapper",)

@ -1,641 +0,0 @@
from collections import defaultdict
import re
import os
import subprocess
import traceback
import shutil
from typing import Dict
import anyascii
from sphinx.util.osutil import ensuredir
from sphinx.util.console import colorize
import sphinx.util.logging
from sphinx.errors import ExtensionError
import yaml
from .base import PythonMapperBase, SphinxMapperBase
LOGGER = sphinx.util.logging.getLogger(__name__)
# Doc comment patterns
DOC_COMMENT_PATTERN = r"""
\<%(tag)s
\s+%(attr)s="(?P<attr_value>[^"]*?)"
\s*?
(?:
\/\>|
\>(?P<inner>[^\<]*?)\<\/%(tag)s\>
)
"""
DOC_COMMENT_SEE_PATTERN = re.compile(
DOC_COMMENT_PATTERN % {"tag": "(?:see|seealso)", "attr": "cref"}, re.X
)
DOC_COMMENT_PARAM_PATTERN = re.compile(
DOC_COMMENT_PATTERN % {"tag": "(?:paramref|typeparamref)", "attr": "name"}, re.X
)
# Comment member identities
# From: https://msdn.microsoft.com/en-us/library/vstudio/fsbx0t7x(v=VS.100).aspx
DOC_COMMENT_IDENTITIES = {
"N": "dn:ns",
"T": "any", # can be any type (class, delegate, enum, etc), so use any
"F": "dn:field",
"P": "dn:prop",
"M": "dn:meth",
"E": "dn:event",
}
class DotNetSphinxMapper(SphinxMapperBase):
"""Auto API domain handler for .NET
Searches for YAML files, and soon to be JSON files as well, for auto API
sources. If no pattern configuration was explicitly specified, then default
to looking up a ``docfx.json`` file.
:param app: Sphinx application passed in as part of the extension
"""
top_namespaces: Dict[str, "DotNetNamespace"] = {}
DOCFX_OUTPUT_PATH = "_api"
# pylint: disable=arguments-differ
def load(self, patterns, dirs, ignore=None):
"""Load objects from the filesystem into the ``paths`` dictionary.
If the setting ``autoapi_patterns`` was not specified, look for a
``docfx.json`` file by default. A ``docfx.json`` should be treated as
the canonical source before the default patterns. Fallback to default
pattern matches if no ``docfx.json`` files are found.
"""
LOGGER.info(
colorize("bold", "[AutoAPI] ") + colorize("darkgreen", "Loading Data")
)
all_files = set()
if not self.app.config.autoapi_file_patterns:
all_files = set(
self.find_files(patterns=["docfx.json"], dirs=dirs, ignore=ignore)
)
if not all_files:
all_files = set(
self.find_files(patterns=patterns, dirs=dirs, ignore=ignore)
)
if all_files:
command = ["docfx", "metadata", "--raw", "--force"]
command.extend(all_files)
proc = subprocess.run(
command,
check=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True,
env=dict(
(key, os.environ[key])
for key in [
"PATH",
"HOME",
"SYSTEMROOT",
"USERPROFILE",
"WINDIR",
]
if key in os.environ
),
)
if proc.stderr:
LOGGER.warning(proc.stderr, type="autoapi", subtype="not_readable")
# We now have yaml files
for xdoc_path in self.find_files(
patterns=["*.yml"], dirs=[self.DOCFX_OUTPUT_PATH], ignore=ignore
):
data = self.read_file(path=xdoc_path)
if data:
self.paths[xdoc_path] = data
return True
def read_file(self, path, **kwargs):
"""Read file input into memory, returning deserialized objects
:param path: Path of file to read
"""
try:
with open(path, "r", encoding="utf-8") as handle:
parsed_data = yaml.safe_load(handle)
return parsed_data
except IOError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
except TypeError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
return None
# Subclassed to iterate over items
def map(self, options=None):
"""Trigger find of serialized sources and build objects"""
for _, data in sphinx.util.status_iterator(
self.paths.items(),
colorize("bold", "[AutoAPI] ") + "Mapping Data... ",
length=len(self.paths),
stringify_func=(lambda x: x[0]),
):
references = data.get("references", [])
for item in data["items"]:
for obj in self.create_class(item, options, references=references):
self.add_object(obj)
self.organize_objects()
def create_class(self, data, options=None, **kwargs):
"""
Return instance of class based on Roslyn type property
Data keys handled here:
type
Set the object class
items
Recurse into :py:meth:`create_class` to create child object
instances
:param data: dictionary data from Roslyn output artifact
"""
kwargs.pop("path", None)
obj_map = {cls.type: cls for cls in ALL_CLASSES}
try:
cls = obj_map[data["type"].lower()]
except KeyError:
# this warning intentionally has no (sub-)type
LOGGER.warning(f"Unknown type: {data}")
else:
obj = cls(
data, jinja_env=self.jinja_env, app=self.app, options=options, **kwargs
)
obj.url_root = self.url_root
# Append child objects
# TODO this should recurse in the case we're getting back more
# complex argument listings
yield obj
def add_object(self, obj):
"""Add object to local and app environment storage
:param obj: Instance of a .NET object
"""
if obj.top_level_object:
if isinstance(obj, DotNetNamespace):
self.namespaces[obj.name] = obj
self.objects[obj.id] = obj
def organize_objects(self):
"""Organize objects and namespaces"""
def _render_children(obj):
for child in obj.children_strings:
child_object = self.objects.get(child)
if child_object:
obj.item_map[child_object.plural].append(child_object)
obj.children.append(child_object)
for key in obj.item_map:
obj.item_map[key].sort()
def _recurse_ns(obj):
if not obj:
return
namespace = obj.top_namespace
if namespace is not None:
ns_obj = self.top_namespaces.get(namespace)
if ns_obj is None or not isinstance(ns_obj, DotNetNamespace):
for ns_obj in self.create_class(
{"uid": namespace, "type": "namespace"}
):
self.top_namespaces[ns_obj.id] = ns_obj
if obj not in ns_obj.children and namespace != obj.id:
ns_obj.children.append(obj)
for obj in self.objects.values():
_render_children(obj)
_recurse_ns(obj)
# Clean out dead namespaces
for key, namespace in self.top_namespaces.copy().items():
if not namespace.children:
del self.top_namespaces[key]
for key, namespace in self.namespaces.copy().items():
if not namespace.children:
del self.namespaces[key]
def output_rst(self, root, source_suffix):
if not self.objects:
raise ExtensionError("No API objects exist. Can't continue")
for _, obj in sphinx.util.status_iterator(
self.objects.items(),
colorize("bold", "[AutoAPI] ") + "Rendering Data... ",
length=len(self.objects),
stringify_func=(lambda x: x[0]),
):
if not obj or not obj.top_level_object:
continue
rst = obj.render()
if not rst:
continue
detail_dir = os.path.join(root, obj.pathname)
ensuredir(detail_dir)
path = os.path.join(detail_dir, f"index{source_suffix}")
with open(path, "wb") as detail_file:
detail_file.write(rst.encode("utf-8"))
# Render Top Index
top_level_index = os.path.join(root, "index.rst")
with open(top_level_index, "wb") as top_level_file:
content = self.jinja_env.get_template("index.rst")
top_level_file.write(
content.render(pages=self.namespaces.values()).encode("utf-8")
)
@staticmethod
def build_finished(app, _):
if app.verbosity > 1:
LOGGER.info(
colorize("bold", "[AutoAPI] ")
+ colorize("darkgreen", "Cleaning generated .yml files")
)
if os.path.exists(DotNetSphinxMapper.DOCFX_OUTPUT_PATH):
shutil.rmtree(DotNetSphinxMapper.DOCFX_OUTPUT_PATH)
class DotNetPythonMapper(PythonMapperBase):
"""Base .NET object representation
Args:
references (list of dict objects): object reference list from
docfx
"""
language = "dotnet"
def __init__(self, obj, **kwargs):
self.references = dict(
(obj.get("uid"), obj)
for obj in kwargs.pop("references", [])
if "uid" in obj
)
super().__init__(obj, **kwargs)
# Always exist
self.id = obj.get("uid", obj.get("id"))
self.definition = obj.get("definition", self.id)
self.name = obj.get("fullName", self.definition)
# Optional
self.fullname = obj.get("fullName")
self.summary = self.transform_doc_comments(obj.get("summary", ""))
self.parameters = []
self.items = obj.get("items", [])
self.children_strings = obj.get("children", [])
self.children = []
self.item_map = defaultdict(list)
self.inheritance = []
self.assemblies = obj.get("assemblies", [])
# Syntax example and parameter list
syntax = obj.get("syntax", None)
self.example = ""
if syntax is not None:
# Code example
try:
self.example = syntax["content"]
except (KeyError, TypeError):
traceback.print_exc()
self.parameters = []
for param in syntax.get("parameters", []):
if "id" in param:
self.parameters.append(
{
"name": param.get("id"),
"type": self.resolve_spec_identifier(param.get("type")),
"desc": self.transform_doc_comments(
param.get("description", "")
),
}
)
self.returns = {}
self.returns["type"] = self.resolve_spec_identifier(
syntax.get("return", {}).get("type")
)
self.returns["description"] = self.transform_doc_comments(
syntax.get("return", {}).get("description")
)
# Inheritance
# TODO Support more than just a class type here, should support enum/etc
self.inheritance = [
DotNetClass(
{"uid": name, "name": name}, jinja_env=self.jinja_env, app=self.app
)
for name in obj.get("inheritance", [])
]
def __str__(self):
return f"<{self.__class__.__name__} {self.id}>"
@property
def pathname(self):
"""Sluggified path for filenames
Slugs to a filename using the follow steps
* Decode unicode to approximate ascii
* Remove existing hyphens
* Substitute hyphens for non-word characters
* Break up the string as paths
"""
slug = self.name
try:
slug = self.name.split("(")[0]
except IndexError:
pass
slug = anyascii.anyascii(slug)
slug = slug.replace("-", "")
slug = re.sub(r"[^\w\.]+", "-", slug).strip("-")
return os.path.join(*slug.split("."))
@property
def short_name(self):
"""Shorten name property"""
return self.name.split(".")[-1]
@property
def edit_link(self):
try:
repo = self.source["remote"]["repo"].replace(".git", "")
path = self.path
return f"{repo}/blob/master/{path}"
except KeyError:
return ""
@property
def source(self):
return self.obj.get("source")
@property
def path(self):
return self.source["path"]
@property
def namespace(self):
pieces = self.id.split(".")[:-1]
if pieces:
return ".".join(pieces)
return None
@property
def top_namespace(self):
pieces = self.id.split(".")[:2]
if pieces:
return ".".join(pieces)
return None
@property
def ref_type(self):
return self.type
@property
def ref_directive(self):
return self.type
@property
def ref_name(self):
"""Return object name suitable for use in references
Escapes several known strings that cause problems, including the
following reference syntax::
:dotnet:cls:`Foo.Bar<T>`
As the `<T>` notation is also special syntax in references, indicating
the reference to Foo.Bar should be named T.
See: https://www.sphinx-doc.org/en/master/#role-cpp:any
"""
return self.name.replace("<", r"\<").replace("`", r"\`")
@property
def ref_short_name(self):
"""Same as above, return the truncated name instead"""
return self.ref_name.split(".")[-1]
@staticmethod
def transform_doc_comments(text):
"""Parse XML content for references and other syntax.
This avoids an LXML dependency, we only need to parse out a small subset
of elements here. Iterate over string to reduce regex pattern complexity
and make substitutions easier
See Also:
`Doc comment reference <https://msdn.microsoft.com/en-us/library/5ast78ax.aspx>`
Reference on XML documentation comment syntax
"""
try:
while True:
found = DOC_COMMENT_SEE_PATTERN.search(text)
if found is None:
break
ref = found.group("attr_value").replace("<", r"\<").replace("`", r"\`")
reftype = "any"
replacement = ""
# Given the pattern of `\w:\w+`, inspect first letter of
# reference for identity type
if ref[1] == ":" and ref[0] in DOC_COMMENT_IDENTITIES:
reftype = DOC_COMMENT_IDENTITIES[ref[:1]]
ref = ref[2:]
replacement = f":{reftype}:`{ref}`"
elif ref[:2] == "!:":
replacement = ref[2:]
else:
replacement = f":any:`{ref}`"
# Escape following text
text_end = text[found.end() :]
text_start = text[: found.start()]
text_end = re.sub(r"^(\S)", r"\\\1", text_end)
text_start = re.sub(r"(\S)$", r"\1 ", text_start)
text = "".join([text_start, replacement, text_end])
while True:
found = DOC_COMMENT_PARAM_PATTERN.search(text)
if found is None:
break
# Escape following text
text_end = text[found.end() :]
text_start = text[: found.start()]
text_end = re.sub(r"^(\S)", r"\\\1", text_end)
text_start = re.sub(r"(\S)$", r"\1 ", text_start)
text = "".join(
[text_start, "``", found.group("attr_value"), "``", text_end]
)
except TypeError:
pass
return text
def resolve_spec_identifier(self, obj_name):
"""Find reference name based on spec identifier
Spec identifiers are used in parameter and return type definitions, but
should be a user-friendly version instead. Use docfx ``references``
lookup mapping for resolution.
If the spec identifier reference has a ``spec.csharp`` key, this implies
a compound reference that should be linked in a special way. Resolve to
a nested reference, with the corrected nodes.
Note:
This uses a special format that is interpreted by the domain for
parameter type and return type fields.
Args:
obj_name: spec identifier to resolve to a correct reference
Returns:
str: resolved string with one or more references
"""
ref = self.references.get(obj_name)
if ref is None:
return obj_name
resolved = ref.get("fullName", obj_name)
spec = ref.get("spec.csharp", [])
parts = []
for part in spec:
if part.get("name") == "<":
parts.append("{")
elif part.get("name") == ">":
parts.append("}")
elif "fullName" in part and "uid" in part:
parts.append(f"{part['fullName']}<{part['uid']}>")
elif "uid" in part:
parts.append(part["uid"])
elif "fullName" in part:
parts.append(part["fullName"])
if parts:
resolved = "".join(parts)
return resolved
class DotNetNamespace(DotNetPythonMapper):
type = "namespace"
ref_directive = "ns"
plural = "namespaces"
top_level_object = True
class DotNetMethod(DotNetPythonMapper):
type = "method"
ref_directive = "meth"
plural = "methods"
class DotNetOperator(DotNetPythonMapper):
type = "operator"
ref_directive = "op"
plural = "operators"
class DotNetProperty(DotNetPythonMapper):
type = "property"
ref_directive = "prop"
plural = "properties"
class DotNetEnum(DotNetPythonMapper):
type = "enum"
ref_type = "enumeration"
ref_directive = "enum"
plural = "enumerations"
top_level_object = True
class DotNetStruct(DotNetPythonMapper):
type = "struct"
ref_type = "structure"
ref_directive = "struct"
plural = "structures"
top_level_object = True
class DotNetConstructor(DotNetPythonMapper):
type = "constructor"
ref_directive = "ctor"
plural = "constructors"
class DotNetInterface(DotNetPythonMapper):
type = "interface"
ref_directive = "iface"
plural = "interfaces"
top_level_object = True
class DotNetDelegate(DotNetPythonMapper):
type = "delegate"
ref_directive = "del"
plural = "delegates"
top_level_object = True
class DotNetClass(DotNetPythonMapper):
type = "class"
ref_directive = "cls"
plural = "classes"
top_level_object = True
class DotNetField(DotNetPythonMapper):
type = "field"
plural = "fields"
class DotNetEvent(DotNetPythonMapper):
type = "event"
plural = "events"
ALL_CLASSES = [
DotNetNamespace,
DotNetClass,
DotNetEnum,
DotNetStruct,
DotNetInterface,
DotNetDelegate,
DotNetOperator,
DotNetProperty,
DotNetMethod,
DotNetConstructor,
DotNetField,
DotNetEvent,
]

@ -1,213 +0,0 @@
import json
import subprocess
from sphinx.util.console import colorize
import sphinx.util.logging
from .base import PythonMapperBase, SphinxMapperBase
LOGGER = sphinx.util.logging.getLogger(__name__)
class GoSphinxMapper(SphinxMapperBase):
"""Auto API domain handler for Go
Parses directly from Go files.
:param app: Sphinx application passed in as part of the extension
"""
def load(self, patterns, dirs, ignore=None):
"""
Load objects from the filesystem into the ``paths`` dictionary.
"""
for _dir in sphinx.util.status_iterator(
dirs, colorize("bold", "[AutoAPI] Loading Data "), "darkgreen", len(dirs)
):
data = self.read_file(_dir, ignore=ignore)
if data:
self.paths[_dir] = data
return True
def read_file(self, path, **kwargs):
"""Read file input into memory, returning deserialized objects
:param path: Path of file to read
:param **kwargs:
* ignore (``list``): List of file patterns to ignore
"""
# TODO support JSON here
# TODO sphinx way of reporting errors in logs?
parser_command = ["godocjson"]
_ignore = kwargs.get("ignore")
if _ignore:
parser_command.extend(["-e", "|".join(_ignore)])
parser_command.append(path)
try:
parsed_data = json.loads(subprocess.check_output(parser_command))
return parsed_data
except IOError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
except TypeError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
return None
def create_class(self, data, options=None, **kwargs):
"""Return instance of class based on Go data
Data keys handled here:
_type
Set the object class
consts, types, vars, funcs, methods
Recurse into :py:meth:`create_class` to create child object
instances
:param data: dictionary data from godocjson output
"""
_type = kwargs.get("_type")
obj_map = dict((cls.type, cls) for cls in ALL_CLASSES)
try:
# Contextual type data from children recursion
if _type:
LOGGER.debug(f"Forcing Go Type {_type}")
cls = obj_map[_type]
else:
cls = obj_map[data["type"]]
except KeyError:
# this warning intentionally has no (sub-)type
LOGGER.warning(f"Unknown type: {data}")
else:
if cls.inverted_names and "names" in data:
# Handle types that have reversed names parameter
for name in data["names"]:
data_inv = {}
data_inv.update(data)
data_inv["name"] = name
if "names" in data_inv:
del data_inv["names"]
for obj in self.create_class(data_inv):
yield obj
else:
# Recurse for children
obj = cls(data, jinja_env=self.jinja_env, app=self.app)
for child_type in ["consts", "types", "vars", "funcs", "methods"]:
for child_data in data.get(child_type, []):
obj.children += list(
self.create_class(
child_data,
_type=child_type.replace("consts", "const")
.replace("types", "type")
.replace("vars", "variable")
.replace("funcs", "func")
.replace("methods", "method"),
)
)
yield obj
class GoPythonMapper(PythonMapperBase):
language = "go"
inverted_names = False
def __init__(self, obj, **kwargs):
super().__init__(obj, **kwargs)
self.name = obj.get("name") or obj.get("packageName")
self.id = self.name
# Second level
self.imports = obj.get("imports", [])
self.children = []
temp_parameters = map(
lambda n: {"name": n["name"], "type": n["type"].lstrip("*")},
obj.get("parameters", []),
)
self.parameters = list(temp_parameters)
self.results = obj.get("results", [])
self.docstring = obj.get("doc", "")
# Go Specific
self.notes = obj.get("notes", {})
self.filenames = obj.get("filenames", [])
self.bugs = obj.get("bugs", [])
def __str__(self):
return f"<{self.__class__.__name__} {self.id}>"
@property
def short_name(self):
"""Shorten name property"""
return self.name.split(".")[-1]
@property
def namespace(self):
pieces = self.id.split(".")[:-1]
if pieces:
return ".".join(pieces)
return None
@property
def ref_type(self):
return self.type
@property
def ref_directive(self):
return self.type
@property
def methods(self):
return self.obj.get("methods", [])
class GoVariable(GoPythonMapper):
type = "var"
inverted_names = True
class GoMethod(GoPythonMapper):
type = "method"
ref_directive = "meth"
def __init__(self, obj, **kwargs):
super().__init__(obj, **kwargs)
self.receiver = obj.get("recv")
class GoConstant(GoPythonMapper):
type = "const"
inverted_names = True
class GoFunction(GoPythonMapper):
type = "func"
ref_type = "function"
class GoPackage(GoPythonMapper):
type = "package"
ref_directive = "pkg"
top_level_object = True
_RENDER_LOG_LEVEL = "VERBOSE"
class GoType(GoPythonMapper):
type = "type"
ALL_CLASSES = [GoConstant, GoFunction, GoPackage, GoVariable, GoType, GoMethod]

@ -1,152 +0,0 @@
import json
import subprocess
import os
from sphinx.util.console import colorize
import sphinx.util.logging
from .base import PythonMapperBase, SphinxMapperBase
LOGGER = sphinx.util.logging.getLogger(__name__)
class JavaScriptSphinxMapper(SphinxMapperBase):
"""Auto API domain handler for Javascript
Parses directly from Javascript files.
:param app: Sphinx application passed in as part of the extension
"""
def read_file(self, path, **kwargs):
"""Read file input into memory, returning deserialized objects
:param path: Path of file to read
"""
# TODO support JSON here
# TODO sphinx way of reporting errors in logs?
subcmd = "jsdoc"
if os.name == "nt":
subcmd = ".".join([subcmd, "cmd"])
try:
parsed_data = json.loads(subprocess.check_output([subcmd, "-X", path]))
return parsed_data
except IOError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
except TypeError:
LOGGER.warning(
f"Error reading file: {path}",
type="autoapi",
subtype="not_readable",
)
return None
# Subclassed to iterate over items
def map(self, options=None):
"""Trigger find of serialized sources and build objects"""
for _, data in sphinx.util.status_iterator(
self.paths.items(),
colorize("bold", "[AutoAPI] ") + "Mapping Data... ",
length=len(self.paths),
stringify_func=(lambda x: x[0]),
):
for item in data:
for obj in self.create_class(item, options):
obj.jinja_env = self.jinja_env
self.add_object(obj)
def create_class(self, data, options=None, **kwargs):
"""Return instance of class based on Javascript data
Data keys handled here:
type
Set the object class
consts, types, vars, funcs
Recurse into :py:meth:`create_class` to create child object
instances
:param data: dictionary data from godocjson output
"""
obj_map = dict((cls.type, cls) for cls in ALL_CLASSES)
try:
cls = obj_map[data["kind"]]
except (KeyError, TypeError):
# this warning intentionally has no (sub-)type
LOGGER.warning(f"Unknown type: {data}")
else:
# Recurse for children
obj = cls(data, jinja_env=self.jinja_env, app=self.app)
if "children" in data:
for child_data in data["children"]:
for child_obj in self.create_class(child_data, options=options):
obj.children.append(child_obj)
yield obj
class JavaScriptPythonMapper(PythonMapperBase):
language = "javascript"
def __init__(self, obj, **kwargs):
"""
Map JSON data into Python object.
This is the standard object that will be rendered into the templates,
so we try and keep standard naming to keep templates more re-usable.
"""
super().__init__(obj, **kwargs)
self.name = obj.get("name")
self.id = self.name
# Second level
self.docstring = obj.get("description", "")
# self.docstring = obj.get('comment', '')
self.imports = obj.get("imports", [])
self.children = []
self.parameters = map(
lambda n: {"name": n["name"], "type": n["type"][0]}, obj.get("param", [])
)
class JavaScriptClass(JavaScriptPythonMapper):
type = "class"
ref_directive = "class"
top_level_object = True
class JavaScriptFunction(JavaScriptPythonMapper):
type = "function"
ref_type = "func"
class JavaScriptData(JavaScriptPythonMapper):
type = "data"
ref_directive = "data"
class JavaScriptMember(JavaScriptPythonMapper):
type = "member"
ref_directive = "member"
class JavaScriptAttribute(JavaScriptPythonMapper):
type = "attribute"
ref_directive = "attr"
ALL_CLASSES = [
JavaScriptFunction,
JavaScriptClass,
JavaScriptData,
JavaScriptAttribute,
JavaScriptMember,
]

@ -1,88 +0,0 @@
{% block title %}
{{ obj.short_name }} {{ obj.type.title()}}
{{ "=" * (obj.short_name|length + obj.type|length + 1) }}
{% endblock %}
{% block summary %}
{% if obj.summary %}
{{ obj.summary }}
{% endif %}
{% endblock %}
{% if obj.namespace %}
Namespace
:dn:ns:`{{ obj.namespace }}`
{% endif %}
{% if obj.assemblies %}
Assemblies
{% for assembly in obj.assemblies %}
* {{ assembly }}
{% endfor %}
{% endif %}
----
.. contents::
:local:
{% block inheritance %}
{% if obj.inheritance %}
Inheritance Hierarchy
---------------------
{% for item in obj.inheritance %}
* :dn:{{ item.ref_directive }}:`{{ item.ref_name }}`
{% endfor %}
* :dn:{{ obj.ref_directive }}:`{{ obj.ref_name }}`
{% endif %}
{% endblock %}
{% block syntax %}
{% if obj.example %}
Syntax
------
.. code-block:: csharp
{{ obj.example|indent(4) }}
{% endif %}
{% endblock %}
{% block content %}
.. dn:{{ obj.ref_type }}:: {{ obj.definition }}
:hidden:
.. dn:{{ obj.ref_type }}:: {{ obj.name }}
{% for item_type in obj.item_map.keys() %}
{% if item_type in obj.item_map %}
{{ item_type.title() }}
{{ "-" * item_type|length }}
.. dn:{{ obj.ref_type }}:: {{ obj.name }}
:noindex:
:hidden:
{% for obj_item in obj.item_map.get(item_type, []) %}
{{ obj_item.render()|indent(4) }}
{% endfor %}
{% endif %}
{% endfor %}
{% endblock %}

@ -1,29 +0,0 @@
.. dn:{{ obj.ref_type }}:: {{ obj.name }}
{% if obj.summary %}
{{ obj.summary|indent(4) }}
{% endif %}
{% for param in obj.parameters %}
{% if param.desc %}
:param {{ param.name }}: {{ param.desc|indent(8) }}
{% endif %}
{% if param.type %}
:type {{ param.name }}: {{ param.type|indent(8) }}
{% endif %}
{% endfor %}
{% if obj.returns.type %}
:rtype: {{ obj.returns.type|indent(8) }}
{% endif %}
{% if obj.returns.description %}
:return: {{ obj.returns.description|indent(8) }}
{% endif %}
{% if obj.example %}
.. code-block:: csharp
{{ obj.example|indent(8) }}
{% endif %}

@ -1,66 +0,0 @@
{% block title %}
{{ obj.name }} {{ obj.type.title() }}
{{ "=" * (obj.name|length + obj.type|length + 1) }}
{% endblock %}
{% block toc %}
{% if obj.children %}
.. toctree::
:hidden:
:maxdepth: 2
{% for item in obj.children|sort %}
{% if item.type != 'namespace' %}
{{ item.include_path }}
{% endif %}
{% endfor %}
{% endif %}
{% if obj.references %}
.. toctree::
:hidden:
:maxdepth: 2
{% for item in obj.references|sort %}
{% if item.type != 'namespace' %}
{{ item.include_path }}
{% endif %}
{% endfor %}
{% endif %}
{% endblock %}
{% block content %}
{% macro display_type(item_type) %}
.. rubric:: {{ item_type.title() }}
{% for obj_item in obj.item_map.get(item_type, []) %}
{% macro render() %}{{ obj_item.summary }}{% endmacro %}
{{ obj_item.type }} :dn:{{ obj_item.ref_directive }}:`{{ obj_item.ref_short_name }}`
.. object: type={{ obj_item.type }} name={{ obj_item.ref_name }}
{{ render()|indent(8) }}
{% endfor %}
{% endmacro %}
.. dn:{{ obj.ref_type }}:: {{ obj.name }}
{% for item_type in obj.item_map.keys() %}
{{ display_type(item_type) }}
{% endfor %}
{% endblock %}

@ -1 +0,0 @@
{% extends "dotnet/base_detail.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_detail.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_detail.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_detail.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_list.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_embed.rst" %}

@ -1 +0,0 @@
{% extends "dotnet/base_detail.rst" %}

@ -1,32 +0,0 @@
{% if obj.type == 'func' %}
{# Creating the parameters line #}
{% set ns = namespace(tmpstring='') %}
{% set argjoin = joiner(', ') %}
{% for param in obj.parameters %}
{% set ns.tmpstring = ns.tmpstring ~ argjoin() ~ param.name ~ ' ' ~ param.type %}
{% endfor %}
.. go:{{ obj.ref_type }}:: {{ obj.name }}({{ ns.tmpstring }})
{% else %}
.. go:{{ obj.ref_type }}:: {{ obj.name }}
{% endif %}
{% macro render() %}{{ obj.docstring }}{% endmacro %}
{{ render()|indent(4) }}
{# Don't define parameter description here, that can be done in the block
above #}
{% for param in obj.parameters %}
:param {{ param.name }}:
:type {{ param.name }}: {{ param.type }}
{% endfor %}
{% if obj.returns %}
:rtype: {{ obj.returns.type }}
{% endif %}
{% if obj.children %}
{% for child in obj.children|sort %}
{% macro render_child() %}{{ child.render() }}{% endmacro %}
{{ render_child()|indent(4) }}
{% endfor %}
{% endif %}

@ -1 +0,0 @@
{% extends "go/base_member.rst" %}

@ -1 +0,0 @@
{% extends "go/base_member.rst" %}

@ -1 +0,0 @@
{% extends "go/base_member.rst" %}

@ -1,32 +0,0 @@
.. go:package:: {{ obj.name }}
{{ obj.name }}
{{ "=" * obj.name|length }}
{% block toc %}
{% if obj.children %}
{# TODO Make this work
.. toctree::
:maxdepth: 4
{% for item in obj.children|sort %}
/autoapi/{{ item.id.split('.')|join('/') }}/index
{% endfor %}
#}
{% endif %}
{% endblock %}
{% if obj.docstring %}
{{ obj.docstring }}
{% endif %}
{% block content %}
{% for obj_item in obj.children|sort %}
{% macro render() %}{{ obj_item.render() }}{% endmacro %}
{{ render()|indent(0) }}
{% endfor %}
{% endblock %}

@ -1 +0,0 @@
{% extends "go/base_member.rst" %}

@ -1 +0,0 @@
{% extends "go/base_member.rst" %}

@ -1,20 +0,0 @@
.. js:class:: {{ obj.name }}{% if obj.args %}({{ obj.args|join(',') }}){% endif %}
{% if obj.docstring %}
.. rubric:: Summary
{{ obj.docstring|indent(3) }}
{% endif %}
{% if obj.methods %}
{% for method in obj.methods %}
{% macro render() %}{{ method.render() }}{% endmacro %}
{{ render()|indent(3) }}
{%- endfor %}
{% endif %}

@ -1,14 +0,0 @@
{# Indentation in this file is important #}
{% if is_method %}
{# Slice self off #}
.. js:method:: {{ obj.name.split('.')[-1] }}({{ args[1:]|join(',') }})
{% else %}
.. js:function:: {{ obj.name.split('.')[-1] }}({{ args|join(',') }})
{% endif %}
{% if obj.docstring %}
{{ obj.docstring|indent(3) }}
{% endif %}

@ -1,7 +0,0 @@
{# Indentation in this file is important #}
.. js:{{ obj.type }}:: {{ obj.name }}
{{ obj.docstring|indent(3) }}

@ -1,52 +0,0 @@
{{ obj.name }}
{{ "-" * obj.name|length }}
{% block toc %}
{% if obj.children %}
.. toctree::
:maxdepth: 4
{% for item in obj.children|sort %}
/autoapi/{{ item.pathname }}/index
{%- endfor %}
{% endif %}
{% endblock %}
{% if obj.docstring %}
.. rubric:: Summary
{{ obj.docstring }}
{% endif %}
.. js:module:: {{ obj.name }}
{% block content %}
{%- macro display_type(item_type) %}
{{ item_type.title() }}
{{ "*" * item_type|length }}
{%- for obj_item in obj.item_map.get(item_type, []) %}
{% macro render() %}{{ obj_item.render() }}{% endmacro %}
{{ render()|indent(4) }}
{%- endfor %}
{%- endmacro %}
{%- for item_type in obj.item_map.keys() %}
{% if item_type.lower() != 'module' %}
{{ display_type(item_type) }}
{% endif %}
{%- endfor %}
{% endblock %}

@ -0,0 +1 @@
Removed support for documenting languages other than Python

@ -41,7 +41,6 @@ html_static_path = ['_static']
html_css_files = ['overrides.css']
# -- Options for AutoAPI extension -------------------------------------------
autoapi_type = 'python'
autoapi_dirs = ['../autoapi']
autoapi_generate_api_docs = False

@ -31,36 +31,6 @@ with some exceptions:
* :meth:`type.__new__`
.NET
----
This document talks about the design of a .NET Sphinx integration.
This will include a mechanism for generating Javadoc style API references automatically.
We will describe decisions that lead to specific implementation details.
Goals
-----
The main goal of this project is to be able to generate a MSDN or Javadoc style API reference from a .Net project in Sphinx.
Primary Goals
~~~~~~~~~~~~~
* Build MSDN/Javadoc style HTML output for arbitrary .Net code.
* Have specific pages for each Package, Class, and all class-level structures.
- `/api/System/`
- `/api/System/String/`
- `/api/System/String/Constructors/`
Secondary Goals
~~~~~~~~~~~~~~~
* Allow for definition of .Net classes inside of normal Sphinx prose docs (classic Sphinx style definition).
* Allow generation of Javadoc style docs from other languages.
Requirements
~~~~~~~~~~~~
Introduction
------------
@ -97,6 +67,7 @@ Autodoc is a Python-only solution that imports the author's code into memory, an
This will generate output that looks like:
.. class:: Noodle
:noindex:
Noodle's docstring.
@ -109,36 +80,19 @@ Proposed Architecture
The proposed architecture for this project is as follows:
* A program that will generate a YAML (or JSON) file from a .Net project, representing it's full API information.
* Read the YAML and generate an appropriate tree structure that will the outputted HTML will look like (YAMLTree)
- If time allows, we will allow a merging of these objects with multiple YAML files to allow for prose content to be injected into the output
* Take the YAML structure and generate in-memory rst that corresponds to the Sphinx dotnet Domain objects
* dotnet Domain will output HTML based on the doctree generated from the in-memory RST
* A parser will read the source files into an internal representation of the objects that can be documented.
* Take the internal representation and generate in-memory rst that corresponds to the Sphinx domain objects.
* Sphinx will output HTML based on the doctree generated from the in-memory rst.
In diagram form::
Code -> YAML -> YAMLTree -> RST (Dotnet Domain) -> Sphinx -> HTML
YAMLTree
~~~~~~~~
One of the main problems is how to actually structure the outputted HTML pages.
The YAML file will likely be ordered,
but we need to have a place to define the page structure in the HTML.
This can be done before or after the loading of the content into RST.
We decided to do it before loading into RST because that matches standard Sphinx convention.
Generally the markup being fed in as RST is considered to be in a file that maps to it's output location.
If we tried to manipulate this structure after loading into the Domain,
that could lead to unexpected consequences like wrong indexes and missing references.
Code -> Internal Objects -> RST -> Sphinx -> HTML
File Structure vs. Hierarchy
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Specific ID's should have one specific detail representation.
This means that every YAML docid object should only have one place that it is rendered with a ``.. dn:<method>`` canonical identifier.
This means that every internal object should only have one place that it is rendered with a ``.. <domain>:<type>::`` canonical identifier.
All other places it is referenced should be in either:
* A reference
@ -158,11 +112,10 @@ There will be Sphinx configuration for how things get built:
autoapi_root = 'api' # Where HTML is generated
autoapi_dirs = ['yaml'] # Directory of YAML sources
We will then loop over all YAML files in the ``autoapi_dir`` and parse them.
We will then loop over all source files in the ``autoapi_dir`` and parse them.
They will then be output into ``autoapi_root`` inside the documentation.
Examples
--------
@ -173,17 +126,4 @@ A nice example of Sphinx Python output similar to what we want:
An example domain for Spec:
* https://subversion.xray.aps.anl.gov/bcdaext/specdomain/trunk/src/specdomain/sphinxcontrib/specdomain.py
Other Ideas
-----------
.. warning:: Things in this section might not get implemented.
The .Net domain will not be able to depend on importing code from the users code base. We might be able to implement similar authoring tools with the YAML file. We might be able to output the YAML subtree of an object with autodoc style tools:
.. code-block:: rst
.. autodnclass:: System.String
:members:
* https://subversion.xray.aps.anl.gov/bcdaext/specdomain/trunk/src/specdomain/sphinxcontrib/specdomain.py

@ -14,26 +14,6 @@ Configuration Options
If an ordinary directory is specified,
that directory will not be included in the relative path.
.. confval:: autoapi_type
Default: ``python``
Set the type of files you are documenting.
This depends on the programming language that you are using:
========== ================
Language ``autoapi_type``
========== ================
Python ``'python'``
Go ``'go'``
Javascript ``'javascript'``
.NET ``'dotnet'``
========== ================
.. warning::
Support for all languages other than Python will be removed in the next major version!
.. confval:: autoapi_template_dir
Default: ``''``
@ -51,7 +31,7 @@ Configuration Options
.. confval:: autoapi_file_patterns
Default: Varies by Language
Default: ``['*.py', '*.pyi']``
A list containing the file patterns to look for when generating documentation.
Patterns should be listed in order of preference.
@ -60,17 +40,6 @@ Configuration Options
and a `.py` file and a `.pyi` file are found,
then the `.py` will be read.
The defaults by language are:
========== ============================================
Language ``autoapi_file_patterns``
========== ============================================
Python ``['*.py', '*.pyi']``
Go ``['*.go']``
Javascript ``['*.js']``
.NET ``['project.json', '*.csproj', '*.vbproj']``
========== ============================================
.. confval:: autoapi_generate_api_docs
Default: ``True``
@ -119,19 +88,9 @@ Customisation Options
.. confval:: autoapi_ignore
Default: Varies By Language
Default: ``['*migrations*']``
A list of patterns to ignore when finding files.
The defaults by language are:
========== ============================================
Language ``autoapi_file_patterns``
========== ============================================
Python ``['*migrations*']``
Go ``[]``
Javascript ``[]``
.NET ``['*toc.yml', '*index.yml']``
========== ============================================
.. confval:: autoapi_root
@ -229,7 +188,6 @@ The following events allow you to control the behaviour of AutoAPI.
.. event:: autoapi-skip-member (app, what, name, obj, skip, options)
(Python only)
Emitted when a template has to decide whether a member should be included
in the documentation.
Usually the member is skipped if a handler returns ``True``,

@ -9,18 +9,18 @@ Structure
---------
Every type of data structure has its own template.
It uses the form :samp:`{language}/{type}.rst` to find the template to render.
It uses the form :samp:`python/{type}.rst` to find the template to render.
The full search path is:
* :samp:`{language}/{type}.rst`
* :samp:`python/{type}.rst`
So for a .NET Class, this would resolve to:
So for a Python Class, this would resolve to:
* :samp:`dotnet/class.rst`
* :samp:`python/class.rst`
We provide :samp:`base/base.rst` as an incredibly basic output of every object::
.. {language}:{type}:: {name}
.. py:{type}:: {name}
Custom Filters, Tests, and Globals
@ -48,11 +48,11 @@ This contains:
configuration option.
* ``include_summaries``: The value of the :confval:`autoapi_include_summaries`
configuration option.
* ``obj``: A Python object derived from :class:`PythonMapperBase`.
* ``obj``: A Python object derived from :class:`PythonPythonMapper`.
* ``sphinx_version``: The contents of :attr:`sphinx.version_info`.
The object in ``obj`` has a number of standard attributes
that you can reliably access per language.
that you can reliably access.
.. warning::
@ -60,9 +60,6 @@ that you can reliably access per language.
They can be reliably accessed through templates
and :event:`autoapi-skip-member` only.
Python
~~~~~~
.. autoapiclass:: autoapi.mappers.python.objects.PythonPythonMapper
:members:
@ -104,22 +101,4 @@ Python
.. autoapiclass:: autoapi.mappers.python.objects.PythonException
:members:
:show-inheritance:
Go
~~~
.. autoapiclass:: autoapi.mappers.go.GoPythonMapper
:members:
Javascript
~~~~~~~~~~
.. autoapiclass:: autoapi.mappers.javascript.JavaScriptPythonMapper
:members:
.NET
~~~~
.. autoapiclass:: autoapi.mappers.dotnet.DotNetPythonMapper
:members:
:show-inheritance:

@ -13,25 +13,9 @@ Setting up Automatic API Documentation Generation
The recommended way of installing AutoAPI is through a `virtualenv <https://virtualenv.pypa.io/>`_.
Once you have a virtualenv set up, you can install AutoAPI with the command:
========== ======================================
Language Command
========== ======================================
Python ``pip install sphinx-autoapi``
Go ``pip install sphinx-autoapi[go]``
Javascript ``pip install sphinx-autoapi``
.NET ``pip install sphinx-autoapi[dotnet]``
========== ======================================
.. warning::
Support for all languages other than Python will be removed in the next major version!
Depending on which language you are trying to document,
each language has a different set of steps for finishing the setup of AutoAPI.
.. code-block:: bash
Python
^^^^^^
pip install sphinx-autoapi
..
Validate this section with the following commands:
@ -54,7 +38,7 @@ we need to add it to the list of extensions in Sphinx's ``conf.py`` file::
extensions = ['autoapi.extension']
For Python, there is only one required configuration option that we need to set.
There is only one required configuration option that we need to set.
:confval:`autoapi_dirs` tells AutoAPI which directories contain
the source code to document.
These can either be absolute, or relative to the source directory of
@ -126,143 +110,4 @@ The page will have a table of contents with a link to API reference
documentation that has been generated by AutoAPI.
Next, you might want to :ref:`customise what gets documented <customise-documented-api>`
or :ref:`customise or remove the API reference index page <customise-index-page>`.
Go
^^^
Support for Go requires you to have the go environment installed
(https://golang.org/dl/), as well as our godocjson tool::
go get github.com/readthedocs/godocjson
and the Go domain extension for Sphinx::
pip install sphinxcontrib-golangdomain
To enable the AutoAPI extension,
we need to add it to the list of extensions in Sphinx's ``conf.py`` file
with the Go domain extension::
extensions = [
'sphinxcontrib.golangdomain',
'autoapi.extension',
]
For Go, there are two required configuration options that we need to set.
:confval:`autoapi_type` tells AutoAPI what type of language we are documenting.
For Go, this is::
autoapi_type = 'go'
The second configuration option is :confval:`autoapi_dirs`,
which tells AutoAPI which directories contain the source code to document.
These can either be absolute, or relative to the source directory of
your documentation files.
So if your documentation was inside a ``docs/`` directory
and your source code is in an ``example`` directory one level up,
you would configure :confval:`autoapi_dirs` to be::
autoapi_dirs = ['../example']
Now that everything is configured,
AutoAPI will generate documentation when you run Sphinx!
.. code-block:: bash
cd docs/
sphinx-build -b html . _build
Javascript
^^^^^^^^^^
Support for Javascript requires you to have jsdoc (http://usejsdoc.org/) installed::
npm install jsdoc -g
To enable the AutoAPI extension,
we need to add it to the list of extensions in Sphinx's ``conf.py`` file::
extensions = ['autoapi.extension']
For Javascript, there are two required configuration options that we need to set.
:confval:`autoapi_type` tells AutoAPI what type of language we are documenting.
For Javascript, this is::
autoapi_type = 'javascript'
The second configuration option is :confval:`autoapi_dirs`,
which tells AutoAPI which directories contain the source code to document.
These can either be absolute, or relative to the source directory of
your documentation files.
So if your documentation was inside a ``docs/`` directory
and your source code is in an ``example`` directory one level up,
you would configure :confval:`autoapi_dirs` to be::
autoapi_dirs = ['../example']
Now that everything is configured,
AutoAPI will generate documentation when you run Sphinx!
.. code-block:: bash
cd docs/
sphinx-build -b html . _build
.NET
^^^^
Support for .NET requires you to have the docfx (https://dotnet.github.io/docfx/) tool installed,
as well as the .NET domain extension for Sphinx::
pip install sphinxcontrib-dotnetdomain
Firstly, we need to configure docfx to output to a directory known to AutoAPI.
By default, ``docfx`` will output metadata files into the ``_api`` path.
You can configure which path to output files into by setting the path in your
`docfx configuration file <https://dotnet.github.io/docfx/tutorial/docfx.exe_user_manual.html#3-docfx-json-format>`_
in your project repository.
For example, if your documentation source files are located inside a ``docs/`` directory:
.. code:: json
{
"metadata": [{
"dest": "docs/_api"
}]
}
To enable the AutoAPI extension,
we need to add it to the list of extensions in Sphinx's ``conf.py`` file
with the .NET domain extension::
extensions = [
'sphinxcontrib.dotnetdomain',
'autoapi.extension',
]
For .NET, there are two required configuration options that we need to set.
:confval:`autoapi_type` tells AutoAPI what type of language we are documenting.
For .NET, this is::
autoapi_type = 'dotnet'
The second configuration option is :confval:`autoapi_dirs`,
which tells AutoAPI which directories contain the source code to document.
These can either be absolute, or relative to the source directory of
your documentation files.
So if your documentation was inside a ``docs/`` directory
and your source code is in an ``example`` directory one level up,
you would configure :confval:`autoapi_dirs` to be::
autoapi_dirs = ['../example']
Now that everything is configured,
AutoAPI will generate documentation when you run Sphinx!
.. code-block:: bash
cd docs/
sphinx-build -b html . _build
or :ref:`customise or remove the API reference index page <customise-index-page>`.

@ -46,10 +46,6 @@ docs =
furo
sphinx
sphinx_design
go =
sphinxcontrib-golangdomain
dotnet =
sphinxcontrib-dotnetdomain
[options.packages.find]
include =

@ -1,195 +0,0 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from https://www.sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SphinxAutoAPI.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SphinxAutoAPI.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/SphinxAutoAPI"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SphinxAutoAPI"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
livehtml:
sphinx-autobuild -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html

@ -1,8 +0,0 @@
## .NET example
This assumes that you have a ``docfx`` executable on your `PATH`.
It also depends on the sphinxcontrib-dotnet domain: https://github.com/readthedocs/sphinxcontrib-dotnetdomain
Currently, this is set up to build the Identity repo from ASP.Net
You should simply be able to run ``make html`` in this directory.

@ -1,33 +0,0 @@
# -*- coding: utf-8 -*-
templates_path = ["_templates"]
source_suffix = ".rst"
master_doc = "index"
project = "dotnetexample"
copyright = "2015, readthedocs"
author = "readthedocs"
version = "0.1"
release = "0.1"
language = "en"
exclude_patterns = ["_build"]
pygments_style = "sphinx"
todo_include_todos = False
html_theme = "sphinx_rtd_theme"
htmlhelp_basename = "dotnetexampledoc"
extensions = ["autoapi.extension", "sphinxcontrib.dotnetdomain"]
autoapi_type = "dotnet"
# Turn this on for debugging
# autoapi_keep_files = True
autoapi_dirs = ["example/Identity/src/"]
import os
SITE_ROOT = os.path.dirname(os.path.realpath(__file__))
DIR = os.path.join(SITE_ROOT, autoapi_dirs[0])
if not os.path.exists(DIR):
os.system(
"git clone https://github.com/aspnet/Identity %s"
% os.path.join(SITE_ROOT, "example/Identity")
)

@ -1 +0,0 @@
git clone https://github.com/aspnet/Identity

@ -1,7 +0,0 @@
Welcome to .Net example's documentation!
========================================
.. toctree::
autoapi/index

@ -1,808 +0,0 @@
{
"items": [
{
"uid": "Microsoft.AspNet.Identity.IUserStore`1",
"parent": "Microsoft.AspNet.Identity",
"syntax": {
"content": "public interface IUserStore<TUser> : IDisposable where TUser : class",
"typeParameters": [
{
"id": "TUser",
"description": "The type encapsulating a user."
}
],
"content.vb": "Public Interface IUserStore(Of TUser As Class) Inherits IDisposable"
},
"children": [
"Microsoft.AspNet.Identity.IUserStore`1.CreateAsync(`0,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.DeleteAsync(`0,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.FindByIdAsync(System.String,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.FindByNameAsync(System.String,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.GetNormalizedUserNameAsync(`0,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.GetUserIdAsync(`0,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.GetUserNameAsync(`0,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.SetNormalizedUserNameAsync(`0,System.String,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.SetUserNameAsync(`0,System.String,CancellationToken)",
"Microsoft.AspNet.Identity.IUserStore`1.UpdateAsync(`0,CancellationToken)"
],
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser)",
"name.vb": "IUserStore(Of TUser)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>",
"id": "IUserStore`1",
"name": "IUserStore<TUser>",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Provides an abstraction for a store which manages user accounts.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 13,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"type": "Interface",
"example": []
},
{
"name": "GetUserIdAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Gets the user identifier for the specified <paramref name=\"user\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 21,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).GetUserIdAsync(TUser, CancellationToken)",
"id": "GetUserIdAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.GetUserIdAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<string> GetUserIdAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{System.String}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the identifier for the specified <paramref name=\"user\" />."
},
"content.vb": "Function GetUserIdAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of String)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user whose identifier should be retrieved."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.GetUserIdAsync(`0,CancellationToken)"
},
{
"name": "GetUserNameAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Gets the user name for the specified <paramref name=\"user\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 29,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).GetUserNameAsync(TUser, CancellationToken)",
"id": "GetUserNameAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.GetUserNameAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<string> GetUserNameAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{System.String}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the name for the specified <paramref name=\"user\" />."
},
"content.vb": "Function GetUserNameAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of String)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user whose name should be retrieved."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.GetUserNameAsync(`0,CancellationToken)"
},
{
"name": "SetUserNameAsync(TUser, String, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Sets the given <paramref name=\"userName\" /> for the specified <paramref name=\"user\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 38,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).SetUserNameAsync(TUser, System.String, CancellationToken)",
"id": "SetUserNameAsync(`0,System.String,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.SetUserNameAsync(TUser, System.String, CancellationToken)",
"syntax": {
"content": "Task SetUserNameAsync(TUser user, string userName, CancellationToken cancellationToken)",
"return": {
"type": "Task",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation."
},
"content.vb": "Function SetUserNameAsync(user As TUser, userName As String, cancellationToken As CancellationToken) As Task",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user whose name should be set."
},
{
"type": "System.String",
"id": "userName",
"description": "The user name to set."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.SetUserNameAsync(`0,System.String,CancellationToken)"
},
{
"name": "GetNormalizedUserNameAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Gets the normalized user name for the specified <paramref name=\"user\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 46,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).GetNormalizedUserNameAsync(TUser, CancellationToken)",
"id": "GetNormalizedUserNameAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.GetNormalizedUserNameAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<string> GetNormalizedUserNameAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{System.String}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the normalized user name for the specified <paramref name=\"user\" />."
},
"content.vb": "Function GetNormalizedUserNameAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of String)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user whose normalized name should be retrieved."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.GetNormalizedUserNameAsync(`0,CancellationToken)"
},
{
"name": "SetNormalizedUserNameAsync(TUser, String, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Sets the given normalized name for the specified <paramref name=\"user\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 55,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).SetNormalizedUserNameAsync(TUser, System.String, CancellationToken)",
"id": "SetNormalizedUserNameAsync(`0,System.String,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.SetNormalizedUserNameAsync(TUser, System.String, CancellationToken)",
"syntax": {
"content": "Task SetNormalizedUserNameAsync(TUser user, string normalizedName, CancellationToken cancellationToken)",
"return": {
"type": "Task",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation."
},
"content.vb": "Function SetNormalizedUserNameAsync(user As TUser, normalizedName As String, cancellationToken As CancellationToken) As Task",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user whose name should be set."
},
{
"type": "System.String",
"id": "normalizedName",
"description": "The normalized name to set."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.SetNormalizedUserNameAsync(`0,System.String,CancellationToken)"
},
{
"name": "CreateAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Creates the specified <paramref name=\"user\" /> in the user store.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 63,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).CreateAsync(TUser, CancellationToken)",
"id": "CreateAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.CreateAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<IdentityResult> CreateAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{Microsoft.AspNet.Identity.IdentityResult}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the <see cref=\"T:Microsoft.AspNet.Identity.IdentityResult\" /> of the creation operation."
},
"content.vb": "Function CreateAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of IdentityResult)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user to create."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.CreateAsync(`0,CancellationToken)"
},
{
"name": "UpdateAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Updates the specified <paramref name=\"user\" /> in the user store.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 71,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).UpdateAsync(TUser, CancellationToken)",
"id": "UpdateAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.UpdateAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<IdentityResult> UpdateAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{Microsoft.AspNet.Identity.IdentityResult}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the <see cref=\"T:Microsoft.AspNet.Identity.IdentityResult\" /> of the update operation."
},
"content.vb": "Function UpdateAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of IdentityResult)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user to update."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.UpdateAsync(`0,CancellationToken)"
},
{
"name": "DeleteAsync(TUser, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Deletes the specified <paramref name=\"user\" /> from the user store.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 79,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).DeleteAsync(TUser, CancellationToken)",
"id": "DeleteAsync(`0,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.DeleteAsync(TUser, CancellationToken)",
"syntax": {
"content": "Task<IdentityResult> DeleteAsync(TUser user, CancellationToken cancellationToken)",
"return": {
"type": "Task{Microsoft.AspNet.Identity.IdentityResult}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the <see cref=\"T:Microsoft.AspNet.Identity.IdentityResult\" /> of the update operation."
},
"content.vb": "Function DeleteAsync(user As TUser, cancellationToken As CancellationToken) As Task(Of IdentityResult)",
"parameters": [
{
"type": "{TUser}",
"id": "user",
"description": "The user to delete."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.DeleteAsync(`0,CancellationToken)"
},
{
"name": "FindByIdAsync(String, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Finds and returns a user, if any, who has the specified <paramref name=\"userId\" />.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 89,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).FindByIdAsync(System.String, CancellationToken)",
"id": "FindByIdAsync(System.String,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.FindByIdAsync(System.String, CancellationToken)",
"syntax": {
"content": "Task<TUser> FindByIdAsync(string userId, CancellationToken cancellationToken)",
"return": {
"type": "Task{{TUser}}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the user matching the specified <paramref name=\"userID\" /> if it exists."
},
"content.vb": "Function FindByIdAsync(userId As String, cancellationToken As CancellationToken) As Task(Of TUser)",
"parameters": [
{
"type": "System.String",
"id": "userId",
"description": "The user ID to search for."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.FindByIdAsync(System.String,CancellationToken)"
},
{
"name": "FindByNameAsync(String, CancellationToken)",
"parent": "Microsoft.AspNet.Identity.IUserStore`1",
"href": "Microsoft.AspNet.Identity.IUserStore`1.yml",
"assemblies": [
"Microsoft.AspNet.Identity"
],
"namespace": "Microsoft.AspNet.Identity",
"summary": "Finds and returns a user, if any, who has the specified normalized user name.",
"source": {
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"startLine": 99,
"remote": {
"repo": "https://github.com/aspnet/apidocs",
"path": "aspnet/identity/src/Microsoft.AspNet.Identity/IUserStore.cs",
"branch": "master"
}
},
"fullName.vb": "Microsoft.AspNet.Identity.IUserStore(Of TUser).FindByNameAsync(System.String, CancellationToken)",
"id": "FindByNameAsync(System.String,CancellationToken)",
"langs": [
"csharp",
"vb"
],
"fullName": "Microsoft.AspNet.Identity.IUserStore<TUser>.FindByNameAsync(System.String, CancellationToken)",
"syntax": {
"content": "Task<TUser> FindByNameAsync(string normalizedUserName, CancellationToken cancellationToken)",
"return": {
"type": "Task{{TUser}}",
"description": "The <see cref=\"!:Task\" /> that represents the asynchronous operation, containing the user matching the specified <paramref name=\"userID\" /> if it exists."
},
"content.vb": "Function FindByNameAsync(normalizedUserName As String, cancellationToken As CancellationToken) As Task(Of TUser)",
"parameters": [
{
"type": "System.String",
"id": "normalizedUserName",
"description": "The normalized user name to search for."
},
{
"type": "CancellationToken",
"id": "cancellationToken",
"description": "The used to propagate notifications that the operation should be canceled."
}
]
},
"type": "Method",
"example": [],
"uid": "Microsoft.AspNet.Identity.IUserStore`1.FindByNameAsync(System.String,CancellationToken)"
}
],
"references": [
{
"fullName": "Microsoft.AspNet.Identity",
"isExternal": false,
"uid": "Microsoft.AspNet.Identity",
"name": "Microsoft.AspNet.Identity"
},
{
"fullName": "TUser",
"isExternal": false,
"uid": "{TUser}",
"name": "TUser"
},
{
"fullName": "CancellationToken",
"isExternal": true,
"name": "CancellationToken",
"parent": null,
"uid": "CancellationToken"
},
{
"definition": "Task`1",
"uid": "Task{System.String}",
"parent": null,
"spec.vb": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "(Of ",
"name": "(Of "
},
{
"fullName": "System.String",
"uid": "System.String",
"name": "String",
"isExternal": true
},
{
"fullName": ")",
"name": ")"
}
],
"fullName.vb": "Task(Of System.String)",
"name.vb": "Task(Of String)",
"fullName": "Task<System.String>",
"spec.csharp": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "<",
"name": "<"
},
{
"fullName": "System.String",
"uid": "System.String",
"name": "String",
"isExternal": true
},
{
"fullName": ">",
"name": ">"
}
],
"name": "Task<String>"
},
{
"fullName": null,
"isExternal": false,
"uid": null,
"name": null
},
{
"name": "Task<>",
"parent": null,
"spec.vb": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "(Of ",
"name": "(Of "
},
{
"fullName": null,
"name": null
},
{
"fullName": ")",
"name": ")"
}
],
"fullName.vb": "Task(Of )",
"name.vb": "Task(Of )",
"uid": "Task`1",
"fullName": "Task<>",
"spec.csharp": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "<",
"name": "<"
},
{
"fullName": null,
"name": null
},
{
"fullName": ">",
"name": ">"
}
],
"isExternal": true
},
{
"fullName": "System.String",
"isExternal": true,
"name": "String",
"parent": "System",
"uid": "System.String"
},
{
"fullName": "Task",
"isExternal": true,
"name": "Task",
"parent": null,
"uid": "Task"
},
{
"fullName": "System",
"isExternal": false,
"uid": "System",
"name": "System"
},
{
"definition": "Task`1",
"uid": "Task{Microsoft.AspNet.Identity.IdentityResult}",
"parent": null,
"href": "Microsoft.AspNet.Identity.IdentityResult.yml",
"spec.vb": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "(Of ",
"name": "(Of "
},
{
"fullName": "Microsoft.AspNet.Identity.IdentityResult",
"href": "Microsoft.AspNet.Identity.IdentityResult.yml",
"uid": "Microsoft.AspNet.Identity.IdentityResult",
"name": "IdentityResult"
},
{
"fullName": ")",
"name": ")"
}
],
"fullName.vb": "Task(Of Microsoft.AspNet.Identity.IdentityResult)",
"name.vb": "Task(Of IdentityResult)",
"fullName": "Task<Microsoft.AspNet.Identity.IdentityResult>",
"spec.csharp": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "<",
"name": "<"
},
{
"fullName": "Microsoft.AspNet.Identity.IdentityResult",
"href": "Microsoft.AspNet.Identity.IdentityResult.yml",
"uid": "Microsoft.AspNet.Identity.IdentityResult",
"name": "IdentityResult"
},
{
"fullName": ">",
"name": ">"
}
],
"name": "Task<IdentityResult>"
},
{
"definition": "Task`1",
"uid": "Task{{TUser}}",
"parent": null,
"spec.vb": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "(Of ",
"name": "(Of "
},
{
"fullName": "TUser",
"name": "TUser"
},
{
"fullName": ")",
"name": ")"
}
],
"fullName.vb": "Task(Of TUser)",
"name.vb": "Task(Of TUser)",
"fullName": "Task<TUser>",
"spec.csharp": [
{
"fullName": "Task",
"uid": "Task`1",
"name": "Task",
"isExternal": true
},
{
"fullName": "<",
"name": "<"
},
{
"fullName": "TUser",
"name": "TUser"
},
{
"fullName": ">",
"name": ">"
}
],
"name": "Task<TUser>"
}
]
}

@ -1,100 +0,0 @@
{
"funcs": [
{
"name": "CopyFuncs",
"doc": "CopyFuncs produces a json-annotated array of Func objects from an array of GoDoc Func objects.\n",
"packageName": "main",
"packageImportPath": "example",
"recv": "",
"orig": ""
},
{
"name": "CopyValues",
"doc": "CopyValues produces a json-annotated array of Value objects from an array of GoDoc Value objects.\n",
"packageName": "main",
"packageImportPath": "example",
"recv": "",
"orig": ""
}
],
"name": "main",
"vars": [],
"doc": "",
"notes": {},
"bugs": null,
"filenames": [
"example/godocjson.go"
],
"importPath": "example",
"consts": [],
"imports": [
"encoding/json",
"fmt",
"go/doc",
"go/parser",
"go/token",
"os"
],
"type": "package",
"types": [
{
"funcs": [],
"name": "Func",
"vars": [],
"doc": "Func represents a function declaration.\n",
"packageName": "main",
"packageImportPath": "example",
"consts": [],
"methods": []
},
{
"funcs": [],
"name": "Note",
"vars": [],
"doc": "Note represents a note comment.\n",
"packageName": "main",
"packageImportPath": "example",
"consts": [],
"methods": []
},
{
"funcs": [
{
"name": "CopyPackage",
"doc": "CopyPackage produces a json-annotated Package object from a GoDoc Package object.\n",
"packageName": "main",
"packageImportPath": "example",
"recv": "",
"orig": ""
}
],
"name": "Package",
"vars": [],
"doc": "Package represents a package declaration.\n",
"packageName": "main",
"packageImportPath": "example",
"consts": [],
"methods": []
},
{
"funcs": [],
"name": "Type",
"vars": [],
"doc": "Type represents a type declaration.\n",
"packageName": "main",
"packageImportPath": "example",
"consts": [],
"methods": []
},
{
"funcs": [],
"name": "Value",
"vars": [],
"doc": "Value represents a value declaration.\n",
"packageName": "main",
"packageImportPath": "example",
"consts": [],
"methods": []
}
]
}

@ -1,297 +0,0 @@
[
{
"comment": "/**\n * Creates an instance of Circle.\n *\n * @constructor\n * @this {Circle}\n * @param {number} r The desired radius of the circle.\n */",
"kind": "class",
"description": "Creates an instance of Circle.",
"this": "{Circle}",
"see": [],
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
134,
251
],
"code": {
"node": "<Object>",
"paramnames": [
"r"
],
"type": "function",
"id": "astnode194706439",
"name": "Circle"
},
"lineno": 8,
"filename": "jsdoc-example.js"
},
"params": [
{
"description": "The desired radius of the circle.",
"nullable": "undefined",
"type": {
"names": [
"number"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined",
"name": "r"
}
],
"longname": "Circle",
"scope": "global",
"name": "Circle"
},
{
"comment": "/** @private */",
"kind": "member",
"name": "radius",
"memberof": "{Circle}",
"access": "private",
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
175,
190
],
"code": {
"node": "<Object>",
"type": "NAME",
"id": "astnode1413378318",
"value": "r",
"name": "this.radius"
},
"lineno": 9,
"filename": "jsdoc-example.js"
},
"longname": "{Circle}#radius",
"scope": "instance"
},
{
"comment": "/** @private */",
"kind": "member",
"name": "circumference",
"memberof": "{Circle}",
"access": "private",
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
212,
248
],
"code": {
"node": "<Object>",
"type": "MUL",
"id": "astnode1157058691",
"value": "MUL",
"name": "this.circumference"
},
"lineno": 10,
"filename": "jsdoc-example.js"
},
"longname": "{Circle}#circumference",
"scope": "instance"
},
{
"comment": "/**\n * Creates a new Circle from a diameter.\n *\n * @param {number} d The desired diameter of the circle.\n * @return {Circle} The new Circle object.\n */",
"kind": "function",
"description": "Creates a new Circle from a diameter.",
"memberof": "Circle",
"returns": [
{
"description": "The new Circle object.",
"nullable": "undefined",
"type": {
"names": [
"Circle"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined"
}
],
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
406,
474
],
"code": {
"node": "<Object>",
"paramnames": [
"d"
],
"name": "Circle.fromDiameter",
"value": "FUNCTION",
"type": "FUNCTION",
"id": "astnode398110318"
},
"lineno": 19,
"filename": "jsdoc-example.js"
},
"params": [
{
"description": "The desired diameter of the circle.",
"nullable": "undefined",
"type": {
"names": [
"number"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined",
"name": "d"
}
],
"longname": "Circle.fromDiameter",
"scope": "static",
"name": "fromDiameter"
},
{
"comment": "/**\n * Calculates the circumference of the Circle.\n *\n * @deprecated\n * @this {Circle}\n * @return {number} The circumference of the circle.\n */",
"kind": "function",
"description": "Calculates the circumference of the Circle.",
"this": "{Circle}",
"deprecated": true,
"longname": "Circle#calculateCircumference",
"returns": [
{
"description": "The circumference of the circle.",
"nullable": "undefined",
"type": {
"names": [
"number"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined"
}
],
"see": [],
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
622,
717
],
"code": {
"node": "<Object>",
"paramnames": [],
"name": "Circle.prototype.calculateCircumference",
"value": "FUNCTION",
"type": "FUNCTION",
"id": "astnode1582785598"
},
"lineno": 30,
"filename": "jsdoc-example.js"
},
"memberof": "Circle",
"scope": "instance",
"name": "calculateCircumference"
},
{
"comment": "/**\n * Returns the pre-computed circumference of the Circle.\n *\n * @this {Circle}\n * @return {number} The circumference of the circle.\n */",
"kind": "function",
"description": "Returns the pre-computed circumference of the Circle.",
"this": "{Circle}",
"memberof": "Circle",
"returns": [
{
"description": "The circumference of the circle.",
"nullable": "undefined",
"type": {
"names": [
"number"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined"
}
],
"see": [],
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
860,
942
],
"code": {
"node": "<Object>",
"paramnames": [],
"name": "Circle.prototype.getCircumference",
"value": "FUNCTION",
"type": "FUNCTION",
"id": "astnode2134991632"
},
"lineno": 40,
"filename": "jsdoc-example.js"
},
"longname": "Circle#getCircumference",
"scope": "instance",
"name": "getCircumference"
},
{
"comment": "/**\n * Find a String representation of the Circle.\n *\n * @override\n * @this {Circle}\n * @return {string} Human-readable representation of this Circle.\n */",
"kind": "function",
"description": "Find a String representation of the Circle.",
"tags": [
{
"originalTitle": "override",
"text": "",
"title": "override"
}
],
"this": "{Circle}",
"memberof": "Circle",
"returns": [
{
"description": "Human-readable representation of this Circle.",
"nullable": "undefined",
"type": {
"names": [
"string"
]
},
"defaultvalue": "undefined",
"variable": "undefined",
"optional": "undefined"
}
],
"see": [],
"meta": {
"path": "/Users/eric/projects/sphinx-autoapi/tests/jsexample/example",
"range": [
1101,
1210
],
"code": {
"node": "<Object>",
"paramnames": [],
"name": "Circle.prototype.toString",
"value": "FUNCTION",
"type": "FUNCTION",
"id": "astnode1822383117"
},
"lineno": 51,
"filename": "jsdoc-example.js"
},
"longname": "Circle#toString",
"scope": "instance",
"name": "toString"
},
{
"files": [
"/Users/eric/projects/sphinx-autoapi/tests/jsexample/example/jsdoc-example.js"
],
"kind": "package",
"description": "undefined",
"version": "undefined",
"longname": "package:undefined",
"licenses": "undefined",
"name": "undefined"
}
]

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
templates_path = ["_templates"]
source_suffix = ".rst"
master_doc = "index"
project = "goexample"
copyright = "2015, readthedocs"
author = "readthedocs"
version = "0.1"
release = "0.1"
language = "en"
exclude_patterns = ["_build"]
pygments_style = "sphinx"
todo_include_todos = False
html_theme = "alabaster"
html_static_path = ["_static"]
htmlhelp_basename = "goexampledoc"
extensions = ["autoapi.extension", "sphinxcontrib.golangdomain"]
autoapi_type = "go"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.go"

@ -1,174 +0,0 @@
package main
import (
"encoding/json"
"fmt"
"go/doc"
"go/parser"
"go/token"
"os"
)
// Func represents a function declaration.
type Func struct {
Doc string `json:"doc"`
Name string `json:"name"`
PackageName string `json:"packageName"`
PackageImportPath string `json:"packageImportPath"`
// Decl *ast.FuncDecl
// methods
// (for functions, these fields have the respective zero value)
Recv string `json:"recv"` // actual receiver "T" or "*T"
Orig string `json:"orig"` // original receiver "T" or "*T"
// Level int // embedding level; 0 means not embedded
}
// Package represents a package declaration.
type Package struct {
Type string `json:"type"`
Doc string `json:"doc"`
Name string `json:"name"`
ImportPath string `json:"importPath"`
Imports []string `json:"imports"`
Filenames []string `json:"filenames"`
Notes map[string][]*Note `json:"notes"`
// DEPRECATED. For backward compatibility Bugs is still populated,
// but all new code should use Notes instead.
Bugs []string `json:"bugs"`
// declarations
Consts []*Value `json:"consts"`
Types []*Type `json:"types"`
Vars []*Value `json:"vars"`
Funcs []*Func `json:"funcs"`
}
// Note represents a note comment.
type Note struct {
Pos token.Pos `json:"pos"`
End token.Pos `json:"end"` // position range of the comment containing the marker
UID string `json:"uid"` // uid found with the marker
Body string `json:"body"` // note body text
}
// Type represents a type declaration.
type Type struct {
PackageName string `json:"packageName"`
PackageImportPath string `json:"packageImportPath"`
Doc string `json:"doc"`
Name string `json:"name"`
// Decl *ast.GenDecl
// associated declarations
Consts []*Value `json:"consts"` // sorted list of constants of (mostly) this type
Vars []*Value `json:"vars"` // sorted list of variables of (mostly) this type
Funcs []*Func `json:"funcs"` // sorted list of functions returning this type
Methods []*Func `json:"methods"` // sorted list of methods (including embedded ones) of this type
}
// Value represents a value declaration.
type Value struct {
PackageName string `json:"packageName"`
PackageImportPath string `json:"packageImportPath"`
Doc string `json:"doc"`
Names []string `json:"names"` // var or const names in declaration order
// Decl *ast.GenDecl
}
// CopyFuncs produces a json-annotated array of Func objects from an array of GoDoc Func objects.
func CopyFuncs(f []*doc.Func, packageName string, packageImportPath string) []*Func {
newFuncs := make([]*Func, len(f))
for i, n := range f {
newFuncs[i] = &Func{
Doc: n.Doc,
Name: n.Name,
PackageName: packageName,
PackageImportPath: packageImportPath,
Orig: n.Orig,
Recv: n.Recv,
}
}
return newFuncs
}
// CopyValues produces a json-annotated array of Value objects from an array of GoDoc Value objects.
func CopyValues(c []*doc.Value, packageName string, packageImportPath string) []*Value {
newConsts := make([]*Value, len(c))
for i, c := range c {
newConsts[i] = &Value{
Doc: c.Doc,
Names: c.Names,
PackageName: packageName,
PackageImportPath: packageImportPath,
}
}
return newConsts
}
// CopyPackage produces a json-annotated Package object from a GoDoc Package object.
func CopyPackage(pkg *doc.Package) Package {
newPkg := Package{
Type: "package",
Doc: pkg.Doc,
Name: pkg.Name,
ImportPath: pkg.ImportPath,
Imports: pkg.Imports,
Filenames: pkg.Filenames,
Bugs: pkg.Bugs,
}
newPkg.Notes = map[string][]*Note{}
for key, value := range pkg.Notes {
notes := make([]*Note, len(value))
for i, note := range value {
notes[i] = &Note{
Pos: note.Pos,
End: note.End,
UID: note.UID,
Body: note.Body,
}
}
newPkg.Notes[key] = notes
}
newPkg.Consts = CopyValues(pkg.Consts, pkg.Name, pkg.ImportPath)
newPkg.Funcs = CopyFuncs(pkg.Funcs, pkg.Name, pkg.ImportPath)
newPkg.Types = make([]*Type, len(pkg.Types))
for i, t := range pkg.Types {
newPkg.Types[i] = &Type{
Name: t.Name,
PackageName: pkg.Name,
PackageImportPath: pkg.ImportPath,
Consts: CopyValues(t.Consts, pkg.Name, pkg.ImportPath),
Doc: t.Doc,
Funcs: CopyFuncs(t.Funcs, pkg.Name, pkg.ImportPath),
Methods: CopyFuncs(t.Methods, pkg.Name, pkg.ImportPath),
Vars: CopyValues(t.Vars, pkg.Name, pkg.ImportPath),
}
}
newPkg.Vars = CopyValues(pkg.Vars, pkg.Name, pkg.ImportPath)
return newPkg
}
func main() {
directories := os.Args[1:]
for _, dir := range directories {
fileSet := token.NewFileSet()
pkgs, firstError := parser.ParseDir(fileSet, dir, nil, parser.ParseComments|parser.AllErrors)
if firstError != nil {
panic(firstError)
}
for _, pkg := range pkgs {
docPkg := doc.New(pkg, dir, 0)
cleanedPkg := CopyPackage(docPkg)
pkgJSON, err := json.MarshalIndent(cleanedPkg, "", " ")
if err != nil {
panic(err)
}
fmt.Printf("%s\n", pkgJSON)
}
}
}

@ -1,13 +0,0 @@
Welcome to Go example's documentation!
======================================
.. toctree::
autoapi/index
Contents:
.. toctree::
:maxdepth: 2

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
templates_path = ["_templates"]
source_suffix = ".rst"
master_doc = "index"
project = "jsexample"
copyright = "2015, readthedocs"
author = "readthedocs"
version = "0.1"
release = "0.1"
language = "en"
exclude_patterns = ["_build"]
pygments_style = "sphinx"
todo_include_todos = False
html_theme = "alabaster"
html_static_path = ["_static"]
htmlhelp_basename = "jsexampledoc"
extensions = ["autoapi.extension"]
autoapi_type = "javascript"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.js"

@ -1,53 +0,0 @@
/**
* Creates an instance of Circle.
*
* @constructor
* @this {Circle}
* @param {number} r The desired radius of the circle.
*/
function Circle(r) {
/** @private */ this.radius = r;
/** @private */ this.circumference = 2 * Math.PI * r;
}
/**
* Creates a new Circle from a diameter.
*
* @param {number} d The desired diameter of the circle.
* @return {Circle} The new Circle object.
*/
Circle.fromDiameter = function (d) {
return new Circle(d / 2);
};
/**
* Calculates the circumference of the Circle.
*
* @deprecated
* @this {Circle}
* @return {number} The circumference of the circle.
*/
Circle.prototype.calculateCircumference = function () {
return 2 * Math.PI * this.radius;
};
/**
* Returns the pre-computed circumference of the Circle.
*
* @this {Circle}
* @return {number} The circumference of the circle.
*/
Circle.prototype.getCircumference = function () {
return this.circumference;
};
/**
* Find a String representation of the Circle.
*
* @override
* @this {Circle}
* @return {string} Human-readable representation of this Circle.
*/
Circle.prototype.toString = function () {
return "A Circle object with radius of " + this.radius + ".";
};

@ -1,21 +0,0 @@
Welcome to jsexample's documentation!
=====================================
.. toctree::
autoapi/index
Contents:
.. toctree::
:maxdepth: 2
Indices and tables
==================
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

@ -16,6 +16,5 @@ html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.intersphinx", "sphinx.ext.autodoc", "autoapi.extension"]
intersphinx_mapping = {"python": ("https://docs.python.org/3.10", None)}
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"

@ -15,6 +15,5 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_python_class_content = "both"
autoapi_keep_files = True

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "py3implicitnamespacedoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["namespace"]
autoapi_file_pattern = "*.py"
autoapi_python_use_implicit_namespaces = True

@ -15,6 +15,5 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension", "sphinx.ext.napoleon"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_python_class_content = "both"
autoapi_options = [

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_python_class_content = "both"
autoapi_options = [

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"
autoapi_python_class_content = "both"

@ -15,6 +15,5 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_patterns = ["*.pyi", "*.py"]

@ -15,5 +15,4 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]

@ -15,6 +15,5 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pypackagecomplexdoc"
extensions = ["autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["complex"]
autoapi_file_pattern = "*.py"

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pypackageexampledoc"
extensions = ["autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"
autoapi_keep_files = True

@ -15,7 +15,6 @@ todo_include_todos = False
html_theme = "alabaster"
htmlhelp_basename = "pyexampledoc"
extensions = ["sphinx.ext.autodoc", "autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"
autoapi_options = ["members", "undoc-members", "special-members"]

@ -16,7 +16,6 @@ html_theme = "alabaster"
html_static_path = ["_static"]
htmlhelp_basename = "pyexampledoc"
extensions = ["autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"
autoapi_template_dir = "template_overrides"

@ -1,190 +0,0 @@
"""Test .NET autoapi domain"""
from unittest import mock
from unittest.mock import patch
from autoapi.mappers import dotnet
class MockConfig:
def __getattr__(self, key):
attrs = {
"autoapi_dirs": ["/tmp/autoapi/tmp"],
"autoapi_root": "/tmp/autoapi/root",
}
return attrs.get(key, None)
class MockApplication:
config = MockConfig()
def warn(self, *args, **kwargs):
pass
class TestDotNetSphinxMapper:
def test_create_class(self):
"""Test .NET class instance creation helper"""
dom = dotnet.DotNetSphinxMapper(MockApplication())
def _create_class(data):
return list(dom.create_class(data))[0]
cls = _create_class({"id": "Foo.Bar", "type": "Namespace"})
assert isinstance(cls, dotnet.DotNetNamespace)
cls = _create_class({"id": "Foo.Bar", "type": "Class"})
assert isinstance(cls, dotnet.DotNetClass)
cls = _create_class({"id": "Foo.Bar", "type": "Property"})
assert isinstance(cls, dotnet.DotNetProperty)
cls = _create_class({"id": "Foo.Bar", "type": "Method"})
assert isinstance(cls, dotnet.DotNetMethod)
cls = _create_class({"id": "Foo.Bar", "type": "Enum"})
assert isinstance(cls, dotnet.DotNetEnum)
cls = _create_class({"id": "Foo.Bar", "type": "Constructor"})
assert isinstance(cls, dotnet.DotNetConstructor)
cls = _create_class({"id": "Foo.Bar", "type": "Struct"})
assert isinstance(cls, dotnet.DotNetStruct)
cls = _create_class({"id": "Foo.Bar", "type": "Interface"})
assert isinstance(cls, dotnet.DotNetInterface)
cls = _create_class({"id": "Foo.Bar", "type": "Delegate"})
assert isinstance(cls, dotnet.DotNetDelegate)
cls = _create_class({"id": "Foo.Bar", "type": "Field"})
assert isinstance(cls, dotnet.DotNetField)
cls = _create_class({"id": "Foo.Bar", "type": "Event"})
assert isinstance(cls, dotnet.DotNetEvent)
def test_create_class_with_children(self):
dom = dotnet.DotNetSphinxMapper(MockApplication())
def _create_class(data):
return list(dom.create_class(data))[0]
cls = _create_class(
{
"id": "Foo.Bar",
"type": "Class",
"items": [{"id": "Foo.Bar.Baz", "type": "Method"}],
}
)
assert isinstance(cls, dotnet.DotNetClass)
assert cls.item_map == {}
@patch("subprocess.check_output", lambda foo: foo)
def test_get_objects(self):
"""Test basic get objects"""
objs = []
def _mock_find(self, patterns, **kwargs):
return {"items": ["foo", "bar"]}
def _mock_read(self, path):
return {
"items": [
{"id": "Foo.Bar", "name": "Foo", "type": "property"},
{"id": "Foo.Bar2", "name": "Bar", "type": "property"},
],
"id": "Foo.Bar",
"type": "Class",
"summary": path,
}
with patch("autoapi.mappers.dotnet.DotNetSphinxMapper.find_files", _mock_find):
with patch(
"autoapi.mappers.dotnet.DotNetSphinxMapper.read_file", _mock_read
):
dom = dotnet.DotNetSphinxMapper(MockApplication())
dom.load("", "", "")
dom.map()
objs = dom.objects
assert len(objs) == 2
assert objs["Foo.Bar"].id == "Foo.Bar"
assert objs["Foo.Bar"].name == "Foo.Bar"
assert objs["Foo.Bar2"].id == "Foo.Bar2"
assert objs["Foo.Bar2"].name == "Foo.Bar2"
class TestDotNetPythonMapper:
def test_xml_parse(self):
"""XML doc comment parsing"""
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'This is an example comment <see cref="FOO" />'
)
assert ret == "This is an example comment :any:`FOO`"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'This is an example comment <see cref="!:FOO" />'
)
assert ret == "This is an example comment FOO"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'This is an example comment <see cref="N:FOO">inner foo</see>'
)
assert ret == "This is an example comment :dn:ns:`FOO`"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'Test <see cref="P:FOO" /> and <see cref="E:BAR">Blah</see>'
)
assert ret == "Test :dn:prop:`FOO` and :dn:event:`BAR`"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'This is an example comment <paramref name="FOO" />'
)
assert ret == "This is an example comment ``FOO``"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'This is an example comment <typeparamref name="FOO" />'
)
assert ret == "This is an example comment ``FOO``"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'With surrounding characters s<see cref="FOO" />s'
)
assert ret == r"With surrounding characters s :any:`FOO`\s"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'With surrounding characters s<paramref name="FOO" />s'
)
assert ret == r"With surrounding characters s ``FOO``\s"
def test_xml_transform_escape(self):
"""XML transform escaping"""
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'Foo <see cref="Foo`1" /> Bar'
)
assert ret == "Foo :any:`Foo\\`1` Bar"
ret = dotnet.DotNetPythonMapper.transform_doc_comments(
'No space before<see cref="M:Foo`1" />or after'
)
assert ret == "No space before :dn:meth:`Foo\\`1`\\or after"
def test_parsing_obj(self):
"""Parse out object, test for transforms, etc"""
obj = {
"uid": "Foo`1",
"name": "Foo<TUser>",
"summary": 'Test parsing <see cref="Bar" />',
"syntax": {
"parameters": [
{
"id": "a",
"type": "{TUser}",
"description": 'Test <see cref="TUser" />',
}
],
"return": {
"type": "Bar",
"description": (
'Test references <see cref="Bar" /> '
'and paramrefs <paramref name="a" />'
),
},
},
}
mapped = dotnet.DotNetPythonMapper(obj, app=mock.MagicMock(), jinja_env=None)
expected = {"name": "a", "type": "{TUser}", "desc": "Test :any:`TUser`"}
assert mapped.parameters[0] == expected
assert (
mapped.returns["description"]
== "Test references :any:`Bar` and paramrefs ``a``"
)

@ -1,16 +1,9 @@
import io
import json
import os
import sys
import shutil
from contextlib import contextmanager
from unittest.mock import patch
import pytest
import sphinx
from sphinx.application import Sphinx
from sphinx.errors import ExtensionError
@contextmanager
@ -41,64 +34,6 @@ class LanguageIntegrationTests:
assert test_string in text
class TestJavaScript(LanguageIntegrationTests):
def _js_read(self, path):
return json.load(open("../fixtures/javascript.json"))
@patch("autoapi.mappers.javascript.JavaScriptSphinxMapper.read_file", _js_read)
def test_integration(self):
self._run_test(
"jsexample",
"_build/text/autoapi/Circle/index.txt",
"Creates an instance of Circle",
)
@pytest.mark.skipif(
sphinx.version_info >= (3,),
reason="golangdomain extension does not support sphinx >=3",
)
class TestGo(LanguageIntegrationTests):
def _go_read(self, path, **kwargs):
return json.load(open("../fixtures/go.json"))
@patch("autoapi.mappers.go.GoSphinxMapper.read_file", _go_read)
def test_integration(self):
self._run_test(
"goexample",
"_build/text/autoapi/main/index.txt",
"CopyFuncs produces a json-annotated array of Func objects",
)
@pytest.mark.skipif(
sphinx.version_info >= (3,),
reason="dotnetdomain extension does not support sphinx >=3",
)
class TestDotNet(LanguageIntegrationTests):
def _dotnet_read(self, path):
return json.load(open("../fixtures/dotnet.json"))
# Mock this because it's slow otherwise
def _dotnet_load(self, patterns, dirs, ignore=()):
data = self.read_file(path="inmem")
self.paths["inmem"] = data
@staticmethod
def _dotnet_finished(app, exception):
pass
@patch("autoapi.mappers.dotnet.DotNetSphinxMapper.load", _dotnet_load)
@patch("autoapi.mappers.dotnet.DotNetSphinxMapper.read_file", _dotnet_read)
@patch("autoapi.mappers.dotnet.DotNetSphinxMapper.build_finished", _dotnet_finished)
def test_integration(self):
self._run_test(
"dotnetexample",
"_build/text/autoapi/Microsoft/AspNet/Identity/IUserStore-TUser/index.txt",
"Provides an abstraction for a store which manages user accounts.",
)
class TestIntegration(LanguageIntegrationTests):
def test_template_overrides(self):
self._run_test(
@ -119,54 +54,3 @@ class TestTOCTree(LanguageIntegrationTests):
self._run_test(
"toctreeexample", "_build/text/index.txt", '* "example_function()"'
)
class TestExtensionErrors:
@pytest.fixture(autouse=True)
def unload_go_and_dotnet_libraries(self):
# unload dotnet and golang domain libraries, because they may be imported before
for mod_name in ("sphinxcontrib.dotnetdomain", "sphinxcontrib.golangdomain"):
try:
del sys.modules[mod_name]
except KeyError:
pass
@pytest.mark.parametrize(
"proj_name, override_conf, err_msg",
[
(
"toctreeexample",
{"autoapi_type": "INVALID VALUE"},
(
"Invalid autoapi_type setting, following values are "
'allowed: "dotnet", "go", "javascript", "python"'
),
),
(
"goexample",
{"autoapi_type": "go", "extensions": ["autoapi.extension"]},
(
"AutoAPI of type `go` requires following "
"packages to be installed and included in extensions list: "
"sphinxcontrib.golangdomain (available as "
'"sphinxcontrib-golangdomain" on PyPI)'
),
),
(
"dotnetexample",
{"autoapi_type": "dotnet", "extensions": ["autoapi.extension"]},
(
"AutoAPI of type `dotnet` requires following "
"packages to be installed and included in extensions list: "
"sphinxcontrib.dotnetdomain (available as "
'"sphinxcontrib-dotnetdomain" on PyPI)'
),
),
],
)
def test_extension_setup_errors(self, proj_name, override_conf, err_msg):
with pytest.raises(ExtensionError) as err_info:
with sphinx_build(proj_name, override_conf):
pass
assert str(err_info.value) == err_msg

@ -1,145 +0,0 @@
# coding=utf8
"""Test .NET autoapi objects"""
from collections import namedtuple
from unittest import mock
import os
from jinja2 import Environment, FileSystemLoader
from autoapi.mappers import dotnet
from autoapi.mappers import python
from autoapi.settings import TEMPLATE_DIR
class TestDotNetObject:
def test_type(self):
"""Test types of some of the objects"""
obj = dotnet.DotNetNamespace({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "namespace"
assert obj.ref_type == "namespace"
assert obj.ref_directive == "ns"
obj = dotnet.DotNetMethod({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "method"
assert obj.ref_type == "method"
assert obj.ref_directive == "meth"
obj = dotnet.DotNetProperty({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "property"
assert obj.ref_type == "property"
assert obj.ref_directive == "prop"
obj = dotnet.DotNetEnum({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "enum"
assert obj.ref_type == "enumeration"
assert obj.ref_directive == "enum"
obj = dotnet.DotNetStruct({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "struct"
assert obj.ref_type == "structure"
assert obj.ref_directive == "struct"
obj = dotnet.DotNetConstructor({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "constructor"
assert obj.ref_type == "constructor"
assert obj.ref_directive == "ctor"
obj = dotnet.DotNetInterface({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "interface"
assert obj.ref_type == "interface"
assert obj.ref_directive == "iface"
obj = dotnet.DotNetDelegate({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "delegate"
assert obj.ref_type == "delegate"
assert obj.ref_directive == "del"
obj = dotnet.DotNetClass({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "class"
assert obj.ref_type == "class"
assert obj.ref_directive == "cls"
obj = dotnet.DotNetField({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "field"
assert obj.ref_type == "field"
assert obj.ref_directive == "field"
obj = dotnet.DotNetEvent({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.type == "event"
assert obj.ref_type == "event"
assert obj.ref_directive == "event"
def test_names(self):
"""Test names of objects"""
obj = dotnet.DotNetNamespace({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert obj.name == "Foo.Bar"
assert obj.short_name == "Bar"
obj = dotnet.DotNetNamespace(
{"id": "Foo.Bar.Something`1"}, jinja_env=None, app=None
)
assert obj.name == "Foo.Bar.Something`1"
assert obj.short_name == "Something`1"
def test_namespace_namespace(self):
"""Namespace parent resolution"""
ns = dotnet.DotNetNamespace({"id": "Foo.Bar.Widgets"}, jinja_env=None, app=None)
assert ns.namespace == "Foo.Bar"
ns = dotnet.DotNetNamespace({"id": "Foo.Bar"}, jinja_env=None, app=None)
assert ns.namespace == "Foo"
ns = dotnet.DotNetNamespace({"id": "Foo"}, jinja_env=None, app=None)
assert ns.namespace is None
def test_class_namespace(self):
"""Class parent resolution"""
cls = dotnet.DotNetClass(
dict(id="Foo.Bar.Widget", type="class"),
jinja_env=None,
app=None,
)
assert cls.namespace == "Foo.Bar"
cls = dotnet.DotNetClass(
dict(id="Foo.Bar", type="class"), jinja_env=None, app=None
)
assert cls.namespace == "Foo"
cls = dotnet.DotNetClass(dict(id="Foo", type="class"), jinja_env=None, app=None)
assert cls.namespace is None
def test_filename(self):
"""Object file name"""
cls = dotnet.DotNetClass({"id": "Foo.Bar.Widget"}, jinja_env=None, app=None)
assert cls.pathname == os.path.join("Foo", "Bar", "Widget")
cls = dotnet.DotNetClass({"id": "Foo.Bar.Widget<T>"}, jinja_env=None, app=None)
assert cls.pathname == os.path.join("Foo", "Bar", "Widget-T")
cls = dotnet.DotNetClass(
{"id": "Foo.Bar.Widget<T>(TFoo)"}, jinja_env=None, app=None
)
assert cls.pathname == os.path.join("Foo", "Bar", "Widget-T")
cls = dotnet.DotNetClass(
{"id": "Foo.Foo-Bar.Widget<T>(TFoo)"}, jinja_env=None, app=None
)
assert cls.pathname == os.path.join("Foo", "FooBar", "Widget-T")
cls = dotnet.DotNetClass({"id": "Foo.Bär"}, jinja_env=None, app=None)
assert cls.pathname == os.path.join("Foo", "Bar")
cls = dotnet.DotNetClass({"id": "Ащщ.юИфк"}, jinja_env=None, app=None)
assert cls.pathname == os.path.join("Ashchshch", "yuIfk")
def test_rendered_class_escaping(self):
"""Rendered class escaping"""
jinja_env = Environment(loader=FileSystemLoader([TEMPLATE_DIR]))
cls = dotnet.DotNetClass(
{"id": "Foo.Bar`1", "inheritance": ["Foo.Baz`1"]},
jinja_env=jinja_env,
app=mock.MagicMock(),
)
assert "* :dn:cls:`Foo.Baz\\`1`\n" in cls.render()
def test_include_path(self):
"""Include path"""
cls = dotnet.DotNetClass({"id": "Foo.Bar.Widget"}, jinja_env=None, app=None)
assert cls.include_path == "/autoapi/Foo/Bar/Widget/index"
cls = dotnet.DotNetClass({"id": "Foo.Bar.Widget"}, jinja_env=None, app=None)
cls.url_root = "/autofoo"
assert cls.include_path == "/autofoo/Foo/Bar/Widget/index"

@ -16,6 +16,5 @@ html_theme = "alabaster"
html_static_path = ["_static"]
htmlhelp_basename = "pyexampledoc"
extensions = ["autoapi.extension"]
autoapi_type = "python"
autoapi_dirs = ["example"]
autoapi_file_pattern = "*.py"

@ -19,9 +19,6 @@ python =
3.12: py312
[testenv]
extras =
dotnet
go
deps =
beautifulsoup4
pytest

Loading…
Cancel
Save