Added Value

Added Value is a tool which makes it easy to embed values extracted from Python modules in Sphinx documentation. This allows important constants, collections and tables to have a single source of truth in the software, so that documentation always faithfully represents the underlying values used by the software. Uses of Added Value are not specific to documenting source code, although it can help in that task in conjunction with Sphinx’ tools for such at the roles and directives in the Python, and other language domains.

Some Quick Examples

Using added value we can extract the value of pi from the Python Standard Library math module, and embed it in a sentence, using Added Values’s format role:

The ratio of the circumference to the diameter of a circle is :format:`math.pi, .3f` to three
decimal places.

Which gives:

The ratio of the circumference to the diameter of a circle is 3.142 to three decimal places.

Added value is powerful, and allows lists, dictionaries, and even complex data structures such as lists of lists of dictionaries to be rendered into text in various ways. Consider the following dictionary of dictionaries of dictionaries:

economic_data = {
    "United States": {
        "GDP %": {
            "latest": 3.0,
            "quarter": 3.5,
            "2018": 2.9,
        },
        "Consumer prices %": {
            "latest": 2.3,
            "2018": 2.5,
        },
        "Unemployment rate %": {
            "latest": 3.7,
        },
    },
    "China": {
        "GDP %": {
            "latest": 6.5,
            "quarter": 6.6,
            "2018": 6.6,
        },
        "Consumer prices %": {
            "latest": 2.5,
            "2018": 2.1,
        },
        "Unemployment rate %": {
            "latest": 3.8,
        },
    },
    "Japan": {
        "GDP %": {
            "latest": 1.3,
            "quarter": 3.0,
            "2018": 1.0,
        },
        "Consumer prices %": {
            "latest": 1.2,
            "2018": 0.9,
        },
        "Unemployment rate %": {
            "latest": 2.3,
        },
    },
    "Britain": {
        "GDP %": {
            "latest": 1.2,
            "quarter": 1.6,
            "2018": 1.3,
        },
        "Consumer prices %": {
            "latest": 2.4,
            "2018": 2.4,
        },
        "Unemployment rate %": {
            "latest": 4.0,
        },
    },
}

usa_economic_data = {country: data for country, data in economic_data.items() if country == "United States"}

Using Added Value’s items-table directive, we can embed this into the documentation as a table:

.. items-table:: economy.economic_data
   :title: **Economic Data**
   :v-level-indexes: 0
   :h-level-indexes: 1, 2
   :header-rows: 2
   :stub-columns: 1

which when rendered, looks like this:

Economic Data
  GDP % Consumer prices % Unemployment rate %
  latest quarter 2018 latest 2018 latest
United States 3.0 3.5 2.9 2.3 2.5 3.7
China 6.5 6.6 6.6 2.5 2.1 3.8
Japan 1.3 3.0 1.0 1.2 0.9 2.3
Britain 1.2 1.6 1.3 2.4 2.4 4.0

Reference Documentation

Embedding Single Items

For the examples below, assume the existence of a Python module called elements with the following contents:

# elements.py

CARBON_WEIGHT = 12.011
SILICON_SYMBOL = 'Si'

Role: str – embed the string conversion of an object

Single values from Python code may be included in this documentation using the :str: role, like this:

The atomic weight of carbon-12 is :str:`elements.CARBON_WEIGHT`.

which gives:

The atomic weight of carbon-12 is 12.011.

The value here is a float, but any Python object which can be converted to a string using the built string constructor str(obj) is suitable, which will ultimately invoke the __str__() special method of the object being formatted.

Role: repr – embed the string representation of an object

By using the :repr: role instead, the alternative Python string representation (usually intended for consumption by developers) can be inserted:

By passing the string key, such as :repr:`elements.SILICON_SYMBOL`, to the function the
corresponding element name can be retrieved.

which gives:

By passing the string key, such as ‘Si’, to the function the corresponding element name can be retrieved.

Note that the quotes now included in the string, as they are part of the representation of the object returned by the built-in repr(obj) function, which will ultimately invoke the __repr__() special method of the object being embedded.

Role: format – embed a formatted string representation of an object

By using the :format: role, you can gain control over the formatting of Python objects.

The value of the mathematic constamt *e* is :format:`math.e, .3f` to three decimal places.

