|
4 | 4 | """ |
5 | 5 |
|
6 | 6 | import itertools |
| 7 | +from pathlib import Path |
| 8 | + |
7 | 9 | from sphinx_gallery.sorting import ExplicitOrder |
8 | 10 |
|
9 | 11 | # Gallery sections shall be displayed in the following order. |
|
23 | 25 | '../galleries/examples/style_sheets', |
24 | 26 | '../galleries/examples/pyplots', |
25 | 27 | '../galleries/examples/axes_grid1', |
26 | | - '../galleries/examples/axisartist', |
| 28 | + '../galleries/examples/axisartst', |
27 | 29 | '../galleries/examples/showcase', |
28 | 30 | UNSORTED, |
29 | 31 | '../galleries/examples/userdemo', |
@@ -72,62 +74,104 @@ def __call__(self, item): |
72 | 74 | list_all = [ |
73 | 75 | # **Tutorials** |
74 | 76 | # introductory |
75 | | - "quick_start", "pyplot", "images", "lifecycle", "customizing", |
| 77 | + "quick_start", "customizing", |
76 | 78 | # intermediate |
77 | | - "artists", "legend_guide", "color_cycle", |
| 79 | + "legend_guide", "color_cycle", |
78 | 80 | "constrainedlayout_guide", "tight_layout_guide", |
79 | 81 | # advanced |
80 | 82 | # text |
81 | 83 | "text_intro", "text_props", |
82 | 84 | # 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 | | - ] |
| 85 | + "colors", ] |
110 | 86 | explicit_subsection_order = [item + ".py" for item in list_all] |
111 | 87 |
|
112 | 88 |
|
113 | | -class MplExplicitSubOrder(ExplicitOrder): |
114 | | - """For use within the 'within_subsection_order' key.""" |
| 89 | +class MplFileExplicitOrder(ExplicitOrder): |
| 90 | + """ |
| 91 | + An explicit order class that reads the order of examples from 'gallery_order.txt'. |
| 92 | +
|
| 93 | + For use with the sphinx_gallery 'within_subsection_order' key. |
| 94 | +
|
| 95 | + The file contains a list of example filenames (without the .py extension) in the |
| 96 | + desired order, with an optional '*' to indicate where unsorted examples should be |
| 97 | + placed. |
| 98 | +
|
| 99 | + If '*' is not present, all examples must be listed, or an error will be raised. |
| 100 | + Use this if you want to ensure that a full order is intentionally maintained. |
| 101 | + """ |
115 | 102 | def __init__(self, src_dir): |
116 | | - self.src_dir = src_dir # src_dir is unused here |
117 | | - self.ordered_list = explicit_subsection_order |
| 103 | + ordered_list = self.read_gallery_order(Path(src_dir)) or [] |
| 104 | + super().__init__(ordered_list) |
| 105 | + |
| 106 | + @staticmethod |
| 107 | + def read_gallery_order(src_dir: Path): |
| 108 | + """Return the list of examples to be sorted; read from 'gallery_order.txt'.""" |
| 109 | + gallery_order_txt = src_dir / "gallery_order.txt" |
| 110 | + if not gallery_order_txt.exists(): |
| 111 | + return None |
| 112 | + lines = [ |
| 113 | + line.strip() |
| 114 | + for line in gallery_order_txt.read_text().splitlines() |
| 115 | + if line.strip() and not line.startswith("#") |
| 116 | + ] |
| 117 | + |
| 118 | + try: |
| 119 | + placeholder_index = lines.index("*") |
| 120 | + except ValueError: |
| 121 | + placeholder_index = None |
| 122 | + |
| 123 | + lines = [line + ".py" for line in lines] |
| 124 | + |
| 125 | + if placeholder_index is None: |
| 126 | + front = lines |
| 127 | + back = [] |
| 128 | + else: |
| 129 | + front = lines[:placeholder_index] |
| 130 | + back = lines[placeholder_index+1:] |
| 131 | + |
| 132 | + listed_examples = set(front + back) |
| 133 | + existing_examples = set( |
| 134 | + str(file.name) for file in src_dir.iterdir() if file.suffix == ".py" |
| 135 | + ) |
| 136 | + |
| 137 | + non_exiting_examples = listed_examples - existing_examples |
| 138 | + missing_examples = existing_examples - listed_examples |
| 139 | + print(f"non_exiting_examples: {non_exiting_examples}") |
| 140 | + print(f"missing_examples: {missing_examples}") |
| 141 | + |
| 142 | + if non_exiting_examples: |
| 143 | + raise ValueError( |
| 144 | + f"The following examples listed in {gallery_order_txt} do not exist: " |
| 145 | + f"{', '.join(non_exiting_examples)}" |
| 146 | + ) |
| 147 | + if placeholder_index is None and missing_examples: |
| 148 | + raise ValueError( |
| 149 | + f"The following examples are not listed in {gallery_order_txt}. " |
| 150 | + f"Either include them or add a '*' to indicate where not listed" |
| 151 | + f"examples should be placed: " |
| 152 | + f"{', '.join(missing_examples)}" |
| 153 | + ) |
| 154 | + |
| 155 | + mid = list( |
| 156 | + sorted( |
| 157 | + str(file.name) for file in src_dir.iterdir() |
| 158 | + if file.suffix == ".py" and str(file.name) not in listed_examples |
| 159 | + ) |
| 160 | + ) |
| 161 | + return front + mid + back |
118 | 162 |
|
119 | 163 | def __call__(self, item): |
120 | 164 | """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 |
| 165 | + if not self.ordered_list: |
| 166 | + return item |
| 167 | + return f"{self.ordered_list.index(item):04d}" |
126 | 168 |
|
| 169 | + def __repr__(self): |
| 170 | + return '<%s: %s>' % (self.__class__.__name__, self.ordered_list) |
127 | 171 |
|
128 | 172 | # Provide the above classes for use in conf.py |
129 | 173 | sectionorder = MplExplicitOrder(explicit_order_folders) |
130 | | -subsectionorder = MplExplicitSubOrder |
| 174 | +subsectionorder = MplFileExplicitOrder |
131 | 175 |
|
132 | 176 | _preserve_count = itertools.count() |
133 | 177 |
|
|
0 commit comments