fmu-manipulation-toolbox 1.9.2b1__tar.gz → 1.9.2b2__tar.gz

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 (85) hide show
  1. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/LICENSE.txt +1 -1
  2. fmu_manipulation_toolbox-1.9.2b2/PKG-INFO +42 -0
  3. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/README.md +27 -23
  4. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/__main__.py +2 -2
  5. fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/__version__.py +1 -0
  6. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/assembly.py +12 -8
  7. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/checker.py +4 -2
  8. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/cli/fmucontainer.py +27 -19
  9. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/cli/fmusplit.py +5 -2
  10. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/cli/fmutool.py +8 -3
  11. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/cli/utils.py +11 -1
  12. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/container.py +29 -6
  13. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/operations.py +2 -1
  14. fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
  15. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/linux32/client_sm.so +0 -0
  16. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/linux64/client_sm.so +0 -0
  17. fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  18. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/win32/client_sm.dll +0 -0
  19. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/win32/server_sm.exe +0 -0
  20. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/win64/client_sm.dll +0 -0
  21. fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  22. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/win64/server_sm.exe +0 -0
  23. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/split.py +10 -1
  24. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/version.py +1 -1
  25. fmu_manipulation_toolbox-1.9.2b2/fmu_manipulation_toolbox.egg-info/PKG-INFO +42 -0
  26. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +0 -2
  27. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox.egg-info/entry_points.txt +1 -1
  28. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/setup.py +20 -9
  29. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/tests/test_suite.py +79 -41
  30. fmu_manipulation_toolbox-1.9.2b1/PKG-INFO +0 -30
  31. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/__version__.py +0 -1
  32. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/gui.py +0 -749
  33. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/gui_style.py +0 -252
  34. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/resources/darwin64/container.dylib +0 -0
  35. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/resources/linux64/container.so +0 -0
  36. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox/resources/win64/container.dll +0 -0
  37. fmu_manipulation_toolbox-1.9.2b1/fmu_manipulation_toolbox.egg-info/PKG-INFO +0 -30
  38. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/__init__.py +0 -0
  39. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/cli/__init__.py +0 -0
  40. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/help.py +0 -0
  41. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/ls.py +0 -0
  42. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/remoting.py +0 -0
  43. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
  44. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
  45. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
  46. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
  47. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
  48. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
  49. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/container.png +0 -0
  50. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
  51. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
  52. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
  53. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
  54. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
  55. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
  56. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
  57. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
  58. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
  59. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
  60. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
  61. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
  62. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
  63. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
  64. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
  65. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
  66. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
  67. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
  68. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
  69. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
  70. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
  71. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
  72. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/help.png +0 -0
  73. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
  74. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/icon.png +0 -0
  75. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
  76. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/license.txt +0 -0
  77. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/linux32/server_sm +0 -0
  78. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/linux64/server_sm +0 -0
  79. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/mask.png +0 -0
  80. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/resources/model.png +0 -0
  81. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox/terminals.py +0 -0
  82. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
  83. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox.egg-info/requires.txt +0 -0
  84. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
  85. {fmu_manipulation_toolbox-1.9.2b1 → fmu_manipulation_toolbox-1.9.2b2}/setup.cfg +0 -0
@@ -1,4 +1,4 @@
1
- Copyright (c) 2024 Renault SAS - Nicolas.LAURENT@Renault.com
1
+ Copyright (c) 2024 Renault SAS
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without
4
4
  modification, are permitted provided that the following conditions
