fmu-manipulation-toolbox 1.8.4.3b0__py3-none-any.whl → 1.9rc0__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.
- fmu_manipulation_toolbox/__version__.py +1 -1
- fmu_manipulation_toolbox/assembly.py +13 -6
- fmu_manipulation_toolbox/container.py +14 -20
- fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
- fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
- fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
- fmu_manipulation_toolbox/split.py +25 -9
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/METADATA +1 -1
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/RECORD +16 -16
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/WHEEL +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/entry_points.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/licenses/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/top_level.txt +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
'V1.
|
|
1
|
+
'V1.9-pre0'
|
|
@@ -37,7 +37,7 @@ class Connection:
|
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
class AssemblyNode:
|
|
40
|
-
def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False,
|
|
40
|
+
def __init__(self, name: Optional[str], step_size: float = None, mt=False, profiling=False, sequential=False,
|
|
41
41
|
auto_link=True, auto_input=True, auto_output=True, auto_parameter=False, auto_local=False):
|
|
42
42
|
self.name = name
|
|
43
43
|
if step_size:
|
|
@@ -50,6 +50,7 @@ class AssemblyNode:
|
|
|
50
50
|
self.step_size = None
|
|
51
51
|
self.mt = mt
|
|
52
52
|
self.profiling = profiling
|
|
53
|
+
self.sequential = sequential
|
|
53
54
|
self.auto_link = auto_link
|
|
54
55
|
self.auto_input = auto_input
|
|
55
56
|
self.auto_output = auto_output
|
|
@@ -138,7 +139,8 @@ class AssemblyNode:
|
|
|
138
139
|
for link_rule in wired.rule_link:
|
|
139
140
|
self.add_link(link_rule[0], link_rule[1], link_rule[2], link_rule[3])
|
|
140
141
|
|
|
141
|
-
container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling,
|
|
142
|
+
container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
|
|
143
|
+
debug=debug)
|
|
142
144
|
|
|
143
145
|
for node in self.children.values():
|
|
144
146
|
logger.info(f"Deleting transient FMU Container '{node.name}'")
|
|
@@ -216,7 +218,7 @@ class AssemblyError(Exception):
|
|
|
216
218
|
|
|
217
219
|
|
|
218
220
|
class Assembly:
|
|
219
|
-
def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False,
|
|
221
|
+
def __init__(self, filename: str, step_size=None, auto_link=True, auto_input=True, debug=False, sequential=False,
|
|
220
222
|
auto_output=True, mt=False, profiling=False, fmu_directory: Path = Path("."), auto_parameter=False,
|
|
221
223
|
auto_local=False):
|
|
222
224
|
self.filename = Path(filename)
|
|
@@ -228,6 +230,7 @@ class Assembly:
|
|
|
228
230
|
self.default_auto_parameter = auto_parameter
|
|
229
231
|
self.default_auto_local = auto_local
|
|
230
232
|
self.default_mt = mt
|
|
233
|
+
self.default_sequential = sequential
|
|
231
234
|
self.default_profiling = profiling
|
|
232
235
|
self.fmu_directory = fmu_directory
|
|
233
236
|
self.transient_filenames: List[Path] = []
|
|
@@ -283,8 +286,9 @@ class Assembly:
|
|
|
283
286
|
name = str(self.filename.with_suffix(".fmu"))
|
|
284
287
|
self.root = AssemblyNode(name, step_size=self.default_step_size, auto_link=self.default_auto_link,
|
|
285
288
|
mt=self.default_mt, profiling=self.default_profiling,
|
|
286
|
-
|
|
287
|
-
|
|
289
|
+
sequential=self.default_sequential, auto_input=self.default_auto_input,
|
|
290
|
+
auto_output=self.default_auto_output, auto_parameter=self.default_auto_parameter,
|
|
291
|
+
auto_local=self.default_auto_local)
|
|
288
292
|
|
|
289
293
|
with open(self.input_pathname) as file:
|
|
290
294
|
reader = csv.reader(file, delimiter=';')
|
|
@@ -385,6 +389,7 @@ class Assembly:
|
|
|
385
389
|
name = data.get("name", None) # 1
|
|
386
390
|
mt = data.get("mt", self.default_mt) # 2
|
|
387
391
|
profiling = data.get("profiling", self.default_profiling) # 3
|
|
392
|
+
sequential = data.get("sequential", self.default_sequential) # 3b
|
|
388
393
|
auto_link = data.get("auto_link", self.default_auto_link) # 4
|
|
389
394
|
auto_input = data.get("auto_input", self.default_auto_input) # 5
|
|
390
395
|
auto_output = data.get("auto_output", self.default_auto_output) # 6
|
|
@@ -393,11 +398,12 @@ class Assembly:
|
|
|
393
398
|
step_size = data.get("step_size", self.default_step_size) # 7
|
|
394
399
|
|
|
395
400
|
node = AssemblyNode(name, step_size=step_size, auto_link=auto_link, mt=mt, profiling=profiling,
|
|
401
|
+
sequential=sequential,
|
|
396
402
|
auto_input=auto_input, auto_output=auto_output, auto_parameter=auto_parameter,
|
|
397
403
|
auto_local=auto_local)
|
|
398
404
|
|
|
399
405
|
for key, value in data.items():
|
|
400
|
-
if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling',
|
|
406
|
+
if key in ('name', 'step_size', 'auto_link', 'auto_input', 'auto_output', 'mt', 'profiling', 'sequential',
|
|
401
407
|
'auto_parameter', 'auto_local'):
|
|
402
408
|
continue # Already read
|
|
403
409
|
|
|
@@ -455,6 +461,7 @@ class Assembly:
|
|
|
455
461
|
json_node["name"] = node.name # 1
|
|
456
462
|
json_node["mt"] = node.mt # 2
|
|
457
463
|
json_node["profiling"] = node.profiling # 3
|
|
464
|
+
json_node["sequential"] = node.sequential # 3b
|
|
458
465
|
json_node["auto_link"] = node.auto_link # 4
|
|
459
466
|
json_node["auto_input"] = node.auto_input # 5
|
|
460
467
|
json_node["auto_output"] = node.auto_output # 6
|
|
@@ -16,15 +16,15 @@ logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
|
16
16
|
|
|
17
17
|
class FMUPort:
|
|
18
18
|
def __init__(self, attrs: Dict[str, str]):
|
|
19
|
-
self.causality = attrs.
|
|
20
|
-
self.variability = attrs.
|
|
21
|
-
self.name = attrs.
|
|
22
|
-
self.vr = int(attrs.
|
|
23
|
-
self.description = attrs.
|
|
19
|
+
self.causality = attrs.get("causality", "local")
|
|
20
|
+
self.variability = attrs.get("variability", "continuous")
|
|
21
|
+
self.name = attrs.get("name")
|
|
22
|
+
self.vr = int(attrs.get("valueReference"))
|
|
23
|
+
self.description = attrs.get("description", None)
|
|
24
24
|
|
|
25
|
-
self.type_name = attrs.
|
|
26
|
-
self.start_value = attrs.
|
|
27
|
-
self.initial = attrs.
|
|
25
|
+
self.type_name = attrs.get("type_name", None)
|
|
26
|
+
self.start_value = attrs.get("start", None)
|
|
27
|
+
self.initial = attrs.get("initial", None)
|
|
28
28
|
|
|
29
29
|
def set_port_type(self, type_name: str, attrs: Dict[str, str]):
|
|
30
30
|
self.type_name = type_name
|
|
@@ -465,7 +465,7 @@ class FMUContainer:
|
|
|
465
465
|
logger.warning(f"{cport} is not connected")
|
|
466
466
|
|
|
467
467
|
def make_fmu(self, fmu_filename: Union[str, Path], step_size: Optional[float] = None, debug=False, mt=False,
|
|
468
|
-
profiling=False):
|
|
468
|
+
profiling=False, sequential=False):
|
|
469
469
|
if isinstance(fmu_filename, str):
|
|
470
470
|
fmu_filename = Path(fmu_filename)
|
|
471
471
|
|
|
@@ -481,7 +481,7 @@ class FMUContainer:
|
|
|
481
481
|
with open(base_directory / "modelDescription.xml", "wt") as xml_file:
|
|
482
482
|
self.make_fmu_xml(xml_file, step_size, profiling)
|
|
483
483
|
with open(resources_directory / "container.txt", "wt") as txt_file:
|
|
484
|
-
self.make_fmu_txt(txt_file, step_size, mt, profiling)
|
|
484
|
+
self.make_fmu_txt(txt_file, step_size, mt, profiling, sequential)
|
|
485
485
|
|
|
486
486
|
self.make_fmu_package(base_directory, fmu_filename)
|
|
487
487
|
if not debug:
|
|
@@ -594,16 +594,10 @@ class FMUContainer:
|
|
|
594
594
|
</fmiModelDescription>
|
|
595
595
|
""")
|
|
596
596
|
|
|
597
|
-
def make_fmu_txt(self, txt_file, step_size: float, mt: bool, profiling: bool):
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
print("# Don't use MT\n0", file=txt_file)
|
|
602
|
-
|
|
603
|
-
if profiling:
|
|
604
|
-
print("# Profiling ENABLED\n1", file=txt_file)
|
|
605
|
-
else:
|
|
606
|
-
print("# Profiling DISABLED\n0", file=txt_file)
|
|
597
|
+
def make_fmu_txt(self, txt_file, step_size: float, mt: bool, profiling: bool, sequential: bool):
|
|
598
|
+
print("# Container flags <MT> <Profiling> <Sequential>", file=txt_file)
|
|
599
|
+
flags = [ str(int(flag == True)) for flag in (mt, profiling, sequential)]
|
|
600
|
+
print(" ".join(flags), file=txt_file)
|
|
607
601
|
|
|
608
602
|
print(f"# Internal time step in seconds", file=txt_file)
|
|
609
603
|
print(f"{step_size}", file=txt_file)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -40,6 +40,7 @@ class FMUSplitter:
|
|
|
40
40
|
def __init__(self, fmu_filename: str):
|
|
41
41
|
self.fmu_filename = Path(fmu_filename)
|
|
42
42
|
self.directory = self.fmu_filename.with_suffix(".dir")
|
|
43
|
+
self.zip = None # to handle error
|
|
43
44
|
self.zip = zipfile.ZipFile(self.fmu_filename)
|
|
44
45
|
self.filenames_list = self.zip.namelist()
|
|
45
46
|
self.dir_set = self.get_dir_set()
|
|
@@ -58,8 +59,9 @@ class FMUSplitter:
|
|
|
58
59
|
return dir_set
|
|
59
60
|
|
|
60
61
|
def __del__(self):
|
|
61
|
-
|
|
62
|
-
|
|
62
|
+
if self.zip is not None:
|
|
63
|
+
logger.debug("Closing zip file")
|
|
64
|
+
self.zip.close()
|
|
63
65
|
|
|
64
66
|
def split_fmu(self):
|
|
65
67
|
logger.info(f"Splitting...")
|
|
@@ -178,8 +180,18 @@ class FMUSplitterDescription:
|
|
|
178
180
|
parser.ParseFile(file)
|
|
179
181
|
|
|
180
182
|
def parse_txt_file_header(self, file, txt_filename):
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
flags = self.get_line(file).split(" ")
|
|
184
|
+
if len(flags) == 1:
|
|
185
|
+
self.config["mt"] = flags[0] == "1"
|
|
186
|
+
self.config["profiling"] = self.get_line(file) == "1"
|
|
187
|
+
self.config["sequential"] = False
|
|
188
|
+
elif len(flags) == 3:
|
|
189
|
+
self.config["mt"] = flags[0] == "1"
|
|
190
|
+
self.config["profiling"] = flags[1] == "1"
|
|
191
|
+
self.config["sequential"] = flags[2] == "1"
|
|
192
|
+
else:
|
|
193
|
+
raise FMUSplitterError(f"Cannot interpret flags '{flags}'")
|
|
194
|
+
|
|
183
195
|
self.config["step_size"] = float(self.get_line(file))
|
|
184
196
|
nb_fmu = int(self.get_line(file))
|
|
185
197
|
logger.debug(f"Number of FMUs: {nb_fmu}")
|
|
@@ -188,10 +200,15 @@ class FMUSplitterDescription:
|
|
|
188
200
|
for i in range(nb_fmu):
|
|
189
201
|
fmu_filename = self.get_line(file)
|
|
190
202
|
base_directory = "/".join(txt_filename.split("/")[0:-1])
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
203
|
+
|
|
204
|
+
directory = f"{base_directory}/{fmu_filename}"
|
|
205
|
+
if f"{directory}/modelDescription.xml" not in self.zip.namelist():
|
|
206
|
+
directory = f"{base_directory}/{i:02x}"
|
|
207
|
+
if f"{directory}/modelDescription.xml" not in self.zip.namelist():
|
|
208
|
+
print(self.zip.namelist())
|
|
209
|
+
raise FMUSplitterError(f"Cannot find in FMU directory in {directory}.")
|
|
210
|
+
|
|
211
|
+
self.parse_model_description(directory, fmu_filename)
|
|
195
212
|
self.config["candidate_fmu"].append(fmu_filename)
|
|
196
213
|
_library = self.get_line(file)
|
|
197
214
|
_uuid = self.get_line(file)
|
|
@@ -241,7 +258,6 @@ class FMUSplitterDescription:
|
|
|
241
258
|
self.parse_txt_file_header(file, txt_filename)
|
|
242
259
|
self.parse_txt_file_ports(file)
|
|
243
260
|
|
|
244
|
-
|
|
245
261
|
for fmu_filename in self.config["candidate_fmu"]:
|
|
246
262
|
# Inputs per FMUs
|
|
247
263
|
for fmi_type in ("Real", "Integer", "Boolean", "String"):
|
{fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: fmu_manipulation_toolbox
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9rc0
|
|
4
4
|
Summary: FMU Manipulation Toolbox is a python application for modifying Functional Mock-up Units (FMUs) without recompilation or bundling them into FMU Containers
|
|
5
5
|
Home-page: https://github.com/grouperenault/fmu_manipulation_toolbox/
|
|
6
6
|
Author: Nicolas.LAURENT@Renault.com
|
{fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/RECORD
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
fmu_manipulation_toolbox/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
2
2
|
fmu_manipulation_toolbox/__main__.py,sha256=mAzrtkil506DS0F3g3CEbHdtZsZotzntcNhIn_lNJkw,344
|
|
3
|
-
fmu_manipulation_toolbox/__version__.py,sha256=
|
|
4
|
-
fmu_manipulation_toolbox/assembly.py,sha256=
|
|
3
|
+
fmu_manipulation_toolbox/__version__.py,sha256=pIetL3-rgAy__3Y9bhoI5aPvTCG8a1qRIBr7IZdM-aA,12
|
|
4
|
+
fmu_manipulation_toolbox/assembly.py,sha256=1jlNc_Rfls2Nah22sd9IL11rC0J5MWs0slT4Bc3sjOw,26364
|
|
5
5
|
fmu_manipulation_toolbox/checker.py,sha256=836wCri6aEl0M6_xHPZ94JRngFjsy8Ee-_t8bzclxBs,2332
|
|
6
|
-
fmu_manipulation_toolbox/container.py,sha256=
|
|
6
|
+
fmu_manipulation_toolbox/container.py,sha256=DjzRgSGNth50V-8eQ107mbYZQq1Q5-ZPsO6E-oZG4KE,32831
|
|
7
7
|
fmu_manipulation_toolbox/gui.py,sha256=tVTPLbGZlD5P0WYqaD5B4crG2nHjBGe73yAJrzRXpYE,29218
|
|
8
8
|
fmu_manipulation_toolbox/gui_style.py,sha256=uzEruJumnC5Vf2cfHXVa_c-SHAQoTvDWemro3-b9Mpc,6492
|
|
9
9
|
fmu_manipulation_toolbox/help.py,sha256=aklKiLrsE0adSzQ5uoEB1sBDmI6s4l231gavu4XxxzA,5856
|
|
10
10
|
fmu_manipulation_toolbox/operations.py,sha256=p0e6OgNRT0JrQaDjhdHk1rxVoRXbdhPHueVvn021UdM,16346
|
|
11
|
-
fmu_manipulation_toolbox/split.py,sha256=
|
|
11
|
+
fmu_manipulation_toolbox/split.py,sha256=lHIct-ANlFB0p7MgViUaSF8jlOlD1-M7TP-I-x9kkpI,13061
|
|
12
12
|
fmu_manipulation_toolbox/version.py,sha256=OhBLkZ1-nhC77kyvffPNAf6m8OZe1bYTnNf_PWs1NvM,392
|
|
13
13
|
fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png,sha256=FWIuyrXlaNLLePHfXj7j9ca5rT8Hgr14KCe1EqTCZyk,2288
|
|
14
14
|
fmu_manipulation_toolbox/resources/checkbox-checked-hover.png,sha256=KNlV-d_aJNTTvUVXKGT9DBY30sIs2LwocLJrFKNKv8k,2419
|
|
@@ -49,16 +49,16 @@ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd,sha256=YQS
|
|
|
49
49
|
fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=xVdY2zy13pa2DcvFiweSNpp7E6DiONqeoBdlcJHrW_k,35940
|
|
50
50
|
fmu_manipulation_toolbox/resources/linux32/server_sm,sha256=1TLGqNPyM5UVOrCfzNqWyF6ClLksY3EiY3CSsrnp6c0,22836
|
|
51
51
|
fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=EhY1XHo1YcQn6yqZ7wk5okqtZyp0MrcCsGcudqE-aIM,37000
|
|
52
|
-
fmu_manipulation_toolbox/resources/linux64/container.so,sha256=
|
|
52
|
+
fmu_manipulation_toolbox/resources/linux64/container.so,sha256=0hpVEgJkGxbgMeoVAgeqL73aewZ8j-tfzXlf0A0UBpM,85064
|
|
53
53
|
fmu_manipulation_toolbox/resources/linux64/server_sm,sha256=ulfoPvmaYe9nInYcVEyj7mD9zDzGk56OUoWx1mPKLiE,22768
|
|
54
|
-
fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=
|
|
55
|
-
fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=
|
|
56
|
-
fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=
|
|
57
|
-
fmu_manipulation_toolbox/resources/win64/container.dll,sha256=
|
|
58
|
-
fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=
|
|
59
|
-
fmu_manipulation_toolbox-1.
|
|
60
|
-
fmu_manipulation_toolbox-1.
|
|
61
|
-
fmu_manipulation_toolbox-1.
|
|
62
|
-
fmu_manipulation_toolbox-1.
|
|
63
|
-
fmu_manipulation_toolbox-1.
|
|
64
|
-
fmu_manipulation_toolbox-1.
|
|
54
|
+
fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=ZF0W5N4ZZgMWVnyYrLrEgxamj3WNw667QK5pqK4HvnA,17920
|
|
55
|
+
fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=KnUM49rDTpTHjVr-J2kfBsYnQnPsX7ho6H7vTlF8i-E,15872
|
|
56
|
+
fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=58N8xOmJ9XU_oe2rC9JP95lzR-IhDzbwD9FDPaQ7VtM,22016
|
|
57
|
+
fmu_manipulation_toolbox/resources/win64/container.dll,sha256=bvxsESgpzAn7IyLnf5Oc41pBPCM7tQz0LJrlXaSpTJQ,57856
|
|
58
|
+
fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=ftJC5fBoCnlzrcbLJBIfniOAieWGFHZ5klv5UFL9LEE,19968
|
|
59
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
|
|
60
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/METADATA,sha256=kWBmPNMw9UYn11B144bSf7H0inSSo6uD-Cpe0h2OyQ4,1156
|
|
61
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
62
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/entry_points.txt,sha256=HjOZkflbI1IuSY8BpOZre20m24M4GDQGCJfPIa7NrlY,264
|
|
63
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
|
|
64
|
+
fmu_manipulation_toolbox-1.9rc0.dist-info/RECORD,,
|
{fmu_manipulation_toolbox-1.8.4.3b0.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|