Skip to content

Commit bc2d2ed

Browse files
timhoffmQuLogic
andcommitted
DOC: Add file-based listed gallery order for examples
This adds support for a file "gallery_order.txt" in gallery folders for specifying the display order or examples. Advantages compared to the previous order approach: - Orders are now defined inside each gallery and not in a central list - The placeholder '*' allows to put some examples at the front, some at the end, and all others alphabetically sorted in the position of the placeholder - Checking of entries that do no exist as examples - Checking that all examples are listed (if no placeholder is specified) Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
1 parent 4946ac3 commit bc2d2ed

11 files changed

Lines changed: 134 additions & 74 deletions

File tree

doc/devel/document.rst

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1100,24 +1100,18 @@ reference should always be the second to mention; see the example above.
11001100
Order examples
11011101
--------------
11021102

1103-
The order of the sections of the :ref:`tutorials` and the :ref:`gallery`, as
1104-
well as the order of the examples within each section are determined in a
1105-
two step process from within the :file:`/doc/sphinxext/gallery_order.py`:
1106-
1107-
* *Explicit order*: This file contains a list of folders for the section order
1108-
and a list of examples for the subsection order. The order of the items
1109-
shown in the doc pages is the order those items appear in those lists.
1110-
* *Implicit order*: If a folder or example is not in those lists, it will be
1111-
appended after the explicitly ordered items and all of those additional
1112-
items will be ordered by pathname (for the sections) or by filename
1113-
(for the subsections).
1114-
1115-
As a consequence, if you want to let your example appear in a certain
1116-
position in the gallery, extend those lists with your example.
1117-
In case no explicit order is desired or necessary, still make sure
1118-
to name your example consistently, i.e. use the main function or subject
1119-
of the example as first word in the filename; e.g. an image example
1120-
should ideally be named similar to :file:`imshow_mynewexample.py`.
1103+
The order of the sections in :ref:`plot_types`, :ref:`tutorials` and :ref:`gallery`
1104+
are determined through a custom Sphinx Gallery plugin in :file:`/doc/sphinxext/gallery_order.py`
1105+
Configuration happens directly in that file.
1106+
1107+
The order of examples within each gallery section is determined from a file
1108+
:file:`gallery_order.txt` in each folder. If the file is missing, the examples
1109+
are sorted alphabetically by filename.
1110+
1111+
:file:`gallery_order.txt` contains a list of example filenames (without the .py extension)
1112+
in the desired order, with an optional '*' to indicate where not-listed examples should be
1113+
placed. If '*' is not present, all examples must be listed, or an error will be raised.
1114+
Use this if you want to ensure that a full order is intentionally maintained.
11211115

11221116
.. _raw_restructured_gallery:
11231117

doc/sphinxext/gallery_order.py