@@ -0,0 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: fmu_manipulation_toolbox
3
+ Version: 1.9.2b2
4
+ Summary: FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine Functional Mock-up Units (FMUs) without recompilation.
5
+ Home-page: https://github.com/grouperenault/fmu_manipulation_toolbox/
6
+ Author: Nicolas.LAURENT@Renault.com
7
+ License: BSD-2-Clause
8
+ Requires-Python: >=3.9
9
+ Description-Content-Type: text/markdown
10
+ License-File: LICENSE.txt
11
+ Requires-Dist: PySide6>=6.8.0
12
+ Requires-Dist: xmlschema>=3.3.1
13
+ Requires-Dist: elementpath>=4.4.0
14
+ Requires-Dist: colorama>=0.4.6
15
+ Dynamic: author
16
+ Dynamic: description
17
+ Dynamic: description-content-type
18
+ Dynamic: home-page
19
+ Dynamic: license
20
+ Dynamic: license-file
21
+ Dynamic: requires-dist
22
+ Dynamic: requires-python
23
+ Dynamic: summary
24
+
25
+ FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine
26
+ [Functional Mock-up Units (FMUs)](http://fmi-standard.org/) without recompilation. It is highly customizable and comes with
27
+ a Python API.
28
+
29
+ FMU Manipulation Toolbox can be used in different ways:
30
+ - Using a Graphical User Interface: suitable for end users
31
+ - Using a Command Line Interface: useful for scripting and automation
32
+ - Using a Python API: the most efficient option for automation (CI/CD, transformation scripts, ...))
33
+
34
+ Major features:
35
+ - Analyze FMU content: list ports and their attributes, check compliance of `ModelDescription.xml` with XSD, etc.
36
+ - Alter FMU by modifying its `modelDescription.xml` file. NOTE: manipulating this file can be a risky.
37
+ When possible, it is preferable to communicate with the FMU developer and adapt the FMU generation process.
38
+ - Add binary interfaces. Typical use case is porting a 32-bit FMUs to 64-bit systems (or vice et versa).
39
+ - Combine FMUs into [FMU Containers](doc/container.md) and allow your favourite FMI tool to orchestrate complex assembly of FMUs.
40
+
41
+ FMI versions 2.0 and 3.0 are supported.
42
+
@@ -1,31 +1,36 @@
1
1
  ![](fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png)
2
2
 
