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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
|
r"""Sorters for Sphinx-Gallery (sub)sections.
Sorting key functions for gallery subsection folders and section files.
"""
# Created: Sun May 21 20:38:59 2017
# Author: Óscar Nájera
# License: 3-clause BSD
import os
import types
from sphinx.errors import ConfigError
from .gen_rst import extract_intro_and_title
from .py_source_parser import split_code_and_text_blocks
class ExplicitOrder:
"""Sorting key for all gallery subsections.
All subsections folders must be listed, otherwise an exception is raised.
However, you can add '*' as a placeholder to the list. All not-listed
subsection folders will be inserted at the given position and no
exception is raised.
Parameters
----------
ordered_list : list, tuple, or :term:`python:generator`
Hold the paths of each galleries' subsections.
Raises
------
ValueError
Wrong input type or Subgallery path missing.
"""
def __init__(self, ordered_list):
if not isinstance(ordered_list, (list, tuple, types.GeneratorType)):
raise ConfigError(
"ExplicitOrder sorting key takes a list, "
"tuple or Generator, which hold"
"the paths of each gallery subfolder"
)
self.ordered_list = [
"*" if path == "*" else os.path.normpath(path) for path in ordered_list
]
try:
i = ordered_list.index("*")
self.has_wildcard = True
self.ordered_list_start = self.ordered_list[:i]
self.ordered_list_end = self.ordered_list[i + 1 :]
except ValueError: # from index("*")
self.has_wildcard = False
self.ordered_list_start = []
self.ordered_list_end = self.ordered_list
def __call__(self, item):
"""
Return an integer suited for ordering the items.
If the ordered_list contains a wildcard "*", items before "*" will return
negative numbers, items after "*" will have positive numbers, and
not-listed items will return 0.
If there is no wildcard, all items with return positive numbers, and
not-listed items will raise a ConfigError.
"""
if item in self.ordered_list_start:
return self.ordered_list_start.index(item) - len(self.ordered_list_start)
elif item in self.ordered_list_end:
return self.ordered_list_end.index(item) + 1
else:
if self.has_wildcard:
return 0
else:
raise ConfigError(
"The subsection folder {!r} was not found in the "
"'subsection_order' config. If you use an explicit "
"'subsection_order', you must specify all subsection folders "
"or add '*' as a wildcard to collect all not-listed subsection "
"folders.".format(item)
)
def __repr__(self):
return f"<{self.__class__.__name__} : {self.ordered_list}>"
class _SortKey:
"""Base class for section order key classes."""
def __init__(self, src_dir):
self.src_dir = src_dir
def __repr__(self):
return f"<{self.__class__.__name__}>"
class NumberOfCodeLinesSortKey(_SortKey):
"""Sort examples in src_dir by the number of code lines.
Parameters
----------
src_dir : str
The source directory.
"""
def __call__(self, filename):
"""Return number of code lines in `filename`."""
src_file = os.path.normpath(os.path.join(self.src_dir, filename))
file_conf, script_blocks = split_code_and_text_blocks(src_file)
amount_of_code = sum(
len(block.content) for block in script_blocks if block.type == "code"
)
return amount_of_code
class FileSizeSortKey(_SortKey):
"""Sort examples in src_dir by file size.
Parameters
----------
src_dir : str
The source directory.
"""
def __call__(self, filename):
"""Return file size."""
src_file = os.path.normpath(os.path.join(self.src_dir, filename))
return int(os.stat(src_file).st_size)
class FileNameSortKey(_SortKey):
"""Sort examples in src_dir by file name.
Parameters
----------
src_dir : str
The source directory.
"""
def __call__(self, filename):
"""Return `filename`."""
return filename
class ExampleTitleSortKey(_SortKey):
"""Sort examples in src_dir by example title.
Parameters
----------
src_dir : str
The source directory.
"""
def __call__(self, filename):
"""Return title of example."""
src_file = os.path.normpath(os.path.join(self.src_dir, filename))
_, script_blocks = split_code_and_text_blocks(src_file)
_, title = extract_intro_and_title(src_file, script_blocks[0].content)
return title
class FunctionSortKey:
"""Sort examples using a function passed through to :py:func:`sorted`.
Parameters
----------
func : :external+python:term:`callable`
sorting key function,
can only take one argument, i.e. lambda func = arg: arg[0] * arg[1]
r : str, None
printable representation of object
"""
def __init__(self, func, r=None):
self.f = func
self.r = r
def __repr__(self):
return self.r if self.r else "FunctionSortKey"
def __call__(self, arg):
"""Return func(arg)."""
return self.f(arg)
|