math-spec-mapping 0.2.7__py3-none-any.whl → 0.3.0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,,