fmu-manipulation-toolbox 1.8.4.2rc1__py3-none-any.whl → 1.9__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 +22 -13
- fmu_manipulation_toolbox/checker.py +16 -11
- fmu_manipulation_toolbox/cli/__init__.py +0 -0
- fmu_manipulation_toolbox/cli/fmucontainer.py +105 -0
- fmu_manipulation_toolbox/cli/fmusplit.py +48 -0
- fmu_manipulation_toolbox/cli/fmutool.py +127 -0
- fmu_manipulation_toolbox/cli/utils.py +36 -0
- fmu_manipulation_toolbox/container.py +1054 -0
- fmu_manipulation_toolbox/gui.py +48 -56
- fmu_manipulation_toolbox/gui_style.py +8 -0
- fmu_manipulation_toolbox/help.py +3 -0
- fmu_manipulation_toolbox/operations.py +577 -0
- fmu_manipulation_toolbox/remoting.py +107 -0
- fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +51 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +119 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +117 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +80 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +93 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +131 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +87 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +84 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +207 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +69 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +413 -0
- fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +64 -0
- fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
- fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
- fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
- fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
- fmu_manipulation_toolbox/resources/linux64/server_sm +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 +331 -0
- {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/METADATA +1 -1
- fmu_manipulation_toolbox-1.9.dist-info/RECORD +71 -0
- fmu_manipulation_toolbox-1.9.dist-info/entry_points.txt +7 -0
- fmu_manipulation_toolbox/cli.py +0 -235
- fmu_manipulation_toolbox/fmu_container.py +0 -753
- fmu_manipulation_toolbox/fmu_operations.py +0 -489
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/RECORD +0 -52
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/entry_points.txt +0 -3
- {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/WHEEL +0 -0
- {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/licenses/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import zipfile
|
|
3
|
+
import json
|
|
4
|
+
import xml.parsers.expat
|
|
5
|
+
|
|
6
|
+
from typing import *
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
from .container import EmbeddedFMUPort
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class FMUSplitterError(Exception):
|
|
15
|
+
def __init__(self, message: str):
|
|
16
|
+
self.message = message
|
|
17
|
+
|
|
18
|
+
def __str__(self):
|
|
19
|
+
return str(self.message)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class FMUSplitterPort:
|
|
23
|
+
def __init__(self, fmu_filename: str, port_name):
|
|
24
|
+
self.fmu_filename = fmu_filename
|
|
25
|
+
self.port_name = port_name
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return f"{self.fmu_filename}/{self.port_name}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class FMUSplitterLink:
|
|
32
|
+
def __init__(self):
|
|
33
|
+
self.from_port: Optional[FMUSplitterPort] = None
|
|
34
|
+
self.to_port: List[FMUSplitterPort] = []
|
|
35
|
+
|
|
36
|
+
def __str__(self):
|
|
37
|
+
to_str = ", ".join([f"{port}" for port in self.to_port])
|
|
38
|
+
return f"{self.from_port} -> {to_str}"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class FMUSplitter:
|
|
42
|
+
def __init__(self, fmu_filename: str):
|
|
43
|
+
self.fmu_filename = Path(fmu_filename)
|
|
44
|
+
self.directory = self.fmu_filename.with_suffix(".dir")
|
|
45
|
+
self.zip = None # to handle error
|
|
46
|
+
self.zip = zipfile.ZipFile(self.fmu_filename)
|
|
47
|
+
self.filenames_list = self.zip.namelist()
|
|
48
|
+
self.dir_set = self.get_dir_set()
|
|
49
|
+
|
|
50
|
+
if "resources/container.txt" not in self.filenames_list:
|
|
51
|
+
raise FMUSplitterError(f"FMU file {self.fmu_filename} is not an FMU Container.")
|
|
52
|
+
|
|
53
|
+
self.directory.mkdir(exist_ok=True)
|
|
54
|
+
logger.info(f"Preparing to split '{self.fmu_filename}' into '{self.directory}'")
|
|
55
|
+
|
|
56
|
+
def get_dir_set(self) -> Set[str]:
|
|
57
|
+
dir_set = set()
|
|
58
|
+
for filename in self.filenames_list:
|
|
59
|
+
parent = "/".join(filename.split("/")[:-1])
|
|
60
|
+
dir_set.add(parent+"/")
|
|
61
|
+
return dir_set
|
|
62
|
+
|
|
63
|
+
def __del__(self):
|
|
64
|
+
if self.zip is not None:
|
|
65
|
+
logger.debug("Closing zip file")
|
|
66
|
+
self.zip.close()
|
|
67
|
+
|
|
68
|
+
def split_fmu(self):
|
|
69
|
+
logger.info(f"Splitting...")
|
|
70
|
+
config = self._split_fmu(fmu_filename=str(self.fmu_filename), relative_path="")
|
|
71
|
+
config_filename = self.directory / self.fmu_filename.with_suffix(".json").name
|
|
72
|
+
with open(config_filename, "w") as file:
|
|
73
|
+
json.dump(config, file, indent=2)
|
|
74
|
+
logger.info(f"Container definition saved to '{config_filename}'")
|
|
75
|
+
|
|
76
|
+
def _split_fmu(self, fmu_filename: str, relative_path: str) -> Dict[str, Any]:
|
|
77
|
+
txt_filename = f"{relative_path}resources/container.txt"
|
|
78
|
+
|
|
79
|
+
if txt_filename in self.filenames_list:
|
|
80
|
+
description = FMUSplitterDescription(self.zip)
|
|
81
|
+
config = description.parse_txt_file(txt_filename)
|
|
82
|
+
config["name"] = Path(fmu_filename).name
|
|
83
|
+
for i, fmu_filename in enumerate(config["candidate_fmu"]):
|
|
84
|
+
directory = f"{relative_path}resources/{i:02x}/"
|
|
85
|
+
if directory not in self.dir_set:
|
|
86
|
+
directory = f"{relative_path}resources/{fmu_filename}/"
|
|
87
|
+
if directory not in self.dir_set:
|
|
88
|
+
raise FMUSplitterError(f"{directory} not found in FMU")
|
|
89
|
+
sub_config = self._split_fmu(fmu_filename=fmu_filename, relative_path=directory)
|
|
90
|
+
if isinstance(sub_config, str):
|
|
91
|
+
key = "fmu"
|
|
92
|
+
else:
|
|
93
|
+
key = "container"
|
|
94
|
+
try:
|
|
95
|
+
config[key].append(sub_config)
|
|
96
|
+
except KeyError:
|
|
97
|
+
config[key] = [sub_config]
|
|
98
|
+
config.pop("candidate_fmu")
|
|
99
|
+
else:
|
|
100
|
+
config = fmu_filename
|
|
101
|
+
self.extract_fmu(relative_path, str(self.directory / fmu_filename))
|
|
102
|
+
|
|
103
|
+
return config
|
|
104
|
+
|
|
105
|
+
def extract_fmu(self, directory: str, filename: str):
|
|
106
|
+
logger.debug(f"Extracting {directory} to {filename}")
|
|
107
|
+
with zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED) as fmu_file:
|
|
108
|
+
for file in self.zip.namelist():
|
|
109
|
+
if file.startswith(directory):
|
|
110
|
+
data = self.zip.read(file)
|
|
111
|
+
fmu_file.writestr(file[len(directory):], data)
|
|
112
|
+
logger.info(f"FMU Extraction of '{filename}'")
|
|
113
|
+
|
|
114
|
+
class FMUSplitterDescription:
|
|
115
|
+
def __init__(self, zip):
|
|
116
|
+
self.zip = zip
|
|
117
|
+
self.links: Dict[str, Dict[int, FMUSplitterLink]] = dict((el, {}) for el in EmbeddedFMUPort.ALL_TYPES)
|
|
118
|
+
self.vr_to_name: Dict[str, Dict[str, Dict[int, Dict[str, str]]]] = {} # name, fmi_type, vr <-> {name, causality}
|
|
119
|
+
self.config: Dict[str, Any] = {
|
|
120
|
+
"auto_input": False,
|
|
121
|
+
"auto_output": False,
|
|
122
|
+
"auto_parameter": False,
|
|
123
|
+
"auto_local": False,
|
|
124
|
+
"auto_link": False,
|
|
125
|
+
}
|
|
126
|
+
self.fmu_filename_list = []
|
|
127
|
+
|
|
128
|
+
# used for modelDescription.xml parsing
|
|
129
|
+
self.current_fmu_filename = None
|
|
130
|
+
self.current_fmi_version = None
|
|
131
|
+
self.current_vr = None
|
|
132
|
+
self.current_name = None
|
|
133
|
+
self.current_causality = None
|
|
134
|
+
self.supported_fmi_types: Tuple[str] = tuple()
|
|
135
|
+
|
|
136
|
+
@staticmethod
|
|
137
|
+
def get_line(file):
|
|
138
|
+
for line in file:
|
|
139
|
+
line = line.decode('utf-8').strip()
|
|
140
|
+
if line and not line.startswith("#"):
|
|
141
|
+
return line
|
|
142
|
+
raise StopIteration
|
|
143
|
+
|
|
144
|
+
def start_element(self, tag, attrs):
|
|
145
|
+
if tag == "fmiModelDescription":
|
|
146
|
+
self.current_fmi_version = attrs["fmiVersion"]
|
|
147
|
+
elif tag == "ScalarVariable":
|
|
148
|
+
self.current_name = attrs["name"]
|
|
149
|
+
self.current_vr = int(attrs["valueReference"])
|
|
150
|
+
self.current_causality = attrs["causality"]
|
|
151
|
+
elif self.current_fmi_version == "2.0" and tag in EmbeddedFMUPort.FMI_TO_CONTAINER[2]:
|
|
152
|
+
fmi_type = EmbeddedFMUPort.FMI_TO_CONTAINER[2][tag]
|
|
153
|
+
self.vr_to_name[self.current_fmu_filename][fmi_type][self.current_vr] = {
|
|
154
|
+
"name": self.current_name,
|
|
155
|
+
"causality": self.current_causality}
|
|
156
|
+
elif self.current_fmi_version == "3.0" and tag in EmbeddedFMUPort.FMI_TO_CONTAINER[3]:
|
|
157
|
+
fmi_type = EmbeddedFMUPort.FMI_TO_CONTAINER[3][tag]
|
|
158
|
+
self.vr_to_name[self.current_fmu_filename][fmi_type][int(attrs["valueReference"])] = {
|
|
159
|
+
"name": attrs["name"],
|
|
160
|
+
"causality": attrs["causality"]}
|
|
161
|
+
else:
|
|
162
|
+
self.current_vr = None
|
|
163
|
+
self.current_name = None
|
|
164
|
+
self.current_causality = None
|
|
165
|
+
|
|
166
|
+
def parse_model_description(self, directory: str, fmu_filename: str):
|
|
167
|
+
|
|
168
|
+
if directory == ".":
|
|
169
|
+
filename = "modelDescription.xml"
|
|
170
|
+
else:
|
|
171
|
+
filename = f"{directory}/modelDescription.xml"
|
|
172
|
+
|
|
173
|
+
self.vr_to_name[fmu_filename] = dict((el, {}) for el in EmbeddedFMUPort.ALL_TYPES)
|
|
174
|
+
parser = xml.parsers.expat.ParserCreate()
|
|
175
|
+
self.current_fmu_filename = fmu_filename
|
|
176
|
+
self.current_fmi_version = None
|
|
177
|
+
self.current_vr = None
|
|
178
|
+
self.current_name = None
|
|
179
|
+
self.current_causality = None
|
|
180
|
+
parser.StartElementHandler = self.start_element
|
|
181
|
+
with (self.zip.open(filename) as file):
|
|
182
|
+
logger.debug(f"Parsing '{filename}' ({fmu_filename})")
|
|
183
|
+
parser.ParseFile(file)
|
|
184
|
+
|
|
185
|
+
def parse_txt_file_header(self, file, txt_filename):
|
|
186
|
+
flags = self.get_line(file).split(" ")
|
|
187
|
+
if len(flags) == 1:
|
|
188
|
+
self.supported_fmi_types = ("Real", "Integer", "Boolean", "String")
|
|
189
|
+
self.config["mt"] = flags[0] == "1"
|
|
190
|
+
self.config["profiling"] = self.get_line(file) == "1"
|
|
191
|
+
self.config["sequential"] = False
|
|
192
|
+
elif len(flags) == 3:
|
|
193
|
+
self.supported_fmi_types = EmbeddedFMUPort.ALL_TYPES
|
|
194
|
+
self.config["mt"] = flags[0] == "1"
|
|
195
|
+
self.config["profiling"] = flags[1] == "1"
|
|
196
|
+
self.config["sequential"] = flags[2] == "1"
|
|
197
|
+
else:
|
|
198
|
+
raise FMUSplitterError(f"Cannot interpret flags '{flags}'")
|
|
199
|
+
|
|
200
|
+
self.config["step_size"] = float(self.get_line(file))
|
|
201
|
+
nb_fmu = int(self.get_line(file))
|
|
202
|
+
logger.debug(f"Number of FMUs: {nb_fmu}")
|
|
203
|
+
self.config["candidate_fmu"] = []
|
|
204
|
+
|
|
205
|
+
for i in range(nb_fmu):
|
|
206
|
+
# format is
|
|
207
|
+
# filename.fmu
|
|
208
|
+
# or
|
|
209
|
+
# filename.fmu fmi_version
|
|
210
|
+
fmu_filename = self.get_line(file)
|
|
211
|
+
if ' ' in fmu_filename:
|
|
212
|
+
fmu_filename = fmu_filename.split(' ')[0]
|
|
213
|
+
# fmi version is not needed for further operations
|
|
214
|
+
|
|
215
|
+
base_directory = "/".join(txt_filename.split("/")[0:-1])
|
|
216
|
+
|
|
217
|
+
directory = f"{base_directory}/{fmu_filename}"
|
|
218
|
+
if f"{directory}/modelDescription.xml" not in self.zip.namelist():
|
|
219
|
+
directory = f"{base_directory}/{i:02x}"
|
|
220
|
+
if f"{directory}/modelDescription.xml" not in self.zip.namelist():
|
|
221
|
+
print(self.zip.namelist())
|
|
222
|
+
raise FMUSplitterError(f"Cannot find in FMU directory in {directory}.")
|
|
223
|
+
|
|
224
|
+
self.parse_model_description(directory, fmu_filename)
|
|
225
|
+
self.config["candidate_fmu"].append(fmu_filename)
|
|
226
|
+
_library = self.get_line(file)
|
|
227
|
+
_uuid = self.get_line(file)
|
|
228
|
+
_nb_local_variables = self.get_line(file)
|
|
229
|
+
|
|
230
|
+
def add_port(self, fmi_type: str, fmu_id: int, fmu_vr: int, container_vr: int):
|
|
231
|
+
if fmu_id >= 0:
|
|
232
|
+
fmu_filename = self.config["candidate_fmu"][fmu_id]
|
|
233
|
+
causality = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["causality"]
|
|
234
|
+
fmu_port_name = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["name"]
|
|
235
|
+
container_port = self.vr_to_name["."][fmi_type][container_vr]["name"]
|
|
236
|
+
if not causality == "output":
|
|
237
|
+
causality = "input"
|
|
238
|
+
definition = [container_port, fmu_filename, fmu_port_name]
|
|
239
|
+
else:
|
|
240
|
+
definition = [fmu_filename, fmu_port_name, container_port]
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
self.config[causality].append(definition)
|
|
244
|
+
except KeyError:
|
|
245
|
+
self.config[causality] = [definition]
|
|
246
|
+
|
|
247
|
+
logger.debug(f"Adding container port {causality}: {definition}")
|
|
248
|
+
|
|
249
|
+
def parse_txt_file_ports(self, file):
|
|
250
|
+
for fmi_type in self.supported_fmi_types:
|
|
251
|
+
nb_port_variables = self.get_line(file).split(" ")[0]
|
|
252
|
+
for i in range(int(nb_port_variables)):
|
|
253
|
+
tokens = self.get_line(file).split(" ")
|
|
254
|
+
if len(tokens) > 3:
|
|
255
|
+
container_vr = int(tokens[0])
|
|
256
|
+
for j in range(int(tokens[1])):
|
|
257
|
+
fmu_id = int(tokens[2 + 2 * j])
|
|
258
|
+
fmu_vr = int(tokens[2 + 2 * j + 1])
|
|
259
|
+
self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
|
|
260
|
+
else: # For FMUContainer <= 1.8.4
|
|
261
|
+
container_vr = int(tokens[0])
|
|
262
|
+
fmu_id = int(tokens[1])
|
|
263
|
+
fmu_vr = int(tokens[2])
|
|
264
|
+
self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
|
|
265
|
+
|
|
266
|
+
def parse_txt_file(self, txt_filename: str):
|
|
267
|
+
self.parse_model_description(str(Path(txt_filename).parent.parent), ".")
|
|
268
|
+
logger.debug(f"Parsing container file '{txt_filename}'")
|
|
269
|
+
with (self.zip.open(txt_filename) as file):
|
|
270
|
+
self.parse_txt_file_header(file, txt_filename)
|
|
271
|
+
self.parse_txt_file_ports(file)
|
|
272
|
+
|
|
273
|
+
for fmu_filename in self.config["candidate_fmu"]:
|
|
274
|
+
# Inputs per FMUs
|
|
275
|
+
|
|
276
|
+
for fmi_type in self.supported_fmi_types:
|
|
277
|
+
nb_input = int(self.get_line(file))
|
|
278
|
+
for i in range(nb_input):
|
|
279
|
+
local, vr = self.get_line(file).split(" ")
|
|
280
|
+
try:
|
|
281
|
+
link = self.links[fmi_type][local]
|
|
282
|
+
except KeyError:
|
|
283
|
+
link = FMUSplitterLink()
|
|
284
|
+
self.links[fmi_type][local] = link
|
|
285
|
+
link.to_port.append(FMUSplitterPort(fmu_filename,
|
|
286
|
+
self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"]))
|
|
287
|
+
|
|
288
|
+
for fmi_type in self.supported_fmi_types:
|
|
289
|
+
nb_start = int(self.get_line(file))
|
|
290
|
+
for i in range(nb_start):
|
|
291
|
+
tokens = self.get_line(file).split(" ")
|
|
292
|
+
vr = int(tokens[0])
|
|
293
|
+
value = tokens[-1]
|
|
294
|
+
start_definition = [fmu_filename, self.vr_to_name[fmu_filename][fmi_type][vr]["name"],
|
|
295
|
+
value]
|
|
296
|
+
try:
|
|
297
|
+
self.config["start"].append(start_definition)
|
|
298
|
+
except KeyError:
|
|
299
|
+
self.config["start"] = [start_definition]
|
|
300
|
+
|
|
301
|
+
# Output per FMUs
|
|
302
|
+
for fmi_type in self.supported_fmi_types:
|
|
303
|
+
nb_output = int(self.get_line(file))
|
|
304
|
+
|
|
305
|
+
for i in range(nb_output):
|
|
306
|
+
local, vr = self.get_line(file).split(" ")
|
|
307
|
+
try:
|
|
308
|
+
link = self.links[fmi_type][local]
|
|
309
|
+
except KeyError:
|
|
310
|
+
link = FMUSplitterLink()
|
|
311
|
+
self.links[fmi_type][local] = link
|
|
312
|
+
link.from_port = FMUSplitterPort(fmu_filename,
|
|
313
|
+
self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"])
|
|
314
|
+
#conversion
|
|
315
|
+
nb_conversion = int(self.get_line(file))
|
|
316
|
+
for i in range(nb_conversion):
|
|
317
|
+
self.get_line(file)
|
|
318
|
+
|
|
319
|
+
logger.debug("End of parsing.")
|
|
320
|
+
|
|
321
|
+
for fmi_type, links in self.links.items():
|
|
322
|
+
for link in links.values():
|
|
323
|
+
for to_port in link.to_port:
|
|
324
|
+
definition = [ link.from_port.fmu_filename, link.from_port.port_name,
|
|
325
|
+
to_port.fmu_filename, to_port.port_name]
|
|
326
|
+
try:
|
|
327
|
+
self.config["link"].append(definition)
|
|
328
|
+
except KeyError:
|
|
329
|
+
self.config["link"] = [definition]
|
|
330
|
+
|
|
331
|
+
return self.config
|
{fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.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.9
|
|
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
|
|
@@ -0,0 +1,71 @@
|
|
|
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=RpjnZ-g4XsDa0uZToxk2ez_E9cmR3N2SrOqy0awR3so,7
|
|
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=Ed6JsWM2oMs-jyGyKmrHHebNuG4qwiGLYtx0BREIiBE,45710
|
|
7
|
+
fmu_manipulation_toolbox/gui.py,sha256=ax-IbGO7GyBG0Mb5okN588CKQDfMxoF1uZtD1_CYnjc,29199
|
|
8
|
+
fmu_manipulation_toolbox/gui_style.py,sha256=s6WdrnNd_lCMWhuBf5LKK8wrfLXCU7pFTLUfvqkJVno,6633
|
|
9
|
+
fmu_manipulation_toolbox/help.py,sha256=j8xmnCrwQpaW-SZ8hSqA1dlTXgaqzQWc4Yr3RH_oqck,6012
|
|
10
|
+
fmu_manipulation_toolbox/operations.py,sha256=VQvFXRHF48e-ZLqoG8nbz61iB5lX6qAkqZHQ0m0lUPw,20577
|
|
11
|
+
fmu_manipulation_toolbox/remoting.py,sha256=N25MDFkIcEWe9CIT1M4L9kea3j-8E7i2I1VOI6zIAdw,3876
|
|
12
|
+
fmu_manipulation_toolbox/split.py,sha256=yFaW6yhvFjOXpRynWzitR7o7uSrxb-RxeFzmQNxUFHI,14147
|
|
13
|
+
fmu_manipulation_toolbox/version.py,sha256=OhBLkZ1-nhC77kyvffPNAf6m8OZe1bYTnNf_PWs1NvM,392
|
|
14
|
+
fmu_manipulation_toolbox/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
fmu_manipulation_toolbox/cli/fmucontainer.py,sha256=6UaSSY6UGGlOfIh_CTG-Gk3ZPSd88Pi2cFCuzb87eks,4839
|
|
16
|
+
fmu_manipulation_toolbox/cli/fmusplit.py,sha256=VMDYjmvIsjPHJINZaOt1Zy8D0so6d99285LbS8v-Tro,1734
|
|
17
|
+
fmu_manipulation_toolbox/cli/fmutool.py,sha256=QRe6xQxQMD8FtEzoT5421Bq0YasgdIwOd9Too5TX5zg,6086
|
|
18
|
+
fmu_manipulation_toolbox/cli/utils.py,sha256=gNhdlFYSSNSb0fovzS0crnxgmqqKXe0KtoZZFhRKhfg,1375
|
|
19
|
+
fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png,sha256=FWIuyrXlaNLLePHfXj7j9ca5rT8Hgr14KCe1EqTCZyk,2288
|
|
20
|
+
fmu_manipulation_toolbox/resources/checkbox-checked-hover.png,sha256=KNlV-d_aJNTTvUVXKGT9DBY30sIs2LwocLJrFKNKv8k,2419
|
|
21
|
+
fmu_manipulation_toolbox/resources/checkbox-checked.png,sha256=gzyFqvRFsZixVh6ZlV4SMWUKzglY1rSn7SvJUKMVvtk,2411
|
|
22
|
+
fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png,sha256=KNdiE8zJ8H-mH81spHL8Ck-V87dj-fPPPrPNZFRv3wA,1783
|
|
23
|
+
fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png,sha256=7XT54vwzDfSK-i6oJ5BBKGXKz8duRRVtoUzaOlWX0WE,1797
|
|
24
|
+
fmu_manipulation_toolbox/resources/checkbox-unchecked.png,sha256=w3MG3RwFeTwkVOAFi8ZBs6yNlmtVnXxXY5atNyvLw54,1793
|
|
25
|
+
fmu_manipulation_toolbox/resources/container.png,sha256=DnMSCl4hlZqYuLDJpE4EnKIhYYXRbUZ7C_Q2HmAOaHU,16682
|
|
26
|
+
fmu_manipulation_toolbox/resources/drop_fmu.png,sha256=Q7yWe3hzBYuou2xlPN9Yg9lgQYFSVuYxGnp_SRwkVe0,10344
|
|
27
|
+
fmu_manipulation_toolbox/resources/fmu.png,sha256=QrNZ5PRaana0r-7pbluYf20m8ngzOZEZWi-MPSQG1eU,47050
|
|
28
|
+
fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png,sha256=iuztmrW9f3Ayi4fe_WdkYZbI1VXrCa1HVasfIhW5J18,38023
|
|
29
|
+
fmu_manipulation_toolbox/resources/help.png,sha256=WrIbjmlgIqdo6UWYj6L6gG-BCGWlu4qma8HRgRk8k7o,1822
|
|
30
|
+
fmu_manipulation_toolbox/resources/icon-round.png,sha256=j7jk-9NVQQZJMNazjpj8WeC1q6ptXwTaiO38kPoDEnE,83754
|
|
31
|
+
fmu_manipulation_toolbox/resources/icon.png,sha256=Ovui-UDBARqdTlVQwTn5Ud8seSsVh9pdElwLq5s6xKg,69976
|
|
32
|
+
fmu_manipulation_toolbox/resources/icon_fmu.png,sha256=EuygB2xcoM2WAfKKdyKG_UvTL8coM4CkpHSIsSCe_Ks,5189
|
|
33
|
+
fmu_manipulation_toolbox/resources/license.txt,sha256=5ODuU8g8pIkK-NMWXu_rjZ6k7gM7b-N2rmg87-2Kmqw,1583
|
|
34
|
+
fmu_manipulation_toolbox/resources/mask.png,sha256=px1U4hQGL0AmZ4BQPknOVREpMpTSejbah3ntkpqAzFA,3008
|
|
35
|
+
fmu_manipulation_toolbox/resources/model.png,sha256=EAf_HnZJe8zYGZygerG1MMt2U-tMMZlifzXPj4_iORA,208788
|
|
36
|
+
fmu_manipulation_toolbox/resources/darwin64/container.dylib,sha256=omGiU38-2Zh6pyvPjySKDQ5TNDRVS2lkNDIf8BjHD8A,161560
|
|
37
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd,sha256=OGfyJtaJntKypX5KDpuZ-nV1oYLZ6HV16pkpKOmYox4,2731
|
|
38
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd,sha256=HwyV7LBse-PQSv4z1xjmtzPU3Hjnv4mluq9YdSBNHMQ,3704
|
|
39
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd,sha256=JM4j_9q-pc40XYHb28jfT3iV3aYM5JLqD5aRjO72K1E,18939
|
|
40
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd,sha256=hYZGmhvHBuycWMGe1Gt9xQY82c4Ek_5wAO1P2xu5txQ,9675
|
|
41
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd,sha256=8A0hl2wb1suoxv47xezkmvVTyJM2ZJp5RPQ2xQ_SjlY,3883
|
|
42
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd,sha256=pB9Pe-yBMGZN-JQAu6VB_lXS99kz23mwiUSY74ONZd4,5403
|
|
43
|
+
fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd,sha256=Tc9RWKqvUXpB1qsoU64DAHO4Gfu5DotrQJ3Ece7GnTU,4647
|
|
44
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd,sha256=H4OB87z_hK5CSrpbzZjxva9VLpitI94Nbm8lQOlwkp8,2570
|
|
45
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd,sha256=g6jtK05vCrlHBKun__QqIUe-S7ja6wDZ3KgpaJpReyY,6141
|
|
46
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd,sha256=G4clniTvFReBcqoABaU8t16OIeMJVZNzW9q1Qys8c9k,7516
|
|
47
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd,sha256=2KkVadEBEK1L2aatQ3HOjhl2XIv7V6tWcT9WmvpYyI4,4652
|
|
48
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd,sha256=DhSi-eVKFmdUv6tHsjWf8GYEfbymhxQKbGbeJYMtGLs,4474
|
|
49
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd,sha256=0W02POCyDiqwswx9ST97JXa7ZLpXtuNAh37-MxgWluQ,7249
|
|
50
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd,sha256=uq14wOMseu7R5m8h5Bsmlo0QoMECpYCyfT1cEUtPa_k,4937
|
|
51
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd,sha256=-kFjVGjFhZ6zb_bnAoQsJkLhVSZ7w1l_FodKrFzmrQ4,4581
|
|
52
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd,sha256=TaHRoUBIFtmdEwBKBpIOE_TtfQR91D0zVjgD7LHn2CM,10107
|
|
53
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd,sha256=CK_F2t5LfyQ6eSNJ8soTFMVK9DU8vD2WiMi2MQvjB0g,3746
|
|
54
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd,sha256=3YU-3q1-c-namz7sMe5cxnmOVOJsRSmfWR02PKv3xaU,19171
|
|
55
|
+
fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd,sha256=YQSBwXt4IsDlyegY8bX-qQHGSfE5TipTPfo2g2yqq1c,3082
|
|
56
|
+
fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=ad_Fo62_Vt4P3DmROhS3B4N-jBD5jQZHYBq20wTL1_U,34756
|
|
57
|
+
fmu_manipulation_toolbox/resources/linux32/server_sm,sha256=gzKU0BTeaRkvhTMQtHHj3K8uYFyEdyGGn_mZy_jG9xo,21304
|
|
58
|
+
fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=JHMekdWhn2RPUDqfH3U7WB8SM1WyGl-0UbaVE-Fh-Aw,32592
|
|
59
|
+
fmu_manipulation_toolbox/resources/linux64/container.so,sha256=3wwgP8xYumKzmaGH761f3D_mkVbUCntOE_UgGUtahyg,135520
|
|
60
|
+
fmu_manipulation_toolbox/resources/linux64/server_sm,sha256=MZn6vITN2qpBHYt_RaK2VnFFp00hk8fTALBHmXPtLwc,22608
|
|
61
|
+
fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=WcieLopqhHu3fIXZo_k71FMgroylR5pRWs9qGdoVzCc,17920
|
|
62
|
+
fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=wqKQrr5m6DsdNk5rKFRKwgyTDOySlPX_jMMhdyywMsQ,15360
|
|
63
|
+
fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=uOTC5yGOtSheSGcWmBEWXhwyrJMJpoKgtTNEo8WJVC0,21504
|
|
64
|
+
fmu_manipulation_toolbox/resources/win64/container.dll,sha256=YG2zagCEmzrtGbbNCYir5N-pm5hxPdZft9cZPVMQuWI,98816
|
|
65
|
+
fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=SikJSqTwrq7HMKITP3ksFi2j0ZqCIqgOMdPMsHi5L8w,18432
|
|
66
|
+
fmu_manipulation_toolbox-1.9.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
|
|
67
|
+
fmu_manipulation_toolbox-1.9.dist-info/METADATA,sha256=8Ls_kJpVghQrFyyDEGHeyc6aKD0LlHKd7rJDAsWbTxk,1153
|
|
68
|
+
fmu_manipulation_toolbox-1.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
69
|
+
fmu_manipulation_toolbox-1.9.dist-info/entry_points.txt,sha256=HjOZkflbI1IuSY8BpOZre20m24M4GDQGCJfPIa7NrlY,264
|
|
70
|
+
fmu_manipulation_toolbox-1.9.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
|
|
71
|
+
fmu_manipulation_toolbox-1.9.dist-info/RECORD,,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
fmucontainer = fmu_manipulation_toolbox.cli.fmucontainer:fmucontainer
|
|
3
|
+
fmusplit = fmu_manipulation_toolbox.cli.fmusplit:fmusplit
|
|
4
|
+
fmutool = fmu_manipulation_toolbox.cli.fmutool:fmutool
|
|
5
|
+
|
|
6
|
+
[gui_scripts]
|
|
7
|
+
fmutool-gui = fmu_manipulation_toolbox.gui:main
|
fmu_manipulation_toolbox/cli.py
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import logging
|
|
3
|
-
import sys
|
|
4
|
-
from colorama import Fore, Style, init
|
|
5
|
-
|
|
6
|
-
from .fmu_operations import *
|
|
7
|
-
from .fmu_container import FMUContainerError
|
|
8
|
-
from .assembly import Assembly, AssemblyError
|
|
9
|
-
from .checker import checker_list
|
|
10
|
-
from .version import __version__ as version
|
|
11
|
-
from .help import Help
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def setup_logger():
|
|
15
|
-
class CustomFormatter(logging.Formatter):
|
|
16
|
-
def format(self, record):
|
|
17
|
-
log_format = "%(levelname)-8s | %(message)s"
|
|
18
|
-
format_per_level = {
|
|
19
|
-
logging.DEBUG: str(Fore.BLUE) + log_format,
|
|
20
|
-
logging.INFO: str(Fore.CYAN) + log_format,
|
|
21
|
-
logging.WARNING: str(Fore.YELLOW) + log_format,
|
|
22
|
-
logging.ERROR: str(Fore.RED) + log_format,
|
|
23
|
-
logging.CRITICAL: str(Fore.RED + Style.BRIGHT) + log_format,
|
|
24
|
-
}
|
|
25
|
-
formatter = logging.Formatter(format_per_level[record.levelno])
|
|
26
|
-
return formatter.format(record)
|
|
27
|
-
init()
|
|
28
|
-
logger = logging.getLogger("fmu_manipulation_toolbox")
|
|
29
|
-
handler = logging.StreamHandler(stream=sys.stdout)
|
|
30
|
-
handler.setFormatter(CustomFormatter())
|
|
31
|
-
logger.addHandler(handler)
|
|
32
|
-
logger.setLevel(logging.INFO)
|
|
33
|
-
|
|
34
|
-
return logger
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def make_wide(formatter, w=120, h=36):
|
|
38
|
-
"""Return a wider HelpFormatter, if possible."""
|
|
39
|
-
try:
|
|
40
|
-
# https://stackoverflow.com/a/5464440
|
|
41
|
-
# beware: "Only the name of this class is considered a public API."
|
|
42
|
-
kwargs = {'width': w, 'max_help_position': h}
|
|
43
|
-
formatter(None, **kwargs)
|
|
44
|
-
return lambda prog: formatter(prog, **kwargs)
|
|
45
|
-
except TypeError:
|
|
46
|
-
return formatter
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def fmutool():
|
|
50
|
-
print(f"FMU Manipulation Toolbox version {version}")
|
|
51
|
-
help_message = Help()
|
|
52
|
-
|
|
53
|
-
parser = argparse.ArgumentParser(prog='fmutool',
|
|
54
|
-
description="Analyse and Manipulate a FMU by modifying its 'modelDescription.xml'",
|
|
55
|
-
formatter_class=make_wide(argparse.HelpFormatter),
|
|
56
|
-
add_help=False,
|
|
57
|
-
epilog="see: https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/README.md")
|
|
58
|
-
|
|
59
|
-
def add_option(option, *args, **kwargs):
|
|
60
|
-
parser.add_argument(option, *args, help=help_message.usage(option), **kwargs)
|
|
61
|
-
|
|
62
|
-
add_option('-h', '-help', action="help")
|
|
63
|
-
|
|
64
|
-
# I/O
|
|
65
|
-
add_option('-input', action='store', dest='fmu_input', default=None, required=True, metavar='path/to/module.fmu')
|
|
66
|
-
add_option('-output', action='store', dest='fmu_output', default=None, metavar='path/to/module-modified.fmu')
|
|
67
|
-
|
|
68
|
-
# Port name manipulation
|
|
69
|
-
add_option('-remove-toplevel', action='append_const', dest='operations_list', const=OperationStripTopLevel())
|
|
70
|
-
add_option('-merge-toplevel', action='append_const', dest='operations_list', const=OperationMergeTopLevel())
|
|
71
|
-
add_option('-trim-until', action='append', dest='operations_list', type=OperationTrimUntil, metavar='prefix')
|
|
72
|
-
add_option('-remove-regexp', action='append', dest='operations_list', type=OperationRemoveRegexp,
|
|
73
|
-
metavar='regular-expression')
|
|
74
|
-
add_option('-keep-only-regexp', action='append', dest='operations_list', type=OperationKeepOnlyRegexp,
|
|
75
|
-
metavar='regular-expression')
|
|
76
|
-
add_option('-remove-all', action='append_const', dest='operations_list', const=OperationRemoveRegexp('.*'))
|
|
77
|
-
|
|
78
|
-
# Batch Rename
|
|
79
|
-
add_option('-dump-csv', action='append', dest='operations_list', type=OperationSaveNamesToCSV,
|
|
80
|
-
metavar='path/to/list.csv')
|
|
81
|
-
add_option('-rename-from-csv', action='append', dest='operations_list', type=OperationRenameFromCSV,
|
|
82
|
-
metavar='path/to/translation.csv')
|
|
83
|
-
|
|
84
|
-
# Remoting
|
|
85
|
-
add_option('-add-remoting-win32', action='append_const', dest='operations_list', const=OperationAddRemotingWin32())
|
|
86
|
-
add_option('-add-remoting-win64', action='append_const', dest='operations_list', const=OperationAddRemotingWin64())
|
|
87
|
-
add_option('-add-frontend-win32', action='append_const', dest='operations_list', const=OperationAddFrontendWin32())
|
|
88
|
-
add_option('-add-frontend-win64', action='append_const', dest='operations_list', const=OperationAddFrontendWin64())
|
|
89
|
-
|
|
90
|
-
# Extraction / Removal
|
|
91
|
-
add_option('-extract-descriptor', action='store', dest='extract_description',
|
|
92
|
-
metavar='path/to/saved-modelDescriptor.xml')
|
|
93
|
-
add_option('-remove-sources', action='append_const', dest='operations_list',
|
|
94
|
-
const=OperationRemoveSources())
|
|
95
|
-
# Filter
|
|
96
|
-
add_option('-only-parameters', action='append_const', dest='apply_on', const='parameter')
|
|
97
|
-
add_option('-only-inputs', action='append_const', dest='apply_on', const='input')
|
|
98
|
-
add_option('-only-outputs', action='append_const', dest='apply_on', const='output')
|
|
99
|
-
# Checker
|
|
100
|
-
add_option('-summary', action='append_const', dest='operations_list', const=OperationSummary())
|
|
101
|
-
add_option('-check', action='append_const', dest='operations_list', const=[checker() for checker in checker_list])
|
|
102
|
-
|
|
103
|
-
cli_options = parser.parse_args()
|
|
104
|
-
# handle the "no operation" use case
|
|
105
|
-
if not cli_options.operations_list:
|
|
106
|
-
cli_options.operations_list = []
|
|
107
|
-
|
|
108
|
-
if cli_options.fmu_input == cli_options.fmu_output:
|
|
109
|
-
print(f"FATAL ERROR: '-input' and '-output' should point to different files.")
|
|
110
|
-
sys.exit(-3)
|
|
111
|
-
|
|
112
|
-
print(f"READING Input='{cli_options.fmu_input}'")
|
|
113
|
-
try:
|
|
114
|
-
fmu = FMU(cli_options.fmu_input)
|
|
115
|
-
except FMUException as reason:
|
|
116
|
-
print(f"FATAL ERROR: {reason}")
|
|
117
|
-
sys.exit(-4)
|
|
118
|
-
|
|
119
|
-
if cli_options.apply_on:
|
|
120
|
-
print("Applying operation for :")
|
|
121
|
-
for causality in cli_options.apply_on:
|
|
122
|
-
print(f" - causality = {causality}")
|
|
123
|
-
|
|
124
|
-
def flatten(list_of_list: list):
|
|
125
|
-
return [x for xs in list_of_list for x in xs]
|
|
126
|
-
|
|
127
|
-
for operation in flatten(cli_options.operations_list):
|
|
128
|
-
print(f" => {operation}")
|
|
129
|
-
try:
|
|
130
|
-
fmu.apply_operation(operation, cli_options.apply_on)
|
|
131
|
-
except OperationException as reason:
|
|
132
|
-
print(f"ERROR: {reason}")
|
|
133
|
-
sys.exit(-6)
|
|
134
|
-
|
|
135
|
-
if cli_options.extract_description:
|
|
136
|
-
print(f"WRITING ModelDescriptor='{cli_options.extract_description}'")
|
|
137
|
-
fmu.save_descriptor(cli_options.extract_description)
|
|
138
|
-
|
|
139
|
-
if cli_options.fmu_output:
|
|
140
|
-
print(f"WRITING Output='{cli_options.fmu_output}'")
|
|
141
|
-
try:
|
|
142
|
-
fmu.repack(cli_options.fmu_output)
|
|
143
|
-
except FMUException as reason:
|
|
144
|
-
print(f"FATAL ERROR: {reason}")
|
|
145
|
-
sys.exit(-5)
|
|
146
|
-
else:
|
|
147
|
-
print(f"INFO Modified FMU is not saved. If necessary use '-output' option.")
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
def fmucontainer():
|
|
151
|
-
logger = setup_logger()
|
|
152
|
-
|
|
153
|
-
logger.info(f"FMUContainer version {version}")
|
|
154
|
-
parser = argparse.ArgumentParser(prog="fmucontainer", description="Generate FMU from FMU's",
|
|
155
|
-
formatter_class=make_wide(argparse.ArgumentDefaultsHelpFormatter),
|
|
156
|
-
add_help=False,
|
|
157
|
-
epilog="see: https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/"
|
|
158
|
-
"container/README.md")
|
|
159
|
-
|
|
160
|
-
parser.add_argument('-h', '-help', action="help")
|
|
161
|
-
|
|
162
|
-
parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
|
|
163
|
-
help="Directory containing initial FMU’s and used to generate containers. "
|
|
164
|
-
"If not defined, current directory is used.")
|
|
165
|
-
|
|
166
|
-
parser.add_argument("-container", action="append", dest="container_descriptions_list", default=[],
|
|
167
|
-
metavar="filename.{csv|json|ssp},[:step_size]", required=True,
|
|
168
|
-
help="Description of the container to create.")
|
|
169
|
-
|
|
170
|
-
parser.add_argument("-debug", action="store_true", dest="debug",
|
|
171
|
-
help="Add lot of useful log during the process.")
|
|
172
|
-
|
|
173
|
-
parser.add_argument("-no-auto-input", action="store_false", dest="auto_input", default=True,
|
|
174
|
-
help="Create ONLY explicit input.")
|
|
175
|
-
|
|
176
|
-
parser.add_argument("-no-auto-output", action="store_false", dest="auto_output", default=True,
|
|
177
|
-
help="Create ONLY explicit output.")
|
|
178
|
-
|
|
179
|
-
parser.add_argument("-auto-parameter", action="store_true", dest="auto_parameter", default=False,
|
|
180
|
-
help="Expose parameters of the embedded fmu's.")
|
|
181
|
-
|
|
182
|
-
parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
|
|
183
|
-
help="Expose local variables of the embedded fmu's.")
|
|
184
|
-
|
|
185
|
-
parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
|
|
186
|
-
help="Create ONLY explicit links.")
|
|
187
|
-
|
|
188
|
-
parser.add_argument("-mt", action="store_true", dest="mt", default=False,
|
|
189
|
-
help="Enable Multi-Threaded mode for the generated container.")
|
|
190
|
-
|
|
191
|
-
parser.add_argument("-profile", action="store_true", dest="profiling", default=False,
|
|
192
|
-
help="Enable Profiling mode for the generated container.")
|
|
193
|
-
|
|
194
|
-
parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
|
|
195
|
-
help="Dump a JSON file for each container.")
|
|
196
|
-
|
|
197
|
-
config = parser.parse_args()
|
|
198
|
-
|
|
199
|
-
if config.debug:
|
|
200
|
-
logger.setLevel(logging.DEBUG)
|
|
201
|
-
|
|
202
|
-
fmu_directory = Path(config.fmu_directory)
|
|
203
|
-
logger.info(f"FMU directory: '{fmu_directory}'")
|
|
204
|
-
|
|
205
|
-
for description in config.container_descriptions_list:
|
|
206
|
-
try:
|
|
207
|
-
tokens = description.split(":")
|
|
208
|
-
filename = ":".join(tokens[:-1])
|
|
209
|
-
step_size = float(tokens[-1])
|
|
210
|
-
except ValueError:
|
|
211
|
-
step_size = None
|
|
212
|
-
filename = description
|
|
213
|
-
|
|
214
|
-
try:
|
|
215
|
-
assembly = Assembly(filename, step_size=step_size, auto_link=config.auto_link,
|
|
216
|
-
auto_input=config.auto_input, auto_output=config.auto_output,
|
|
217
|
-
auto_local=config.auto_local, mt=config.mt,
|
|
218
|
-
profiling=config.profiling, fmu_directory=fmu_directory, debug=config.debug,
|
|
219
|
-
auto_parameter=config.auto_parameter)
|
|
220
|
-
except FileNotFoundError as e:
|
|
221
|
-
logger.fatal(f"Cannot read file: {e}")
|
|
222
|
-
continue
|
|
223
|
-
except (FMUContainerError, AssemblyError) as e:
|
|
224
|
-
logger.fatal(f"{filename}: {e}")
|
|
225
|
-
continue
|
|
226
|
-
|
|
227
|
-
try:
|
|
228
|
-
assembly.make_fmu(dump_json=config.dump)
|
|
229
|
-
except FMUContainerError as e:
|
|
230
|
-
logger.fatal(f"{filename}: {e}")
|
|
231
|
-
continue
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
if __name__ == "__main__":
|
|
235
|
-
fmucontainer()
|