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