math-spec-mapping 0.2.7__py3-none-any.whl → 0.3.0__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.
@@ -5,6 +5,7 @@ from .Mechanism import Mechanism
5
5
  from .ControlAction import ControlAction
6
6
  from .BoundaryAction import BoundaryAction
7
7
  import os
8
+ from copy import deepcopy
8
9
 
9
10
 
10
11
  class MathSpec:
@@ -41,6 +42,8 @@ class MathSpec:
41
42
  self._crawl_parameters()
42
43
  self._crawl_parameters_exploded()
43
44
  self._check_dictionary_names()
45
+ self._build_functional_parameters()
46
+ self._build_parameter_types()
44
47
 
45
48
  def _check_dictionary_names(self):
46
49
  for key in self.boundary_actions:
@@ -352,6 +355,56 @@ class MathSpec:
352
355
  sm.extend([x.name for x in metrics.metrics])
353
356
  return sm
354
357
 
358
+ def _build_functional_parameters(self):
359
+ opts = [
360
+ (x, x.policy_options)
361
+ for x in self.policies.values()
362
+ if len(x.policy_options) > 1
363
+ ]
364
+ opts.extend(
365
+ [
366
+ (x, x.boundary_actions)
367
+ for x in self.boundary_actions.values()
368
+ if len(x.boundary_action_options) > 1
369
+ ]
370
+ )
371
+ opts.extend(
372
+ [
373
+ (x, x.control_actions)
374
+ for x in self.control_actions.values()
375
+ if len(x.control_action_options) > 1
376
+ ]
377
+ )
378
+ self.functional_parameters = {}
379
+ for x in opts:
380
+ x, y = x
381
+ self.functional_parameters["FP {}".format(x.name)] = {}
382
+ for y1 in y:
383
+ self.functional_parameters["FP {}".format(x.name)][y1.name] = y1
384
+
385
+ def _build_parameter_types(self):
386
+ system_parameters_types = {}
387
+ behavioral_parameters_types = {}
388
+ functional_parameters_types = {}
389
+
390
+ for x in self.parameters.all_parameters:
391
+ pt = self.parameters.parameter_map[x].variable_type.original_type_name
392
+ pc = self.parameters.parameter_map[x].parameter_class
393
+ if pc == "Functional":
394
+ functional_parameters_types[x] = pt
395
+ elif pc == "System":
396
+ system_parameters_types[x] = pt
397
+ elif pc == "Behavioral":
398
+ behavioral_parameters_types[x] = pt
399
+ else:
400
+ assert False
401
+ for x in self.functional_parameters:
402
+ functional_parameters_types[x] = "str"
403
+
404
+ self.system_parameters_types = system_parameters_types
405
+ self.behavioral_parameters_types = behavioral_parameters_types
406
+ self.functional_parameters_types = functional_parameters_types
407
+
355
408
  def metaprogramming_python_types(self, model_directory, overwrite=False):
356
409
  path = model_directory + "/types.py"
357
410
  if not overwrite:
@@ -447,3 +500,248 @@ class MathSpec:
447
500
 
448
501
  with open(path, "w") as f:
449
502
  f.write(out)
