Coverage for src/mkdocs_gallery/sorting.py: 57%
58 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-30 08:26 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-30 08:26 +0000
1# Authors: Sylvain MARIE <sylvain.marie@se.com>
2# + All contributors to <https://github.com/smarie/mkdocs-gallery>
3#
4# Original idea and code: sphinx-gallery, <https://sphinx-gallery.github.io>
5# License: 3-clause BSD, <https://github.com/smarie/mkdocs-gallery/blob/master/LICENSE>
6"""
7Sorters for mkdocs-gallery (sub)sections
8========================================
10Sorting key functions for gallery subsection folders and section files.
11"""
13from __future__ import absolute_import, division, print_function
15import os
16import types
17from enum import Enum
18from pathlib import Path
19from typing import Iterable, Type
21from .errors import ConfigError
22from .gen_single import extract_intro_and_title
23from .py_source_parser import split_code_and_text_blocks
26class _SortKey(object):
27 """Base class for section order key classes."""
29 def __repr__(self):
30 return "<%s>" % (self.__class__.__name__,)
33class ExplicitOrder(_SortKey):
34 """Sorting key for all gallery subsections.
36 This requires all folders to be listed otherwise an exception is raised.
38 Parameters
39 ----------
40 ordered_list : list, tuple, or :term:`python:generator`
41 Hold the paths of each galleries' subsections.
43 Raises
44 ------
45 ValueError
46 Wrong input type or Subgallery path missing.
47 """
49 def __init__(self, ordered_list: Iterable[str]):
50 if not isinstance(ordered_list, (list, tuple, types.GeneratorType)):
51 raise ConfigError(
52 "ExplicitOrder sorting key takes a list, "
53 "tuple or Generator, which hold"
54 "the paths of each gallery subfolder"
55 )
57 self.ordered_list = list(os.path.normpath(path) for path in ordered_list)
59 def __call__(self, item: Path):
60 if item.name in self.ordered_list:
61 return self.ordered_list.index(item.name)
62 else:
63 raise ConfigError(
64 "If you use an explicit folder ordering, you "
65 "must specify all folders. Explicit order not "
66 "found for {}".format(item.name)
67 )
69 def __repr__(self):
70 return "<%s : %s>" % (self.__class__.__name__, self.ordered_list)
73class NumberOfCodeLinesSortKey(_SortKey):
74 """Sort examples by the number of code lines."""
76 def __call__(self, file: Path):
77 file_conf, script_blocks = split_code_and_text_blocks(file)
78 amount_of_code = sum([len(bcontent) for blabel, bcontent, lineno in script_blocks if blabel == "code"])
79 return amount_of_code
82class FileSizeSortKey(_SortKey):
83 """Sort examples by file size."""
85 def __call__(self, file: Path):
86 # src_file = os.path.normpath(str(file))
87 # return int(os.stat(src_file).st_size)
88 return file.stat().st_size
91class FileNameSortKey(_SortKey):
92 """Sort examples by file name."""
94 def __call__(self, file: Path):
95 return file.name
98class ExampleTitleSortKey(_SortKey):
99 """Sort examples by example title."""
101 def __call__(self, file: Path):
102 _, script_blocks = split_code_and_text_blocks(file)
103 _, title = extract_intro_and_title(file, script_blocks[0][1])
104 return title
107class SortingMethod(Enum):
108 """
109 All known sorting methods.
110 """
112 ExplicitOrder = ExplicitOrder
113 NumberOfCodeLinesSortKey = NumberOfCodeLinesSortKey
114 FileSizeSortKey = FileSizeSortKey
115 FileNameSortKey = FileNameSortKey
116 ExampleTitleSortKey = ExampleTitleSortKey
118 def __call__(self, *args, **kwargs):
119 """When enum member is called, return the class"""
120 return self.value(*args, **kwargs)
122 @classmethod
123 def all_names(cls):
124 return [s.name for s in cls]
126 @classmethod
127 def from_str(cls, name) -> "SortingMethod":
128 try:
129 return cls[name]
130 except KeyError:
131 raise ValueError(f"Unknown sorting method {name!r}. Available methods: {cls.all_names()}")
134def str_to_sorting_method(name: str) -> Type:
135 """Return the sorting method class associated with the fiven name."""
136 return SortingMethod.from_str(name).value