math-spec-mapping 0.3.17__py3-none-any.whl → 0.3.19__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,
@@ -172,6 +172,9 @@ class Block:
172
172
  out = list(set(out))
173
173
  return out
174
174
 
175
+ def __repr__(self):
176
+ return "<{}>".format(self.name)
177
+
175
178
 
176
179
  class ParallelBlock(Block):
177
180
  def __init__(self, data: Dict):
@@ -241,7 +244,9 @@ class ParallelBlock(Block):
241
244
  elif go_deep == False:
242
245
  i += 1
243
246
  out = 'X{}["{}"]'.format(i, self.name)
244
- for u in self.all_updates:
247
+ for u in sorted(
248
+ self.all_updates, key=lambda x: x[0].name + "-" + x[1].name
249
+ ):
245
250
  out += "\n"
246
251
  out += "X{} --> {}".format(
247
252
  i,
@@ -305,6 +310,7 @@ class ParallelBlock(Block):
305
310
  d = domain_map[ix1]
306
311
  if len(d) > 0:
307
312
  d_length = len(d)
313
+ d = ["<a href='{}' class=internal-link>{}</a>".format(x, x) for x in d]
308
314
  d = "\n".join(d)
309
315
  d = '"{}"'.format(d)
310
316
  out += "X{} --{}{}-> X{}".format(domain_i, d, "-" * d_length, ix1)
@@ -434,7 +440,10 @@ class StackBlock(Block):
434
440
  elif go_deep == False:
435
441
  i += 1
436
442
  out = 'X{}["{}"]'.format(i, self.name)
437
- for u in self.all_updates:
443
+
444
+ for u in sorted(
445
+ self.all_updates, key=lambda x: x[0].name + "-" + x[1].name
446
+ ):
438
447
  out += "\n"
439
448
  out += "X{} --> {}".format(
440
449
  i,
@@ -486,6 +495,10 @@ class StackBlock(Block):
486
495
  optional = global_optional
487
496
  if len(d) > 0:
488
497
  d_length = len(d)
498
+ d = [
499
+ "<a href='{}' class=internal-link>{}</a>".format(x, x)
500
+ for x in d
501
+ ]
489
502
  d = "\n".join(d)
490
503
  d = '"{}"'.format(d)
491
504
  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()
@@ -438,7 +439,195 @@ class MathSpec:
438
439
 
439
440
  self._used_spaces = list(set().union(*self._used_spaces))
440
441
  us_names = [y.name for y in self._used_spaces]
441
- self._unused_spaces = [self.spaces[x] for x in self.spaces if x not in us_names]
442
+ self._unused_spaces = [
443
+ self.spaces[x]
444
+ for x in self.spaces
445
+ if x not in us_names and x not in ["Terminating Space", "Empty Space"]
446
+ ]
447
+
448
+ if len(self._unused_spaces) > 0:
449
+ print("The following spaces are not used: {}".format(self._unused_spaces))
450
+
451
+ def _add_spec_tree(self, tree):
452
+ self.tree = tree
453
+ for folder in [
454
+ "StatefulMetrics",
455
+ "Metrics",
456
+ "Mechanisms",
457
+ "BoundaryActions",
458
+ "Types",
459
+ "ControlActions",
460
+ "Displays",
461
+ "Spaces",
462
+ "State",
463
+ "Policies",
464
+ "Wiring",
465
+ "Parameters",
466
+ "Entities",
467
+ ]:
468
+ tree = self.tree[folder]
469
+ if folder == "StatefulMetrics":
470
+ for component in self.stateful_metrics_map:
471
+ if component not in tree:
472
+ print(
473
+ "Can't find component code source in {} for {}".format(
474
+ folder, component
475
+ )
476
+ )
477
+ self.stateful_metrics_map[component].source_code_location = None
478
+ else:
479
+ self.stateful_metrics_map[component].source_code_location = (
480
+ tree[component]
481
+ )
482
+ elif folder == "Metrics":
483
+ for component in self.metrics:
484
+ if component not in tree:
485
+ print(
486
+ "Can't find component code source in {} for {}".format(
487
+ folder, component
488
+ )
489
+ )
490
+ self.metrics[component].source_code_location = None
491
+ else:
492
+ self.metrics[component].source_code_location = tree[component]
493
+ elif folder == "Mechanisms":
494
+ for component in self.mechanisms:
495
+ if component not in tree:
496
+ print(
497
+ "Can't find component code source in {} for {}".format(
498
+ folder, component
499
+ )
500
+ )
501
+ self.mechanisms[component].source_code_location = None
502
+ else:
503
+ self.mechanisms[component].source_code_location = tree[
504
+ component
505
+ ]
506
+ elif folder == "BoundaryActions":
507
+ for component in self.boundary_actions:
508
+ if component not in tree:
509
+ print(
510
+ "Can't find component code source in {} for {}".format(
511
+ folder, component
512
+ )
513
+ )
514
+ self.boundary_actions[component].source_code_location = None
515
+ else:
516
+ self.boundary_actions[component].source_code_location = tree[
517
+ component
518
+ ]
519
+ elif folder == "Types":
520
+ for component in self.types:
521
+ if component not in tree:
522
+
523
+ print(
524
+ "Can't find component code source in {} for {}".format(
525
+ folder, component
526
+ )
527
+ )
528
+ self.types[component].source_code_location = None
529
+ else:
530
+ self.types[component].source_code_location = tree[component]
531
+ elif folder == "ControlActions":
532
+ for component in self.control_actions:
533
+ if component not in tree:
534
+ print(
535
+ "Can't find component code source in {} for {}".format(
536
+ folder, component
537
+ )
538
+ )
539
+ self.control_actions[component].source_code_location = None
540
+ else:
541
+ self.control_actions[component].source_code_location = tree[
542
+ component
543
+ ]
544
+ elif folder == "Displays":
545
+
546
+ for component in self.displays["Wiring"]:
547
+ if component["name"] not in tree:
548
+ print(
549
+ "Can't find component code source in {} for {}".format(
550
+ folder, component["name"]
551
+ )
552
+ )
553
+ component["Source Code Location"] = None
554
+ else:
555
+ component["Source Code Location"] = tree[component["name"]]
556
+ elif folder == "Spaces":
557
+ for component in self.spaces:
558
+ if component in ["Terminating Space", "Empty Space"]:
559
+ self.spaces[component].source_code_location = None
560
+ continue
561
+ if component not in tree:
562
+ print(
563
+ "Can't find component code source in {} for {}".format(
564
+ folder, component
565
+ )
566
+ )
567
+ self.spaces[component].source_code_location = None
568
+ else:
569
+ self.spaces[component].source_code_location = tree[component]
570
+ elif folder == "State":
571
+ for component in self.state:
572
+ if component not in tree:
573
+ print(
574
+ "Can't find component code source in {} for {}".format(
575
+ folder, component
576
+ )
577
+ )
578
+ self.state[component].source_code_location = None
579
+ else:
580
+ self.state[component].source_code_location = tree[component]
581
+ elif folder == "Policies":
582
+ for component in self.policies:
583
+ if component not in tree:
584
+ print(
585
+ "Can't find component code source in {} for {}".format(
586
+ folder, component
587
+ )
588
+ )
589
+ self.policies[component].source_code_location = None
590
+ else:
591
+ self.policies[component].source_code_location = tree[component]
592
+ elif folder == "Wiring":
593
+ for component in self.wiring:
594
+ if component not in tree:
595
+ print(
596
+ "Can't find component code source in {} for {}".format(
597
+ folder, component
598
+ )
599
+ )
600
+ self.wiring[component].source_code_location = None
601
+ else:
602
+ self.wiring[component].source_code_location = tree[component]
603
+ elif folder == "Parameters":
604
+ for component in self.parameters.parameter_map:
605
+ if component not in tree:
606
+ print(
607
+ "Can't find component code source in {} for {}".format(
608
+ folder, component
609
+ )
610
+ )
611
+ self.parameters.parameter_map[
612
+ component
613
+ ].source_code_location = None
614
+ else:
615
+ self.parameters.parameter_map[
616
+ component
617
+ ].source_code_location = tree[component]
618
+ elif folder == "Entities":
619
+ for component in self.entities:
620
+ if component not in tree:
621
+ print(
622
+ "Can't find component code source in {} for {}".format(
623
+ folder, component
624
+ )
625
+ )
626
+ self.entities[component].source_code_location = None
627
+ else:
628
+ self.entities[component].source_code_location = tree[component]
629
+ else:
630
+ assert False
442
631
 
443
632
  def metaprogramming_python_types(self, model_directory, overwrite=False):
444
633
  path = model_directory + "/types.py"
@@ -837,6 +1026,14 @@ class MathSpecImplementation:
837
1026
  )
838
1027
  else:
839
1028
  control_actions[ca.name] = opt.implementations["python"]
1029
+
1030
+ for opt_i in [x for x in ca.control_action_options if x != opt]:
1031
+ if "python" not in opt_i.implementations:
1032
+ print(
1033
+ "No python implementation for {} / {}. To fix this, go to Implementations/Python/ControlActions and add {}".format(
1034
+ ca.name, opt_i.name, opt_i.name
1035
+ )
1036
+ )
840
1037
  return control_actions
841
1038
 
842
1039
  def load_boundary_actions(self):
@@ -868,6 +1065,14 @@ class MathSpecImplementation:
868
1065
  )