503
+
504
+ def metaprogramming_python_parameters(
505
+ self, model_directory, overwrite=False, default_values=None
506
+ ):
507
+ path = model_directory + "/parameters.py"
508
+ if not overwrite:
509
+ assert "parameters.py" not in os.listdir(
510
+ model_directory
511
+ ), "The parameters file is already written, either delete it or switch to overwrite mode"
512
+ out = ""
513
+
514
+ unique_types = (
515
+ set(self.system_parameters_types.values())
516
+ .union(set(self.functional_parameters_types.values()))
517
+ .union(set(self.behavioral_parameters_types.values()))
518
+ )
519
+ unique_types = [x for x in unique_types if x != "str"]
520
+
521
+ out = ""
522
+ out += "from .types import {}".format(", ".join(unique_types))
523
+ out += "\n"
524
+ out += "from typing import TypedDict"
525
+ out += "\n"
526
+ out += "\n"
527
+
528
+ d = self.system_parameters_types
529
+ d = [(x, d[x]) for x in d]
530
+ d = ["'{}': {}".format(x[0], x[1]) for x in d]
531
+ d = ", ".join(d)
532
+ d = "{" + d + "}"
533
+
534
+ out += "SystemParameters = TypedDict('SystemParameters', {})".format(d)
535
+ out += "\n\n"
536
+
537
+ d = self.behavioral_parameters_types
538
+ d = [(x, d[x]) for x in d]
539
+ d = ["'{}': {}".format(x[0], x[1]) for x in d]
540
+ d = ", ".join(d)
541
+ d = "{" + d + "}"
542
+
543
+ out += "BehavioralParameters = TypedDict('BehavioralParameters', {})".format(d)
544
+ out += "\n\n"
545
+
546
+ d = self.functional_parameters_types
547
+ d = [(x, d[x]) for x in d]
548
+ d = ["'{}': {}".format(x[0], x[1]) for x in d]
549
+ d = ", ".join(d)
550
+ d = "{" + d + "}"
551
+
552
+ out += "FunctionalParameters = TypedDict('FunctionalParameters', {})".format(d)
553
+ out += "\n\n"
554
+ out += """Parameters = TypedDict("Parameters",{**BehavioralParameters.__annotations__,
555
+ **FunctionalParameters.__annotations__,
556
+ **SystemParameters.__annotations__})"""
557
+ out += "\n\n"
558
+
559
+ out += "functional_parameters: FunctionalParameters = "
560
+ out += "{"
561
+ for key in self.functional_parameters_types:
562
+ out += '"{}"'.format(key)
563
+ out += ": "
564
+ val = "None"
565
+ if default_values:
566
+ if key in default_values:
567
+ val = str(default_values[key])
568
+ out += val
569
+ out += ",\n"
570
+ out += "}"
571
+ out += "\n\n"
572
+
573
+ out += "behavioral_parameters: BehavioralParameters = "
574
+ out += "{"
575
+ for key in self.behavioral_parameters_types:
576
+ out += '"{}"'.format(key)
577
+ out += ": "
578
+ val = "None"
579
+ if default_values:
580
+ if key in default_values:
581
+ val = str(default_values[key])
582
+ out += val
583
+ out += ",\n"
584
+ out += "}"
585
+ out += "\n\n"
586
+
587
+ out += "system_parameters: SystemParameters = "
588
+ out += "{"
589
+ for key in self.system_parameters_types:
590
+ out += '"{}"'.format(key)
591
+ out += ": "
592
+ val = "None"
593
+ if default_values:
594
+ if key in default_values:
595
+ val = str(default_values[key])
596
+ out += val
597
+ out += ",\n"
598
+ out += "}"
599
+ out += "\n\n"
600
+
601
+ out += "parameters: Parameters = {**behavioral_parameters, **functional_parameters, **system_parameters}"
602
+
603
+ with open(path, "w") as f:
604
+ f.write(out)
605
+
606
+ def build_implementation(self, params):
607
+ return MathSpecImplementation(self, params)
608
+
609
+
610
+ class MathSpecImplementation:
611
+ def __init__(self, ms: MathSpec, params):
612
+ self.ms = deepcopy(ms)
613
+ self.params = params
614
+ self.control_actions = self.load_control_actions()
615
+ self.boundary_actions = {}
616
+ self.policies = self.load_policies()
617
+ self.mechanisms = self.load_mechanisms()
618
+ self.load_wiring()
619
+
620
+ def load_control_actions(self):
621
+ control_actions = {}
622
+ for ca in self.ms.control_actions:
623
+ ca = self.ms.control_actions[ca]
624
+ opts = ca.control_action_options
625
+ if len(opts) == 0:
626
+ print("{} has no control action options".format(ca.name))
627
+ else:
628
+ if len(opts) == 1:
629
+ opt = opts[0]
630
+ else:
631
+ assert (
632
+ "FP {}".format(ca.name) in self.params
633
+ ), "No functional parameterization for {}".format(ca.name)
634
+ opt = self.ms.functional_parameters["FP {}".format(ca.name)][
635
+ self.params["FP {}".format(ca.name)]
636
+ ]
637
+
638
+ assert (
639
+ "python" in opt.implementations
640
+ ), "No python implementation for {} / {}".format(ca.name, opt.name)
641
+
642
+ control_actions[ca.name] = opt.implementations["python"]
643
+ return control_actions
644
+
645
+ def load_mechanisms(self):
646
+ mechanisms = {}
647
+ for m in self.ms.mechanisms:
648
+ m = self.ms.mechanisms[m]
649
+ if "python" not in m.implementations:
650
+ print("No python implementation for {}".format(m.name))
651
+ else:
652
+ mechanisms[m.name] = m.implementations["python"]
653
+ return mechanisms
654
+
655
+ def load_single_wiring(self, wiring):
656
+ components = [x.name for x in wiring.components]
657
+ if wiring.block_type == "Stack Block":
658
+
659
+ def wiring(state, params, spaces):
660
+ for component in components:
661
+ spaces = self.blocks[component](state, params, spaces)
662
+ return spaces
663
+
664
+ elif wiring.block_type == "Parallel Block":
665
+
666
+ spaces_mapping = {}
667
+ for x in wiring.components:
668
+ spaces_mapping[x.name] = []
669
+
670
+ for i, x in enumerate([x.name for x in wiring.domain_blocks]):
671
+ spaces_mapping[x].append(i)
672
+
673
+ def wiring(state, params, spaces):
674
+ codomain = []
675
+ for component in components:
676
+ spaces_i = [spaces[i] for i in spaces_mapping[component]]
677
+ spaces_i = self.blocks[component](state, params, spaces_i)
678
+ if spaces_i:
679
+ codomain.extend(spaces_i)
680
+ return codomain
681
+
682
+ else:
683
+ assert False
684
+
685
+ return wiring
686
+
687
+ def load_policies(self):
688
+ policies = {}
689
+ for p in self.ms.policies:
690
+ p = self.ms.policies[p]
691
+ opts = p.policy_options
692
+ if len(opts) == 0:
693
+ print("{} has no policy options".format(p.name))
694
+ else:
695
+ if len(opts) == 1:
696
+ opt = opts[0]
697
+ else:
698
+ assert (
699
+ "FP {}".format(p.name) in self.params
700
+ ), "No functional parameterization for {}".format(p.name)
701
+ opt = self.ms.functional_parameters["FP {}".format(p.name)][
702
+ self.params["FP {}".format(p.name)]
703
+ ]
704
+
705
+ if "python" not in opt.implementations:
706
+ print(
707
+ "No python implementation for {} / {}".format(p.name, opt.name)
708
+ )
709
+ else:
710
+ policies[p.name] = opt.implementations["python"]
711
+ return policies
712
+
713
+ def load_wiring(
714
+ self,
715
+ ):
716
+ self.blocks = {}
717
+ self.blocks.update(self.boundary_actions)
718
+ self.blocks.update(self.control_actions)
719
+ self.blocks.update(self.policies)
720
+ self.blocks.update(self.mechanisms)
721
+
722
+ self.wiring = {}
723
+
724
+ wiring = [x for x in self.ms.wiring.values()]
725
+
726
+ i = 1
727
+ while i > 0:
728
+ i = 0
729
+ hold = []
730
+ for w in wiring:
731
+ components = [x.name for x in w.components]
732
+ if all([x in self.blocks for x in components]):
733
+ i += 1
734
+ w2 = self.load_single_wiring(w)
735
+ assert w.name not in self.blocks, "{} was a repeated block".format(
736
+ w.name
737
+ )
738
+ if w2:
739
+ self.blocks[w.name] = w2
740
+ self.wiring[w.name] = w2
741
+
742
+ else:
743
+ hold.append(w)
744
+ wiring = hold
745
+ if len(wiring) > 0:
746
+ wiring = [x.name for x in wiring]
747
+ print("The following wirings were not loading: {}".format(wiring))
@@ -1,4 +1,4 @@
1
- from .MathSpec import MathSpec
1
+ from .MathSpec import MathSpec, MathSpecImplementation
2
2
  from .State import State, StateVariable
