mkdocstrings-matlab 0.1.7__py2.py3-none-any.whl → 0.2.0__py2.py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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.7
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=PhxgwIJigwhYmpy-cjX0l7fC-LQRYUS5VvTw8w1VKmc,16964
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.7.dist-info/METADATA,sha256=pmieiST1GvTvFawrOemM1j-8ilj6TzKbrRZu5zSBBe4,549
26
- mkdocstrings_matlab-0.1.7.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
27
- mkdocstrings_matlab-0.1.7.dist-info/licenses/LICENSE,sha256=14xA0OIYNpfmdeuq8-Yyqg7-3IJ4qhu3BJhknent-cY,1069
28
- mkdocstrings_matlab-0.1.7.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,,