Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/alicevision/meshroom.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabien Castan <fabcastan@gmail.com>2022-10-21 17:49:28 +0300
committerGitHub <noreply@github.com>2022-10-21 17:49:28 +0300
commita0068c3da4c4f120e849416d90a5683c35cdf994 (patch)
tree6dc8cc894219fd6447fb125f1db55c072adb6db0
parentad69c7085e4f7bf225670bead4697794aeb47279 (diff)
parentf3bed081bda887d2c9df953fbdbe30d01829940e (diff)
Merge pull request #1794 from alicevision/dev/lv/sphinxDoc
[docs] Python documentation generation using Sphinx
-rw-r--r--.readthedocs.yaml18
-rw-r--r--docs/.gitignore3
-rw-r--r--docs/Makefile20
-rw-r--r--docs/README.md24
-rw-r--r--docs/make.bat35
-rw-r--r--docs/requirements.txt1
-rw-r--r--docs/source/_ext/__init__.py0
-rw-r--r--docs/source/_ext/fetch_md.py70
-rw-r--r--docs/source/_ext/meshroom_doc.py67
-rw-r--r--docs/source/_ext/utils.py25
-rw-r--r--docs/source/_templates/autosummary/class.rst38
-rw-r--r--docs/source/_templates/autosummary/module.rst63
-rw-r--r--docs/source/api.rst10
-rw-r--r--docs/source/changes.rst5
-rw-r--r--docs/source/conf.py43
-rw-r--r--docs/source/index.rst14
-rw-r--r--docs/source/install.rst5
-rw-r--r--meshroom/__init__.py19
-rw-r--r--meshroom/common/__init__.py73
-rw-r--r--meshroom/ui/__init__.py2
-rw-r--r--meshroom/ui/__main__.py13
21 files changed, 474 insertions, 74 deletions
diff --git a/.readthedocs.yaml b/.readthedocs.yaml
new file mode 100644
index 00000000..5aebe693
--- /dev/null
+++ b/.readthedocs.yaml
@@ -0,0 +1,18 @@
+# .readthedocs.yaml
+# Read the Docs configuration file
+# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
+
+# Required
+version: 2
+
+# Build HTML documentation with Sphinx
+sphinx:
+ builder: html
+ configuration: docs/source/conf.py
+
+# Python requirements
+python:
+ install:
+ - requirements: requirements.txt
+ - requirements: dev_requirements.txt
+ - requirements: docs/requirements.txt
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 00000000..50e5506a
--- /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 00000000..d0c3cbf1
--- /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 00000000..6680e8c8
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,24 @@
+# Documentation
+
+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
+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 00000000..dc1312ab
--- /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/requirements.txt b/docs/requirements.txt
new file mode 100644
index 00000000..f0694bdc
--- /dev/null
+++ b/docs/requirements.txt
@@ -0,0 +1 @@
+myst-parser
diff --git a/docs/source/_ext/__init__.py b/docs/source/_ext/__init__.py
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/docs/source/_ext/__init__.py
diff --git a/docs/source/_ext/fetch_md.py b/docs/source/_ext/fetch_md.py
new file mode 100644
index 00000000..fa85fcc3
--- /dev/null
+++ b/docs/source/_ext/fetch_md.py
@@ -0,0 +1,70 @@
+# 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
+from utils import md_to_docutils, get_link_key
+
+# Python2 compatibility
+try:
+ FileNotFoundError
+except NameError:
+ FileNotFoundError = IOError
+
+
+class Relinker(SparseNodeVisitor):
+
+ def relink(self, node, base_dir):
+ key = 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 = 1
+
+ def run(self):
+ path = os.path.abspath(os.getenv('PROJECT_DIR')+'/'+self.arguments[0])
+ result = []
+ try:
+ with open(path) as file:
+ text = file.read()
+ doc = md_to_docutils(text)
+ 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/_ext/meshroom_doc.py b/docs/source/_ext/meshroom_doc.py
new file mode 100644
index 00000000..d5151ef7
--- /dev/null
+++ b/docs/source/_ext/meshroom_doc.py
@@ -0,0 +1,67 @@
+# 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
+
+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()
+ # Category
+ doc = md_to_docutils('**Category**: {}'.format(node.category))
+ result.extend(doc.children)
+ # Documentation
+ 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 = 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 = md_to_docutils(text_outputs)
+ 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/_ext/utils.py b/docs/source/_ext/utils.py
new file mode 100644
index 00000000..cbfbb6b9
--- /dev/null
+++ b/docs/source/_ext/utils.py
@@ -0,0 +1,25 @@
+# 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)
+ parser.parse(text, doc)
+ 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:
+ if key in node.attributes.keys():
+ return key
+ return None
diff --git a/docs/source/_templates/autosummary/class.rst b/docs/source/_templates/autosummary/class.rst
new file mode 100644
index 00000000..958658a3
--- /dev/null
+++ b/docs/source/_templates/autosummary/class.rst
@@ -0,0 +1,38 @@
+{{ fullname | escape | underline}}
+
+
+.. inheritance-diagram:: {{ fullname }}
+
+
+.. 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/_templates/autosummary/module.rst b/docs/source/_templates/autosummary/module.rst
new file mode 100644
index 00000000..635912f7
--- /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 00000000..a47d7527
--- /dev/null
+++ b/docs/source/api.rst
@@ -0,0 +1,10 @@
+Python API Reference
+====================
+
+
+.. autosummary::
+ :recursive:
+ :toctree: generated
+
+ meshroom
+ tests
diff --git a/docs/source/changes.rst b/docs/source/changes.rst
new file mode 100644
index 00000000..6f46995b
--- /dev/null
+++ b/docs/source/changes.rst
@@ -0,0 +1,5 @@
+Release Notes
+=============
+
+
+.. fetch_md:: CHANGES.md
diff --git a/docs/source/conf.py b/docs/source/conf.py
new file mode 100644
index 00000000..33c201d9
--- /dev/null
+++ b/docs/source/conf.py
@@ -0,0 +1,43 @@
+# 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',
+ 'meshroom_doc',
+ 'sphinx.ext.graphviz',
+ 'sphinx.ext.inheritance_diagram'
+]
+
+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 00000000..e1c45124
--- /dev/null
+++ b/docs/source/index.rst
@@ -0,0 +1,14 @@
+Welcome to meshroom's documentation!
+====================================
+
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ api
+ install
+ changes
+
+
+.. fetch_md:: README.md
diff --git a/docs/source/install.rst b/docs/source/install.rst
new file mode 100644
index 00000000..a6500ed1
--- /dev/null
+++ b/docs/source/install.rst
@@ -0,0 +1,5 @@
+Install
+=======
+
+
+.. fetch_md:: INSTALL.md
diff --git a/meshroom/__init__.py b/meshroom/__init__.py
index 9b091cfe..c29a3450 100644
--- a/meshroom/__init__.py
+++ b/meshroom/__init__.py
@@ -2,10 +2,10 @@ __version__ = "2021.1.0"
__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 @@ __version_name__ = os.environ.get("REZ_MESHROOM_VERSION", __version_name__)
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 3331e9c6..db73fe05 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 @@ Variant = None
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 58c3fb21..e69de29b 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 5914f1ad..7cede123 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_()