3
3
  from .Entity import Entity
4
4
  from .BoundaryAction import BoundaryAction, BoundaryActionOption
@@ -675,7 +675,6 @@ def write_all_markdown_reports(ms, path, clear_folders=False):
675
675
  "Types",
676
676
  "Control Actions",
677
677
  "Spaces",
678
- ".obsidian",
679
678
  "Boundary Actions",
680
679
  "Policies",
681
680
  "Wiring",
@@ -116,28 +116,34 @@
116
116
  "additionalProperties": false,
117
117
  "properties": {
118
118
  "name": {
119
- "type": "string"
119
+ "type": "string",
120
+ "description": "The name of the control action"
120
121
  },
121
122
  "description": {
122
- "type": "string"
123
+ "type": "string",
124
+ "description": "The description of the control action"
123
125
  },
124
126
  "constraints": {
125
127
  "type": "array",
126
- "items": {}
128
+ "description": "Any constraints which the control action must respect",
129
+ "items": {"type": "string"}
127
130
  },
128
131
  "control_action_options": {
129
132
  "type": "array",
130
- "items": {}
133
+ "items": {},
134
+ "description": "Possible implementations of the control action"
131
135
  },
132
136
  "codomain": {
133
137
  "type": "array",
134
138
  "items": {
135
139
  "type": "string"
136
- }
140
+ },
141
+ "description": "The output spaces of the control action"
137
142
  },