869
1066
  else:
870
1067
  boundary_actions[ba.name] = opt.implementations["python"]
1068
+
1069
+ for opt_i in [x for x in ba.boundary_action_options if x != opt]:
1070
+ if "python" not in opt_i.implementations:
1071
+ print(
1072
+ "No python implementation for {} / {}. To fix this, go to Implementations/Python/BoundaryActions and add {}".format(
1073
+ ba.name, opt_i.name, opt_i.name
1074
+ )
1075
+ )
871
1076
  return boundary_actions
872
1077
 
873
1078
  def load_mechanisms(self):
@@ -964,6 +1169,14 @@ class MathSpecImplementation:
964
1169
  )
965
1170
  else:
966
1171
  policies[p.name] = opt.implementations["python"]
1172
+ for opt_i in [x for x in p.policy_options if x != opt]:
1173
+ if "python" not in opt_i.implementations:
1174
+ print(
1175
+ "No python implementation for {} / {}. To fix this, go to Implementations/Python/Policies and add {}".format(
1176
+ p.name, opt_i.name, opt_i.name
1177
+ )
1178
+ )
1179
+
967
1180
  return policies
968
1181
 
969
1182
  def load_stateful_metrics(self):
@@ -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
@@ -50,8 +50,14 @@ def convert_action_transmission_channel(
50
50
  data["target"] = ms["Mechanisms"][target]
51
51
 
52
52
  # Add in called by and called here with origin and target
53
- data["origin"].calls.append((data["target"], data["optional"], data["space"]))
54
- data["target"].called_by.append((data["origin"], data["optional"], data["space"]))
53
+ if (data["target"], data["optional"], data["space"]) not in data["origin"].calls:
54
+ data["origin"].calls.append((data["target"], data["optional"], data["space"]))
55
+ if (data["origin"], data["optional"], data["space"]) not in data[
56
+ "target"
57
+ ].called_by:
58
+ data["target"].called_by.append(
59
+ (data["origin"], data["optional"], data["space"])
60
+ )
55
61
 
56
62
  # Build the action transmission channel object
57
63
  return ActionTransmissionChannel(data)
@@ -1,6 +1,6 @@
1
1
  from typing import Dict
2
2
  from ..Classes import BoundaryAction, BoundaryActionOption
3
- from .general import check_json_keys
3
+ from .general import check_json_keys, check_domain_codomain_spaces
4
4
 
5
5
 
6
6
  def convert_boundary_action(data: Dict, ms: Dict) -> BoundaryAction:
@@ -24,6 +24,8 @@ def convert_boundary_action(data: Dict, ms: Dict) -> BoundaryAction:
24
24
  data["name"]
25
25
  )
