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_manpages_c2html 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 'sphinx_design', 81] 82 83copybutton_prompt_text = '$ ' 84 85bibtex_bibfiles = ['petsc.bib'] 86 87myst_enable_extensions = ["fieldlist", "dollarmath", "amsmath", "deflist", "colon_fence"] 88 89remove_from_toctrees = ['manualpages/*/[A-Z]*','changes/2*','changes/3*'] 90 91# prevents incorrect WARNING: duplicate citation for key "xxxx" warnings 92suppress_warnings = ['bibtex.duplicate_citation'] 93 94# -- Options for HTML output --------------------------------------------------- 95 96html_theme = 'pydata_sphinx_theme' 97 98html_logo_light = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB.svg') 99html_logo_dark = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc-TAO', 'web', 'PETSc-TAO_RGB_white.svg') 100 101html_static_path = ['_static', html_logo_light, html_logo_dark] 102 103# use much smaller font for h1, h2 etc. They are absurdly large in the standard style 104# https://pydata-sphinx-theme.readthedocs.io/en/v0.12.0/user_guide/styling.html 105html_css_files = [ 106 'css/custom.css', 107] 108 109html_theme_options = { 110 "icon_links": [ 111 { 112 "name": "GitLab", 113 "url": "https://gitlab.com/petsc/petsc", 114 "icon": "fab fa-gitlab", 115 }, 116 ], 117 "use_edit_page_button": True, 118 "footer_end": ["theme-version", "last-updated"], 119# "secondary_sidebar_items" : ["edit-this-page"], 120 "header_links_before_dropdown": 10, 121 "logo": { 122 "image_light": os.path.basename(html_logo_light), 123 "image_dark": os.path.basename(html_logo_dark) 124 }, 125 "navigation_with_keys":True 126} 127 128try: 129 git_ref = subprocess.check_output(["git", "rev-parse", "HEAD"]).rstrip() 130 git_ref_release = subprocess.check_output(["git", "rev-parse", "origin/release"]).rstrip() 131 edit_branch = "release" if git_ref == git_ref_release else "main" 132except subprocess.CalledProcessError: 133 print("WARNING: determining branch for page edit links failed") 134 edit_branch = "main" 135 136html_context = { 137 "display_gitlab": True, 138 "gitlab_user": "petsc", 139 "gitlab_repo": "petsc", 140 "gitlab_version": edit_branch, 141 "doc_path": "doc", 142} 143 144html_logo = html_logo_light 145html_favicon = os.path.join('images', 'logos', 'PETSc_TAO_logos', 'PETSc', 'petsc_favicon.png') 146html_last_updated_fmt = r'%Y-%m-%dT%H:%M:%S%z (' + git_describe_version + ')' 147 148 149# -- Options for LaTeX output -------------------------------------------------- 150latex_engine = 'xelatex' 151 152# How to arrange the documents into LaTeX files, building only the manual. 153latex_documents = [ 154 ('manual/index', 'manual.tex', 'PETSc/TAO Users Manual', author, 'manual', False) 155 ] 156 157latex_additional_files = [ 158 'images/manual/anl_tech_report/ArgonneLogo.pdf', 159 'images/manual/anl_tech_report/ArgonneReportTemplateLastPage.pdf', 160 'images/manual/anl_tech_report/ArgonneReportTemplatePage2.pdf', 161 'manual/anl_tech_report/first.inc', 162 'manual/anl_tech_report/last.inc', 163] 164 165latex_elements = { 166 'maketitle': r'\newcommand{\techreportversion}{%s}' % version + 167r''' 168\input{first.inc} 169''', 170 'printindex': r''' 171\printindex 172\input{last.inc} 173''', 174 'fontpkg': r''' 175\setsansfont{DejaVu Sans} 176\setmonofont{DejaVu Sans Mono} 177''', 178 'tableofcontents' : r'' 179} 180 181# -- Setup and event callbacks ------------------------------------------------- 182 183def setup(app): 184 app.connect('builder-inited', builder_init_handler) 185 app.connect('build-finished', build_finished_handler) 186 187 188def builder_init_handler(app): 189 global xtime 190 if app.builder.name.endswith('html'): 191 _build_manpages_c2html(app, 'pre') 192 _update_htmlmap_links(app) 193 ptype = 'html' 194 else: ptype = 'pdf' 195 print("============================================") 196 print(" Running Sphinx on PETSc " + ptype) 197 xtime = time.clock_gettime(time.CLOCK_REALTIME) 198 199 200def build_finished_handler(app, exception): 201 global xtime 202 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - xtime)) 203 print("============================================") 204 if app.builder.name.endswith('html'): 205 _build_manpages_c2html(app, 'post') 206 build_petsc4py_docs(app) 207 _fix_links(app, exception) 208 _fix_man_page_edit_links(app, exception) 209 fix_pydata_margins.fix_pydata_margins(app.outdir) 210 if app.builder.name == 'dirhtml': 211 _add_man_page_redirects(app, exception) 212 # remove sources for manual pages since they are automatically generated and should not be looked at on the website 213 if os.path.isdir(os.path.join(app.outdir,'_sources','manualpages')): 214 shutil.rmtree(os.path.join(app.outdir,'_sources','manualpages')) 215 if app.builder.name == 'html': 216 print("==========================================================================") 217 print(" open %s/index.html in your browser to view the documentation " % app.outdir) 218 print("==========================================================================") 219 220def _add_man_page_redirects(app, exception): 221 if exception is None: 222 import time 223 print("============================================") 224 print(" Adding man pages redirects") 225 x = time.clock_gettime(time.CLOCK_REALTIME) 226 add_man_page_redirects.add_man_page_redirects(app.outdir) 227 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 228 print("============================================") 229 230def _build_manpages_c2html(app, stage): 231 '''Builds the .md versions of the manual pages and the .html version of the source code''' 232 build_manpages_c2html.main(stage,app.outdir) 233 234def _fix_man_page_edit_links(app, exception): 235 if exception is None: 236 import time 237 print("============================================") 238 print(" Fixing manual page edit links") 239 x = time.clock_gettime(time.CLOCK_REALTIME) 240 fix_man_page_edit_links.fix_man_page_edit_links(app.outdir) 241 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 242 print("============================================") 243 244# 245# The following two scripts are needed because the Sphinx html and dirhtml builds save the output html 246# files at different levels of the directory hierarchy. file.rst/md -> file.html with html but 247# file.rst/md -> file/index.html with dirhtml and we want both to work correctly using relative links. 248 249def _fix_links(app, exception): 250 """We need to manage our own relative paths in the User's Manual for the source code files which 251 are auto-generated by c2html outside of Sphinx so Sphinx cannot directly handle those links for use. 252 We use the string PETSC_DOC_OUT_ROOT_PLACEHOLDER in URLs in the Sphinx .rst files as a stand in 253 for the root directory that needs to be constructed based on if the Sphinx build is html or dirhtml 254 """ 255 if exception is None: 256 import time 257 print("============================================") 258 print(" Fixing relative links") 259 x = time.clock_gettime(time.CLOCK_REALTIME) 260 make_links_relative.make_links_relative(app.outdir) 261 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 262 print("============================================") 263 264 265def _update_htmlmap_links(app): 266 """htmlmap maps from manualpage names to relative locations in the generated documentation directory 267 hierarchy. The format of the directory location needs to be different for the Sphinx html and dirhtml 268 builds 269 """ 270 import time 271 print("============================================") 272 print(" Updating htmlmap") 273 x = time.clock_gettime(time.CLOCK_REALTIME) 274 update_htmlmap_links.update_htmlmap_links(app.builder,os.path.join('manualpages','htmlmap')) 275 print("Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 276 print("============================================") 277 278def build_petsc4py_docs(app): 279 petsc_dir = os.path.dirname(os.path.abspath(os.path.join(__file__,'..'))) 280 petsc_arch = 'arch-docs' 281 282 # petsc4py needs to be built to build petsc4py docs via introspection 283 command = ['make', '-f', 'makefile', 'libs', 284 'PETSC_DIR=%s' % petsc_dir, 285 'PETSC_ARCH=%s' % petsc_arch] 286 import time 287 print('==============================================') 288 print('Building library to make petsc4py docs') 289 print(command) 290 x = time.clock_gettime(time.CLOCK_REALTIME) 291 subprocess.run(command, cwd=petsc_dir, check=True) 292 print("End building library for petsc4py docs Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 293 print('==============================================') 294 295 command = ['make', 'website', 296 'PETSC_DIR=%s' % petsc_dir, 297 'PETSC_ARCH=%s' % petsc_arch, 298 'LOC=%s' % app.outdir] 299 print('============================================') 300 print('Building petsc4py docs') 301 print(command) 302 x = time.clock_gettime(time.CLOCK_REALTIME) 303 subprocess.run(command, cwd=os.path.join(petsc_dir,'src','binding','petsc4py'), check=True) 304 print("End petsc4py docs Time: "+str(time.clock_gettime(time.CLOCK_REALTIME) - x)) 305 print('============================================') 306