evennia/docs/source/conf.py

326 lines
9.6 KiB
Python
Raw Normal View History

2020-04-05 00:02:02 +02:00
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
import os
import sys
2020-07-10 14:14:34 +02:00
import re
2020-06-14 11:45:10 +02:00
import sphinx_theme
2020-04-05 00:02:02 +02:00
from recommonmark.transform import AutoStructify
from sphinx.util.osutil import cd
# -- Project information -----------------------------------------------------
2020-06-14 11:45:10 +02:00
project = "Evennia"
copyright = "2020, The Evennia developer community"
author = "The Evennia developer community"
# The full Evennia version covered by these docs, including alpha/beta/rc tags
# This will be used for multi-version selection options.
release = "1.0-dev"
2020-04-05 00:02:02 +02:00
# -- General configuration ---------------------------------------------------
extensions = [
"recommonmark",
2020-04-05 15:02:38 +02:00
"sphinx_multiversion",
2020-04-05 16:50:52 +02:00
"sphinx.ext.napoleon",
2020-04-07 23:13:24 +02:00
"sphinx.ext.autosectionlabel",
2020-04-10 17:38:26 +02:00
"sphinx.ext.viewcode",
# "sphinxcontrib.lunrsearch",
2020-06-14 11:45:10 +02:00
"sphinx.ext.todo",
"sphinx.ext.githubpages",
2020-04-05 00:02:02 +02:00
]
2020-06-16 14:50:02 +02:00
source_suffix = [".md", ".rst"]
master_doc = "index"
2020-06-14 20:19:31 +02:00
2020-04-05 15:02:38 +02:00
# make sure sectionlabel references can be used as path/to/file:heading
autosectionlabel_prefix_document = True
2020-04-05 00:02:02 +02:00
# Add any paths that contain templates here, relative to this directory.
2020-06-14 11:45:10 +02:00
templates_path = ["_templates"]
2020-04-09 08:39:55 +02:00
# 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".
2020-06-14 11:45:10 +02:00
html_static_path = ["_static"]
# -- Sphinx-multiversion config ----------------------------------------------
# which branches to include in multi-versioned docs
# - master, develop and vX.X branches
smv_branch_whitelist = r"^master$|^develop$|^v[0-9\.]+?$"
smv_outputdir_format = "{config.release}"
# don't make docs for tags
smv_tag_whitelist = r"^$"
# -- Options for HTML output -------------------------------------------------
2020-06-16 14:50:02 +02:00
html_theme = "nature"
2020-04-09 08:39:55 +02:00
# Custom extras for sidebar
html_sidebars = {
2020-06-14 11:45:10 +02:00
"**": [
2020-04-09 08:39:55 +02:00
"searchbox.html",
"localtoc.html",
# "globaltoc.html",
"relations.html",
"sourcelink.html",
"versioning.html",
]
}
2020-06-15 21:30:49 +02:00
html_favicon = "_static/images/favicon.ico"
html_logo = "_static/images/evennia_logo.png"
2020-06-19 18:11:20 +02:00
html_short_title = f"Evennia {release}"
2020-04-05 00:02:02 +02:00
2020-06-14 11:45:10 +02:00
# HTML syntax highlighting style
pygments_style = "sphinx"
2020-04-05 00:02:02 +02:00
2020-06-14 20:19:31 +02:00
# -- Options for LaTeX output ------------------------------------------------
# experimental, not working well atm
2020-06-16 14:50:02 +02:00
latex_engine = "xelatex"
latex_show_urls = "footnote"
2020-06-14 20:19:31 +02:00
latex_elements = {
2020-06-16 14:50:02 +02:00
"papersize": "a4paper",
"fncychap": r"\usepackage[Bjarne]{fncychap}",
"fontpkg": r"\usepackage{times,amsmath,amsfonts,amssymb,amsthm}",
"preamble": r"""
2020-06-14 20:19:31 +02:00
\usepackage[utf8]{fontenc}
\usepackage{amsmath,amsfonts,amssymb,amsthm}
\usepackage[math-style=literal]{unicode-math}
\usepackage{newunicodechar}
\usepackage{graphicx}
2020-06-16 14:50:02 +02:00
""",
2020-06-14 20:19:31 +02:00
}
latex_documents = [
2020-06-16 14:50:02 +02:00
(master_doc, "main.tex", "Sphinx format", "Evennia", "report"),
("toc", "toc.tex", "TOC", "Evennia", "report"),
2020-06-14 20:19:31 +02:00
]
2020-06-14 11:45:10 +02:00
# -- Recommonmark ------------------------------------------------------------
# allows for writing Markdown and convert to rst dynamically
2020-04-07 23:13:24 +02:00
# reroute to github links or to the api
2020-04-05 12:32:52 +02:00
2020-06-14 20:19:31 +02:00
_github_code_root = "https://github.com/evennia/evennia/blob/"
2020-04-07 23:13:24 +02:00
_github_doc_root = "https://github.com/evennia/tree/master/docs/sources/"
_github_issue_choose = "https://github.com/evennia/evennia/issues/new/choose"
2020-04-05 16:50:52 +02:00
2020-04-05 16:50:52 +02:00
def url_resolver(url):
2020-06-23 00:13:21 +02:00
"""
2020-07-10 14:14:34 +02:00
Convert urls by catching special markers.
2020-06-23 00:13:21 +02:00
"""
2020-06-14 20:19:31 +02:00
githubstart = "github:"
apistart = "api:"
2020-06-23 00:13:21 +02:00
choose_issue = "github:issue"
2020-07-07 00:18:47 +02:00
sourcestart = "src:"
2020-07-10 14:14:34 +02:00
2020-06-23 00:13:21 +02:00
if url.endswith(choose_issue):
return _github_issue_choose
2020-06-23 00:13:21 +02:00
elif githubstart in url:
urlpath = url[url.index(githubstart) + len(githubstart):]
2020-06-14 20:19:31 +02:00
if not (urlpath.startswith("develop/") or urlpath.startswith("master")):
urlpath = "master/" + urlpath
2020-06-14 20:19:31 +02:00
return _github_code_root + urlpath
2020-06-23 00:13:21 +02:00
elif apistart in url:
2020-07-06 20:48:21 +02:00
# locate the api/ folder in the doc structure
ind = url.index(apistart)
depth = url[:ind].count("/") + 1
path = "../".join("" for _ in range(depth))
urlpath = path + "api/" + url[ind + len(apistart):] + ".html"
return urlpath
2020-07-07 00:18:47 +02:00
elif sourcestart in url:
ind = url.index(sourcestart)
depth = url[:ind].count("/") + 1
path = "../".join("" for _ in range(depth))
modpath, *inmodule = url[ind + len(sourcestart):].rsplit("#", 1)
modpath = "/".join(modpath.split("."))
inmodule = "#" + inmodule[0] if inmodule else ""
modpath = modpath + ".html" + inmodule
urlpath = path + "_modules/" + modpath
return urlpath
2020-06-12 20:33:11 +02:00
return url
2020-04-05 16:50:52 +02:00
# auto-create TOCs if a list of links is under these headers
2020-06-19 18:11:20 +02:00
auto_toc_sections = ["Contents", "Toc", "Index", "API", "Overview"]
2020-04-09 08:39:55 +02:00
recommonmark_config = {
"enable_auto_toc_tree": True,
"url_resolver": url_resolver,
2020-06-15 20:08:00 +02:00
"auto_toc_maxdepth": 1,
"auto_toc_tree_section": ["Contents", "Toc", "Index"],
2020-06-14 11:45:10 +02:00
"code_highlight_options": {"force": True, "linenos": True},
}
# -- API/Autodoc ---------------------------------------------------------------
# automatic creation of API documentation. This requires a valid Evennia setup
_no_autodoc = os.environ.get("NOAUTODOC")
ansi_clean = None
2020-06-14 11:45:10 +02:00
if not _no_autodoc:
# we must set up Evennia and its paths for autodocs to work
EV_ROOT = os.environ.get("EVDIR")
GAME_DIR = os.environ.get("EVGAMEDIR")
if not (EV_ROOT and GAME_DIR):
err = (
"The EVDIR and EVGAMEDIR environment variables must be set to "
"the absolute paths to the evennia/ repo and an initialized "
"evennia gamedir respectively."
)
raise RuntimeError(err)
print("Evennia root: {}, Game dir: {}".format(EV_ROOT, GAME_DIR))
sys.path.insert(1, EV_ROOT)
sys.path.insert(1, GAME_DIR)
with cd(GAME_DIR):
# set up Evennia so its sources can be parsed
os.environ["DJANGO_SETTINGS_MODULE"] = "server.conf.settings"
import django # noqa
django.setup()
import evennia # noqa
evennia._init()
from evennia.utils.ansi import strip_raw_ansi as ansi_clean
2020-06-14 11:45:10 +02:00
if _no_autodoc:
exclude_patterns = ["api/*"]
else:
2020-07-10 17:58:07 +02:00
exclude_patterns = ["api/*migrations.rst"]
2020-06-14 11:45:10 +02:00
autodoc_default_options = {
"members": True,
2020-06-18 23:30:11 +02:00
"undoc-members": False,
2020-06-14 11:45:10 +02:00
"show-inheritance": True,
"special-members": "__init__",
"enable_eval_rst": True,
2020-07-10 17:58:07 +02:00
# "inherited_members": True
}
2020-06-18 23:30:11 +02:00
autodoc_member_order = "bysource"
autodoc_typehints = "description"
2020-04-05 12:32:52 +02:00
2020-06-14 11:45:10 +02:00
def autodoc_skip_member(app, what, name, obj, skip, options):
2020-06-18 23:30:11 +02:00
"""Which members the autodoc should ignore."""
2020-06-14 11:45:10 +02:00
if _no_autodoc:
return True
2020-06-18 23:30:11 +02:00
if name.startswith("_") and name != "__init__":
2020-06-14 11:45:10 +02:00
return True
return False
2020-07-10 14:14:34 +02:00
def autodoc_post_process_docstring(app, what, name, obj, options, lines):
"""
Post-process docstring in various ways. Must modify lines-list in-place.
"""
try:
# clean out ANSI colors
if ansi_clean:
for il, line in enumerate(lines):
lines[il] = ansi_clean(line)
# post-parse docstrings to convert any remaining
# markdown -> reST since napoleon doesn't know Markdown
def _sub_codeblock(match):
code = match.group(1)
return "::\n\n {}".format(
"\n ".join(lne for lne in code.split("\n")))
2020-07-10 18:04:55 +02:00
underline_map = {
1: "-",
2: "=",
3: '^',
4: '"',
}
def _sub_header(match):
# add underline to convert a markdown #header to ReST
groupdict = match.groupdict()
hashes, title = groupdict["hashes"], groupdict["title"]
title = title.strip()
lvl = min(max(1, len(hashes)), 4)
return f"{title}\n" + (underline_map[lvl] * len(title))
2020-07-10 14:14:34 +02:00
doc = "\n".join(lines)
doc = re.sub(r"```python\s*\n+(.*?)```", _sub_codeblock, doc,
flags=re.MULTILINE + re.DOTALL)
doc = re.sub(r"```", "", doc, flags=re.MULTILINE)
doc = re.sub(r"`{1}", "**", doc, flags=re.MULTILINE)
2020-07-10 18:04:55 +02:00
doc = re.sub(r"^(?P<hashes>#{1,2})\s*?(?P<title>.*?)$", _sub_header, doc, flags=re.MULTILINE)
2020-07-10 14:14:34 +02:00
newlines = doc.split("\n")
# we must modify lines in-place
lines[:] = newlines[:]
except Exception as err:
# if we don't print here we won't see what the error actually is
print(f"Post-process docstring exception: {err}")
raise
2020-06-18 23:30:11 +02:00
2020-06-14 11:45:10 +02:00
# Napoleon Google-style docstring parser for autodocs
napoleon_google_docstring = True
napoleon_numpy_docstring = False
napoleon_include_init_with_doc = False
napoleon_include_private_with_doc = False
napoleon_include_special_with_doc = False
2020-07-10 14:14:34 +02:00
napoleon_use_admonition_for_examples = False
2020-06-14 11:45:10 +02:00
napoleon_use_admonition_for_notes = False
napoleon_use_admonition_for_references = False
napoleon_use_ivar = False
napoleon_use_param = True
napoleon_use_keyword = True
2020-06-18 23:30:11 +02:00
napoleon_use_rtype = False
2020-06-14 11:45:10 +02:00
# -- Main config setup ------------------------------------------
# last setup steps for some plugins
2020-06-16 14:50:02 +02:00
2020-04-05 00:02:02 +02:00
def setup(app):
2020-04-05 16:50:52 +02:00
app.connect("autodoc-skip-member", autodoc_skip_member)
2020-07-10 14:14:34 +02:00
app.connect("autodoc-process-docstring", autodoc_post_process_docstring)
2020-04-05 00:02:02 +02:00
app.add_transform(AutoStructify)
# build toctree file
2020-06-16 14:50:02 +02:00
sys.path.insert(1, os.path.join(os.path.dirname(os.path.dirname(__file__)), "docs"))
2020-07-12 18:10:13 +02:00
from docs.pylib import auto_link_remapper
2020-06-16 14:50:02 +02:00
2020-07-12 18:10:13 +02:00
auto_link_remapper.auto_link_remapper()
print("Updated source/toc.md file")
# custom lunr-based search
# from docs import search
# custom search
# search.setup(app)