26
26
 
27
+ check_domain_codomain_spaces(data, ms)
28
+
27
29
  if len(data["codomain"]) == 0:
28
30
  data["codomain"] = ("Empty Space",)
29
31
 
@@ -1,6 +1,6 @@
1
1
  from typing import Dict
2
2
  from ..Classes import ControlAction, ControlActionOption
3
- from .general import check_json_keys
3
+ from .general import check_json_keys, check_domain_codomain_spaces
4
4
 
5
5
 
6
6
  def convert_control_action(data: Dict, ms: Dict) -> ControlAction:
@@ -25,6 +25,8 @@ def convert_control_action(data: Dict, ms: Dict) -> ControlAction:
25
25
  data["name"]
26
26
  )
27
27
 
28
+ check_domain_codomain_spaces(data, ms)
29
+
28
30
  if len(data["codomain"]) == 0:
29
31
  data["codomain"] = ("Empty Space",)
30
32
 
@@ -159,3 +159,12 @@ def check_json_keys(json: Dict, check_set_key: str) -> None:
159
159
 
160
160
  def validate_json_schema(json):
161
161
  validate(json, schema)
162
+
163
+
164
+ def check_domain_codomain_spaces(json: Dict, ms) -> None:
165
+ if "domain" in json:
166
+ for key in json["domain"]:
167
+ assert key in ms["Spaces"], "{} not in spaces".format(key)
168
+ if "codomain" in json:
169
+ for key in json["codomain"]:
170
+ assert key in ms["Spaces"], "{} not in spaces".format(key)
@@ -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
@@ -1,6 +1,6 @@
1
1
  from typing import Dict
