math-spec-mapping 0.3.17__tar.gz → 0.3.18__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. {math_spec_mapping-0.3.17/src/math_spec_mapping.egg-info → math_spec_mapping-0.3.18}/PKG-INFO +1 -1
  2. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/pyproject.toml +1 -1
  3. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Block.py +13 -3
  4. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/MathSpec.py +173 -0
  5. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Convenience/starter.py +142 -22
  6. math_spec_mapping-0.3.18/src/math_spec_mapping/Load/__init__.py +1 -0
  7. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/load.py +6 -1
  8. math_spec_mapping-0.3.18/src/math_spec_mapping/Load/spec_tree.py +71 -0
  9. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/markdown.py +96 -17
  10. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/__init__.py +1 -1
  11. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18/src/math_spec_mapping.egg-info}/PKG-INFO +1 -1
  12. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping.egg-info/SOURCES.txt +1 -0
  13. math_spec_mapping-0.3.17/src/math_spec_mapping/Load/__init__.py +0 -1
  14. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/LICENSE +0 -0
  15. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/README.md +0 -0
  16. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/setup.cfg +0 -0
  17. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/ActionTransmissionChannel.py +0 -0
  18. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/BoundaryAction.py +0 -0
  19. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/ControlAction.py +0 -0
  20. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Entity.py +0 -0
  21. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Mechanism.py +0 -0
  22. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Metric.py +0 -0
  23. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Parameter.py +0 -0
  24. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Policy.py +0 -0
  25. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Space.py +0 -0
  26. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/State.py +0 -0
  27. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/StateUpdateTransmissionChannel.py +0 -0
  28. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/StatefulMetric.py +0 -0
  29. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/Type.py +0 -0
  30. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Classes/__init__.py +0 -0
  31. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Convenience/__init__.py +0 -0
  32. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Convenience/documentation.py +0 -0
  33. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Convenience/github.py +0 -0
  34. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/action_transmission_channel.py +0 -0
  35. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/boundary_actions.py +0 -0
  36. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/control_actions.py +0 -0
  37. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/displays.py +0 -0
  38. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/entities.py +0 -0
  39. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/general.py +0 -0
  40. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/implementations.py +0 -0
  41. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/mechanism.py +0 -0
  42. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/metrics.py +0 -0
  43. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/parameters.py +0 -0
  44. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/policy.py +0 -0
  45. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/spaces.py +0 -0
  46. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/state_update_transmission_channels.py +0 -0
  47. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/stateful_metrics.py +0 -0
  48. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/states.py +0 -0
  49. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/type.py +0 -0
  50. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Load/wiring.py +0 -0
  51. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/__init__.py +0 -0
  52. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/boundary_actions.py +0 -0
  53. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/control_actions.py +0 -0
  54. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/general.py +0 -0
  55. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/html.py +0 -0
  56. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/mechanisms.py +0 -0
  57. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/node_map.py +0 -0
  58. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/parameters.py +0 -0
  59. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/policies.py +0 -0
  60. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/spaces.py +0 -0
  61. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/state.py +0 -0
  62. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/tables.py +0 -0
  63. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/Reports/wiring.py +0 -0
  64. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/schema.py +0 -0
  65. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping/schema.schema.json +0 -0
  66. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping.egg-info/dependency_links.txt +0 -0
  67. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping.egg-info/requires.txt +0 -0
  68. {math_spec_mapping-0.3.17 → math_spec_mapping-0.3.18}/src/math_spec_mapping.egg-info/top_level.txt +0 -0
@@ -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
@@ -3,7 +3,7 @@ requires = ["setuptools>=61.0"]
3
3
  build-backend = "setuptools.build_meta"
4
4
  [project]
5
5
  name = "math-spec-mapping"
6
- version = "0.3.17"
6
+ version = "0.3.18"
7
7
  authors = [
8
8
  { name="Sean McOwen", email="Sean@Block.Science" },
9
9
  ]
@@ -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
+ )
@@ -0,0 +1 @@
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
@@ -43,6 +43,7 @@ src/math_spec_mapping/Load/metrics.py
43
43
  src/math_spec_mapping/Load/parameters.py
44
44
  src/math_spec_mapping/Load/policy.py
45
45
  src/math_spec_mapping/Load/spaces.py
46
+ src/math_spec_mapping/Load/spec_tree.py
46
47
  src/math_spec_mapping/Load/state_update_transmission_channels.py
47
48
  src/math_spec_mapping/Load/stateful_metrics.py
48
49
  src/math_spec_mapping/Load/states.py
@@ -1 +0,0 @@
1
- from .load import load_from_json