3
- FMU Manipulation Toolbox is a python package which help to analyse, modify or combine
4
- [Functional Mock-up Units (FMUs)](http://fmi-standard.org/) without recompilation. It is highly customizable as it comes with
3
+ ![](https://raw.githubusercontent.com/grouperenault/fmu_manipulation_toolbox/refs/heads/badges/.github/badges/python-version.svg)
4
+ ![](https://raw.githubusercontent.com/grouperenault/fmu_manipulation_toolbox/refs/heads/badges/.github/badges/fmi-version.svg)
5
+ ![](https://raw.githubusercontent.com/grouperenault/fmu_manipulation_toolbox/refs/heads/badges/.github/badges/coverage.svg)
6
+
7
+ # 👀 Overview
8
+
9
+ FMU Manipulation Toolbox is a python package which helps to analyze, modify or combine
10
+ [Functional Mock-up Units (FMUs)](http://fmi-standard.org/) without recompilation. It is highly customizable and comes with
5
11
  a Python API.
6
12
 
7
- FMU Manipulation Toolbox can be used in different ways :
8
- - Using a Graphical User Interface: suitable for end user
9
- - Using a Command Line Interface: useful in
10
- - Using a python API: the most efficient for automation (CI/CD, transformation scripts, ...)
13
+ FMU Manipulation Toolbox can be used in different ways:
14
+ - Using a Graphical User Interface: suitable for end users
15
+ - Using a Command Line Interface: useful for scripting and automation
16
+ - Using a Python API: the most efficient option for automation (CI/CD, transformation scripts, ...))
11
17
 
12
18
  Major features:
13
- - Analyse FMU content: list ports and their attributes, check compliance of `ModelDescription.xml` with XSD, ...
14
- - Alter FMU by modifying its `modelDescription.xml` file. NOTE: manipulating this file can be a dangerous
15
- thing! Communicating with the FMU-developer and adapting the way the FMU is generated is preferable when
16
- possible.
17
- - Add binary interface. Typical use case is porting a 32bits FMUs to 64bits (or vice et versa).
18
- - Nest FMUs in a [FMU Container](doc/container.md)
19
+ - Analyze FMU content: list ports and their attributes, check compliance of `ModelDescription.xml` with XSD, etc.
20
+ - Alter FMU by modifying its `modelDescription.xml` file. NOTE: manipulating this file can be a risky.
21
+ When possible, it is preferable to communicate with the FMU developer and adapt the FMU generation process.
22
+ - Add binary interfaces. Typical use case is porting a 32-bit FMUs to 64-bit systems (or vice et versa).
23
+ - Combine FMUs into [FMU Containers](doc/container.md) and allow your favourite FMI tool to orchestrate complex assembly of FMUs.
19
24
 
20
25
  FMI versions 2.0 and 3.0 are supported.
21
26
 
22
- ## Installation
27
+ # ⚙️ Installation
23
28
 
24
29
  Two options available to install FMU Manipulation Toolbox:
25
30
 
26
31
  - (*Easiest option*) Install with from PyPI: `pip install fmu-manipulation-toolbox`. This will install the latest
27
32
  version of FMU Manipulation Toolbox and all its dependencies. See [PyPI page](https://pypi.org/project/fmu-manipulation-toolbox/).
28
- - Compile and install from [github repository](https://github.com/grouperenault/fmu_manipulation_toolbox). You will need
33
+ - Compile and install from [GitHub repository](https://github.com/grouperenault/fmu_manipulation_toolbox). You will need
29
34
  - Python required packages. See [`requirements.txt`](requirements.txt).
30
35
  - C compiler (C99 or later)
31
36
  - CMake (>= 3.20)
@@ -39,7 +44,7 @@ FMU Manipulation Toolbox is packaged for:
39
44
  - Darwin
40
45
 
41
46
 
42
- ## Graphical User Interface
47
+ # 🖥️ Graphical User Interface
43
48
 
44
49
  FMU Manipulation Toolbox is released with a GUI. You can launch it with the following command `fmutool-gui`
45
50
 
@@ -55,7 +60,7 @@ Button colors descriptions:
55
60
  **Original FMU is never modified**. Use `Save` button to get modified copy of the original FMU.
56
61
 
57
62
 
58
- ## Command Line Interface
63
+ # 🔧 Command Line Interface
59
64
 
60
65
  FMU Manipulation Toolbox comes with 2 commands:
61
66
  - `fmutool`: a versatile analysis and manipulation tool for FMU.
@@ -63,7 +68,7 @@ FMU Manipulation Toolbox comes with 2 commands:
63
68
  - `fmusplit: to extract FMUs from a FMU Container.
64
69
 
65
70
 
66
- ### Analysis and Manipulation tool:
71
+ ## Analysis and Manipulation tool:
67
72
 
68
73
  You can use `fmutool -help` to get usage:
69
74
 
@@ -149,7 +154,7 @@ optional arguments:
149
154
  later issues when using the FMU. (default: None)
150
155
  ```
151
156
 
152
- ### FMU Containers
157
+ ## FMU Containers
153
158
 
154
159
  ```
155
160
  usage: fmucontainer [-h] [-fmu-directory FMU_DIRECTORY] [-fmi FMI_VERSION]
@@ -178,7 +183,7 @@ options:
178
183
  -dump-json Dump a JSON file for each container. (default: False)
179
184
  ```
180
185
 
181
- ## API
186
+ # 🚀 API
182
187
 
183
188
  You can write your own FMU Manipulation scripts. Once you downloaded fmutool module,
184
189
  adding the `import` statement lets you access the API :
@@ -188,7 +193,7 @@ from fmu_manipulation_toolbox.operations import ...
188
193
  ```
189
194
 
190
195
 
191
- ### remove toplevel bus (if any)
196
+ ## remove toplevel bus (if any)
192
197
 
193
198
  Given a FMU with the following I/O structure
194
199
  ```
@@ -230,9 +235,8 @@ The following code will dump all FMU's Scalars names into a CSV:
230
235
  from fmu_manipulation_toolbox.operations import FMU, OperationSaveNamesToCSV
231
236
 
232
237
  fmu = FMU(r"bouncing_ball.fmu")
233
- operation = OperationSaveNamesToCSV()
238
+ operation = OperationSaveNamesToCSV(r"bouncing_ball.csv")
234
239
  fmu.apply_operation(operation)
235
- operation.write_csv(r"bouncing_ball.csv")
236
240
  ```
237
241
 
238
242
  The produced CSV contains 2 columns in order to be reused in the next transformation.
@@ -249,7 +253,7 @@ e;e;5;parameter;tunable
249
253
  ```
250
254
 
251
255
 
252
- ### Read CSV and rename FMU ports
256
+ ## Read CSV and rename FMU ports
253
257
 
254
258
  CSV file should contain 2 columns:
255
259
  1. the current name
@@ -3,7 +3,7 @@ import sys
3
3
 
4
4
  def gui():
5
5
  try:
6
- from .gui import main
6
+ from .gui.gui import main
7
7
  main()
8
8
  except ModuleNotFoundError as e:
9
9
  print(f"FATAL ERROR: {e}. No GUI Available.")
@@ -11,7 +11,7 @@ def gui():
11
11
 
12
12
  def cli():
13
13
  from .cli.fmutool import fmutool
14
- fmutool(sys.argv[1:])
14
+ fmutool()
15
15
 
16
16
 
17
17
  def main():
@@ -7,7 +7,7 @@ import uuid
7
7
  import xml.parsers.expat
8
8
  import zipfile
9
9
 
10
- from .container import FMUContainer, AutoWired
10
+ from .container import FMUContainer
11
11
 
12
12
  logger = logging.getLogger("fmu_manipulation_toolbox")
13
13
 
@@ -103,7 +103,8 @@ class AssemblyNode:
103
103
  def add_start_value(self, fmu_filename: str, port_name: str, value: str):
104
104
  self.start_values[Port(fmu_filename, port_name)] = value
105
105
 
106
- def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None, fmi_version=2):
106
+ def make_fmu(self, fmu_directory: Path, debug=False, description_pathname=None, fmi_version=2, datalog=False,
107
+ filename=None):
107
108
  for node in self.children.values():
108
109
  node.make_fmu(fmu_directory, debug=debug, fmi_version=fmi_version)
109
110
 
@@ -142,8 +143,11 @@ class AssemblyNode:
142
143
  for link_rule in wired.rule_link:
143
144
  self.add_link(link_rule[0], link_rule[1], link_rule[2], link_rule[3])
144
145
 
145
- container.make_fmu(self.name, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
146
- debug=debug, ts_multiplier=self.ts_multiplier)
146
+ if filename is None:
147
+ filename = self.name
148
+
149
+ container.make_fmu(filename, self.step_size, mt=self.mt, profiling=self.profiling, sequential=self.sequential,
150
+ debug=debug, ts_multiplier=self.ts_multiplier, datalog=datalog)
147
151
 
148
152
  for node in self.children.values():
149
153
  logger.info(f"Deleting transient FMU Container '{node.name}'")
@@ -241,7 +245,7 @@ class Assembly:
241
245
  self.transient_dirnames: Set[Path] = set()
242
246
 
243
247
  if not fmu_directory.is_dir():
244
- raise AssemblyError(f"FMU directory is not valid: '{fmu_directory}'")
248
+ raise AssemblyError(f"FMU directory is not valid: '{fmu_directory.resolve()}'")
245
249
 
246
250
  self.input_pathname = fmu_directory / self.filename
247
251
  self.description_pathname = self.input_pathname # For inclusion in FMU
@@ -284,7 +288,7 @@ class Assembly:
284
288
  elif filename.endswith(".json"):
285
289
  return self.write_json(filename)
286
290
  else:
287
- logger.critical(f"Unable to write to '{filename}': format unsupported.")
291
+ raise AssemblyError(f"Unable to write to '{filename}': format unsupported.")
288
292
 
289
293
  def read_csv(self):
290
294
  name = str(self.filename.with_suffix(".fmu"))
@@ -525,9 +529,9 @@ class Assembly:
525
529
  self.root = sdd.parse(self.description_pathname)
526
530
  self.root.name = str(self.filename.with_suffix(".fmu"))
527
531
 
528
- def make_fmu(self, dump_json=False, fmi_version=2):
532
+ def make_fmu(self, dump_json=False, fmi_version=2, datalog=False, filename=None):
529
533
  self.root.make_fmu(self.fmu_directory, debug=self.debug, description_pathname=self.description_pathname,
530
- fmi_version=fmi_version)
534
+ fmi_version=fmi_version, datalog=datalog, filename=filename)
531
535
  if dump_json:
532
536
  dump_file = Path(self.input_pathname.stem + "-dump").with_suffix(".json")
533
537
  logger.info(f"Dump Json '{dump_file}'")
@@ -27,11 +27,11 @@ class OperationGenericCheck(OperationAbstract):
27
27
  return
28
28
 
29
29
  fmi_name = f"fmi{attrs['fmiVersion'][0]}"
30
-
31
30
  xsd_filename = os.path.join(os.path.dirname(__file__), "resources", "fmi-" + attrs['fmiVersion'],
32
31
  f"{fmi_name}ModelDescription.xsd")
32
+ xsd = xmlschema.XMLSchema(xsd_filename)
33
33
  try:
34
- xmlschema.validate(self.fmu.descriptor_filename, schema=xsd_filename)
34
+ xsd.validate(self.fmu.descriptor_filename)
35
35
  except XMLSchemaValidationError as error:
36
36
  logger.error(error.reason, error.msg)
37
37
  else:
@@ -43,8 +43,10 @@ class OperationGenericCheck(OperationAbstract):
43
43
  else:
44
44
  logger.error(f"This FMU does not validate with FMI standard.")
45
45
 
46
+
46
47
  _checkers_list: List[type[OperationAbstract]] = [OperationGenericCheck]
47
48
 
49
+
48
50
  def get_checkers() -> List[type[OperationAbstract]]:
49
51
  if sys.version_info < (3, 10):
50
52
  from importlib_metadata import entry_points
@@ -4,7 +4,7 @@ import sys
4
4
 
5
5
  from pathlib import Path
6
6
 
7
- from .utils import setup_logger, make_wide
7
+ from .utils import setup_logger, close_logger, make_wide
8
8
  from ..assembly import Assembly, AssemblyError
9
9
  from ..container import FMUContainerError
10
10
  from ..version import __version__ as version
@@ -22,36 +22,42 @@ def fmucontainer():
22
22
 
23
23
  parser.add_argument('-h', '-help', action="help")
24
24
 
25
- parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
26
- help="Directory containing initial FMU’s and used to generate containers. "
27
- "If not defined, current directory is used.")
28
-
29
- parser.add_argument("-fmi", action="store", dest="fmi_version", required=False, default="2",
30
- help="Define version of FMI to be used for container interface."
31
- "Only '2' or '3' is supported.")
32
-
33
25
  parser.add_argument("-container", action="append", dest="container_descriptions_list", default=[],
34
26
  metavar="filename.{csv|json|ssp},[:step_size]", required=True,
35
27
  help="Description of the container to create.")
36
28
 
29
+ parser.add_argument("-datalog", action="store_true", dest="datalog", default=False,
30
+ help="Log into log file input, output and local variables of the container")
31
+
37
32
  parser.add_argument("-debug", action="store_true", dest="debug",
38
33
  help="Add lot of useful log during the process.")
39
34
 
35
+ parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
36
+ help="Dump a JSON file for each container.")
37
+
38
+ parser.add_argument("-fmi", action="store", dest="fmi_version", required=False, default="2",
39
+ help="Define version of FMI to be used for container interface."
40
+ "Only '2' or '3' is supported.")
41
+
42
+ parser.add_argument("-fmu-directory", action="store", dest="fmu_directory", required=False, default=".",
43
+ help="Directory containing initial FMU’s and used to generate containers. "
44
+ "If not defined, current directory is used.")
45
+
40
46
  parser.add_argument("-no-auto-input", action="store_false", dest="auto_input", default=True,
41
47
  help="Create ONLY explicit input.")
42
48
 
49
+ parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
50
+ help="Create ONLY explicit links.")
51
+
52
+ parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
53
+ help="Expose local variables of the embedded fmu's.")
54
+
43
55
  parser.add_argument("-no-auto-output", action="store_false", dest="auto_output", default=True,
44
56
  help="Create ONLY explicit output.")
45
57
 
46
58
  parser.add_argument("-auto-parameter", action="store_true", dest="auto_parameter", default=False,
47
59
  help="Expose parameters of the embedded fmu's.")
48
60
 
49
- parser.add_argument("-auto-local", action="store_true", dest="auto_local", default=False,
50
- help="Expose local variables of the embedded fmu's.")
51
-
52
- parser.add_argument("-no-auto-link", action="store_false", dest="auto_link", default=True,
53
- help="Create ONLY explicit links.")
54
-
55
61
  parser.add_argument("-mt", action="store_true", dest="mt", default=False,
56
62
  help="Enable Multi-Threaded mode for the generated container.")
57
63
 
@@ -61,9 +67,6 @@ def fmucontainer():
61
67
  parser.add_argument("-sequential", action="store_true", dest="sequential", default=False,
62
68
  help="Use sequential mode to schedule embedded fmu's.")
63
69
 
64
- parser.add_argument("-dump-json", action="store_true", dest="dump", default=False,
65
- help="Dump a JSON file for each container.")
66
-
67
70
  parser.add_argument("-vr", action="store_true", dest="ts_multiplier", default=False,
68
71
  help="Add TS_MULTIPLIER input port to control step_size")
69
72
 
@@ -92,16 +95,21 @@ def fmucontainer():
92
95
  auto_parameter=config.auto_parameter, ts_multiplier=config.ts_multiplier)