which gives:

The value of the mathematic constamt e is 2.718 to three decimal places.

The role accepts two items separated by a comma. The first is a reference to the object to be embedded. The second is a format specifier. The object being embedded here is a float, but any Python object which can be passed to the built-in format() function can be used. The allowable values for the format specifier depend on the type of the object being formatted.

Embedding Series of Items

Series of values (e.g. Python lists, tuples and other iterables) may be incorporated into the documentation using the roles described below.

For the examples below, assume the existence of a Python module called materials with the following contents:

# materials.py

metals = [
    "platinum",
    "silver",
    "gold",
]

Role: any-items – embed a series of alternative items

To embed a series of alternative items in a sentence, use the :any-items role:

You must select :any-items:`materials.metals` when specifying a material.

which gives:

You must select platinum, silver, or gold when specifying a material.

Note that :any-items: uses the English “or” as the coordinating conjunction between the final two items. Each item is rendered by conversion to string using the string constructor str() which ultimately called the __str__() special method on the item.

Role: all-items - embed a series of non-contrasting items

To embed a series of non-contrasting items in a sentence, use the :all-items role:

Precious metals include :all-items:`materials.metals`.

which gives:

Precious metals include platinum, silver, and gold.

Note that :all-items: uses the English “and” as the coordinating conjunction between the final two items. Each item is rendered by conversion to string using the string constructor str() which ultimately called the __str__() special method on the item.

Directive: items-list – embed collections as lists

Bullet lists

The items-list:: directive can be used to represent collections as lists. The :list-type: option is mandatory. For a flat bullet list, specify :list-types: bullet like this:

Precious metals include:

.. items-list:: materials.metals
   :list-types: bullet

which gives:

Precious metals include:

  • platinum
  • silver
  • gold

Enumerated lists

For an enumerated list, specify :list-types: enumerated

Precious metals include:

.. items-list:: materials.metals
   :list-types: bullet

which gives:

Precious metals include:

  • platinum
  • silver
  • gold

Definition lists

Definition lists are designed to display a term and its definition, and so must be used with a mapping type, such as a dictionary, and cannot be used with other iterable types, such as a list or set. For example, given the dictionary:

month_abbreviations = {
    "Jan": "January",
    "Feb": "February",
    "Mar": "March",
    "Apr": "April",
    "May": "May",
    "Jun": "June",
    "Jul": "July",
    "Aug": "August",
    "Sep": "September",
    "Oct": "October",
    "Nov": "November",
    "Dec": "December",
}

using the follow directive,

Abbreviations of months and their definitions:

.. items-list:: cal.month_abbreviations
   :list-types: definition

we can render a definition list:

Abbreviations of months and their definitions:

Jan
January
Feb
February
Mar
March
Apr
April
May
May
Jun
June
Jul
July
Aug
August
Sep
September
Oct
October
Nov
November
Dec
December

Sorting lists

The order of display of items can be controlled using the :sort-orders: option, which accepts three values: asc for ascending natural sort, dec for descending natural sort, or as-is for displaying the values in their original order.

Precious metals include:

.. items-list:: materials.metals
   :list-types: bullet
   :sort-orders: asc

which gives:

Precious metals include:

  • gold
  • platinum
  • silver

Nested lists from nested data structures

The items-list:: directive can be used to represent hierarchical data structures. Consider the following, dictionary of dictionaries of dictionaries:

economic_data = {
    "United States": {
        "GDP %": {
            "latest": 3.0,
            "quarter": 3.5,
            "2018": 2.9,
        },
        "Consumer prices %": {
            "latest": 2.3,
            "2018": 2.5,
        },
        "Unemployment rate %": {
            "latest": 3.7,
        },
    },
    "China": {
        "GDP %": {
            "latest": 6.5,
            "quarter": 6.6,
            "2018": 6.6,
        },
        "Consumer prices %": {
            "latest": 2.5,
            "2018": 2.1,
        },
        "Unemployment rate %": {
            "latest": 3.8,
        },
    },
    "Japan": {
        "GDP %": {
            "latest": 1.3,
            "quarter": 3.0,
            "2018": 1.0,
        },
        "Consumer prices %": {
            "latest": 1.2,
            "2018": 0.9,
        },
        "Unemployment rate %": {
            "latest": 2.3,
        },
    },
    "Britain": {
        "GDP %": {
            "latest": 1.2,
            "quarter": 1.6,
            "2018": 1.3,
        },
        "Consumer prices %": {
            "latest": 2.4,
            "2018": 2.4,
        },
        "Unemployment rate %": {
            "latest": 4.0,
        },
    },
}

usa_economic_data = {country: data for country, data in economic_data.items() if country == "United States"}

When displaying, data structures with multiple levels, the type of list to be used at each level must be specified as a comma-separated list. In this case the outer list will be a bullet list, the intermediate lists will be enumerated lists, and the innermost lists will be definition lists:

.. items-list:: economy.economic_data
   :list-types: bullet, enumerated, definition

which is displayed as:

  • United States

    1. GDP %

      latest

      3.0

      quarter

      3.5

      2018

      2.9

    2. Consumer prices %

      latest

      2.3

      2018

      2.5

    3. Unemployment rate %

      latest

      3.7

  • China

    1. GDP %

      latest

      6.5

      quarter

      6.6

      2018

      6.6

    2. Consumer prices %

      latest

      2.5

      2018

      2.1

    3. Unemployment rate %

      latest

      3.8

  • Japan

    1. GDP %

      latest

      1.3

      quarter

      3.0

      2018

      1.0

    2. Consumer prices %

      latest

      1.2

      2018

      0.9

    3. Unemployment rate %

      latest

      2.3

  • Britain

    1. GDP %

      latest

      1.2

      quarter

      1.6

      2018

      1.3

    2. Consumer prices %

      latest

      2.4

      2018

      2.4

    3. Unemployment rate %

      latest

      4.0

Notice how the dictionary keys are used for headings before each nested list.

Formatting control

The formatting of lists is controlled with various additional format options.

Controlling bullets, enumerator and terms with key-formats

The :key-formats: option controls how bullets, enumerators and terms are displayed for bullet lists, enumerated lists, and definition lists respectively.

.. items-list:: economy.usa_economic_data
   :list-types: bullet, enumerated, definition
   :key-formats: •, i), {k}:-
  • United States

    1. GDP %

      latest:-

      3.0

      quarter:-

      3.5

      2018:-

      2.9

    2. Consumer prices %

      latest:-

      2.3

      2018:-

      2.5

    3. Unemployment rate %

      latest:-

      3.7

Above, the bullet list has a disc bullet, the enumerated lists use lower-case roman numerals, and the term for the definition list is terminated by a colon and hypen.

For bullet lists the options are *, +, -, , , or . Note that while this information is passed through the documentation rendering pipeline, few renderers or styles respect this option, so it’s usually easiest to stay with a asterisk *. The default is *.

For enumerated lists, the options are arabic numerals 1, upper-case letters A, lower-case letters A, lower-case Roman numerals i, upper-case Roman numerals I. These can be combined with various prefix and suffix puncuation, so (A), 1. i: are all valid. Furthermore, the starting value can be specified with, for example, iv.. The extent to which the enumerator format is respected is very much a function of the theme or stylesheets in use, and some popular themes, such as the Read The Docs theme, are somewhat defective in this area. The default is 1.

For definition lists, the key-format is a string containing Python-style replacement fields delimited by curly braces. Three replacement values are supported: {k} is the key of the current item from the mapping; the {v} replacement field is the value of the current item from the mapping. These may be used in any combination and the format specifiers support any options supported by the underlying key and value types in the dictionary. The {o} replacement field is the one-based integer ordinal after sorting. Any features from the Python format specifier mini-language can be used. See the Python documentation for more details. The default is key format for defintion lists is {k}.

Controlling internal and leaf node formats

We can consider a nested hierarchy of dictionaries to consist of internal nodes and leaf nodes. The dictionary keys (or sequence indexes) at all levels represent the internal nodes, and the values of the innermost collections represent the leaf nodes.

The formats of the internal nodes are controlled by the :internal-formats: option, which accepts a comma-separated list of formats, one for each level. Each value format is a string containing Python-style replacement fields delimited by curly braces. Three replacement values are supported: {k} is the key of the current item from the mapping, or for sequences and other iterables, a zero-based index before sorting; the {v} replacement field is the value of the current item from the collection; the {o} replacement field is the one-based ordinal integer after sorting. The default internal format for mapping collections such as dict is {k}, whereas the default for other collections such as list is empty.

