mkdocstrings-matlab 0.1.6__py2.py3-none-any.whl → 0.2.0__py2.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.
@@ -10,6 +10,7 @@ from pprint import pprint
10
10
 
11
11
  import charset_normalizer
12
12
  import json
13
+ import requests
13
14
 
14
15
 
15
16
  from mkdocstrings_handlers.matlab.collections import LinesCollection, ModelsCollection
@@ -60,7 +61,8 @@ class MatlabHandler(BaseHandler):
60
61
  # "find_stubs_package": False,
61
62
  # "allow_inspection": True,
62
63
  "show_bases": True,
63
- "show_inheritance_diagram": False, # Insider feature
64
+ "show_inheritance_diagram": True,
65
+ "inheritance_diagram_show_builtin": False,
64
66
  "show_source": True,
65
67
  # "preload_modules": None,
66
68
  # Heading options
@@ -125,7 +127,7 @@ class MatlabHandler(BaseHandler):
125
127
  super().__init__(*args, **kwargs)
126
128
 
127
129
  if paths is None:
128
- paths = ""
130
+ full_paths = ""
129
131
  else:
130
132
  config_path = Path(config_file_path).parent
131
133
  full_paths = [str((config_path / path).resolve()) for path in paths]
@@ -143,6 +145,46 @@ class MatlabHandler(BaseHandler):
143
145
  # (it assumes the python handler is installed)
144
146
  return super().get_templates_dir("python")
145
147
 
148
+ def get_ast(self, identifier:str, config: Mapping[str, Any]) -> dict:
149
+ """Retrieve the Abstract Syntax Tree (AST) for a given MATLAB identifier.
150
+
151
+ This method resolves the docstring for the specified identifier and parses it into an AST.
152
+ If the identifier corresponds to a class, it processes its superclasses and optionally
153
+ includes an inheritance diagram based on the provided configuration.
154
+ Args:
155
+ identifier (str): The MATLAB identifier to resolve.
156
+ config (Mapping[str, Any]): Configuration options for processing the AST.
157
+ Returns:
158
+ dict: The parsed AST for the given identifier.
159
+ Raises:
160
+ MatlabExecutionError: If there is an error resolving the superclass AST.
161
+ """
162
+
163
+ ast_json = self.engine.docstring.resolve(identifier)
164
+ ast = json.loads(ast_json)
165
+
166
+ if ast['type'] == 'class':
167
+
168
+ if isinstance(ast["superclasses"], str):
169
+ ast["superclasses"] = [ast["superclasses"]]
170
+
171
+ if config["show_inheritance_diagram"]:
172
+ # Check if class is builtin and skip superclasses if option is not set
173
+ builtin = ast.get('builtin', False) or ast["name"].startswith("matlab.")
174
+ resursive = not builtin or config["inheritance_diagram_show_builtin"]
175
+ if not resursive:
176
+ ast["superclasses"] = []
177
+
178
+ # Get superclasses AST
179
+ for index, base in enumerate(ast["superclasses"]):
180
+ try:
181
+ ast["superclasses"][index] = self.get_ast(base, config)
182
+ ast["superclasses"][index]["name"] = base
183
+ except MatlabExecutionError:
184
+ ast["superclasses"][index] = {"name": base}
185
+ return ast
186
+
187
+
146
188
  def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem:
147
189
  """Collect data given an identifier and user configuration.
148
190
 
@@ -156,26 +198,28 @@ class MatlabHandler(BaseHandler):
156
198
  Returns:
157
199
  CollectorItem
158
200
  """
201
+ if identifier == "":
202
+ raise CollectionError("Empty identifier")
203
+
159
204
  final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
160
205
  if identifier in self.models:
161
206
  return self.models[identifier]
162
207
 
163
208
  try:
164
- ast_json = self.engine.docstring.resolve(identifier)
209
+ ast = self.get_ast(identifier, final_config)
165
210
  except MatlabExecutionError as error:
166
211
  raise CollectionError(error.args[0].strip()) from error
167
- ast_dict = json.loads(ast_json)
168
212
 
169
- filepath = Path(ast_dict["path"])
213
+ filepath = Path(ast["path"])
170
214
  if filepath not in self.lines:
171
215
  lines = str(charset_normalizer.from_path(filepath).best()).splitlines()
172
216
  self.lines[filepath] = lines
173
217
 
174
- match ast_dict["type"]:
218
+ match ast["type"]:
175
219
  case "function" | "method":
176
- return self.collect_function(ast_dict, final_config)
220
+ return self.collect_function(ast, final_config)
177
221
  case "class":
178
- return self.collect_class(ast_dict, final_config)
222
+ return self.collect_class(ast, final_config)
179
223
  case _:
180
224
  return None
181
225
 
@@ -247,15 +291,11 @@ class MatlabHandler(BaseHandler):
247
291
  lambda template_name: template_name in self.env.list_templates()
248
292
  )
249
293
 
250
- def collect_class(self, ast_dict: dict, config: Mapping) -> Class:
251
- docstring = (
252
- Docstring(ast_dict["docstring"], parser=config["docstring_style"])
253
- if ast_dict["docstring"]
254
- else None
255
- )
294
+ def collect_class(self, ast: dict, config: Mapping) -> Class:
256
295
 
257
- filepath = Path(ast_dict["path"])
296
+ filepath = Path(ast["path"])
258
297
 
298
+ # Parse textmate object
259
299
  if config["show_source"]:
260
300
  tmObject = self.parser.parse_file(filepath)
261
301
  tmClass = next(
@@ -266,18 +306,24 @@ class MatlabHandler(BaseHandler):
266
306
  else:
267
307
  tmClass = None
268
308
 
269
- bases = ast_dict["superclasses"] if isinstance(ast_dict["superclasses"], list) else [ast_dict["superclasses"]]
270
- bases = [base for base in bases if base != "handle"]
271
-
309
+ # Get bases
310
+ if config["show_bases"]:
311
+ if config["show_inheritance_diagram"]:
312
+ bases = [base["name"] for base in ast["superclasses"]]
313
+ else:
314
+ bases = ast["superclasses"] if isinstance(ast["superclasses"], list) else [ast["superclasses"]]
315
+ else:
316
+ bases = []
317
+
318
+ # Load model
272
319
  model = Class(
273
- ast_dict["name"],
274
- docstring=docstring,
320
+ ast["name"],
275
321
  parent=self.get_parent(filepath.parent),
276
- hidden=ast_dict["hidden"],
277
- sealed=ast_dict["sealed"],
278
- abstract=ast_dict["abstract"],
279
- enumeration=ast_dict["enumeration"],
280
- handle=ast_dict["handle"],
322
+ hidden=ast["hidden"],
323
+ sealed=ast["sealed"],
324
+ abstract=ast["abstract"],
325
+ enumeration=ast["enumeration"],
326
+ handle=ast["handle"],
281
327
  bases=bases,
282
328
  filepath=filepath,
283
329
  modules_collection=self.models,
@@ -286,8 +332,21 @@ class MatlabHandler(BaseHandler):
286
332
  endlineno=len(self.lines[filepath]),
287
333
  textmate=tmClass,
288
334
  )
335
+ ast["name"] = model.canonical_path
336
+
337
+ # Format mermaid inheritance diagram
338
+ if config["show_inheritance_diagram"] and ast["superclasses"]:
339
+ section = get_inheritance_diagram(ast)
340
+ docstring = Docstring(ast["docstring"] + section, parser=config["docstring_style"])
341
+ elif ast["docstring"]:
342
+ docstring = Docstring(ast["docstring"], parser=config["docstring_style"])
343
+ else:
344
+ docstring
345
+
346
+ model.docstring = docstring
289
347
 
290
- for property_dict in ast_dict["properties"]:
348
+ # Load properties
349
+ for property_dict in ast["properties"]:
291
350
  name = property_dict.pop("name")
292
351
  defining_class = property_dict.pop("class")
293
352
  property_doc = property_dict.pop("docstring")
@@ -306,7 +365,8 @@ class MatlabHandler(BaseHandler):
306
365
  model.members[name] = prop
307
366
  self.models[prop.canonical_path] = prop
308
367
 
309
- for method_dict in ast_dict["methods"]:
368
+ # Load methods
369
+ for method_dict in ast["methods"]:
310
370
  name = method_dict.pop("name")
311
371
  defining_class = method_dict.pop("class")
312
372
  if (
@@ -337,13 +397,13 @@ class MatlabHandler(BaseHandler):
337
397
 
338
398
  return model
339
399
 
340
- def collect_function(self, ast_dict: dict, config: Mapping) -> Function:
400
+ def collect_function(self, ast: dict, config: Mapping) -> Function:
341
401
  parameters = []
342
402
 
343
403
  inputs = (
344
- ast_dict["inputs"]
345
- if isinstance(ast_dict["inputs"], list)
346
- else [ast_dict["inputs"]]
404
+ ast["inputs"]
405
+ if isinstance(ast["inputs"], list)
406
+ else [ast["inputs"]]
347
407
  )
348
408
  for input_dict in inputs:
349
409
  if input_dict["name"] == "varargin":
@@ -362,16 +422,16 @@ class MatlabHandler(BaseHandler):
362
422
  )
363
423
  )
