fmu-manipulation-toolbox 1.9rc0__py3-none-any.whl → 1.9rc2__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/__init__.py +0 -1
- fmu_manipulation_toolbox/__main__.py +1 -1
- fmu_manipulation_toolbox/__version__.py +1 -1
- fmu_manipulation_toolbox/assembly.py +8 -6
- fmu_manipulation_toolbox/checker.py +11 -8
- fmu_manipulation_toolbox/container.py +492 -206
- fmu_manipulation_toolbox/gui.py +45 -55
- fmu_manipulation_toolbox/gui_style.py +8 -0
- fmu_manipulation_toolbox/operations.py +184 -120
- fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- 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 +8 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/METADATA +1 -1
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/RECORD +23 -22
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/WHEEL +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/entry_points.txt +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/licenses/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/top_level.txt +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import csv
|
|
2
2
|
import html
|
|
3
|
+
import logging
|
|
3
4
|
import os
|
|
4
5
|
import re
|
|
5
6
|
import shutil
|
|
@@ -10,13 +11,16 @@ import hashlib
|
|
|
10
11
|
from pathlib import Path
|
|
11
12
|
from typing import *
|
|
12
13
|
|
|
14
|
+
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
13
15
|
|
|
14
16
|
class FMU:
|
|
15
17
|
"""Unpack and Repack facilities for FMU package. Once unpacked, we can process Operation on
|
|
16
18
|
modelDescription.xml file."""
|
|
17
19
|
|
|
18
20
|
FMI2_TYPES = ('Real', 'Integer', 'String', 'Boolean', 'Enumeration')
|
|
19
|
-
FMI3_TYPES = ('Float64'
|
|
21
|
+
FMI3_TYPES = ('Float64', 'Float32',
|
|
22
|
+
'Int8', 'UInt8', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64',
|
|
23
|
+
'String', 'Boolean', 'Enumeration')
|
|
20
24
|
|
|
21
25
|
def __init__(self, fmu_filename):
|
|
22
26
|
self.fmu_filename = fmu_filename
|
|
@@ -51,6 +55,54 @@ class FMU:
|
|
|
51
55
|
manipulation.manipulate(self.descriptor_filename, apply_on)
|
|
52
56
|
|
|
53
57
|
|
|
58
|
+
class FMUPort:
|
|
59
|
+
def __init__(self):
|
|
60
|
+
self.fmi_type = None
|
|
61
|
+
self.attrs_list: List[Dict] = []
|
|
62
|
+
self.dimension = None
|
|
63
|
+
|
|
64
|
+
def dict_level(self, nb):
|
|
65
|
+
return " ".join([f'{key}="{value}"' for key, value in self.attrs_list[nb].items()])
|
|
66
|
+
|
|
67
|
+
def write_xml(self, fmi_version: int, file):
|
|
68
|
+
if fmi_version == 2:
|
|
69
|
+
print(f" <ScalarVariable {self.dict_level(0)}>", file=file)
|
|
70
|
+
print(f" <{self.fmi_type} {self.dict_level(1)}/>", file=file)
|
|
71
|
+
print(f" </ScalarVariable>", file=file)
|
|
72
|
+
elif fmi_version == 3:
|
|
73
|
+
print(f" <{self.fmi_type} {self.dict_level(0)}/>", file=file)
|
|
74
|
+
else:
|
|
75
|
+
raise FMUError(f"FMUPort writing: unsupported FMI version {fmi_version}")
|
|
76
|
+
|
|
77
|
+
def __contains__(self, item):
|
|
78
|
+
for attrs in self.attrs_list:
|
|
79
|
+
if item in attrs:
|
|
80
|
+
return True
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
def __getitem__(self, item):
|
|
84
|
+
for attrs in self.attrs_list:
|
|
85
|
+
if item in attrs:
|
|
86
|
+
return attrs[item]
|
|
87
|
+
raise KeyError
|
|
88
|
+
|
|
89
|
+
def __setitem__(self, key, value):
|
|
90
|
+
for attrs in self.attrs_list:
|
|
91
|
+
if key in attrs:
|
|
92
|
+
attrs[key] = value
|
|
93
|
+
return
|
|
94
|
+
raise KeyError
|
|
95
|
+
|
|
96
|
+
def get(self, item, default_value):
|
|
97
|
+
try:
|
|
98
|
+
return self[item]
|
|
99
|
+
except KeyError:
|
|
100
|
+
return default_value
|
|
101
|
+
|
|
102
|
+
def push_attrs(self, attrs):
|
|
103
|
+
self.attrs_list.append(attrs)
|
|
104
|
+
|
|
105
|
+
|
|
54
106
|
class FMUError(Exception):
|
|
55
107
|
def __init__(self, reason):
|
|
56
108
|
self.reason = reason
|
|
@@ -73,9 +125,12 @@ class Manipulation:
|
|
|
73
125
|
self.operation.set_fmu(fmu)
|
|
74
126
|
self.fmu = fmu
|
|
75
127
|
|
|
76
|
-
self.current_port:
|
|
77
|
-
|
|
128
|
+
self.current_port: Optional[FMUPort] = None
|
|
129
|
+
|
|
130
|
+
self.current_port_number: int = 0
|
|
131
|
+
self.port_translation: List[Optional[int]] = []
|
|
78
132
|
self.port_names_list: List[str] = []
|
|
133
|
+
self.port_removed_vr: Set[str] = set()
|
|
79
134
|
self.apply_on = None
|
|
80
135
|
|
|
81
136
|
@staticmethod
|
|
@@ -85,48 +140,55 @@ class Manipulation:
|
|
|
85
140
|
else:
|
|
86
141
|
return value
|
|
87
142
|
|
|
88
|
-
def
|
|
89
|
-
causality =
|
|
90
|
-
port_name =
|
|
143
|
+
def handle_port(self):
|
|
144
|
+
causality = self.current_port.get('causality', 'local')
|
|
145
|
+
port_name = self.current_port['name']
|
|
146
|
+
vr = self.current_port['valueReference']
|
|
91
147
|
if not self.apply_on or causality in self.apply_on:
|
|
92
|
-
if self.operation.
|
|
93
|
-
self.remove_port(port_name)
|
|
148
|
+
if self.operation.port_attrs(self.current_port):
|
|
149
|
+
self.remove_port(port_name, vr)
|
|
150
|
+
# Exception is raised by remove port !
|
|
94
151
|
else:
|
|
95
152
|
self.keep_port(port_name)
|
|
96
153
|
else: # Keep ScalarVariable as it is.
|
|
97
154
|
self.keep_port(port_name)
|
|
98
155
|
|
|
99
|
-
|
|
100
156
|
def start_element(self, name, attrs):
|
|
101
157
|
if self.skip_until:
|
|
102
158
|
return
|
|
103
159
|
try:
|
|
104
|
-
if name == 'ScalarVariable':
|
|
105
|
-
self.
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
self.
|
|
160
|
+
if name == 'ScalarVariable': # FMI 2.0 only
|
|
161
|
+
self.current_port = FMUPort()
|
|
162
|
+
self.current_port.push_attrs(attrs)
|
|
163
|
+
elif self.fmu.fmi_version == 2 and name in self.fmu.FMI2_TYPES:
|
|
164
|
+
self.current_port.fmi_type = name
|
|
165
|
+
self.current_port.push_attrs(attrs)
|
|
166
|
+
elif self.fmu.fmi_version == 3 and name in self.fmu.FMI3_TYPES:
|
|
167
|
+
self.current_port = FMUPort()
|
|
168
|
+
self.current_port.fmi_type = name
|
|
169
|
+
self.current_port.push_attrs(attrs)
|
|
109
170
|
elif name == 'CoSimulation':
|
|
110
171
|
self.operation.cosimulation_attrs(attrs)
|
|
111
172
|
elif name == 'DefaultExperiment':
|
|
112
173
|
self.operation.experiment_attrs(attrs)
|
|
113
174
|
elif name == 'fmiModelDescription':
|
|
175
|
+
self.fmu.fmi_version = int(float(attrs["fmiVersion"]))
|
|
114
176
|
self.operation.fmi_attrs(attrs)
|
|
115
|
-
elif name == 'Unknown':
|
|
177
|
+
elif name == 'Unknown': # FMI-2.0 only
|
|
116
178
|
self.unknown_attrs(attrs)
|
|
117
|
-
elif name
|
|
118
|
-
self.
|
|
179
|
+
elif name == 'Output' or name == "ContinuousStateDerivative" or "InitialUnknown":
|
|
180
|
+
self.handle_structure(attrs)
|
|
119
181
|
|
|
120
182
|
except ManipulationSkipTag:
|
|
121
183
|
self.skip_until = name
|
|
122
184
|
return
|
|
123
185
|
|
|
124
|
-
if
|
|
125
|
-
attrs
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
186
|
+
if self.current_port is None:
|
|
187
|
+
if attrs:
|
|
188
|
+
attrs_list = [f'{key}="{self.escape(value)}"' for (key, value) in attrs.items()]
|
|
189
|
+
print(f"<{name}", " ".join(attrs_list), ">", end='', file=self.out)
|
|
190
|
+
else:
|
|
191
|
+
print(f"<{name}>", end='', file=self.out)
|
|
130
192
|
|
|
131
193
|
def end_element(self, name):
|
|
132
194
|
if self.skip_until:
|
|
@@ -134,21 +196,31 @@ class Manipulation:
|
|
|
134
196
|
self.skip_until = None
|
|
135
197
|
return
|
|
136
198
|
else:
|
|
137
|
-
|
|
199
|
+
if name == "ScalarVariable" or (self.fmu.fmi_version == 3 and name in FMU.FMI3_TYPES):
|
|
200
|
+
try:
|
|
201
|
+
self.handle_port()
|
|
202
|
+
self.current_port.write_xml(self.fmu.fmi_version, self.out)
|
|
203
|
+
except ManipulationSkipTag:
|
|
204
|
+
logger.info(f"Port '{self.current_port['name']}' is removed.")
|
|
205
|
+
self.current_port = None
|
|
206
|
+
|
|
207
|
+
elif self.current_port is None:
|
|
208
|
+
print(f"</{name}>", end='', file=self.out)
|
|
138
209
|
|
|
139
210
|
def char_data(self, data):
|
|
140
211
|
if not self.skip_until:
|
|
141
212
|
print(data, end='', file=self.out)
|
|
142
213
|
|
|
143
|
-
def remove_port(self, name):
|
|
214
|
+
def remove_port(self, name, vr):
|
|
144
215
|
self.port_names_list.append(name)
|
|
145
216
|
self.port_translation.append(None)
|
|
217
|
+
self.port_removed_vr.add(vr)
|
|
146
218
|
raise ManipulationSkipTag
|
|
147
219
|
|
|
148
220
|
def keep_port(self, name):
|
|
149
221
|
self.port_names_list.append(name)
|
|
150
|
-
self.
|
|
151
|
-
self.port_translation.append(self.
|
|
222
|
+
self.current_port_number += 1
|
|
223
|
+
self.port_translation.append(self.current_port_number)
|
|
152
224
|
|
|
153
225
|
def unknown_attrs(self, attrs):
|
|
154
226
|
index = int(attrs['index']) - 1
|
|
@@ -156,9 +228,29 @@ class Manipulation:
|
|
|
156
228
|
if new_index:
|
|
157
229
|
attrs['index'] = self.port_translation[int(attrs['index']) - 1]
|
|
158
230
|
else:
|
|
159
|
-
|
|
231
|
+
logger.warning(f"Removed port '{self.port_names_list[index]}' is involved in dependencies tree.")
|
|
160
232
|
raise ManipulationSkipTag
|
|
161
233
|
|
|
234
|
+
def handle_structure(self, attrs):
|
|
235
|
+
try:
|
|
236
|
+
vr = attrs['valueReference']
|
|
237
|
+
if vr in self.port_removed_vr:
|
|
238
|
+
raise ManipulationSkipTag
|
|
239
|
+
except KeyError:
|
|
240
|
+
return
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
dependencies = attrs['dependencies']
|
|
244
|
+
new_dependencies = []
|
|
245
|
+
for dependency in dependencies.split(" "):
|
|
246
|
+
if dependency in self.port_removed_vr:
|
|
247
|
+
logger.warning(f"Removed port 'vr={dependency}' was involved in dependencies tree.")
|
|
248
|
+
else:
|
|
249
|
+
new_dependencies.append(dependency)
|
|
250
|
+
attrs['dependencies'] = " ".join(new_dependencies)
|
|
251
|
+
except KeyError:
|
|
252
|
+
return
|
|
253
|
+
|
|
162
254
|
def manipulate(self, descriptor_filename, apply_on=None):
|
|
163
255
|
self.apply_on = apply_on
|
|
164
256
|
with open(self.output_filename, "w", encoding="utf-8") as self.out, open(descriptor_filename, "rb") as file:
|
|
@@ -181,31 +273,19 @@ class OperationAbstract:
|
|
|
181
273
|
def fmi_attrs(self, attrs):
|
|
182
274
|
pass
|
|
183
275
|
|
|
184
|
-
def scalar_attrs(self, attrs) -> int:
|
|
185
|
-
""" return 0 to keep port, otherwise remove it"""
|
|
186
|
-
return 0
|
|
187
|
-
|
|
188
276
|
def cosimulation_attrs(self, attrs):
|
|
189
277
|
pass
|
|
190
278
|
|
|
191
279
|
def experiment_attrs(self, attrs):
|
|
192
280
|
pass
|
|
193
281
|
|
|
194
|
-
def
|
|
195
|
-
|
|
282
|
+
def port_attrs(self, fmu_port) -> int:
|
|
283
|
+
""" return 0 to keep port, otherwise remove it"""
|
|
284
|
+
return 0
|
|
196
285
|
|
|
197
286
|
def closure(self):
|
|
198
287
|
pass
|
|
199
288
|
|
|
200
|
-
@staticmethod
|
|
201
|
-
def scalar_get_causality(attrs) -> str:
|
|
202
|
-
try:
|
|
203
|
-
causality = attrs['causality']
|
|
204
|
-
except KeyError:
|
|
205
|
-
causality = 'local' # Default value according to FMI Specifications.
|
|
206
|
-
|
|
207
|
-
return causality
|
|
208
|
-
|
|
209
289
|
|
|
210
290
|
class OperationSaveNamesToCSV(OperationAbstract):
|
|
211
291
|
def __repr__(self):
|
|
@@ -217,48 +297,29 @@ class OperationSaveNamesToCSV(OperationAbstract):
|
|
|
217
297
|
self.writer = csv.writer(self.csvfile, delimiter=';', quotechar="'", quoting=csv.QUOTE_MINIMAL)
|
|
218
298
|
self.writer.writerow(['name', 'newName', 'valueReference', 'causality', 'variability', 'scalarType',
|
|
219
299
|
'startValue'])
|
|
220
|
-
self.name = None
|
|
221
|
-
self.vr = None
|
|
222
|
-
self.variability = None
|
|
223
|
-
self.causality = None
|
|
224
|
-
|
|
225
|
-
def reset(self):
|
|
226
|
-
self.name = None
|
|
227
|
-
self.vr = None
|
|
228
|
-
self.variability = None
|
|
229
|
-
self.causality = None
|
|
230
300
|
|
|
231
301
|
def closure(self):
|
|
232
302
|
self.csvfile.close()
|
|
233
303
|
|
|
234
|
-
def
|
|
235
|
-
self.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
self.variability = 'continuous' # Default value according to FMI Specifications.
|
|
304
|
+
def port_attrs(self, fmu_port: FMUPort) -> int:
|
|
305
|
+
self.writer.writerow([fmu_port["name"],
|
|
306
|
+
fmu_port["name"],
|
|
307
|
+
fmu_port["valueReference"],
|
|
308
|
+
fmu_port.get("causality", "local"),
|
|
309
|
+
fmu_port.get("variability", "continuous"),
|
|
310
|
+
fmu_port.fmi_type,
|
|
311
|
+
fmu_port.get("start", "")])
|
|
243
312
|
|
|
244
313
|
return 0
|
|
245
314
|
|
|
246
|
-
def scalar_type(self, type_name, attrs):
|
|
247
|
-
if "start" in attrs:
|
|
248
|
-
start = attrs["start"]
|
|
249
|
-
else:
|
|
250
|
-
start = ""
|
|
251
|
-
self.writer.writerow([self.name, self.name, self.vr, self.causality, self.variability, type_name, start])
|
|
252
|
-
self.reset()
|
|
253
|
-
|
|
254
315
|
|
|
255
316
|
class OperationStripTopLevel(OperationAbstract):
|
|
256
317
|
def __repr__(self):
|
|
257
318
|
return "Remove Top Level Bus"
|
|
258
319
|
|
|
259
|
-
def
|
|
260
|
-
new_name =
|
|
261
|
-
|
|
320
|
+
def port_attrs(self, fmu_port):
|
|
321
|
+
new_name = fmu_port['name'].split('.', 1)[-1]
|
|
322
|
+
fmu_port['name'] = new_name
|
|
262
323
|
return 0
|
|
263
324
|
|
|
264
325
|
|
|
@@ -266,9 +327,9 @@ class OperationMergeTopLevel(OperationAbstract):
|
|
|
266
327
|
def __repr__(self):
|
|
267
328
|
return "Merge Top Level Bus with signal names"
|
|
268
329
|
|
|
269
|
-
def
|
|
270
|
-
old =
|
|
271
|
-
|
|
330
|
+
def port_attrs(self, fmu_port):
|
|
331
|
+
old = fmu_port['name']
|
|
332
|
+
fmu_port['name'] = old.replace('.', '_', 1)
|
|
272
333
|
return 0
|
|
273
334
|
|
|
274
335
|
|
|
@@ -279,27 +340,26 @@ class OperationRenameFromCSV(OperationAbstract):
|
|
|
279
340
|
def __init__(self, csv_filename):
|
|
280
341
|
self.csv_filename = csv_filename
|
|
281
342
|
self.translations = {}
|
|
282
|
-
|
|
283
|
-
self.port_translation = []
|
|
343
|
+
|
|
284
344
|
try:
|
|
285
345
|
with open(csv_filename, newline='') as csvfile:
|
|
286
346
|
reader = csv.reader(csvfile, delimiter=';', quotechar="'")
|
|
287
347
|
for row in reader:
|
|
288
348
|
self.translations[row[0]] = row[1]
|
|
289
349
|
except FileNotFoundError:
|
|
290
|
-
raise
|
|
350
|
+
raise OperationError(f"file '{csv_filename}' is not found")
|
|
291
351
|
except KeyError:
|
|
292
|
-
raise
|
|
352
|
+
raise OperationError(f"file '{csv_filename}' should contain two columns")
|
|
293
353
|
|
|
294
|
-
def
|
|
295
|
-
name =
|
|
354
|
+
def port_attrs(self, fmu_port):
|
|
355
|
+
name = fmu_port['name']
|
|
296
356
|
try:
|
|
297
|
-
new_name = self.translations[
|
|
357
|
+
new_name = self.translations[fmu_port['name']]
|
|
298
358
|
except KeyError:
|
|
299
359
|
new_name = name # if port is not in CSV file, keep old name
|
|
300
360
|
|
|
301
361
|
if new_name:
|
|
302
|
-
|
|
362
|
+
fmu_port['name'] = new_name
|
|
303
363
|
return 0
|
|
304
364
|
else:
|
|
305
365
|
# we want to delete this name!
|
|
@@ -313,6 +373,10 @@ class OperationAddRemotingWinAbstract(OperationAbstract):
|
|
|
313
373
|
def __repr__(self):
|
|
314
374
|
return f"Add '{self.bitness_to}' remoting on '{self.bitness_from}' FMU"
|
|
315
375
|
|
|
376
|
+
def fmi_attrs(self, attrs):
|
|
377
|
+
if not attrs["fmiVersion"] == "2.0":
|
|
378
|
+
raise OperationError(f"Adding remoting is only available for FMI-2.0")
|
|
379
|
+
|
|
316
380
|
def cosimulation_attrs(self, attrs):
|
|
317
381
|
fmu_bin = {
|
|
318
382
|
"win32": os.path.join(self.fmu.tmp_directory, "binaries", f"win32"),
|
|
@@ -320,10 +384,10 @@ class OperationAddRemotingWinAbstract(OperationAbstract):
|
|
|
320
384
|
}
|
|
321
385
|
|
|
322
386
|
if not os.path.isdir(fmu_bin[self.bitness_from]):
|
|
323
|
-
raise
|
|
387
|
+
raise OperationError(f"{self.bitness_from} interface does not exist")
|
|
324
388
|
|
|
325
389
|
if os.path.isdir(fmu_bin[self.bitness_to]):
|
|
326
|
-
|
|
390
|
+
logger.info(f"{self.bitness_to} already exists. Add front-end.")
|
|
327
391
|
shutil.move(os.path.join(fmu_bin[self.bitness_to], attrs['modelIdentifier'] + ".dll"),
|
|
328
392
|
os.path.join(fmu_bin[self.bitness_to], attrs['modelIdentifier'] + "-remoted.dll"))
|
|
329
393
|
else:
|
|
@@ -368,11 +432,11 @@ class OperationRemoveRegexp(OperationAbstract):
|
|
|
368
432
|
def __init__(self, regex_string):
|
|
369
433
|
self.regex_string = regex_string
|
|
370
434
|
self.regex = re.compile(regex_string)
|
|
371
|
-
self.
|
|
435
|
+
self.current_port_number = 0
|
|
372
436
|
self.port_translation = []
|
|
373
437
|
|
|
374
|
-
def
|
|
375
|
-
name =
|
|
438
|
+
def port_attrs(self, fmu_port):
|
|
439
|
+
name = fmu_port['name']
|
|
376
440
|
if self.regex.match(name):
|
|
377
441
|
return 1 # Remove port
|
|
378
442
|
else:
|
|
@@ -387,8 +451,8 @@ class OperationKeepOnlyRegexp(OperationAbstract):
|
|
|
387
451
|
self.regex_string = regex_string
|
|
388
452
|
self.regex = re.compile(regex_string)
|
|
389
453
|
|
|
390
|
-
def
|
|
391
|
-
name =
|
|
454
|
+
def port_attrs(self, fmu_port):
|
|
455
|
+
name = fmu_port['name']
|
|
392
456
|
if self.regex.match(name):
|
|
393
457
|
return 0
|
|
394
458
|
else:
|
|
@@ -403,34 +467,34 @@ class OperationSummary(OperationAbstract):
|
|
|
403
467
|
return f"FMU Summary"
|
|
404
468
|
|
|
405
469
|
def fmi_attrs(self, attrs):
|
|
406
|
-
|
|
407
|
-
|
|
470
|
+
logger.info(f"| fmu filename = {self.fmu.fmu_filename}")
|
|
471
|
+
logger.info(f"| temporary directory = {self.fmu.tmp_directory}")
|
|
408
472
|
hash_md5 = hashlib.md5()
|
|
409
473
|
with open(self.fmu.fmu_filename, "rb") as f:
|
|
410
474
|
for chunk in iter(lambda: f.read(4096), b""):
|
|
411
475
|
hash_md5.update(chunk)
|
|
412
476
|
digest = hash_md5.hexdigest()
|
|
413
|
-
|
|
477
|
+
logger.info(f"| MD5Sum = {digest}")
|
|
414
478
|
|
|
415
|
-
|
|
479
|
+
logger.info(f"|\n| FMI properties: ")
|
|
416
480
|
for (k, v) in attrs.items():
|
|
417
|
-
|
|
418
|
-
|
|
481
|
+
logger.info(f"| - {k} = {v}")
|
|
482
|
+
logger.info(f"|")
|
|
419
483
|
|
|
420
484
|
def cosimulation_attrs(self, attrs):
|
|
421
|
-
|
|
485
|
+
logger.info("| Co-Simulation capabilities: ")
|
|
422
486
|
for (k, v) in attrs.items():
|
|
423
|
-
|
|
424
|
-
|
|
487
|
+
logger.info(f"| - {k} = {v}")
|
|
488
|
+
logger.info(f"|")
|
|
425
489
|
|
|
426
490
|
def experiment_attrs(self, attrs):
|
|
427
|
-
|
|
491
|
+
logger.info("| Default Experiment values: ")
|
|
428
492
|
for (k, v) in attrs.items():
|
|
429
|
-
|
|
430
|
-
|
|
493
|
+
logger.info(f"| - {k} = {v}")
|
|
494
|
+
logger.info(f"|")
|
|
431
495
|
|
|
432
|
-
def
|
|
433
|
-
causality =
|
|
496
|
+
def port_attrs(self, fmu_port) -> int:
|
|
497
|
+
causality = fmu_port.get("causality", "local")
|
|
434
498
|
|
|
435
499
|
try:
|
|
436
500
|
self.nb_port_per_causality[causality] += 1
|
|
@@ -440,33 +504,33 @@ class OperationSummary(OperationAbstract):
|
|
|
440
504
|
return 0
|
|
441
505
|
|
|
442
506
|
def closure(self):
|
|
443
|
-
|
|
507
|
+
logger.info("| Supported platforms: ")
|
|
444
508
|
try:
|
|
445
509
|
for platform in os.listdir(os.path.join(self.fmu.tmp_directory, "binaries")):
|
|
446
|
-
|
|
510
|
+
logger.info(f"| - {platform}")
|
|
447
511
|
except FileNotFoundError:
|
|
448
512
|
pass # no binaries
|
|
449
513
|
|
|
450
514
|
if os.path.isdir(os.path.join(self.fmu.tmp_directory, "sources")):
|
|
451
|
-
|
|
515
|
+
logger.info(f"| - RT (sources available)")
|
|
452
516
|
|
|
453
517
|
resource_dir = os.path.join(self.fmu.tmp_directory, "resources")
|
|
454
518
|
if os.path.isdir(resource_dir):
|
|
455
|
-
|
|
519
|
+
logger.info("|\n| Embedded resources:")
|
|
456
520
|
for resource in os.listdir(resource_dir):
|
|
457
|
-
|
|
521
|
+
logger.info(f"| - {resource}")
|
|
458
522
|
|
|
459
523
|
extra_dir = os.path.join(self.fmu.tmp_directory, "extra")
|
|
460
524
|
if os.path.isdir(extra_dir):
|
|
461
|
-
|
|
525
|
+
logger.info("|\n| Additional (meta-)data:")
|
|
462
526
|
for extra in os.listdir(extra_dir):
|
|
463
|
-
|
|
527
|
+
logger.info(f"| - {extra}")
|
|
464
528
|
|
|
465
|
-
|
|
529
|
+
logger.info("|\n| Number of ports")
|
|
466
530
|
for causality, nb_ports in self.nb_port_per_causality.items():
|
|
467
|
-
|
|
531
|
+
logger.info(f"| {causality} : {nb_ports}")
|
|
468
532
|
|
|
469
|
-
|
|
533
|
+
logger.info("|\n| [End of report]")
|
|
470
534
|
|
|
471
535
|
|
|
472
536
|
class OperationRemoveSources(OperationAbstract):
|
|
@@ -477,7 +541,7 @@ class OperationRemoveSources(OperationAbstract):
|
|
|
477
541
|
try:
|
|
478
542
|
shutil.rmtree(os.path.join(self.fmu.tmp_directory, "sources"))
|
|
479
543
|
except FileNotFoundError:
|
|
480
|
-
|
|
544
|
+
logger.info("This FMU does not embed sources.")
|
|
481
545
|
|
|
482
546
|
|
|
483
547
|
class OperationTrimUntil(OperationAbstract):
|
|
@@ -487,17 +551,17 @@ class OperationTrimUntil(OperationAbstract):
|
|
|
487
551
|
def __repr__(self):
|
|
488
552
|
return f"Trim names until (and including) '{self.separator}'"
|
|
489
553
|
|
|
490
|
-
def
|
|
491
|
-
name =
|
|
554
|
+
def port_attrs(self, fmu_port) -> int:
|
|
555
|
+
name = fmu_port['name']
|
|
492
556
|
try:
|
|
493
|
-
|
|
557
|
+
fmu_port['name'] = name[name.index(self.separator)+len(self.separator):-1]
|
|
494
558
|
except KeyError:
|
|
495
559
|
pass # no separator
|
|
496
560
|
|
|
497
561
|
return 0
|
|
498
562
|
|
|
499
563
|
|
|
500
|
-
class
|
|
564
|
+
class OperationError(Exception):
|
|
501
565
|
def __init__(self, reason):
|
|
502
566
|
self.reason = reason
|
|
503
567
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -198,7 +198,15 @@ class FMUSplitterDescription:
|
|
|
198
198
|
self.config["candidate_fmu"] = []
|
|
199
199
|
|
|
200
200
|
for i in range(nb_fmu):
|
|
201
|
+
# format is
|
|
202
|
+
# filename.fmu
|
|
203
|
+
# or
|
|
204
|
+
# filename.fmu fmi_version
|
|
201
205
|
fmu_filename = self.get_line(file)
|
|
206
|
+
if ' ' in fmu_filename:
|
|
207
|
+
fmu_filename = fmu_filename.split(' ')[0]
|
|
208
|
+
# fmi version is not needed for further operations
|
|
209
|
+
|
|
202
210
|
base_directory = "/".join(txt_filename.split("/")[0:-1])
|
|
203
211
|
|
|
204
212
|
directory = f"{base_directory}/{fmu_filename}"
|
{fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.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.9rc2
|
|
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.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/RECORD
RENAMED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
fmu_manipulation_toolbox/__init__.py,sha256=
|
|
2
|
-
fmu_manipulation_toolbox/__main__.py,sha256=
|
|
3
|
-
fmu_manipulation_toolbox/__version__.py,sha256=
|
|
4
|
-
fmu_manipulation_toolbox/assembly.py,sha256=
|
|
5
|
-
fmu_manipulation_toolbox/checker.py,sha256=
|
|
6
|
-
fmu_manipulation_toolbox/container.py,sha256=
|
|
7
|
-
fmu_manipulation_toolbox/gui.py,sha256=
|
|
8
|
-
fmu_manipulation_toolbox/gui_style.py,sha256=
|
|
1
|
+
fmu_manipulation_toolbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
fmu_manipulation_toolbox/__main__.py,sha256=FpG0ITBz5q-AvIbXplVh_1g1zla5souFGtpiDdECxEw,352
|
|
3
|
+
fmu_manipulation_toolbox/__version__.py,sha256=Z-9JT4Rjt43p25I55xHJame93p0nfRXYoSRRq-Je6wY,11
|
|
4
|
+
fmu_manipulation_toolbox/assembly.py,sha256=XQ_1sB6K1Dk2mnNe-E3_6Opoeub7F9Qaln0EUDzsop8,26553
|
|
5
|
+
fmu_manipulation_toolbox/checker.py,sha256=jw1omfrMMIMHlIpHXpWBcQgIiS9hnHe5T9CZ5KlbVGs,2422
|
|
6
|
+
fmu_manipulation_toolbox/container.py,sha256=8Wf16sgUPkY-ByWeKt-3TD_4vNRQuLwH9Gs7D2Q6tAk,44959
|
|
7
|
+
fmu_manipulation_toolbox/gui.py,sha256=iOJ3F_zfw3mU34VofZrYdaffljTmYfuy33fJXlLaOwg,29045
|
|
8
|
+
fmu_manipulation_toolbox/gui_style.py,sha256=s6WdrnNd_lCMWhuBf5LKK8wrfLXCU7pFTLUfvqkJVno,6633
|
|
9
9
|
fmu_manipulation_toolbox/help.py,sha256=aklKiLrsE0adSzQ5uoEB1sBDmI6s4l231gavu4XxxzA,5856
|
|
10
|
-
fmu_manipulation_toolbox/operations.py,sha256=
|
|
11
|
-
fmu_manipulation_toolbox/split.py,sha256=
|
|
10
|
+
fmu_manipulation_toolbox/operations.py,sha256=b7N5AVHLIpQO8od4BYasb9CppHJ-ZmW8mu0ZdhndoHI,19472
|
|
11
|
+
fmu_manipulation_toolbox/split.py,sha256=NVkfdTRR0jj_VOdgtxHQoKptkAg5TFVUA7nUx3_o9Pg,13336
|
|
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
|
|
@@ -27,6 +27,7 @@ fmu_manipulation_toolbox/resources/icon_fmu.png,sha256=EuygB2xcoM2WAfKKdyKG_UvTL
|
|
|
27
27
|
fmu_manipulation_toolbox/resources/license.txt,sha256=5ODuU8g8pIkK-NMWXu_rjZ6k7gM7b-N2rmg87-2Kmqw,1583
|
|
28
28
|
fmu_manipulation_toolbox/resources/mask.png,sha256=px1U4hQGL0AmZ4BQPknOVREpMpTSejbah3ntkpqAzFA,3008
|
|
29
29
|
fmu_manipulation_toolbox/resources/model.png,sha256=EAf_HnZJe8zYGZygerG1MMt2U-tMMZlifzXPj4_iORA,208788
|
|
30
|
+
fmu_manipulation_toolbox/resources/darwin64/container.dylib,sha256=G6ABYe2mBmI_0pGU6HJly3yhKh6VEirgN4RFAThUES4,161496
|
|
30
31
|
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd,sha256=OGfyJtaJntKypX5KDpuZ-nV1oYLZ6HV16pkpKOmYox4,2731
|
|
31
32
|
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd,sha256=HwyV7LBse-PQSv4z1xjmtzPU3Hjnv4mluq9YdSBNHMQ,3704
|
|
32
33
|
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd,sha256=JM4j_9q-pc40XYHb28jfT3iV3aYM5JLqD5aRjO72K1E,18939
|
|
@@ -49,16 +50,16 @@ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd,sha256=YQS
|
|
|
49
50
|
fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=xVdY2zy13pa2DcvFiweSNpp7E6DiONqeoBdlcJHrW_k,35940
|
|
50
51
|
fmu_manipulation_toolbox/resources/linux32/server_sm,sha256=1TLGqNPyM5UVOrCfzNqWyF6ClLksY3EiY3CSsrnp6c0,22836
|
|
51
52
|
fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=EhY1XHo1YcQn6yqZ7wk5okqtZyp0MrcCsGcudqE-aIM,37000
|
|
52
|
-
fmu_manipulation_toolbox/resources/linux64/container.so,sha256=
|
|
53
|
+
fmu_manipulation_toolbox/resources/linux64/container.so,sha256=KtvL1rmCFE6FA2mFGoHEhIYqAYd47ZmJLK5YsyO7TqM,135464
|
|
53
54
|
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.
|
|
55
|
+
fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=rL9OCeoOmCvzf88mFubyPvTDImKxO26fNHoX5a_wuaI,17920
|
|
56
|
+
fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=NGBZkTqSBFg8Wja_BYqoumk6qKmQoND4n8tDcPvKj8g,15872
|
|
57
|
+
fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=UZi61eVctdZ0jLEsC5GWAG4zM6LTq6firPYNByz39LQ,22016
|
|
58
|
+
fmu_manipulation_toolbox/resources/win64/container.dll,sha256=6-HLcAhtd68PMD0SVloSrfpFJlUdSJLp58hqjzCLsHQ,97792
|
|
59
|
+
fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=wWZuT98XkCraZNNlWsnxoxoYABsXiJbxVDXg5zirnjI,19968
|
|
60
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
|
|
61
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/METADATA,sha256=CAh7QGHMed2PqNbtoLGwhn46FEwESV4uXEMaAPIPkJY,1156
|
|
62
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
63
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/entry_points.txt,sha256=HjOZkflbI1IuSY8BpOZre20m24M4GDQGCJfPIa7NrlY,264
|
|
64
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
|
|
65
|
+
fmu_manipulation_toolbox-1.9rc2.dist-info/RECORD,,
|
{fmu_manipulation_toolbox-1.9rc0.dist-info → fmu_manipulation_toolbox-1.9rc2.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|