1# Configuration file for the Sphinx documentation builder. 2# 3# For information on options, see 4# http://www.sphinx-doc.org/en/master/config 5# 6 7import os 8import sys 9import subprocess 10import re 11import datetime 12import shutil 13import time 14 15sys.path.append(os.getcwd()) 16sys.path.append(os.path.abspath('./ext')) 17 18import add_man_page_redirects 19import build_classic_docs 20import fix_man_page_edit_links 21import make_links_relative 22import update_htmlmap_links 23import fix_pydata_margins 24 25 26if not os.path.isdir("images"): 27 print("-----------------------------------------------------------------------------") 28 print("ERROR") 29 print("images directory does not seem to exist.") 30 print("To clone the required repository, try") 31 print(" make images") 32 print("-----------------------------------------------------------------------------") 33 raise Exception("Aborting because images missing") 34 35 36# -- Project information ------------------------------------------------------- 37 38project = 'PETSc' 39copyright = '1991-%d, UChicago Argonne, LLC and the PETSc Development Team' % datetime.date.today().year 40author = 'The PETSc Development Team' 41 42with open(os.path.join('..', 'include', 'petscversion.h'),'r') as version_file: 43 buf = version_file.read() 44 petsc_release_flag = re.search(' PETSC_VERSION_RELEASE[ ]*([0-9]*)',buf).group(1) 45 major_version = re.search(' PETSC_VERSION_MAJOR[ ]*([0-9]*)',buf).group(1) 46 minor_version = re.search(' PETSC_VERSION_MINOR[ ]*([0-9]*)',buf).group(1) 47 subminor_version = re.search(' PETSC_VERSION_SUBMINOR[ ]*([0-9]*)',buf).group(1) 48 49 git_describe_version = subprocess.check_output(['git', 'describe', '--always']).strip().decode('utf-8') 50 if petsc_release_flag == '0': 51 version = git_describe_version 52 release = git_describe_version 53 else: 54 version = '.'.join([major_version, minor_version]) 55 release = '.'.join([major_version,minor_version,subminor_version]) 56 57 58# -- General configuration ----------------------------------------------------- 59 60# The information on the next line must also be the same in requirements.txt 61needs_sphinx='5.3' 62nitpicky = True # checks internal links. For external links, use "make linkcheck" 63master_doc = 'index' 64templates_path = ['_templates'] 65exclude_patterns = ['_build*', 'images', 'Thumbs.db', '.DS_Store','community/meetings/pre-2023'] 66highlight_language = 'c' 67numfig = True 68 69# -- Extensions ---------------------------------------------------------------- 70 71extensions = [ 72 'sphinx_copybutton', 73 'sphinx_design', 74 'sphinxcontrib.bibtex', 75 'sphinxcontrib.katex', 76 'sphinxcontrib.rsvgconverter', 77 'myst_parser', 78 'html5_petsc', 79 'sphinx_remove_toctrees', 80] 81 82copybutton_prompt_text = '$ ' 83 84bibtex_bibfiles = ['petsc.bib'] 85 86myst_enable_extensions = ["fieldlist", "dollarmath", "amsmath", "deflist"] 87 88remove_from_toctrees = ['manualpages/*/[A-Z]*','changes/2*','changes/3*'] 89 90# prevents incorrect WARNING: duplicate citation for key "xxxx" warnings 91suppress_warnings = ['bibtex.duplicate_citation'] 92 93# -- Options for HTML output --------------------------------------------------- 94 95html_theme = 'pydata_sphinx_theme' 96 97html_logo_light = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB.svg') 98html_logo_dark = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB_white.svg') 99 100html_static_path = ['_static', html_logo_light, html_logo_dark] 101 102# use much smaller font for h1, h2 etc. They are absurdly large in the standard style 103# https://pydata-sphinx-theme.readthedocs.io/en/v0.12.0/user_guide/styling.html 104html_css_files = [ 105 'css/custom.css', 106] 107 108html_theme_options = { 109 "icon_links": [ 110 { 111 "name": "GitLab", 112 "url": "https://gitlab.com/petsc/petsc", 113 "icon": "fab fa-gitlab", 114 }, 115 ], 116 "use_edit_page_button": True, 117 "footer_items": ["copyright", "sphinx-version", "last-updated"], 118# "secondary_sidebar_items" : ["edit-this-page"], 119 "header_links_before_dropdown": 10, 120 "logo": { 121 "image_light": os.path.basename(html_logo_light), 122 "image_dark": os.path.basename(html_logo_dark) 123 }, 124 "navigation_with_keys":True 125} 126 127try: 128 git_ref = subprocess.check_output(["git", "rev-parse", "HEAD"]).rstrip() 129 git_ref_release = subprocess.check_output(["git", "rev-parse", "origin/release"]).rstrip() 130 edit_branch = "release" if git_ref == git_ref_release else "main" 131except subprocess.CalledProcessError: 132 print("WARNING: determining branch for page edit links failed") 133 edit_branch = "main" 134 135html_context = { 136 "github_url": "https://gitlab.com", 137 "github_user": "petsc", 138 "github_repo": "petsc", 139 "github_version": edit_branch, 140 "doc_path": "doc", 141} 142 143html_logo = html_logo_light 144html_favicon = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc', 'petsc_favicon.png') 145html_last_updated_fmt = r'%Y-%m-%dT%H:%M:%S%z (' + git_describe_version + ')' 146 147 148# -- Options for LaTeX output -------------------------------------------------- 149latex_engine = 'xelatex' 150 151# How to arrange the documents into LaTeX files, building only the manual. 152latex_documents = [ 153 ('manual/index', 'manual.tex', 'PETSc/TAO Users Manual', author, 'manual', False) 154 ] 155 156latex_additional_files = [ 157 'images/manual/anl_tech_report/ArgonneLogo.pdf', 158 'images/manual/anl_tech_report/ArgonneReportTemplateLastPage.pdf', 159 'images/manual/anl_tech_report/ArgonneReportTemplatePage2.pdf', 160 'manual/anl_tech_report/first.inc', 161 'manual/anl_tech_report/last.inc', 162] 163 164latex_elements = { 165 'maketitle': r'\newcommand{\techreportversion}{%s}' % version + 166r''' 167\input{first.inc} 168''', 169 'printindex': r''' 170\printindex 171\input{last.inc} 172''', 173 'fontpkg': r''' 174\setsansfont{DejaVu Sans} 175\setmonofont{DejaVu Sans Mono} 176''', 177 'tableofcontents' : r'' 178} 179 180# -- Setup and event callbacks ------------------------------------------------- 181 182def setup(app): 183 app.connect('builder-inited', builder_init_handler) 184 app.connect('build-finished', build_finished_handler) 185 186 187def builder_init_handler(app): 188 global xtime 189 if app.builder.name.endswith('html'): 190 _build_classic_docs(app, 'pre') 191 _update_htmlmap_links(app) 192 ptype = 'html' 193 else: ptype = 'pdf' 194 print("============================================") 195 print(" Running Sphinx on PETSc " + ptype) 196 xtime = time.clock_gettime(time.CLOCK_REALTIME) 197 198 199def build_finished_handler(app, exception): 200 global xtime 201 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - xtime)) 202 print("============================================") 203 if app.builder.name.endswith('html'): 204 _build_classic_docs(app, 'post') 205 build_petsc4py_docs(app) 206 _fix_links(app, exception) 207 _fix_man_page_edit_links(app, exception) 208 fix_pydata_margins.fix_pydata_margins(app.outdir) 209 if app.builder.name == 'dirhtml': 210 _add_man_page_redirects(app, exception) 211 # remove sources for manual pages since they are automatically generated and should not be looked at on the website 212 if os.path.isdir(os.path.join(app.outdir,'_sources','manualpages')): 213 shutil.rmtree(os.path.join(app.outdir,'_sources','manualpages')) 214 if app.builder.name == 'html': 215 print("==========================================================================") 216 print(" open %s/index.html in your browser to view the documentation " % app.outdir) 217 print("==========================================================================") 218 219def _add_man_page_redirects(app, exception): 220 if exception is None: 221 import time 222 print("============================================") 223 print(" Adding man pages redirects") 224 x = time.clock_gettime(time.CLOCK_REALTIME) 225 add_man_page_redirects.add_man_page_redirects(app.outdir) 226 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 227 print("============================================") 228 229def _build_classic_docs(app, stage): 230 '''Builds the .md versions of the manual pages and the .html version of the source code''' 231 build_classic_docs.main(stage,app.outdir) 232 233def _fix_man_page_edit_links(app, exception): 234 if exception is None: 235 import time 236 print("============================================") 237 print(" Fixing manual page edit links") 238 x = time.clock_gettime(time.CLOCK_REALTIME) 239 fix_man_page_edit_links.fix_man_page_edit_links(app.outdir) 240 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 241 print("============================================") 242 243# 244# The following two scripts are needed because the Sphinx html and dirhtml builds save the output html 245# files at different levels of the directory hierarchy. file.rst -> file.html with html but 246# file.rst -> file/index.html with dirhtml and we want both to work correctly using relative links. 247 248def _fix_links(app, exception): 249 """We need to manage our own relative paths in the User's Manual for the source code files which 250 are auto-generated by c2html outside of Sphinx so Sphinx cannot directly handle those links for use. 251 We use the string PETSC_DOC_OUT_ROOT_PLACEHOLDER in URLs in the Sphinx .rst files as a stand in 252 for the root directory that needs to be constructed based on if the Sphinx build is html or dirhtml 253 """ 254 if exception is None: 255 import time 256 print("============================================") 257 print(" Fixing relative links") 258 x = time.clock_gettime(time.CLOCK_REALTIME) 259 make_links_relative.make_links_relative(app.outdir) 260 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 261 print("============================================") 262 263 264def _update_htmlmap_links(app): 265 """htmlmap maps from manualpage names to relative locations in the generated documentation directory 266 hierarchy. The format of the directory location needs to be different for the Sphinx html and dirhtml 267 builds 268 """ 269 import time 270 print("============================================") 271 print(" Updating htmlmap") 272 x = time.clock_gettime(time.CLOCK_REALTIME) 273 update_htmlmap_links.update_htmlmap_links(app.builder,os.path.join('manualpages','htmlmap')) 274 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 275 print("============================================") 276 277def build_petsc4py_docs(app): 278 petsc_dir = os.path.dirname(os.path.abspath(os.path.join(__file__,'..'))) 279 petsc_arch = 'arch-classic-docs' 280 281 # petsc4py needs to be built to build petsc4py docs via introspection 282 command = ['make', 'all', 283 'PETSC_DIR=%s' % petsc_dir, 284 'PETSC_ARCH=%s' % petsc_arch] 285 import time 286 print('==============================================') 287 print('Building library to make petsc4py docs') 288 print(command) 289 x = time.clock_gettime(time.CLOCK_REALTIME) 290 subprocess.run(command, cwd=petsc_dir, check=True) 291 print("End building library for petsc4py docs Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 292 print('==============================================') 293 294 command = ['make', 'website', 295 'PETSC_DIR=%s' % petsc_dir, 296 'PETSC_ARCH=%s' % petsc_arch, 297 'LOC=%s' % app.outdir] 298 print('============================================') 299 print('Building petsc4py docs') 300 print(command) 301 x = time.clock_gettime(time.CLOCK_REALTIME) 302 subprocess.run(command, cwd=os.path.join(petsc_dir,'src','binding','petsc4py'), check=True) 303 print("End petsc4py docs Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 304 print('============================================') 305