Source code for sphinx_gallery.sorting
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
[docs]
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__}>"
[docs]
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
[docs]
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)
[docs]
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
[docs]
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
[docs]
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)