fmu-manipulation-toolbox 1.8.4.2rc1__py3-none-any.whl → 1.8.4.3b0__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 +1 -1
  3. fmu_manipulation_toolbox/checker.py +5 -3
  4. fmu_manipulation_toolbox/{fmu_container.py → container.py} +66 -52
  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 +298 -0
  26. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.8.4.3b0.dist-info}/METADATA +1 -1
  27. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.8.4.3b0.dist-info}/RECORD +31 -19
  28. fmu_manipulation_toolbox-1.8.4.3b0.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.8.4.3b0.dist-info}/WHEEL +0 -0
  32. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.8.4.3b0.dist-info}/licenses/LICENSE.txt +0 -0
  33. {fmu_manipulation_toolbox-1.8.4.2rc1.dist-info → fmu_manipulation_toolbox-1.8.4.3b0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,298 @@
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 = zipfile.ZipFile(self.fmu_filename)
44
+ self.filenames_list = self.zip.namelist()
45
+ self.dir_set = self.get_dir_set()
46
+
47
+ if "resources/container.txt" not in self.filenames_list:
48
+ raise FMUSplitterError(f"FMU file {self.fmu_filename} is not an FMU Container.")
49
+
50
+ self.directory.mkdir(exist_ok=True)
51
+ logger.info(f"Preparing to split '{self.fmu_filename}' into '{self.directory}'")
52
+
53
+ def get_dir_set(self) -> Set[str]:
54
+ dir_set = set()
55
+ for filename in self.filenames_list:
56
+ parent = "/".join(filename.split("/")[:-1])
57
+ dir_set.add(parent+"/")
58
+ return dir_set
59
+
60
+ def __del__(self):
61
+ logger.debug("Closing zip file")
62
+ self.zip.close()
63
+
64
+ def split_fmu(self):
65
+ logger.info(f"Splitting...")
66
+ config = self._split_fmu(fmu_filename=str(self.fmu_filename), relative_path="")
67
+ config_filename = self.directory / self.fmu_filename.with_suffix(".json")
68
+ with open(config_filename, "w") as file:
69
+ json.dump(config, file, indent=2)
70
+ logger.info(f"Container definition saved to '{config_filename}'")
71
+
72
+ def _split_fmu(self, fmu_filename: str, relative_path: str) -> Dict[str, Any]:
73
+ txt_filename = f"{relative_path}resources/container.txt"
74
+
75
+ if txt_filename in self.filenames_list:
76
+ description = FMUSplitterDescription(self.zip)
77
+ config = description.parse_txt_file(txt_filename)
78
+ config["name"] = fmu_filename
79
+ for i, fmu_filename in enumerate(config["candidate_fmu"]):
80
+ directory = f"{relative_path}resources/{i:02x}/"
81
+ if directory not in self.dir_set:
82
+ directory = f"{relative_path}resources/{fmu_filename}/"
83
+ if directory not in self.dir_set:
84
+ raise FMUSplitterError(f"{directory} not found in FMU")
85
+ sub_config = self._split_fmu(fmu_filename=fmu_filename, relative_path=directory)
86
+ if isinstance(sub_config, str):
87
+ key = "fmu"
88
+ else:
89
+ key = "container"
90
+ try:
91
+ config[key].append(sub_config)
92
+ except KeyError:
93
+ config[key] = [sub_config]
94
+ config.pop("candidate_fmu")
95
+ else:
96
+ config = fmu_filename
97
+ self.extract_fmu(relative_path, str(self.directory / fmu_filename))
98
+
99
+ return config
100
+
101
+ def extract_fmu(self, directory: str, filename: str):
102
+ logger.debug(f"Extracting {directory} to {filename}")
103
+ with zipfile.ZipFile(filename, "w", zipfile.ZIP_DEFLATED) as fmu_file:
104
+ for file in self.zip.namelist():
105
+ if file.startswith(directory):
106
+ data = self.zip.read(file)
107
+ fmu_file.writestr(file[len(directory):], data)
108
+ logger.info(f"FMU Extraction of '{filename}'")
109
+
110
+
111
+ class FMUSplitterDescription:
112
+ def __init__(self, zip):
113
+ self.zip = zip
114
+ self.links: Dict[str, Dict[int, FMUSplitterLink]] = {
115
+ "Real": {},
116
+ "Integer": {},
117
+ "Boolean": {},
118
+ "String": {}
119
+ }
120
+ self.vr_to_name: Dict[str, Dict[str, Dict[int, Dict[str, str]]]] = {} # name, fmi_type, vr <-> {name, causality}
121
+ self.config: Dict[str, Any] = {
122
+ "auto_input": False,
123
+ "auto_output": False,
124
+ "auto_parameter": False,
125
+ "auto_local": False,
126
+ "auto_link": False,
127
+ }
128
+ self.fmu_filename_list = []
129
+
130
+ # used for modelDescription.xml parsing
131
+ self.current_fmu_filename = None
132
+ self.current_vr = None
133
+ self.current_name = None
134
+ self.current_causality = None
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, name, attrs):
145
+ if name == "ScalarVariable":
146
+ self.current_name = attrs["name"]
147
+ self.current_vr = int(attrs["valueReference"])
148
+ self.current_causality = attrs["causality"]
149
+ elif name in self.vr_to_name[self.current_fmu_filename]:
150
+ self.vr_to_name[self.current_fmu_filename][name][self.current_vr] = {"name": self.current_name,
151
+ "causality": self.current_causality}
152
+ else:
153
+ self.current_vr = None
154
+ self.current_name = None
155
+ self.current_causality = None
156
+
157
+ def parse_model_description(self, directory: str, fmu_filename: str):
158
+
159
+ if directory == ".":
160
+ filename = "modelDescription.xml"
161
+ else:
162
+ filename = f"{directory}/modelDescription.xml"
163
+
164
+ self.vr_to_name[fmu_filename] = {
165
+ "Real": {},
166
+ "Integer": {},
167
+ "Boolean": {},
168
+ "String": {}
169
+ }
170
+ parser = xml.parsers.expat.ParserCreate()
171
+ self.current_fmu_filename = fmu_filename
172
+ self.current_vr = None
173
+ self.current_name = None
174
+ self.current_causality = None
175
+ parser.StartElementHandler = self.start_element
176
+ with (self.zip.open(filename) as file):
177
+ logger.debug(f"Parsing '{filename}' ({fmu_filename})")
178
+ parser.ParseFile(file)
179
+
180
+ def parse_txt_file_header(self, file, txt_filename):
181
+ self.config["mt"] = self.get_line(file) == "1"
182
+ self.config["profiling"] = self.get_line(file) == "1"
183
+ self.config["step_size"] = float(self.get_line(file))
184
+ nb_fmu = int(self.get_line(file))
185
+ logger.debug(f"Number of FMUs: {nb_fmu}")
186
+ self.config["candidate_fmu"] = []
187
+
188
+ for i in range(nb_fmu):
189
+ fmu_filename = self.get_line(file)
190
+ base_directory = "/".join(txt_filename.split("/")[0:-1])
191
+ try:
192
+ self.parse_model_description(f"{base_directory}/{fmu_filename}", fmu_filename)
193
+ except KeyError:
194
+ self.parse_model_description(f"{base_directory}/{i:02x}", fmu_filename)
195
+ self.config["candidate_fmu"].append(fmu_filename)
196
+ _library = self.get_line(file)
197
+ _uuid = self.get_line(file)
198
+ _nb_local_variables = self.get_line(file)
199
+
200
+ def add_port(self, fmi_type: str, fmu_id: int, fmu_vr: int, container_vr: int):
201
+ if fmu_id >= 0:
202
+ fmu_filename = self.config["candidate_fmu"][fmu_id]
203
+ causality = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["causality"]
204
+ fmu_port_name = self.vr_to_name[fmu_filename][fmi_type][fmu_vr]["name"]
205
+ container_port = self.vr_to_name["."][fmi_type][container_vr]["name"]
206
+ if not causality == "output":
207
+ causality = "input"
208
+ definition = [container_port, fmu_filename, fmu_port_name]
209
+ else:
210
+ definition = [fmu_filename, fmu_port_name, container_port]
211
+
212
+ try:
213
+ self.config[causality].append(definition)
214
+ except KeyError:
215
+ self.config[causality] = [definition]
216
+
217
+ logger.debug(f"Adding container port {causality}: {definition}")
218
+
219
+ def parse_txt_file_ports(self, file):
220
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
221
+ nb_port_variables = self.get_line(file).split(" ")[0]
222
+ for i in range(int(nb_port_variables)):
223
+ tokens = self.get_line(file).split(" ")
224
+ if len(tokens) > 3:
225
+ container_vr = int(tokens[0])
226
+ for j in range(int(tokens[1])):
227
+ fmu_id = int(tokens[2 + 2 * j])
228
+ fmu_vr = int(tokens[2 + 2 * j + 1])
229
+ self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
230
+ else: # For FMUContainer <= 1.8.4
231
+ container_vr = int(tokens[0])
232
+ fmu_id = int(tokens[1])
233
+ fmu_vr = int(tokens[2])
234
+ self.add_port(fmi_type, fmu_id, fmu_vr, container_vr)
235
+
236
+ def parse_txt_file(self, txt_filename: str):
237
+ self.parse_model_description(str(Path(txt_filename).parent.parent), ".")
238
+ logger.debug(f"Parsing container file '{txt_filename}'")
239
+
240
+ with (self.zip.open(txt_filename) as file):
241
+ self.parse_txt_file_header(file, txt_filename)
242
+ self.parse_txt_file_ports(file)
243
+
244
+
245
+ for fmu_filename in self.config["candidate_fmu"]:
246
+ # Inputs per FMUs
247
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
248
+ nb_input = int(self.get_line(file))
249
+ for i in range(nb_input):
250
+ local, vr = self.get_line(file).split(" ")
251
+ try:
252
+ link = self.links[fmi_type][local]
253
+ except KeyError:
254
+ link = FMUSplitterLink()
255
+ self.links[fmi_type][local] = link
256
+ link.to_port.append(FMUSplitterPort(fmu_filename,
257
+ self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"]))
258
+
259
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
260
+ nb_start = int(self.get_line(file))
261
+ for i in range(nb_start):
262
+ tokens = self.get_line(file).split(" ")
263
+ vr = int(tokens[0])
264
+ value = tokens[-1]
265
+ start_definition = [fmu_filename, self.vr_to_name[fmu_filename][fmi_type][vr]["name"],
266
+ value]
267
+ try:
268
+ self.config["start"].append(start_definition)
269
+ except KeyError:
270
+ self.config["start"] = [start_definition]
271
+
272
+ # Output per FMUs
273
+ for fmi_type in ("Real", "Integer", "Boolean", "String"):
274
+ nb_output = int(self.get_line(file))
275
+
276
+ for i in range(nb_output):
277
+ local, vr = self.get_line(file).split(" ")
278
+ try:
279
+ link = self.links[fmi_type][local]
280
+ except KeyError:
281
+ link = FMUSplitterLink()
282
+ self.links[fmi_type][local] = link
283
+ link.from_port = FMUSplitterPort(fmu_filename,
284
+ self.vr_to_name[fmu_filename][fmi_type][int(vr)]["name"])
285
+
286
+ logger.debug("End of parsing.")
287
+
288
+ for fmi_type, links in self.links.items():
289
+ for link in links.values():
290
+ for to_port in link.to_port:
291
+ definition = [ link.from_port.fmu_filename, link.from_port.port_name,
292
+ to_port.fmu_filename, to_port.port_name]
293
+ try:
294
+ self.config["link"].append(definition)
295
+ except KeyError:
296
+ self.config["link"] = [definition]
297
+
298
+ 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.8.4.3b0
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=kO0geLXvmJSP0NCIby9Nscf2scBBfyXPyYch2kg_YYA,16
4
+ fmu_manipulation_toolbox/assembly.py,sha256=cQ6VNPFxTVDKbgcGQlvfHz-Eztzz8DaAf2o5LZ9wZrY,25896
5
+ fmu_manipulation_toolbox/checker.py,sha256=836wCri6aEl0M6_xHPZ94JRngFjsy8Ee-_t8bzclxBs,2332
6
+ fmu_manipulation_toolbox/container.py,sha256=quBczJ5E2TaXRF33q9zetiyjgIdUNvSmZmj8ga1qaJM,32862
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=zRWzgOjB630COXVhFaRoxif8Se8H3736ZbLvtLFz4sI,12330
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=7-AS67SdNH5Qvu3o0XOyESFpeZ1hCFPJdgjKuxRXqv8,85016
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=xoHrLIGt5BlTs5VMiMJZI2zOwH9DmRG_SCi2nHRVsZg,17920
55
+ fmu_manipulation_toolbox/resources/win32/server_sm.exe,sha256=Kj3OZ24oo0RNVKkOq-MLexbmwDablL5PrWTb-KQ-bJ4,15872
56
+ fmu_manipulation_toolbox/resources/win64/client_sm.dll,sha256=lXGSeSrUjiVJ871DivDvcwEgukmdhWe6i6wXc0jXoXQ,22016
57
+ fmu_manipulation_toolbox/resources/win64/container.dll,sha256=HGUFaLTuRVbyyu3vgzvVTlwARfzUmbnd4kWxiFzdwqg,57856
58
+ fmu_manipulation_toolbox/resources/win64/server_sm.exe,sha256=eUgs_cbUba_GeTXjs6mY3T0RbCqGOT-zdVE_Qlq3bgU,19968
59
+ fmu_manipulation_toolbox-1.8.4.3b0.dist-info/licenses/LICENSE.txt,sha256=c_862mzyk6ownO3Gt6cVs0-53IXLi_-ZEQFNDVabESw,1285
60
+ fmu_manipulation_toolbox-1.8.4.3b0.dist-info/METADATA,sha256=JGtqdb2vX-tfi5iU0w-gBcaubnVfHpHHAIU9hEik1hY,1159
61
+ fmu_manipulation_toolbox-1.8.4.3b0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
62
+ fmu_manipulation_toolbox-1.8.4.3b0.dist-info/entry_points.txt,sha256=HjOZkflbI1IuSY8BpOZre20m24M4GDQGCJfPIa7NrlY,264
63
+ fmu_manipulation_toolbox-1.8.4.3b0.dist-info/top_level.txt,sha256=9D_h-5BMjSqf9z-XFkbJL_bMppR2XNYW3WNuPkXou0k,25
64
+ fmu_manipulation_toolbox-1.8.4.3b0.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