diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d089bb6b71f1066dd183b7501a1472e7f1c3c79..318c77620bd78ecdc49f1c626f55644c824e46b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,9 +31,9 @@ pages: script: - pip install sphinx - pip install sphinx_rtd_theme + - pip install better-apidoc - pip install numpydoc - - sphinx-apidoc -l -e -d 3 -o docs/source/mod nifty4 - - sphinx-build -b html docs/source/ docs/build/ + - sh docs/generate.sh - mv docs/build/ public/ artifacts: paths: diff --git a/docs/better_apidoc.py b/docs/better_apidoc.py new file mode 100644 index 0000000000000000000000000000000000000000..0d877560ea52d95be4ee49e0cbf81d9795ff356c --- /dev/null +++ b/docs/better_apidoc.py @@ -0,0 +1,663 @@ +# -*- coding: utf-8 -*- +""" + better apidoc + ~~~~~~~~~~~~~ + + Parses a directory tree looking for Python modules and packages and creates + ReST files appropriately to create code documentation with Sphinx. It also + creates a modules index (named modules.<suffix>). + + This is derived from the "sphinx-apidoc" script, which is: + Copyright 2007-2016 by the Sphinx team + http://www.sphinx-doc.org + + It extends "sphinx-apidoc" by the --template / -t option, which allows to + render the output ReST files based on arbitrary Jinja templates. + + :copyright: Copyright 2017 by Michael Goerz + :license: BSD, see LICENSE for details. +""" +from __future__ import print_function + +import os +import sys +import importlib +import optparse +from os import path +from six import binary_type +from fnmatch import fnmatch + +from jinja2 import FileSystemLoader, TemplateNotFound +from jinja2.sandbox import SandboxedEnvironment + +from sphinx.util.osutil import FileAvoidWrite, walk +#from sphinx import __display_version__ +from sphinx.quickstart import EXTENSIONS +from sphinx.ext.autosummary import get_documenter +from sphinx.util.inspect import safe_getattr + +# Add documenters to AutoDirective registry +from sphinx.ext.autodoc import add_documenter, \ + ModuleDocumenter, ClassDocumenter, ExceptionDocumenter, DataDocumenter, \ + FunctionDocumenter, MethodDocumenter, AttributeDocumenter, \ + InstanceAttributeDocumenter +add_documenter(ModuleDocumenter) +add_documenter(ClassDocumenter) +add_documenter(ExceptionDocumenter) +add_documenter(DataDocumenter) +add_documenter(FunctionDocumenter) +add_documenter(MethodDocumenter) +add_documenter(AttributeDocumenter) +add_documenter(InstanceAttributeDocumenter) + +__version__ = '0.1.2' +__display_version__ = __version__ + +if False: + # For type annotation + from typing import Any, List, Tuple # NOQA + +# automodule options +if 'SPHINX_APIDOC_OPTIONS' in os.environ: + OPTIONS = os.environ['SPHINX_APIDOC_OPTIONS'].split(',') +else: + OPTIONS = [ + 'members', + 'undoc-members', + # 'inherited-members', # disabled because there's a bug in sphinx + 'show-inheritance', + ] + +INITPY = '__init__.py' +PY_SUFFIXES = set(['.py', '.pyx']) + + +def _warn(msg): + # type: (unicode) -> None + print('WARNING: ' + msg, file=sys.stderr) + + +def makename(package, module): + # type: (unicode, unicode) -> unicode + """Join package and module with a dot.""" + # Both package and module can be None/empty. + if package: + name = package + if module: + name += '.' + module + else: + name = module + return name + + +def write_file(name, text, opts): + # type: (unicode, unicode, Any) -> None + """Write the output file for module/package <name>.""" + fname = path.join(opts.destdir, '%s.%s' % (name, opts.suffix)) + if opts.dryrun: + print('Would create file %s.' % fname) + return + if not opts.force and path.isfile(fname): + print('File %s already exists, skipping.' % fname) + else: + print('Creating file %s.' % fname) + with FileAvoidWrite(fname) as f: + f.write(text) + + +def format_heading(level, text): + # type: (int, unicode) -> unicode + """Create a heading of <level> [1, 2 or 3 supported].""" + underlining = ['=', '-', '~', ][level - 1] * len(text) + return '%s\n%s\n\n' % (text, underlining) + + +def format_directive(module, package=None): + # type: (unicode, unicode) -> unicode + """Create the automodule directive and add the options.""" + directive = '.. automodule:: %s\n' % makename(package, module) + for option in OPTIONS: + directive += ' :%s:\n' % option + return directive + + +def create_module_file(package, module, opts): + # type: (unicode, unicode, Any) -> None + """Generate RST for a top-level module (i.e., not part of a package)""" + if not opts.noheadings: + text = format_heading(1, '%s module' % module) + else: + text = '' + # text += format_heading(2, ':mod:`%s` Module' % module) + text += format_directive(module, package) + + if opts.templates: + template_loader = FileSystemLoader(opts.templates) + template_env = SandboxedEnvironment(loader=template_loader) + try: + mod_ns = _get_mod_ns( + name=module, fullname=module, + includeprivate=opts.includeprivate) + template = template_env.get_template('module.rst') + text = template.render(**mod_ns) + except ImportError as e: + _warn('failed to import %r: %s' % (module, e)) + write_file(makename(package, module), text, opts) + + +def _get_members( + mod, typ=None, include_imported=False, as_refs=False, in__all__=False): + """Get (filtered) public/total members of the module or package `mod`. + + Args: + mod: object resulting from importing a module or package + typ: filter on members. If None, include all members. If one of + 'function', 'class', 'exception', 'data', only include members of + the matching type + include_imported: If True, also include members that are imports + as_refs: If True, return ReST-formatted reference strings for all + members, instead of just their names. In combinations with + `include_imported` or `in__all__`, these link to the original + location where the member is defined + in__all__: If True, return only members that are in ``mod.__all__`` + + Returns: + lists `public` and `items`. The lists contains the public and private + + public members, as strings. + + Note: + For data members, there is no way to tell whether they were imported or + defined locally (without parsing the source code). A module may define + one or both attributes + + __local_data__: list of names of data objects defined locally + __imported_data__: dict of names to ReST-formatted references of where + a data object originates + + If either one of these attributes is present, the member will be + classified accordingly. Otherwise, it will be classified as local if it + appeard in the __all__ list, or as imported otherwise + + """ + roles = {'function': 'func', 'module': 'mod', 'class': 'class', + 'exception': 'exc', 'data': 'data'} + # not included, because they cannot occur at modul level: + # 'method': 'meth', 'attribute': 'attr', 'instanceattribute': 'attr' + + def check_typ(typ, mod, member): + """Check if mod.member is of the desired typ""" + documenter = get_documenter(member, mod) + if typ is None: + return True + if typ == getattr(documenter, 'objtype', None): + return True + if hasattr(documenter, 'directivetype'): + return roles[typ] == getattr(documenter, 'directivetype') + + def is_local(mod, member, name): + """Check whether mod.member is defined locally in module mod""" + if hasattr(member, '__module__'): + return getattr(member, '__module__') == mod.__name__ + else: + # we take missing __module__ to mean the member is a data object + if hasattr(mod, '__local_data__'): + return name in getattr(mod, '__local_data__') + if hasattr(mod, '__imported_data__'): + return name not in getattr(mod, '__imported_data__') + else: + return name in getattr(mod, '__all__', []) + + if typ is not None and typ not in roles: + raise ValueError("typ must be None or one of %s" + % str(list(roles.keys()))) + items = [] + public = [] + all_list = getattr(mod, '__all__', []) + for name in dir(mod): + try: + member = safe_getattr(mod, name) + except AttributeError: + continue + if check_typ(typ, mod, member): + if in__all__ and name not in all_list: + continue + if include_imported or is_local(mod, member, name): + if as_refs: + documenter = get_documenter(member, mod) + role = roles.get(documenter.objtype, 'obj') + ref = _get_member_ref_str( + name, obj=member, role=role, + known_refs=getattr(mod, '__imported_data__', None)) + items.append(ref) + if not name.startswith('_'): + public.append(ref) + else: + items.append(name) + if not name.startswith('_'): + public.append(name) + return public, items + + +def _get_member_ref_str(name, obj, role='obj', known_refs=None): + """generate a ReST-formmated reference link to the given `obj` of type + `role`, using `name` as the link text""" + if known_refs is not None: + if name in known_refs: + return known_refs[name] + if hasattr(obj, '__name__'): + try: + ref = obj.__module__ + '.' + obj.__name__ + except AttributeError: + ref = obj.__name__ + except TypeError: # e.g. obj.__name__ is None + ref = name + else: + ref = name + return ":%s:`%s <%s>`" % (role, name, ref) + + +def _get_mod_ns(name, fullname, includeprivate): + """Return the template context of module identified by `fullname` as a + dict""" + ns = { # template variables + 'name': name, 'fullname': fullname, 'members': [], 'functions': [], + 'classes': [], 'exceptions': [], 'subpackages': [], 'submodules': [], + 'all_refs': [], 'members_imports': [], 'members_imports_refs': [], + 'data': [], 'doc':None} + p = 0 + if includeprivate: + p = 1 + mod = importlib.import_module(fullname) + ns['members'] = _get_members(mod)[p] + ns['functions'] = _get_members(mod, typ='function')[p] + ns['classes'] = _get_members(mod, typ='class')[p] + ns['exceptions'] = _get_members(mod, typ='exception')[p] + ns['all_refs'] = _get_members(mod, include_imported=True, in__all__=True, as_refs=True)[p] + ns['members_imports'] = _get_members(mod, include_imported=True)[p] + ns['members_imports_refs'] = _get_members(mod, include_imported=True, as_refs=True)[p] + ns['data'] = _get_members(mod, typ='data')[p] + ns['doc'] = mod.__doc__ + return ns + + +def create_package_file(root, master_package, subroot, py_files, opts, subs, is_namespace): + # type: (unicode, unicode, unicode, List[unicode], Any, List[unicode], bool) -> None + """Build the text of the file and write the file.""" + + use_templates = False + if opts.templates: + use_templates = True + template_loader = FileSystemLoader(opts.templates) + template_env = SandboxedEnvironment(loader=template_loader) + + fullname = makename(master_package, subroot) + + text = format_heading( + 1, ('%s package' if not is_namespace else "%s namespace") % fullname) + + if opts.modulefirst and not is_namespace: + text += format_directive(subroot, master_package) + text += '\n' + + # build a list of directories that are szvpackages (contain an INITPY file) + subs = [sub for sub in subs if path.isfile(path.join(root, sub, INITPY))] + # if there are some package directories, add a TOC for theses subpackages + if subs: + text += format_heading(2, 'Subpackages') + text += '.. toctree::\n\n' + for sub in subs: + text += ' %s.%s\n' % (makename(master_package, subroot), sub) + text += '\n' + + submods = [path.splitext(sub)[0] for sub in py_files + if not shall_skip(path.join(root, sub), opts) and + sub != INITPY] + + if use_templates: + try: + package_ns = _get_mod_ns(name=subroot, fullname=fullname, + includeprivate=opts.includeprivate) + package_ns['subpackages'] = subs + package_ns['submodules'] = submods + except ImportError as e: + _warn('failed to import %r: %s' % (fullname, e)) + + if submods: + text += format_heading(2, 'Submodules') + if opts.separatemodules: + text += '.. toctree::\n\n' + for submod in submods: + modfile = makename(master_package, makename(subroot, submod)) + text += ' %s\n' % modfile + + # generate separate file for this module + if not opts.noheadings: + filetext = format_heading(1, '%s module' % modfile) + else: + filetext = '' + filetext += format_directive(makename(subroot, submod), + master_package) + if use_templates: + try: + mod_ns = _get_mod_ns( + name=submod, fullname=modfile, + includeprivate=opts.includeprivate) + template = template_env.get_template('module.rst') + filetext = template.render(**mod_ns) + except ImportError as e: + _warn('failed to import %r: %s' % (modfile, e)) + write_file(modfile, filetext, opts) + else: + for submod in submods: + modfile = makename(master_package, makename(subroot, submod)) + if not opts.noheadings: + text += format_heading(2, '%s module' % modfile) + text += format_directive(makename(subroot, submod), + master_package) + text += '\n' + text += '\n' + + if use_templates: + template = template_env.get_template('package.rst') + text = template.render(**package_ns) + else: + if not opts.modulefirst and not is_namespace: + text += format_heading(2, 'Module contents') + text += format_directive(subroot, master_package) + + write_file(makename(master_package, subroot), text, opts) + + +def create_modules_toc_file(modules, opts, name='modules'): + # type: (List[unicode], Any, unicode) -> None + """Create the module's index.""" + text = format_heading(1, '%s' % opts.header) + text += '.. toctree::\n' + text += ' :maxdepth: %s\n\n' % opts.maxdepth + + modules.sort() + prev_module = '' # type: unicode + for module in modules: + # look if the module is a subpackage and, if yes, ignore it + if module.startswith(prev_module + '.'): + continue + prev_module = module + text += ' %s\n' % module + + write_file(name, text, opts) + + +def shall_skip(module, opts): + # type: (unicode, Any) -> bool + """Check if we want to skip this module.""" + # skip if the file doesn't exist and not using implicit namespaces + if not opts.implicit_namespaces and not path.exists(module): + return True + + # skip it if there is nothing (or just \n or \r\n) in the file + if path.exists(module) and path.getsize(module) <= 2: + return True + + # skip if it has a "private" name and this is selected + filename = path.basename(module) + if filename != '__init__.py' and filename.startswith('_') and \ + not opts.includeprivate: + return True + return False + + +def recurse_tree(rootpath, excludes, opts): + # type: (unicode, List[unicode], Any) -> List[unicode] + """ + Look for every file in the directory tree and create the corresponding + ReST files. + """ + # check if the base directory is a package and get its name + if INITPY in os.listdir(rootpath): + root_package = rootpath.split(path.sep)[-1] + else: + # otherwise, the base is a directory with packages + root_package = None + + toplevels = [] + followlinks = getattr(opts, 'followlinks', False) + includeprivate = getattr(opts, 'includeprivate', False) + implicit_namespaces = getattr(opts, 'implicit_namespaces', False) + for root, subs, files in walk(rootpath, followlinks=followlinks): + # document only Python module files (that aren't excluded) + py_files = sorted(f for f in files + if path.splitext(f)[1] in PY_SUFFIXES and + not is_excluded(path.join(root, f), excludes)) + is_pkg = INITPY in py_files + is_namespace = INITPY not in py_files and implicit_namespaces + if is_pkg: + py_files.remove(INITPY) + py_files.insert(0, INITPY) + elif root != rootpath: + # only accept non-package at toplevel unless using implicit namespaces + if not implicit_namespaces: + del subs[:] + continue + # remove hidden ('.') and private ('_') directories, as well as + # excluded dirs + if includeprivate: + exclude_prefixes = ('.',) # type: Tuple[unicode, ...] + else: + exclude_prefixes = ('.', '_') + subs[:] = sorted(sub for sub in subs if not sub.startswith(exclude_prefixes) and + not is_excluded(path.join(root, sub), excludes)) + + if is_pkg or is_namespace: + # we are in a package with something to document + if subs or len(py_files) > 1 or not shall_skip(path.join(root, INITPY), opts): + subpackage = root[len(rootpath):].lstrip(path.sep).\ + replace(path.sep, '.') + # if this is not a namespace or + # a namespace and there is something there to document + if not is_namespace or len(py_files) > 0: + create_package_file(root, root_package, subpackage, + py_files, opts, subs, is_namespace) + toplevels.append(makename(root_package, subpackage)) + else: + # if we are at the root level, we don't require it to be a package + assert root == rootpath and root_package is None + if opts.templates: + sys.path.insert(0, rootpath) + for py_file in py_files: + if not shall_skip(path.join(rootpath, py_file), opts): + module = path.splitext(py_file)[0] + create_module_file(root_package, module, opts) + toplevels.append(module) + if opts.templates: + sys.path.pop(0) + + return toplevels + + +def normalize_excludes(rootpath, excludes): + # type: (unicode, List[unicode]) -> List[unicode] + """Normalize the excluded directory list.""" + return [path.abspath(exclude) for exclude in excludes] + + +def is_excluded(root, excludes): + # type: (unicode, List[unicode]) -> bool + """Check if the directory is in the exclude list. + + Note: by having trailing slashes, we avoid common prefix issues, like + e.g. an exlude "foo" also accidentally excluding "foobar". + """ + for exclude in excludes: + if fnmatch(root, exclude): + return True + return False + + +def main(argv=sys.argv): + # type: (List[str]) -> int + """Parse and check the command line arguments.""" + parser = optparse.OptionParser( + usage="""\ +usage: %prog [options] -o <output_path> <module_path> [exclude_pattern, ...] + +Look recursively in <module_path> for Python modules and packages and create +one reST file with automodule directives per package in the <output_path>. + +The <exclude_pattern>s can be file and/or directory patterns that will be +excluded from generation. + +Note: By default this script will not overwrite already created files.""") + + parser.add_option('-o', '--output-dir', action='store', dest='destdir', + help='Directory to place all output', default='') + parser.add_option('-d', '--maxdepth', action='store', dest='maxdepth', + help='Maximum depth of submodules to show in the TOC ' + '(default: 4)', type='int', default=4) + parser.add_option('-f', '--force', action='store_true', dest='force', + help='Overwrite existing files') + parser.add_option('-l', '--follow-links', action='store_true', + dest='followlinks', default=False, + help='Follow symbolic links. Powerful when combined ' + 'with collective.recipe.omelette.') + parser.add_option('-n', '--dry-run', action='store_true', dest='dryrun', + help='Run the script without creating files') + parser.add_option('-e', '--separate', action='store_true', + dest='separatemodules', + help='Put documentation for each module on its own page') + parser.add_option('-P', '--private', action='store_true', + dest='includeprivate', + help='Include "_private" modules') + parser.add_option('-T', '--no-toc', action='store_true', dest='notoc', + help='Don\'t create a table of contents file') + parser.add_option('-E', '--no-headings', action='store_true', + dest='noheadings', + help='Don\'t create headings for the module/package ' + 'packages (e.g. when the docstrings already contain ' + 'them). No effect in combination with -t') + parser.add_option('-M', '--module-first', action='store_true', + dest='modulefirst', + help='Put module documentation before submodule ' + 'documentation (no effect in combination with -t)') + parser.add_option('--implicit-namespaces', action='store_true', + dest='implicit_namespaces', + help='Interpret module paths according to PEP-0420 ' + 'implicit namespaces specification') + parser.add_option('-s', '--suffix', action='store', dest='suffix', + help='file suffix (default: rst)', default='rst') + parser.add_option('-F', '--full', action='store_true', dest='full', + help='Generate a full project with sphinx-quickstart') + parser.add_option('-a', '--append-syspath', action='store_true', + dest='append_syspath', + help='Append module_path to sys.path, used when --full is given') + parser.add_option("-t", "--templates", action="store", type="string", + dest="templates", default=None, + help="Custom template directory (default: %default). " + "Must contain template files package.rst and/or " + "module.rst") + parser.add_option('-H', '--doc-project', action='store', dest='header', + help='Project name (default: root module name)') + parser.add_option('-A', '--doc-author', action='store', dest='author', + type='str', + help='Project author(s), used when --full is given') + parser.add_option('-V', '--doc-version', action='store', dest='version', + help='Project version, used when --full is given') + parser.add_option('-R', '--doc-release', action='store', dest='release', + help='Project release, used when --full is given, ' + 'defaults to --doc-version') + parser.add_option('--version', action='store_true', dest='show_version', + help='Show version information and exit') + group = parser.add_option_group('Extension options') + for ext in EXTENSIONS: + group.add_option('--ext-' + ext, action='store_true', + dest='ext_' + ext, default=False, + help='enable %s extension' % ext) + + (opts, args) = parser.parse_args(argv[1:]) + + if opts.show_version: + #print('Sphinx (sphinx-apidoc) %s' % __display_version__) + print('better-apidoc %s' % __display_version__) + return 0 + + if not args: + parser.error('A package path is required.') + + rootpath, excludes = args[0], args[1:] + if not opts.destdir: + parser.error('An output directory is required.') + if opts.header is None: + opts.header = path.abspath(rootpath).split(path.sep)[-1] + if opts.suffix.startswith('.'): + opts.suffix = opts.suffix[1:] + if not path.isdir(rootpath): + print('%s is not a directory.' % rootpath, file=sys.stderr) + sys.exit(1) + if not path.isdir(opts.destdir): + if not opts.dryrun: + os.makedirs(opts.destdir) + rootpath = path.abspath(rootpath) + excludes = normalize_excludes(rootpath, excludes) + try: + modules = recurse_tree(rootpath, excludes, opts) + except TemplateNotFound as e: + print('Cannot find template in %s: %s' % + (opts.templates, e), file=sys.stderr) + sys.exit(1) + + if opts.full: + raise NotImplementedError("--full not supported") + # This would only make sense if this script was integrated in Sphinx + from sphinx import quickstart as qs + modules.sort() + prev_module = '' # type: unicode + text = '' + for module in modules: + if module.startswith(prev_module + '.'): + continue + prev_module = module + text += ' %s\n' % module + d = dict( + path = opts.destdir, + sep = False, + dot = '_', + project = opts.header, + author = opts.author or 'Author', + version = opts.version or '', + release = opts.release or opts.version or '', + suffix = '.' + opts.suffix, + master = 'index', + epub = True, + ext_autodoc = True, + ext_viewcode = True, + ext_todo = True, + makefile = True, + batchfile = True, + mastertocmaxdepth = opts.maxdepth, + mastertoctree = text, + language = 'en', + module_path = rootpath, + append_syspath = opts.append_syspath, + ) + enabled_exts = {'ext_' + ext: getattr(opts, 'ext_' + ext) + for ext in EXTENSIONS if getattr(opts, 'ext_' + ext)} + d.update(enabled_exts) + + if isinstance(opts.header, binary_type): + d['project'] = d['project'].decode('utf-8') + if isinstance(opts.author, binary_type): + d['author'] = d['author'].decode('utf-8') + if isinstance(opts.version, binary_type): + d['version'] = d['version'].decode('utf-8') + if isinstance(opts.release, binary_type): + d['release'] = d['release'].decode('utf-8') + + if not opts.dryrun: + qs.generate(d, silent=True, overwrite=opts.force) + elif not opts.notoc: + create_modules_toc_file(modules, opts) + return 0 + + +# So program can be started with "python -m sphinx.apidoc ..." +#if __name__ == "__main__": + #main() diff --git a/docs/generate.sh b/docs/generate.sh index c9b3decc94ef3b8a11ac19e0129cb521cb300bf1..5db8580609395da176dc4d777e4d9726fa753c22 100755 --- a/docs/generate.sh +++ b/docs/generate.sh @@ -1,4 +1,3 @@ rm -rf docs/build docs/source/mod -sphinx-apidoc -l -e -d 3 -o docs/source/mod nifty4 +better-apidoc -l -e -d 2 -t docs/generation-templates -o docs/source/mod nifty4 sphinx-build -b html docs/source/ docs/build/ - diff --git a/docs/generation-templates/module.rst b/docs/generation-templates/module.rst new file mode 100644 index 0000000000000000000000000000000000000000..445deed76e5033a9404e6274c1b939e576110490 --- /dev/null +++ b/docs/generation-templates/module.rst @@ -0,0 +1,79 @@ +{% if name %} +{{ name }} +{% for item in range(8 + name|length) -%}={%- endfor %} +{% else %} +{{ fullname }} +{% for item in range(8 + fullname|length) -%}={%- endfor %} +({{ fullname }} module) +{% endif %} + +.. currentmodule:: {{ fullname }} + +.. automodule:: {{ fullname }} + {% if members -%} + :members: {{ members|join(", ") }} + :undoc-members: + :show-inheritance: + :member-order: bysource + + Summary + ------- + {% if doc:%} + {{doc}} + {% endif %} + + {%- if exceptions %} + + Exceptions: + + .. autosummary:: + :nosignatures: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {%- endif %} + + {%- if classes %} + + Classes: + + .. autosummary:: + :nosignatures: + {% for item in classes %} + {{ item }} + {%- endfor %} + {%- endif %} + + {%- if functions %} + + Functions: + + .. autosummary:: + :nosignatures: + {% for item in functions %} + {{ item }} + {%- endfor %} + {%- endif %} + {%- endif %} + + {%- if data %} + + Data: + + .. autosummary:: + :nosignatures: + {% for item in data %} + {{ item }} + {%- endfor %} + {%- endif %} + +{% if all_refs %} + ``__all__``: {{ all_refs|join(", ") }} +{%- endif %} + + +{% if members %} + Reference + --------- + +{%- endif %} \ No newline at end of file diff --git a/docs/generation-templates/package.rst b/docs/generation-templates/package.rst new file mode 100644 index 0000000000000000000000000000000000000000..8d4c87781b8e0b412ac7bdf13f291e08ae9d70df --- /dev/null +++ b/docs/generation-templates/package.rst @@ -0,0 +1,108 @@ +{% if name %} +{{ name }} +{% for item in range(8 + name|length) -%}={%- endfor %} +({{ fullname }} package) + +{% else %} +{{ fullname }} +{% for item in range(8 + fullname|length) -%}={%- endfor %} +({{ fullname }} package) +{% endif %} + +.. automodule:: {{ fullname }} + {% if members -%} + :members: {{ members|join(", ") }} + :undoc-members: + :show-inheritance: + {%- endif %} + + + + + {% if submodules %} + Submodules: + + .. toctree:: + :maxdepth: 1 + {% for item in submodules %} + {{ fullname }}.{{ item }} + {%- endfor %} + {%- endif -%} + + {% if subpackages %} + + + Subpackages: + + .. toctree:: + :maxdepth: 1 + {% for item in subpackages %} + {{ fullname }}.{{ item }} + {%- endfor %} + + + {%- endif %} + + {% if members or doc %} + Summary + ------- + {% if doc:%} + {{doc}} + {% endif %} + + {%- if exceptions %} + + Exceptions: + + .. autosummary:: + :nosignatures: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {%- endif %} + + {%- if classes %} + + Classes: + + .. autosummary:: + :nosignatures: + {% for item in classes %} + {{ item }} + {%- endfor %} + {%- endif %} + + {%- if functions %} + + Functions: + + .. autosummary:: + :nosignatures: + {% for item in functions %} + {{ item }} + {%- endfor %} + {%- endif %} + + {%- endif %} + + {%- if data %} + + Data: + + .. autosummary:: + :nosignatures: + {% for item in data %} + {{ item }} + {%- endfor %} + {%- endif %} + +{% if all_refs %} + ``__all__``: {{ all_refs|join(", ") }} +{%- endif %} + + +{% if members %} + Reference + --------- + +{%- endif %} \ No newline at end of file diff --git a/docs/source/code.rst b/docs/source/code.rst index 5d661f6b8e408c59db4b736cbbbff35161912113..abbd167defcde1aa0c0776e4f1dca769a086aab8 100644 --- a/docs/source/code.rst +++ b/docs/source/code.rst @@ -5,7 +5,7 @@ The NIFTy code is divided in the concepts Spaces, Fields, Operators and Minimiza .. toctree:: - :maxdepth: 1 + :maxdepth: 2 :caption: Concepts :glob: diff --git a/docs/source/concepts/field.rst b/docs/source/concepts/field.rst index 07957662016dd63dc1256ffad5707ca6fe260188..7ade8e375e513e19c946f58366482600b8484ef2 100644 --- a/docs/source/concepts/field.rst +++ b/docs/source/concepts/field.rst @@ -4,6 +4,7 @@ Fields Description of Fields .. toctree:: + :maxdepth: 1 :caption: Types of Fields Field <../mod/nifty4.field> diff --git a/docs/source/concepts/minimization.rst b/docs/source/concepts/minimization.rst index fddbed0595fca1ada6adc0a382477d2d53288250..36594ac0d4a90c489202099f31f8873e17d9c937 100644 --- a/docs/source/concepts/minimization.rst +++ b/docs/source/concepts/minimization.rst @@ -4,6 +4,7 @@ Minimization Description of Minimization .. toctree:: + :maxdepth: 1 :caption: Minimization Concepts Conjugate Gradient <../mod/nifty4.minimization.conjugate_gradient> diff --git a/docs/source/concepts/operators.rst b/docs/source/concepts/operators.rst index 492b90b294f53845d82f2f87f05e37dfb7211390..72bace3fd26b192f110b748566f1e4219806b5a3 100644 --- a/docs/source/concepts/operators.rst +++ b/docs/source/concepts/operators.rst @@ -4,6 +4,7 @@ Operators Description of Operators .. toctree:: + :maxdepth: 1 :caption: Types of Operators Adjoint <../mod/nifty4.operators.adjoint_operator> diff --git a/docs/source/concepts/spaces.rst b/docs/source/concepts/spaces.rst index bf08046aeb7af8a8a996adfc9b34cdd3fc58205f..af5a8ce5ee33b06a9847899e36cea96f47c7b398 100644 --- a/docs/source/concepts/spaces.rst +++ b/docs/source/concepts/spaces.rst @@ -4,6 +4,7 @@ Spaces Description of Spaces .. toctree:: + :maxdepth: 1 :caption: Types of Spaces DOF <../mod/nifty4.spaces.dof_space> diff --git a/nifty4/spaces/__init__.py b/nifty4/spaces/__init__.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..f441fd8a61b96fc62458f08a81bb1a17c7a2262c 100644 --- a/nifty4/spaces/__init__.py +++ b/nifty4/spaces/__init__.py @@ -0,0 +1,3 @@ +""" +Sample documentation for spaces. (or any other package) This will be displayed under Summary section of module documentation +""" diff --git a/nifty4/spaces/dof_space.py b/nifty4/spaces/dof_space.py index bd79d3c7b1fffd83cd805ff0cf498b79001c170a..31145a785e3cb558239909e02dde9cf1094654e1 100644 --- a/nifty4/spaces/dof_space.py +++ b/nifty4/spaces/dof_space.py @@ -16,6 +16,10 @@ # NIFTy is being developed at the Max-Planck-Institut fuer Astrophysik # and financially supported by the Studienstiftung des deutschen Volkes. +""" +Sample documentation for DOF space. (or any other module). This will be displayed under Summary section of module documentation +""" + import numpy as np from .structured_domain import StructuredDomain