93
96
  except FileNotFoundError as e:
94
97
  logger.fatal(f"Cannot read file: {e}")
98
+ close_logger(logger)
95
99
  sys.exit(-1)
96
100
  except (FMUContainerError, AssemblyError) as e:
97
101
  logger.fatal(f"{filename}: {e}")
102
+ close_logger(logger)
98
103
  sys.exit(-2)
99
104
 
100
105
  try:
101
- assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version))
106
+ assembly.make_fmu(dump_json=config.dump, fmi_version=int(config.fmi_version), datalog=config.datalog)
102
107
  except FMUContainerError as e:
103
108
  logger.fatal(f"{filename}: {e}")
109
+ close_logger(logger)
104
110
  sys.exit(-3)
105
111
 
112
+ close_logger(logger)
113
+
106
114
  if __name__ == "__main__":
107
115
  fmucontainer()
@@ -2,8 +2,7 @@ import argparse
2
2
  import logging
3
3
  import sys
4
4
 
5
-
6
- from .utils import setup_logger, make_wide
5
+ from .utils import setup_logger, close_logger, make_wide
7
6
  from ..split import FMUSplitter, FMUSplitterError
8
7
  from ..version import __version__ as version
9
8
 
@@ -37,11 +36,15 @@ def fmusplit():
37
36
  splitter.split_fmu()