.. items-list:: economy.usa_economic_data
   :list-types: bullet, enumerated, bullet
   :internal-formats: "Country: {k}", "Statistic: {k}", "Period: {k}"

Note

We have used a bullet list at the third-level here, as :internal-format: has no effect on definition lists at the innermost level, as the corresponding :key-format: will be used instead to format the term.

  • Country: United States

    1. Statistic: GDP %

      • Period: latest

        3.0

      • Period: quarter

        3.5

      • Period: 2018

        2.9

    2. Statistic: Consumer prices %

      • Period: latest

        2.3

      • Period: 2018

        2.5

    3. Statistic: Unemployment rate %

      • Period: latest

        3.7

The leaf-node formats are controlled with the :leaf-format: option. This accepts a single Python style format-string containing curly-brace delimited replacements fields. Three replacement values are supported: {k} is the key of the current item from the mapping, or for sequences and other iterables, a zero-based index before sorting; the {v} replacement field is the value of the current item from the collection; the {o} field is the integer ordinal after sorting. The default leaf format is {v}.

.. items-list:: economy.usa_economic_data
   :list-types: bullet, enumerated, bullet
   :internal-formats: "Country: {k}", "Statistic: {k}", "Period: {k}"
   :leaf-format: {v:.1f}%

The leaf values are floating point numbers, and here the :leaf-format: option is used to display those values with one decimal place and append a percentage symbol.

  • Country: United States

    1. Statistic: GDP %

      • Period: latest

        3.0%

      • Period: quarter

        3.5%

      • Period: 2018

        2.9%

    2. Statistic: Consumer prices %

      • Period: latest

        2.3%

      • Period: 2018

        2.5%

    3. Statistic: Unemployment rate %

      • Period: latest

        3.7%

By means of creative combination of these options various effects can be achieved. In this economic dataset the innermost dictionaries each contain only one item. By using an combining the leaf value into the internal-format and specifying an empty leaf-format the innermost structure can be flattened:

.. items-list:: economy.usa_economic_data
   :list-types: bullet, enumerated, bullet
   :key-formats: *, i., *
   :internal-formats: "Country: {k}", {k}, "{k}{v:.1f}%"
   :leaf-format:
   :sort-orders: as-is, asc, as-is
  • Country: United States

    1. Consumer prices %

      • latest – 2.3%

      • 2018 – 2.5%

    2. GDP %

      • latest – 3.0%

      • quarter – 3.5%

      • 2018 – 2.9%

    3. Unemployment rate %

      • latest – 3.7%

Using iterables and sequences with items-list::

The examples so far have used nested collections which support the Mapping protocol, specifically dictionaries. The items-list:: directive can be used with other collections which support the Iterable or Sequence protocols, and in any combination.

Consider the following list of lists:

quarter_months = [
    ["Jan", "Feb", "Mar"],
    ["Apr", "May", "Jun"],
    ["Jul", "Aug", "Sep"],
    ["Oct", "Nov", "Dec"],
]

Without specifying any options,

.. items-list:: cal.quarter_months

this is displayed as a single-level bullet list:

  • [‘Jan’, ‘Feb’, ‘Mar’]
  • [‘Apr’, ‘May’, ‘Jun’]
  • [‘Jul’, ‘Aug’, ‘Sep’]
  • [‘Oct’, ‘Nov’, ‘Dec’]

Not very useful.

By specifying two list types, like this,

.. items-list:: cal.quarter_months
   :list-types: bullet, bullet

we get this:

    • Jan
    • Feb
    • Mar
    • Apr
    • May
    • Jun
    • Jul
    • Aug
    • Sep
    • Oct
    • Nov
    • Dec

Notice that the internal-format for non-mapping types defaults to being empty, so the list indexes not displayed. Using the {o} format-specifier in the internal-format for the outer list, we can include the one-based ordinal number in the string.

  • Quarter 1
    • Jan
    • Feb
    • Mar
  • Quarter 2
    • Apr
    • May
    • Jun
  • Quarter 3
    • Jul
    • Aug
    • Sep
  • Quarter 4
    • Oct
    • Nov
    • Dec