2
2
  from ..Classes import Mechanism
3
- from .general import check_json_keys
3
+ from .general import check_json_keys, check_domain_codomain_spaces
4
4
 
5
5
 
6
6
  def convert_mechanism(data: Dict, ms: Dict) -> Mechanism:
@@ -26,6 +26,8 @@ def convert_mechanism(data: Dict, ms: Dict) -> Mechanism:
26
26
  if len(data["domain"]) == 0:
27
27
  data["domain"] = ("Empty Space",)
28
28
 
29
+ check_domain_codomain_spaces(data, ms)
30
+
29
31
  # Copy
30
32
  data = data.copy()
31
33
 
@@ -2,7 +2,7 @@ from typing import Dict
2
2
  from ..Classes import Policy, PolicyOption
3
3
 
4
4
 
5
- from .general import check_json_keys
5
+ from .general import check_json_keys, check_domain_codomain_spaces
6
6
 
7
7
 
8
8
  def convert_policy_options(data: Dict, ms) -> PolicyOption:
@@ -58,6 +58,7 @@ def convert_policy(data: Dict, ms: Dict) -> Policy:
58
58
  assert type(data["domain"]) == tuple, "{} domain is not a tuple".format(
59
59
  data["name"]
60
60
  )
61
+ check_domain_codomain_spaces(data, ms)
61
62
 
62
63
  if len(data["codomain"]) == 0:
63
64
  data["codomain"] = ("Empty Space",)
@@ -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
@@ -40,6 +40,12 @@ def convert_stateful_metric(ms, data: Dict) -> StatefulMetricSet:
40
40
  x[1]
41
41
  )
42
42
 
43
+ assert (
44
+ var["type"] in ms["Types"]
45
+ ), "{} type referenced by {} is not present in math spec".format(
46
+ var["type"], var["name"]
47
+ )
48
+
43
49
  var["implementations"] = {}
44
50
  if "python" in ms["Implementations"]:
45
51
  if "stateful_metrics" in ms["Implementations"]["python"]:
@@ -169,6 +169,13 @@ cssclasses:
169
169
  else:
170
170
  out += symbol3 + "{}".format(var.name) + "\n"
171
171
 
172
+ out += symbol1 + "**Metrics**\n"
173
+ for name in ms.metrics.keys():
174
+ if linking:
175
+ out += symbol2 + "[[{}]]".format(name) + "\n"
176
+ else:
177
+ out += symbol2 + "{}".format(name) + "\n"
178
+
172
179
  out += symbol1 + "**Types**\n"
173
180
  for name in ms.types.keys():
174
181
  if linking:
@@ -221,6 +228,12 @@ cssclasses:
221
228
  out += symbol2 + "[[{}]]".format(name) + "\n"
222
229
  else:
223
230
  out += symbol2 + name + "\n"
231
+ out += symbol1 + "**Wirings**\n"
232
+ for name in ms.wiring.keys():
233
+ if linking:
234
+ out += symbol2 + "[[{}]]".format(name) + "\n"
235
+ else:
236
+ out += symbol2 + name + "\n"
224
237
 
225
238
  if add_tabbing:
226
239
  out = out.split("\n")
@@ -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,28 @@ 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
+ if hasattr(component, "source_code_location"):
71
+ file_path = component.source_code_location
72
+ else:
73
+ file_path = component["Source Code Location"]
74
+ if file_path:
75
+ file_path = os.path.relpath(file_path, path)
76
+ text += "## Spec Source Code Location\n\n"
77
+ text += "Spec Path (only works if vault is opened at level including the src folder): [{}]({})".format(
78
+ file_path, file_path
79
+ )
80
+ text += "\n\n"
81
+ return text
82
+
83
+
62
84
  def write_state_markdown_report(ms, path, state, add_metadata=True):
63
85
  state = ms.state[state]
64
86
  if "States" not in os.listdir(path):
@@ -83,7 +105,10 @@ def write_state_markdown_report(ms, path, state, add_metadata=True):
83
105
  out += "### [[{}]]".format(ba.name)
84
106
  out += "\n"
85
107
 
86
- with open("{}/States/{}.md".format(path, state.name), "w") as f:
108
+ path = "{}/States/{}.md".format(path, state.name)
109
+ out = write_source_code_block(state, out, path)
110
+
111
+ with open(path, "w") as f:
87
112
  f.write(out)
88
113
 
89
114
 
@@ -121,8 +146,11 @@ def write_types_markdown_report(ms, path, t, add_metadata=True):
121
146
  out += "## Notes"
122
147
  out += "\n\n"
123
148
  out += t.notes
149
+ out += "\n"
124
150
 
125
- with open("{}/Types/{}.md".format(path, t.name), "w") as f:
151
+ path = "{}/Types/{}.md".format(path, t.name)
152
+ out = write_source_code_block(t, out, path)
153
+ with open(path, "w") as f:
126
154
  f.write(out)
127
155
 
128
156
 