38
37
  except FMUSplitterError as e:
39
38
  logger.fatal(f"{fmu_filename}: {e}")
39
+ close_logger(logger)
40
40
  sys.exit(-1)
41
41
  except FileNotFoundError as e:
42
42
  logger.fatal(f"Cannot read file: {e}")
43
+ close_logger(logger)
43
44
  sys.exit(-2)
44
45
 
46
+ close_logger(logger)
47
+
45
48
 
46
49
  if __name__ == "__main__":
47
50
  fmusplit()
@@ -1,9 +1,7 @@
1
1
  import argparse
2
2
  import sys
3
3
 
4
- from typing import *
5
-
6
- from .utils import setup_logger, make_wide
4
+ from .utils import setup_logger, close_logger, make_wide
7
5
  from ..operations import (OperationSummary, OperationError, OperationRemoveRegexp,
8
6
  OperationRemoveSources, OperationTrimUntil, OperationKeepOnlyRegexp, OperationMergeTopLevel,
9
7
  OperationStripTopLevel, OperationRenameFromCSV, OperationSaveNamesToCSV, FMU, FMUError)
@@ -78,6 +76,7 @@ def fmutool():
78
76
 
79
77
  if cli_options.fmu_input == cli_options.fmu_output:
80
78
  logger.fatal(f"'-input' and '-output' should point to different files.")
