mkdocstrings-matlab 0.6.0__py3-none-any.whl → 0.8.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.
Files changed (22) hide show
  1. mkdocstrings_handlers/matlab/collect.py +84 -32
  2. mkdocstrings_handlers/matlab/handler.py +31 -10
  3. mkdocstrings_handlers/matlab/models.py +60 -28
  4. mkdocstrings_handlers/matlab/templates/material/children.html.jinja +172 -0
  5. mkdocstrings_handlers/matlab/templates/material/docstring/namespaces.html.jinja +86 -0
  6. mkdocstrings_handlers/matlab/templates/material/docstring/properties.html.jinja +109 -0
  7. mkdocstrings_handlers/matlab/templates/material/folder.html.jinja +121 -0
  8. mkdocstrings_handlers/matlab/templates/material/namespace.html.jinja +121 -0
  9. mkdocstrings_handlers/matlab/templates/material/property.html.jinja +120 -0
  10. mkdocstrings_handlers/matlab/templates/material/style.css +26 -0
  11. mkdocstrings_handlers/matlab/templates/material/summary/namespaces.html.jinja +21 -0
  12. mkdocstrings_handlers/matlab/templates/material/summary/properties.html.jinja +21 -0
  13. mkdocstrings_handlers/matlab/templates/material/summary.html.jinja +26 -0
  14. {mkdocstrings_matlab-0.6.0.dist-info → mkdocstrings_matlab-0.8.0.dist-info}/METADATA +9 -9
  15. mkdocstrings_matlab-0.8.0.dist-info/RECORD +21 -0
  16. mkdocs_material_matlab/__init__.py +0 -4
  17. mkdocs_material_matlab/css/style.css +0 -7
  18. mkdocs_material_matlab/mkdocs_material_matlab.py +0 -20
  19. mkdocstrings_matlab-0.6.0.dist-info/RECORD +0 -15
  20. mkdocstrings_matlab-0.6.0.dist-info/entry_points.txt +0 -2
  21. {mkdocstrings_matlab-0.6.0.dist-info → mkdocstrings_matlab-0.8.0.dist-info}/WHEEL +0 -0
  22. {mkdocstrings_matlab-0.6.0.dist-info → mkdocstrings_matlab-0.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,7 +3,7 @@
3
3
  from collections import defaultdict, deque
4
4
  from copy import copy, deepcopy
5
5
  from pathlib import Path
6
- from typing import Mapping, Sequence
6
+ from typing import Mapping, Sequence, Callable, TypeVar
7
7
 
8
8
  from _griffe.collections import LinesCollection as GLC, ModulesCollection
9
9
  from _griffe.docstrings.models import (
@@ -24,14 +24,16 @@ from mkdocstrings_handlers.matlab.models import (
24
24
  Docstring,
25
25
  DocstringSectionText,
26
26
  Function,
27
+ Folder,
27
28
  MatlabMixin,
28
- Object,
29
29
  Namespace,
30
- ROOT,
30
+ PathMixin,
31
31
  )
32
32
  from mkdocstrings_handlers.matlab.treesitter import FileParser
33
33
 
34
34
 
35
+ PathType = TypeVar("PathType", bound=PathMixin)
36
+
35
37
  __all__ = ["LinesCollection", "PathCollection"]
36
38
 
37
39
 
@@ -104,6 +106,7 @@ class PathCollection(ModulesCollection):
104
106
  matlab_path (Sequence[str | Path]): A list of strings or Path objects representing the MATLAB paths.
105
107
  recursive (bool, optional): If True, recursively adds all subdirectories of the given paths to the search path. Defaults to False.
106
108
  config (Mapping, optional): Configuration settings for the PathCollection. Defaults to {}.
109
+ config_path (Path | None, optional): The path to the configuration file. Defaults to None.
107
110
 
108
111
  Methods:
109
112
  members() -> dict:
@@ -130,6 +133,7 @@ class PathCollection(ModulesCollection):
130
133
  matlab_path: Sequence[str | Path],
131
134
  recursive: bool = False,
132
135
  config: Mapping = {},
136
+ config_path: Path | None = None,
133
137
  ) -> None:
134
138
  """
135
139
  Initialize an instance of PathCollection.
@@ -148,6 +152,8 @@ class PathCollection(ModulesCollection):
148
152
  self._mapping: dict[str, deque[Path]] = defaultdict(deque)
149
153
  self._models: dict[Path, LazyModel] = {}
150
154
  self._members: dict[Path, list[tuple[str, Path]]] = defaultdict(list)
155
+ self._folders: dict[str, LazyModel] = {}
156
+ self._config_path = config_path
151
157
 
152
158
  self.config = config
153
159
  self.lines_collection = LinesCollection()
@@ -188,6 +194,26 @@ class PathCollection(ModulesCollection):
188
194
  model = self._models[self._mapping[identifier][0]].model()
189
195
  if model is not None:
190
196
  model = self.update_model(model, config)
197
+
198
+ elif self._config_path is not None and "/" in identifier:
199
+ absolute_path = (self._config_path / Path(identifier)).resolve()
200
+ if absolute_path.exists():
201
+ path = absolute_path.relative_to(self._config_path)
202
+ if path.suffix:
203
+ path, member = path.parent, path.stem
204
+ else:
205
+ member = None
206
+ lazymodel = self._folders.get(str(path), None)
207
+
208
+ if lazymodel is not None:
209
+ model = lazymodel.model()
210
+ if model is not None and member is not None:
211
+ model = model.members.get(member, None)
212
+ else:
213
+ model = None
214
+ else:
215
+ model = None
216
+
191
217
  else:
192
218
  model = None
193
219
  name_parts = identifier.split(".")
@@ -511,13 +537,25 @@ class PathCollection(ModulesCollection):
511
537
  else:
512
538
  self._path.appendleft(path)
513
539
 
514
- members = PathGlobber(path, recursive=recursive)
515
- for member in members:
540
+ for member in PathGlobber(path, recursive=recursive):
516
541
  model = LazyModel(member, self)
517
542
  self._models[member] = model
518
543
  self._mapping[model.name].append(member)
519
544
  self._members[path].append((model.name, member))
520
545
 
546
+ if self._config_path is not None and member.parent.stem[0] not in [
547
+ "+",
548
+ "@",
549
+ ]:
550
+ if member.parent.is_relative_to(self._config_path):
551
+ relative_path = member.parent.relative_to(self._config_path)
552
+ if member.parent not in self._folders:
553
+ self._folders[str(relative_path)] = LazyModel(
554
+ member.parent, self
555
+ )
556
+ else:
557
+ pass # TODO: Issue warning?
558
+
521
559
  def rm_path(self, path: str | Path, recursive: bool = False):
522
560
  """
523
561
  Removes a path from the search path and updates the namespace and database accordingly.
@@ -610,6 +648,10 @@ class LazyModel:
610
648
  self._path_collection: PathCollection = path_collection
611
649
  self._lines_collection: LinesCollection = path_collection.lines_collection
612
650
 
651
+ @property
652
+ def is_folder(self) -> bool:
653
+ return self._path.is_dir() and self._path.name[0] not in ["+", "@"]
654
+
613
655
  @property
614
656
  def is_class_folder(self) -> bool:
615
657
  return self._path.is_dir() and self._path.name[0] == "@"
@@ -648,7 +690,7 @@ class LazyModel:
648
690
  else:
649
691
  return name
650
692
 
651
- def model(self):
693
+ def model(self) -> MatlabMixin | None:
652
694
  if not self._path.exists():
653
695
  return None
654
696
 
@@ -657,19 +699,22 @@ class LazyModel:
657
699
  self._model = self._collect_classfolder(self._path)
658
700
  elif self.is_namespace:
659
701
  self._model = self._collect_namespace(self._path)
702
+ elif self.is_folder:
703
+ self._model = self._collect_folder(self._path)
660
704
  else:
661
705
  self._model = self._collect_path(self._path)
662
706
  if self._model is not None:
663
707
  self._model.parent = self._collect_parent(self._path.parent)
664
708
  return self._model
665
709
 
666
- def _collect_parent(self, path: Path) -> Object | _ParentGrabber:
710
+ def _collect_parent(self, path: Path) -> _ParentGrabber | None:
667
711
  if self.is_in_namespace:
668
- parent = _ParentGrabber(
669
- lambda: self._path_collection._models[path].model() or ROOT
670
- )
712
+ grabber: Callable[[], MatlabMixin | None] = self._path_collection._models[
713
+ path
714
+ ].model
715
+ parent = _ParentGrabber(grabber)
671
716
  else:
672
- parent = ROOT
717
+ parent = None
673
718
  return parent
674
719
 
675
720
  def _collect_path(self, path: Path) -> MatlabMixin:
@@ -678,6 +723,27 @@ class LazyModel:
678
723
  self._lines_collection[path] = file.content.split("\n")
679
724
  return model
680
725
 
726
+ def _collect_directory(self, path: Path, model: PathType) -> PathType:
727
+ for member in path.iterdir():
728
+ if member.is_dir() and member.name[0] in ["+", "@"]:
729
+ submodel = self._path_collection._models[member].model()
730
+ if submodel is not None:
731
+ model.members[submodel.name] = submodel
732
+
733
+ elif member.is_file() and member.suffix == ".m":
734
+ if member.name == "Contents.m":
735
+ contentsfile = self._collect_path(member)
736
+ model.docstring = contentsfile.docstring
737
+ else:
738
+ submodel = self._path_collection._models[member].model()
739
+ if submodel is not None:
740
+ model.members[submodel.name] = submodel
741
+
742
+ if model.docstring is None:
743
+ model.docstring = self._collect_readme_md(path, model)
744
+
745
+ return model
746
+
681
747
  def _collect_classfolder(self, path: Path) -> Classfolder | None:
682
748
  classfile = path / (path.name[1:] + ".m")
683
749
  if not classfile.exists():
@@ -698,31 +764,17 @@ class LazyModel:
698
764
  model.docstring = self._collect_readme_md(path, model)
699
765
  return model
700
766
 
701
- def _collect_namespace(self, path: Path) -> Namespace | None:
767
+ def _collect_namespace(self, path: Path) -> Namespace:
702
768
  name = self.name[1:].split(".")[-1]
703
769
  model = Namespace(name, filepath=path, path_collection=self._path_collection)
770
+ return self._collect_directory(path, model)
704
771
 
705
- for member in path.iterdir():
706
- if member.is_dir() and member.name[0] in ["+", "@"]:
707
- submodel = self._path_collection._models[member].model()
708
- if submodel is not None:
709
- model.members[submodel.name] = submodel
710
-
711
- elif member.is_file() and member.suffix == ".m":
712
- if member.name == "Contents.m":
713
- contentsfile = self._collect_path(member)
714
- model.docstring = contentsfile.docstring
715
- else:
716
- submodel = self._path_collection._models[member].model()
717
- if submodel is not None:
718
- model.members[submodel.name] = submodel
719
-
720
- if model.docstring is None:
721
- model.docstring = self._collect_readme_md(path, model)
722
-
723
- return model
772
+ def _collect_folder(self, path: Path) -> Folder:
773
+ name = path.stem
774
+ model = Folder(name, filepath=path, path_collection=self._path_collection)
775
+ return self._collect_directory(path, model)
724
776
 
725
- def _collect_readme_md(self, path, parent: MatlabMixin) -> Docstring | None:
777
+ def _collect_readme_md(self, path, parent: PathMixin) -> Docstring | None:
726
778
  if (path / "README.md").exists():
727
779
  readme = path / "README.md"
728
780
  elif (path / "readme.md").exists():
@@ -2,8 +2,9 @@
2
2
 
3
3
  from pathlib import Path
4
4
  from collections import ChainMap
5
+ from jinja2.loaders import FileSystemLoader
5
6
  from markdown import Markdown
6
- from mkdocstrings.extension import PluginError
7
+ from mkdocs.exceptions import PluginError
7
8
  from mkdocstrings.handlers.base import BaseHandler, CollectorItem, CollectionError
8
9
  from mkdocstrings_handlers.python import rendering
9
10
  from typing import Any, ClassVar, Mapping
@@ -152,7 +153,9 @@ class MatlabHandler(BaseHandler):
152
153
 
153
154
  def __init__(
154
155
  self,
155
- *args: Any,
156
+ handler: str,
157
+ theme: str,
158
+ custom_templates: str | None = None,
156
159
  config_file_path: str | None = None,
157
160
  paths: list[str] | None = None,
158
161
  paths_recursive: bool = False,
@@ -163,7 +166,9 @@ class MatlabHandler(BaseHandler):
163
166
  Initialize the handler with the given configuration.
164
167
 
165
168
  Args:
166
- *args (Any): Variable length argument list.
169
+ handler: The name of the handler.
170
+ theme: The name of theme to use.
171
+ custom_templates: Directory containing custom templates.
167
172
  config_file_path (str | None, optional): Path to the configuration file. Defaults to None.
168
173
  paths (list[str] | None, optional): List of paths to include. Defaults to None.
169
174
  paths_recursive (bool, optional): Whether to include paths recursively. Defaults to False.
@@ -173,21 +178,37 @@ class MatlabHandler(BaseHandler):
173
178
  Returns:
174
179
  None
175
180
  """
176
- super().__init__(*args, **kwargs)
181
+
182
+ super().__init__(handler, theme, custom_templates=custom_templates)
183
+
184
+ theme_path = Path(__file__).resolve().parent / "templates" / theme
185
+ if theme_path.exists() and isinstance(self.env.loader, FileSystemLoader):
186
+ # Insert our templates directory at the beginning of the search path to overload the Python templates
187
+ self.env.loader.searchpath.insert(0, str(theme_path))
188
+ css_path = theme_path / "style.css"
189
+ if css_path.exists():
190
+ self.extra_css += "\n" + css_path.read_text(encoding="utf-8")
177
191
 
178
192
  if paths is None or config_file_path is None:
193
+ config_path = None
179
194
  full_paths = []
180
195
  else:
181
196
  config_path = Path(config_file_path).parent
182
197
  full_paths = [(config_path / path).resolve() for path in paths]
183
198
 
199
+ if pathIds := [str(path) for path in full_paths if not path.is_dir()]:
200
+ raise PluginError(
201
+ "The following paths do not exist or are not directories: "
202
+ + ", ".join(pathIds)
203
+ )
204
+
184
205
  self.paths: PathCollection = PathCollection(
185
- full_paths, recursive=paths_recursive
206
+ full_paths, recursive=paths_recursive, config_path=config_path
186
207
  )
187
208
  self.lines: LinesCollection = self.paths.lines_collection
188
209
  self._locale: str = locale
189
210
 
190
- def get_templates_dir(self, handler: str | None = None) -> Path:
211
+ def get_templates_dir(self, *args, **kwargs) -> Path:
191
212
  # use the python handler templates
192
213
  # (it assumes the python handler is installed)
193
214
  return super().get_templates_dir("python")
@@ -253,9 +274,6 @@ class MatlabHandler(BaseHandler):
253
274
  }
254
275
 
255
276
  # Map docstring options
256
- final_config["show_submodules"] = config.get(
257
- "show_subnamespaces", False
258
- )
259
277
  final_config["show_docstring_attributes"] = config.get(
260
278
  "show_docstring_properties", True
261
279
  )
@@ -340,7 +358,10 @@ class MatlabHandler(BaseHandler):
340
358
  raise CollectionError("Empty identifier")
341
359
 
342
360
  final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
343
- return self.paths.resolve(identifier, config=final_config)
361
+ model = self.paths.resolve(identifier, config=final_config)
362
+ if model is None:
363
+ raise CollectionError(f"Identifier '{identifier}' not found")
364
+ return model
344
365
 
345
366
 
346
367
  def get_handler(
@@ -99,7 +99,7 @@ class _ParentGrabber:
99
99
  __call__(): Calls the grabber function and returns a MatlabObject.
100
100
  """
101
101
 
102
- def __init__(self, grabber: "Callable[[], Object]") -> None:
102
+ def __init__(self, grabber: "Callable[[], MatlabMixin | None]") -> None:
103
103
  """
104
104
  Initializes the _ParentGrabber with a grabber function.
105
105
 
@@ -109,7 +109,7 @@ class _ParentGrabber:
109
109
  self._grabber = grabber
110
110
 
111
111
  @property
112
- def parent(self) -> "Object":
112
+ def parent(self) -> "MatlabMixin | None":
113
113
  """
114
114
  Calls the grabber function and returns a MatlabObject.
115
115
 
@@ -141,13 +141,24 @@ class MatlabObject(Object):
141
141
  path_collection (PathCollection | None): The collection of paths related to the object.
142
142
  **kwargs: Arbitrary keyword arguments.
143
143
  """
144
-
145
144
  self.path_collection: "PathCollection | None" = path_collection
146
145
  lines_collection = (
147
146
  path_collection.lines_collection if path_collection is not None else None
148
147
  )
149
148
  super().__init__(*args, lines_collection=lines_collection, **kwargs)
150
149
 
150
+ @property
151
+ def namespaces(self) -> dict[str, "Namespace"]:
152
+ return {}
153
+
154
+ @property
155
+ def is_namespace(self) -> bool:
156
+ return False
157
+
158
+ @property
159
+ def is_folder(self) -> bool:
160
+ return False
161
+
151
162
  @property
152
163
  def canonical_path(self) -> str:
153
164
  """
@@ -156,7 +167,7 @@ class MatlabObject(Object):
156
167
  Returns:
157
168
  str: The canonical path of the object.
158
169
  """
159
- if isinstance(self.parent, _Root):
170
+ if self.parent is None:
160
171
  return self.name
161
172
 
162
173
  if isinstance(self.parent, MatlabObject):
@@ -165,7 +176,7 @@ class MatlabObject(Object):
165
176
  parent = getattr(self.parent, "model", self.parent)
166
177
 
167
178
  if isinstance(parent, Classfolder) and self.name == parent.name:
168
- if isinstance(parent.parent, _Root) or parent.parent is None:
179
+ if parent.parent is None:
169
180
  return self.name
170
181
  else:
171
182
  return f"{parent.parent.canonical_path}.{self.name}"
@@ -173,23 +184,6 @@ class MatlabObject(Object):
173
184
  return f"{parent.canonical_path}.{self.name}" if parent else self.name
174
185
 
175
186
 
176
- class _Root(MatlabObject):
177
- """
178
- A class representing the root object in a MATLAB structure.
179
- All the objects that have the root object as parent are at the top level,
180
- and can be called directly.
181
- """
182
-
183
- def __init__(self) -> None:
184
- super().__init__("ROOT", parent=None)
185
-
186
- def __repr__(self) -> str:
187
- return "MATLABROOT"
188
-
189
-
190
- ROOT = _Root()
191
-
192
-
193
187
  class PathMixin(Object):
194
188
  """
195
189
  A mixin class that provides a filepath attribute and related functionality.
@@ -200,7 +194,6 @@ class PathMixin(Object):
200
194
 
201
195
  def __init__(self, *args: Any, filepath: Path | None = None, **kwargs: Any) -> None:
202
196
  self._filepath: Path | None = filepath
203
-
204
197
  super().__init__(*args, **kwargs)
205
198
 
206
199
  @property
@@ -215,22 +208,22 @@ class MatlabMixin(Object):
215
208
  def __init__(
216
209
  self,
217
210
  *args: Any,
218
- parent: "Class | Classfolder | Namespace | _Root | None" = None,
211
+ parent: "Class | Classfolder | Namespace | None" = None,
219
212
  docstring: Docstring | None = None,
220
213
  **kwargs: Any,
221
214
  ):
222
- self._parent: "Class | Classfolder | Namespace | _Root | _ParentGrabber | None" = parent
215
+ self._parent: "Class | Classfolder | Namespace | _ParentGrabber | None" = parent
223
216
  self._docstring: Docstring | None = docstring
224
217
  super().__init__(*args, **kwargs)
225
218
 
226
219
  @property
227
- def parent(self) -> Object:
220
+ def parent(self) -> Object | None:
228
221
  if isinstance(self._parent, MatlabMixin):
229
222
  return self._parent
230
223
  elif isinstance(self._parent, _ParentGrabber):
231
224
  return self._parent.parent
232
225
  else:
233
- return ROOT
226
+ return None
234
227
 
235
228
  @parent.setter
236
229
  def parent(self, value):
@@ -444,6 +437,8 @@ class Property(MatlabMixin, Attribute, MatlabObject):
444
437
  self.SetAccess: AccessEnum = SetAccess
445
438
  self.getter: Function | None = None
446
439
 
440
+ self.extra["mkdocstrings"] = {"template": "property.html.jinja"}
441
+
447
442
  @property
448
443
  def Private(self) -> bool:
449
444
  private = self.Access != AccessEnum.public
@@ -559,19 +554,52 @@ class Function(MatlabMixin, PathMixin, GriffeFunction, MatlabObject):
559
554
  pass
560
555
 
561
556
 
557
+ class Folder(MatlabMixin, PathMixin, Module, MatlabObject):
558
+ """
559
+ A class representing a Folder in a MATLAB project.
560
+
561
+ Inherits from:
562
+ - MatlabMixin: A mixin class providing MATLAB-specific functionality.
563
+ - PathMixin: A mixin class providing path-related functionality.
564
+ - Module: A class representing a module.
565
+ - MatlabObject: A base class for MATLAB objects.
566
+ """
567
+
568
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
569
+ super().__init__(*args, **kwargs)
570
+ self.extra["mkdocstrings"] = {"template": "folder.html.jinja"}
571
+
572
+ def __repr__(self) -> str:
573
+ return f"Folder({self.filepath!r})"
574
+
575
+ @property
576
+ def namespaces(self) -> dict[str, "Namespace"]:
577
+ return {
578
+ name: member
579
+ for name, member in self.members.items()
580
+ if isinstance(member, Namespace)
581
+ }
582
+
583
+ @property
584
+ def is_folder(self) -> bool:
585
+ return True
586
+
587
+
562
588
  class Namespace(MatlabMixin, PathMixin, Module, MatlabObject):
563
589
  """
564
590
  A class representing a namespace in a MATLAB project.
565
591
 
566
592
  Inherits from:
593
+ - MatlabMixin: A mixin class providing MATLAB-specific functionality.
567
594
  - PathMixin: A mixin class providing path-related functionality.
568
- - MatlabObject: A base class for MATLAB objects.
569
595
  - Module: A class representing a module.
596
+ - MatlabObject: A base class for MATLAB objects.
570
597
  """
571
598
 
572
599
  def __init__(self, *args: Any, **kwargs: Any) -> None:
573
600
  super().__init__(*args, **kwargs)
574
601
  self._access: AccessEnum = AccessEnum.public
602
+ self.extra["mkdocstrings"] = {"template": "namespace.html.jinja"}
575
603
 
576
604
  def __repr__(self) -> str:
577
605
  return f"Namespace({self.path!r})"
@@ -583,3 +611,7 @@ class Namespace(MatlabMixin, PathMixin, Module, MatlabObject):
583
611
  if self.filepath
584
612
  else False
585
613
  )
614
+
615
+ @property
616
+ def is_namespace(self) -> bool:
617
+ return True
@@ -0,0 +1,172 @@
1
+ {#- Template for members (children) of an object.
2
+
3
+ This template iterates on members of a given object and renders them.
4
+ It can group members by category (attributes, classes, functions, modules) or render them in a flat list.
5
+
6
+ Context:
7
+ obj (griffe.Object): The object to render.
8
+ config (dict): The configuration options.
9
+ root_members (bool): Whether the object is the root object.
10
+ heading_level (int): The HTML heading level to use.
11
+ -#}
12
+
13
+ {% if obj.all_members %}
14
+ {% block logs scoped %}
15
+ {#- Logging block.
16
+
17
+ This block can be used to log debug messages, deprecation messages, warnings, etc.
18
+ -#}
19
+ {{ log.debug("Rendering children of " + obj.path) }}
20
+ {% endblock logs %}
21
+
22
+ <div class="doc doc-children">
23
+
24
+ {% if root_members %}
25
+ {% set members_list = config.members %}
26
+ {% else %}
27
+ {% set members_list = none %}
28
+ {% endif %}
29
+
30
+ {% if config.group_by_category %}
31
+
32
+ {% with %}
33
+
34
+ {% if config.show_category_heading %}
35
+ {% set extra_level = 1 %}
36
+ {% else %}
37
+ {% set extra_level = 0 %}
38
+ {% endif %}
39
+
40
+ {% with attributes = obj.attributes|filter_objects(
41
+ filters=config.filters,
42
+ members_list=members_list,
43
+ inherited_members=config.inherited_members,
44
+ keep_no_docstrings=config.show_if_no_docstring,
45
+ ) %}
46
+ {% if attributes %}
47
+ {% if config.show_category_heading %}
48
+ {% filter heading(heading_level, id=html_id ~ "-properties") %}Properties{% endfilter %}
49
+ {% endif %}
50
+ {% with heading_level = heading_level + extra_level %}
51
+ {% for attribute in attributes|order_members(config.members_order, members_list) %}
52
+ {% if members_list is not none or (not attribute.is_imported or attribute.is_public) %}
53
+ {% include attribute|get_template with context %}
54
+ {% endif %}
55
+ {% endfor %}
56
+ {% endwith %}
57
+ {% endif %}
58
+ {% endwith %}
59
+
60
+ {% with classes = obj.classes|filter_objects(
61
+ filters=config.filters,
62
+ members_list=members_list,
63
+ inherited_members=config.inherited_members,
64
+ keep_no_docstrings=config.show_if_no_docstring,
65
+ ) %}
66
+ {% if classes %}
67
+ {% if config.show_category_heading %}
68
+ {% filter heading(heading_level, id=html_id ~ "-classes") %}Classes{% endfilter %}
69
+ {% endif %}
70
+ {% with heading_level = heading_level + extra_level %}
71
+ {% for class in classes|order_members(config.members_order, members_list) %}
72
+ {% if members_list is not none or (not class.is_imported or class.is_public) %}
73
+ {% include class|get_template with context %}
74
+ {% endif %}
75
+ {% endfor %}
76
+ {% endwith %}
77
+ {% endif %}
78
+ {% endwith %}
79
+
80
+ {% with functions = obj.functions|filter_objects(
81
+ filters=config.filters,
82
+ members_list=members_list,
83
+ inherited_members=config.inherited_members,
84
+ keep_no_docstrings=config.show_if_no_docstring,
85
+ ) %}
86
+ {% if functions %}
87
+ {% if config.show_category_heading %}
88
+ {% filter heading(heading_level, id=html_id ~ "-functions") %}Functions{% endfilter %}
89
+ {% endif %}
90
+ {% with heading_level = heading_level + extra_level %}
91
+ {% for function in functions|order_members(config.members_order, members_list) %}
92
+ {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
93
+ {% if members_list is not none or (not function.is_imported or function.is_public) %}
94
+ {% include function|get_template with context %}
95
+ {% endif %}
96
+ {% endif %}
97
+ {% endfor %}
98
+ {% endwith %}
99
+ {% endif %}
100
+ {% endwith %}
101
+
102
+ {% if config.show_submodules or obj.is_folder %}
103
+ {% with modules = obj.modules|filter_objects(
104
+ filters=config.filters,
105
+ members_list=members_list,
106
+ inherited_members=config.inherited_members,
107
+ keep_no_docstrings=config.show_if_no_docstring,
108
+ ) %}
109
+ {% if modules %}
110
+ {% if config.show_category_heading %}
111
+ {% filter heading(heading_level, id=html_id ~ "-namespaces") %}Modules{% endfilter %}
112
+ {% endif %}
113
+ {% with heading_level = heading_level + extra_level %}
114
+ {% for module in modules|order_members(config.members_order.alphabetical, members_list) %}
115
+ {% if members_list is not none or (not module.is_alias or module.is_public) %}
116
+ {% include module|get_template with context %}
117
+ {% endif %}
118
+ {% endfor %}
119
+ {% endwith %}
120
+ {% endif %}
121
+ {% endwith %}
122
+ {% endif %}
123
+
124
+ {% endwith %}
125
+
126
+ {% else %}
127
+
128
+ {% for child in obj.all_members
129
+ |filter_objects(
130
+ filters=config.filters,
131
+ members_list=members_list,
132
+ inherited_members=config.inherited_members,
133
+ keep_no_docstrings=config.show_if_no_docstring,
134
+ )
135
+ |order_members(config.members_order, members_list)
136
+ %}
137
+
138
+ {% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}
139
+
140
+ {% if members_list is not none or child.is_public %}
141
+ {% if child.is_attribute %}
142
+ {% with attribute = child %}
143
+ {% include attribute|get_template with context %}
144
+ {% endwith %}
145
+
146
+ {% elif child.is_class %}
147
+ {% with class = child %}
148
+ {% include class|get_template with context %}
149
+ {% endwith %}
150
+
151
+ {% elif child.is_function %}
152
+ {% with function = child %}
153
+ {% include function|get_template with context %}
154
+ {% endwith %}
155
+
156
+ {% elif (child.is_namespace and config.show_submodules) or obj.is_folder %}
157
+ {% with module = child %}
158
+ {% include module|get_template with context %}
159
+ {% endwith %}
160
+
161
+ {% endif %}
162
+ {% endif %}
163
+
164
+ {% endif %}
165
+
166
+ {% endfor %}
167
+
168
+ {% endif %}
169
+
170
+ </div>
171
+
172
+ {% endif %}