138
143
  "parameters_used": {
139
144
  "type": "array",
140
- "items": {"type": "string"}
145
+ "items": {"type": "string"},
146
+ "description": "The parameters which the control action uses in its implenetations"
141
147
  }
142
148
  },
143
149
  "required": [
@@ -308,44 +314,52 @@
308
314
  "additionalProperties": false,
309
315
  "properties": {
310
316
  "name": {
311
- "type": "string"
317
+ "type": "string",
318
+ "description": "The name of the policy"
312
319
  },
313
320
  "description": {
314
- "type": "string"
321
+ "type": "string",
322
+ "description": "Description of the policy"
315
323
  },
316
324
  "constraints": {
317
325
  "type": "array",
318
- "items": {}
326
+ "description": "Any constraints which the policy must respect",
327
+ "items": {"type": "string"}
319
328
  },
320
329
  "policy_options": {
321
330
  "type": "array",
322
331
  "items": {
323
332
  "$ref": "./schema.schema.json/#/definitions/PolicyOption"
324
- }
333
+ },
334
+ "description": "Possible implementations of the policy"
325
335
  },
326
336
  "domain": {
327
337
  "type": "array",
328
338
  "items": {
329
339
  "type": "string"
330
- }
340
+ },
341
+ "description": "The spaces which are passed in as inputs to the policy"
331
342
  },
332
343
  "codomain": {
333
344
  "type": "array",
334
345
  "items": {
335
346
  "type": "string"
336
- }
347
+ },
348
+ "description": "The spaces which are returned as results of the policy"
337
349
  },
338
350
  "parameters_used": {
339
351
  "type": "array",
340
352
  "items": {
341
353
  "type": "string"
342
- }
354
+ },
355
+ "description": "All parameters used in the implementations of policies"
343
356
  },
344
357
  "metrics_used": {
345
358
  "type": "array",
346
359
  "items": {
347
360
  "type": "string"
348
- }
361
+ },
362
+ "description": "All metrics used in implementation of policies"
349
363
  }
350
364
  },
351
365
  "required": [
@@ -366,13 +380,16 @@
366
380
  "additionalProperties": false,
367
381
  "properties": {
368
382
  "name": {
369
- "type": "string"
383
+ "type": "string",
384
+ "description": "The name of the policy option"
370
385
  },
371
386
  "description": {
372
- "type": "string"
387
+ "type": "string",
388
+ "description": "A description of the implementation"
373
389
  },
374
390
  "logic": {
375
- "type": "string"
391
+ "type": "string",
392
+ "description": "Any logic associated with the implementation"
376
393
  }
377
394
  },
378
395
  "required": [
@@ -434,38 +451,45 @@
434
451
  "additionalProperties": true,
435
452
  "properties": {
436
453
  "name": {
437
- "type": "string"
454
+ "type": "string",
455
+ "description": "Name of the boundary action"
438
456
  },
439
457
  "description": {
440
- "type": "string"
458
+ "type": "string",
459
+ "description": "Quick description of the boundary action"
441
460
  },
442
461
  "constraints": {
443
462
  "type": "array",
444
463
  "items": {
445
464
  "type": "string"
446
- }
465
+ },
466
+ "description": "Any constraints which the boundary action must respect"
447
467
  },
448
468
  "boundary_action_options": {
449
469
  "type": "array",
450
- "items": {}
470
+ "items": {},
471
+ "description": "The options for implementation of the boundary action"
451
472
  },
452
473
  "called_by": {
453
474
  "type": "array",
454
475
  "items": {
455
476
  "type": "string"
456
- }
477
+ },
478
+ "description": "The entities which are allowed to call this boundary action"
457
479
  },
458
480
  "codomain": {
459
481
  "type": "array",
460
482
  "items": {
461
483
  "type": "string"
462
- }
484
+ },
485
+ "description": "List of outputs that come out of this block"
463
486
  },