79
+ close_logger(logger)
81
80
  sys.exit(-3)
82
81
 
83
82
  logger.info(f"READING Input='{cli_options.fmu_input}'")
@@ -85,6 +84,7 @@ def fmutool():
85
84
  fmu = FMU(cli_options.fmu_input)
86
85
  except FMUError as reason:
87
86
  logger.fatal(f"{reason}")
87
+ close_logger(logger)
88
88
  sys.exit(-4)
89
89
 
90
90
  if cli_options.apply_on:
@@ -107,6 +107,7 @@ def fmutool():
107
107
  fmu.apply_operation(operation, cli_options.apply_on)
108
108
  except OperationError as reason:
109
109
  logger.fatal(f"{reason}")
110
+ close_logger(logger)
110
111
  sys.exit(-6)
111
112
 
112
113
  if cli_options.extract_description:
@@ -119,9 +120,13 @@ def fmutool():
119
120
  fmu.repack(cli_options.fmu_output)
120
121
  except FMUError as reason:
121
122
  logger.fatal(f"FATAL ERROR: {reason}")
123
+ close_logger(logger)
122
124
  sys.exit(-5)
123
125
  else:
124
126
  logger.info(f"INFO Modified FMU is not saved. If necessary use '-output' option.")
125
127
 
128
+ close_logger(logger)
129
+
130
+
126
131
  if __name__ == "__main__":
