docs: add Sphinx documentation build and deploy workflow
- Add Gitea Actions workflow to build and deploy docs on push to main - Generate Sphinx reference documentation for all apps and modules - Deploy versioned and latest docs via rsync over SSH
This commit is contained in:
97
docs/source/conf.py
Normal file
97
docs/source/conf.py
Normal file
@@ -0,0 +1,97 @@
|
||||
import os
|
||||
import sys
|
||||
import tomllib
|
||||
|
||||
# The Django package lives at <repo>/mnemosyne/<inner mnemosyne>/. Adding the
|
||||
# outer mnemosyne/ directory to sys.path lets autodoc resolve every app
|
||||
# (themis, library, llm_manager, mcp_server) and the project settings module.
|
||||
sys.path.insert(0, os.path.abspath('../../mnemosyne'))
|
||||
|
||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mnemosyne.settings')
|
||||
|
||||
# Load real .env if present (local dev). In CI there is none and that's fine —
|
||||
# settings.py provides a default for every env var it reads, so the import
|
||||
# succeeds either way.
|
||||
_repo_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||
_env_file = os.path.join(_repo_root, 'mnemosyne', '.env')
|
||||
if os.path.exists(_env_file):
|
||||
with open(_env_file) as _f:
|
||||
for _line in _f:
|
||||
_line = _line.strip()
|
||||
if not _line or _line.startswith('#') or '=' not in _line:
|
||||
continue
|
||||
_key, _val = _line.split('=', 1)
|
||||
os.environ.setdefault(_key.strip(), _val.strip())
|
||||
|
||||
import django # noqa: E402
|
||||
|
||||
django.setup()
|
||||
|
||||
# Sphinx autodoc calls repr() on every class attribute it documents. Django's
|
||||
# QuerySet.__repr__ executes a SELECT against the database — which doc builds
|
||||
# have no business doing. Intercept object_description so QuerySet instances
|
||||
# render as a static string instead. Mnemosyne's themis app has at least one
|
||||
# DRF viewset with a class-level queryset attribute, so this matters.
|
||||
from django.db.models.query import QuerySet # noqa: E402
|
||||
import sphinx.util.inspect as _sphinx_inspect # noqa: E402
|
||||
|
||||
_orig_object_description = _sphinx_inspect.object_description
|
||||
|
||||
|
||||
def _safe_object_description(obj, *args, **kwargs):
|
||||
if isinstance(obj, QuerySet):
|
||||
return f'<QuerySet [{obj.model.__name__}]>'
|
||||
return _orig_object_description(obj, *args, **kwargs)
|
||||
|
||||
|
||||
_sphinx_inspect.object_description = _safe_object_description
|
||||
|
||||
# ── Sphinx configuration ──────────────────────────────────────────────────
|
||||
project = 'Mnemosyne'
|
||||
copyright = '2026, Mnemosyne Team'
|
||||
author = 'Mnemosyne Team'
|
||||
|
||||
with open(os.path.join(_repo_root, 'pyproject.toml'), 'rb') as _f:
|
||||
release = tomllib.load(_f)['project']['version']
|
||||
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.viewcode',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx_autodoc_typehints',
|
||||
'sphinxcontrib.httpdomain',
|
||||
'sphinxcontrib.mermaid',
|
||||
'myst_parser',
|
||||
]
|
||||
|
||||
source_suffix = {'.rst': 'restructuredtext', '.md': 'markdown'}
|
||||
|
||||
myst_enable_extensions = ['colon_fence', 'deflist', 'tasklist', 'attrs_inline']
|
||||
myst_heading_anchors = 4
|
||||
|
||||
autodoc_default_options = {
|
||||
'members': True,
|
||||
'member-order': 'bysource',
|
||||
'special-members': '__init__',
|
||||
'undoc-members': True,
|
||||
'exclude-members': '__weakref__',
|
||||
}
|
||||
autodoc_inherit_docstrings = False
|
||||
napoleon_use_ivar = True
|
||||
|
||||
intersphinx_mapping = {
|
||||
'python': ('https://docs.python.org/3', None),
|
||||
'django': ('https://docs.djangoproject.com/en/stable/',
|
||||
'https://docs.djangoproject.com/en/stable/_objects/'),
|
||||
}
|
||||
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_static_path = ['_static']
|
||||
html_theme_options = {
|
||||
'navigation_depth': 4,
|
||||
'collapse_navigation': False,
|
||||
'sticky_navigation': True,
|
||||
'includehidden': True,
|
||||
'titles_only': False,
|
||||
}
|
||||
Reference in New Issue
Block a user