doc: fix project version in guides
[dpdk.git] / doc / guides / conf.py
1 #!/usr/bin/env python3
2 # SPDX-License-Identifier: BSD-3-Clause
3 # Copyright(c) 2010-2015 Intel Corporation
4
5 from docutils import nodes
6 from distutils.version import LooseVersion
7 from sphinx import __version__ as sphinx_version
8 from sphinx.highlighting import PygmentsBridge
9 from pygments.formatters.latex import LatexFormatter
10 from os import listdir
11 from os import environ
12 from os.path import basename
13 from os.path import dirname
14 from os.path import join as path_join
15
16 import configparser
17
18 try:
19     import sphinx_rtd_theme
20
21     html_theme = "sphinx_rtd_theme"
22     html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
23 except:
24     print('Install the sphinx ReadTheDocs theme for improved html documentation '
25           'layout: https://sphinx-rtd-theme.readthedocs.io/')
26     pass
27
28 project = 'Data Plane Development Kit'
29 html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
30 latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
31 html_add_permalinks = ""
32 html_show_copyright = False
33 highlight_language = 'none'
34
35 release = environ['DPDK_VERSION']
36 version = release
37
38 master_doc = 'index'
39
40 # Maximum feature description string length
41 feature_str_len = 30
42
43 # Figures, tables and code-blocks automatically numbered if they have caption
44 numfig = True
45
46 latex_documents = [
47     ('index',
48      'doc.tex',
49      '',
50      '',
51      'manual')
52 ]
53
54 # Latex directives to be included directly in the latex/pdf docs.
55 custom_latex_preamble = r"""
56 \usepackage{textalpha}
57 \RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
58 \usepackage{etoolbox}
59 \robustify\(
60 \robustify\)
61 """
62
63 # Configuration for the latex/pdf docs.
64 latex_elements = {
65     'papersize': 'a4paper',
66     'pointsize': '11pt',
67     # remove blank pages
68     'classoptions': ',openany,oneside',
69     'babel': '\\usepackage[english]{babel}',
70     # customize Latex formatting
71     'preamble': custom_latex_preamble
72 }
73
74
75 # Override the default Latex formatter in order to modify the
76 # code/verbatim blocks.
77 class CustomLatexFormatter(LatexFormatter):
78     def __init__(self, **options):
79         super(CustomLatexFormatter, self).__init__(**options)
80         # Use the second smallest font size for code/verbatim blocks.
81         self.verboptions = r'formatcom=\footnotesize'
82
83 # Replace the default latex formatter.
84 PygmentsBridge.latex_formatter = CustomLatexFormatter
85
86 # Configuration for man pages
87 man_pages = [("testpmd_app_ug/run_app", "testpmd",
88               "tests for dpdk pmds", "", 1),
89              ("tools/pdump", "dpdk-pdump",
90               "enable packet capture on dpdk ports", "", 1),
91              ("tools/proc_info", "dpdk-procinfo",
92               "access dpdk port stats and memory info", "", 1),
93              ("tools/pmdinfo", "dpdk-pmdinfo",
94               "dump a PMDs hardware support info", "", 1),
95              ("tools/devbind", "dpdk-devbind",
96               "check device status and bind/unbind them from drivers", "", 8)]
97
98
99 # ####### :numref: fallback ########
100 # The following hook functions add some simple handling for the :numref:
101 # directive for Sphinx versions prior to 1.3.1. The functions replace the
102 # :numref: reference with a link to the target (for all Sphinx doc types).
103 # It doesn't try to label figures/tables.
104 def numref_role(reftype, rawtext, text, lineno, inliner):
105     """
106     Add a Sphinx role to handle numref references. Note, we can't convert
107     the link here because the doctree isn't build and the target information
108     isn't available.
109     """
110     # Add an identifier to distinguish numref from other references.
111     newnode = nodes.reference('',
112                               '',
113                               refuri='_local_numref_#%s' % text,
114                               internal=True)
115     return [newnode], []
116
117
118 def process_numref(app, doctree, from_docname):
119     """
120     Process the numref nodes once the doctree has been built and prior to
121     writing the files. The processing involves replacing the numref with a
122     link plus text to indicate if it is a Figure or Table link.
123     """
124
125     # Iterate over the reference nodes in the doctree.
126     for node in doctree.traverse(nodes.reference):
127         target = node.get('refuri', '')
128
129         # Look for numref nodes.
130         if target.startswith('_local_numref_#'):
131             target = target.replace('_local_numref_#', '')
132
133             # Get the target label and link information from the Sphinx env.
134             data = app.builder.env.domains['std'].data
135             docname, label, _ = data['labels'].get(target, ('', '', ''))
136             relative_url = app.builder.get_relative_uri(from_docname, docname)
137
138             # Add a text label to the link.
139             if target.startswith('figure'):
140                 caption = 'Figure'
141             elif target.startswith('table'):
142                 caption = 'Table'
143             else:
144                 caption = 'Link'
145
146             # New reference node with the updated link information.
147             newnode = nodes.reference('',
148                                       caption,
149                                       refuri='%s#%s' % (relative_url, label),
150                                       internal=True)
151             node.replace_self(newnode)
152
153
154 def generate_overview_table(output_filename, table_id, section, table_name, title):
155     """
156     Function to generate the Overview Table from the ini files that define
157     the features for each driver.
158
159     The default features for the table and their order is defined by the
160     'default.ini' file.
161
162     """
163     # Default warning string.
164     warning = 'Warning generate_overview_table()'
165
166     # Get the default features and order from the 'default.ini' file.
167     ini_path = path_join(dirname(output_filename), 'features')
168     config = configparser.ConfigParser()
169     config.optionxform = str
170     config.read(path_join(ini_path, 'default.ini'))
171     default_features = config.items(section)
172
173     # Create a dict of the valid features to validate the other ini files.
174     valid_features = {}
175     max_feature_length = 0
176     for feature in default_features:
177         key = feature[0]
178         valid_features[key] = ' '
179         max_feature_length = max(max_feature_length, len(key))
180
181     # Get a list of driver ini files, excluding 'default.ini'.
182     ini_files = [basename(file) for file in listdir(ini_path)
183                  if file.endswith('.ini') and file != 'default.ini']
184     ini_files.sort()
185
186     # Build up a list of the table header names from the ini filenames.
187     pmd_names = []
188     for ini_filename in ini_files:
189         name = ini_filename[:-4]
190         name = name.replace('_vf', 'vf')
191         pmd_names.append(name)
192
193     # Pad the table header names.
194     max_header_len = len(max(pmd_names, key=len))
195     header_names = []
196     for name in pmd_names:
197         if '_vec' in name:
198             pmd, vec = name.split('_')
199             name = '{0:{fill}{align}{width}}vec'.format(pmd,
200                     fill='.', align='<', width=max_header_len-3)
201         else:
202             name = '{0:{fill}{align}{width}}'.format(name,
203                     fill=' ', align='<', width=max_header_len)
204         header_names.append(name)
205
206     # Create a dict of the defined features for each driver from the ini files.
207     ini_data = {}
208     for ini_filename in ini_files:
209         config = configparser.ConfigParser()
210         config.optionxform = str
211         config.read(path_join(ini_path, ini_filename))
212
213         # Initialize the dict with the default.ini value.
214         ini_data[ini_filename] = valid_features.copy()
215
216         # Check for a valid ini section.
217         if not config.has_section(section):
218             print("{}: File '{}' has no [{}] secton".format(warning,
219                                                             ini_filename,
220                                                             section))
221             continue
222
223         # Check for valid features names.
224         for name, value in config.items(section):
225             if name not in valid_features:
226                 print("{}: Unknown feature '{}' in '{}'".format(warning,
227                                                                 name,
228                                                                 ini_filename))
229                 continue
230
231             if value:
232                 # Get the first letter only.
233                 ini_data[ini_filename][name] = value[0]
234
235     # Print out the RST Driver Overview table from the ini file data.
236     outfile = open(output_filename, 'w')
237     num_cols = len(header_names)
238
239     print_table_css(outfile, table_id)
240     print('.. table:: ' + table_name + '\n', file=outfile)
241     print_table_header(outfile, num_cols, header_names, title)
242     print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
243
244
245 def print_table_header(outfile, num_cols, header_names, title):
246     """ Print the RST table header. The header names are vertical. """
247     print_table_divider(outfile, num_cols)
248
249     line = ''
250     for name in header_names:
251         line += ' ' + name[0]
252
253     print_table_row(outfile, title, line)
254
255     for i in range(1, len(header_names[0])):
256         line = ''
257         for name in header_names:
258             line += ' ' + name[i]
259
260         print_table_row(outfile, '', line)
261
262     print_table_divider(outfile, num_cols)
263
264
265 def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
266     """ Print out the body of the table. Each row is a NIC feature. """
267
268     for feature, _ in default_features:
269         line = ''
270
271         for ini_filename in ini_files:
272             line += ' ' + ini_data[ini_filename][feature]
273
274         print_table_row(outfile, feature, line)
275
276     print_table_divider(outfile, num_cols)
277
278
279 def print_table_row(outfile, feature, line):
280     """ Print a single row of the table with fixed formatting. """
281     line = line.rstrip()
282     print('   {:<{}}{}'.format(feature, feature_str_len, line), file=outfile)
283
284
285 def print_table_divider(outfile, num_cols):
286     """ Print the table divider line. """
287     line = ' '
288     column_dividers = ['='] * num_cols
289     line += ' '.join(column_dividers)
290
291     feature = '=' * feature_str_len
292
293     print_table_row(outfile, feature, line)
294
295
296 def print_table_css(outfile, table_id):
297     template = """
298 .. raw:: html
299
300    <style>
301       .wy-nav-content {
302          opacity: .99;
303       }
304       table#idx {
305          cursor: default;
306          overflow: hidden;
307       }
308       table#idx p {
309          margin: 0;
310          line-height: inherit;
311       }
312       table#idx th, table#idx td {
313          text-align: center;
314          border: solid 1px #ddd;
315       }
316       table#idx th {
317          padding: 0.5em 0;
318       }
319       table#idx th, table#idx th p {
320          font-size: 11px;
321          white-space: pre-wrap;
322          vertical-align: top;
323          min-width: 0.9em;
324       }
325       table#idx col:first-child {
326          width: 0;
327       }
328       table#idx th:first-child {
329          vertical-align: bottom;
330       }
331       table#idx td {
332          padding: 1px;
333       }
334       table#idx td, table#idx td p {
335          font-size: 11px;
336       }
337       table#idx td:first-child {
338          padding-left: 1em;
339          text-align: left;
340       }
341       table#idx tr:nth-child(2n-1) td {
342          background-color: rgba(210, 210, 210, 0.2);
343       }
344       table#idx th:not(:first-child):hover,
345       table#idx td:not(:first-child):hover {
346          position: relative;
347       }
348       table#idx th:not(:first-child):hover::after,
349       table#idx td:not(:first-child):hover::after {
350          content: '';
351          height: 6000px;
352          top: -3000px;
353          width: 100%;
354          left: 0;
355          position: absolute;
356          z-index: -1;
357          background-color: #ffb;
358       }
359       table#idx tr:hover td {
360          background-color: #ffb;
361       }
362    </style>
363 """
364     print(template.replace("idx", "id%d" % (table_id)), file=outfile)
365
366
367 def setup(app):
368     table_file = dirname(__file__) + '/nics/overview_table.txt'
369     generate_overview_table(table_file, 1,
370                             'Features',
371                             'Features availability in networking drivers',
372                             'Feature')
373     table_file = dirname(__file__) + '/cryptodevs/overview_feature_table.txt'
374     generate_overview_table(table_file, 1,
375                             'Features',
376                             'Features availability in crypto drivers',
377                             'Feature')
378     table_file = dirname(__file__) + '/cryptodevs/overview_cipher_table.txt'
379     generate_overview_table(table_file, 2,
380                             'Cipher',
381                             'Cipher algorithms in crypto drivers',
382                             'Cipher algorithm')
383     table_file = dirname(__file__) + '/cryptodevs/overview_auth_table.txt'
384     generate_overview_table(table_file, 3,
385                             'Auth',
386                             'Authentication algorithms in crypto drivers',
387                             'Authentication algorithm')
388     table_file = dirname(__file__) + '/cryptodevs/overview_aead_table.txt'
389     generate_overview_table(table_file, 4,
390                             'AEAD',
391                             'AEAD algorithms in crypto drivers',
392                             'AEAD algorithm')
393     table_file = dirname(__file__) + '/cryptodevs/overview_asym_table.txt'
394     generate_overview_table(table_file, 5,
395                             'Asymmetric',
396                             'Asymmetric algorithms in crypto drivers',
397                             'Asymmetric algorithm')
398     table_file = dirname(__file__) + '/compressdevs/overview_feature_table.txt'
399     generate_overview_table(table_file, 1,
400                             'Features',
401                             'Features availability in compression drivers',
402                             'Feature')
403     table_file = dirname(__file__) + '/regexdevs/overview_feature_table.txt'
404     generate_overview_table(table_file, 1,
405                             'Features',
406                             'Features availability in regex drivers',
407                             'Feature')
408     table_file = dirname(__file__) + '/vdpadevs/overview_feature_table.txt'
409     generate_overview_table(table_file, 1,
410                             'Features',
411                             'Features availability in vDPA drivers',
412                             'Feature')
413     table_file = dirname(__file__) + '/bbdevs/overview_feature_table.txt'
414     generate_overview_table(table_file, 1,
415                             'Features',
416                             'Features availability in bbdev drivers',
417                             'Feature')
418
419     if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
420         print('Upgrade sphinx to version >= 1.3.1 for '
421               'improved Figure/Table number handling.')
422         # Add a role to handle :numref: references.
423         app.add_role('numref', numref_role)
424         # Process the numref references once the doctree has been created.
425         app.connect('doctree-resolved', process_numref)
426
427     try:
428         # New function in sphinx 1.8
429         app.add_css_file('css/custom.css')
430     except:
431         app.add_stylesheet('css/custom.css')