From b2db98f128866370b631ecbca510164d7200ba56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Tue, 4 Oct 2022 16:46:29 +0200 Subject: [PATCH 1/9] [doc] sphinx documentation setup --- docs/.gitignore | 3 + docs/Makefile | 20 +++++ docs/README.md | 18 +++++ docs/make.bat | 35 +++++++++ docs/source/_ext/fetch_md.py | 65 +++++++++++++++++ docs/source/_templates/autosummary/module.rst | 63 ++++++++++++++++ docs/source/api.rst | 9 +++ docs/source/changes.rst | 6 ++ docs/source/conf.py | 40 ++++++++++ docs/source/index.rst | 15 ++++ docs/source/install.rst | 6 ++ meshroom/__init__.py | 19 +---- meshroom/common/__init__.py | 73 ++++++------------- meshroom/ui/__init__.py | 2 - meshroom/ui/__main__.py | 13 ++-- 15 files changed, 313 insertions(+), 74 deletions(-) create mode 100644 docs/.gitignore create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/make.bat create mode 100644 docs/source/_ext/fetch_md.py create mode 100644 docs/source/_templates/autosummary/module.rst create mode 100644 docs/source/api.rst create mode 100644 docs/source/changes.rst create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100644 docs/source/install.rst diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..50e5506ad6 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,3 @@ +# Sphinx +build/ +source/generated/ diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000..d0c3cbf102 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..303059dcf2 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,18 @@ +# Documentation + +We use [Sphinx](https://www.sphinx-doc.org) to generate Meshroom's documentation. + +To install all the requirements for building the documentation, simply run: +```bash +pip install sphinx sphinx-rtd-theme myst-parser +``` + +> Note: since Sphinx will import the entire `meshroom` package, all requirements for Meshroom must also be installed + +To generate the documentation, go to the `docs` folder and run the Sphinx makefile: +```bash +cd meshroom/docs +make html +``` + +To access the documentation, simply go to `meshroom/docs/build/html` and open `index.html` in a browser. diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000000..dc1312ab09 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=source +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py new file mode 100644 index 0000000000..43a07930cf --- /dev/null +++ b/docs/source/_ext/fetch_md.py @@ -0,0 +1,65 @@ +import os +from docutils.nodes import SparseNodeVisitor +from docutils.parsers.rst import Directive +from myst_parser.docutils_ import Parser +from myst_parser.mdit_to_docutils.base import make_document + + +class Relinker(SparseNodeVisitor): + + @staticmethod + def get_link_key(node): + link_keys = ['uri', 'refuri', 'refname'] + for key in link_keys: + if key in node.attributes.keys(): + return key + return None + + def relink(self, node, base_dir): + key = Relinker.get_link_key(node) + if key is None: + return + link = node.attributes[key] + if link.startswith('http') or link.startswith('mailto'): + return + if link.startswith('/'): + link = link[1:] + node.attributes[key] = base_dir+'/'+link + + def visit_image(self, node): + self.relink(node, os.getenv('PROJECT_DIR')) + + +class FetchMd(Directive): + + required_arguments = 2 + + def arg_path(self): + if self.arguments[0] == ':file:': + return self.arguments[1] + + def run(self): + path = os.path.abspath(os.getenv('PROJECT_DIR') + '/' + self.arg_path()) + result = [] + try: + with open(path) as file: + parser = Parser() + text = file.read() + doc = make_document(parser_cls=Parser) + parser.parse(text, doc) + relinker = Relinker(doc) + doc.walk(relinker) + result.append(doc[0]) + except FileNotFoundError: + pass + return result + + +def setup(app): + app.add_directive('fetch_md', FetchMd) + + return { + 'version': '0.1', + 'parallel_read_safe': True, + 'parallel_write_safe': True + } diff --git a/docs/source/_templates/autosummary/module.rst b/docs/source/_templates/autosummary/module.rst new file mode 100644 index 0000000000..635912f70a --- /dev/null +++ b/docs/source/_templates/autosummary/module.rst @@ -0,0 +1,63 @@ +{{ fullname | escape | underline}} + + +.. automodule:: {{ fullname }} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Module Attributes') }} + + .. autosummary:: + {% for item in attributes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block functions %} + {% if functions %} + .. rubric:: {{ _('Functions') }} + + .. autosummary:: + {% for item in functions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block classes %} + {% if classes %} + .. rubric:: {{ _('Classes') }} + + .. autosummary:: + :toctree: + :recursive: + {% for item in classes %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block exceptions %} + {% if exceptions %} + .. rubric:: {{ _('Exceptions') }} + + .. autosummary:: + {% for item in exceptions %} + {{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + +{% block modules %} +{% if modules %} +.. rubric:: Modules + +.. autosummary:: + :toctree: + :recursive: +{% for item in modules %} + {{ item }} +{%- endfor %} +{% endif %} +{% endblock %} diff --git a/docs/source/api.rst b/docs/source/api.rst new file mode 100644 index 0000000000..8af742bc21 --- /dev/null +++ b/docs/source/api.rst @@ -0,0 +1,9 @@ +Python API Reference +==================== + + +.. autosummary:: + :recursive: + :toctree: generated + + meshroom diff --git a/docs/source/changes.rst b/docs/source/changes.rst new file mode 100644 index 0000000000..1b84907c76 --- /dev/null +++ b/docs/source/changes.rst @@ -0,0 +1,6 @@ +Release Notes +============= + + +.. fetch_md:: + :file: CHANGES.md diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000000..709e205aee --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,40 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import os +from pathlib import Path +import sys + +os.environ['PROJECT_DIR'] = Path('../..').resolve().as_posix() + +sys.path.append(os.path.abspath(os.getenv('PROJECT_DIR'))) +sys.path.append(os.path.abspath('./_ext')) + +project = 'Meshroom' +copyright = '2022, AliceVision Association' +author = 'AliceVision Association' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.autosummary', + 'fetch_md' +] + +templates_path = ['_templates'] +exclude_patterns = [] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'sphinx_rtd_theme' +html_static_path = ['_static'] diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000000..bd01d0c5fd --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,15 @@ +Welcome to meshroom's documentation! +==================================== + + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + api + install + changes + + +.. fetch_md:: + :file: README.md diff --git a/docs/source/install.rst b/docs/source/install.rst new file mode 100644 index 0000000000..b05e16768f --- /dev/null +++ b/docs/source/install.rst @@ -0,0 +1,6 @@ +Install +======= + + +.. fetch_md:: + :file: INSTALL.md diff --git a/meshroom/__init__.py b/meshroom/__init__.py index 9b091cfe49..c29a34503c 100644 --- a/meshroom/__init__.py +++ b/meshroom/__init__.py @@ -2,10 +2,10 @@ __version_name__ = __version__ from distutils import util -from enum import Enum import logging import os import sys +from .common import init, Backend # sys.frozen is initialized by cx_Freeze and identifies a release package isFrozen = getattr(sys, "frozen", False) @@ -25,20 +25,7 @@ useMultiChunks = util.strtobool(os.environ.get("MESHROOM_USE_MULTI_CHUNKS", "True")) -class Backend(Enum): - STANDALONE = 1 - PYSIDE = 2 - - -backend = Backend.STANDALONE - - -def useUI(): - global backend - backend = Backend.PYSIDE - - -def setupEnvironment(): +def setupEnvironment(backend=Backend.STANDALONE): """ Setup environment for Meshroom to work in a prebuilt, standalone configuration. @@ -61,6 +48,8 @@ def setupEnvironment(): COPYING.md # Meshroom COPYING file """ + init(backend) + def addToEnvPath(var, val, index=-1): """ Add paths to the given environment variable. diff --git a/meshroom/common/__init__.py b/meshroom/common/__init__.py index 3331e9c680..db73fe05db 100644 --- a/meshroom/common/__init__.py +++ b/meshroom/common/__init__.py @@ -1,4 +1,15 @@ -import meshroom +""" +This module provides an abstraction around standard non-gui Qt notions (like Signal/Slot), +so it can be used in python-only without the dependency to Qt. + +Warning: A call to `init(Backend.XXX)` is required to choose the backend before using this module. +""" + +from enum import Enum + +class Backend(Enum): + STANDALONE = 1 + PYSIDE = 2 DictModel = None ListModel = None @@ -10,52 +21,14 @@ VariantList = None JSValue = None -if meshroom.backend == meshroom.Backend.PYSIDE: - # PySide types - from .qt import DictModel, ListModel, Slot, Signal, Property, BaseObject, Variant, VariantList, JSValue -elif meshroom.backend == meshroom.Backend.STANDALONE: - # Core types - from .core import DictModel, ListModel, Slot, Signal, Property, BaseObject, Variant, VariantList, JSValue - - -class _BaseModel: - """ Common API for model implementation """ - - def __init__(self, keyAttrName="name", **kwargs): - """ - :param keyAttrName: name of the attribute containing the unique key for an object - """ - pass - - @property - def objects(self): - """ Return a dictionary with {unique_key: object} mapping""" - return None - - def get(self, key): - """ Get the object with the unique key 'key' """ - pass - - def add(self, obj): - """ Add given object using its 'keyAttrName' as unique key """ - pass - - def pop(self, key): - """ Remove 'item' with unique key 'key' from the model """ - pass - - def remove(self, obj): - """ Remove 'obj' from the model """ - pass - - def clear(self): - """ Remove all internal objects """ - pass - - def update(self, d): - """ Combine dict 'd' with self """ - pass - - def reset(self, d): - """ Reset model with given values """ - pass +def init(backend): + global DictModel, ListModel, Slot, Signal, Property, BaseObject, Variant, VariantList, JSValue + if backend == Backend.PYSIDE: + # PySide types + from .qt import DictModel, ListModel, Slot, Signal, Property, BaseObject, Variant, VariantList, JSValue + elif backend == Backend.STANDALONE: + # Core types + from .core import DictModel, ListModel, Slot, Signal, Property, BaseObject, Variant, VariantList, JSValue + +# default initialization +init(Backend.STANDALONE) diff --git a/meshroom/ui/__init__.py b/meshroom/ui/__init__.py index 58c3fb215e..e69de29bb2 100644 --- a/meshroom/ui/__init__.py +++ b/meshroom/ui/__init__.py @@ -1,2 +0,0 @@ -import meshroom -meshroom.useUI() diff --git a/meshroom/ui/__main__.py b/meshroom/ui/__main__.py index 5914f1ad2d..7cede12378 100644 --- a/meshroom/ui/__main__.py +++ b/meshroom/ui/__main__.py @@ -1,12 +1,11 @@ import signal import sys import meshroom +from meshroom.common import Backend +meshroom.setupEnvironment(backend=Backend.PYSIDE) -if __name__ == "__main__": - meshroom.setupEnvironment() - - signal.signal(signal.SIGINT, signal.SIG_DFL) - from meshroom.ui.app import MeshroomApp - app = MeshroomApp(sys.argv) - app.exec_() +signal.signal(signal.SIGINT, signal.SIG_DFL) +from meshroom.ui.app import MeshroomApp +app = MeshroomApp(sys.argv) +app.exec_() From f8406aa6daa4d593221de2b1688b227770663d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Tue, 11 Oct 2022 11:14:45 +0200 Subject: [PATCH 2/9] [docs] python2 compatibility --- docs/source/_ext/fetch_md.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py index 43a07930cf..20f0462a84 100644 --- a/docs/source/_ext/fetch_md.py +++ b/docs/source/_ext/fetch_md.py @@ -4,6 +4,12 @@ from myst_parser.docutils_ import Parser from myst_parser.mdit_to_docutils.base import make_document +# Python2 compatibility +try: + FileNotFoundError +except NameError: + FileNotFoundError = IOError + class Relinker(SparseNodeVisitor): From e022b377c42d50839b66cb1e38fbe86f58e65b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Tue, 11 Oct 2022 13:58:03 +0200 Subject: [PATCH 3/9] [docs] add tests --- docs/source/api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/source/api.rst b/docs/source/api.rst index 8af742bc21..a47d752730 100644 --- a/docs/source/api.rst +++ b/docs/source/api.rst @@ -7,3 +7,4 @@ Python API Reference :toctree: generated meshroom + tests From cec2c79d6a31d532d5f9dfc62830b4cfc89b8278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Wed, 12 Oct 2022 18:25:10 +0200 Subject: [PATCH 4/9] [docs] generate extra node doc with custom extension --- docs/source/_ext/fetch_md.py | 8 +-- docs/source/_ext/meshroom_doc.py | 60 ++++++++++++++++++++ docs/source/_templates/autosummary/class.rst | 35 ++++++++++++ docs/source/changes.rst | 3 +- docs/source/conf.py | 3 +- docs/source/index.rst | 3 +- docs/source/install.rst | 3 +- 7 files changed, 102 insertions(+), 13 deletions(-) create mode 100644 docs/source/_ext/meshroom_doc.py create mode 100644 docs/source/_templates/autosummary/class.rst diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py index 20f0462a84..bfc3da0928 100644 --- a/docs/source/_ext/fetch_md.py +++ b/docs/source/_ext/fetch_md.py @@ -38,14 +38,10 @@ def visit_image(self, node): class FetchMd(Directive): - required_arguments = 2 - - def arg_path(self): - if self.arguments[0] == ':file:': - return self.arguments[1] + required_arguments = 1 def run(self): - path = os.path.abspath(os.getenv('PROJECT_DIR') + '/' + self.arg_path()) + path = os.path.abspath(os.getenv('PROJECT_DIR')+'/'+self.arguments[0]) result = [] try: with open(path) as file: diff --git a/docs/source/_ext/meshroom_doc.py b/docs/source/_ext/meshroom_doc.py new file mode 100644 index 0000000000..acde4aab7a --- /dev/null +++ b/docs/source/_ext/meshroom_doc.py @@ -0,0 +1,60 @@ +from docutils import nodes +from docutils.parsers.rst import Directive +from myst_parser.docutils_ import Parser +from myst_parser.mdit_to_docutils.base import make_document + +import importlib +from meshroom.core import desc + + +class MeshroomDoc(Directive): + + required_arguments = 4 + + def parse_args(self): + module_name = self.arguments[self.arguments.index(':module:')+1] + class_name = self.arguments[self.arguments.index(':class:')+1] + return (module_name, class_name) + + def run(self): + result = [] + # Import module and class + module_name, class_name = self.parse_args() + module = importlib.import_module(module_name) + node_class = getattr(module, class_name) + # Class inherits desc.Node + if issubclass(node_class, desc.Node): + node = node_class() + parser = Parser() + # Category + doc = make_document(parser_cls=Parser) + parser.parse('**Category**: {}'.format(node.category), doc) + result.extend(doc.children) + # Documentation + doc = make_document(parser_cls=Parser) + parser.parse(node.documentation, doc) + result.extend(doc.children) + # Inputs + text_inputs = '**Inputs**: \n' + for attr in node.inputs: + text_inputs += '- {} ({})\n'.format(attr._name, attr.__class__.__name__) + doc = make_document(parser_cls=Parser) + parser.parse(text_inputs, doc) + result.extend(doc.children) + # Outputs + text_outputs = '**Outputs**: \n' + for attr in node.outputs: + text_outputs += '- {} ({})\n'.format(attr._name, attr.__class__.__name__) + doc = make_document(parser_cls=Parser) + parser.parse(text_outputs, doc) + result.extend(doc.children) + return result + + +def setup(app): + app.add_directive("meshroom_doc", MeshroomDoc) + return { + 'version': '0.1', + 'parallel_read_safe': True, + 'parallel_write_safe': True, + } diff --git a/docs/source/_templates/autosummary/class.rst b/docs/source/_templates/autosummary/class.rst new file mode 100644 index 0000000000..03dc3878bd --- /dev/null +++ b/docs/source/_templates/autosummary/class.rst @@ -0,0 +1,35 @@ +{{ fullname | escape | underline}} + + +.. meshroom_doc:: + :module: {{ module }} + :class: {{ objname }} + + +.. currentmodule:: {{ module }} + +.. autoclass:: {{ objname }} + + {% block methods %} + .. automethod:: __init__ + + {% if methods %} + .. rubric:: {{ _('Methods') }} + + .. autosummary:: + {% for item in methods %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} + + {% block attributes %} + {% if attributes %} + .. rubric:: {{ _('Attributes') }} + + .. autosummary:: + {% for item in attributes %} + ~{{ name }}.{{ item }} + {%- endfor %} + {% endif %} + {% endblock %} diff --git a/docs/source/changes.rst b/docs/source/changes.rst index 1b84907c76..6f46995b7c 100644 --- a/docs/source/changes.rst +++ b/docs/source/changes.rst @@ -2,5 +2,4 @@ Release Notes ============= -.. fetch_md:: - :file: CHANGES.md +.. fetch_md:: CHANGES.md diff --git a/docs/source/conf.py b/docs/source/conf.py index 709e205aee..6f58c9121e 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -25,7 +25,8 @@ extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', - 'fetch_md' + 'fetch_md', + 'meshroom_doc' ] templates_path = ['_templates'] diff --git a/docs/source/index.rst b/docs/source/index.rst index bd01d0c5fd..e1c451244a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -11,5 +11,4 @@ Welcome to meshroom's documentation! changes -.. fetch_md:: - :file: README.md +.. fetch_md:: README.md diff --git a/docs/source/install.rst b/docs/source/install.rst index b05e16768f..a6500ed1bd 100644 --- a/docs/source/install.rst +++ b/docs/source/install.rst @@ -2,5 +2,4 @@ Install ======= -.. fetch_md:: - :file: INSTALL.md +.. fetch_md:: INSTALL.md From 652113443d79e95ac85db2c168cf5a372a66f179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Thu, 13 Oct 2022 12:12:26 +0200 Subject: [PATCH 5/9] [docs] minor code refactoring --- docs/source/_ext/__init__.py | 0 docs/source/_ext/fetch_md.py | 17 +++-------------- docs/source/_ext/meshroom_doc.py | 16 +++++----------- docs/source/_ext/utils.py | 17 +++++++++++++++++ 4 files changed, 25 insertions(+), 25 deletions(-) create mode 100644 docs/source/_ext/__init__.py create mode 100644 docs/source/_ext/utils.py diff --git a/docs/source/_ext/__init__.py b/docs/source/_ext/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py index bfc3da0928..18773dd667 100644 --- a/docs/source/_ext/fetch_md.py +++ b/docs/source/_ext/fetch_md.py @@ -1,8 +1,7 @@ import os from docutils.nodes import SparseNodeVisitor from docutils.parsers.rst import Directive -from myst_parser.docutils_ import Parser -from myst_parser.mdit_to_docutils.base import make_document +from utils import md_to_docutils, get_link_key # Python2 compatibility try: @@ -13,16 +12,8 @@ class Relinker(SparseNodeVisitor): - @staticmethod - def get_link_key(node): - link_keys = ['uri', 'refuri', 'refname'] - for key in link_keys: - if key in node.attributes.keys(): - return key - return None - def relink(self, node, base_dir): - key = Relinker.get_link_key(node) + key = get_link_key(node) if key is None: return link = node.attributes[key] @@ -45,10 +36,8 @@ def run(self): result = [] try: with open(path) as file: - parser = Parser() text = file.read() - doc = make_document(parser_cls=Parser) - parser.parse(text, doc) + doc = md_to_docutils(text) relinker = Relinker(doc) doc.walk(relinker) result.append(doc[0]) diff --git a/docs/source/_ext/meshroom_doc.py b/docs/source/_ext/meshroom_doc.py index acde4aab7a..965824be5e 100644 --- a/docs/source/_ext/meshroom_doc.py +++ b/docs/source/_ext/meshroom_doc.py @@ -1,7 +1,6 @@ from docutils import nodes from docutils.parsers.rst import Directive -from myst_parser.docutils_ import Parser -from myst_parser.mdit_to_docutils.base import make_document +from utils import md_to_docutils import importlib from meshroom.core import desc @@ -25,28 +24,23 @@ def run(self): # Class inherits desc.Node if issubclass(node_class, desc.Node): node = node_class() - parser = Parser() # Category - doc = make_document(parser_cls=Parser) - parser.parse('**Category**: {}'.format(node.category), doc) + doc = md_to_docutils('**Category**: {}'.format(node.category)) result.extend(doc.children) # Documentation - doc = make_document(parser_cls=Parser) - parser.parse(node.documentation, doc) + doc = md_to_docutils(node.documentation) result.extend(doc.children) # Inputs text_inputs = '**Inputs**: \n' for attr in node.inputs: text_inputs += '- {} ({})\n'.format(attr._name, attr.__class__.__name__) - doc = make_document(parser_cls=Parser) - parser.parse(text_inputs, doc) + doc = md_to_docutils(text_inputs) result.extend(doc.children) # Outputs text_outputs = '**Outputs**: \n' for attr in node.outputs: text_outputs += '- {} ({})\n'.format(attr._name, attr.__class__.__name__) - doc = make_document(parser_cls=Parser) - parser.parse(text_outputs, doc) + doc = md_to_docutils(text_outputs) result.extend(doc.children) return result diff --git a/docs/source/_ext/utils.py b/docs/source/_ext/utils.py new file mode 100644 index 0000000000..729aa8a5db --- /dev/null +++ b/docs/source/_ext/utils.py @@ -0,0 +1,17 @@ +from myst_parser.docutils_ import Parser +from myst_parser.mdit_to_docutils.base import make_document + + +def md_to_docutils(text): + parser = Parser() + doc = make_document(parser_cls=Parser) + parser.parse(text, doc) + return doc + + +def get_link_key(node): + link_keys = ['uri', 'refuri', 'refname'] + for key in link_keys: + if key in node.attributes.keys(): + return key + return None From 07e993a3ebf54dc16fcd6bed04d1d83d443ceea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Fri, 14 Oct 2022 12:51:50 +0200 Subject: [PATCH 6/9] [docs] inheritance diagram --- docs/README.md | 6 ++++++ docs/source/_templates/autosummary/class.rst | 3 +++ docs/source/conf.py | 4 +++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 303059dcf2..6680e8c84b 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,13 +2,19 @@ We use [Sphinx](https://www.sphinx-doc.org) to generate Meshroom's documentation. +## Requirements + To install all the requirements for building the documentation, simply run: ```bash pip install sphinx sphinx-rtd-theme myst-parser ``` +You also need to have [Graphviz](https://graphviz.org/) installed. + > Note: since Sphinx will import the entire `meshroom` package, all requirements for Meshroom must also be installed +## Build + To generate the documentation, go to the `docs` folder and run the Sphinx makefile: ```bash cd meshroom/docs diff --git a/docs/source/_templates/autosummary/class.rst b/docs/source/_templates/autosummary/class.rst index 03dc3878bd..958658a32e 100644 --- a/docs/source/_templates/autosummary/class.rst +++ b/docs/source/_templates/autosummary/class.rst @@ -1,6 +1,9 @@ {{ fullname | escape | underline}} +.. inheritance-diagram:: {{ fullname }} + + .. meshroom_doc:: :module: {{ module }} :class: {{ objname }} diff --git a/docs/source/conf.py b/docs/source/conf.py index 6f58c9121e..33c201d9d6 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -26,7 +26,9 @@ 'sphinx.ext.autodoc', 'sphinx.ext.autosummary', 'fetch_md', - 'meshroom_doc' + 'meshroom_doc', + 'sphinx.ext.graphviz', + 'sphinx.ext.inheritance_diagram' ] templates_path = ['_templates'] From e6fa53399a0bde075578a109c026325699a77ef5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Fri, 21 Oct 2022 11:36:40 +0200 Subject: [PATCH 7/9] [docs] readthedocs setup --- .readthedocs.yaml | 15 +++++++++++++++ docs/requirements.txt | 1 + 2 files changed, 16 insertions(+) create mode 100644 .readthedocs.yaml create mode 100644 docs/requirements.txt diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 0000000000..0582c91546 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,15 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docs/source/conf.py + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docs/requirements.txt diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..f0694bdc09 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1 @@ +myst-parser From e63b06a3b9a72f6f4bfc27a0e992a90f69f23a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Fri, 21 Oct 2022 11:42:10 +0200 Subject: [PATCH 8/9] [docs] specifying all requirements for building docs --- .readthedocs.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 0582c91546..baf40bb080 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -11,5 +11,7 @@ sphinx: # Optionally declare the Python requirements required to build your docs python: - install: - - requirements: docs/requirements.txt + install: + - requirements: requirements.txt + - requirements: dev_requirements.txt + - requirements: docs/requirements.txt From f3bed081bda887d2c9df953fbdbe30d01829940e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Vital?= Date: Fri, 21 Oct 2022 13:42:34 +0200 Subject: [PATCH 9/9] [docs] commenting custom extensions --- .readthedocs.yaml | 7 ++++--- docs/source/_ext/fetch_md.py | 14 ++++++++++++++ docs/source/_ext/meshroom_doc.py | 13 +++++++++++++ docs/source/_ext/utils.py | 8 ++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index baf40bb080..5aebe69331 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -5,11 +5,12 @@ # Required version: 2 -# Build documentation in the docs/ directory with Sphinx +# Build HTML documentation with Sphinx sphinx: - configuration: docs/source/conf.py + builder: html + configuration: docs/source/conf.py -# Optionally declare the Python requirements required to build your docs +# Python requirements python: install: - requirements: requirements.txt diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py index 18773dd667..fa85fcc316 100644 --- a/docs/source/_ext/fetch_md.py +++ b/docs/source/_ext/fetch_md.py @@ -1,3 +1,17 @@ +# Sphinx extension defining the fetch_md directive +# +# Goal: +# include the content of a given markdown file +# +# Usage: +# .. fetch_md:: path/to/file.md +# the filepath is relative to the project base directory +# +# Note: +# some markdown files contain links to other files that belong to the project +# since those links are relative to the file location, they are no longer valid in the new context +# therefore we try to update these links but it is not always possible + import os from docutils.nodes import SparseNodeVisitor from docutils.parsers.rst import Directive diff --git a/docs/source/_ext/meshroom_doc.py b/docs/source/_ext/meshroom_doc.py index 965824be5e..d5151ef7d0 100644 --- a/docs/source/_ext/meshroom_doc.py +++ b/docs/source/_ext/meshroom_doc.py @@ -1,3 +1,16 @@ +# Sphinx extension defining the meshroom_doc directive +# +# Goal: +# create specific documentation content for meshroom objects +# +# Usage: +# .. meshroom_doc:: +# :module: module_name +# :class: class_name +# +# Note: +# for now this tool focuses only on meshroom nodes + from docutils import nodes from docutils.parsers.rst import Directive from utils import md_to_docutils diff --git a/docs/source/_ext/utils.py b/docs/source/_ext/utils.py index 729aa8a5db..cbfbb6b991 100644 --- a/docs/source/_ext/utils.py +++ b/docs/source/_ext/utils.py @@ -1,7 +1,12 @@ +# Utility functions for custom Sphinx extensions + from myst_parser.docutils_ import Parser from myst_parser.mdit_to_docutils.base import make_document +# Given a string written in markdown +# parse its content +# and return the corresponding docutils document def md_to_docutils(text): parser = Parser() doc = make_document(parser_cls=Parser) @@ -9,6 +14,9 @@ def md_to_docutils(text): return doc +# Given a docutils node +# find an attribute that corresponds to a link (if it exists) +# and return its key def get_link_key(node): link_keys = ['uri', 'refuri', 'refname'] for key in link_keys: