Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) # -*- coding: utf-8; mode: python -*-
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # pylint: disable=C0103, R0903, R0912, R0915
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) u"""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)     scalable figure and image handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)     Sphinx extension which implements scalable image handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)     :copyright:  Copyright (C) 2016  Markus Heiser
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)     :license:    GPL Version 2, June 1991 see Linux/COPYING for details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)     The build for image formats depend on image's source format and output's
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)     destination format. This extension implement methods to simplify image
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)     handling from the author's POV. Directives like ``kernel-figure`` implement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)     methods *to* always get the best output-format even if some tools are not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)     installed. For more details take a look at ``convert_image(...)`` which is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)     the core of all conversions.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)     * ``.. kernel-image``: for image handling / a ``.. image::`` replacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)     * ``.. kernel-figure``: for figure handling / a ``.. figure::`` replacement
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)     * ``.. kernel-render``: for render markup / a concept to embed *render*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)       markups (or languages). Supported markups (see ``RENDER_MARKUP_EXT``)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26)       - ``DOT``: render embedded Graphviz's **DOC**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27)       - ``SVG``: render embedded Scalable Vector Graphics (**SVG**)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28)       - ... *developable*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)     Used tools:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)     * ``dot(1)``: Graphviz (https://www.graphviz.org). If Graphviz is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)       available, the DOT language is inserted as literal-block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)     * SVG to PDF: To generate PDF, you need at least one of this tools:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)       - ``convert(1)``: ImageMagick (https://www.imagemagick.org)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39)     List of customizations:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41)     * generate PDF from SVG / used by PDF (LaTeX) builder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)     * generate SVG (html-builder) and PDF (latex-builder) from DOT files.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)       DOT: see https://www.graphviz.org/content/dot-language
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) import os
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) from os import path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) import subprocess
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) from hashlib import sha1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) import sys
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) from docutils import nodes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) from docutils.statemachine import ViewList
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) from docutils.parsers.rst import directives
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) from docutils.parsers.rst.directives import images
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) import sphinx
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) from sphinx.util.nodes import clean_astext
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) from six import iteritems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) import kernellog
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) PY3 = sys.version_info[0] == 3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) if PY3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68)     _unicode = str
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70)     _unicode = unicode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) # Get Sphinx version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) major, minor, patch = sphinx.version_info[:3]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) if major == 1 and minor > 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)     # patches.Figure only landed in Sphinx 1.4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)     from sphinx.directives.patches import Figure  # pylint: disable=C0413
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)     Figure = images.Figure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) __version__  = '1.0.0'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) # simple helper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) # -------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) def which(cmd):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)     """Searches the ``cmd`` in the ``PATH`` environment.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)     This *which* searches the PATH for executable ``cmd`` . First match is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)     returned, if nothing is found, ``None` is returned.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91)     envpath = os.environ.get('PATH', None) or os.defpath
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92)     for folder in envpath.split(os.pathsep):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93)         fname = folder + os.sep + cmd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94)         if path.isfile(fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95)             return fname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) def mkdir(folder, mode=0o775):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98)     if not path.isdir(folder):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99)         os.makedirs(folder, mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) def file2literal(fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)     with open(fname, "r") as src:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)         data = src.read()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)         node = nodes.literal_block(data, data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)     return node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) def isNewer(path1, path2):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)     """Returns True if ``path1`` is newer than ``path2``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)     If ``path1`` exists and is newer than ``path2`` the function returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)     ``True`` is returned otherwise ``False``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)     return (path.exists(path1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)             and os.stat(path1).st_ctime > os.stat(path2).st_ctime)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) def pass_handle(self, node):           # pylint: disable=W0613
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)     pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) # setup conversion tools and sphinx extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) # -------------------------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) # Graphviz's dot(1) support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) dot_cmd = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) # ImageMagick' convert(1) support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) convert_cmd = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) def setup(app):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)     # check toolchain first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)     app.connect('builder-inited', setupTools)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)     # image handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)     app.add_directive("kernel-image",  KernelImage)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)     app.add_node(kernel_image,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)                  html    = (visit_kernel_image, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)                  latex   = (visit_kernel_image, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)                  texinfo = (visit_kernel_image, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)                  text    = (visit_kernel_image, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)                  man     = (visit_kernel_image, pass_handle), )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)     # figure handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)     app.add_directive("kernel-figure", KernelFigure)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)     app.add_node(kernel_figure,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)                  html    = (visit_kernel_figure, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)                  latex   = (visit_kernel_figure, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)                  texinfo = (visit_kernel_figure, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)                  text    = (visit_kernel_figure, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)                  man     = (visit_kernel_figure, pass_handle), )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)     # render handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)     app.add_directive('kernel-render', KernelRender)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)     app.add_node(kernel_render,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)                  html    = (visit_kernel_render, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)                  latex   = (visit_kernel_render, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)                  texinfo = (visit_kernel_render, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)                  text    = (visit_kernel_render, pass_handle),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)                  man     = (visit_kernel_render, pass_handle), )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)     app.connect('doctree-read', add_kernel_figure_to_std_domain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)     return dict(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)         version = __version__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)         parallel_read_safe = True,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)         parallel_write_safe = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)     )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) def setupTools(app):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)     u"""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)     Check available build tools and log some *verbose* messages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)     This function is called once, when the builder is initiated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)     global dot_cmd, convert_cmd   # pylint: disable=W0603
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)     kernellog.verbose(app, "kfigure: check installed tools ...")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178)     dot_cmd = which('dot')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179)     convert_cmd = which('convert')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)     if dot_cmd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)         kernellog.verbose(app, "use dot(1) from: " + dot_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)     else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)         kernellog.warn(app, "dot(1) not found, for better output quality install "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)                        "graphviz from https://www.graphviz.org")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)     if convert_cmd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)         kernellog.verbose(app, "use convert(1) from: " + convert_cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)     else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)         kernellog.warn(app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)             "convert(1) not found, for SVG to PDF conversion install "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)             "ImageMagick (https://www.imagemagick.org)")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) # integrate conversion tools
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) # --------------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) RENDER_MARKUP_EXT = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)     # The '.ext' must be handled by convert_image(..) function's *in_ext* input.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)     # <name> : <.ext>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)     'DOT' : '.dot',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)     'SVG' : '.svg'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) def convert_image(img_node, translator, src_fname=None):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)     """Convert a image node for the builder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)     Different builder prefer different image formats, e.g. *latex* builder
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)     prefer PDF while *html* builder prefer SVG format for images.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)     This function handles output image formats in dependence of source the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)     format (of the image) and the translator's output format.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)     app = translator.builder.app
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)     fname, in_ext = path.splitext(path.basename(img_node['uri']))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)     if src_fname is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)         src_fname = path.join(translator.builder.srcdir, img_node['uri'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)         if not path.exists(src_fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)             src_fname = path.join(translator.builder.outdir, img_node['uri'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)     dst_fname = None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)     # in kernel builds, use 'make SPHINXOPTS=-v' to see verbose messages
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)     kernellog.verbose(app, 'assert best format for: ' + img_node['uri'])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)     if in_ext == '.dot':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)         if not dot_cmd:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)             kernellog.verbose(app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231)                               "dot from graphviz not available / include DOT raw.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)             img_node.replace_self(file2literal(src_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)         elif translator.builder.format == 'latex':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)             dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)             img_node['uri'] = fname + '.pdf'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)             img_node['candidates'] = {'*': fname + '.pdf'}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)         elif translator.builder.format == 'html':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)             dst_fname = path.join(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)                 translator.builder.outdir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)                 translator.builder.imagedir,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)                 fname + '.svg')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)             img_node['uri'] = path.join(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)                 translator.builder.imgpath, fname + '.svg')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)             img_node['candidates'] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)                 '*': path.join(translator.builder.imgpath, fname + '.svg')}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)             # all other builder formats will include DOT as raw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)             img_node.replace_self(file2literal(src_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)     elif in_ext == '.svg':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)         if translator.builder.format == 'latex':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)             if convert_cmd is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)                 kernellog.verbose(app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)                                   "no SVG to PDF conversion available / include SVG raw.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)                 img_node.replace_self(file2literal(src_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)             else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)                 dst_fname = path.join(translator.builder.outdir, fname + '.pdf')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)                 img_node['uri'] = fname + '.pdf'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)                 img_node['candidates'] = {'*': fname + '.pdf'}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)     if dst_fname:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)         # the builder needs not to copy one more time, so pop it if exists.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)         translator.builder.images.pop(img_node['uri'], None)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)         _name = dst_fname[len(translator.builder.outdir) + 1:]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)         if isNewer(dst_fname, src_fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)             kernellog.verbose(app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)                               "convert: {out}/%s already exists and is newer" % _name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)         else:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)             ok = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)             mkdir(path.dirname(dst_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)             if in_ext == '.dot':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)                 kernellog.verbose(app, 'convert DOT to: {out}/' + _name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)                 ok = dot2format(app, src_fname, dst_fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)             elif in_ext == '.svg':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)                 kernellog.verbose(app, 'convert SVG to: {out}/' + _name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)                 ok = svg2pdf(app, src_fname, dst_fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)             if not ok:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)                 img_node.replace_self(file2literal(src_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) def dot2format(app, dot_fname, out_fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)     """Converts DOT file to ``out_fname`` using ``dot(1)``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)     * ``dot_fname`` pathname of the input DOT file, including extension ``.dot``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295)     * ``out_fname`` pathname of the output file, including format extension
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)     The *format extension* depends on the ``dot`` command (see ``man dot``
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)     option ``-Txxx``). Normally you will use one of the following extensions:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)     - ``.ps`` for PostScript,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)     - ``.svg`` or ``svgz`` for Structured Vector Graphics,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)     - ``.fig`` for XFIG graphics and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)     - ``.png`` or ``gif`` for common bitmap graphics.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)     out_format = path.splitext(out_fname)[1][1:]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)     cmd = [dot_cmd, '-T%s' % out_format, dot_fname]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)     exit_code = 42
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)     with open(out_fname, "w") as out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)         exit_code = subprocess.call(cmd, stdout = out)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)         if exit_code != 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)             kernellog.warn(app,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)                           "Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)     return bool(exit_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) def svg2pdf(app, svg_fname, pdf_fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)     """Converts SVG to PDF with ``convert(1)`` command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)     Uses ``convert(1)`` from ImageMagick (https://www.imagemagick.org) for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)     conversion.  Returns ``True`` on success and ``False`` if an error occurred.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)     * ``svg_fname`` pathname of the input SVG file with extension (``.svg``)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)     * ``pdf_name``  pathname of the output PDF file with extension (``.pdf``)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)     cmd = [convert_cmd, svg_fname, pdf_fname]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)     # use stdout and stderr from parent
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)     exit_code = subprocess.call(cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)     if exit_code != 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)         kernellog.warn(app, "Error #%d when calling: %s" % (exit_code, " ".join(cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)     return bool(exit_code == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) # image handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) # ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) def visit_kernel_image(self, node):    # pylint: disable=W0613
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)     """Visitor of the ``kernel_image`` Node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)     Handles the ``image`` child-node with the ``convert_image(...)``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)     img_node = node[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)     convert_image(img_node, self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) class kernel_image(nodes.image):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)     """Node for ``kernel-image`` directive."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)     pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) class KernelImage(images.Image):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351)     u"""KernelImage directive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)     Earns everything from ``.. image::`` directive, except *remote URI* and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354)     *glob* pattern. The KernelImage wraps a image node into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)     kernel_image node. See ``visit_kernel_image``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358)     def run(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)         uri = self.arguments[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)         if uri.endswith('.*') or uri.find('://') != -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)             raise self.severe(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)                 'Error in "%s: %s": glob pattern and remote images are not allowed'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)                 % (self.name, uri))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)         result = images.Image.run(self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)         if len(result) == 2 or isinstance(result[0], nodes.system_message):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)             return result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)         (image_node,) = result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)         # wrap image node into a kernel_image node / see visitors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)         node = kernel_image('', image_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)         return [node]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) # figure handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) # ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) def visit_kernel_figure(self, node):   # pylint: disable=W0613
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)     """Visitor of the ``kernel_figure`` Node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)     Handles the ``image`` child-node with the ``convert_image(...)``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)     img_node = node[0][0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381)     convert_image(img_node, self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) class kernel_figure(nodes.figure):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)     """Node for ``kernel-figure`` directive."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) class KernelFigure(Figure):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)     u"""KernelImage directive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)     Earns everything from ``.. figure::`` directive, except *remote URI* and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)     *glob* pattern.  The KernelFigure wraps a figure node into a kernel_figure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)     node. See ``visit_kernel_figure``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)     def run(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)         uri = self.arguments[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)         if uri.endswith('.*') or uri.find('://') != -1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)             raise self.severe(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398)                 'Error in "%s: %s":'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)                 ' glob pattern and remote images are not allowed'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)                 % (self.name, uri))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401)         result = Figure.run(self)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)         if len(result) == 2 or isinstance(result[0], nodes.system_message):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)             return result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404)         (figure_node,) = result
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)         # wrap figure node into a kernel_figure node / see visitors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)         node = kernel_figure('', figure_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)         return [node]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) # render handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) # ---------------------
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) def visit_kernel_render(self, node):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414)     """Visitor of the ``kernel_render`` Node.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)     If rendering tools available, save the markup of the ``literal_block`` child
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)     node into a file and replace the ``literal_block`` node with a new created
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)     ``image`` node, pointing to the saved markup file. Afterwards, handle the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419)     image child-node with the ``convert_image(...)``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)     app = self.builder.app
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422)     srclang = node.get('srclang')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424)     kernellog.verbose(app, 'visit kernel-render node lang: "%s"' % (srclang))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)     tmp_ext = RENDER_MARKUP_EXT.get(srclang, None)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)     if tmp_ext is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)         kernellog.warn(app, 'kernel-render: "%s" unknown / include raw.' % (srclang))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)         return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)     if not dot_cmd and tmp_ext == '.dot':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432)         kernellog.verbose(app, "dot from graphviz not available / include raw.")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)         return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)     literal_block = node[0]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)     code      = literal_block.astext()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)     hashobj   = code.encode('utf-8') #  str(node.attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)     fname     = path.join('%s-%s' % (srclang, sha1(hashobj).hexdigest()))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441)     tmp_fname = path.join(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)         self.builder.outdir, self.builder.imagedir, fname + tmp_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)     if not path.isfile(tmp_fname):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445)         mkdir(path.dirname(tmp_fname))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446)         with open(tmp_fname, "w") as out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)             out.write(code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449)     img_node = nodes.image(node.rawsource, **node.attributes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)     img_node['uri'] = path.join(self.builder.imgpath, fname + tmp_ext)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)     img_node['candidates'] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)         '*': path.join(self.builder.imgpath, fname + tmp_ext)}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454)     literal_block.replace_self(img_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)     convert_image(img_node, self, tmp_fname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) class kernel_render(nodes.General, nodes.Inline, nodes.Element):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459)     """Node for ``kernel-render`` directive."""
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)     pass
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) class KernelRender(Figure):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)     u"""KernelRender directive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)     Render content by external tool.  Has all the options known from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466)     *figure*  directive, plus option ``caption``.  If ``caption`` has a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)     value, a figure node with the *caption* is inserted. If not, a image node is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468)     inserted.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)     The KernelRender directive wraps the text of the directive into a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471)     literal_block node and wraps it into a kernel_render node. See
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)     ``visit_kernel_render``.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)     has_content = True
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)     required_arguments = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476)     optional_arguments = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)     final_argument_whitespace = False
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)     # earn options from 'figure'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)     option_spec = Figure.option_spec.copy()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)     option_spec['caption'] = directives.unchanged
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)     def run(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)         return [self.build_node()]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)     def build_node(self):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)         srclang = self.arguments[0].strip()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)         if srclang not in RENDER_MARKUP_EXT.keys():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490)             return [self.state_machine.reporter.warning(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)                 'Unknown source language "%s", use one of: %s.' % (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)                     srclang, ",".join(RENDER_MARKUP_EXT.keys())),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)                 line=self.lineno)]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)         code = '\n'.join(self.content)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)         if not code.strip():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)             return [self.state_machine.reporter.warning(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)                 'Ignoring "%s" directive without content.' % (
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)                     self.name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500)                 line=self.lineno)]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)         node = kernel_render()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)         node['alt'] = self.options.get('alt','')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504)         node['srclang'] = srclang
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505)         literal_node = nodes.literal_block(code, code)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)         node += literal_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)         caption = self.options.get('caption')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509)         if caption:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)             # parse caption's content
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)             parsed = nodes.Element()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)             self.state.nested_parse(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)                 ViewList([caption], source=''), self.content_offset, parsed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)             caption_node = nodes.caption(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)                 parsed[0].rawsource, '', *parsed[0].children)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516)             caption_node.source = parsed[0].source
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517)             caption_node.line = parsed[0].line
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)             figure_node = nodes.figure('', node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520)             for k,v in self.options.items():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521)                 figure_node[k] = v
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)             figure_node += caption_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)             node = figure_node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526)         return node
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) def add_kernel_figure_to_std_domain(app, doctree):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)     """Add kernel-figure anchors to 'std' domain.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531)     The ``StandardDomain.process_doc(..)`` method does not know how to resolve
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)     the caption (label) of ``kernel-figure`` directive (it only knows about
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)     standard nodes, e.g. table, figure etc.). Without any additional handling
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)     this will result in a 'undefined label' for kernel-figures.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)     This handle adds labels of kernel-figure to the 'std' domain labels.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537)     """
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539)     std = app.env.domains["std"]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540)     docname = app.env.docname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)     labels = std.data["labels"]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)     for name, explicit in iteritems(doctree.nametypes):
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544)         if not explicit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)             continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546)         labelid = doctree.nameids[name]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)         if labelid is None:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548)             continue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)         node = doctree.ids[labelid]
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)         if node.tagname == 'kernel_figure':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)             for n in node.next_node():
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)                 if n.tagname == 'caption':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)                     sectname = clean_astext(n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)                     # add label to std domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)                     labels[name] = docname, labelid, sectname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)                     break