Indexes, keys and ordinals

Various numbering systems are in play with lists of sequences, which can make things confusing. Let’s return to our list of metals:

# materials.py

metals = [
    "platinum",
    "silver",
    "gold",
]

This simple list contains three items at indexes zero, one and two.

We can configure an items list to display the various numbering systems in play:

.. items-list:: materials.metals
   :list-types: enumerated
   :key-formats: iv.
   :leaf-format: value={v}, ordinal={o}, key={k}
  1. value=platinum, ordinal=1, key=0
  2. value=silver, ordinal=2, key=1
  3. value=gold, ordinal=3, key=2

Here we have the enumerator values starting with Roman numeral iv, the ordinal values which give a one-based position in the list (for display purposes we usually want one-based indexes) and the key, which is the original list index (or dictionary key).

The ordinal always increases from top to bottom, but the key is preserved, even if we sort the items.

.. items-list:: materials.metals
   :list-types: enumerated
   :key-formats: iv.
   :leaf-format: value={v}, ordinal={o}, key={k}
   :sort-orders: asc
  1. value=gold, ordinal=1, key=2
  2. value=platinum, ordinal=2, key=0
  3. value=silver, ordinal=3, key=1

The ordinal base can be modified independently using the ordinal-bases option, which defaults to one. Here we set it to zero:

.. items-list:: materials.metals
   :list-types: enumerated
   :key-formats: iv.
   :leaf-format: value={v}, ordinal={o}, key={k}
   :sort-orders: asc
   :ordinal-bases: 0
  1. value=gold, ordinal=0, key=2
  2. value=platinum, ordinal=1, key=0
  3. value=silver, ordinal=2, key=1

Embedding Tables

Directive: items-table – embed sequences and mappings as tables

Added value includes powerful facilities for creating tabular presentations of single- and multi-dimensional data structures, such as lists of lists and lists of dictionaries. We’ll start with a few basic examples of the items-table:: directive, before explaining all various configuration options.

Basic Examples

Table from a list

Python sequences, such as a lists, can be represented as tables. Consider the following Python data structure, which is a list of strings containing the names of the days of the week:

days_of_the_week = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

This is how we would refer to that table using an items-table:: directive:

.. items-table:: cal.days_of_the_week

which will be rendered like this:

0 Monday
1 Tuesday
2 Wednesday
3 Thursday
4 Friday
5 Saturday
6 Sunday

Notice that the list indexes are included in the table data.

Table from a dictionary

Python mappings, such as a dictionaries, can be represented as a tables. Consider the following Python data structure, which is a dictionary mapping the names of the months as strings, to the number of days in those months as an integer:

month_lengths = {
    "January": 31,
    "February": 28,
    "March": 31,
    "April": 30,
    "May": 31,
    "June": 30,
    "July": 31,
    "August": 31,
    "September": 30,
    "October": 31,
    "November": 31,
    "December": 31,
}

This is how we would refer to that table using an items-table:: directive:

.. items-table:: cal.month_lengths

which will be rendered like this:

January 31
February 28
March 31
April 30
May 31
June 30
July 31
August 31
September 30
October 31
November 31
December 31

Notice that the dictionary keys are included in the table data.

Table from list of lists

Arbitrarily nested combinations of sequences and mappings (e.g. lists and dictionaries).

elements = {
    "H": {
        "name": "Hydrogen",
        "weight": 1.008,
        "number": 1,
        "boiling point": 20.271,

    },
    "He": {
        "name": "Helium",
        "weight": 4.003,
        "number": 2,
        "boiling point": 4.222,
    },
    "Li": {
        "name": "Lithium",
        "weight": 6.94,
        "number": 3,
        "boiling point": 1603.0,
    },
    "Be": {
        "name": "Beryllium",
        "weight": 9.012,
        "number": 4,
        "boiling point": 2742.0,
    },
}

This is how we would refer to that table using an items-table:: directive:

.. items-table:: elements.elements

which will be rendered like this:

  name weight number boiling point
H Hydrogen 1.008 1 20.271
He Helium 4.003 2 4.222
Li Lithium 6.94 3 1603.0
Be Beryllium 9.012 4 2742.0

