fmu-manipulation-toolbox 1.8.4.2rc1__py3-none-any.whl → 1.9rc0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. fmu_manipulation_toolbox/__version__.py +1 -1
  2. fmu_manipulation_toolbox/assembly.py +14 -7
  3. fmu_manipulation_toolbox/checker.py +5 -3
  4. fmu_manipulation_toolbox/{fmu_container.py → container.py} +71 -63
  5. fmu_manipulation_toolbox/gui.py +1 -1
  6. fmu_manipulation_toolbox/{fmu_operations.py → operations.py} +35 -19
  7. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +51 -0
  8. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +119 -0
  9. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +117 -0
  10. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +80 -0
  11. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +93 -0
  12. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +131 -0
  13. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +87 -0
  14. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +84 -0
  15. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +207 -0
  16. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +69 -0
  17. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +413 -0
  18. fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +64 -0
  19. fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  20. fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
  21. fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
  22. fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
  23. fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  24. fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
  25. fmu_manipulation_toolbox/split.py +314 -0
  26. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/METADATA +1 -1
  27. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/RECORD +31 -19
  28. fmu_manipulation_toolbox-1.9rc0.dist-info/entry_points.txt +7 -0
  29. fmu_manipulation_toolbox/cli.py +0 -235
  30. fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/entry_points.txt +0 -3
  31. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/WHEEL +0 -0
  32. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/licenses/LICENSE.txt +0 -0
  33. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.9rc0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,314 @@
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
+ logger = logging.getLogger("fmu_manipulation_toolbox")
10
+
11
+
12
+ class FMUSplitterError(Exception):
13
+ def __init__(self, message: str):
14
+ self.message = message
15
+
16
+ def __str__(self):
17
+ return str(self.message)
18
+
19
+
20
+ class FMUSplitterPort:
21
+ def __init__(self, fmu_filename: str, port_name):
22
+ self.fmu_filename = fmu_filename
23
+ self.port_name = port_name
24
+
25
+ def __str__(self):
26
+ return f"{self.fmu_filename}/{self.port_name}"
27
+
28
+
29
+ class FMUSplitterLink:
30
+ def __init__(self):
31
+ self.from_port: Optional[FMUSplitterPort] = None
32
+ self.to_port: List[FMUSplitterPort] = []
33
+
34
+ def __str__(self):
35
+ to_str = ", ".join([f"{port}" for port in self.to_port])
36
+ return f"{self.from_port} -> {to_str}"
37
+
38
+
39
+ class FMUSplitter:
40
+ def __init__(self, fmu_filename: str):
41
+ self.fmu_filename = Path(fmu_filename)
42
+ self.directory = self.fmu_filename.with_suffix(".dir")
43
+ self.zip = None # to handle error
44
+ self.zip = zipfile.ZipFile(self.fmu_filename)
45
+ self.filenames_list = self.zip.namelist()
46
+ self.dir_set = self.get_dir_set()
47
+
48
+ if "resources/container.txt" not in self.filenames_list:
49
+ raise FMUSplitterError(f"FMU file {self.fmu_filename} is not an FMU Container.")
50
+
51
+ self.directory.mkdir(exist_ok=True)
52
+ logger.info(f"Preparing to split '{self.fmu_filename}' into '{self.directory}'")
53
+
54
+ def get_dir_set(self) -> Set[str]:
55
+ dir_set = set()
56
+ for filename in self.filenames_list:
57
+ parent = "/".join(filename.split("/")[:-1])
58
+ dir_set.add(parent+"/")
59
+ return dir_set
60
+
61
+ def __del__(self):
62
+ if self.zip is not None:
63
+ logger.debug("Closing zip file")
64
+ self.zip.close()
65
+
66
+ def split_fmu(self):
67
+ logger.info(f"Splitting...")
68
+ config = self._split_fmu(fmu_filename=str(self.fmu_filename), relative_path="")
69
+ config_filename = self.directory / self.fmu_filename.with_suffix(".json")
70
+ with open(config_filename, "w") as file:
71
+ json.dump(config, file, indent=2)
72
+ logger.info(f"Container definition saved to '{config_filename}'")
73
+
74
+ def _split_fmu(self, fmu_filename: str, relative_path: str) -> Dict[str, Any]:
75
+ txt_filename = f"{relative_path}resources/container.txt"
76
+
77
+ if txt_filename in self.filenames_list:
78
+ description = FMUSplitterDescription(self.zip)
79
+ config = description.parse_txt_file(txt_filename)
80
+ config["name"] = fmu_filename
81
+ for i, fmu_filename in enumerate(config["candidate_fmu"]):
82
+ directory = f"{relative_path}resources/{i:02x}/"
83
+ if directory not in self.dir_set:
84
+ directory = f"{relative_path}resources/{fmu_filename}/"
85
+ if directory not in self.dir_set:
86
+ raise FMUSplitterError(f"{directory} not found in FMU")
87
+ sub_config = self._split_fmu(fmu_filename=fmu_filename, relative_path=directory)
88
+ if isinstance(sub_config, str):
89
+ key = "fmu"
90
+ else:
91
+ key = "container"
92
+ try:
93
+ config[key].append(sub_config)
94
+ except KeyError:
95
+ config[key] = [sub_config]
96
+ config.pop("candidate_fmu")
97
+ else:
98
+ config = fmu_filename
99
+ self.extract_fmu(relative_path, str(self.directory / fmu_filename))
100
+
101
+ return config
102
+
103
+ def extract_fmu(self, directory: str, filename: str):
104
+ logger.debug(f"Extracting {directory} to {filename}")
105
+ with zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED) as fmu_file:
106
+ for file in self.zip.namelist():
107
+ if file.startswith(directory):
108
+ data = self.zip.read(file)
109
+ fmu_file.writestr(file[len(directory):], data)
110
+ logger.info(f"FMU Extraction of '{filename}'")
111
+
112
+
113
+ class FMUSplitterDescription:
114
+ def __init__(self, zip):
115
+ self.zip = zip
116
+ self.links: Dict[str, Dict[int, FMUSplitterLink]] = {
117
+ "Real": {},
118
+ "Integer": {},
119
+ "Boolean": {},
120
+ "String": {}
121
+ }
122
+ self.vr_to_name: Dict[str, Dict[str, Dict[int, Dict[str, str]]]] = {} # name, fmi_type, vr <-> {name, causality}
123
+ self.config: Dict[str, Any] = {
124
+ "auto_input": False,
125
+ "auto_output": False,
126
+ "auto_parameter": False,
127
+ "auto_local": False,
128
+ "auto_link": False,
129
+ }
130
+ self.fmu_filename_list = []
131
+
132
+ # used for modelDescription.xml parsing
133
+ self.current_fmu_filename = None
134
+ self.current_vr = None
135
+ self.current_name = None
136
+ self.current_causality = None
137
+
138
+ @staticmethod
139
+ def get_line(file):
140
+ for line in file:
141
+ line = line.decode('utf-8').strip()
142
+ if line and not line.startswith("#"):
143
+ return line
144
+ raise StopIteration
145
+
146
+ def start_element(self, name, attrs):
147
+ if name == "ScalarVariable":
148
+ self.current_name = attrs["name"]
149
+ self.current_vr = int(attrs["valueReference"])
150
+ self.current_causality = attrs["causality"]
151
+ elif name in self.vr_to_name[self.current_fmu_filename]:
152
+ self.vr_to_name[self.current_fmu_filename][name][self.current_vr] = {"name": self.current_name,
153
+ "causality": self.current_causality}
154
+ else:
155
+ self.current_vr = None
156
+ self.current_name = None
157
+ self.current_causality = None
158
+
159
+ def parse_model_description(self, directory: str, fmu_filename: str):
160
+
161
+ if directory == ".":
162
+ filename = "modelDescription.xml"
163
+ else:
164
+ filename = f"{directory}/modelDescription.xml"
165
+
166
+ self.vr_to_name[fmu_filename] = {
167
+ "Real": {},
168
+ "Integer": {},
169
+ "Boolean": {},
170
+ "String": {}
171
+ }
172
+ parser = xml.parsers.expat.ParserCreate()
173
+ self.current_fmu_filename = fmu_filename
174
+ self.current_vr = None
175
+ self.current_name = None
176
+ self.current_causality = None
177
+ parser.StartElementHandler = self.start_element
178
+ with (self.zip.open(filename) as file):
179
+ logger.debug(f"Parsing '{filename}' ({fmu_filename})")
180
+ parser.ParseFile(file)
181
+
182
+ def parse_txt_file_header(self, file, txt_filename):
183
+ flags = self.get_line(file).split(" ")
184
+ if len(flags) == 1:
185
+ self.config["mt"] = flags[0] == "1"
186
+ self.config["profiling"] = self.get_line(file) == "1"
187
+ self.config["sequential"] = False
188
+ elif len(flags) == 3:
189
+ self.config["mt"] = flags[0] == "1"
190
+ self.config["profiling"] = flags[1] == "1"
191
+ self.config["sequential"] = flags[2] == "1"
192
+ else:
193
+ raise FMUSplitterError(f"Cannot interpret flags '{flags}'")
194
+
195
+ self.config["step_size"] = float(self.get_line(file))
196
+ nb_fmu = int(self.get_line(file))
197
+ logger.debug(f"Number of FMUs: {nb_fmu}")
198
+ self.config["candidate_fmu"] = []
199
+
200
+ for i in range(nb_fmu):
201
+ fmu_filename = self.get_line(file)
202
+ base_directory = "/".join(txt_filename.split("/")[0:-1])
203
+
204
+ directory = f"{base_directory}/{fmu_filename}"
205
+ if f"{directory}/modelDescription.xml" not in self.zip.namelist():
206
+ directory = f"{base_directory}/{i:02x}"
207
+ if f"{directory}/modelDescription.xml" not in self.zip.namelist():
208
+ print(self.zip.namelist())
209
+ raise FMUSplitterError(f"Cannot find in FMU directory in {directory}.")
210
+
211
+ self.parse_model_description(directory, fmu_filename)
212
+ self.config["candidate_fmu"].append(fmu_filename)
213
+ _library = self.get_line(file)
214
+ _uuid = self.get_line(file)
215
+ _nb_local_variables = self.get_line(file)
216
+
217
+ def add_port(self, fmi_type: str, fmu_id: int, fmu_vr: int, container_vr: int):
218
+ if fmu_id >= 0:
219
+ fmu_filename = self.config["candidate_fmu"][fmu_id]
220
+ causality = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["causality"]
221
+ fmu_port_name = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["name"]
222
+ container_port = self.vr_to_name["."][fmi_type][container_vr]["name"]
223
+ if not causality == "output":
224
+ causality = "input"
225
+ definition = [container_port, fmu_filename, fmu_port_name]
226
+ else:
227
+ definition = [fmu_filename, fmu_port_name, container_port]
228
+
229
+ try:
230
+ self.config[causality].append(definition)
231
+ except KeyError:
232
+ self.config[causality] = [definition]
233
+
234
+ logger.debug(f"Adding container port {causality}: {definition}")
235
+
236
+ def parse_txt_file_ports(self, file):
237
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
238
+ nb_port_variables = self.get_line(file).split(" ")[0]
239
+ for i in range(int(nb_port_variables)):
240
+ tokens = self.get_line(file).split(" ")
241
+ if len(tokens) > 3:
242
+ container_vr = int(tokens[0])
243
+ for j in range(int(tokens[1])):
244
+ fmu_id = int(tokens[2 + 2 * j])
245
+ fmu_vr = int(tokens[2 + 2 * j + 1])
246
+ self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
247
+ else: # For FMUContainer <= 1.8.4
248
+ container_vr = int(tokens[0])
249
+ fmu_id = int(tokens[1])
250
+ fmu_vr = int(tokens[2])
251
+ self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
252
+
253
+ def parse_txt_file(self, txt_filename: str):
254
+ self.parse_model_description(str(Path(txt_filename).parent.parent), ".")
255
+ logger.debug(f"Parsing container file '{txt_filename}'")
256
+
257
+ with (self.zip.open(txt_filename) as file):
258
+ self.parse_txt_file_header(file, txt_filename)
259
+ self.parse_txt_file_ports(file)
260
+
261
+ for fmu_filename in self.config["candidate_fmu"]:
262
+ # Inputs per FMUs
263
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
264
+ nb_input = int(self.get_line(file))
265
+ for i in range(nb_input):
266
+ local, vr = self.get_line(file).split(" ")
267
+ try:
268
+ link = self.links[fmi_type][local]
269
+ except KeyError:
270
+ link = FMUSplitterLink()
271
+ self.links[fmi_type][local] = link
272
+ link.to_port.append(FMUSplitterPort(fmu_filename,
273
+ self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"]))
274
+
275
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
276
+ nb_start = int(self.get_line(file))
277
+ for i in range(nb_start):
278
+ tokens = self.get_line(file).split(" ")
279
+ vr = int(tokens[0])
280
+ value = tokens[-1]
281
+ start_definition = [fmu_filename, self.vr_to_name[fmu_filename][fmi_type][vr]["name"],
282
+ value]
283
+ try:
284
+ self.config["start"].append(start_definition)
285
+ except KeyError:
286
+ self.config["start"] = [start_definition]
287
+
288
+ # Output per FMUs
289
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
290
+ nb_output = int(self.get_line(file))
291
+
292
+ for i in range(nb_output):
293
+ local, vr = self.get_line(file).split(" ")
294
+ try:
295
+ link = self.links[fmi_type][local]
296
+ except KeyError:
297
+ link = FMUSplitterLink()
298
+ self.links[fmi_type][local] = link
299
+ link.from_port = FMUSplitterPort(fmu_filename,
300
+ self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"])
301
+
302
+ logger.debug("End of parsing.")
303
+
304
+ for fmi_type, links in self.links.items():
305
+ for link in links.values():
306
+ for to_port in link.to_port:
307
+ definition = [ link.from_port.fmu_filename, link.from_port.port_name,
308
+ to_port.fmu_filename, to_port.port_name]
309
+ try:
310
+ self.config["link"].append(definition)
311
+ except KeyError:
312
+ self.config["link"] = [definition]
313
+
314
+ 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.9rc0
4
4
  Summary: FMU Manipulation Toolbox is a python application for modifying Functional Mock-up Units (FMUs) without recompilation or bundling them into FMU Containers
5
5
  Home-page: https://github.com/grouperenault/fmu_manipulation_toolbox/
6
6
  Author: Nicolas.LAURENT@Renault.com
@@ -1,14 +1,14 @@
1
1
  fmu_manipulation_toolbox/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
2
2
  fmu_manipulation_toolbox/__main__.py,sha256=mAzrtkil506DS0F3g3CEbHdtZsZotzntcNhIn_lNJkw,344
3
- fmu_manipulation_toolbox/__version__.py,sha256=jnm0HeOalO32T8hqtCK89pKFbJPLz-YFYj_G4Pi_q6M,15
4
- fmu_manipulation_toolbox/assembly.py,sha256=p8c8l2BLexns21ADr8WhmedLO015Oma1tOHEYZwvgpk,25900
5
- fmu_manipulation_toolbox/checker.py,sha256=lE2MpH4BAKCDjUvbr06N56u7ao8hWXaJgMKaLvmhFTQ,2272
6
- fmu_manipulation_toolbox/cli.py,sha256=2p5T1qp7kTcMlScwmvXyUfEmAIGSJsld96ObY216QMA,10616
7
- fmu_manipulation_toolbox/fmu_container.py,sha256=V6-pcAdkj380h16Gbxe0kmzfw1n8GDoqmpI270v2ZsE,32079
8
- fmu_manipulation_toolbox/fmu_operations.py,sha256=zxsbwnfctmTv-wU37GiiaX3CFM7LmvXAVDCNpdVyRZo,15886
9
- fmu_manipulation_toolbox/gui.py,sha256=3y_3CjPr-R-Oa5DTCm0LLnOLVG0_IFjadpNjACAmayQ,29222
3
+ fmu_manipulation_toolbox/__version__.py,sha256=pIetL3-rgAy__3Y9bhoI5aPvTCG8a1qRIBr7IZdM-aA,12
4
+ fmu_manipulation_toolbox/assembly.py,sha256=1jlNc_Rfls2Nah22sd9IL11rC0J5MWs0slT4Bc3sjOw,26364
5
+ fmu_manipulation_toolbox/checker.py,sha256=836wCri6aEl0M6_xHPZ94JRngFjsy8Ee-_t8bzclxBs,2332
6
+ fmu_manipulation_toolbox/container.py,sha256=DjzRgSGNth50V-8eQ107mbYZQq1Q5-ZPsO6E-oZG4KE,32831
7
+ fmu_manipulation_toolbox/gui.py,sha256=tVTPLbGZlD5P0WYqaD5B4crG2nHjBGe73yAJrzRXpYE,29218
10
8
  fmu_manipulation_toolbox/gui_style.py,sha256=uzEruJumnC5Vf2cfHXVa_c-SHAQoTvDWemro3-b9Mpc,6492
11
9
  fmu_manipulation_toolbox/help.py,sha256=aklKiLrsE0adSzQ5uoEB1sBDmI6s4l231gavu4XxxzA,5856
10
+ fmu_manipulation_toolbox/operations.py,sha256=p0e6OgNRT0JrQaDjhdHk1rxVoRXbdhPHueVvn021UdM,16346
11
+ fmu_manipulation_toolbox/split.py,sha256=lHIct-ANlFB0p7MgViUaSF8jlOlD1-M7TP-I-x9kkpI,13061
12
12
  fmu_manipulation_toolbox/version.py,sha256=OhBLkZ1-nhC77kyvffPNAf6m8OZe1bYTnNf_PWs1NvM,392
13
13
  fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png,sha256=FWIuyrXlaNLLePHfXj7j9ca5rT8Hgr14KCe1EqTCZyk,2288
14
14
  fmu_manipulation_toolbox/resources/checkbox-checked-hover.png,sha256=KNlV-d_aJNTTvUVXKGT9DBY30sIs2LwocLJrFKNKv8k,2419
@@ -34,19 +34,31 @@ fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd,sha256=hYZGmhv
34
34
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd,sha256=8A0hl2wb1suoxv47xezkmvVTyJM2ZJp5RPQ2xQ_SjlY,3883
35
35
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd,sha256=pB9Pe-yBMGZN-JQAu6VB_lXS99kz23mwiUSY74ONZd4,5403
36
36
  fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd,sha256=Tc9RWKqvUXpB1qsoU64DAHO4Gfu5DotrQJ3Ece7GnTU,4647
37
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd,sha256=H4OB87z_hK5CSrpbzZjxva9VLpitI94Nbm8lQOlwkp8,2570
38
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd,sha256=g6jtK05vCrlHBKun__QqIUe-S7ja6wDZ3KgpaJpReyY,6141
39
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd,sha256=G4clniTvFReBcqoABaU8t16OIeMJVZNzW9q1Qys8c9k,7516
40
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd,sha256=2KkVadEBEK1L2aatQ3HOjhl2XIv7V6tWcT9WmvpYyI4,4652
41
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd,sha256=DhSi-eVKFmdUv6tHsjWf8GYEfbymhxQKbGbeJYMtGLs,4474
42
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd,sha256=0W02POCyDiqwswx9ST97JXa7ZLpXtuNAh37-MxgWluQ,7249
43
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd,sha256=uq14wOMseu7R5m8h5Bsmlo0QoMECpYCyfT1cEUtPa_k,4937
44
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd,sha256=-kFjVGjFhZ6zb_bnAoQsJkLhVSZ7w1l_FodKrFzmrQ4,4581
45
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd,sha256=TaHRoUBIFtmdEwBKBpIOE_TtfQR91D0zVjgD7LHn2CM,10107
46
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd,sha256=CK_F2t5LfyQ6eSNJ8soTFMVK9DU8vD2WiMi2MQvjB0g,3746
47
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd,sha256=3YU-3q1-c-namz7sMe5cxnmOVOJsRSmfWR02PKv3xaU,19171
48
+ fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd,sha256=YQSBwXt4IsDlyegY8bX-qQHGSfE5TipTPfo2g2yqq1c,3082
37
49
  fmu_manipulation_toolbox/resources/linux32/client_sm.so,sha256=xVdY2zy13pa2DcvFiweSNpp7E6DiONqeoBdlcJHrW_k,35940
38
50
  fmu_manipulation_toolbox/resources/linux32/server_sm,sha256=1TLGqNPyM5UVOrCfzNqWyF6ClLksY3EiY3CSsrnp6c0,22836
39
51
  fmu_manipulation_toolbox/resources/linux64/client_sm.so,sha256=EhY1XHo1YcQn6yqZ7wk5okqtZyp0MrcCsGcudqE-aIM,37000
40
- fmu_manipulation_toolbox/resources/linux64/container.so,sha256=diiqk5qF2doso3lYvb1qL-B062HY7-qgf55RItP9d3U,50152
52
+ fmu_manipulation_toolbox/resources/linux64/container.so,sha256=0hpVEgJkGxbgMeoVAgeqL73aewZ8j-tfzXlf0A0UBpM,85064
41
53
  fmu_manipulation_toolbox/resources/linux64/server_sm,sha256=ulfoPvmaYe9nInYcVEyj7mD9zDzGk56OUoWx1mPKLiE,22768
42
- fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=ttt3rSF4hqNhxIEiXaJx95-_9pPD44r1gjK5ky76bMA,17920
43
- fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=Xh_YAy8OfLXKVhGuxPl940YzEePiU65HKOLkAHUzKsk,15872
44
- fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=cRO6IW_i5mom29FLhWIrYp0aesyZPh-slQJrDe0tOLU,22016
45
- fmu_manipulation_toolbox/resources/win64/container.dll,sha256=ZLKDYR10jE17Yr2ZtIJTUdk2b_4ObLxA4zAcqfFDc50,40960
46
- fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=pMmVbYV5G3j1fxqVUY32h2f6CJQCtURG_w10sjsrMgA,19456
47
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
48
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/METADATA,sha256=pZQUBDsxkfGn94TulBQLpB2bYife9duUIo9XF9edx-4,1160
49
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
50
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/entry_points.txt,sha256=jCPLMBdS-eOvmRfDv7n0wHZSbJHccHviW03mz5vwO-Q,124
51
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
52
- fmu_manipulation_toolbox-1.8.4.2rc1.dist-info/RECORD,,
54
+ fmu_manipulation_toolbox/resources/win32/client_sm.dll,sha256=ZF0W5N4ZZgMWVnyYrLrEgxamj3WNw667QK5pqK4HvnA,17920
55
+ fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=KnUM49rDTpTHjVr-J2kfBsYnQnPsX7ho6H7vTlF8i-E,15872
56
+ fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=58N8xOmJ9XU_oe2rC9JP95lzR-IhDzbwD9FDPaQ7VtM,22016
57
+ fmu_manipulation_toolbox/resources/win64/container.dll,sha256=bvxsESgpzAn7IyLnf5Oc41pBPCM7tQz0LJrlXaSpTJQ,57856
58
+ fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=ftJC5fBoCnlzrcbLJBIfniOAieWGFHZ5klv5UFL9LEE,19968
59
+ fmu_manipulation_toolbox-1.9rc0.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
60
+ fmu_manipulation_toolbox-1.9rc0.dist-info/METADATA,sha256=kWBmPNMw9UYn11B144bSf7H0inSSo6uD-Cpe0h2OyQ4,1156
61
+ fmu_manipulation_toolbox-1.9rc0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
+ fmu_manipulation_toolbox-1.9rc0.dist-info/entry_points.txt,sha256=HjOZkflbI1IuSY8BpOZre20m24M4GDQGCJfPIa7NrlY,264
63
+ fmu_manipulation_toolbox-1.9rc0.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
64
+ fmu_manipulation_toolbox-1.9rc0.dist-info/RECORD,,
@@ -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()
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- fmucontainer = fmu_manipulation_toolbox.cli:fmucontainer
3
- fmutool = fmu_manipulation_toolbox.__main__:main