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:
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
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
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
GDP %
- latest:-
3.0
- quarter:-
3.5
- 2018:-
2.9
Consumer prices %
- latest:-
2.3
- 2018:-
2.5
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
Statistic: GDP %
Period: latest
3.0
Period: quarter
3.5
Period: 2018
2.9
Statistic: Consumer prices %
Period: latest
2.3
Period: 2018
2.5
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
Statistic: GDP %
Period: latest
3.0%
Period: quarter
3.5%
Period: 2018
2.9%
Statistic: Consumer prices %
Period: latest
2.3%
Period: 2018
2.5%
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
Consumer prices %
latest – 2.3%
2018 – 2.5%
GDP %
latest – 3.0%
quarter – 3.5%
2018 – 2.9%
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}
- value=platinum, ordinal=1, key=0
- value=silver, ordinal=2, key=1
- 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
- value=gold, ordinal=1, key=2
- value=platinum, ordinal=2, key=0
- 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
- value=gold, ordinal=0, key=2
- value=platinum, ordinal=1, key=0
- 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:
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,
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,