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