127
132
  fmutool()
@@ -2,7 +2,8 @@ import logging
2
2
  import sys
3
3
  from colorama import Fore, Style, init
4
4
 
5
- def setup_logger():
5
+
6
+ def setup_logger() -> logging.Logger:
6
7
  class CustomFormatter(logging.Formatter):
7
8
  def format(self, record):
8
9
  log_format = "%(levelname)-8s | %(message)s"
@@ -24,6 +25,15 @@ def setup_logger():
24
25
 
25
26
  return logger
26
27
 
28
+
29
+ def close_logger(logger: logging.Logger):
30
+ for handler in logger.handlers:
31
+ logger.removeHandler(handler)
32
+ handler.close()
33
+ logger.setLevel(logging.NOTSET)
34
+ logger.propagate = True
35
+
36
+
27
37
  def make_wide(formatter, w=120, h=36):
28
38
  """Return a wider HelpFormatter, if possible."""
29
39
  try:
@@ -484,7 +484,7 @@ class FMUIOList:
484
484
 
485
485
  def add_start_value(self, cport: ContainerPort, value: str):
486
486
  reset = 1 if cport.port.causality == "input" else 0
487
- self.start_values[cport.port.type_name][cport.fmu.name].append((cport, reset, value))
487
+ self.start_values[cport.port.type_name][cport.fmu.name].append((cport.port.vr, reset, value))
488
488
 
489
489
  def write_txt(self, fmu_name, txt_file):
490
490
  for type_name in EmbeddedFMUPort.ALL_TYPES:
@@ -535,7 +535,7 @@ class ClockList:
535
535
 
536
536
  def write_txt(self, txt_file):
537
537
  print(f"# importer CLOCKS: <FMU_INDEX> <NB> <FMU_VR> <VR> [<FMU_VR> <VR>]", file=txt_file)
538
- nb_total_clocks = 0;
538
+ nb_total_clocks = 0
539
539
  for clocks in self.clocks_per_fmu.values():
540
540
  nb_total_clocks += len(clocks)
541
541
 
@@ -756,11 +756,11 @@ class FMUContainer:
756
756
  cport = ContainerPort(self.get_fmu(fmu_filename), port_name)
757
757
 
758
758
  try:
759
- if cport.port.type_name in ('Real', 'Float64', 'Float32'):
759
+ if cport.port.type_name.startswith('real'):
760
760
  value = float(value)
761
- elif cport.port.type_name in ('Integer', 'Int8', 'UInt8', 'Int16', 'UInt16', 'Int32', 'UInt32', 'Int64', 'UInt64'):
761
+ elif cport.port.type_name.startswith('integer') or cport.port.type_name.startswith('uinteger'):
762
762
  value = int(value)
763
- elif cport.port.type_name == 'Boolean':
763
+ elif cport.port.type_name.startswith('boolean'):
764
764
  value = int(bool(value))
765
765
  elif cport.port.type_name == 'String':
766
766
  value = value
@@ -872,7 +872,7 @@ class FMUContainer:
872
872
  logger.warning(f"{cport} is not connected")
873
873
 
874
874
  def make_fmu(self, fmu_filename: Union[str, Path], step_size: Optional[float] = None, debug=False, mt=False,
875
- profiling=False, sequential=False, ts_multiplier=False):
875
+ profiling=False, sequential=False, ts_multiplier=False, datalog=False):
876
876
  if isinstance(fmu_filename, str):
877
877
  fmu_filename = Path(fmu_filename)
878
878
 
@@ -885,11 +885,16 @@ class FMUContainer:
885
885
 
886
886
  base_directory = self.fmu_directory / fmu_filename.with_suffix('')
887
887
  resources_directory = self.make_fmu_skeleton(base_directory)
888
+
888
889
  with open(base_directory / "modelDescription.xml", "wt") as xml_file:
