diff --git a/doc/conf.py b/doc/conf.py index e5649a486..a8403ff01 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,35 +1,25 @@ # 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 +# Official documentation: https://www.sphinx-doc.org/en/master/usage/configuration.html -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# import importlib import inspect import os import sys -sys.path.insert(0, os.path.abspath(".")) -sys.path.insert(0, os.path.abspath("../")) - -# -- Project information ----------------------------------------------------- +# -- Path setup -------------------------------------------------------------- +# Ensure project modules can be found by Sphinx +BASE_DIR = os.path.abspath("..") +sys.path.insert(0, BASE_DIR) +# -- Project Information ----------------------------------------------------- project = "grid" copyright = "2024, QC-Devs" author = "QC-Devs" html_logo = "./images/grid_logo_website.svg" -# -- General configuration --------------------------------------------------- - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. +# -- Sphinx Extensions ------------------------------------------------------- +# Add Sphinx extensions to enable features like autodoc, math rendering, and Jupyter notebook integration. extensions = [ "sphinx_rtd_theme", "sphinx.ext.autodoc", @@ -43,66 +33,28 @@ "sphinx.ext.linkcode", ] -# List of arguments to be passed to the kernel that executes the notebooks: +# -- Jupyter Notebook Settings for Documentation ----------------------------- nbsphinx_execute_arguments = [ "--InlineBackend.figure_formats={'svg', 'pdf'}", "--InlineBackend.rc=figure.dpi=200", ] -# nbsphinx_input_prompt = 'In [%s]:' -# nbsphinx_output_prompt = 'Out[%s]:' -# explicitly dis-/enabling notebook execution -nbsphinx_execute = "never" - -# Don't add .txt suffix to source files: -html_sourcelink_suffix = "" - -# This is processed by Jinja2 and inserted before each notebook +nbsphinx_execute = "never" # Prevent execution of notebooks during build -# nbsphinx_prolog = r""" -# nbsphinx_epilog = r""" -# {% set docname = env.docname.split("/")[-1] %} -# .. raw:: html -# .. role:: raw-html(raw) -# :format: html -# .. nbinfo:: -# The corresponding file can be obtained from: -# - Jupyter Notebook: :download:`{{docname+".ipynb"}}` -# - Interactive Jupyter Notebook: :raw-html:`Binder badge` """ - - -# Add any paths that contain templates here, relative to this directory. +# -- Source Files & Template Settings ---------------------------------------- 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", "**.ipynb_checkpoints"] - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# +# -- HTML Output Configuration ----------------------------------------------- html_theme = "sphinx_rtd_theme" - -# 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_style = "css/override.css" -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. html_theme_options = { "collapse_navigation": False, - "logo_only": True + "logo_only": True, } - -# -- Configuration for autodoc extensions --------------------------------- - +# -- Autodoc Configuration --------------------------------------------------- autodoc_default_options = { "undoc-members": True, "show-inheritance": True, @@ -111,60 +63,58 @@ "ignore-module-all": True, } - -add_module_names = False - +add_module_names = False # Prevents redundant module names in generated docs def autodoc_skip_member(app, what, name, obj, skip, options): - """Decide which parts to skip when building the API doc.""" + """ + Control which members are included in the generated documentation. + + - Always document `__init__` methods. + - Include test functions (e.g., `test_*`). + """ if name == "__init__": return False if name.startswith("test_"): return False return skip - def setup(app): - """Set up sphinx.""" + """Configure Sphinx extensions and event handlers.""" app.connect("autodoc-skip-member", autodoc_skip_member) - -# -- Link to Github ------------------------------ -# Configure viewcode extension. -code_url = f"https://github.com/theochem/grid/blob/master/src/grid" - +# -- GitHub Link for Source Code --------------------------------------------- +# Configure the 'viewcode' extension for linking to the GitHub repository. +GITHUB_REPO_URL = "https://github.com/theochem/grid/blob/master/src/grid" def linkcode_resolve(domain, info): - # Non-linkable objects from the starter kit in the tutorial. - if domain != 'py': - return None - if not info['module']: - return None + """ + Generate GitHub links for source code. - mod = importlib.import_module(info["module"]) - if "." in info["fullname"]: - objname, attrname = info["fullname"].split(".") - obj = getattr(mod, objname) - try: - # object is a method of a class - obj = getattr(obj, attrname) - except AttributeError: - # object is an attribute of a class - return None - else: - obj = getattr(mod, info["fullname"]) - try: - file = inspect.getsourcefile(obj) - lines = inspect.getsourcelines(obj) - except TypeError: - # e.g. object is a typing.Union + - Handles both module-level and class-level objects. + - Ensures proper error handling for missing or unrecognized objects. + """ + if domain != "py" or not info["module"]: return None - file = os.path.relpath(file, os.path.abspath("..")) - # Get the file name e.g. /usr/conda/py37/grid/angular.py -> angular.py - split = file.split("grid/") - file = split[-1] + try: + mod = importlib.import_module(info["module"]) + obj = mod + for part in info["fullname"].split("."): + obj = getattr(obj, part, None) + if obj is None: + return None + + file_path = inspect.getsourcefile(obj) + source_lines, start_line = inspect.getsourcelines(obj) + end_line = start_line + len(source_lines) - 1 + + if not file_path: + return None - start, end = lines[1], lines[1] + len(lines[0]) - 1 + # Normalize the path to match the repository structure + file_relpath = os.path.relpath(file_path, BASE_DIR).replace("\\", "/") - return f"{code_url}/{file}#L{start}-L{end}" + return f"{GITHUB_REPO_URL}/{file_relpath}#L{start_line}-L{end_line}" + + except (ImportError, AttributeError, TypeError): + return None