mkdocstrings-matlab 0.1.7__py2.py3-none-any.whl → 0.2.1__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
@@ -143,6 +145,50 @@ 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
+ if isinstance(ast["properties"], dict):
171
+ ast["properties"] = [ast["properties"]]
172
+ if isinstance(ast["methods"], dict):
173
+ ast["methods"] = [ast["methods"]]
174
+
175
+ if config["show_inheritance_diagram"]:
176
+ # Check if class is builtin and skip superclasses if option is not set
177
+ builtin = ast.get('builtin', False) or ast["name"].startswith("matlab.")
178
+ resursive = not builtin or config["inheritance_diagram_show_builtin"]
179
+ if not resursive:
180
+ ast["superclasses"] = []
181
+
182
+ # Get superclasses AST
183
+ for index, base in enumerate(ast["superclasses"]):
184
+ try:
185
+ ast["superclasses"][index] = self.get_ast(base, config)
186
+ ast["superclasses"][index]["name"] = base
187
+ except MatlabExecutionError:
188
+ ast["superclasses"][index] = {"name": base}
189
+ return ast
190
+
191
+
146
192
  def collect(self, identifier: str, config: Mapping[str, Any]) -> CollectorItem:
147
193
  """Collect data given an identifier and user configuration.
148
194
 
@@ -156,26 +202,28 @@ class MatlabHandler(BaseHandler):
156
202
  Returns:
157
203
  CollectorItem
158
204
  """
205
+ if identifier == "":
206
+ raise CollectionError("Empty identifier")
207
+
159
208
  final_config = ChainMap(config, self.default_config) # type: ignore[arg-type]
160
209
  if identifier in self.models:
161
210
  return self.models[identifier]
162
211
 
163
212
  try:
164
- ast_json = self.engine.docstring.resolve(identifier)
213
+ ast = self.get_ast(identifier, final_config)
165
214
  except MatlabExecutionError as error:
166
215
  raise CollectionError(error.args[0].strip()) from error
167
- ast_dict = json.loads(ast_json)
168
216
 
169
- filepath = Path(ast_dict["path"])
217
+ filepath = Path(ast["path"])
170
218
  if filepath not in self.lines:
171
219
  lines = str(charset_normalizer.from_path(filepath).best()).splitlines()
172
220
  self.lines[filepath] = lines
173
221
 
174
- match ast_dict["type"]:
222
+ match ast["type"]:
175
223
  case "function" | "method":
176
- return self.collect_function(ast_dict, final_config)
224
+ return self.collect_function(ast, final_config)
177
225
  case "class":
178
- return self.collect_class(ast_dict, final_config)
226
+ return self.collect_class(ast, final_config)
179
227
  case _:
180
228
  return None
181
229
 
@@ -247,15 +295,11 @@ class MatlabHandler(BaseHandler):
247
295
  lambda template_name: template_name in self.env.list_templates()
248
296
  )
249
297
 
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
- )
298
+ def collect_class(self, ast: dict, config: Mapping) -> Class:
256
299
 
257
- filepath = Path(ast_dict["path"])
300
+ filepath = Path(ast["path"])
258
301
 
302
+ # Parse textmate object
259
303
  if config["show_source"]:
260
304
  tmObject = self.parser.parse_file(filepath)
261
305
  tmClass = next(
@@ -266,18 +310,24 @@ class MatlabHandler(BaseHandler):
266
310
  else:
267
311
  tmClass = None
268
312
 
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
-
313
+ # Get bases
314
+ if config["show_bases"]:
315
+ if config["show_inheritance_diagram"]:
316
+ bases = [base["name"] for base in ast["superclasses"]]
317
+ else:
318
+ bases = ast["superclasses"] if isinstance(ast["superclasses"], list) else [ast["superclasses"]]
319
+ else:
320
+ bases = []
321
+
322
+ # Load model
272
323
  model = Class(
273
- ast_dict["name"],
274
- docstring=docstring,
324
+ ast["name"],
275
325
  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"],
326
+ hidden=ast["hidden"],
327
+ sealed=ast["sealed"],
328
+ abstract=ast["abstract"],
329
+ enumeration=ast["enumeration"],
330
+ handle=ast["handle"],
281
331
  bases=bases,
282
332
  filepath=filepath,
283
333
  modules_collection=self.models,
@@ -286,8 +336,21 @@ class MatlabHandler(BaseHandler):
286
336
  endlineno=len(self.lines[filepath]),
287
337
  textmate=tmClass,
288
338
  )
339
+ ast["name"] = model.canonical_path
340
+
341
+ # Format mermaid inheritance diagram
342
+ if config["show_inheritance_diagram"] and ast["superclasses"]:
343
+ section = get_inheritance_diagram(ast)
344
+ docstring = Docstring(ast["docstring"] + section, parser=config["docstring_style"])
345
+ elif ast["docstring"]:
346
+ docstring = Docstring(ast["docstring"], parser=config["docstring_style"])
347
+ else:
348
+ docstring = None
289
349
 
290
- for property_dict in ast_dict["properties"]:
350
+ model.docstring = docstring
351
+
352
+ # Load properties
353
+ for property_dict in ast["properties"]:
291
354
  name = property_dict.pop("name")
292
355
  defining_class = property_dict.pop("class")
293
356
  property_doc = property_dict.pop("docstring")
@@ -306,7 +369,8 @@ class MatlabHandler(BaseHandler):
306
369
  model.members[name] = prop
307
370
  self.models[prop.canonical_path] = prop
308
371
 
309
- for method_dict in ast_dict["methods"]:
372
+ # Load methods
373
+ for method_dict in ast["methods"]:
310
374
  name = method_dict.pop("name")
311
375
  defining_class = method_dict.pop("class")
312
376
  if (
@@ -330,20 +394,21 @@ class MatlabHandler(BaseHandler):
330
394
  if config["merge_init_into_class"] and model.name in model.members:
331
395
  constructor = model.members.pop(model.name)
332
396
  model.members["__init__"] = constructor
333
- if constructor.docstring.value == model.docstring.value:
397
+
398
+ if getattr(constructor.docstring, 'value', '') == getattr(model.docstring, 'value', ''):
334
399
  model.docstring = None
335
400
 
336
401
  self.models[model.canonical_path] = model
337
402
 
338
403
  return model
339
404
 
340
- def collect_function(self, ast_dict: dict, config: Mapping) -> Function:
405
+ def collect_function(self, ast: dict, config: Mapping) -> Function:
341
406
  parameters = []
342
407
 
343
408
  inputs = (
344
- ast_dict["inputs"]
345
- if isinstance(ast_dict["inputs"], list)
346
- else [ast_dict["inputs"]]
409
+ ast["inputs"]
410
+ if isinstance(ast["inputs"], list)
411
+ else [ast["inputs"]]
347
412
  )
348
413
  for input_dict in inputs:
349
414
  if input_dict["name"] == "varargin":
@@ -362,16 +427,16 @@ class MatlabHandler(BaseHandler):
362
427
  )
363
428
  )