464
487
  "parameters_used": {
465
488
  "type": "array",
466
489
  "items": {
467
490
  "type": "string"
468
- }
491
+ },
492
+ "description": "The string keys of parameters which have an effect on the boundary action"
469
493
  }
470
494
  },
471
495
  "required": [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: math-spec-mapping
3
- Version: 0.2.7
3
+ Version: 0.3.0
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
1
  math_spec_mapping/__init__.py,sha256=k5KVhqX1_iIkGjTBHAHezWUeh0b3ilWpJaSIVSbKMcg,907
2
2
  math_spec_mapping/schema.py,sha256=6mrRqzEnTTSXjb19xJ63MBp0KjKH0s7i6TfT4MkAY9k,233
3
- math_spec_mapping/schema.schema.json,sha256=E8-TQIiv7AjIMXnAIB84z_O4cMLfGuDmDCFCoIlwQz0,27174
3
+ math_spec_mapping/schema.schema.json,sha256=DTrPuYbA-n27jatLt2h76WgMm7pWVgkFwC3zGDnlptQ,29208
4
4
  math_spec_mapping/Classes/ActionTransmissionChannel.py,sha256=zWMo5QsgPh5WGIWXl-xOrZNMXYJXmK6Vejw1dQvi0og,246
5
5
  math_spec_mapping/Classes/Block.py,sha256=hXQO221IP-TqZm_TwFKfURpEEjZm7L1TPZDCYlaOdho,17302
6
6
  math_spec_mapping/Classes/BoundaryAction.py,sha256=AOENCqCEfpjotnHhzUj_F2SOP0SGpkN1tNPr8Mtl6Tc,476
7
7
  math_spec_mapping/Classes/ControlAction.py,sha256=ysqpgANwdizVdwqtgZmnxXMpCqrzmVEF_6YT0M3l4Ho,526
8
8
  math_spec_mapping/Classes/Entity.py,sha256=fA0-b128_OHHxfCg4pzqyQV083EYev1HlVpy86S5igg,1226
9
- math_spec_mapping/Classes/MathSpec.py,sha256=eweFUB8iuEI5Y-9VOULbAWbIeHd18Iw-I_VPUjvnn0E,16999
9
+ math_spec_mapping/Classes/MathSpec.py,sha256=FTxArDTLt7PBwXE79VqhP7qIA4Gf6zgXAo_iQWOh_7U,27443
10
10
  math_spec_mapping/Classes/Mechanism.py,sha256=2sLm3wYBIeTQaMBcsJ9btqIWsbS895Ra8NY6Y9_G_Dg,379
11
11
  math_spec_mapping/Classes/Metric.py,sha256=AhPgYppOP6q49xvR8S9STxQsXUKJlTWx7wI1LfZEtww,581
12
12
  math_spec_mapping/Classes/Parameter.py,sha256=ZuJ_w0sChvRElJ4sOnXZ2EV4Ell2xXFulKLjVOpgz2E,1237
@@ -16,7 +16,7 @@ math_spec_mapping/Classes/State.py,sha256=0gJHHTNjTrz1fL2K-yPu-dJlaCsU_NMxClw6ne
16
16
  math_spec_mapping/Classes/StateUpdateTransmissionChannel.py,sha256=3hBLvD1lE64PkwqksBXAfFWv7foOZzGQLAFQWy42tOA,257
17
17
  math_spec_mapping/Classes/StatefulMetric.py,sha256=UCis1BJ7fsajHHxFF05ZiyDean2D4s4a95uYYW1Mjq4,749
18
18
  math_spec_mapping/Classes/Type.py,sha256=2KFY8d3cv1PzJJ7SSMHJf1zcfQ3ZbqxotK2KgTaLZdM,289
19
- math_spec_mapping/Classes/__init__.py,sha256=_hXyZMJanmIex_W6yCR2H7Jw8iU2JJIf3U7VcvBSOGU,737
19
+ math_spec_mapping/Classes/__init__.py,sha256=0zxgOqns_9JybD74HKMVh6aw8ij8WVbfQ4Q_1uWzof0,761
20
20
  math_spec_mapping/Convenience/__init__.py,sha256=-hNZVoaNSgTmZTiyZoMfWyg14xonC3ppz-diQk1VlUY,60
21
21
  math_spec_mapping/Convenience/documentation.py,sha256=Jf7-JJIk_vZkNBIGV4bs5LM3B0RVaCCtuwJ164thGfY,1607
22
22
  math_spec_mapping/Convenience/starter.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -44,7 +44,7 @@ math_spec_mapping/Reports/boundary_actions.py,sha256=45BPp4QjWdD-3E9ZWwqgj_nI2-Y
44
44
  math_spec_mapping/Reports/control_actions.py,sha256=NksekZKIPFSIkubttFstKFthc5AU9B9PWRLSl9j1wWs,1216
45
45
  math_spec_mapping/Reports/general.py,sha256=WOOn6Wlb8M4fsdN49FlKLwOka6vJPQ9aCUy88TL2ki0,1610
46
46
  math_spec_mapping/Reports/html.py,sha256=xf5jk3DHWg4CfZHZuF2JK5iZ515ecjDShJJsahiqb4g,8882
47
- math_spec_mapping/Reports/markdown.py,sha256=pDGHYMdtZmeXHqvU9FB3BycyB4qflWXq0bf2m-wsXMU,21138
47
+ math_spec_mapping/Reports/markdown.py,sha256=eJidreiLmfUznoq_-C4IsFTZ__Bka-PWLKjKYn6bhmw,21113
48
48
  math_spec_mapping/Reports/mechanisms.py,sha256=d2Rxt3JBYvqAOAYUynl0buYVoXEHrO8EGq7GK6hK8NA,1322
49
49
  math_spec_mapping/Reports/node_map.py,sha256=FdSMDQG16NX6n9sZcH-T5xwsvgjrV9OqBHc9J_VlNK0,3129
50
50
  math_spec_mapping/Reports/parameters.py,sha256=yizNG4lNGrgrlzYYcHMGfXKDFlPw4PMDYshDqZ3YARs,535
@@ -53,8 +53,8 @@ math_spec_mapping/Reports/spaces.py,sha256=-76hR5wQBv4lsG000ypBJ-OprjsNjI-rNRMYd
53
53
  math_spec_mapping/Reports/state.py,sha256=RSHDjzSiUj4ZjReWbkBW7k2njs3Ovp-q0rCC7GBfD-A,2203
54
54
  math_spec_mapping/Reports/tables.py,sha256=O0CNuqh3LMECq5uLjBOoxMUk5hUvkUK660FNnwWUxDY,1505
55
55
  math_spec_mapping/Reports/wiring.py,sha256=u9SvKWy6T-WJUEgFI6-zgZanoOaTTs_2YwmEceDLsV8,1618
56
- math_spec_mapping-0.2.7.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
57
- math_spec_mapping-0.2.7.dist-info/METADATA,sha256=H3plPQQrT7sss_57Z2341oAlBkMpW7_QHihqFoZcgUM,6012
58
- math_spec_mapping-0.2.7.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
59
- math_spec_mapping-0.2.7.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
60
- math_spec_mapping-0.2.7.dist-info/RECORD,,
56
+ math_spec_mapping-0.3.0.dist-info/LICENSE,sha256=ObyEzSw8kgCaFbEfpu1zP4TrcAKLA0xhqHMZZfyh7N0,1069
57
+ math_spec_mapping-0.3.0.dist-info/METADATA,sha256=Vc8ZOoyIufYp8gQkctaAbFV6cuSPNQnOWZw2SaYJXPI,6012
58
+ math_spec_mapping-0.3.0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
59
+ math_spec_mapping-0.3.0.dist-info/top_level.txt,sha256=AImhn9wgazkdV0a9vfiphtQR8uGe2nq-ZIOp-6yUk9o,18
60
+ math_spec_mapping-0.3.0.dist-info/RECORD,,