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.
Files changed (51) hide show
  1. fmu_manipulation_toolbox/__init__.py +0 -1
  2. fmu_manipulation_toolbox/__main__.py +1 -1
  3. fmu_manipulation_toolbox/__version__.py +1 -1
  4. fmu_manipulation_toolbox/assembly.py +22 -13
  5. fmu_manipulation_toolbox/checker.py +16 -11
  6. fmu_manipulation_toolbox/cli/__init__.py +0 -0
  7. fmu_manipulation_toolbox/cli/fmucontainer.py +105 -0
  8. fmu_manipulation_toolbox/cli/fmusplit.py +48 -0
  9. fmu_manipulation_toolbox/cli/fmutool.py +127 -0
  10. fmu_manipulation_toolbox/cli/utils.py +36 -0
  11. fmu_manipulation_toolbox/container.py +1054 -0
  12. fmu_manipulation_toolbox/gui.py +48 -56
  13. fmu_manipulation_toolbox/gui_style.py +8 -0
  14. fmu_manipulation_toolbox/help.py +3 -0
  15. fmu_manipulation_toolbox/operations.py +577 -0
  16. fmu_manipulation_toolbox/remoting.py +107 -0
  17. fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
  18. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +51 -0
  19. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +119 -0
  20. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +117 -0
  21. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +80 -0
  22. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +93 -0
  23. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +131 -0
  24. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +87 -0
  25. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +84 -0
  26. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +207 -0
  27. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +69 -0
  28. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +413 -0
  29. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +64 -0
  30. fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
  31. fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
  32. fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
  33. fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  34. fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
  35. fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
  36. fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
  37. fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
  38. fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  39. fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
  40. fmu_manipulation_toolbox/split.py +331 -0
  41. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/METADATA +1 -1
  42. fmu_manipulation_toolbox-1.9.dist-info/RECORD +71 -0
  43. fmu_manipulation_toolbox-1.9.dist-info/entry_points.txt +7 -0
  44. fmu_manipulation_toolbox/cli.py +0 -235
  45. fmu_manipulation_toolbox/fmu_container.py +0 -753
  46. fmu_manipulation_toolbox/fmu_operations.py +0 -489
  47. fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/RECORD +0 -52
  48. fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/entry_points.txt +0 -3
  49. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/WHEEL +0 -0
  50. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9.dist-info}/licenses/LICENSE.txt +0 -0
  51. {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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu_manipulation_toolbox
3
- Version: 1.8.4.2rc1
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
@@ -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()