math-spec-mapping 0.3.17__py3-none-any.whl → 0.3.18__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.
@@ -73,7 +73,7 @@ class Block:
73
73
  i += 1
74
74
  out = 'X{}["{}"]'.format(i, self.name)
75
75
  if self.block_type == "Mechanism":
76
- for u in self.updates:
76
+ for u in sorted(self.updates, key=lambda x: x[0].name + "-" + x[1].name):
77
77
  out += "\n"
78
78
  out += "X{} --> {}".format(
79
79
  i,
@@ -241,7 +241,9 @@ class ParallelBlock(Block):
241
241
  elif go_deep == False:
242
242
  i += 1
243
243
  out = 'X{}["{}"]'.format(i, self.name)
244
- for u in self.all_updates:
244
+ for u in sorted(
245
+ self.all_updates, key=lambda x: x[0].name + "-" + x[1].name
246
+ ):
245
247
  out += "\n"
246
248
  out += "X{} --> {}".format(
247
249
  i,
@@ -305,6 +307,7 @@ class ParallelBlock(Block):
305
307
  d = domain_map[ix1]
306
308
  if len(d) > 0:
307
309
  d_length = len(d)
310
+ d = ["<a href='{}' class=internal-link>{}</a>".format(x, x) for x in d]
308
311
  d = "\n".join(d)
309
312
  d = '"{}"'.format(d)
310
313
  out += "X{} --{}{}-> X{}".format(domain_i, d, "-" * d_length, ix1)
@@ -434,7 +437,10 @@ class StackBlock(Block):
434
437
  elif go_deep == False:
435
438
  i += 1
436
439
  out = 'X{}["{}"]'.format(i, self.name)
437
- for u in self.all_updates:
440
+
441
+ for u in sorted(
442
+ self.all_updates, key=lambda x: x[0].name + "-" + x[1].name
443
+ ):
438
444
  out += "\n"
439
445
  out += "X{} --> {}".format(
440
446
  i,
@@ -486,6 +492,10 @@ class StackBlock(Block):
486
492
  optional = global_optional
487
493
  if len(d) > 0:
488
494
  d_length = len(d)
495
+ d = [
496
+ "<a href='{}' class=internal-link>{}</a>".format(x, x)
497
+ for x in d
498
+ ]
489
499
  d = "\n".join(d)
490
500
  d = '"{}"'.format(d)
491
501
  if optional:
@@ -33,6 +33,7 @@ class MathSpec:
33
33
  ]
34
34
  self.stateful_metrics = ms_dict["Stateful Metrics"]
35
35
  self.wiring = ms_dict["Wiring"]
36
+ self.tree = None
36
37
  # self.blocks = ms_dict["Blocks"]
37
38
  self._load_blocks()
38
39
  self._load_components()
@@ -440,6 +441,178 @@ class MathSpec:
440
441
  us_names = [y.name for y in self._used_spaces]
441
442
  self._unused_spaces = [self.spaces[x] for x in self.spaces if x not in us_names]
442
443
 
444
+ def _add_spec_tree(self, tree):
445
+ self.tree = tree
446
+ for folder in [
447
+ "StatefulMetrics",
448
+ "Metrics",
449
+ "Mechanisms",
450
+ "BoundaryActions",
451
+ "Types",
452
+ "ControlActions",
453
+ "Displays",
454
+ "Spaces",
455
+ "State",
456
+ "Policies",
457
+ "Wiring",
458
+ "Parameters",
459
+ "Entities",
460
+ ]:
461
+ tree = self.tree[folder]
462
+ if folder == "StatefulMetrics":
463
+ for component in self.stateful_metrics_map:
464
+ if component not in tree:
465
+ print(
466
+ "Can't find component code source in {} for {}".format(
467
+ folder, component
468
+ )
469
+ )
470
+ self.stateful_metrics_map[component].source_code_location = None
471
+ else:
472
+ self.stateful_metrics_map[component].source_code_location = (
473
+ tree[component]
474
+ )
475
+ elif folder == "Metrics":
476
+ for component in self.metrics:
477
+ if component not in tree:
478
+ print(
479
+ "Can't find component code source in {} for {}".format(
480
+ folder, component
481
+ )
482
+ )
483
+ self.metrics[component].source_code_location = None
484
+ else:
485
+ self.metrics[component].source_code_location = tree[component]
486
+ elif folder == "Mechanisms":
487
+ for component in self.mechanisms:
488
+ if component not in tree:
489
+ print(
490
+ "Can't find component code source in {} for {}".format(
491
+ folder, component
492
+ )
493
+ )
494
+ self.mechanisms[component].source_code_location = None
495
+ else:
496
+ self.mechanisms[component].source_code_location = tree[
497
+ component
498
+ ]
499
+ elif folder == "BoundaryActions":
500
+ for component in self.boundary_actions:
501
+ if component not in tree:
502
+ print(
503
+ "Can't find component code source in {} for {}".format(
504
+ folder, component
505
+ )
506
+ )
507
+ self.boundary_actions[component].source_code_location = None
508
+ else:
509
+ self.boundary_actions[component].source_code_location = tree[
510
+ component
511
+ ]
512
+ elif folder == "Types":
513
+ for component in self.types:
514
+ if component not in tree:
515
+
516
+ print(
517
+ "Can't find component code source in {} for {}".format(
518
+ folder, component
519
+ )
520
+ )
521
+ self.types[component].source_code_location = None
522
+ else:
523
+ self.types[component].source_code_location = tree[component]
524
+ elif folder == "ControlActions":
525
+ for component in self.control_actions:
526
+ if component not in tree:
527
+ print(
528
+ "Can't find component code source in {} for {}".format(
529
+ folder, component
530
+ )
531
+ )
532
+ self.control_actions[component].source_code_location = None
533
+ else:
534
+ self.control_actions[component].source_code_location = tree[
535
+ component
536
+ ]
537
+ elif folder == "Displays":
538
+ print("Displays not implemented")
539
+ # keys = [x["name"] for x in ms.displays["Wiring"]]
540
+ elif folder == "Spaces":
541
+ for component in self.spaces:
542
+ if component in ["Terminating Space", "Empty Space"]:
543
+ self.spaces[component].source_code_location = None
544
+ continue
545
+ if component not in tree:
546
+ print(
547
+ "Can't find component code source in {} for {}".format(
548
+ folder, component
549
+ )
550
+ )
551
+ self.spaces[component].source_code_location = None
552
+ else:
553
+ self.spaces[component].source_code_location = tree[component]
554
+ elif folder == "State":
555
+ for component in self.state:
556
+ if component not in tree:
557
+ print(
558
+ "Can't find component code source in {} for {}".format(
559
+ folder, component
560
+ )
561
+ )
562
+ self.state[component].source_code_location = None
563
+ else:
564
+ self.state[component].source_code_location = tree[component]
565
+ elif folder == "Policies":
566
+ for component in self.policies:
567
+ if component not in tree:
568
+ print(
569
+ "Can't find component code source in {} for {}".format(
570
+ folder, component
571
+ )
572
+ )
573
+ self.policies[component].source_code_location = None
574
+ else:
575
+ self.policies[component].source_code_location = tree[component]
576
+ elif folder == "Wiring":
577
+ for component in self.wiring:
578
+ if component not in tree:
579
+ print(
580
+ "Can't find component code source in {} for {}".format(
581
+ folder, component
582
+ )
583
+ )
584
+ self.wiring[component].source_code_location = None
585
+ else:
586
+ self.wiring[component].source_code_location = tree[component]
587
+ elif folder == "Parameters":
588
+ for component in self.parameters.parameter_map:
589
+ if component not in tree:
590
+ print(
591
+ "Can't find component code source in {} for {}".format(
592
+ folder, component
593
+ )
594
+ )
595
+ self.parameters.parameter_map[
596
+ component
597
+ ].source_code_location = None
598
+ else:
599
+ self.parameters.parameter_map[
600
+ component
601
+ ].source_code_location = tree[component]
602
+ elif folder == "Entities":
603
+ for component in self.entities:
604
+ if component not in tree:
605
+ print(
606
+ "Can't find component code source in {} for {}".format(
607
+ folder, component
608
+ )
609
+ )
610
+ self.entities[component].source_code_location = None
611
+ else:
612
+ self.entities[component].source_code_location = tree[component]
613
+ else:
614
+ assert False
615
+
443
616
  def metaprogramming_python_types(self, model_directory, overwrite=False):
444
617
  path = model_directory + "/types.py"
445
618
  if not overwrite:
@@ -33,9 +33,9 @@ def remove_dummy_repo_components(path):
33
33
  if "__init__.py" in contents:
34
34
  with open(path2 + "/__init__.py", "r") as f:
35
35
  contents = f.read()
36
- contents = contents.replace("from .Dummy import metrics_x\n", "")
37
- contents = contents.replace("metrics.extend(metrics_x)\n", "")
38
- contents = contents.replace("metrics.extend(metrics_x)", "")
36
+ contents = contents.replace("from .Dummy import dummy_metrics\n", "")
37
+ contents = contents.replace("metrics.extend(dummy_metrics)\n", "")
38
+ contents = contents.replace("metrics.extend(dummy_metrics)", "")
39
39
  with open(path2 + "/__init__.py", "w") as f:
40
40
  f.write(contents)
41
41
 
@@ -46,17 +46,17 @@ def remove_dummy_repo_components(path):
46
46
  with open(path2 + "/wiring.py", "r") as f:
47
47
  contents = f.read()
48
48
 
49
- contents = contents.replace('"Dummy Boundary Wiring 2",\n', "")
50
- contents = contents.replace('"Dummy Boundary Wiring 2",', "")
51
- contents = contents.replace('"Dummy Boundary Wiring 2"', "")
49
+ contents = contents.replace('"DUMMY Length-1 Boundary Wiring",\n', "")
50
+ contents = contents.replace('"DUMMY Length-1 Boundary Wiring",', "")
51
+ contents = contents.replace('"DUMMY Length-1 Boundary Wiring"', "")
52
52
 
53
- contents = contents.replace('"Dummy Boundary Wiring",\n', "")
54
- contents = contents.replace('"Dummy Boundary Wiring",', "")
55
- contents = contents.replace('"Dummy Boundary Wiring"', "")
53
+ contents = contents.replace('"DUMMY Length-2 Boundary Wiring",\n', "")
54
+ contents = contents.replace('"DUMMY Length-2 Boundary Wiring",', "")
55
+ contents = contents.replace('"DUMMY Length-2 Boundary Wiring"', "")
56
56
 
57
- contents = contents.replace('"Dummy Control Wiring",\n', "")
58
- contents = contents.replace('"Dummy Control Wiring",', "")
59
- contents = contents.replace('"Dummy Control Wiring"', "")
57
+ contents = contents.replace('"DUMMY Control Wiring",\n', "")
58
+ contents = contents.replace('"DUMMY Control Wiring",', "")
59
+ contents = contents.replace('"DUMMY Control Wiring"', "")
60
60
 
61
61
  with open(path2 + "/wiring.py", "w") as f:
62
62
  f.write(contents)
@@ -188,6 +188,32 @@ def remove_dummy_repo_components(path):
188
188
  contents = contents.replace("dummy_state", "")
189
189
  with open(path2 + "/__init__.py", "w") as f:
190
190
  f.write(contents)
191
+ contents = os.listdir(path2)
192
+ if "Global.py" in contents:
193
+ with open(path2 + "/Global.py", "r") as f:
194
+ contents = f.read()
195
+ for x in [
196
+ """ {
197
+ "type": "DUMMY Integer Type",
198
+ "name": "Time",
199
+ "description": "The clock time",
200
+ "symbol": None,
201
+ "domain": None,
202
+ }""",
203
+ """ {
204
+ "type": "Entity Type",
205
+ "name": "Dummy",
206
+ "description": "The dummy entity",
207
+ "symbol": None,
208
+ "domain": None,
209
+ }""",
210
+ ]:
211
+ contents = contents.replace("{},\n".format(x), "")
212
+ contents = contents.replace("{}\n".format(x), "")
213
+ contents = contents.replace("{},".format(x), "")
214
+ contents = contents.replace("{}".format(x), "")
215
+ with open(path2 + "/Global.py", "w") as f:
216
+ f.write(contents)
191
217
 
192
218
  if "Parameters" in directory_folders:
193
219
  path2 = path + "/Parameters"
@@ -257,12 +283,15 @@ def remove_dummy_repo_components(path):
257
283
  if "types.py" in contents:
258
284
  with open(path2 + "/types.py", "r") as f:
259
285
  contents = f.read()
260
- contents = contents.replace(
261
- """ "DummyType1": str,
262
- "DummyType2": int,
263
- "DummyCompoundType": {"A": "Dummy Type 1", "B": "Dummy Type 2"},""",
264
- "",
265
- )
286
+ for x in [
287
+ '"DummyABCDEFType": str',
288
+ '"DummyIntegerType": int',
289
+ '"DummyDecimalType": float',
290
+ ]:
291
+ contents = contents.replace("{},\n".format(x), "")
292
+ contents = contents.replace("{}\n".format(x), "")
293
+ contents = contents.replace("{},".format(x), "")
294
+ contents = contents.replace("{}".format(x), "")
266
295
 
267
296
  with open(path2 + "/types.py", "w") as f:
268
297
  f.write(contents)
@@ -271,7 +300,7 @@ def remove_dummy_repo_components(path):
271
300
  path2 = path + "/TypeMappings"
272
301
  contents = os.listdir(path2)
273
302
 
274
- if "types.py" in contents:
303
+ if "types.jl" in contents:
275
304
  with open(path2 + "/types.jl", "r") as f:
276
305
  contents = f.read()
277
306
  contents = contents.replace(
@@ -295,11 +324,102 @@ end""",
295
324
  with open(path2 + "/types.ts", "r") as f:
296
325
  contents = f.read()
297
326
  contents = contents.replace(
298
- """type DummyType1 = string
299
- type DummyType2 = number
300
- type DummyCompoundType = {"A": DummyType1, "B": DummyType2}""",
327
+ """type DummyABCDEFType = string""",
328
+ "",
329
+ )
330
+ contents = contents.replace(
331
+ """type DummyIntegerType = number""",
332
+ "",
333
+ )
334
+ contents = contents.replace(
335
+ """type DummyDecimalType = number""",
301
336
  "",
302
337
  )
303
338
 
304
339
  with open(path2 + "/types.ts", "w") as f:
305
340
  f.write(contents)
341
+
342
+ remove_dummy_repo_implementations(path)
343
+
344
+
345
+ def remove_implementation_folder(path, folder, component_names, import_statement):
346
+ path = path + "/" + folder
347
+ contents = os.listdir(path)
348
+ if "Dummy.py" in contents:
349
+ os.remove(path + "/Dummy.py")
350
+ if "__init__.py" in contents:
351
+ with open(path + "/__init__.py", "r") as f:
352
+ contents = f.read()
353
+ contents = contents.replace(import_statement + "\n", "")
354
+ contents = contents.replace(import_statement, "")
355
+ for x in component_names:
356
+ contents = contents.replace("{},\n".format(x), "")
357
+ contents = contents.replace("{}\n".format(x), "")
358
+ contents = contents.replace("{},".format(x), "")
359
+ contents = contents.replace("{}".format(x), "")
360
+ with open(path + "/__init__.py", "w") as f:
361
+ f.write(contents)
362
+
363
+
364
+ def remove_dummy_repo_implementations(path):
365
+ path = path + "/Implementations/Python"
366
+ directory_folders = os.listdir(path)
367
+
368
+ if "BoundaryActions" in directory_folders:
369
+ remove_implementation_folder(
370
+ path,
371
+ "BoundaryActions",
372
+ [
373
+ '"Length-1 ABC Equal Weight Option": v1_dummy_boundary',
374
+ '"DUMMY Length-2 ABC Equal Weight Option": v1_dummy_boundary2',
375
+ '"DUMMY Length-2 ABC Equal Weight 2 Option": v2_dummy_boundary2',
376
+ ],
377
+ "from .Dummy import v1_dummy_boundary, v1_dummy_boundary2, v2_dummy_boundary2",
378
+ )
379
+ if "ControlActions" in directory_folders:
380
+ remove_implementation_folder(
381
+ path,
382
+ "ControlActions",
383
+ [
384
+ '"DUMMY Length-1 DEF Equal Weight Option": v1_dummy_control',
385
+ '"DUMMY Length-1 DEF D Probability Option": v2_dummy_control',
386
+ ],
387
+ "from .Dummy import v1_dummy_control, v2_dummy_control",
388
+ )
389
+ if "Policies" in directory_folders:
390
+ remove_implementation_folder(
391
+ path,
392
+ "Policies",
393
+ ['"DUMMY Letter Count Policy V1": dummy_letter_count_policy'],
394
+ "from .Dummy import dummy_letter_count_policy",
395
+ )
396
+ if "Mechanisms" in directory_folders:
397
+ remove_implementation_folder(
398
+ path,
399
+ "Mechanisms",
400
+ [
401
+ '"DUMMY Update Dummy Entity Mechanism": dummy_update_dummy_entity_mechanism',
402
+ '"DUMMY Increment Time Mechanism": dummy_increment_time_mechanism',
403
+ '"DUMMY Log Simulation Data Mechanism": dummy_log_simulation_data_mechanism',
404
+ ],
405
+ """from .Dummy import (
406
+ dummy_update_dummy_entity_mechanism,
407
+ dummy_increment_time_mechanism,
408
+ dummy_log_simulation_data_mechanism,
409
+ )""",
410
+ )
411
+
412
+ if "StatefulMetrics" in directory_folders:
413
+ remove_implementation_folder(
414
+ path,
415
+ "StatefulMetrics",
416
+ ['"DUMMY Nominal Length Stateful Metric": dummy_metric'],
417
+ """from .Dummy import dummy_metric""",
418
+ )
419
+ if "Metrics" in directory_folders:
420
+ remove_implementation_folder(
421
+ path,
422
+ "Metrics",
423
+ ['"DUMMY Multiplied Length Metric": dummy_multiplied_length_metric'],
424
+ """from .Dummy import dummy_multiplied_length_metric""",
425
+ )
@@ -1 +1 @@
1
- from .load import load_from_json
1
+ from .load import load_from_json, load_spec_tree
@@ -17,9 +17,10 @@ from .type import load_types, load_type_keys
17
17
  from .metrics import load_metrics
18
18
  from .displays import load_displays
19
19
  from .implementations import load_implementations
20
+ from .spec_tree import load_spec_tree
20
21
 
21
22
 
22
- def load_from_json(json: Dict) -> MathSpec:
23
+ def load_from_json(json: Dict, spec_path=None) -> MathSpec:
23
24
  """Function to load a math spec from a json format
24
25
 
25
26
  Args:
@@ -81,4 +82,8 @@ def load_from_json(json: Dict) -> MathSpec:
81
82
  for space in ms.spaces.values():
82
83
  space.domain_blocks = list(set(space.domain_blocks))
83
84
  space.codomain_blocks = list(set(space.codomain_blocks))
85
+
86
+ if spec_path:
87
+ tree = load_spec_tree(spec_path, ms)
88
+ ms._add_spec_tree(tree)
84
89
  return ms
@@ -0,0 +1,71 @@
1
+ import ast
2
+ import os
3
+
4
+
5
+ def load_spec_tree(path, ms):
6
+ tree = {}
7
+ for folder in [
8
+ "StatefulMetrics",
9
+ "Metrics",
10
+ "Mechanisms",
11
+ "BoundaryActions",
12
+ "Types",
13
+ "ControlActions",
14
+ "Displays",
15
+ "Spaces",
16
+ "State",
17
+ "Policies",
18
+ "Wiring",
19
+ "Parameters",
20
+ "Entities",
21
+ ]:
22
+ if folder == "StatefulMetrics":
23
+ keys = ms.get_all_stateful_metric_names()
24
+ elif folder == "Metrics":
25
+ keys = ms.metrics.keys()
26
+ elif folder == "Mechanisms":
27
+ keys = ms.mechanisms.keys()
28
+ elif folder == "BoundaryActions":
29
+ keys = ms.boundary_actions.keys()
30
+ elif folder == "Types":
31
+ keys = ms.types.keys()
32
+ elif folder == "ControlActions":
33
+ keys = ms.control_actions.keys()
34
+ elif folder == "Displays":
35
+ keys = [x["name"] for x in ms.displays["Wiring"]]
36
+ elif folder == "Spaces":
37
+ keys = ms.spaces.keys()
38
+ elif folder == "State":
39
+ keys = ms.state.keys()
40
+ elif folder == "Policies":
41
+ keys = ms.policies.keys()
42
+ elif folder == "Wiring":
43
+ keys = ms.wiring.keys()
44
+ elif folder == "Parameters":
45
+ keys = ms.parameters.all_parameters
46
+ elif folder == "Entities":
47
+ keys = ms.entities.keys()
48
+ else:
49
+ assert False
50
+ keys = list(keys)
51
+ tree[folder] = {}
52
+
53
+ init_path = path + "/" + folder + "/__init__.py"
54
+ with open(init_path, "r") as file:
55
+ tree2 = ast.parse(file.read(), filename=init_path)
56
+ imports = []
57
+ for node in ast.walk(tree2):
58
+ if isinstance(node, ast.Import):
59
+ for alias in node.names:
60
+ imports.append(alias.name)
61
+ assert False, "Not implemented for imports that are not import from"
62
+ elif isinstance(node, ast.ImportFrom):
63
+ if node.module:
64
+ for name in node.names:
65
+ file_path = "{}/{}/{}.py".format(path, folder, node.module)
66
+ with open(file_path, "r") as file2:
67
+ contents = file2.read()
68
+ for key in keys:
69
+ if key in contents:
70
+ tree[folder][key] = os.path.abspath(file_path)
71
+ return tree
@@ -3,7 +3,11 @@ from .state import write_state_section
3
3
  from inspect import signature, getsource, getfile
4
4
 
5
5
 
6
- def get_source_code(ms, component_type, implementation_name):
6
+ def get_source_code(
7
+ ms,
8
+ component_type,
9
+ implementation_name,
10
+ ):
7
11
  if implementation_name in ms.implementations["python"][component_type]:
8
12
  code = ms.implementations["python"][component_type][implementation_name]
9
13
  else:
@@ -55,10 +59,25 @@ def write_entity_markdown_report(ms, path, entity, add_metadata=True):
55
59
  out += "### [[{}]]".format(ac.name)
56
60
  out += "\n"
57
61
 
58
- with open("{}/Entities/{}.md".format(path, entity.name), "w") as f:
62
+ path = "{}/Entities/{}.md".format(path, entity.name)
63
+ out = write_source_code_block(entity, out, path)
64
+
65
+ with open(path, "w") as f:
59
66
  f.write(out)
60
67
 
61
68
 
69
+ def write_source_code_block(component, text, path):
70
+ file_path = component.source_code_location
71
+ if file_path:
72
+ file_path = os.path.relpath(file_path, path)
73
+ text += "## Spec Source Code Location\n\n"
74
+ text += "Spec Path (only works if vault is opened at level including the src folder): [{}]({})".format(
75
+ file_path, file_path
76
+ )
77
+ text += "\n\n"
78
+ return text
79
+
80
+
62
81
  def write_state_markdown_report(ms, path, state, add_metadata=True):
63
82
  state = ms.state[state]
64
83
  if "States" not in os.listdir(path):
@@ -83,7 +102,10 @@ def write_state_markdown_report(ms, path, state, add_metadata=True):
83
102
  out += "### [[{}]]".format(ba.name)
84
103
  out += "\n"
85
104
 
86
- with open("{}/States/{}.md".format(path, state.name), "w") as f:
105
+ path = "{}/States/{}.md".format(path, state.name)
106
+ out = write_source_code_block(state, out, path)
107
+
108
+ with open(path, "w") as f:
87
109
  f.write(out)
88
110
 
89
111
 
@@ -121,8 +143,11 @@ def write_types_markdown_report(ms, path, t, add_metadata=True):
121
143
  out += "## Notes"
122
144
  out += "\n\n"
123
145
  out += t.notes
146
+ out += "\n"
124
147
 
125
- with open("{}/Types/{}.md".format(path, t.name), "w") as f:
148
+ path = "{}/Types/{}.md".format(path, t.name)
149
+ out = write_source_code_block(t, out, path)
150
+ with open(path, "w") as f:
126
151
  f.write(out)
127
152
 
128
153
 
@@ -211,9 +236,10 @@ def write_boundary_action_markdown_report(ms, path, boundary_action, add_metadat
211
236
 
212
237
  out += "\n"
213
238
 
214
- with open(
215
- "{}/Boundary Actions/{}.md".format(path, boundary_action.label), "w"
216
- ) as f:
239
+ path = "{}/Boundary Actions/{}.md".format(path, boundary_action.label)
240
+ out = write_source_code_block(boundary_action, out, path)
241
+
242
+ with open(path, "w") as f:
217
243
  f.write(out)
218
244
 
219
245
 
@@ -302,7 +328,10 @@ def write_policy_markdown_report(ms, path, policy, add_metadata=True):
302
328
 
303
329
  out += "\n"
304
330
 
305
- with open("{}/Policies/{}.md".format(path, policy.label), "w") as f:
331
+ path = "{}/Policies/{}.md".format(path, policy.label)
332
+ out = write_source_code_block(policy, out, path)
333
+
334
+ with open(path, "w") as f:
306
335
  f.write(out)
307
336
 
308
337
 
@@ -381,7 +410,10 @@ def write_mechanism_markdown_report(ms, path, mechanism, add_metadata=True):
381
410
 
382
411
  out += "\n"
383
412
 
384
- with open("{}/Mechanisms/{}.md".format(path, mechanism.label), "w") as f:
413
+ path = "{}/Mechanisms/{}.md".format(path, mechanism.label)
414
+ out = write_source_code_block(mechanism, out, path)
415
+
416
+ with open(path, "w") as f:
385
417
  f.write(out)
386
418
 
387
419
 
@@ -415,19 +447,22 @@ def write_space_markdown_report(ms, path, space, add_metadata=True):
415
447
 
416
448
  out += "## Blocks with Space in Domain"
417
449
  out += "\n"
418
- for i, x in enumerate(space.domain_blocks):
450
+ for i, x in enumerate(sorted(space.domain_blocks, key=lambda x: x.name)):
419
451
  out += "{}. [[{}]]".format(i + 1, x.name)
420
452
  out += "\n"
421
453
  out += "\n"
422
454
 
423
455
  out += "## Blocks with Space in Codomain"
424
456
  out += "\n"
425
- for i, x in enumerate(space.codomain_blocks):
457
+ for i, x in enumerate(sorted(space.codomain_blocks, key=lambda x: x.name)):
426
458
  out += "{}. [[{}]]".format(i + 1, x.name)
427
459
  out += "\n"
428
460
  out += "\n"
429
461
 
430
- with open("{}/Spaces/{}.md".format(path, space.name), "w") as f:
462
+ path = "{}/Spaces/{}.md".format(path, space.name)
463
+ out = write_source_code_block(space, out, path)
464
+
465
+ with open(path, "w") as f:
431
466
  f.write(out)
432
467
 
433
468
 
@@ -510,7 +545,10 @@ def write_control_action_markdown_report(ms, path, control_action, add_metadata=
510
545
 
511
546
  out += "\n"
512
547
 
513
- with open("{}/Control Actions/{}.md".format(path, control_action.label), "w") as f:
548
+ path = "{}/Control Actions/{}.md".format(path, control_action.label)
549
+ out = write_source_code_block(control_action, out, path)
550
+
551
+ with open(path, "w") as f:
514
552
  f.write(out)
515
553
 
516
554
 
@@ -626,7 +664,10 @@ def write_wiring_markdown_report(ms, path, wiring, add_metadata=True):
626
664
  out += "\n"
627
665
  out += "\n"
628
666
 
629
- with open("{}/Wiring/{}.md".format(path, wiring.name), "w") as f:
667
+ path = "{}/Wiring/{}.md".format(path, wiring.name)
668
+ out = write_source_code_block(wiring, out, path)
669
+
670
+ with open(path, "w") as f:
630
671
  f.write(out)
631
672
 
632
673
 
@@ -651,7 +692,10 @@ def write_parameter_markdown_report(ms, path, parameter, add_metadata=True):
651
692
  out += "Domain: {}\n\n".format(param.domain)
652
693
  out += "Parameter Class: {}\n\n".format(param.parameter_class)
653
694
 
654
- with open("{}/Parameters/{}.md".format(path, param.name), "w") as f:
695
+ path = "{}/Parameters/{}.md".format(path, param.name)
696
+ out = write_source_code_block(param, out, path)
697
+
698
+ with open(path, "w") as f:
655
699
  f.write(out)
656
700
 
657
701
 
@@ -687,7 +731,25 @@ def write_stateful_metrics_markdown_report(ms, path, metric, add_metadata=True):
687
731
  out += "\n"
688
732
  out += "\n"
689
733
 
690
- with open("{}/Stateful Metrics/{}.md".format(path, metric.name), "w") as f:
734
+ temp = get_source_code(ms, "stateful_metrics", metric.name)
735
+ if temp:
736
+ source_code, file_path = temp
737
+ file_path = os.path.relpath(file_path, "{}/Stateful Metrics".format(path))
738
+ out += "## Python Implementation\n"
739
+ out += source_code
740
+ out += "\n"
741
+ out += "Implementation Path (only works if vault is opened at level including the src folder): [{}]({})".format(
742
+ file_path, file_path
743
+ )
744
+ out += "\n"
745
+
746
+ out += "\n"
747
+
748
+ path = "{}/Stateful Metrics/{}.md".format(path, metric.name)
749
+
750
+ out = write_source_code_block(metric, out, path)
751
+
752
+ with open(path, "w") as f:
691
753
  f.write(out)
692
754
 
693
755
 
@@ -742,7 +804,24 @@ def write_metrics_markdown_report(ms, path, metric, add_metadata=True):
742
804
  out += "{}. [[{}]]".format(i + 1, x.name)
743
805
  out += "\n"
744
806
 
745
- with open("{}/Metrics/{}.md".format(path, metric.name), "w") as f:
807
+ temp = get_source_code(ms, "metrics", metric.name)
808
+ if temp:
809
+ source_code, file_path = temp
810
+ file_path = os.path.relpath(file_path, "{}/Metrics".format(path))
811
+ out += "## Python Implementation\n"
812
+ out += source_code
813
+ out += "\n"
814
+ out += "Implementation Path (only works if vault is opened at level including the src folder): [{}]({})".format(
815
+ file_path, file_path
816
+ )
817
+ out += "\n"
818
+
819
+ out += "\n"
820
+
821
+ path = "{}/Metrics/{}.md".format(path, metric.name)
822
+ out = write_source_code_block(metric, out, path)
823
+
824
+ with open(path, "w") as f:
746
825
  f.write(out)
747
826
 
748
827
 
@@ -1,4 +1,4 @@
1
- from .Load import load_from_json
1
+ from .Load import load_from_json, load_spec_tree
2
2
  from .Reports import (
3
3
  create_action_chains_graph,
4
4
  write_out_boundary_actions,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: math-spec-mapping
3
- Version: 0.3.17
3
+ Version: 0.3.18
4
4
  Summary: A library for easy mapping of mathematical specifications.
5
5
  Author-email: Sean McOwen <Sean@Block.Science>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,12 +1,12 @@
1
- math_spec_mapping/__init__.py,sha256=uuz8qXGzsumq0W4-iAIw2w-xxyI10PhbNlGGQ9MxR60,1244
1
+ math_spec_mapping/__init__.py,sha256=7fGuxoSDYl61z0PZ_PzS6x5P8l174gOzobI9u0aoLVw,1260
2
2
  math_spec_mapping/schema.py,sha256=6mrRqzEnTTSXjb19xJ63MBp0KjKH0s7i6TfT4MkAY9k,233
3
3
  math_spec_mapping/schema.schema.json,sha256=hJP2TcV5WPFPmx4u_A5U1xtnpkE1LeYaTeYOXadTot0,30916
4
4
  math_spec_mapping/Classes/ActionTransmissionChannel.py,sha256=zWMo5QsgPh5WGIWXl-xOrZNMXYJXmK6Vejw1dQvi0og,246
5
- math_spec_mapping/Classes/Block.py,sha256=x5eYzuWp6C_n1tUVMxECpdYi4w_Tv0NLyxg0m8pHjMo,19602
5
+ math_spec_mapping/Classes/Block.py,sha256=D-UNvG7kYJa3iVgBH9KUaaldnFL4RVjCQQvrjjm00k4,20082
6
6
  math_spec_mapping/Classes/BoundaryAction.py,sha256=_rFvEZ4LNxmlM59js4SuQ9n5CgVmITw4YWKs0-q0r-4,560
7
7
  math_spec_mapping/Classes/ControlAction.py,sha256=4AzMSA8fbnUf-fGlvMJXHJFbz32G1h1QVWf2yzrXrLA,493
8
8
  math_spec_mapping/Classes/Entity.py,sha256=fA0-b128_OHHxfCg4pzqyQV083EYev1HlVpy86S5igg,1226
9
- math_spec_mapping/Classes/MathSpec.py,sha256=jOWfO5mx_7RjAy4SF9Faiw-tGEhL2HeyzV9lKk0pVDQ,43432
9
+ math_spec_mapping/Classes/MathSpec.py,sha256=GVyRz_a-afJcmj3W5fqqFYlX1YmxpmbjLFdLpFZGN60,51282
10
10
  math_spec_mapping/Classes/Mechanism.py,sha256=2sLm3wYBIeTQaMBcsJ9btqIWsbS895Ra8NY6Y9_G_Dg,379
11
11
  math_spec_mapping/Classes/Metric.py,sha256=iQhH4g8Z60QlM22nPX9ytGmidOsZSiSs0KjqwmsScwU,636
12
12
  math_spec_mapping/Classes/Parameter.py,sha256=ZuJ_w0sChvRElJ4sOnXZ2EV4Ell2xXFulKLjVOpgz2E,1237
@@ -20,8 +20,8 @@ math_spec_mapping/Classes/__init__.py,sha256=0zxgOqns_9JybD74HKMVh6aw8ij8WVbfQ4Q
20
20
  math_spec_mapping/Convenience/__init__.py,sha256=BEZr1rXohKAknOa3wjNVx3EvSVxDcfftJsvtSw5mvmQ,264
21
21
  math_spec_mapping/Convenience/documentation.py,sha256=1ziWVJznbCUxeAAt03nAdEYtMlXNo5TeedHfgs0vSBU,1625
22
22
  math_spec_mapping/Convenience/github.py,sha256=Wddr1FCxcIxaFeiKyvx3mvVDbzjcgTxs4rU8ulc4qXk,3539
23
- math_spec_mapping/Convenience/starter.py,sha256=9dBKU3EHscut2wA6Nx1XUmehrFIdr4dCjP9V1BbTF6s,12567
24
- math_spec_mapping/Load/__init__.py,sha256=_ga5nHi7U5rY5lCF36_XI9Qmybq4P8R4m5I5mmjLBk8,33
23
+ math_spec_mapping/Convenience/starter.py,sha256=dD1R9wcVFZV-BCTflxNkR6Ay6NF1TlVBdIaWmbJwMGE,17379
24
+ math_spec_mapping/Load/__init__.py,sha256=QfHMLatZAKqj4up-LkDL_r42tO7Mo_-qdqPQYLYY5l0,49
25
25
  math_spec_mapping/Load/action_transmission_channel.py,sha256=9Wer7g2s5SSOcUYuZ0PqSKUVVnW3EvGQJZNXJTwW__0,2561
26
26
  math_spec_mapping/Load/boundary_actions.py,sha256=cDN0pjkkWfYY3HHmgSrD__-weGD4DXElnG8w1pRc5Lc,2933
27
27
  math_spec_mapping/Load/control_actions.py,sha256=Y9LeEJuVj2OwxdTfnHZ57UV48j6PYCfyQWux4uXp1Mo,2371
@@ -29,12 +29,13 @@ math_spec_mapping/Load/displays.py,sha256=uQvs0Jhp8-9SXGex8SG3ibxHJu7ahAV3xLeBFb
29
29
  math_spec_mapping/Load/entities.py,sha256=Ds7VQY_govWEn1vSHYVrLa8IadSNyOQzaCK18JPYPKk,1289
30
30
  math_spec_mapping/Load/general.py,sha256=2q6aGKxXhebiHHTZhtACvM4nWIkTben0o5rXuvfv2Vw,4463
31
31
  math_spec_mapping/Load/implementations.py,sha256=a8YvumnyQvrnCo-o52Rv4yU8D7nmkMrV1iIA15fr6Bw,490
32
- math_spec_mapping/Load/load.py,sha256=oC-CuqbVqqhWw0kK7iiNKexAB_djgVNbjXSQfTsj2FA,2647
32
+ math_spec_mapping/Load/load.py,sha256=Cm1IP_jIzWNGFVPcb1OOfQQYSNgyIfUdT--v1D1dkKE,2797
33
33
  math_spec_mapping/Load/mechanism.py,sha256=VRjkR2McsSJh2oq8n9JkeewirdlVjPRA-T5SRSKWPPQ,2293
34
34
  math_spec_mapping/Load/metrics.py,sha256=CcVM0_aN-aPnH5_AyEKzFCJGPbgMb0brw5nECsdNVeU,3936
35
35
  math_spec_mapping/Load/parameters.py,sha256=W4utm7to3s2fo4z3XgLH0TM1agaIad1qfM2I-lLMua4,1393
36
36
  math_spec_mapping/Load/policy.py,sha256=QTIcslHKgdYjjG69cqkJbW20CPvEL-B8R5u51rd2Puo,2697
37
37
  math_spec_mapping/Load/spaces.py,sha256=5nJto38BVMED5KuMXOqavYj8gcSTKiNSTdMOOp5ThTA,1186
38
+ math_spec_mapping/Load/spec_tree.py,sha256=4If9twlH30tDFxmZSRkwrRnfLlG_dTWOHbzvVrn42Bg,2481
38
39
  math_spec_mapping/Load/state_update_transmission_channels.py,sha256=FJWp5n4HdtHAfof5BUQ6BnRakljatL2h8dWCapaVSc0,2238
39
40
  math_spec_mapping/Load/stateful_metrics.py,sha256=3Lq1ZGMaDd5OcGeqR2p5c_znkYw7ETTNPFjUVdZAHKk,2384
40
41
  math_spec_mapping/Load/states.py,sha256=3YurI7eTNkN6nrXRFVrc58wH0VfM22XOuWE07HVpR7Y,1365
@@ -45,7 +46,7 @@ math_spec_mapping/Reports/boundary_actions.py,sha256=45BPp4QjWdD-3E9ZWwqgj_nI2-Y
45
46
  math_spec_mapping/Reports/control_actions.py,sha256=NksekZKIPFSIkubttFstKFthc5AU9B9PWRLSl9j1wWs,1216
46
47
  math_spec_mapping/Reports/general.py,sha256=WOOn6Wlb8M4fsdN49FlKLwOka6vJPQ9aCUy88TL2ki0,1610
47
48
  math_spec_mapping/Reports/html.py,sha256=RpyQQON8pDnMmfcyxOsm8UAD5Ad8VKnnW-OyOarTmzA,9711
48
- math_spec_mapping/Reports/markdown.py,sha256=DG0DmzE6Pas5dLLjbSnGa0xmWSFz0IGLa0sT_1MgYvI,27804
49
+ math_spec_mapping/Reports/markdown.py,sha256=ErQYnMtl1yxvFVS1Y4AuhifQYEmEab-75HN5kVRFAMo,30114
49
50
  math_spec_mapping/Reports/mechanisms.py,sha256=d2Rxt3JBYvqAOAYUynl0buYVoXEHrO8EGq7GK6hK8NA,1322
50
51
  math_spec_mapping/Reports/node_map.py,sha256=FdSMDQG16NX6n9sZcH-T5xwsvgjrV9OqBHc9J_VlNK0,3129
51
52
  math_spec_mapping/Reports/parameters.py,sha256=-ucL71lolqU0xvV7yb0sXl4pFMRl5tXNWdoBfUjLOaQ,1944
@@ -54,8 +55,8 @@ math_spec_mapping/Reports/spaces.py,sha256=-76hR5wQBv4lsG000ypBJ-OprjsNjI-rNRMYd
54
55
  math_spec_mapping/Reports/state.py,sha256=QYeCvX5cHeZBrbvMeDsTqJcUDTuDFJSLvPbasjLspk8,3643
55
56
  math_spec_mapping/Reports/tables.py,sha256=O0CNuqh3LMECq5uLjBOoxMUk5hUvkUK660FNnwWUxDY,1505
56
57
  math_spec_mapping/Reports/wiring.py,sha256=u9SvKWy6T-WJUEgFI6-zgZanoOaTTs_2YwmEceDLsV8,1618
57
- math_spec_mapping-0.3.17.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
58
- math_spec_mapping-0.3.17.dist-info/METADATA,sha256=niURiLlRa8ejIvpDjiOcvg1jFeanlxz-76-Mb1joMsU,6498
59
- math_spec_mapping-0.3.17.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
60
- math_spec_mapping-0.3.17.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
61
- math_spec_mapping-0.3.17.dist-info/RECORD,,
58
+ math_spec_mapping-0.3.18.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
59
+ math_spec_mapping-0.3.18.dist-info/METADATA,sha256=hQL3NZ1h1AWYGEQvanepfsOHymyzJbwks-puwjMI0Ho,6498
60
+ math_spec_mapping-0.3.18.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
61
+ math_spec_mapping-0.3.18.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
62
+ math_spec_mapping-0.3.18.dist-info/RECORD,,