Projecting multi-level data structures into tables

Data structures such a list-of-lists or list-of-dictionaries can be considered as being multi-level. For example, a list of integers is a single-level data structure, a list of list of integers is a two-level data structure, and a list of lists of lists is a three- level data structure. Each of these levels can be given a zero-based indexed, called the level index. So in the case of a list of lists of dictionaries, the outer list has indexes at level zero, the inner lists have indexes at level one, and the dictionaries contained within those inner lists have indexes at level two.

One easy way to see this is to think about how many successive applications of Python’s indexing operator are required to access an item.

                                  ┌────────── level 0 (outer list index)
                                  │   ┌────── level 1 (inner list index)
                                  │   │    ┌─ level 2 (dictionary key)
                                  │   │    │
item = list_of_lists_dictionaries[12][32]["red"]

Tables can be no more than two dimensional, so when projecting multi-level data structures into a table some decisions have to be be made. By default, even levels are projected to the vertical axis of the table, and odd levels are projected to the horizontal axis of the table. This works well for the common cases of single level and double-level data structures. For more than two levels, it will likely to necessary to exercise greater control over which levels are projected onto which table axes using options to the items-table:: directive.

Options to control items-table

The items-table:: directive support the following options:

header-rows:The number of leading rows to be formatted as the header.
stub-columns:The number of leading columns to be formatted as header.
header:A comma-separated list of strings to be used as a header row.
widths:A comma-separated list of column widths
title:A title for the table.
v-level-indexes:
 A comma-separated list of level indexes for the vertical axis of the table (row indexes). Defaults to even level indexes. Must be disjoint with h-level-indexes.
h-level-indexes:
 A comma-separated list of level indexes for the horizontal axis of the table (column indexes). Defaults to odd level indexes. Must be disjoint with v-level-indexes.
v-level-visibility:
 A comma-separated list of show or hide values controlling index visibility for the vertical axis of the table. Useful for hiding unwanted sequence indexes.
h-level-visibility:
 A comma-separated list of show or hide values controlling index visibility for the horizontal axis of the table. Useful for hiding unwanted sequence indexes.
h-level-titles:A comma-separated list of names to be associated with each level for the horizontal axis of the table (column indexes).
v-level-titles:A comma-separated list of names to be associated with each level for the vertical axis of the table (column indexes).
v-level-sort-orders:
 A comma-separated list of asc, dec or as-is values, controlling whether the corresponding indexes are sorted in ascending natural order, descending natural order, or taken as-is.
h-level-sort-orders:
 A comma-separated list of asc, dec or as-is values, controlling whether the corresponding indexes are sorted in ascending natural order, descending natural order, or taken as-is.
cell-formats:TODO

Examples

Specify the number of header rows

Use the :header-rows: option to specify the number of leading rows of the table which are to be considered as column headers:

.. items-table:: elements.elements
   :header-rows: 1

which will be rendered like this:

  name weight number boiling point
H Hydrogen 1.008 1 20.271
He Helium 4.003 2 4.222
Li Lithium 6.94 3 1603.0
Be Beryllium 9.012 4 2742.0

The exact style of header rows depends on the theme in use.

Specify the number of stub columns

Use the :stub-columms: option to specify the number of leading columns of the table which are to be considered as row headers:

.. items-table:: elements.elements
   :stub-columns: 1

which will be rendered like this:

  name weight number boiling point
H Hydrogen 1.008 1 20.271
He Helium 4.003 2 4.222
Li Lithium 6.94 3 1603.0
Be Beryllium 9.012 4 2742.0

The exact style of stub columns depends on the theme in use.

Control the assignment of level indexes to tables axes

By default even-numbered levels are projected on to the vertical tables axis, and odd-numbered levels projected to horizontal table axis. To gain more control over which levels of the data structure are projected onto which table axis, use the :v-level-indexes and :h-level-indexes options to the items-table:: directive.

Consider the following three-level economic data stored in a dictionary of dictionaries of dictionaries:

economic_data = {
    "United States": {
        "GDP %": {
            "latest": 3.0,
            "quarter": 3.5,
            "2018": 2.9,
        },
        "Consumer prices %": {
            "latest": 2.3,
            "2018": 2.5,
        },
        "Unemployment rate %": {
            "latest": 3.7,
        },
    },
    "China": {
        "GDP %": {
            "latest": 6.5,
            "quarter": 6.6,
            "2018": 6.6,
        },
        "Consumer prices %": {
            "latest": 2.5,
            "2018": 2.1,
        },
        "Unemployment rate %": {
            "latest": 3.8,
        },
    },
    "Japan": {
        "GDP %": {
            "latest": 1.3,
            "quarter": 3.0,
            "2018": 1.0,
        },
        "Consumer prices %": {
            "latest": 1.2,
            "2018": 0.9,
        },
        "Unemployment rate %": {
            "latest": 2.3,
        },
    },
    "Britain": {
        "GDP %": {
            "latest": 1.2,
            "quarter": 1.6,
            "2018": 1.3,
        },
        "Consumer prices %": {
            "latest": 2.4,
            "2018": 2.4,
        },
        "Unemployment rate %": {
            "latest": 4.0,
        },
    },
}

usa_economic_data = {country: data for country, data in economic_data.items() if country == "United States"}

The default view is equivalent to this, with even-numbered :v-level indexes:, and odd-numbered :h-level-indexes::

.. items-table:: economy.economic_data
   :v-level-indexes: 0, 2
   :h-level-indexes: 1

which will be rendered like this:

    GDP % Consumer prices % Unemployment rate %
United States latest 3.0 2.3 3.7
United States quarter 3.5    
United States 2018 2.9 2.5  
China latest 6.5 2.5 3.8
China quarter 6.6    
China 2018 6.6 2.1  
Japan latest 1.3 1.2 2.3
Japan quarter 3.0    
Japan 2018 1.0 0.9  
Britain latest 1.2 2.4 4.0
Britain quarter 1.6    
Britain 2018 1.3 2.4  

Note

Tables cells for which there is no corresponding data will be left empty.

A more useful presentation would be to put only the country (level zero) on the vertical table axis, and both catgeory and timing information on the horizontal axis:

.. items-table:: economy.economic_data
   :v-level-indexes: 0
   :h-level-indexes: 1, 2

which will be rendered like this:

  GDP % GDP % GDP % Consumer prices % Consumer prices % Unemployment rate %
  latest quarter 2018 latest 2018 latest
United States 3.0 3.5 2.9 2.3 2.5 3.7
China 6.5 6.6 6.6 2.5 2.1 3.8
Japan 1.3 3.0 1.0 1.2 0.9 2.3
Britain 1.2 1.6 1.3 2.4 2.4 4.0
Hide a level of indexes

Particularly when dealing with sequences (e.g. lists) of data, we don’t wish to see the zero-based indexes. Consider this list of lists containing a calendar of days in October 2018:

october_2018 = [
    [1, 2, 3, 4, 5, 6, 7],
    [8, 9, 10, 11, 12, 13, 14],
    [15, 16, 17, 18, 19, 20, 21],
    [22, 23, 24, 25, 26, 27, 28],
    [29, 30, 31, 1, 2, 3, 4],
]

We can display it as a table using this:

.. items-table:: cal.october_2018

which will be rendered like this:

  0 1 2 3 4 5 6
0 1 2 3 4 5 6 7
1 8 9 10 11 12 13 14
2 15 16 17 18 19 20 21
3 22 23 24 25 26 27 28
4 29 30 31 1 2 3 4

The zero-based indexes used as row and column headers are unnecessary, and can be disabled using the :v-level-visibility: and :h-level-visibility: options. Each of these accepts a comma-separated list of show or hide values:

.. items-table:: cal.october_2018
   :v-level-visibility: hide
   :h-level-visibility: hide

which now looks like this:

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
Adding a header row

If a suitable header row is not incorporated into the data structure, you can add it using :header: option, which accepts a comma-separated items. Each item can optionally be quoted, which can be useful if it needs to contain a comma.

.. items-table:: cal.october_2018
   :header: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
   :v-level-visibility: hide
   :h-level-visibility: hide

which renders like this:

Monday Tuesday Wednesday Thursday Friday Saturday Sunday
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4
Adding a title

A title can be added using the :title: option:

