Belle II Software  release-08-01-10
conf.py
1 #!/usr/bin/env python3
2 # -*- coding: utf-8 -*-
3 #
4 # basf2 documentation build configuration file, created by
5 # sphinx-quickstart on Mon May 23 17:26:16 2016.
6 #
7 # This file is execfile()d with the current directory set to its
8 # containing dir.
9 #
10 # Note that not all possible configuration values are present in this
11 # autogenerated file.
12 #
13 # All configuration values have a default; values that are commented out
14 # serve to show the default.
15 
16 import sys
17 import os
18 import re
19 import subprocess
20 import jupytext
21 
22 sys.path.insert(0, os.path.abspath("extensions"))
23 
24 # If extensions (or modules to document with autodoc) are in another directory,
25 # add these directories to sys.path here. If the directory is relative to the
26 # documentation root, use os.path.abspath to make it absolute, like shown here.
27 # sys.path.insert(0, os.path.abspath('....'))
28 
29 # -- General configuration ------------------------------------------------
30 
31 # If your documentation needs a minimal Sphinx version, state it here.
32 # needs_sphinx = '1.0'
33 
34 # Add any Sphinx extension module names here, as strings. They can be
35 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
36 # ones.
37 extensions = [
38  'sphinx.ext.intersphinx',
39  'sphinx.ext.autodoc',
40  # 'sphinx.ext.autosummary',
41  'sphinx.ext.mathjax',
42  'sphinx.ext.napoleon',
43  'sphinx.ext.viewcode',
44  'sphinx.ext.autosectionlabel',
45  'sphinx_codeautolink',
46  'sphinxarg.ext',
47  'basf2ext',
48  'nbsphinx',
49  'sphinxcontrib.programoutput',
50  'IPython.sphinxext.ipython_console_highlighting',
51 ]
52 
53 # Codeautolink warnings for compilation. Turned off due to conflicts with line
54 # numbering.
55 codeautolink_warn_on_missing_inventory = False
56 codeautolink_warn_on_failed_resolve = False
57 
58 nbsphinx_allow_errors = True
59 # Anything that ends with .jupy.py will be understood as a jupyter
60 # notebook converted to a plain python file with jupytext. During the sphinx
61 # build, jupytext will converted it back to a .ipynb file and nbsphinx will
62 # build the HTML
63 nbsphinx_custom_formats = {
64  '.doc.jupy.py': lambda s: jupytext.reads(s, '.py'),
65 }
66 
67 # autosummary_generate = True
68 
69 # prefix each section with the name of the document it is in followed by a
70 # colon
71 autosectionlabel_prefix_document = True
72 suppress_warnings = ['autosectionlabel.*', 'codeautolink.*']
73 
74 # Add any paths that contain templates here, relative to this directory.
75 templates_path = ['_sphinxtemplates']
76 
77 # The suffix(es) of source filenames.
78 # You can specify multiple suffix as a list of string:
79 # source_suffix = ['.rst', '.md']
80 source_suffix = '.rst'
81 
82 # The encoding of source files.
83 # source_encoding = 'utf-8-sig'
84 
85 # The master toctree document.
86 master_doc = 'index'
87 
88 # General information about the project.
89 project = 'basf2'
90 copyright = 'Belle II Collaboration'
91 author = 'Belle II Software Group'
92 
93 # The version info for the project you're documenting, acts as replacement for
94 # |version| and |release|, also used in various other places throughout the
95 # built documents.
96 #
97 # The short X.Y version.
98 version = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]).decode().strip()
99 # Used for links to the repository
100 basf2_repository = "https://gitlab.desy.de/belle2/software/basf2/"
101 basf2_commitid = subprocess.check_output(["git", "rev-parse", "HEAD"]).decode().strip()
102 basf2_issues = "https://gitlab.desy.de/belle2/software/basf2/-/issues/"
103 
104 # The full version, including alpha/beta/rc tags.
105 release = os.environ.get('BELLE2_RELEASE', 'development')
106 if release == 'head':
107  release = 'development'
108 
109 # Add warnings in the code if this is not a release
110 keep_warnings = release == "development"
111 nitpicky = keep_warnings
112 
113 # Mask false warnings
114 nitpick_ignore = []
115 for entry in ['cppyy.gbl.TObject', 'cppyy.gbl.TFile', 'ROOT.TFile']:
116  nitpick_ignore.append(('py:class', entry))
117 for entry in ['int', 'bool', 'list', 'str', 'object', 'None', 'LogConfig', 'ModuleStatistics']:
118  nitpick_ignore.append(('py:class', entry + ' :'))
119 
120 # The language for content autogenerated by Sphinx. Refer to documentation
121 # for a list of supported languages.
122 #
123 # This is also used if you do content translation via gettext catalogs.
124 # Usually you set "language" from the command line for these cases.
125 language = None
126 
127 # There are two options for replacing |today|: either, you set today to some
128 # non-false value, then it is used:
129 # today = ''
130 # Else, today_fmt is used as the format for a strftime call.
131 # today_fmt = '%B %d, %Y'
132 
133 # List of patterns, relative to source directory, that match files and
134 # directories to ignore when looking for source files.
135 # This patterns also effect to html_static_path and html_extra_path
136 exclude_patterns = ['.*', '_sphinxbuild', 'Thumbs.db', 'build', 'include', 'lib', 'bin', 'modules', 'data', 'site_scons']
137 # If we want to create the light release documentation then we need t exclude anything not in the light release.
138 if tags.has('light'): # noqa
139  light_packages = set([entry.strip('/') for entry in open('../../.light').read().split() if entry.endswith('/')])
140  for entry in os.listdir("../../"):
141  if entry.find('.') > -1 or os.path.isfile(entry) or entry in exclude_patterns or entry in light_packages:
142  continue
143  exclude_patterns.append(entry)
144  del light_packages
145 
146 # now we need to exclude everything in the build dir except for the tools_doc
147 # sub dir but there's no negative exclusion pattern so do it manually
148 exclude_patterns.remove("build")
149 exclude_patterns += ['build/html', 'build/latex', 'build/json', 'build/Linux*', 'build/belle2_tools']
150 # Ignore jupyter notebooks by default, we only want the ones meant for documentation
151 exclude_patterns += ['**/*.ipynb', '*.ipynb']
152 
153 # The reST default role (used for this markup: `text`) to use for all
154 # documents. :any: allows easy linking to functions/classes/modules
155 default_role = 'any'
156 
157 # If true, '()' will be appended to :func: etc. cross-reference text.
158 # add_function_parentheses = True
159 
160 # If true, the current module name will be prepended to all description
161 # unit titles (such as .. function::).
162 # add_module_names = True
163 
164 # If true, sectionauthor and moduleauthor directives will be shown in the
165 # output. They are ignored by default.
166 # show_authors = False
167 
168 # The name of the Pygments (syntax highlighting) style to use.
169 pygments_style = 'sphinx'
170 
171 # A list of ignored prefixes for module index sorting.
172 # modindex_common_prefix = []
173 
174 # If true, keep warnings as "system message" paragraphs in the built documents.
175 # keep_warnings = False
176 
177 # If true, `todo` and `todoList` produce output, else they produce nothing.
178 todo_include_todos = False
179 
180 # If true, figures with captions automatically get figure numbers included at the start of the caption.
181 # Also the :numref: role is allowed for figures. Referencing figures/sections etc in this way
182 # will insert a reference to the reference number instead of the reference text/caption.
183 numfig = True
184 
185 # -- Options for HTML output ----------------------------------------------
186 
187 # The theme to use for HTML and HTML Help pages. See the documentation for
188 # a list of builtin themes.
189 html_theme = 'sphinx_book_theme'
190 
191 # Theme options are theme-specific and customize the look and feel of a theme
192 # further. For a list of options available for each theme, see the
193 # documentation.
194 # html_theme_options = {'stickysidebar': True}
195 
196 # Add any paths that contain custom themes here, relative to this directory.
197 html_theme_path = ["_themes", ]
198 
199 # The name for this set of Sphinx documents.
200 # "<project> v<release> documentation" by default.
201 # html_title = 'basf2 vhead'
202 
203 # A shorter title for the navigation bar. Default is the same as html_title.
204 # html_short_title = None
205 
206 # The name of an image file (relative to this directory) to place at the top
207 # of the sidebar.
208 html_logo = "b2logo.svg"
209 
210 # The name of an image file (relative to this directory) to use as a favicon of
211 # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
212 # pixels large.
213 # html_favicon = None
214 
215 # Add any paths that contain custom static files (such as style sheets) here,
216 # relative to this directory. They are copied after the builtin static files,
217 # so a file named "default.css" will overwrite the builtin "default.css".
218 html_static_path = ['_sphinxstatic']
219 
220 # Add any extra paths that contain custom files (such as robots.txt or
221 # .htaccess) here, relative to this directory. These files are copied
222 # directly to the root of the documentation.
223 # html_extra_path = []
224 
225 # If not None, a 'Last updated on:' timestamp is inserted at every page
226 # bottom, using the given strftime format.
227 # The empty string is equivalent to '%b %d, %Y'.
228 # html_last_updated_fmt = None
229 
230 # If true, SmartyPants will be used to convert quotes and dashes to
231 # typographically correct entities.
232 # html_use_smartypants = True
233 
234 # Custom sidebar templates, maps document names to template names.
235 # html_sidebars = {}
236 
237 # Additional templates that should be rendered to pages, maps page names to
238 # template names.
239 # html_additional_pages = {}
240 
241 # If false, no module index is generated.
242 # html_domain_indices = True
243 
244 # If false, no index is generated.
245 # html_use_index = True
246 
247 # If true, the index is split into individual pages for each letter.
248 # html_split_index = False
249 
250 # If true, links to the reST sources are added to the pages.
251 # html_show_sourcelink = True
252 
253 # If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
254 # html_show_sphinx = True
255 
256 # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
257 # html_show_copyright = True
258 
259 # If true, an OpenSearch description file will be output, and all pages will
260 # contain a <link> tag referring to it. The value of this option must be the
261 # base URL from which the finished HTML is served.
262 # html_use_opensearch = ''
263 
264 # This is the file name suffix for HTML files (e.g. ".xhtml").
265 # html_file_suffix = None
266 
267 # Language to be used for generating the HTML full-text search index.
268 # Sphinx supports the following languages:
269 # 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
270 # 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
271 # html_search_language = 'en'
272 
273 # A dictionary with options for the search language support, empty by default.
274 # 'ja' uses this config value.
275 # 'zh' user can custom change `jieba` dictionary path.
276 # html_search_options = {'type': 'default'}
277 
278 # The name of a javascript file (relative to the configuration directory) that
279 # implements a search results scorer. If empty, the default will be used.
280 # html_search_scorer = 'scorer.js'
281 
282 # Output file base name for HTML help builder.
283 htmlhelp_basename = 'basf2doc'
284 
285 # -- Options for LaTeX output ---------------------------------------------
286 
287 latex_elements = {
288  # The paper size ('letterpaper' or 'a4paper').
289  'papersize': 'a4paper',
290 
291  # The font size ('10pt', '11pt' or '12pt').
292  'pointsize': '10pt',
293 
294  # Additional stuff for the LaTeX preamble.
295  'preamble': '\\setcounter{tocdepth}{2}',
296 
297  # Latex figure (float) alignment
298  # 'figure_align': 'htbp',
299 }
300 
301 # Grouping the document tree into LaTeX files. List of tuples
302 # (source start file, target name, title,
303 # author, documentclass [howto, manual, or own class]).
304 latex_documents = [
305  (master_doc, 'basf2.tex', 'Belle II Software Documentation',
306  author, 'manual'),
307 ]
308 
309 # The name of an image file (relative to this directory) to place at the top of
310 # the title page.
311 latex_logo = "belle2-logo.pdf"
312 
313 # For "manual" documents, if this is true, then toplevel headings are parts,
314 # not chapters.
315 latex_use_parts = True
316 latex_show_urls = 'footnote'
317 latex_show_pagerefs = True
318 
319 # If true, show page references after internal links.
320 # latex_show_pagerefs = False
321 
322 # If true, show URL addresses after external links.
323 # latex_show_urls = False
324 
325 # Documents to append as an appendix to all manuals.
326 # latex_appendices = []
327 
328 # If false, no module index is generated.
329 # latex_domain_indices = True
330 
331 
332 # -- Options for manual page output ---------------------------------------
333 
334 # One entry per manual page. List of tuples
335 # (source start file, name, description, authors, manual section).
336 man_pages = [
337  (master_doc, 'basf2', 'basf2 Documentation',
338  [author], 1)
339 ]
340 
341 # If true, show URL addresses after external links.
342 # man_show_urls = False
343 
344 
345 # -- Options for Texinfo output -------------------------------------------
346 
347 # Grouping the document tree into Texinfo files. List of tuples
348 # (source start file, target name, title, author,
349 # dir menu entry, description, category)
350 texinfo_documents = [
351  (master_doc, 'basf2', 'basf2 Documentation',
352  author, 'basf2', 'One line description of project.',
353  'Miscellaneous'),
354 ]
355 
356 # Documents to append as an appendix to all manuals.
357 # texinfo_appendices = []
358 
359 # If false, no module index is generated.
360 # texinfo_domain_indices = True
361 
362 # How to display URL addresses: 'footnote', 'no', or 'inline'.
363 # texinfo_show_urls = 'footnote'
364 
365 # If true, do not generate a @detailmenu in the "Top" node's menu.
366 # texinfo_no_detailmenu = False
367 
368 # allow to have links to python documentation
369 intersphinx_mapping = {'python': ('https://docs.python.org/3.8/', None),
370  'numpy': ('https://numpy.org/doc/stable/', None),
371  'scipy': ('https://docs.scipy.org/doc/scipy/', None),
372  'pandas': ('https://pandas.pydata.org/docs/', None),
373  'matplotlib': ('https://matplotlib.org/stable/', None),
374  'uproot': ('https://uproot.readthedocs.io/en/stable/', None)}
375 
376 
377 def process_sig(app, what, name, obj, options, signature, return_annotation):
378  """
379  remove unhelpful 'self' arguments from methods.
380  """
381  if what == 'method' and signature:
382  reg = re.compile('^\\( \\(.*\\)arg1')
383  signature = reg.sub('(', signature)
384  return (signature, return_annotation)
385 
386 
387 def improve_docstring(obj):
388  """
389  Enhances docstrings of PyROOT objects/classes.
390 
391  >>> improve_docstring(Belle2.Variable.Manager)
392 
393  or
394 
395  >>> variables = ROOT.Belle2.Variable.Manager
396  >>> improve_docstring(variables)
397  """
398  try:
399  # is this a ..._meta object?
400  classname = obj.__name__
401  pyclass = obj
402  except AttributeError:
403  classname = obj.__class__.__name__
404  pyclass = obj.__class__
405 
406  if '::' not in classname:
407  return # not a ROOT class?
408  pos = classname.find('Belle2::')
409  classname = classname[pos:]
410  if pyclass.__doc__ is None:
411  pyclass.__doc__ = ''
412 
413  pyclass.__name__ = 'Belle2.' + classname
414 
415  from ROOT import TClass
416  tclass = TClass(classname)
417  # if tclass:
418  # pyclass.__doc__ += '\n' + tclass.GetTitle()
419 
420  doxygen_url = 'https://software.belle2.org/development/class'
421  doxygen_url += '_1_1'.join(classname.split('::'))
422  doxygen_url += '.html'
423  pyclass.__doc__ += '\n`Doxygen page for %s <%s>`_' % (classname, doxygen_url)
424 
425  # TODO put this into the member docstrings directly? (sadly, readonly)
426  members = tclass.GetListOfMethods()
427  if members.GetEntries() > 0:
428  pyclass.__doc__ += '\n\nMember functions:'
429  for f in members:
430  # getattr(pyclass, f.GetName()).__doc__ = "test"
431  pyclass.__doc__ += '\n * %s %s%s' % (f.GetReturnTypeName(), f.GetName(), f.GetSignature())
432  title = f.GetTitle()
433  if title:
434  pyclass.__doc__ += ' (%s)' % (title)
435 
436  members = tclass.GetListOfAllPublicDataMembers()
437  if members.GetEntries() > 0:
438  pyclass.__doc__ += '\n\nPublic data members'
439  for f in members:
440  pyclass.__doc__ += '\n * %s' % (f.GetName())
441  title = f.GetTitle()
442  if title:
443  pyclass.__doc__ += ' (%s)' % (title)
444 
445 
446 def skipmember(app, what, name, obj, skip, options):
447  """
448  This is executed before docstring processing,
449  so try improving them a bit.
450  """
451  try:
452  improve_docstring(obj)
453  except AttributeError:
454  pass
455  return skip
456 
457 
458 def process_docstring(app, what, name, obj, options, lines):
459  """
460  convert doxygen syntax to sphinx
461  """
462  substitutions = {
463  re.compile(r'^( *)@param (.*?):? '): r':param \2: ',
464  re.compile(r'^( *)@returns? '): r':return: ',
465  }
466  newlines = []
467  for line in lines:
468  new = line
469  for reg, sub in substitutions.items():
470  new = reg.sub(sub, new)
471  if new != line:
472  # Sphinx wants a new paragraph before these, so let's add one
473  newlines += ['']
474  newlines += [new]
475  lines[:] = newlines
476 
477 
478 def setup(app):
479  """
480  Install some event handlers to improve output.
481  """
482  app.connect('autodoc-process-signature', process_sig)
483  app.connect('autodoc-process-docstring', process_docstring)
484  app.connect('autodoc-skip-member', skipmember)
485  app.add_css_file('css/custom.css')
486 
487 
488 # Work around https://github.com/sphinx-doc/sphinx/issues/9189 by monkey patching the member function in question
489 # FIXME: Not needed with sphinx>=4.0.1
490 
491 from sphinx.ext import autodoc # noqa
492 # remember the old function
493 old_directive_header = autodoc.PropertyDocumenter.add_directive_header
494 
495 
496 # make a new one that ignores the value error
497 def _fixed_directive_header(*args, **argk):
498  """Catch the ValueError and ignore it as done in https://github.com/sphinx-doc/sphinx/pull/9190"""
499  try:
500  old_directive_header(*args, **argk)
501  except ValueError:
502  return None
503 
504 
505 # and override the existing function with our new and improved version.
506 autodoc.PropertyDocumenter.add_directive_header = _fixed_directive_header