math-spec-mapping 0.2.6.7__py3-none-any.whl → 0.2.7__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- math_spec_mapping/Classes/ControlAction.py +1 -0
- math_spec_mapping/Classes/MathSpec.py +98 -0
- math_spec_mapping/Classes/Mechanism.py +1 -0
- math_spec_mapping/Classes/Policy.py +1 -0
- math_spec_mapping/Classes/Space.py +1 -0
- math_spec_mapping/Classes/State.py +1 -0
- math_spec_mapping/Classes/Type.py +1 -0
- math_spec_mapping/Load/control_actions.py +10 -0
- math_spec_mapping/Load/mechanism.py +8 -0
- math_spec_mapping/Load/policy.py +11 -2
- math_spec_mapping/Load/type.py +1 -0
- math_spec_mapping/Reports/html.py +33 -1
- {math_spec_mapping-0.2.6.7.dist-info → math_spec_mapping-0.2.7.dist-info}/METADATA +1 -1
- {math_spec_mapping-0.2.6.7.dist-info → math_spec_mapping-0.2.7.dist-info}/RECORD +17 -17
- {math_spec_mapping-0.2.6.7.dist-info → math_spec_mapping-0.2.7.dist-info}/LICENSE +0 -0
- {math_spec_mapping-0.2.6.7.dist-info → math_spec_mapping-0.2.7.dist-info}/WHEEL +0 -0
- {math_spec_mapping-0.2.6.7.dist-info → math_spec_mapping-0.2.7.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@ from .Policy import Policy
|
|
4
4
|
from .Mechanism import Mechanism
|
5
5
|
from .ControlAction import ControlAction
|
6
6
|
from .BoundaryAction import BoundaryAction
|
7
|
+
import os
|
7
8
|
|
8
9
|
|
9
10
|
class MathSpec:
|
@@ -12,6 +13,7 @@ class MathSpec:
|
|
12
13
|
self._ms_dict = ms_dict
|
13
14
|
self._json = json
|
14
15
|
self.type_keys = ms_dict["Type Keys"]
|
16
|
+
self.implementations = ms_dict["Implementations"]
|
15
17
|
self.action_transmission_channels = ms_dict["Action Transmission Channels"]
|
16
18
|
self.boundary_actions = ms_dict["Boundary Actions"]
|
17
19
|
self.control_actions = ms_dict["Control Actions"]
|
@@ -349,3 +351,99 @@ class MathSpec:
|
|
349
351
|
for metrics in self.stateful_metrics.values():
|
350
352
|
sm.extend([x.name for x in metrics.metrics])
|
351
353
|
return sm
|
354
|
+
|
355
|
+
def metaprogramming_python_types(self, model_directory, overwrite=False):
|
356
|
+
path = model_directory + "/types.py"
|
357
|
+
if not overwrite:
|
358
|
+
assert "types.py" not in os.listdir(
|
359
|
+
model_directory
|
360
|
+
), "The types file is already written, either delete it or switch to overwrite mode"
|
361
|
+
out = "import typing\n\n"
|
362
|
+
for t in self.types:
|
363
|
+
t = self.types[t]
|
364
|
+
assert "python" in t.type, "No python type associated with {}".format(
|
365
|
+
t.name
|
366
|
+
)
|
367
|
+
x = t.type["python"]
|
368
|
+
type_desc = x.__name__ if hasattr(x, "__name__") else str(x)
|
369
|
+
out += "{} = {}".format(t.original_type_name, type_desc)
|
370
|
+
out += "\n"
|
371
|
+
with open(path, "w") as f:
|
372
|
+
f.write(out)
|
373
|
+
|
374
|
+
def metaprogramming_python_spaces(self, model_directory, overwrite=False):
|
375
|
+
path = model_directory + "/spaces.py"
|
376
|
+
if not overwrite:
|
377
|
+
assert "spaces.py" not in os.listdir(
|
378
|
+
model_directory
|
379
|
+
), "The spaces file is already written, either delete it or switch to overwrite mode"
|
380
|
+
unique_spaces = set().union(
|
381
|
+
*[set(x.schema.values()) for x in self.spaces.values()]
|
382
|
+
)
|
383
|
+
unique_types = [x.original_type_name for x in unique_spaces]
|
384
|
+
out = ""
|
385
|
+
out += "from .types import {}".format(", ".join(unique_types))
|
386
|
+
out += "\n"
|
387
|
+
out += "from typing import TypedDict"
|
388
|
+
out += "\n"
|
389
|
+
out += "\n"
|
390
|
+
|
391
|
+
for space in self.spaces:
|
392
|
+
out += self.spaces[space].name_variable
|
393
|
+
out += " = "
|
394
|
+
d = self.spaces[space].schema
|
395
|
+
d = [(x, d[x].original_type_name) for x in d]
|
396
|
+
d = ["'{}': {}".format(x[0], x[1]) for x in d]
|
397
|
+
d = ", ".join(d)
|
398
|
+
d = "{" + d + "}"
|
399
|
+
out += "TypedDict('{}', {})".format(self.spaces[space].name, d)
|
400
|
+
out += "\n"
|
401
|
+
|
402
|
+
with open(path, "w") as f:
|
403
|
+
f.write(out)
|
404
|
+
|
405
|
+
def metaprogramming_python_states(
|
406
|
+
self, model_directory, overwrite=False, default_values=None
|
407
|
+
):
|
408
|
+
path = model_directory + "/states.py"
|
409
|
+
if not overwrite:
|
410
|
+
assert "states.py" not in os.listdir(
|
411
|
+
model_directory
|
412
|
+
), "The states file is already written, either delete it or switch to overwrite mode"
|
413
|
+
out = ""
|
414
|
+
unique_types = [x.variables for x in self.state.values()]
|
415
|
+
unique_types = [set(y.type.original_type_name for y in x) for x in unique_types]
|
416
|
+
unique_types = set().union(*unique_types)
|
417
|
+
out = ""
|
418
|
+
out += "from .types import {}".format(", ".join(unique_types))
|
419
|
+
out += "\n"
|
420
|
+
out += "from typing import TypedDict"
|
421
|
+
out += "\n"
|
422
|
+
out += "\n"
|
423
|
+
|
424
|
+
for state in self.state:
|
425
|
+
out += self.state[state].name_variable
|
426
|
+
out += " = "
|
427
|
+
d = self.state[state].variables
|
428
|
+
d = [(x.name, x.type.original_type_name) for x in d]
|
429
|
+
d = ["'{}': {}".format(x[0], x[1]) for x in d]
|
430
|
+
d = ", ".join(d)
|
431
|
+
d = "{" + d + "}"
|
432
|
+
out += "TypedDict('{}', {})".format(self.state[state].name, d)
|
433
|
+
out += "\n"
|
434
|
+
out += "\n"
|
435
|
+
out += "state: GlobalState = "
|
436
|
+
out += "{"
|
437
|
+
for x in self.state["Global State"].variables:
|
438
|
+
out += '"{}"'.format(x.name)
|
439
|
+
out += ": "
|
440
|
+
val = "None"
|
441
|
+
if default_values:
|
442
|
+
if x.name in default_values:
|
443
|
+
val = str(default_values[x.name])
|
444
|
+
out += val
|
445
|
+
out += ",\n"
|
446
|
+
out += "}"
|
447
|
+
|
448
|
+
with open(path, "w") as f:
|
449
|
+
f.write(out)
|
@@ -35,6 +35,16 @@ def convert_control_action(data: Dict, ms: Dict) -> ControlAction:
|
|
35
35
|
new_cao = []
|
36
36
|
for ca in data["control_action_options"]:
|
37
37
|
check_json_keys(ca, "Control Action Option")
|
38
|
+
ca["implementations"] = {}
|
39
|
+
if "python" in ms["Implementations"]:
|
40
|
+
if "control_action_options" in ms["Implementations"]["python"]:
|
41
|
+
if (
|
42
|
+
ca["name"]
|
43
|
+
in ms["Implementations"]["python"]["control_action_options"]
|
44
|
+
):
|
45
|
+
ca["implementations"]["python"] = ms["Implementations"]["python"][
|
46
|
+
"control_action_options"
|
47
|
+
][ca["name"]]
|
38
48
|
new_cao.append(ControlActionOption(ca))
|
39
49
|
data["control_action_options"] = new_cao
|
40
50
|
|
@@ -42,6 +42,14 @@ def convert_mechanism(data: Dict, ms: Dict) -> Mechanism:
|
|
42
42
|
)
|
43
43
|
|
44
44
|
data["domain"] = tuple(ms["Spaces"][x] for x in data["domain"])
|
45
|
+
data["implementations"] = {}
|
46
|
+
|
47
|
+
if "python" in ms["Implementations"]:
|
48
|
+
if "mechanisms" in ms["Implementations"]["python"]:
|
49
|
+
if data["name"] in ms["Implementations"]["python"]["mechanisms"]:
|
50
|
+
data["implementations"]["python"] = ms["Implementations"]["python"][
|
51
|
+
"mechanisms"
|
52
|
+
][data["name"]]
|
45
53
|
|
46
54
|
# Build the action transmission channel object
|
47
55
|
return Mechanism(data), new_channels
|
math_spec_mapping/Load/policy.py
CHANGED
@@ -5,7 +5,7 @@ from ..Classes import Policy, PolicyOption
|
|
5
5
|
from .general import check_json_keys
|
6
6
|
|
7
7
|
|
8
|
-
def convert_policy_options(data: Dict) -> PolicyOption:
|
8
|
+
def convert_policy_options(data: Dict, ms) -> PolicyOption:
|
9
9
|
"""Function to convert policy options
|
10
10
|
|
11
11
|
Args:
|
@@ -21,6 +21,15 @@ def convert_policy_options(data: Dict) -> PolicyOption:
|
|
21
21
|
# Copy
|
22
22
|
data = data.copy()
|
23
23
|
|
24
|
+
data["implementations"] = {}
|
25
|
+
|
26
|
+
if "python" in ms["Implementations"]:
|
27
|
+
if "policies" in ms["Implementations"]["python"]:
|
28
|
+
if data["name"] in ms["Implementations"]["python"]["policies"]:
|
29
|
+
data["implementations"]["python"] = ms["Implementations"]["python"][
|
30
|
+
"policies"
|
31
|
+
][data["name"]]
|
32
|
+
|
24
33
|
# Build the policy object
|
25
34
|
return PolicyOption(data)
|
26
35
|
|
@@ -62,7 +71,7 @@ def convert_policy(data: Dict, ms: Dict) -> Policy:
|
|
62
71
|
# Convert policy options
|
63
72
|
policy_options = []
|
64
73
|
for po in data["policy_options"]:
|
65
|
-
policy_options.append(convert_policy_options(po))
|
74
|
+
policy_options.append(convert_policy_options(po, ms))
|
66
75
|
data["policy_options"] = policy_options
|
67
76
|
|
68
77
|
data["codomain"] = tuple(ms["Spaces"][x] for x in data["codomain"])
|
math_spec_mapping/Load/type.py
CHANGED
@@ -9,6 +9,7 @@ from .node_map import create_action_chains_graph
|
|
9
9
|
from .parameters import write_out_params
|
10
10
|
from .state import write_local_state_variable_tables, write_global_state_variable_table
|
11
11
|
from typing import List
|
12
|
+
import os
|
12
13
|
|
13
14
|
|
14
15
|
def write_basic_report_full(ms: MathSpec, directory: str, name: str) -> None:
|
@@ -128,6 +129,15 @@ def write_spec_tree(
|
|
128
129
|
symbol3 = "│ │ ├──"
|
129
130
|
|
130
131
|
out = ""
|
132
|
+
|
133
|
+
if linking:
|
134
|
+
out += """---
|
135
|
+
cssclasses:
|
136
|
+
- spec
|
137
|
+
---
|
138
|
+
|
139
|
+
"""
|
140
|
+
|
131
141
|
out += symbol1 + "**Entities**\n"
|
132
142
|
for name in ms.entities.keys():
|
133
143
|
if linking:
|
@@ -214,7 +224,29 @@ def write_spec_tree(
|
|
214
224
|
if path:
|
215
225
|
with open("{}/Spec Tree.md".format(path), "w") as f:
|
216
226
|
f.write(out)
|
217
|
-
|
227
|
+
try:
|
228
|
+
if ".obsidian" not in os.listdir(path):
|
229
|
+
path = path + "/" + ".obsidian"
|
230
|
+
os.mkdir(path)
|
231
|
+
else:
|
232
|
+
path = path + "/" + ".obsidian"
|
233
|
+
if "snippets" not in os.listdir(path):
|
234
|
+
path = path + "/" + "snippets"
|
235
|
+
os.mkdir(path)
|
236
|
+
else:
|
237
|
+
path = path + "/" + "snippets"
|
238
|
+
|
239
|
+
snippet = """.spec {
|
240
|
+
font-family: 'Consolas', Courier, monospace ;
|
241
|
+
line-height: 1;
|
242
|
+
}"""
|
243
|
+
with open("{}/spec.css".format(path), "w") as f:
|
244
|
+
f.write(snippet)
|
245
|
+
|
246
|
+
except:
|
247
|
+
print("Couldn't find .obsidian/snippets to put snippet in")
|
248
|
+
else:
|
249
|
+
return out
|
218
250
|
|
219
251
|
|
220
252
|
def write_overview(ms: MathSpec, name: str, file_path: str, summary: str = None):
|
@@ -4,18 +4,18 @@ math_spec_mapping/schema.schema.json,sha256=E8-TQIiv7AjIMXnAIB84z_O4cMLfGuDmDCFC
|
|
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
|
-
math_spec_mapping/Classes/ControlAction.py,sha256=
|
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=
|
10
|
-
math_spec_mapping/Classes/Mechanism.py,sha256=
|
9
|
+
math_spec_mapping/Classes/MathSpec.py,sha256=eweFUB8iuEI5Y-9VOULbAWbIeHd18Iw-I_VPUjvnn0E,16999
|
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
|
13
|
-
math_spec_mapping/Classes/Policy.py,sha256=
|
14
|
-
math_spec_mapping/Classes/Space.py,sha256=
|
15
|
-
math_spec_mapping/Classes/State.py,sha256=
|
13
|
+
math_spec_mapping/Classes/Policy.py,sha256=fzV85tB3QScjiYGfhw_dyQt9L1BYYfTyTIQQcxeT8ac,530
|
14
|
+
math_spec_mapping/Classes/Space.py,sha256=QsahxoUfRsDWQLBL683KnGx72MAmRxv7CDE7TMgCG-E,472
|
15
|
+
math_spec_mapping/Classes/State.py,sha256=0gJHHTNjTrz1fL2K-yPu-dJlaCsU_NMxClw6neDv6gE,1497
|
16
16
|
math_spec_mapping/Classes/StateUpdateTransmissionChannel.py,sha256=3hBLvD1lE64PkwqksBXAfFWv7foOZzGQLAFQWy42tOA,257
|
17
17
|
math_spec_mapping/Classes/StatefulMetric.py,sha256=UCis1BJ7fsajHHxFF05ZiyDean2D4s4a95uYYW1Mjq4,749
|
18
|
-
math_spec_mapping/Classes/Type.py,sha256=
|
18
|
+
math_spec_mapping/Classes/Type.py,sha256=2KFY8d3cv1PzJJ7SSMHJf1zcfQ3ZbqxotK2KgTaLZdM,289
|
19
19
|
math_spec_mapping/Classes/__init__.py,sha256=_hXyZMJanmIex_W6yCR2H7Jw8iU2JJIf3U7VcvBSOGU,737
|
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
|
@@ -23,27 +23,27 @@ math_spec_mapping/Convenience/starter.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
|
|
23
23
|
math_spec_mapping/Load/__init__.py,sha256=_ga5nHi7U5rY5lCF36_XI9Qmybq4P8R4m5I5mmjLBk8,33
|
24
24
|
math_spec_mapping/Load/action_transmission_channel.py,sha256=9Wer7g2s5SSOcUYuZ0PqSKUVVnW3EvGQJZNXJTwW__0,2561
|
25
25
|
math_spec_mapping/Load/boundary_actions.py,sha256=WvEj2tqN0pUZtE4EiKUuGzMdAcWsMlLslJJeFjIu6gk,2058
|
26
|
-
math_spec_mapping/Load/control_actions.py,sha256=
|
26
|
+
math_spec_mapping/Load/control_actions.py,sha256=4E57s730W4tX5SaKXKaAvet37r8Bwt-g8Kk6EanF4TU,2042
|
27
27
|
math_spec_mapping/Load/displays.py,sha256=ooHWT_OryzEkp7F3LcGywwdLMRJLxuyPK82zJ3gcyN0,414
|
28
28
|
math_spec_mapping/Load/entities.py,sha256=rMD_Pja-zqH1Z14rsO_Ia7dg3BIi5_HoQmqGAoEYofA,1208
|
29
29
|
math_spec_mapping/Load/general.py,sha256=2q6aGKxXhebiHHTZhtACvM4nWIkTben0o5rXuvfv2Vw,4463
|
30
30
|
math_spec_mapping/Load/implementations.py,sha256=SGKZ_YXeNpJUTnw5fajQTXji7S2bNQo8sh-7YcIO6pk,395
|
31
31
|
math_spec_mapping/Load/load.py,sha256=CLprDhJpbwm9RAzKM2Ghwr8eqBu0a-wvGDOCMmc01YE,2484
|
32
|
-
math_spec_mapping/Load/mechanism.py,sha256=
|
32
|
+
math_spec_mapping/Load/mechanism.py,sha256=JBy-QpB4W0Z2OcNiakONjD4_RtEgxlFKtLXfDqfhR-0,2037
|
33
33
|
math_spec_mapping/Load/metrics.py,sha256=gD68mt0Y5jSgofZUwscV8PFatOMV_LPwYyPrwV9SdtE,3273
|
34
34
|
math_spec_mapping/Load/parameters.py,sha256=aid_vqYub9643s82NDtMAXLRdV9BPQkri5MadA0L0eQ,1334
|
35
|
-
math_spec_mapping/Load/policy.py,sha256=
|
35
|
+
math_spec_mapping/Load/policy.py,sha256=HvlhGHGJTweVs7DOI2HSL_2_diECr8ukDUmzoFLQELo,2444
|
36
36
|
math_spec_mapping/Load/spaces.py,sha256=7zgGA57Te7T4hfuCCDElffiidWgn1lKm5E14e1yjt8M,1116
|
37
37
|
math_spec_mapping/Load/state_update_transmission_channels.py,sha256=FJWp5n4HdtHAfof5BUQ6BnRakljatL2h8dWCapaVSc0,2238
|
38
38
|
math_spec_mapping/Load/stateful_metrics.py,sha256=uGSTc6x6lld5xptgSUMHrO0Vg0QDRIL14C6zTg33S8o,1977
|
39
39
|
math_spec_mapping/Load/states.py,sha256=cwo29SBAtj1FoQLEb8c0wkSCn038lIgM9RjNiZefUaE,1223
|
40
|
-
math_spec_mapping/Load/type.py,sha256=
|
40
|
+
math_spec_mapping/Load/type.py,sha256=Wq2EYTofuq4v8_jGGSr23IXJjwavLMjsqSEyhX9VoAM,4217
|
41
41
|
math_spec_mapping/Load/wiring.py,sha256=1dR94U5N1W_WI5rL6lYBltH25ZvApB2pIpq9r5Opkug,3083
|
42
42
|
math_spec_mapping/Reports/__init__.py,sha256=W27I6S9Ro1hWeHmnxIokCA06awB__eYey7PvKD4Hc1s,933
|
43
43
|
math_spec_mapping/Reports/boundary_actions.py,sha256=45BPp4QjWdD-3E9ZWwqgj_nI2-YdcI2ZZ19_Qv_K7Qk,1410
|
44
44
|
math_spec_mapping/Reports/control_actions.py,sha256=NksekZKIPFSIkubttFstKFthc5AU9B9PWRLSl9j1wWs,1216
|
45
45
|
math_spec_mapping/Reports/general.py,sha256=WOOn6Wlb8M4fsdN49FlKLwOka6vJPQ9aCUy88TL2ki0,1610
|
46
|
-
math_spec_mapping/Reports/html.py,sha256=
|
46
|
+
math_spec_mapping/Reports/html.py,sha256=xf5jk3DHWg4CfZHZuF2JK5iZ515ecjDShJJsahiqb4g,8882
|
47
47
|
math_spec_mapping/Reports/markdown.py,sha256=pDGHYMdtZmeXHqvU9FB3BycyB4qflWXq0bf2m-wsXMU,21138
|
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
|
@@ -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.
|
57
|
-
math_spec_mapping-0.2.
|
58
|
-
math_spec_mapping-0.2.
|
59
|
-
math_spec_mapping-0.2.
|
60
|
-
math_spec_mapping-0.2.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|