.. items-table:: cal.october_2018
   :title: October 2018
   :header: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
   :v-level-visibility: hide
   :h-level-visibility: hide

which renders like this:

October 2018
Monday Tuesday Wednesday Thursday Friday Saturday Sunday
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 1 2 3 4

Embedding Literals

Directive: literal-block – embed blocks of text

Added value includes facilities for rendering mutliline strings as blocks of text, with optional syntax highlighting.

The directive accepts two arguments:

.. literal-block:: module.data
   :language: yaml

Other options include the :linenos: flag to show line numbers:

.. literal-block:: module.data
   :language: json
   :linenos:

and highlighting of optional lines using :highlight-lines::

.. literal-block:: module.data
   :language: toml
   :emphasize-lines: 8, 10, 16

Basic Examples

JSON literal

Consider the following Python data structure representing some facts about a few Nordic countries, and the code to render it into a string as a JSON literal:

import json

countries = [
    dict(
        name="Denmark",
        code="DK",
        area_km2=42933,
        population_millions=5.85,
        currency="DKK",
    ),
    dict(
        name="Norway",
        code="NO",
        area_km2=385207,
        population_millions=5.39,
        currency="NOK",
    ),
    dict(
        name="Sweden",
        code="SE",
        area_km2=450295,
        population_millions=10.40,
        currency="SEK",
    )
]

json_countries = json.dumps(countries, indent=2)

This is how we would refer to that this JSON literal using a literal-block:: directive:

.. literal-block:: countries.json_countries
   :language: json

which will be rendered like this:

[
  {
    "name": "Denmark",
    "code": "DK",
    "area_km2": 42933,
    "population_millions": 5.85,
    "currency": "DKK"
  },
  {
    "name": "Norway",
    "code": "NO",
    "area_km2": 385207,
    "population_millions": 5.39,
    "currency": "NOK"
  },
  {
    "name": "Sweden",
    "code": "SE",
    "area_km2": 450295,
    "population_millions": 10.4,
    "currency": "SEK"
  }
]

Embedding Tables of Contents

Tables of contents directives are fundamental to the way Sphinx connects otherwise separate documents. The standard toctree directive permits hard-wired lists of linked documents with optional titles, but it’s not possible to easily generate a table of contents dynamically based on data from a program. It is particularly useful to be able to do so with plug-in architectures so that a program can report the location of each plugin’s documentation, allowing each plug-in to remain cohesive in the source code directory structure, rather than with documentation placed elsewhere.

The items-toc directive allows the list of references to be retrieved from a Python object, which must be provided as the only argument to the directive. The provided object can be an iterable series of strings, in which case each string is treated as a reference to another page where the title for each entry is extracted from the linked page. Alternatively it can be a mapping from page title strings to page references.

Building a table-of-contents from a list of references

So given this code in pages.py,

references = [
    "chemistry/H",
    "chemistry/He",
    "chemistry/Li",
    "chemistry/Be",
]

So given the directory structure and this file tocs.rst:

├── chemistry
│   ├── Be.rst
│   ├── H.rst
│   ├── He.rst
│   └── Li.rst
└── tocs.rst

the following items-toc directive

.. items-toc:: pages.references

gives the following table of contents,

Hydrogen

The lightest element.

Physical properties
Electron configuration

Helium

The lightest noble gas.

Physical properties
Electron configuration

Lithium

An important element in batteries

Physical properties
Electron configuration

Beryllium

A relatively rare element.

Physical properties
Electron configuration

All of the normal toctree options are supported. For example, to reverse the table of contents and limit its depth to one, use:

.. items-toc:: pages.references
   :maxdepth: 1
   :reversed:

to give,

See the Sphinx documentation for toctree for a full list of the supported options.

Building a table-of-contents from a mapping of titles to references

So given this code in pages.py,

titled_references = {
    "Element 1": "chemistry/H",
    "Element 2": "chemistry/He",
    "Element 3": "chemistry/Li",
    "Element 4": "chemistry/Be",
}

And given the same directory structure as before alogside this file tocs.rst:

├── chemistry
│   ├── Be.rst
│   ├── H.rst
│   ├── He.rst
│   └── Li.rst
└── tocs.rst

the following items-toc directive

.. items-toc:: pages.titled_references

gives the following table of contents,

Indices and tables