@@ -211,9 +239,10 @@ def write_boundary_action_markdown_report(ms, path, boundary_action, add_metadat
211
239
 
212
240
  out += "\n"
213
241
 
214
- with open(
215
- "{}/Boundary Actions/{}.md".format(path, boundary_action.label), "w"
216
- ) as f:
242
+ path = "{}/Boundary Actions/{}.md".format(path, boundary_action.label)
243
+ out = write_source_code_block(boundary_action, out, path)
244
+
245
+ with open(path, "w") as f:
217
246
  f.write(out)
218
247
 
219
248
 
@@ -302,7 +331,10 @@ def write_policy_markdown_report(ms, path, policy, add_metadata=True):
302
331
 
303
332
  out += "\n"
304
333
 
305
- with open("{}/Policies/{}.md".format(path, policy.label), "w") as f:
334
+ path = "{}/Policies/{}.md".format(path, policy.label)
335
+ out = write_source_code_block(policy, out, path)
336
+
337
+ with open(path, "w") as f:
306
338
  f.write(out)
307
339
 
308
340
 
@@ -381,7 +413,10 @@ def write_mechanism_markdown_report(ms, path, mechanism, add_metadata=True):
381
413
 
382
414
  out += "\n"
383
415
 
384
- with open("{}/Mechanisms/{}.md".format(path, mechanism.label), "w") as f:
416
+ path = "{}/Mechanisms/{}.md".format(path, mechanism.label)
417
+ out = write_source_code_block(mechanism, out, path)
418
+
419
+ with open(path, "w") as f:
385
420
  f.write(out)
386
421
 
387
422
 
@@ -415,19 +450,22 @@ def write_space_markdown_report(ms, path, space, add_metadata=True):
415
450
 
416
451
  out += "## Blocks with Space in Domain"
417
452
  out += "\n"
418
- for i, x in enumerate(space.domain_blocks):
453
+ for i, x in enumerate(sorted(space.domain_blocks, key=lambda x: x.name)):
419
454
  out += "{}. [[{}]]".format(i + 1, x.name)
420
455
  out += "\n"
421
456
  out += "\n"
422
457
 
423
458
  out += "## Blocks with Space in Codomain"
424
459
  out += "\n"
425
- for i, x in enumerate(space.codomain_blocks):
460
+ for i, x in enumerate(sorted(space.codomain_blocks, key=lambda x: x.name)):
426
461
  out += "{}. [[{}]]".format(i + 1, x.name)
427
462
  out += "\n"
428
463
  out += "\n"
429
464
 
430
- with open("{}/Spaces/{}.md".format(path, space.name), "w") as f:
465
+ path = "{}/Spaces/{}.md".format(path, space.name)
466
+ out = write_source_code_block(space, out, path)
467
+
468
+ with open(path, "w") as f:
431
469
  f.write(out)
432
470
 
433
471
 
@@ -510,7 +548,10 @@ def write_control_action_markdown_report(ms, path, control_action, add_metadata=
510
548
 
511
549
  out += "\n"
512
550
 
513
- with open("{}/Control Actions/{}.md".format(path, control_action.label), "w") as f:
551
+ path = "{}/Control Actions/{}.md".format(path, control_action.label)
552
+ out = write_source_code_block(control_action, out, path)
553
+
554
+ with open(path, "w") as f:
514
555
  f.write(out)
515
556
 
516
557
 
@@ -626,7 +667,10 @@ def write_wiring_markdown_report(ms, path, wiring, add_metadata=True):
626
667
  out += "\n"
627
668
  out += "\n"
628
669
 
629
- with open("{}/Wiring/{}.md".format(path, wiring.name), "w") as f:
670
+ path = "{}/Wiring/{}.md".format(path, wiring.name)
671
+ out = write_source_code_block(wiring, out, path)
672
+
673
+ with open(path, "w") as f:
630
674
  f.write(out)
631
675
 
632
676
 
@@ -651,7 +695,10 @@ def write_parameter_markdown_report(ms, path, parameter, add_metadata=True):
651
695
  out += "Domain: {}\n\n".format(param.domain)
652
696
  out += "Parameter Class: {}\n\n".format(param.parameter_class)
653
697
 
654
- with open("{}/Parameters/{}.md".format(path, param.name), "w") as f:
698
+ path = "{}/Parameters/{}.md".format(path, param.name)
699
+ out = write_source_code_block(param, out, path)
700
+
701
+ with open(path, "w") as f:
655
702
  f.write(out)
656
703
 
657
704
 
@@ -687,7 +734,25 @@ def write_stateful_metrics_markdown_report(ms, path, metric, add_metadata=True):
687
734
  out += "\n"
688
735
  out += "\n"
689
736
 
690
- with open("{}/Stateful Metrics/{}.md".format(path, metric.name), "w") as f:
737
+ temp = get_source_code(ms, "stateful_metrics", metric.name)
738
+ if temp:
739
+ source_code, file_path = temp
740
+ file_path = os.path.relpath(file_path, "{}/Stateful Metrics".format(path))
741
+ out += "## Python Implementation\n"
742
+ out += source_code
743
+ out += "\n"
744
+ out += "Implementation Path (only works if vault is opened at level including the src folder): [{}]({})".format(
745
+ file_path, file_path
746
+ )
747
+ out += "\n"
748
+
749
+ out += "\n"
750
+
751
+ path = "{}/Stateful Metrics/{}.md".format(path, metric.name)
752
+
753
+ out = write_source_code_block(metric, out, path)
754
+
755
+ with open(path, "w") as f:
691
756
  f.write(out)
692
757
 
693
758
 
@@ -742,7 +807,24 @@ def write_metrics_markdown_report(ms, path, metric, add_metadata=True):
742
807
  out += "{}. [[{}]]".format(i + 1, x.name)
743
808
  out += "\n"
744
809
 
745
- with open("{}/Metrics/{}.md".format(path, metric.name), "w") as f:
810
+ temp = get_source_code(ms, "metrics", metric.name)
811
+ if temp:
812
+ source_code, file_path = temp
813
+ file_path = os.path.relpath(file_path, "{}/Metrics".format(path))
814
+ out += "## Python Implementation\n"
815
+ out += source_code
816
+ out += "\n"
817
+ out += "Implementation Path (only works if vault is opened at level including the src folder): [{}]({})".format(
818
+ file_path, file_path
819
+ )
820
+ out += "\n"
821
+
822
+ out += "\n"
823
+
824
+ path = "{}/Metrics/{}.md".format(path, metric.name)
825
+ out = write_source_code_block(metric, out, path)
826
+
827
+ with open(path, "w") as f:
746
828
  f.write(out)
747
829
 
748
830
 
@@ -860,7 +942,10 @@ def write_wiring_display_markdown_report(ms, path, wiring, add_metadata=True):
860
942
  out += "\n"
861
943
  out += "\n"
862
944
 
863
- with open("{}/Displays/Wiring/{}.md".format(path, wiring["name"]), "w") as f:
945
+ path = "{}/Displays/Wiring/{}.md".format(path, wiring["name"])
946
+ out = write_source_code_block(wiring, out, path)
947
+
948
+ with open(path, "w") as f:
864
949
  f.write(out)
865
950
 
866
951
 
@@ -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.19
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=KHdGILGW7G29nXXsrjeRkKsilqEqYl31ZV1u9gm4xio,20147
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=4tD5c0qkQM2d99f0i1YYzmq20NNnQtqVmsa9P18qoR8,53181
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,23 +20,24 @@ 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
25
- math_spec_mapping/Load/action_transmission_channel.py,sha256=9Wer7g2s5SSOcUYuZ0PqSKUVVnW3EvGQJZNXJTwW__0,2561
26
- math_spec_mapping/Load/boundary_actions.py,sha256=cDN0pjkkWfYY3HHmgSrD__-weGD4DXElnG8w1pRc5Lc,2933
27
- math_spec_mapping/Load/control_actions.py,sha256=Y9LeEJuVj2OwxdTfnHZ57UV48j6PYCfyQWux4uXp1Mo,2371
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
+ math_spec_mapping/Load/action_transmission_channel.py,sha256=oTYCi7as4LWKZLxfRckuWpfLsAPZXjp-VBYmyLBN3yk,2781
26
+ math_spec_mapping/Load/boundary_actions.py,sha256=sR1JWzWD-9jegIQ8Api_NNUp11RgYM-6sAi1Pq-vkss,3007
27
+ math_spec_mapping/Load/control_actions.py,sha256=gL4HVn81e1UwBjUKEVtNEJop7E8KQGuq4F43oMaoyvA,2445
28
28
  math_spec_mapping/Load/displays.py,sha256=uQvs0Jhp8-9SXGex8SG3ibxHJu7ahAV3xLeBFbT8QEE,480
29
29
  math_spec_mapping/Load/entities.py,sha256=Ds7VQY_govWEn1vSHYVrLa8IadSNyOQzaCK18JPYPKk,1289
30
- math_spec_mapping/Load/general.py,sha256=2q6aGKxXhebiHHTZhtACvM4nWIkTben0o5rXuvfv2Vw,4463
30
+ math_spec_mapping/Load/general.py,sha256=Wjg0ESB80j9UwvoRB_-J8SBKq3KqCFZAKsuKNJFqkE4,4789
31
31
  math_spec_mapping/Load/implementations.py,sha256=a8YvumnyQvrnCo-o52Rv4yU8D7nmkMrV1iIA15fr6Bw,490
32
- math_spec_mapping/Load/load.py,sha256=oC-CuqbVqqhWw0kK7iiNKexAB_djgVNbjXSQfTsj2FA,2647
33
- math_spec_mapping/Load/mechanism.py,sha256=VRjkR2McsSJh2oq8n9JkeewirdlVjPRA-T5SRSKWPPQ,2293
32
+ math_spec_mapping/Load/load.py,sha256=Cm1IP_jIzWNGFVPcb1OOfQQYSNgyIfUdT--v1D1dkKE,2797
33
+ math_spec_mapping/Load/mechanism.py,sha256=6tgISsxc-SXCYS5yxuIqnl0nX__t1k0uj9z0O0E1uC4,2367
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
- math_spec_mapping/Load/policy.py,sha256=QTIcslHKgdYjjG69cqkJbW20CPvEL-B8R5u51rd2Puo,2697
36
+ math_spec_mapping/Load/policy.py,sha256=61F7sobAwaXrT1g_pXqBmQS0O-jekdQ1nB9C658LJyg,2770
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
- math_spec_mapping/Load/stateful_metrics.py,sha256=3Lq1ZGMaDd5OcGeqR2p5c_znkYw7ETTNPFjUVdZAHKk,2384
40
+ math_spec_mapping/Load/stateful_metrics.py,sha256=l-tjCnBnURlGxbJG1xtvmfWJ2egI9kMTkcoZUrmvtBY,2562
40
41
  math_spec_mapping/Load/states.py,sha256=3YurI7eTNkN6nrXRFVrc58wH0VfM22XOuWE07HVpR7Y,1365
41
42
  math_spec_mapping/Load/type.py,sha256=FbViE3wV1o1JTx7mUYyUpAvgIxDKDQYc6Iw50FrZ4nY,4808
42
43
  math_spec_mapping/Load/wiring.py,sha256=l1FhHNFRMKorn1oiRhsuMDsExcXnUmTjqQt5ElE-Bbk,3258
@@ -44,8 +45,8 @@ math_spec_mapping/Reports/__init__.py,sha256=P3IuE1wiM1EO_yCSD73D4O0O6j7aVWmiwpK
44
45
  math_spec_mapping/Reports/boundary_actions.py,sha256=45BPp4QjWdD-3E9ZWwqgj_nI2-YdcI2ZZ19_Qv_K7Qk,1410
45
46
  math_spec_mapping/Reports/control_actions.py,sha256=NksekZKIPFSIkubttFstKFthc5AU9B9PWRLSl9j1wWs,1216
46
47
  math_spec_mapping/Reports/general.py,sha256=WOOn6Wlb8M4fsdN49FlKLwOka6vJPQ9aCUy88TL2ki0,1610
47
- math_spec_mapping/Reports/html.py,sha256=RpyQQON8pDnMmfcyxOsm8UAD5Ad8VKnnW-OyOarTmzA,9711
48
- math_spec_mapping/Reports/markdown.py,sha256=DG0DmzE6Pas5dLLjbSnGa0xmWSFz0IGLa0sT_1MgYvI,27804
48
+ math_spec_mapping/Reports/html.py,sha256=MCVp_D1LuRoZrHtwzFOJGQviztGeahqsWf3Zue1Yz64,10134
49
+ math_spec_mapping/Reports/markdown.py,sha256=hrUzpaB7v8odPRH9ZiQCJTcCity8SB8x-NrAs-1IQA8,30303
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.19.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
59
+ math_spec_mapping-0.3.19.dist-info/METADATA,sha256=H5WfPm1pg2PybAhdQL8qx27FPNlvmg-f9iTGTpGJ6oE,6498
60
+ math_spec_mapping-0.3.19.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
61
+ math_spec_mapping-0.3.19.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
62
+ math_spec_mapping-0.3.19.dist-info/RECORD,,