889
890
  self.make_fmu_xml(xml_file, step_size, profiling, ts_multiplier)
890
891
  with open(resources_directory / "container.txt", "wt") as txt_file:
891
892
  self.make_fmu_txt(txt_file, step_size, mt, profiling, sequential)
892
893
 
894
+ if datalog:
895
+ with open(resources_directory / "datalog.txt", "wt") as datalog_file:
896
+ self.make_datalog(datalog_file)
897
+
893
898
  self.make_fmu_package(base_directory, fmu_filename)
894
899
  if not debug:
895
900
  self.make_fmu_cleanup(base_directory)
@@ -1173,6 +1178,24 @@ class FMUContainer:
1173
1178
  # CLOCKS
1174
1179
  clock_list.write_txt(txt_file)
1175
1180
 
1181
+ def make_datalog(self, datalog_file):
1182
+ print(f"# Datalog filename")
1183
+ print(f"{self.identifier}-datalog.csv", file=datalog_file)
1184
+
1185
+ ports = defaultdict(list)
1186
+ for input_port_name, input_port in self.inputs.items():
1187
+ ports[input_port.type_name].append((input_port.vr, input_port_name))
1188
+ for output_port_name, output_port in self.outputs.items():
1189
+ ports[output_port.port.type_name].append((output_port.vr, output_port_name))
1190
+ for link in self.links.values():
1191
+ ports[link.cport_from.port.type_name].append((link.vr, link.name))
1192
+
1193
+ for type_name in EmbeddedFMUPort.ALL_TYPES:
1194
+ print(f"# {type_name}: <VR> <NAME>" , file=datalog_file)
1195
+ print(f"{len(ports[type_name])}", file=datalog_file)
1196
+ for port in ports[type_name]:
1197
+ print(f"{port[0]} {port[1]}", file=datalog_file)
1198
+
1176
1199
  @staticmethod
1177
1200
  def long_path(path: Union[str, Path]) -> str:
1178
1201
  # https://stackoverflow.com/questions/14075465/copy-a-file-with-a-too-long-path-to-another-directory-in-python
@@ -121,7 +121,8 @@ class Manipulation:
121
121
  TAGS_MODEL_STRUCTURE = ("InitialUnknowns", "Derivatives", "Outputs")
122
122
 
123
123
  def __init__(self, operation, fmu):
124
- self.output_filename = tempfile.mktemp()
124
+ (fd, self.output_filename) = tempfile.mkstemp()
125
+ os.close(fd) # File will be re-opened later
125
126
  self.out = None
126
127
  self.operation = operation
127
128
  self.parser = xml.parsers.expat.ParserCreate()
@@ -6,6 +6,15 @@ import xml.parsers.expat
6
6
  from typing import *
7
7
  from pathlib import Path
8
8
 
9
+ from .container import EmbeddedFMUPort
10
+ import logging
11
+ import zipfile
12
+ import json
13
+ import xml.parsers.expat
14
+
15
+ from typing import *
16
+ from pathlib import Path
17
+
9
18
  from .container import EmbeddedFMUPort
10
19
 
11
20
  logger = logging.getLogger("fmu_manipulation_toolbox")
@@ -191,7 +200,7 @@ class FMUSplitterDescription:
191
200
  self.config["mt"] = flags[0] == "1"
192
201
  self.config["profiling"] = self.get_line(file) == "1"
193
202
  self.config["sequential"] = False
194
- elif len(flags) == 3:
203
+ elif len(flags) >= 3:
195
204
  self.supported_fmi_types = EmbeddedFMUPort.ALL_TYPES
196
205
  self.config["mt"] = flags[0] == "1"
197
206
  self.config["profiling"] = flags[1] == "1"
@@ -4,6 +4,6 @@ except ModuleNotFoundError:
4
4
  __version__ = "0.0.dev0"
5
5
 
6
6
  __author__ = "Nicolas.LAURENT@Renault.com"
7
- __copyright__ = "Copyright 2023-2024, Renault SAS"
7
+ __copyright__ = "Copyright 2023-2026, Renault SAS"
8
8
  __license__ = """This code is released under the 2-Clause BSD license.
9
9
  See https://github.com/grouperenault/fmu_manipulation_toolbox/blob/main/LICENSE.txt"""