Lines changed: 75 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
"""
55

66
import itertools
7+
from pathlib import Path
8+
79
from sphinx_gallery.sorting import ExplicitOrder
810

911
# Gallery sections shall be displayed in the following order.
@@ -64,70 +66,87 @@ def __call__(self, item):
6466
else:
6567
return f"{self.ordered_list.index(UNSORTED):04d}{item}"
6668

67-
# Subsection order:
68-
# Subsections are ordered by filename, unless they appear in the following
69-
# lists in which case the list order determines the order within the section.
70-
# Examples/tutorials that do not appear in a list will be appended.
71-
72-
list_all = [
73-
# **Tutorials**
74-
# introductory
75-
"quick_start", "pyplot", "images", "lifecycle", "customizing",
76-
# intermediate
77-
"artists", "legend_guide", "color_cycle",
78-
"constrainedlayout_guide", "tight_layout_guide",
79-
# advanced
80-
# text
81-
"text_intro", "text_props",
82-
# colors
83-
"colors",
84-
85-
# **Examples**
86-
# animation
87-
"simple_anim", # Most basic example
88-
# color
89-
"color_demo",
90-
# pies
91-
"pie_features", "pie_demo2",
92-
# scales
93-
"scales", # Scales overview
94-
95-
# **Plot Types
96-
# Basic
97-
"plot", "scatter_plot", "bar", "stem", "step", "fill_between",
98-
# Arrays
99-
"imshow", "pcolormesh", "contour", "contourf",
100-
"barbs", "quiver", "streamplot",
101-
# Stats
102-
"hist_plot", "boxplot_plot", "errorbar_plot", "violin",
103-
"eventplot", "hist2d", "hexbin", "pie",
104-
# Unstructured
105-
"tricontour", "tricontourf", "tripcolor", "triplot",
106-
# Spines
107-
"spines", "spine_placement_demo", "spines_dropped",
108-
"multiple_yaxis_with_spines", "centered_spines_with_arrows",
109-
]
110-
explicit_subsection_order = [item + ".py" for item in list_all]
111-
112-
113-
class MplExplicitSubOrder(ExplicitOrder):
114-
"""For use within the 'within_subsection_order' key."""
69+
70+
class MplFileExplicitOrder(ExplicitOrder):
71+
"""
72+
An explicit order class that reads the order of examples from 'gallery_order.txt'.
73+
74+
For use with the sphinx_gallery 'within_subsection_order' key.
75+
76+
The file contains a list of example filenames (without the .py extension) in the
77+
desired order, with an optional '*' to indicate where not-listed examples should be
78+
placed.
79+
80+
If '*' is not present, all examples must be listed, or an error will be raised.
81+
Use this if you want to ensure that a full order is intentionally maintained.
82+
"""
11583
def __init__(self, src_dir):
116-
self.src_dir = src_dir # src_dir is unused here
117-
self.ordered_list = explicit_subsection_order
84+
ordered_list = self.read_gallery_order(Path(src_dir)) or []
85+
super().__init__(ordered_list)
86+
87+
@staticmethod
88+
def read_gallery_order(src_dir: Path):
89+
"""Return the list of examples to be sorted; read from 'gallery_order.txt'."""
90+
gallery_order_txt = src_dir / "gallery_order.txt"
91+
if not gallery_order_txt.exists():
92+
return None
93+
lines = [
94+
line.strip()
95+
for line in gallery_order_txt.read_text().splitlines()
96+
if line.strip() and not line.startswith("#")
97+
]
98+
99+
try:
100+
placeholder_index = lines.index("*")
101+
except ValueError:
102+
placeholder_index = None
103+
104+
lines = [line + ".py" for line in lines]
105+
106+
if placeholder_index is None:
107+
front = lines
108+
back = []
109+
else:
110+
front = lines[:placeholder_index]
111+
back = lines[placeholder_index+1:]
112+
113+
listed_examples = {*front, *back}
114+
existing_examples = {
115+
file.name for file in src_dir.iterdir() if file.suffix == ".py"
116+
}
117+
118+
non_existing_examples = listed_examples - existing_examples
119+
missing_examples = existing_examples - listed_examples
120+
print(f"non_existing_examples: {non_existing_examples}")
121+
print(f"missing_examples: {missing_examples}")
122+
123+
if non_existing_examples:
124+
raise ValueError(
125+
f"The following examples listed in {gallery_order_txt} do not exist: "
126+
f"{', '.join(non_existing_examples)}")
127+
if placeholder_index is None and missing_examples:
128+
raise ValueError(
129+
f"The following examples are not listed in {gallery_order_txt}. "
130+
f"Either include them or add a '*' to indicate where not listed "
131+
f"examples should be placed: "
132+
f"{', '.join(missing_examples)}"
133+
)
134+
135+
mid = list(sorted(missing_examples))
136+
return front + mid + back
118137

119138
def __call__(self, item):
120139
"""Return a string determining the sort order."""
121-
if item in self.ordered_list:
122-
return f"{self.ordered_list.index(item):04d}"
123-
else:
124-
# ensure not explicitly listed items come last.
125-
return "zzz" + item
140+
if not self.ordered_list:
141+
return item
142+
return f"{self.ordered_list.index(item):04d}"
126143

144+
def __repr__(self):
145+
return '<%s: %s>' % (self.__class__.__name__, self.ordered_list)
127146

128147
# Provide the above classes for use in conf.py
129148
sectionorder = MplExplicitOrder(explicit_order_folders)
130-
subsectionorder = MplExplicitSubOrder
149+
subsectionorder = MplFileExplicitOrder
131150

132151
_preserve_count = itertools.count()
133152

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
simple_anim
3+
*
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
color_demo
3+
*
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
pie_features
3+
*
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
scales
3+
*
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
spines
3+
spine_placement_demo
4+
spines_dropped
5+
multiple_yaxis_with_spines
6+
centered_spines_with_arrows
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
plot
3+
scatter_plot
4+
bar
5+
stem
6+
fill_between
7+
stackplot
8+
stairs
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
hist_plot
3+
boxplot_plot
4+
errorbar_plot
5+
violin
6+
eventplot
7+
hist2d
8+
hexbin
9+
pie
10+
ecdf
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Explicit example order. See https://matplotlib.org/devdocs/devel/document.html#order-examples
2+
tricontour
3+
tricontourf
4+
tripcolor
5+
triplot

0 commit comments

Comments
 (0)