Commit 277e1504 authored by Thomas Purcell's avatar Thomas Purcell
Browse files

Add python documentation

STill doing some debugging
parent 26fe60c9
......@@ -49,11 +49,11 @@ function(transfer_doc_string PYTHON_BINDING_FILE PYTHON_BINDING_FILE_OUT)
string(REGEX REPLACE "@brief " "" LINE "${LINE}")
string(REGEX REPLACE "@details " "" LINE "${LINE}")
if("${LINE}" MATCHES "@param ([a-zA-Z0-9_]+) (.*)")
if("${LINE}" MATCHES "@param ([a-zA-Z0-9_]+)(\\([a-zA-Z0-9_.]+\\)) (.*)")
if(IN_PARAMS)
set(LINE " ${CMAKE_MATCH_1}: ${CMAKE_MATCH_2}")
set(LINE " ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
else(NOT IN_PARAMS)
set(LINE "Args:\\n ${CMAKE_MATCH_1}: ${CMAKE_MATCH_2}")
set(LINE "\\nArgs:\\n ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
set(IN_PARAMS ON)
endif()
endif()
......@@ -61,15 +61,15 @@ function(transfer_doc_string PYTHON_BINDING_FILE PYTHON_BINDING_FILE_OUT)
if(IN_PARAMS)
set(LINE " ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
else(NOT IN_PARAMS)
set(LINE "Args:\\n ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
set(LINE "\\nArgs:\\n ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
set(IN_PARAMS ON)
endif()
endif()
if("${LINE}" MATCHES "@param ([a-zA-Z0-9_]+)(\\([a-zA-Z0-9_.]+\\)) (.*)")
if("${LINE}" MATCHES "@param ([a-zA-Z0-9_]+) (.*)")
if(IN_PARAMS)
set(LINE " ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
set(LINE " ${CMAKE_MATCH_1}: ${CMAKE_MATCH_2}")
else(NOT IN_PARAMS)
set(LINE "Args:\\n ${CMAKE_MATCH_1} ${CMAKE_MATCH_2}: ${CMAKE_MATCH_3}")
set(LINE "\\nArgs:\\n ${CMAKE_MATCH_1}: ${CMAKE_MATCH_2}")
set(IN_PARAMS ON)
endif()
endif()
......@@ -87,4 +87,4 @@ function(transfer_doc_string PYTHON_BINDING_FILE PYTHON_BINDING_FILE_OUT)
# # To insert docstrings in cpp file
# set(Docstring_${FUNCTION} ${DOCSTRING})
configure_file(${PYTHON_BINDING_FILE} ${PYTHON_BINDING_FILE_OUT} @ONLY)
endfunction()
\ No newline at end of file
endfunction()
......@@ -919,7 +919,7 @@ HTML_FOOTER =
# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this
# tag will in the future become obsolete.
HTML_STYLESHEET = css_files/theme.css
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional
# user-defined cascading style sheet that is included after the standard
......@@ -929,7 +929,7 @@ HTML_STYLESHEET = css_files/theme.css
# robust against future updates. Doxygen will copy the style sheet file to
# the output directory.
HTML_EXTRA_STYLESHEET = css_files/theme_extra.css
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
......@@ -1293,7 +1293,7 @@ EXTRA_SEARCH_MAPPINGS =
# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
# generate Latex output.
GENERATE_LATEX = YES
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be
......
......@@ -17,17 +17,178 @@
# -- Project information -----------------------------------------------------
from sphinx.builders.html import StandaloneHTMLBuilder
import subprocess, os
import subprocess, os, re
from sphinx.ext.napoleon.docstring import GoogleDocstring
# Boost conversion utilities adapted from minieigen: http://eudoxos.github.io/minieigen/#overview
def isBoostFunc(what, obj):
return what == "function" and obj.__repr__().startswith(
"<Boost.Python.function object at 0x"
)
def isBoostMethod(what, obj):
"I don't know how to distinguish boost and non-boost methods..."
return what == "method" and obj.__repr__().startswith("<unbound method ")
def isBoostStaticMethod(what, obj):
return what == "method" and obj.__repr__().startswith(
"<Boost.Python.function object at 0x"
)
def get_temp_lines(lines, start, end):
post_args = False
temp_lines = []
for line in lines[start:end]:
post_args = post_args or ("Args:" in line) or ("Returns:" in line)
temp_lines.append(line[4:] if post_args else line)
return temp_lines
def strip_sig(sig):
args = [
arg.split(")")[1].strip()
for arg in sig.replace("[", "").replace("]", "").split(",")
]
return sig.split("(")[0] + "(" + ", ".join(args) + ")" + sig.split(")")[-1]
def fixDocstring(app, what, name, obj, options, lines):
if (
isBoostFunc(what, obj)
or isBoostMethod(what, obj)
or isBoostStaticMethod(what, obj)
):
l2 = boostFuncSignature(name, obj)[1]
# we must replace lines one by one (in-place) :-|
# knowing that l2 is always shorter than lines (l2 is docstring with the signature stripped off)
for i in range(0, max(len(lines), len(l2))):
lines[i] = l2[i] if i < len(l2) else ""
func_inst = [
ii
for ii in range(len(lines))
if (")self" in lines[ii]) or (")arg1" in lines[ii])
]
if len(func_inst) == 0:
func_inst.append(len(lines))
elif func_inst[-1] != len(l2) - 1:
func_inst.append(len(lines))
temp_lines = get_temp_lines(lines, 0, func_inst[0])
docstrings = GoogleDocstring(
temp_lines, app.config, app, what, name, obj, options
).lines()
for ii in range(len(func_inst) - 1):
docstrings.append(lines[func_inst[ii]])
# docstrings.append(strip_sig(lines[func_inst[ii]]))
temp_lines = get_temp_lines(lines, func_inst[ii] + 1, func_inst[ii + 1])
docstrings += GoogleDocstring(
temp_lines,
app.config,
app,
what,
name,
obj,
options,
).lines()
lines[:] = docstrings[:]
def fixSignature(app, what, name, obj, options, signature, return_annotation):
if what in ("attribute", "class"):
return signature, None
elif isBoostFunc(what, obj):
sig = boostFuncSignature(name, obj)[0] or " (wrapped c++ function)"
return sig, None
elif isBoostMethod(what, obj):
sig = boostFuncSignature(name, obj, removeSelf=True)[0]
return sig, None
elif isBoostStaticMethod(what, obj):
sig = boostFuncSignature(name, obj, removeSelf=False)[0] + " [STATIC]"
return sig, None
def boostFuncSignature(name, obj, removeSelf=False):
"""Scan docstring of obj, returning tuple of properly formatted boost python signature
(first line of the docstring) and the rest of docstring (as list of lines).
The rest of docstring is stripped of 4 leading spaces which are automatically
added by boost.
removeSelf will attempt to remove the first argument from the signature.
"""
doc = obj.__doc__
if doc == None: # not a boost method
return None, None
nname = name.split(".")[-1]
docc = doc.split("\n")
if len(docc) < 2:
return None, docc
doc1 = docc[1]
# functions with weird docstring, likely not documented by boost
if not re.match("^" + nname + r"(.*)->.*$", doc1):
return None, docc
if doc1.endswith(":"):
doc1 = doc1[:-1]
strippedDoc = doc.split("\n")[2:]
# check if all lines are padded
allLinesHave4LeadingSpaces = True
for l in strippedDoc:
if l.startswith(" "):
continue
allLinesHave4LeadingSpaces = False
break
# remove the padding if so
if allLinesHave4LeadingSpaces:
strippedDoc = [l[4:] for l in strippedDoc]
for i in range(len(strippedDoc)):
# fix signatures inside docstring (one function with multiple signatures)
strippedDoc[i], n = re.subn(
r"([a-zA-Z_][a-zA-Z0-9_]*\() \(object\)arg1(, |)",
r"\1",
strippedDoc[i].replace("->", "→"),
)
# inspect dosctring after mangling
sig = doc1.split("(", 1)[1]
if removeSelf:
# remove up to the first comma; if no comma present, then the method takes no arguments
# if [ precedes the comma, add it to the result (ugly!)
try:
ss = sig.split(",", 1)
if ss[0].endswith("["):
sig = "[" + ss[1]
else:
sig = ss[1]
except IndexError:
# grab the return value
try:
sig = ") -> " + sig.split("->")[-1]
except IndexError:
sig = ")"
return strip_sig(sig), strippedDoc
def setup(app):
app.connect("autodoc-process-docstring", fixDocstring)
app.connect("autodoc-process-signature", fixSignature)
# Doxygen
subprocess.call('doxygen Doxyfile.in', shell=True)
subprocess.call("doxygen Doxyfile.in", shell=True)
project = 'SISSO++'
copyright = '2021, Thomas A. R. Purcelll'
author = 'Thomas A. R. Purcelll'
project = "SISSO++"
copyright = "2021, Thomas A. R. Purcelll"
author = "Thomas A. R. Purcelll"
# The full version, including alpha/beta/rc tags
release = '1.0'
release = "1.0"
# -- General configuration ---------------------------------------------------
......@@ -36,28 +197,28 @@ release = '1.0'
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'myst_parser',
'sphinx.ext.autodoc',
'sphinx.ext.napoleon',
'sphinx.ext.intersphinx',
'sphinx.ext.autosectionlabel',
'sphinx.ext.todo',
'sphinx.ext.coverage',
'sphinx.ext.mathjax',
'sphinx.ext.ifconfig',
'sphinx.ext.viewcode',
'sphinx_sitemap',
'sphinx.ext.inheritance_diagram',
'breathe',
"myst_parser",
"sphinx.ext.autodoc",
"sphinx.ext.napoleon",
"sphinx.ext.intersphinx",
"sphinx.ext.autosectionlabel",
"sphinx.ext.todo",
"sphinx.ext.coverage",
"sphinx.ext.mathjax",
"sphinx.ext.ifconfig",
"sphinx.ext.viewcode",
"sphinx_sitemap",
"sphinx.ext.inheritance_diagram",
"breathe",
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
templates_path = ["_templates"]
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# -- Options for HTML output -------------------------------------------------
......@@ -65,30 +226,26 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_rtd_theme"
html_theme_options = {
'canonical_url': '',
'analytics_id': '',
'display_version': True,
'prev_next_buttons_location': 'bottom',
'style_external_links': False,
'logo_only': False,
"canonical_url": "",
"analytics_id": "",
"display_version": True,
"prev_next_buttons_location": "bottom",
"style_external_links": False,
"logo_only": False,
# Toc options
'collapse_navigation': True,
'sticky_navigation': True,
'navigation_depth': 4,
'includehidden': True,
'titles_only': False
"collapse_navigation": True,
"sticky_navigation": True,
"navigation_depth": 4,
"includehidden": True,
"titles_only": False,
}
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_static_path = ["_static"]
breathe_projects = {
"SISSO++": "_build/xml/"
}
breathe_projects = {"SISSO++": "_build/xml/"}
breathe_default_project = "SISSO++"
breathe_default_members = ('members', 'undoc-members')
breathe_default_members = ("members", "undoc-members")
......@@ -28,5 +28,5 @@ Table of Contents
quick_start/QuickStart
tutorial/tutorial
cpp_api/cpp_api
python_api/py_api
python_api/python_api
development/develop
This diff is collapsed.
.. _py_api_di:
Descriptor Identification
=========================
.. toctree::
:maxdepth: 2
Solvers
-------
.. toctree::
:maxdepth: 2
py_solvers
Models
------
.. toctree::
:maxdepth: 2
py_model
.. _py_api_fc:
Feature Creation
================
.. toctree::
:maxdepth: 2
Nodes
-----
.. toctree::
:maxdepth: 3
py_node
py_node_utils
Feature Space
-------------
.. toctree::
:maxdepth: 2
py_FeatureSpace
.. _py_api_feat_space:
Feature Space
=============
.. toctree::
:maxdepth: 2
FeatureSpace
------------
.. autoclass:: sissopp.FeatureSpace
:special-members: __init__
:members:
:undoc-members:
.. _py_api_models:
Models
======
.. toctree::
:maxdepth: 2
Model
-----
.. autoclass:: sissopp.Model
:special-members:
:members:
:undoc-members:
ModelClassifier
---------------
.. autoclass:: sissopp.ModelClassifier
:special-members:
:members:
:undoc-members:
ModelRegressor
--------------
.. autoclass:: sissopp.ModelRegressor
:special-members:
:members:
:undoc-members:
ModelLogRegressor
-----------------
.. autoclass:: sissopp.ModelLogRegressor
:special-members:
:members:
:undoc-members:
.. _py_api_node:
Nodes
=====
.. toctree::
:maxdepth: 2
Node
----
.. autoclass:: sissopp.Node
:special-members:
:members:
:undoc-members:
FeatureNode
-----------
.. autoclass:: sissopp.FeatureNode
:special-members:
:members:
:undoc-members:
ModelNode
---------
.. autoclass:: sissopp.ModelNode
:special-members:
:members:
:undoc-members:
OperatorNode
------------
.. autoclass:: sissopp.OperatorNode
:special-members:
:members:
:undoc-members:
AddNode
-------
.. autoclass:: sissopp.AddNode
:special-members:
:members:
:undoc-members:
SubNode
-------
.. autoclass:: sissopp.SubNode
:special-members:
:members:
:undoc-members:
AbsDiffNode
-----------
.. autoclass:: sissopp.AbsDiffNode
:special-members:
:members:
:undoc-members:
MultNode
--------
.. autoclass:: sissopp.MultNode
:special-members:
:members:
:undoc-members:
DivNode
-------
.. autoclass:: sissopp.DivNode
:special-members:
:members:
:undoc-members:
InvNode
-------
.. autoclass:: sissopp.InvNode
:special-members:
:members:
:undoc-members:
SqNode
------
.. autoclass:: sissopp.SqNode
:special-members:
:members:
:undoc-members:
CbNode
------
.. autoclass:: sissopp.CbNode
:special-members:
:members:
:undoc-members:
SixPowNode
----------
.. autoclass:: sissopp.SixPowNode
:special-members:
:members:
:undoc-members:
SqrtNode
--------
.. autoclass:: sissopp.SqrtNode
:special-members:
:members:
:undoc-members:
CbrtNode
--------
.. autoclass:: sissopp.CbrtNode
:special-members:
:members:
:undoc-members:
ExpNode
-------
.. autoclass:: sissopp.ExpNode
:special-members:
:members:
:undoc-members:
NegExpNode
----------
.. autoclass:: sissopp.NegExpNode
:special-members:
:members:
:undoc-members:
LogNode
-------
.. autoclass:: sissopp.LogNode
:special-members:
:members:
:undoc-members:
SinNode
-------
.. autoclass:: sissopp.SinNode
:special-members:
:members:
:undoc-members:
CosNode
-------
.. autoclass:: sissopp.CosNode
:special-members:
:members:
:undoc-members:
AbsNode
-------
.. autoclass:: sissopp.AbsNode
:special-members:
:members:
:undoc-members:
AddParamNode
------------
.. autoclass:: sissopp.AddParamNode
:special-members:
:members:
:undoc-members:
SubParamNode
------------
.. autoclass:: sissopp.SubParamNode
:special-members:
:members:
:undoc-members:
AbsDiffParamNode
----------------
.. autoclass:: sissopp.AbsDiffParamNode
:special-members:
:members:
:undoc-members:
MultParamNode
-------------
.. autoclass:: sissopp.MultParamNode
:special-members:
:members:
:undoc-members: