xref: /dpdk/doc/guides/conf.py (revision 4c3ea50880c90a1681c7f4c12a558cff37d01f03)
1#   BSD LICENSE
2#   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
3#   All rights reserved.
4#
5#   Redistribution and use in source and binary forms, with or without
6#   modification, are permitted provided that the following conditions
7#   are met:
8#
9#   * Redistributions of source code must retain the above copyright
10#   notice, this list of conditions and the following disclaimer.
11#   * Redistributions in binary form must reproduce the above copyright
12#   notice, this list of conditions and the following disclaimer in
13#   the documentation and/or other materials provided with the
14#   distribution.
15#   * Neither the name of Intel Corporation nor the names of its
16#   contributors may be used to endorse or promote products derived
17#   from this software without specific prior written permission.
18#
19#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20#   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31from __future__ import print_function
32import subprocess
33from docutils import nodes
34from distutils.version import LooseVersion
35from sphinx import __version__ as sphinx_version
36from sphinx.highlighting import PygmentsBridge
37from pygments.formatters.latex import LatexFormatter
38from os import listdir
39from os.path import basename
40from os.path import dirname
41from os.path import join as path_join
42
43try:
44    # Python 2.
45    import ConfigParser as configparser
46except:
47    # Python 3.
48    import configparser
49
50
51project = 'Data Plane Development Kit'
52
53if LooseVersion(sphinx_version) >= LooseVersion('1.3.1'):
54    html_theme = "sphinx_rtd_theme"
55html_logo = '../logo/DPDK_logo_vertical_rev_small.png'
56latex_logo = '../logo/DPDK_logo_horizontal_tag.png'
57html_add_permalinks = ""
58html_show_copyright = False
59highlight_language = 'none'
60
61version = subprocess.check_output(['make', '-sRrC', '../../', 'showversion']).decode('utf-8').rstrip()
62release = version
63
64master_doc = 'index'
65
66# Figures, tables and code-blocks automatically numbered if they have caption
67numfig = True
68
69latex_documents = [
70    ('index',
71     'doc.tex',
72     '',
73     '',
74     'manual')
75]
76
77# Latex directives to be included directly in the latex/pdf docs.
78latex_preamble = r"""
79\usepackage[utf8]{inputenc}
80\usepackage[T1]{fontenc}
81\usepackage{helvet}
82\renewcommand{\familydefault}{\sfdefault}
83\RecustomVerbatimEnvironment{Verbatim}{Verbatim}{xleftmargin=5mm}
84"""
85
86# Configuration for the latex/pdf docs.
87latex_elements = {
88    'papersize': 'a4paper',
89    'pointsize': '11pt',
90    # remove blank pages
91    'classoptions': ',openany,oneside',
92    'babel': '\\usepackage[english]{babel}',
93    # customize Latex formatting
94    'preamble': latex_preamble
95}
96
97# Override the default Latex formatter in order to modify the
98# code/verbatim blocks.
99class CustomLatexFormatter(LatexFormatter):
100    def __init__(self, **options):
101        super(CustomLatexFormatter, self).__init__(**options)
102        # Use the second smallest font size for code/verbatim blocks.
103        self.verboptions = r'formatcom=\footnotesize'
104
105# Replace the default latex formatter.
106PygmentsBridge.latex_formatter = CustomLatexFormatter
107
108######## :numref: fallback ########
109# The following hook functions add some simple handling for the :numref:
110# directive for Sphinx versions prior to 1.3.1. The functions replace the
111# :numref: reference with a link to the target (for all Sphinx doc types).
112# It doesn't try to label figures/tables.
113
114def numref_role(reftype, rawtext, text, lineno, inliner):
115    """
116    Add a Sphinx role to handle numref references. Note, we can't convert
117    the link here because the doctree isn't build and the target information
118    isn't available.
119    """
120    # Add an identifier to distinguish numref from other references.
121    newnode = nodes.reference('',
122                              '',
123                              refuri='_local_numref_#%s' % text,
124                              internal=True)
125    return [newnode], []
126
127def process_numref(app, doctree, from_docname):
128    """
129    Process the numref nodes once the doctree has been built and prior to
130    writing the files. The processing involves replacing the numref with a
131    link plus text to indicate if it is a Figure or Table link.
132    """
133
134    # Iterate over the reference nodes in the doctree.
135    for node in doctree.traverse(nodes.reference):
136        target = node.get('refuri', '')
137
138        # Look for numref nodes.
139        if target.startswith('_local_numref_#'):
140            target = target.replace('_local_numref_#', '')
141
142            # Get the target label and link information from the Sphinx env.
143            data = app.builder.env.domains['std'].data
144            docname, label, _ = data['labels'].get(target, ('', '', ''))
145            relative_url = app.builder.get_relative_uri(from_docname, docname)
146
147            # Add a text label to the link.
148            if target.startswith('figure'):
149                caption = 'Figure'
150            elif target.startswith('table'):
151                caption = 'Table'
152            else:
153                caption = 'Link'
154
155            # New reference node with the updated link information.
156            newnode = nodes.reference('',
157                                      caption,
158                                      refuri='%s#%s' % (relative_url, label),
159                                      internal=True)
160            node.replace_self(newnode)
161
162
163def generate_nic_overview_table(output_filename):
164    """
165    Function to generate the NIC Overview Table from the ini files that define
166    the features for each NIC.
167
168    The default features for the table and their order is defined by the
169    'default.ini' file.
170
171    """
172    # Default worning string.
173    warning = 'Warning generate_nic_overview_table()'
174
175    # Get the default features and order from the 'default.ini' file.
176    ini_path = path_join(dirname(output_filename), 'features')
177    config = configparser.ConfigParser()
178    config.optionxform = str
179    config.read(path_join(ini_path, 'default.ini'))
180    default_section = 'Features'
181    default_features = config.items(default_section)
182
183    # Create a dict of the valid features to validate the other ini files.
184    valid_features = {}
185    max_feature_length = 0
186    for feature in default_features:
187        key = feature[0]
188        valid_features[key] = ' '
189        max_feature_length = max(max_feature_length, len(key))
190
191    # Get a list of NIC ini files, excluding 'default.ini'.
192    ini_files = [basename(file) for file in listdir(ini_path)
193                 if file.endswith('.ini') and file != 'default.ini']
194    ini_files.sort()
195
196    # Build up a list of the table header names from the ini filenames.
197    header_names = []
198    for ini_filename in ini_files:
199        name = ini_filename[:-4]
200        name = name.replace('_vf', 'vf')
201
202        # Pad the table header names to match the existing format.
203        if '_vec' in name:
204            pmd, vec = name.split('_')
205            name = '{0:{fill}{align}7}vec'.format(pmd, fill='.', align='<')
206        else:
207            name = '{0:{fill}{align}10}'.format(name, fill=' ', align='<')
208
209        header_names.append(name)
210
211    # Create a dict of the defined features for each NIC from the ini files.
212    ini_data = {}
213    for ini_filename in ini_files:
214        config = configparser.ConfigParser()
215        config.optionxform = str
216        config.read(path_join(ini_path, ini_filename))
217
218        # Initialize the dict with the default.ini value.
219        ini_data[ini_filename] = valid_features.copy()
220
221        # Check for a valid ini section.
222        if not config.has_section(default_section):
223            print("{}: File '{}' has no [{}] secton".format(warning,
224                                                            ini_filename,
225                                                            default_section))
226            continue
227
228        # Check for valid features names.
229        for name, value in config.items(default_section):
230            if name not in valid_features:
231                print("{}: Unknown feature '{}' in '{}'".format(warning,
232                                                                name,
233                                                                ini_filename))
234                continue
235
236            if value is not '':
237                # Get the first letter only.
238                ini_data[ini_filename][name] = value[0]
239
240    # Print out the RST NIC Overview table from the ini file data.
241    outfile = open(output_filename, 'w')
242    num_cols = len(header_names)
243
244    print('.. table:: Features availability in networking drivers\n',
245          file=outfile)
246
247    print_table_header(outfile, num_cols, header_names)
248    print_table_body(outfile, num_cols, ini_files, ini_data, default_features)
249
250
251def print_table_header(outfile, num_cols, header_names):
252    """ Print the RST table header. The header names are vertical. """
253    print_table_divider(outfile, num_cols)
254
255    line = ''
256    for name in header_names:
257        line += ' ' + name[0]
258
259    print_table_row(outfile, 'Feature', line)
260
261    for i in range(1, 10):
262        line = ''
263        for name in header_names:
264            line += ' ' + name[i]
265
266        print_table_row(outfile, '', line)
267
268    print_table_divider(outfile, num_cols)
269
270
271def print_table_body(outfile, num_cols, ini_files, ini_data, default_features):
272    """ Print out the body of the table. Each row is a NIC feature. """
273
274    for feature, _ in default_features:
275        line = ''
276
277        for ini_filename in ini_files:
278            line += ' ' + ini_data[ini_filename][feature]
279
280        print_table_row(outfile, feature, line)
281
282    print_table_divider(outfile, num_cols)
283
284
285def print_table_row(outfile, feature, line):
286    """ Print a single row of the table with fixed formatting. """
287    line = line.rstrip()
288    print('   {:<20}{}'.format(feature, line), file=outfile)
289
290
291def print_table_divider(outfile, num_cols):
292    """ Print the table divider line. """
293    line = ' '
294    column_dividers = ['='] * num_cols
295    line += ' '.join(column_dividers)
296
297    feature = '=' * 20
298
299    print_table_row(outfile, feature, line)
300
301
302def setup(app):
303    generate_nic_overview_table('doc/guides/nics/overview_table.txt')
304
305    if LooseVersion(sphinx_version) < LooseVersion('1.3.1'):
306        print('Upgrade sphinx to version >= 1.3.1 for '
307              'improved Figure/Table number handling.')
308        # Add a role to handle :numref: references.
309        app.add_role('numref', numref_role)
310        # Process the numref references once the doctree has been created.
311        app.connect('doctree-resolved', process_numref)
312