364
429
 
365
- filepath = Path(ast_dict["path"])
430
+ filepath = Path(ast["path"])
366
431
  model = Function(
367
- ast_dict["name"],
432
+ ast["name"],
368
433
  parameters=Parameters(*parameters),
369
434
  docstring=Docstring(
370
- ast_dict["docstring"],
435
+ ast["docstring"],
371
436
  parser=config["docstring_style"],
372
437
  parser_options=config["docstring_options"],
373
438
  )
374
- if ast_dict["docstring"]
439
+ if ast["docstring"]
375
440
  else None,
376
441
  parent=self.get_parent(filepath.parent),
377
442
  filepath=filepath,
@@ -409,6 +474,32 @@ class MatlabHandler(BaseHandler):
409
474
  parent = ROOT
410
475
  return parent
411
476
 
477
+ def get_inheritance_diagram(ast: dict) -> str:
478
+ def get_id(str: str) -> str:
479
+ return str.replace('.', '_')
480
+ def get_nodes(ast: dict, nodes: set[str] = set(), clicks: set[str] = set()) -> str:
481
+ id = get_id(ast['name'])
482
+ nodes.add(f" {id}[{ast['name']}]")
483
+ if "help" in ast:
484
+ clicks.add(f" click {id} \"{ast['help']}\"")
485
+ if "superclasses" in ast:
486
+ for superclass in ast["superclasses"]:
487
+ get_nodes(superclass, nodes)
488
+ return (nodes, clicks)
489
+ def get_links(ast: dict, links: set[str] = set()) -> str:
490
+ if "superclasses" in ast:
491
+ for superclass in ast["superclasses"]:
492
+ links.add(f" {get_id(ast['name'])} --> {get_id(superclass['name'])}")
493
+ get_links(superclass, links)
494
+ return links
495
+
496
+ (nodes, clicks) = get_nodes(ast)
497
+ nodes_str = '\n'.join(list(nodes))
498
+ clicks_str = '\n'.join(list(clicks))
499
+ links_str = '\n'.join(list(get_links(ast)))
500
+ section = f"\n\n## Inheritance diagram\n\n```mermaid\nflowchart BT\n{nodes_str}\n{clicks_str}\n{links_str}\n```"
501
+ return section
502
+
412
503
 
413
504
  def get_handler(
414
505
  *,
@@ -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
@@ -62,7 +62,7 @@ class Class(CanonicalPathMixin, PathMixin, GriffeClass):
62
62
  for block in self._textmate.children
63
63
  if block.token == "meta.methods.matlab"
64
64
  ]:
65
- for method in block.children:
65
+ for method in [c for c in block.children if c.token == "meta.function.matlab"]:
66
66
  declaration = next(
67
67
  item
68
68
  for item in method.children
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mkdocstrings-matlab
3
- Version: 0.1.7
3
+ Version: 0.2.1
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
4
- mkdocstrings_handlers/matlab/models.py,sha256=n1l1Gr5Wq7nsrsP4PSePGfnGcln0NI-zSrkijGJBf80,5644
3
+ mkdocstrings_handlers/matlab/handler.py,sha256=k0tfPCQlAdK2Km48dOJWM8h857Ys5nQivJ28en994nw,20757
4
+ mkdocstrings_handlers/matlab/models.py,sha256=F8_kvZxEQbD0jwF-_6bO_ICK8T_DHsQv5e2LXY1rGOw,5694
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.1.dist-info/METADATA,sha256=hQxu7qSPf15QcDG7yMsjZdht6QWSjfpT7FmBZ-O23Hk,549
26
+ mkdocstrings_matlab-0.2.1.dist-info/WHEEL,sha256=fl6v0VwpzfGBVsGtkAkhILUlJxROXbA3HvRL6Fe3140,105
27
+ mkdocstrings_matlab-0.2.1.dist-info/licenses/LICENSE,sha256=14xA0OIYNpfmdeuq8-Yyqg7-3IJ4qhu3BJhknent-cY,1069
28
+ mkdocstrings_matlab-0.2.1.dist-info/RECORD,,