364
424
 
365
- filepath = Path(ast_dict["path"])
425
+ filepath = Path(ast["path"])
366
426
  model = Function(
367
- ast_dict["name"],
427
+ ast["name"],
368
428
  parameters=Parameters(*parameters),
369
429
  docstring=Docstring(
370
- ast_dict["docstring"],
430
+ ast["docstring"],
371
431
  parser=config["docstring_style"],
372
432
  parser_options=config["docstring_options"],
373
433
  )
374
- if ast_dict["docstring"]
434
+ if ast["docstring"]
375
435
  else None,
376
436
  parent=self.get_parent(filepath.parent),
377
437
  filepath=filepath,
@@ -409,6 +469,32 @@ class MatlabHandler(BaseHandler):
409
469
  parent = ROOT
410
470
  return parent
411
471
 
472
+ def get_inheritance_diagram(ast: dict) -> str:
473
+ def get_id(str: str) -> str:
474
+ return str.replace('.', '_')
475
+ def get_nodes(ast: dict, nodes: set[str] = set(), clicks: set[str] = set()) -> str:
476
+ id = get_id(ast['name'])
477
+ nodes.add(f" {id}[{ast['name']}]")
478
+ if "help" in ast:
479
+ clicks.add(f" click {id} \"{ast['help']}\"")
480
+ if "superclasses" in ast:
481
+ for superclass in ast["superclasses"]:
482
+ get_nodes(superclass, nodes)
483
+ return (nodes, clicks)
484
+ def get_links(ast: dict, links: set[str] = set()) -> str:
485
+ if "superclasses" in ast:
486
+ for superclass in ast["superclasses"]:
487
+ links.add(f" {get_id(ast['name'])} --> {get_id(superclass['name'])}")
488
+ get_links(superclass, links)
489
+ return links
490
+
491
+ (nodes, clicks) = get_nodes(ast)
492
+ nodes_str = '\n'.join(list(nodes))
493
+ clicks_str = '\n'.join(list(clicks))
494
+ links_str = '\n'.join(list(get_links(ast)))
495
+ section = f"\n\n## Inheritance diagram\n\n```mermaid\nflowchart BT\n{nodes_str}\n{clicks_str}\n{links_str}\n```"
496
+ return section
497
+
412
498
 
413
499
  def get_handler(
414
500
  *,
@@ -1,8 +1,27 @@
1
1
  function data = builtin(identifier)
2
- data.name = identifier;
3
- data.type = 'function';
4
- data.doc = help(identifier);
5
- data.location = string(which(identifier));
6
- data.inputs = struct.empty();
7
- data.outputs = struct.empty();
2
+ if isMATLABReleaseOlderThan('R2024a')
3
+ metaclass = @meta.class.fromName;
4
+ else
5
+ metaclass = @matlab.metadata.Class.fromName;
6
+ end
7
+
8
+ object = metaclass(identifier);
9
+
10
+ if isempty(object)
11
+ data.name = identifier;
12
+ data.type = 'function';
13
+ data.doc = help(identifier);
14
+ data.location = string(which(identifier));
15
+ data.inputs = struct.empty();
16
+ data.outputs = struct.empty();
17
+ if ~contains(identifier, '.internal.')
18
+ data.help = sprintf('https://mathworks.com/help/matlab/ref/%s.html', lower(identifier));
19
+ end
20
+ else
21
+ data = docstring.metadata.class(object, 'builtin', true);
22
+ if ~contains(identifier, '.internal.')
23
+ data.help = sprintf('https://mathworks.com/help/matlab/ref/%s-class.html', lower(identifier));
24
+ end
25
+ end
26
+ data.builtin = true;
8
27
  end
@@ -1,6 +1,7 @@
1
- function data = class(object)
1
+ function data = class(object, opts)
2
2
  arguments
3
3
  object (1,1) % meta.class matlab.metadata.Class
4
+ opts.builtin (1,1) logical = false
4
5
  end
5
6
  data.type = 'class';
6
7
 
@@ -8,7 +9,6 @@ function data = class(object)
8
9
  data.name = namespaces{end};
9
10
 
10
11
  data.docstring = docstring.utils.parse_doc(object);
11
- data.path = matlab.internal.metafunction(object.Name).Location;
12
12
  data.hidden = object.Hidden;
13
13
  data.sealed = object.Sealed;
14
14
  data.abstract = object.Abstract;
@@ -16,6 +16,11 @@ function data = class(object)
16
16
  data.superclasses = arrayfun(@(o) string(o.Name), object.SuperclassList);
17
17
  data.handle = object.HandleCompatible;
18
18
  data.aliases = object.Aliases;
19
+ if opts.builtin
20
+ data.path = '';
21
+ else
22
+ data.path = matlab.internal.metafunction(object.Name).Location;
23
+ end
19
24
 
20
25
  data.methods = [];
21
26
  for methodObject = object.MethodList'
@@ -46,7 +46,7 @@ if contains(identifier, '.')
46
46
  end
47
47
 
48
48
  % Try built-in aliases with which
49
- if contains(which(identifier), ' built-in ')
49
+ if contains(which(identifier), {' built-in ', matlabroot})
50
50
  data = docstring.case.builtin(identifier);
51
51
  jsonString = jsonencode(data);
52
52
  return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mkdocstrings-matlab
3
- Version: 0.1.6
3
+ Version: 0.2.0
4
4
  Summary: Add your description here
5
5
  Author-email: Mark Hu <watermarkhu@gmail.com>
6
6
  License-File: LICENSE
@@ -1,19 +1,19 @@
1
1
  mkdocstrings_handlers/matlab/__init__.py,sha256=laA2bEP5rxdIWBLmfLiKKu7ChZ_HzCe-VeRvxmUTqww,128
2
2
  mkdocstrings_handlers/matlab/collections.py,sha256=oiDK4nwIUXroIPxw6Cu13WcBxmCyAHjPn7naaW_Yhjs,445
3
- mkdocstrings_handlers/matlab/handler.py,sha256=WPfsvlGTZcAYgep6rpRjESPJdXU2QbVm31cf5v9ob0c,16959
3
+ mkdocstrings_handlers/matlab/handler.py,sha256=wgGblmYNXq-u3Y-xxXtYYNzNDF3zeJQkrCE8HyEHpfo,20510
4
4
  mkdocstrings_handlers/matlab/models.py,sha256=n1l1Gr5Wq7nsrsP4PSePGfnGcln0NI-zSrkijGJBf80,5644
5
5
  mkdocstrings_handlers/matlab/parser.py,sha256=bA3KRNnYjSewqyJI8OmLKATk3AZOq9-28UQg0L6f9os,843
6
6
  mkdocstrings_handlers/matlab/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  mkdocstrings_handlers/matlab/matlab/matlab_startup.m,sha256=rGXiR8fI2GW7yWmHxgzE5Un66n5ws3ogYnMvS2oWO8U,464
8
8
  mkdocstrings_handlers/matlab/matlab/+docstring/exception.m,sha256=sj2ycqMpknn_OG5A5X_b5e4WcAoR2oPoqNnDEHJsi7c,222
9
- mkdocstrings_handlers/matlab/matlab/+docstring/resolve.m,sha256=jq_gWvQ0F-BgKgZUZmanaLtaphJqKYWmVESQZpUlvXU,3041
10
- mkdocstrings_handlers/matlab/matlab/+docstring/+case/builtin.m,sha256=IioiokiaLnsi_6VXraaGdU2AgjCNApYhgVEmp2Lg1eA,245
9
+ mkdocstrings_handlers/matlab/matlab/+docstring/resolve.m,sha256=TOL_XmSflwkd3EiDK2PC8wlFCmhxbMW9N8SVgxiwDfk,3055
10
+ mkdocstrings_handlers/matlab/matlab/+docstring/+case/builtin.m,sha256=aU_SlPuyF2G0fiO4Gh2PrkeoE1umNPWuJI9iR26Ln-M,918
11
11
  mkdocstrings_handlers/matlab/matlab/+docstring/+case/class.m,sha256=kVQxUEk8iOfHK2_NnN0HjHVhFnPgUqsf9PzyKC93y0g,276
12
12
  mkdocstrings_handlers/matlab/matlab/+docstring/+case/func.m,sha256=QneDYSICtXqdPNq8sYNieirXUisuDKRM9rxPx-0osDU,137
13
13
  mkdocstrings_handlers/matlab/matlab/+docstring/+case/method.m,sha256=Bw8Mb96OP7-AnbGnvRMySOIbYSTtEC1BGBnqHMEIhsM,165
14
14
  mkdocstrings_handlers/matlab/matlab/+docstring/+case/namespace.m,sha256=ZpYrgZHLIdGvgg3F6210gDTska9YyASn63ZVYkBq41A,667
15
15
  mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/argument.m,sha256=yE1sywrr6Q0YjEkPkdBTjjkLeUrPv0jV-degM_EE_iE,1905
16
- mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/class.m,sha256=n7qDJACSybOGjrQJPR8EzoMxkw2WOPMvPflvshkLz3Q,1673
16
+ mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/class.m,sha256=zvOq3INtGZF65yaiTg0-YZ0jU55XrXcaDSFXQbosBuM,1787
17
17
  mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/func.m,sha256=k1gz4kjEQX5DCIfzCs1lee5jjAL4fg6A7LnwcUF8kRE,424
18
18
  mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/namespace.m,sha256=kMzfAoWIpMXH76rrkyUqauJSRIaylsfnu0Cds4pYnJc,481
19
19
  mkdocstrings_handlers/matlab/matlab/+docstring/+metadata/property.m,sha256=rH3cHz66ZG9sUvDU2fhlyASSB_yp0SiHlbpB44fcFiY,1560
@@ -22,7 +22,7 @@ mkdocstrings_handlers/matlab/matlab/+docstring/+utils/dedent.m,sha256=IsqIZKyaBU
22
22
  mkdocstrings_handlers/matlab/matlab/+docstring/+utils/get_namespace_path.m,sha256=4NlQ7-RjqIFZAn6P-9JzCrm2FvfGRKiM2M_leINj9i4,835
23
23
  mkdocstrings_handlers/matlab/matlab/+docstring/+utils/parse_doc.m,sha256=iFNpbnOr9FAv-3Zn8ksJHIthXAB7XKYVfH2NGFinzHs,499
24
24
  mkdocstrings_handlers/matlab/resources/grammar.yml,sha256=GLI4xdATiB70bzRscXOVwMlw0YFlA-3GJzuzqWeBKJU,19511
25
- mkdocstrings_matlab-0.1.6.dist-info/METADATA,sha256=hSng4k0TMLFDJJIt-l-V89FwzaBZBZOLaPC_IpU5xi4,549
26
- mkdocstrings_matlab-0.1.6.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
27
- mkdocstrings_matlab-0.1.6.dist-info/licenses/LICENSE,sha256=14xA0OIYNpfmdeuq8-Yyqg7-3IJ4qhu3BJhknent-cY,1069
28
- mkdocstrings_matlab-0.1.6.dist-info/RECORD,,
25
+ mkdocstrings_matlab-0.2.0.dist-info/METADATA,sha256=a4cY8E8UhABhC1XuL-pHGJSxNhvF7bVVR8_-fVYUKN4,549
26
+ mkdocstrings_matlab-0.2.0.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
27
+ mkdocstrings_matlab-0.2.0.dist-info/licenses/LICENSE,sha256=14xA0OIYNpfmdeuq8-Yyqg7-3IJ4qhu3BJhknent-cY,1069
28
+ mkdocstrings_matlab-0.2.0.dist-info/RECORD,,