mkdocstrings-matlab 0.9.7__py3-none-any.whl → 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mkdocstrings_handlers/matlab/__init__.py +26 -3
- mkdocstrings_handlers/matlab/config.py +885 -0
- mkdocstrings_handlers/matlab/handler.py +155 -296
- mkdocstrings_handlers/matlab/logger.py +111 -0
- mkdocstrings_handlers/matlab/rendering.py +818 -0
- mkdocstrings_handlers/matlab/templates/material/attributes.html.jinja +25 -0
- mkdocstrings_handlers/matlab/templates/material/backlinks.html.jinja +17 -0
- mkdocstrings_handlers/matlab/templates/material/children.html.jinja +70 -62
- mkdocstrings_handlers/matlab/templates/material/class.html.jinja +236 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/admonition.html.jinja +20 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/classes.html.jinja +85 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/examples.html.jinja +27 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/functions.html.jinja +91 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/input_arguments.html.jinja +171 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/name_value_arguments.html.jinja +166 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/namespaces.html.jinja +5 -6
- mkdocstrings_handlers/matlab/templates/material/docstring/output_arguments.html.jinja +152 -0
- mkdocstrings_handlers/matlab/templates/material/docstring/properties.html.jinja +25 -26
- mkdocstrings_handlers/matlab/templates/material/docstring.html.jinja +53 -0
- mkdocstrings_handlers/matlab/templates/material/expression.html.jinja +55 -0
- mkdocstrings_handlers/matlab/templates/material/folder.html.jinja +31 -39
- mkdocstrings_handlers/matlab/templates/material/function.html.jinja +148 -0
- mkdocstrings_handlers/matlab/templates/material/language.html.jinja +18 -0
- mkdocstrings_handlers/matlab/templates/material/languages/en.html.jinja +38 -0
- mkdocstrings_handlers/matlab/templates/material/languages/ja.html.jinja +38 -0
- mkdocstrings_handlers/matlab/templates/material/languages/zh.html.jinja +38 -0
- mkdocstrings_handlers/matlab/templates/material/namespace.html.jinja +32 -38
- mkdocstrings_handlers/matlab/templates/material/property.html.jinja +39 -35
- mkdocstrings_handlers/matlab/templates/material/script.html.jinja +3 -25
- mkdocstrings_handlers/matlab/templates/material/signature.html.jinja +105 -0
- mkdocstrings_handlers/matlab/templates/material/style.css +179 -4
- mkdocstrings_handlers/matlab/templates/material/summary/classes.html.jinja +25 -0
- mkdocstrings_handlers/matlab/templates/material/summary/functions.html.jinja +25 -0
- mkdocstrings_handlers/matlab/templates/material/summary/namespaces.html.jinja +17 -13
- mkdocstrings_handlers/matlab/templates/material/summary/properties.html.jinja +17 -13
- mkdocstrings_handlers/matlab/templates/material/summary.html.jinja +6 -6
- {mkdocstrings_matlab-0.9.7.dist-info → mkdocstrings_matlab-1.0.0.dist-info}/METADATA +17 -19
- mkdocstrings_matlab-1.0.0.dist-info/RECORD +41 -0
- mkdocstrings_handlers/matlab/collect.py +0 -783
- mkdocstrings_handlers/matlab/enums.py +0 -54
- mkdocstrings_handlers/matlab/models.py +0 -633
- mkdocstrings_handlers/matlab/treesitter.py +0 -707
- mkdocstrings_matlab-0.9.7.dist-info/RECORD +0 -22
- {mkdocstrings_matlab-0.9.7.dist-info → mkdocstrings_matlab-1.0.0.dist-info}/WHEEL +0 -0
- {mkdocstrings_matlab-0.9.7.dist-info → mkdocstrings_matlab-1.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,347 +1,189 @@
|
|
1
1
|
"""The mkdocstrings handler for processing MATLAB code documentation."""
|
2
2
|
|
3
|
-
import
|
4
|
-
|
3
|
+
from __future__ import annotations
|
4
|
+
|
5
|
+
from contextlib import suppress
|
6
|
+
from dataclasses import asdict
|
5
7
|
from pathlib import Path
|
6
|
-
from
|
7
|
-
from typing import Any, ClassVar, Mapping
|
8
|
+
from typing import TYPE_CHECKING, Any, ClassVar
|
8
9
|
|
9
|
-
from
|
10
|
-
from
|
10
|
+
from griffe import AliasResolutionError, Parser
|
11
|
+
from maxx.collection import LinesCollection, PathsCollection
|
11
12
|
from mkdocs.exceptions import PluginError
|
12
|
-
from mkdocstrings
|
13
|
+
from mkdocstrings import (
|
14
|
+
BaseHandler,
|
15
|
+
CollectionError,
|
16
|
+
CollectorItem,
|
17
|
+
HandlerOptions,
|
18
|
+
get_logger,
|
19
|
+
)
|
20
|
+
|
21
|
+
from mkdocstrings_handlers.matlab import rendering
|
22
|
+
from mkdocstrings_handlers.matlab.config import MatlabConfig, MatlabOptions
|
23
|
+
|
24
|
+
if TYPE_CHECKING:
|
25
|
+
from collections.abc import Mapping, MutableMapping
|
13
26
|
|
14
|
-
from
|
15
|
-
|
27
|
+
from mkdocs.config.defaults import MkDocsConfig
|
28
|
+
|
29
|
+
|
30
|
+
_logger = get_logger(__name__)
|
16
31
|
|
17
32
|
|
18
33
|
class MatlabHandler(BaseHandler):
|
19
34
|
"""The `MatlabHandler` class is a handler for processing Matlab code documentation."""
|
20
35
|
|
21
|
-
name: str = "matlab"
|
22
|
-
"""The handler
|
23
|
-
|
36
|
+
name: ClassVar[str] = "matlab"
|
37
|
+
"""The MATLAB handler class."""
|
38
|
+
|
39
|
+
domain: ClassVar[str] = "mat" # to match Sphinx's default domain
|
24
40
|
"""The cross-documentation domain/language for this handler."""
|
25
|
-
|
41
|
+
|
42
|
+
enable_inventory: ClassVar[bool] = True
|
26
43
|
"""Whether this handler is interested in enabling the creation of the `objects.inv` Sphinx inventory file."""
|
27
|
-
|
44
|
+
|
45
|
+
fallback_theme: ClassVar[str] = "material"
|
28
46
|
"""The fallback theme."""
|
29
|
-
fallback_config: ClassVar[dict] = {
|
30
|
-
"fallback": True,
|
31
|
-
}
|
32
|
-
"""The configuration used to collect item during autorefs fallback."""
|
33
|
-
default_config: ClassVar[dict] = {
|
34
|
-
# General options
|
35
|
-
"show_bases": True,
|
36
|
-
"show_inheritance_diagram": False,
|
37
|
-
"show_source": True,
|
38
|
-
# Heading options
|
39
|
-
"heading_level": 2,
|
40
|
-
"parameter_headings": False,
|
41
|
-
"show_root_heading": False,
|
42
|
-
"show_root_toc_entry": True,
|
43
|
-
"show_root_full_path": True,
|
44
|
-
"show_root_members_full_path": False,
|
45
|
-
"show_object_full_path": False,
|
46
|
-
"show_category_heading": False,
|
47
|
-
"show_symbol_type_heading": False,
|
48
|
-
"show_symbol_type_toc": False,
|
49
|
-
# Member options
|
50
|
-
"members": None,
|
51
|
-
"hidden_members": False,
|
52
|
-
"private_members": False,
|
53
|
-
"inherited_members": False,
|
54
|
-
"members_order": rendering.Order.alphabetical.value,
|
55
|
-
"filters": ["!^delete$|^disp$"],
|
56
|
-
"group_by_category": True,
|
57
|
-
"show_subnamespaces": False,
|
58
|
-
"summary": False,
|
59
|
-
"show_labels": True,
|
60
|
-
# Docstring options
|
61
|
-
"docstring_style": "google",
|
62
|
-
"docstring_options": {},
|
63
|
-
"docstring_section_style": "table",
|
64
|
-
"parse_arguments": False,
|
65
|
-
"merge_constructor_into_class": False,
|
66
|
-
"merge_constructor_ignore_summary": False,
|
67
|
-
"show_if_no_docstring": False,
|
68
|
-
"show_docstring_propeties": True,
|
69
|
-
"show_docstring_functions": True,
|
70
|
-
"show_docstring_classes": True,
|
71
|
-
"show_docstring_namespaces": True,
|
72
|
-
"show_docstring_description": True,
|
73
|
-
"show_docstring_examples": True,
|
74
|
-
"show_docstring_input_arguments": True,
|
75
|
-
"show_docstring_name_value_arguments": True,
|
76
|
-
"show_docstring_output_arguments": True,
|
77
|
-
# Signature options
|
78
|
-
"show_signature": True,
|
79
|
-
"show_signature_annotations": False,
|
80
|
-
"separate_signature": False,
|
81
|
-
"signature_crossrefs": False,
|
82
|
-
}
|
83
|
-
"""Default handler configuration.
|
84
|
-
|
85
|
-
Attributes: General options:
|
86
|
-
show_bases (bool): Show the base classes of a class. Default: `True`.
|
87
|
-
show_inheritance_diagram (bool): Show the inheritance diagram of a class using Mermaid. Default: `False`.
|
88
|
-
show_source (bool): Show the source code of this object. Default: `True`.
|
89
|
-
|
90
|
-
|
91
|
-
Attributes: Headings options:
|
92
|
-
heading_level (int): The initial heading level to use. Default: `2`.
|
93
|
-
parameter_headings (bool): Whether to render headings for parameters (therefore showing parameters in the ToC). Default: `False`.
|
94
|
-
show_root_heading (bool): Show the heading of the object at the root of the documentation tree
|
95
|
-
(i.e. the object referenced by the identifier after `:::`). Default: `False`.
|
96
|
-
show_root_toc_entry (bool): If the root heading is not shown, at least add a ToC entry for it. Default: `True`.
|
97
|
-
show_root_full_path (bool): Show the full path for the root object heading. Default: `True`.
|
98
|
-
show_root_members_full_path (bool): Show the full path of the root members. Default: `False`.
|
99
|
-
show_object_full_path (bool): Show the full path of every object. Default: `False`.
|
100
|
-
show_category_heading (bool): When grouped by categories, show a heading for each category. Default: `False`.
|
101
|
-
show_symbol_type_heading (bool): Show the symbol type in headings (e.g. mod, class, meth, func and attr). Default: `False`.
|
102
|
-
show_symbol_type_toc (bool): Show the symbol type in the Table of Contents (e.g. mod, class, methd, func and attr). Default: `False`.
|
103
|
-
|
104
|
-
Attributes: Members options:
|
105
|
-
members (list[str] | bool | None): A boolean, or an explicit list of members to render.
|
106
|
-
If true, select all members without further filtering.
|
107
|
-
If false or empty list, do not render members.
|
108
|
-
If none, select all members and apply further filtering with filters and docstrings. Default: `None`.
|
109
|
-
hidden_members (list[str] | bool | None): A boolean, or an explicit list of hidden members to render.
|
110
|
-
If true, select all inherited members, which can then be filtered with `members`.
|
111
|
-
If false or empty list, do not select any hidden member. Default: `False`.
|
112
|
-
private_members (list[str] | bool | None): A boolean, or an explicit list of private members to render.
|
113
|
-
If true, select all inherited members, which can then be filtered with `members`.
|
114
|
-
If false or empty list, do not select any private member. Default: `False`.
|
115
|
-
inherited_members (list[str] | bool | None): A boolean, or an explicit list of inherited members to render.
|
116
|
-
If true, select all inherited members, which can then be filtered with `members`.
|
117
|
-
If false or empty list, do not select any inherited member. Default: `False`.
|
118
|
-
members_order (str): The members ordering to use. Options: `alphabetical` - order by the members names,
|
119
|
-
`source` - order members as they appear in the source file. Default: `"alphabetical"`.
|
120
|
-
filters (list[str] | None): A list of filters applied to filter objects based on their name.
|
121
|
-
A filter starting with `!` will exclude matching objects instead of including them.
|
122
|
-
The `members` option takes precedence over `filters` (filters will still be applied recursively
|
123
|
-
to lower members in the hierarchy). Default: `["!^delete$|^disp$"]`.
|
124
|
-
group_by_category (bool): Group the object's children by categories: properties, classes, functions, and namespaces. Default: `True`.
|
125
|
-
show_subnamespaces (bool): When rendering a namespace, show its subnamespaces recursively. Default: `False`.
|
126
|
-
summary (bool | dict[str, bool]): Whether to render summaries of namespaces, classes, functions (methods) and properties. Default: `False`.
|
127
|
-
show_labels (bool): Whether to show labels of the members. Default: `True`.
|
128
|
-
|
129
|
-
Attributes: Docstrings options:
|
130
|
-
docstring_style (str): The docstring style to use: `google`, `numpy`, `sphinx`, or `None`. Default: `"google"`.
|
131
|
-
docstring_options (dict): The options for the docstring parser. See [docstring parsers](https://mkdocstrings.github.io/griffe/reference/docstrings/) and their options in Griffe docs.
|
132
|
-
docstring_section_style (str): The style used to render docstring sections. Options: `table`, `list`, `spacy`. Default: `"table"`.
|
133
|
-
parse_arguments (bool): Whether to load inputs and output parameters based on argument validation blocks. Default: `True`.
|
134
|
-
merge_constructor_into_class (bool): Whether to merge the constructor method into the class' signature and docstring. Default: `False`.
|
135
|
-
merge_constructor_ignore_summary (bool): Whether to ignore the constructor summary when merging it into the class. Default: `False`.
|
136
|
-
show_if_no_docstring (bool): Show the object heading even if it has no docstring or children with docstrings. Default: `False`.
|
137
|
-
show_docstring_properties (bool): Whether to display the "Properties" section in the object's docstring. Default: `True`.
|
138
|
-
show_docstring_functions (bool): Whether to display the "Functions" or "Methods" sections in the object's docstring. Default: `True`.
|
139
|
-
show_docstring_classes (bool): Whether to display the "Classes" section in the object's docstring. Default: `True`.
|
140
|
-
show_docstring_namespaces (bool): Whether to display the "Namespaces" section in the object's docstring. Default: `True`.
|
141
|
-
show_docstring_description (bool): Whether to display the textual block (including admonitions) in the object's docstring. Default: `True`.
|
142
|
-
show_docstring_examples (bool): Whether to display the "Examples" section in the object's docstring. Default: `True`.
|
143
|
-
show_docstring_input_arguments (bool): Whether to display the "Input arguments" section in the object's docstring. Default: `True`.
|
144
|
-
show_docstring_name_value_arguments (bool): Whether to display the "Name-value pairs" section in the object's docstring. Default: `True`.
|
145
|
-
show_docstring_output_arguments (bool): Whether to display the "Output arguments" section in the object's docstring. Default: `True`.
|
146
|
-
|
147
|
-
Attributes: Signatures/annotations options:
|
148
|
-
show_signature (bool): Show methods and functions signatures. Default: `True`.
|
149
|
-
show_signature_annotations (bool): Show the type annotations in methods and functions signatures. Default: `False`.
|
150
|
-
separate_signature (bool): Whether to put the whole signature in a code block below the heading.
|
151
|
-
signature_crossrefs (bool): Whether to render cross-references for type annotations in signatures. Default: `False`.
|
152
|
-
"""
|
153
47
|
|
154
48
|
def __init__(
|
155
49
|
self,
|
156
|
-
|
157
|
-
|
158
|
-
custom_templates: str | None = None,
|
159
|
-
config_file_path: str | None = None,
|
160
|
-
paths: list[str] | None = None,
|
161
|
-
paths_recursive: bool = False,
|
162
|
-
locale: str = "en",
|
50
|
+
config: MatlabConfig,
|
51
|
+
base_dir: Path,
|
163
52
|
**kwargs: Any,
|
164
53
|
) -> None:
|
165
54
|
"""
|
166
55
|
Initialize the handler with the given configuration.
|
167
56
|
|
168
57
|
Args:
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
config_file_path (str | None, optional): Path to the configuration file. Defaults to None.
|
173
|
-
paths (list[str] | None, optional): List of paths to include. Defaults to None.
|
174
|
-
paths_recursive (bool, optional): Whether to include paths recursively. Defaults to False.
|
175
|
-
locale (str, optional): Locale setting. Defaults to "en".
|
176
|
-
**kwargs (Any): Arbitrary keyword arguments.
|
58
|
+
config: The handler configuration.
|
59
|
+
base_dir: The base directory of the project.
|
60
|
+
**kwargs: Arguments passed to the parent constructor.
|
177
61
|
|
178
62
|
Returns:
|
179
63
|
None
|
180
64
|
"""
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
65
|
+
super().__init__(**kwargs)
|
66
|
+
|
67
|
+
self.config = config
|
68
|
+
self.base_dir = base_dir
|
69
|
+
self.global_options = config.options
|
70
|
+
|
71
|
+
# Warn if user overrides base templates.
|
72
|
+
if self.custom_templates:
|
73
|
+
for theme_dir in base_dir.joinpath(self.custom_templates, "matlab").iterdir():
|
74
|
+
if theme_dir.joinpath("_base").is_dir():
|
75
|
+
_logger.warning(
|
76
|
+
f"Overriding base template '{theme_dir.name}/_base/<template>.html.jinja' is not supported, "
|
77
|
+
f"override '{theme_dir.name}/<template>.html.jinja' instead",
|
78
|
+
)
|
79
|
+
|
80
|
+
if config.paths:
|
194
81
|
full_paths = []
|
82
|
+
for path in config.paths:
|
83
|
+
if "*" in path:
|
84
|
+
full_paths.extend([d for d in base_dir.glob(path) if d.is_dir()])
|
85
|
+
else:
|
86
|
+
full_paths.append((base_dir / path).resolve())
|
195
87
|
else:
|
196
|
-
|
197
|
-
full_paths = [(config_path / path).resolve() for path in paths]
|
88
|
+
full_paths = []
|
198
89
|
|
199
|
-
if
|
90
|
+
if path_ids := [str(path) for path in full_paths if not path.is_dir()]:
|
200
91
|
raise PluginError(
|
201
|
-
"The following paths do not exist or are not directories: "
|
202
|
-
+ ", ".join(pathIds)
|
92
|
+
"The following paths do not exist or are not directories: " + ", ".join(path_ids)
|
203
93
|
)
|
204
94
|
|
205
|
-
self.
|
206
|
-
|
95
|
+
self._paths = full_paths
|
96
|
+
self._paths_collection: PathsCollection = PathsCollection(
|
97
|
+
full_paths, recursive=config.paths_recursive, working_directory=base_dir
|
207
98
|
)
|
208
|
-
self.
|
209
|
-
|
99
|
+
self._lines_collection: LinesCollection = self._paths_collection.lines_collection
|
100
|
+
|
101
|
+
def get_options(self, local_options: Mapping[str, Any]) -> HandlerOptions:
|
102
|
+
"""Get combined default, global and local options.
|
103
|
+
|
104
|
+
Arguments:
|
105
|
+
local_options: The local options.
|
210
106
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
return super().get_templates_dir("python")
|
107
|
+
Returns:
|
108
|
+
The combined options.
|
109
|
+
"""
|
215
110
|
|
216
|
-
|
111
|
+
extra = {
|
112
|
+
**self.global_options.get("extra", {}),
|
113
|
+
**local_options.get("extra", {}),
|
114
|
+
}
|
115
|
+
options = {**self.global_options, **local_options, "extra": extra}
|
116
|
+
try:
|
117
|
+
return MatlabOptions.from_data(**options)
|
118
|
+
except Exception as error:
|
119
|
+
raise PluginError(f"Invalid options: {error}") from error
|
120
|
+
|
121
|
+
def render(self, data: CollectorItem, options: MatlabOptions) -> str:
|
217
122
|
"""Render a template using provided data and configuration options.
|
218
123
|
|
219
124
|
Arguments:
|
220
125
|
data: The collected data to render.
|
221
|
-
|
126
|
+
options: The handler's configuration options.
|
222
127
|
|
223
128
|
Returns:
|
224
129
|
The rendered template as HTML.
|
225
130
|
"""
|
226
|
-
final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
|
227
131
|
|
228
|
-
template_name = rendering.do_get_template(
|
132
|
+
template_name = rendering.do_get_template(data)
|
229
133
|
template = self.env.get_template(template_name)
|
230
134
|
|
231
|
-
heading_level =
|
232
|
-
|
233
|
-
try:
|
234
|
-
final_config["members_order"] = rendering.Order(
|
235
|
-
final_config["members_order"]
|
236
|
-
)
|
237
|
-
except ValueError as error:
|
238
|
-
choices = "', '".join(item.value for item in rendering.Order)
|
239
|
-
raise PluginError(
|
240
|
-
f"Unknown members_order '{final_config['members_order']}', choose between '{choices}'.",
|
241
|
-
) from error
|
242
|
-
|
243
|
-
if final_config["filters"]:
|
244
|
-
final_config["filters"] = [
|
245
|
-
(re.compile(filtr.lstrip("!")), filtr.startswith("!"))
|
246
|
-
for filtr in final_config["filters"]
|
247
|
-
]
|
248
|
-
|
249
|
-
summary = final_config["summary"]
|
250
|
-
if summary is True:
|
251
|
-
final_config["summary"] = {
|
252
|
-
"attributes": True,
|
253
|
-
"functions": True,
|
254
|
-
"classes": True,
|
255
|
-
"modules": True,
|
256
|
-
}
|
257
|
-
elif summary is False:
|
258
|
-
final_config["summary"] = {
|
259
|
-
"attributes": False,
|
260
|
-
"functions": False,
|
261
|
-
"classes": False,
|
262
|
-
"modules": False,
|
263
|
-
}
|
264
|
-
else:
|
265
|
-
final_config["summary"] = {
|
266
|
-
"attributes": summary.get(
|
267
|
-
"properties", False
|
268
|
-
), # Map properties (MATLAB) to attributes (Python)
|
269
|
-
"functions": summary.get("functions", False),
|
270
|
-
"classes": summary.get("classes", False),
|
271
|
-
"modules": summary.get(
|
272
|
-
"namespaces", False
|
273
|
-
), # Map namespaces (MATLAB) to modules (Python)
|
274
|
-
}
|
275
|
-
|
276
|
-
# Map docstring options
|
277
|
-
final_config["show_docstring_attributes"] = config.get(
|
278
|
-
"show_docstring_properties", True
|
279
|
-
)
|
280
|
-
final_config["show_docstring_modules"] = config.get(
|
281
|
-
"show_docstring_namespaces", True
|
282
|
-
)
|
283
|
-
final_config["show_docstring_parameters"] = config.get(
|
284
|
-
"show_docstring_input_arguments", True
|
285
|
-
)
|
286
|
-
final_config["show_docstring_other_parameters"] = config.get(
|
287
|
-
"show_docstring_name_value_arguments", True
|
288
|
-
)
|
289
|
-
final_config["show_docstring_returns"] = config.get(
|
290
|
-
"show_docstring_output_arguments", True
|
291
|
-
)
|
135
|
+
heading_level = options.heading_level
|
292
136
|
|
293
|
-
|
294
|
-
for setting in [
|
295
|
-
"merge_init_into_class",
|
296
|
-
"show_docstring_raises",
|
297
|
-
"show_docstring_receives",
|
298
|
-
"show_docstring_yields",
|
299
|
-
"show_docstring_warns",
|
300
|
-
]:
|
301
|
-
final_config[setting] = False
|
302
|
-
final_config["line_length"] = 88
|
303
|
-
|
304
|
-
return template.render(
|
137
|
+
html = template.render(
|
305
138
|
**{
|
306
|
-
"config":
|
139
|
+
"config": options,
|
307
140
|
data.kind.value: data,
|
308
141
|
"heading_level": heading_level,
|
309
142
|
"root": True,
|
310
|
-
"locale": self.
|
143
|
+
"locale": self.config.locale,
|
311
144
|
},
|
312
145
|
)
|
313
146
|
|
314
|
-
|
147
|
+
if self.env.filters["stash_crossref"].stash:
|
148
|
+
pass
|
149
|
+
|
150
|
+
return html
|
151
|
+
|
152
|
+
def update_env(self, config: Any) -> None: # noqa: ARG002
|
315
153
|
"""Update the Jinja environment with custom filters and tests.
|
316
154
|
|
317
155
|
Parameters:
|
318
|
-
|
319
|
-
config: The configuration dictionary.
|
156
|
+
config: The SSG configuration.
|
320
157
|
"""
|
321
|
-
super().update_env(md, config)
|
322
158
|
self.env.trim_blocks = True
|
323
159
|
self.env.lstrip_blocks = True
|
324
160
|
self.env.keep_trailing_newline = False
|
325
|
-
self.env.filters["split_path"] = rendering.do_split_path
|
326
|
-
self.env.filters["crossref"] = rendering.do_crossref
|
327
|
-
self.env.filters["multi_crossref"] = rendering.do_multi_crossref
|
328
161
|
self.env.filters["order_members"] = rendering.do_order_members
|
329
|
-
self.env.filters["format_code"] = rendering.do_format_code
|
330
162
|
self.env.filters["format_signature"] = rendering.do_format_signature
|
331
|
-
self.env.filters["
|
163
|
+
self.env.filters["format_property"] = rendering.do_format_property
|
164
|
+
self.env.filters["format_arguments"] = rendering.do_format_arguments
|
332
165
|
self.env.filters["filter_objects"] = rendering.do_filter_objects
|
333
166
|
self.env.filters["stash_crossref"] = rendering.do_stash_crossref
|
334
167
|
self.env.filters["get_template"] = rendering.do_get_template
|
335
|
-
self.env.filters["
|
168
|
+
self.env.filters["function_docstring"] = rendering.do_function_docstring
|
169
|
+
self.env.filters["as_properties_section"] = rendering.do_as_properties_section
|
336
170
|
self.env.filters["as_functions_section"] = rendering.do_as_functions_section
|
337
171
|
self.env.filters["as_classes_section"] = rendering.do_as_classes_section
|
338
|
-
self.env.filters["
|
172
|
+
self.env.filters["as_namespaces_section"] = rendering.do_as_namespaces_section
|
173
|
+
self.env.filters["as_inheritance_diagram_section"] = (
|
174
|
+
rendering.do_as_inheritance_diagram_section
|
175
|
+
)
|
339
176
|
self.env.globals["AutorefsHook"] = rendering.AutorefsHook
|
340
177
|
self.env.tests["existing_template"] = (
|
341
178
|
lambda template_name: template_name in self.env.list_templates()
|
342
179
|
)
|
180
|
+
# The following is required since in MATLAB there is a concept called namespace
|
181
|
+
# This is used as a variable in Jinja templates and would overwrite the namespace macro
|
182
|
+
# Thus we create an alias for this.
|
183
|
+
self.env.globals["jinja_namespace"] = self.env.globals["namespace"]
|
184
|
+
self.env.globals["paths_collection"] = self._paths_collection
|
343
185
|
|
344
|
-
def collect(self, identifier: str,
|
186
|
+
def collect(self, identifier: str, options: MatlabOptions) -> CollectorItem:
|
345
187
|
"""Collect data given an identifier and user configuration.
|
346
188
|
|
347
189
|
In the implementation, you typically call a subprocess that returns JSON, and load that JSON again into
|
@@ -349,7 +191,7 @@ class MatlabHandler(BaseHandler):
|
|
349
191
|
|
350
192
|
Arguments:
|
351
193
|
identifier: An identifier for which to collect data.
|
352
|
-
|
194
|
+
options: The handler's configuration options.
|
353
195
|
|
354
196
|
Returns:
|
355
197
|
CollectorItem
|
@@ -357,51 +199,68 @@ class MatlabHandler(BaseHandler):
|
|
357
199
|
if identifier == "":
|
358
200
|
raise CollectionError("Empty identifier")
|
359
201
|
|
360
|
-
|
202
|
+
if options == {}:
|
203
|
+
options = self.get_options({})
|
204
|
+
|
361
205
|
try:
|
362
|
-
|
206
|
+
if "/" in identifier:
|
207
|
+
# If the identifier contains a slash, it is a path to a file.
|
208
|
+
# We use the lines collection to get the model.
|
209
|
+
path = (self.base_dir / identifier).resolve()
|
210
|
+
if path in self._paths_collection._folders:
|
211
|
+
# If the path is a folder, we return the folder model.
|
212
|
+
model = self._paths_collection._folders[path]
|
213
|
+
else:
|
214
|
+
raise CollectionError(
|
215
|
+
f"Path '{identifier}' is not a valid path in the collection"
|
216
|
+
)
|
217
|
+
else:
|
218
|
+
model = self._paths_collection.get_member(identifier)
|
363
219
|
except SyntaxError as ex:
|
364
220
|
msg = str(ex)
|
365
221
|
if ex.text:
|
366
|
-
msg += ":\n" + ex.text
|
222
|
+
msg += ":\n" + str(ex.text)
|
367
223
|
raise CollectionError(msg) from ex
|
368
|
-
except
|
224
|
+
except KeyError as ex:
|
225
|
+
raise CollectionError(str(ex)) from ex
|
226
|
+
except AliasResolutionError as ex:
|
369
227
|
raise CollectionError(str(ex)) from ex
|
228
|
+
|
370
229
|
if model is None:
|
371
230
|
raise CollectionError(f"Identifier '{identifier}' not found")
|
231
|
+
|
232
|
+
parser_name = options.docstring_style
|
233
|
+
parser = parser_name and Parser(parser_name)
|
234
|
+
parser_options = options.docstring_options and asdict(
|
235
|
+
options.docstring_options # ty: ignore[invalid-argument-type]
|
236
|
+
)
|
237
|
+
|
238
|
+
with suppress(AliasResolutionError):
|
239
|
+
if model.docstring is not None:
|
240
|
+
model.docstring.parser = parser
|
241
|
+
model.docstring.parser_options = parser_options or {}
|
242
|
+
|
372
243
|
return model
|
373
244
|
|
374
245
|
|
375
246
|
def get_handler(
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
config_file_path: str | None = None,
|
380
|
-
**config: Any,
|
247
|
+
handler_config: MutableMapping[str, Any],
|
248
|
+
tool_config: MkDocsConfig,
|
249
|
+
**kwargs: Any,
|
381
250
|
) -> MatlabHandler:
|
382
251
|
"""
|
383
252
|
Create and return a MatlabHandler object with the specified configuration.
|
384
253
|
|
385
254
|
Parameters:
|
386
|
-
|
387
|
-
|
388
|
-
config_file_path (str | None, optional): Path to the configuration file. Defaults to None.
|
389
|
-
paths (list[str] | None, optional): List of paths to include. Defaults to None.
|
390
|
-
paths_recursive (bool, optional): Whether to include paths recursively. Defaults to False.
|
391
|
-
**config (Any): Additional configuration options.
|
255
|
+
handler_config: The handler configuration.
|
256
|
+
tool_config: The tool (SSG) configuration.
|
392
257
|
|
393
258
|
Returns:
|
394
259
|
MatlabHandler: An instance of MatlabHandler configured with the provided parameters.
|
395
260
|
"""
|
261
|
+
base_dir = Path(tool_config.config_file_path or "./mkdocs.yml").parent
|
396
262
|
return MatlabHandler(
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
config_file_path=config_file_path,
|
401
|
-
**config['handler_config']
|
263
|
+
config=MatlabConfig.from_data(**handler_config),
|
264
|
+
base_dir=base_dir,
|
265
|
+
**kwargs,
|
402
266
|
)
|
403
|
-
|
404
|
-
|
405
|
-
if __name__ == "__main__":
|
406
|
-
handler = get_handler(theme="material")
|
407
|
-
pprint(handler.collect("matlab_startup", {}).docstring.parse("google"))
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# This module contains the logger used throughout Griffe.
|
2
|
+
# The logger is actually a wrapper around the standard Python logger.
|
3
|
+
# We wrap it so that it is easier for other downstream libraries to patch it.
|
4
|
+
# For example, mkdocstrings-python patches the logger to relocate it as a child
|
5
|
+
# of `mkdocs.plugins` so that it fits in the MkDocs logging configuration.
|
6
|
+
#
|
7
|
+
# We use a single, global logger because our public API is exposed in a single module, `griffe`.
|
8
|
+
# Extensions however should use their own logger, which is why we provide the `get_logger` function.
|
9
|
+
|
10
|
+
from __future__ import annotations
|
11
|
+
|
12
|
+
import logging
|
13
|
+
from contextlib import contextmanager
|
14
|
+
from typing import TYPE_CHECKING, Any, Callable, ClassVar
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from collections.abc import Iterator
|
18
|
+
|
19
|
+
|
20
|
+
class Logger:
|
21
|
+
_default_logger: Any = logging.getLogger
|
22
|
+
_instances: ClassVar[dict[str, Logger]] = {}
|
23
|
+
|
24
|
+
def __init__(self, name: str) -> None:
|
25
|
+
# Default logger that can be patched by third-party.
|
26
|
+
self._logger = self.__class__._default_logger(name)
|
27
|
+
|
28
|
+
def __getattr__(self, name: str) -> Any:
|
29
|
+
# Forward everything to the logger.
|
30
|
+
return getattr(self._logger, name)
|
31
|
+
|
32
|
+
@contextmanager
|
33
|
+
def disable(self) -> Iterator[None]:
|
34
|
+
"""Temporarily disable logging."""
|
35
|
+
old_level = self._logger.level
|
36
|
+
self._logger.setLevel(100)
|
37
|
+
try:
|
38
|
+
yield
|
39
|
+
finally:
|
40
|
+
self._logger.setLevel(old_level)
|
41
|
+
|
42
|
+
@classmethod
|
43
|
+
def _get(cls, name: str = "griffe") -> Logger:
|
44
|
+
if name not in cls._instances:
|
45
|
+
cls._instances[name] = cls(name)
|
46
|
+
return cls._instances[name]
|
47
|
+
|
48
|
+
@classmethod
|
49
|
+
def _patch_loggers(cls, get_logger_func: Callable) -> None:
|
50
|
+
# Patch current instances.
|
51
|
+
for name, instance in cls._instances.items():
|
52
|
+
instance._logger = get_logger_func(name)
|
53
|
+
|
54
|
+
# Future instances will be patched as well.
|
55
|
+
cls._default_logger = get_logger_func
|
56
|
+
|
57
|
+
|
58
|
+
logger: Logger = Logger._get()
|
59
|
+
"""Our global logger, used throughout the library.
|
60
|
+
|
61
|
+
Griffe's output and error messages are logging messages.
|
62
|
+
|
63
|
+
Griffe provides the [`patch_loggers`][griffe.patch_loggers]
|
64
|
+
function so dependent libraries can patch Griffe loggers as they see fit.
|
65
|
+
|
66
|
+
For example, to fit in the MkDocs logging configuration
|
67
|
+
and prefix each log message with the module name:
|
68
|
+
|
69
|
+
```python
|
70
|
+
import logging
|
71
|
+
from griffe import patch_loggers
|
72
|
+
|
73
|
+
|
74
|
+
class LoggerAdapter(logging.LoggerAdapter):
|
75
|
+
def __init__(self, prefix, logger):
|
76
|
+
super().__init__(logger, {})
|
77
|
+
self.prefix = prefix
|
78
|
+
|
79
|
+
def process(self, msg, kwargs):
|
80
|
+
return f"{self.prefix}: {msg}", kwargs
|
81
|
+
|
82
|
+
|
83
|
+
def get_logger(name):
|
84
|
+
logger = logging.getLogger(f"mkdocs.plugins.{name}")
|
85
|
+
return LoggerAdapter(name, logger)
|
86
|
+
|
87
|
+
|
88
|
+
patch_loggers(get_logger)
|
89
|
+
```
|
90
|
+
"""
|
91
|
+
|
92
|
+
|
93
|
+
def get_logger(name: str = "griffe") -> Logger:
|
94
|
+
"""Create and return a new logger instance.
|
95
|
+
|
96
|
+
Parameters:
|
97
|
+
name: The logger name.
|
98
|
+
|
99
|
+
Returns:
|
100
|
+
The logger.
|
101
|
+
"""
|
102
|
+
return Logger._get(name)
|
103
|
+
|
104
|
+
|
105
|
+
def patch_loggers(get_logger_func: Callable[[str], Any]) -> None:
|
106
|
+
"""Patch Griffe logger and Griffe extensions' loggers.
|
107
|
+
|
108
|
+
Parameters:
|
109
|
+
get_logger_func: A function accepting a name as parameter and returning a logger.
|
110
|
+
"""
|
111
|
+
Logger._patch_loggers(get_logger_func)
|