fmu-manipulation-toolbox 2.0b3__tar.gz → 2.1.dev1__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 (314) hide show
  1. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CHANGELOG.md +71 -4
  2. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/MANIFEST.in +3 -1
  3. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/PKG-INFO +9 -2
  4. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/README.md +7 -0
  5. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/library.c +43 -3
  6. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.h +4 -1
  7. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/_version.py +3 -3
  8. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assembly.py +158 -23
  9. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/fmutools.py +211 -26
  10. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/headless.py +46 -0
  11. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/knowledge.py +7 -3
  12. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/models.py +9 -46
  13. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/server.py +87 -142
  14. fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/assistant/tools.py +319 -0
  15. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/checker.py +2 -11
  16. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool.py +18 -3
  17. fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/cli/fmutool_agent.py +285 -0
  18. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/utils.py +8 -0
  19. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__main__.py +49 -21
  20. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/assembly_io.py +52 -4
  21. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/wire_detail.py +45 -1
  22. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/constants.py +4 -0
  23. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/wire.py +40 -4
  24. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/mcp_bridge.py +38 -13
  25. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__main__.py +10 -4
  26. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__main__.py +44 -14
  27. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/helper.py +5 -352
  28. fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/gui/log.py +617 -0
  29. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/help.py +16 -3
  30. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/model_description.py +58 -1
  31. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/operations.py +85 -22
  32. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/PKG-INFO +9 -2
  33. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +10 -0
  34. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/entry_points.txt +1 -0
  35. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/requires.txt +1 -1
  36. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/scm_file_list.json +23 -0
  37. fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox.egg-info/scm_version.json +8 -0
  38. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/mkdocs.yml +2 -0
  39. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/pyproject.toml +2 -1
  40. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.c +2 -1
  41. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/mcp_budget.py +7 -2
  42. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_assistant_qt_bridge.py +53 -0
  43. fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_architecture_wires.py +165 -0
  44. fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_open_file.py +76 -0
  45. fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_ssp_geometry.py +69 -0
  46. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_gui.py +88 -0
  47. fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_gui_logging.py +470 -0
  48. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli.py +11 -0
  49. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_compile_sources.py +19 -0
  50. fmu_manipulation_toolbox-2.1.dev1/tests/integration/test_ssp.py +202 -0
  51. fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_agent_skills.py +242 -0
  52. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_fmutools.py +175 -5
  53. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_contract.py +6 -4
  54. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_tools.py +76 -0
  55. fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_fmutool_agent.py +286 -0
  56. fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_operations_scope.py +209 -0
  57. fmu_manipulation_toolbox-2.1.dev1/tools/build_skill_zips.py +56 -0
  58. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/make_carousel.py +40 -2
  59. fmu_manipulation_toolbox-2.0b3/fmu_manipulation_toolbox.egg-info/scm_version.json +0 -8
  60. fmu_manipulation_toolbox-2.0b3/tests/gui/test_gui_logging.py +0 -240
  61. fmu_manipulation_toolbox-2.0b3/tests/integration/test_ssp.py +0 -87
  62. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.git_archival.txt +0 -0
  63. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.gitattributes +0 -0
  64. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.gitignore +0 -0
  65. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CLAUDE.md +0 -0
  66. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CONTRIBUTING.md +0 -0
  67. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/LICENSE.txt +0 -0
  68. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/fmutool.cmake +0 -0
  69. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/gen_version.cmake +0 -0
  70. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/pgo.cmake +0 -0
  71. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/version.h.in +0 -0
  72. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/CMakeLists.txt +0 -0
  73. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/build.bat +0 -0
  74. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/config.c +0 -0
  75. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/config.h +0 -0
  76. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/container.c +0 -0
  77. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/container.h +0 -0
  78. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.c +0 -0
  79. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.h +0 -0
  80. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.c +0 -0
  81. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.h +0 -0
  82. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi2.c +0 -0
  83. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi3.c +0 -0
  84. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.c +0 -0
  85. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.h +0 -0
  86. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.c +0 -0
  87. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.h +0 -0
  88. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/library.h +0 -0
  89. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.c +0 -0
  90. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.c +0 -0
  91. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.h +0 -0
  92. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.c +0 -0
  93. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.h +0 -0
  94. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/test_fmi.c +0 -0
  95. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/empty/container.txt +0 -0
  96. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/container.txt.in +0 -0
  97. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/datalog.txt.in +0 -0
  98. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/stub_fmu.c +0 -0
  99. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test.h +0 -0
  100. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_config.c +0 -0
  101. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_configure.c +0 -0
  102. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_datalog.c +0 -0
  103. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_locale.c +0 -0
  104. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_logger.c +0 -0
  105. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_main.c +0 -0
  106. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_malformed.c +0 -0
  107. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_thread.c +0 -0
  108. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_threads_lifecycle.c +0 -0
  109. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.c +0 -0
  110. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.h +0 -0
  111. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__init__.py +0 -0
  112. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__main__.py +0 -0
  113. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/__init__.py +0 -0
  114. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/analysis.py +0 -0
  115. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/auth.py +0 -0
  116. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/bridge.py +0 -0
  117. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/paths.py +0 -0
  118. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/replay.py +0 -0
  119. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/__init__.py +0 -0
  120. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/datalog2pcap.py +0 -0
  121. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmucontainer.py +0 -0
  122. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmusplit.py +0 -0
  123. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool_mcp.py +0 -0
  124. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/compiler.py +0 -0
  125. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/__init__.py +0 -0
  126. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/arrays.py +0 -0
  127. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/builder.py +0 -0
  128. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/embedded.py +0 -0
  129. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/errors.py +0 -0
  130. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/layout.py +0 -0
  131. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/rules.py +0 -0
  132. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/txt.py +0 -0
  133. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/types.py +0 -0
  134. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__init__.py +0 -0
  135. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__main__.py +0 -0
  136. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__init__.py +0 -0
  137. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/__init__.py +0 -0
  138. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/configuration_detail.py +0 -0
  139. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/container_detail.py +0 -0
  140. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/fmu_detail.py +0 -0
  141. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant.py +0 -0
  142. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant_demo.py +0 -0
  143. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_matching.py +0 -0
  144. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/stack.py +0 -0
  145. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/__init__.py +0 -0
  146. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node.py +0 -0
  147. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node_info_dialog.py +0 -0
  148. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/scene.py +0 -0
  149. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/view.py +0 -0
  150. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/widget.py +0 -0
  151. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/__init__.py +0 -0
  152. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/model.py +0 -0
  153. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/panel.py +0 -0
  154. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/sync.py +0 -0
  155. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/widget.py +0 -0
  156. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__init__.py +0 -0
  157. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__init__.py +0 -0
  158. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/style.py +0 -0
  159. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/ls.py +0 -0
  160. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/remoting.py +0 -0
  161. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
  162. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
  163. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
  164. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
  165. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
  166. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
  167. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/container.png +0 -0
  168. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
  169. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2FunctionTypes.h +0 -0
  170. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2Functions.h +0 -0
  171. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2TypesPlatform.h +0 -0
  172. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3FunctionTypes.h +0 -0
  173. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3Functions.h +0 -0
  174. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3PlatformTypes.h +0 -0
  175. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
  176. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
  177. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
  178. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
  179. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
  180. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
  181. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
  182. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
  183. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
  184. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
  185. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
  186. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
  187. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
  188. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
  189. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
  190. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
  191. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
  192. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
  193. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
  194. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
  195. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
  196. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmucontainer.png +0 -0
  197. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmueditor.png +0 -0
  198. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmutool.png +0 -0
  199. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/help.png +0 -0
  200. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
  201. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon.png +0 -0
  202. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
  203. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/license.txt +0 -0
  204. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/mask.png +0 -0
  205. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-disabled.png +0 -0
  206. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-hover.png +0 -0
  207. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked.png +0 -0
  208. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-disabled.png +0 -0
  209. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-hover.png +0 -0
  210. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked.png +0 -0
  211. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/split.py +0 -0
  212. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/terminals.py +0 -0
  213. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/textfiles.py +0 -0
  214. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/version.py +0 -0
  215. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
  216. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
  217. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/overrides/main.html +0 -0
  218. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/CMakeLists.txt +0 -0
  219. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/build.bat +0 -0
  220. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.c +0 -0
  221. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.h +0 -0
  222. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.c +0 -0
  223. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.h +0 -0
  224. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/config.h.in +0 -0
  225. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.c +0 -0
  226. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.h +0 -0
  227. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.h +0 -0
  228. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/requirements.txt +0 -0
  229. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/setup.cfg +0 -0
  230. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/.coveragerc +0 -0
  231. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/__init__.py +0 -0
  232. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/archive.py +0 -0
  233. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assertions.py +0 -0
  234. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assistant_bridge.py +0 -0
  235. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/simulation.py +0 -0
  236. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/benchmarks/bench_manipulation.py +0 -0
  237. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/conftest.py +0 -0
  238. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_instances.py +0 -0
  239. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_reset_ports.py +0 -0
  240. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_step_size.py +0 -0
  241. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant.py +0 -0
  242. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant_wire.py +0 -0
  243. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_array.py +0 -0
  244. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_assistant_stdio_server.py +0 -0
  245. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli_errors.py +0 -0
  246. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container.py +0 -0
  247. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_enumeration.py +0 -0
  248. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_perf.py +0 -0
  249. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_reset.py +0 -0
  250. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_txt.py +0 -0
  251. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_xml.py +0 -0
  252. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_datalog.py +0 -0
  253. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_lsbus.py +0 -0
  254. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_me.py +0 -0
  255. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_operations_invariants.py +0 -0
  256. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_probe_fmu.py +0 -0
  257. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_remoting.py +0 -0
  258. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_split.py +0 -0
  259. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/pytest.ini +0 -0
  260. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_errors.py +0 -0
  261. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_instances.py +0 -0
  262. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_parsing.py +0 -0
  263. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_analysis.py +0 -0
  264. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_auth.py +0 -0
  265. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_budget.py +0 -0
  266. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_headless.py +0 -0
  267. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_runtime.py +0 -0
  268. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker.py +0 -0
  269. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_loading.py +0 -0
  270. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_semantic.py +0 -0
  271. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_compiler.py +0 -0
  272. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_container_internals.py +0 -0
  273. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_descriptor_cache.py +0 -0
  274. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_lifecycle.py +0 -0
  275. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_link_matching.py +0 -0
  276. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_description.py +0 -0
  277. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_exchange_sizes.py +0 -0
  278. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations.py +0 -0
  279. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_conformity.py +0 -0
  280. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_dependencies.py +0 -0
  281. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_errors.py +0 -0
  282. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_split_parsing.py +0 -0
  283. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_terminals.py +0 -0
  284. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_textfiles.py +0 -0
  285. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_assertions.py +0 -0
  286. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_roundtrip.py +0 -0
  287. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/bench_container.py +0 -0
  288. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/compare_traces.py +0 -0
  289. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/dist_inventory.py +0 -0
  290. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe10ms.fmu +0 -0
  291. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe20ms.fmu +0 -0
  292. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe50ms.fmu +0 -0
  293. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/README.md +0 -0
  294. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/make_probe.py +0 -0
  295. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/probe.c +0 -0
  296. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/README.md +0 -0
  297. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S1.json +0 -0
  298. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S2.json +0 -0
  299. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S3.json +0 -0
  300. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4a.json +0 -0
  301. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4b.json +0 -0
  302. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4c.json +0 -0
  303. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4d.json +0 -0
  304. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5j.json +0 -0
  305. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5r.json +0 -0
  306. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5s.json +0 -0
  307. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6m.json +0 -0
  308. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6s.json +0 -0
  309. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/run_container.py +0 -0
  310. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/build_scenarios.m +0 -0
  311. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_scenarios.m +0 -0
  312. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_simulink_api.m +0 -0
  313. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/run_scenarios.m +0 -0
  314. {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/screenshots.py +0 -0
@@ -3,7 +3,66 @@ This package was formerly known as `fmutool`.
3
3
 
4
4
  # Upstream
5
5
 
6
- Not released yet. Changes since 1.9.4.2, by theme: 🟢 **ADDED** new feature, 🔵 **CHANGED** change of behaviour or
6
+ Not released yet. Changes since 2.0, with the same legend as 2.0.
7
+
8
+ ## FMU Container
9
+
10
+ - 🟢 **ADDED** **architecture wires** in SSP files: a connection annotated
11
+ `fmu_manipulation_toolbox.architecture-wire` describes a dependency between two components (directed,
12
+ bidirectional or undirected, with a Markdown description) before the exchanged variables are known. It is not a
13
+ link: it takes no part in the container and is not written in the JSON description; the Container Builder shows it
14
+ as a hint. See [Architecture wires](docs/user-guide/fmucontainer/container.md#architecture-wires).
15
+ - 🔵 **CHANGED** SSP import: each component is embedded as `<component name>.fmu` (it was named after its FMU file,
16
+ `<file>-<n>.fmu` for the components sharing a source), and the FMUs are extracted keeping their path inside the
17
+ archive: two FMUs with the same file name in different directories no longer overwrite each other. A component
18
+ `source` outside the archive is refused. SSP 2.0 files are read; a component without `source` (SSP 2.0) is
19
+ ignored with a warning, together with its connections.
20
+
21
+ ## AI agents
22
+
23
+ - 🟢 **ADDED** **agent skills**: a Claude Code plugin (the repository is a marketplace:
24
+ `/plugin marketplace add grouperenault/fmutool`) with the skills `fmu-inspect`, `fmu-edit` and
25
+ `fmu-container`, which drive the MCP server, or `fmutool-agent` without it; `tools/build_skill_zips.py` builds
26
+ them for claude.ai. They need the toolbox 2.1.dev1 or later (`compatibility` field), and check it by the tools
27
+ available. See [Agent skills](docs/user-guide/agent-skills.md).
28
+ - 🟢 **ADDED** `fmutool-agent`: the tools of the MCP server as a JSON command line (same arguments, same
29
+ results), for agents that only run commands. It needs neither `fastmcp` nor Pydantic; the assembly is kept
30
+ between calls in the file given by `--state`. `fmutool-agent list-tools` prints the version of the toolbox.
31
+ - 🟢 **ADDED** MCP tool `describe_port`: everything declared about one port (every attribute, FMI 3 dimensions,
32
+ declared type and the attributes inherited from it, aliases, terminals).
33
+ - 🟢 **ADDED** MCP filters `type` and `variability` on `list_fmu_ports`, `inspect_fmu_file` and
34
+ `apply_operation`; on an FMI 3 FMU, an FMI 2 type selects its family (`Real`: `Float32`, `Float64`).
35
+ - 🔴 **BREAKING** MCP tool `rename_ports_from_csv` replaced by `rename_ports`, which takes a `mapping`
36
+ (`{"old": "new"}`) or the `csv`, and reports the names of the mapping absent from the FMU (`unknown`).
37
+ - 🔵 **CHANGED** shorter descriptions of some MCP tools and container options, to make room for the new tools
38
+ in the context of small models.
39
+
40
+ ## fmutool and the Python API
41
+
42
+ - 🟢 **ADDED** `-only-type` and `-only-variability` options of `fmutool`, and the `types` and `variabilities`
43
+ arguments of `FMU.apply_operation`: an operation restricted to some types (an FMI 2 type selects its FMI 3
44
+ family) or variabilities (the default of the standard when a port declares none), combined with the
45
+ causality filters.
46
+ - 🟢 **ADDED** `OperationRename`: renaming, or removal, from a mapping of names; `OperationRenameFromCSV` derives
47
+ from it.
48
+ - 🟢 **ADDED** `ModelVariable.causality` and `ModelVariable.variability`, with the defaults of the standard, and
49
+ `ModelVariable.has_type`.
50
+ - 🟢 **ADDED** `-debug` option of `fmutool` and `fmutool-gui` (at launch): the `DEBUG` lines are logged, in the log
51
+ area for `fmutool-gui`, e.g. the command lines of the compiler and of the linker of `-compile-sources`.
52
+
53
+ ## Graphical User Interfaces
54
+
55
+ - 🟢 **ADDED** `fmucontainer-gui <file>` opens an FMU container (`.fmu`) or imports an assembly file (`.json`,
56
+ `.csv`, `.ssp`) given on the command line.
57
+ - 🟢 **ADDED** Container Builder: the nodes imported from an SSP file are placed after the geometry of their
58
+ components, and the [architecture wires](docs/user-guide/fmucontainer/gui-usage.md#architecture-wires) of the file
59
+ are shown as dashed wires until their links are defined, with their direction and description in the wire details.
60
+ - 🟠 **FIXED** status bar of the GUIs: a long log record is elided (the whole line in the tooltip) instead
61
+ of widening the window.
62
+
63
+ # Version 2.0
64
+
65
+ Changes since 1.9.4.2, by theme: 🟢 **ADDED** new feature, 🔵 **CHANGED** change of behaviour or
7
66
  API, 🟠 **FIXED** bug fix; 🔴 **BREAKING** marks what may require changes in scripts, custom operations or checkers.
8
67
 
9
68
  ## Installation and platforms
@@ -177,6 +236,9 @@ API, 🟠 **FIXED** bug fix; 🔴 **BREAKING** marks what may require changes in
177
236
  - 🟠 **FIXED** the runtime reads the lines of `container.txt` of any length: a line longer than 4095 characters
178
237
  (the start values of a large array, a string start value of more than 4095 characters) was cut and shifted the
179
238
  reading of the rest of the file, so that the container failed to instantiate.
239
+ - 🟠 **FIXED** Windows: an embedded FMU, or an FMU run by the remoting server, whose DLL depends on other DLLs
240
+ shipped next to it in `binaries/win64` (or `win32`) failed to load. The dependencies of the DLL are now searched
241
+ first in its own directory.
180
242
  - 🔵 **CHANGED** the runtime checks the format version of `container.txt` and refuses, with an explicit error, a
181
243
  container whose `container.txt` does not come from the same version of the toolbox. See
182
244
  [Troubleshooting](docs/help/troubleshooting.md#fmu-container-fails-to-instantiate-format-version-of-containertxt).
@@ -302,9 +364,14 @@ API, 🟠 **FIXED** bug fix; 🔴 **BREAKING** marks what may require changes in
302
364
  search, **Save Logs…** and **Clear**. In `fmucontainer-gui`, the messages that were lost outside the progress
303
365
  dialog are now visible there, among them the `[AI] …` change journal and the token of the AI Assistant. See the
304
366
  [Container Builder GUI guide](docs/user-guide/fmucontainer/gui-usage.md#log).
305
- - 🔵 **CHANGED** `fmucontainer-gui`: **Verbose Mode** sets the level of the whole log (`DEBUG`) and copies it on the
306
- standard output; without it, nothing is written on the standard output (the tree view and the AI Assistant used to
307
- write their messages there in any case).
367
+ - 🔵 **CHANGED** `fmucontainer-gui`: **Verbose Mode** sets the level of the log of its window (`DEBUG`) and copies
368
+ its messages on the standard output; without it, nothing is written on the standard output (the tree view and the
369
+ AI Assistant used to write their messages there in any case).
370
+ - 🟠 **FIXED** `fmutoolbox`: the windows opened from the launcher shared one log. Each window now has its own: an
371
+ operation of an FMU Tool window, a build or a request of the AI Assistant of a Container Builder are only shown in
372
+ that window (log area, status bar, log window), **Clear** only forgets the messages of its window, and opening a
373
+ window no longer turns off the **Verbose Mode** of an open Container Builder. The few messages that do not come
374
+ from a window are shown in all of them. See the [Launcher guide](docs/user-guide/launcher.md).
308
375
  - 🟢 **ADDED** `fmucontainer-gui`: the `reset_ports` checkbox of a container (root included) adds a
309
376
  `<fmu>.reset` port per FMU, or sub-container, to the `configuration` node; a wire to it resets the FMU. Selecting
310
377
  the node lists its reset ports, to expose them as container inputs. See
@@ -2,13 +2,15 @@
2
2
  # With setuptools-scm, every file tracked by git goes into the sdist by default. Keep the Python package and the C
3
3
  # sources of the native binaries (container/, remoting/, and the FMI headers in
4
4
  # fmu_manipulation_toolbox/resources/fmi/); leave out the test data, the documentation, the CI
5
- # configuration and the prebuilt binaries.
5
+ # configuration, the Claude Code plugin and the prebuilt binaries.
6
6
  #
7
7
  # The wheel needs the prebuilt binaries: build it from the source tree, not from the sdist
8
8
  # (`python -m build --sdist --wheel`).
9
9
  prune tests/data
10
10
  prune docs
11
11
  prune .github
12
+ prune plugins
13
+ prune .claude-plugin
12
14
  recursive-exclude fmu_manipulation_toolbox/resources/win32 *
13
15
  recursive-exclude fmu_manipulation_toolbox/resources/win64 *
14
16
  recursive-exclude fmu_manipulation_toolbox/resources/linux32 *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fmu_manipulation_toolbox
3
- Version: 2.0b3
3
+ Version: 2.1.dev1
4
4
  Summary: FMU Manipulation Toolbox is a python package which helps to analyze, modify, validate, combine or split Functional Mock-up Units (FMUs) without recompilation, through a GUI, a CLI or a Python API.
5
5
  Author-email: Nicolas LAURENT <Nicolas.LAURENT@Renault.com>
6
6
  License-Expression: BSD-2-Clause
@@ -41,7 +41,7 @@ Requires-Dist: PySide6>=6.8.0; extra == "test"
41
41
  Requires-Dist: pytest>=9.0.3; extra == "test"
42
42
  Requires-Dist: pytest-qt>=4.4.0; extra == "test"
43
43
  Requires-Dist: pytest-cov>=7.0.0; extra == "test"
44
- Requires-Dist: coverage-badge>=1.1.2; extra == "test"
44
+ Requires-Dist: anybadge>=1.16.0; extra == "test"
45
45
  Requires-Dist: fmpy>=0.3.20; extra == "test"
46
46
  Requires-Dist: numpy; extra == "test"
47
47
  Provides-Extra: all
@@ -122,6 +122,13 @@ extra:
122
122
  pip install "fmu-manipulation-toolbox[mcp]"
123
123
  ```
124
124
 
125
+ With Claude Code, the `fmutool` plugin adds skills to inspect FMUs, edit their interface and build containers
126
+ ([Agent skills](docs/user-guide/agent-skills.md)); they need version 2.1.dev1 or later of the toolbox:
127
+
128
+ ```
129
+ /plugin install fmutool --marketplace grouperenault/fmutool
130
+ ```
131
+
125
132
 
126
133
  ### Supported platforms
127
134
 
@@ -72,6 +72,13 @@ extra:
72
72
  pip install "fmu-manipulation-toolbox[mcp]"
73
73
  ```
74
74
 
75
+ With Claude Code, the `fmutool` plugin adds skills to inspect FMUs, edit their interface and build containers
76
+ ([Agent skills](docs/user-guide/agent-skills.md)); they need version 2.1.dev1 or later of the toolbox:
77
+
78
+ ```
79
+ /plugin install fmutool --marketplace grouperenault/fmutool
80
+ ```
81
+
75
82
 
76
83
  ### Supported platforms
77
84
 
@@ -5,6 +5,8 @@
5
5
  #ifdef _WIN32
6
6
  # include <windows.h>
7
7
  # include <imagehlp.h>
8
+ # include <stdio.h>
9
+ # include <string.h>
8
10
  #else
9
11
  # include <dlfcn.h>
10
12
  # include <unistd.h>
@@ -54,7 +56,8 @@ static void library_load_error(const logger_t *logger, const char* library_filen
54
56
  library_t library_load(const logger_t *logger, const char* library_filename) {
55
57
  library_t handle;
56
58
  #ifdef _WIN32
57
- handle = LoadLibraryA(library_filename);
59
+ /* Dependencies are searched first in the directory of the DLL */
60
+ handle = LoadLibraryExA(library_filename, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
58
61
  #else
59
62
  handle = dlopen(library_filename, RTLD_LAZY); /* RTLD_LOCAL can lead to failure */
60
63
  #endif
@@ -118,14 +121,28 @@ static LPVOID GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader, PBYTE imageB
118
121
  }
119
122
 
120
123
 
124
+ static const char *libray_last_separator(const char *filename) {
125
+ const char *backslash = strrchr(filename, '\\');
126
+ const char *slash = strrchr(filename, '/');
127
+
128
+ if (!backslash)
129
+ return slash;
130
+ if (!slash)
131
+ return backslash;
132
+ return (backslash > slash) ? backslash : slash;
133
+ }
134
+
135
+
121
136
  static libray_status_t* libray_try_load(const char* filename) {
122
137
  libray_status_t* status = malloc(sizeof(*status));
138
+ /* A bare DLL name is searched with the standard search order: the flag requires a path */
139
+ const DWORD flags = libray_last_separator(filename) ? LOAD_WITH_ALTERED_SEARCH_PATH : 0;
123
140
 
124
141
  HINSTANCE handle = LoadLibraryExA(filename, NULL, DONT_RESOLVE_DLL_REFERENCES);
125
142
  if (handle) {
126
143
  FreeLibrary(handle);
127
144
 
128
- handle = LoadLibraryA(filename);
145
+ handle = LoadLibraryExA(filename, NULL, flags);
129
146
  if (handle) {
130
147
  FreeLibrary(handle);
131
148
  *status = LIBRARY_DLL_OK;
@@ -156,7 +173,29 @@ static void libray_log_status(const logger_t *logger, const char* filename, libr
156
173
  }
157
174
 
158
175
 
176
+ /*
177
+ * The dependencies of a DLL are searched first in its directory, as library_load() does:
178
+ * return the path of the dependency in this directory if it exists, its bare name otherwise.
179
+ */
180
+ static const char *libray_dependency_path(char *path, size_t size, const char *filename, const char *dll_filename) {
181
+ const char *separator = libray_last_separator(filename);
182
+
183
+ if (separator) {
184
+ const int dir_len = (int)(separator - filename);
185
+ const int len = snprintf(path, size, "%.*s\\%s", dir_len, filename, dll_filename);
186
+ if (len > 0 && (size_t)len < size) {
187
+ const DWORD attributes = GetFileAttributesA(path);
188
+ if (attributes != INVALID_FILE_ATTRIBUTES && !(attributes & FILE_ATTRIBUTE_DIRECTORY))
189
+ return path;
190
+ }
191
+ }
192
+
193
+ return dll_filename;
194
+ }
195
+
196
+
159
197
  static void libray_analyse_deeply(const logger_t *logger, hash_t* dll_db, const char* filename) {
198
+ char dependency_path[MAX_PATH];
160
199
  PLOADED_IMAGE image = ImageLoad(filename, NULL);
161
200
  if (!image) {
162
201
  LOGGER_ERROR("Cannot ImageLoad(%s)", filename);
@@ -172,7 +211,8 @@ static void libray_analyse_deeply(const logger_t *logger, hash_t* dll_db, const
172
211
  if ((importDesc->TimeDateStamp == 0) && (importDesc->Name == 0))
173
212
  break;
174
213
  const char* dll_filename = GetPtrFromRVA(importDesc->Name, image->FileHeader, image->MappedAddress);
175
- libray_analyse(logger, dll_db, dll_filename);
214
+ libray_analyse(logger, dll_db,
215
+ libray_dependency_path(dependency_path, sizeof(dependency_path), filename, dll_filename));
176
216
  importDesc++;
177
217
  }
178
218
  }
@@ -54,8 +54,11 @@ extern void logger_embedded_fmu3(void *fmu,
54
54
  /*
55
55
  * Logging macros: they use the variable `logger` (const logger_t *) of the calling scope, e.g.
56
56
  * const logger_t *logger = &container->logger;
57
+ * LOGGER_DEBUG tests the debug flag inline: when it is off, neither logger_message() is called nor its arguments
58
+ * evaluated, which matters in the per-value paths (getters, setters, cache of the importer values).
57
59
  */
58
- #define LOGGER_DEBUG(...) logger_message(logger, LOGGER_LEVEL_DEBUG, __VA_ARGS__)
60
+ #define LOGGER_DEBUG(...) do { if (logger && logger->debug) \
61
+ logger_message(logger, LOGGER_LEVEL_DEBUG, __VA_ARGS__); } while (0)
59
62
  #define LOGGER_WARNING(...) logger_message(logger, LOGGER_LEVEL_WARNING, __VA_ARGS__)
60
63
  #define LOGGER_ERROR(...) logger_message(logger, LOGGER_LEVEL_ERROR, __VA_ARGS__)
61
64
 
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
18
18
  commit_id: str | None
19
19
  __commit_id__: str | None
20
20
 
21
- __version__ = version = '2.0b3'
22
- __version_tuple__ = version_tuple = (2, 0, 'b3')
21
+ __version__ = version = '2.1.dev1'
22
+ __version_tuple__ = version_tuple = (2, 1, 'dev1')
23
23
 
24
- __commit_id__ = commit_id = 'g4ac7fcf20'
24
+ __commit_id__ = commit_id = 'g3d2800ab9'
@@ -4,7 +4,7 @@ import logging
4
4
  import os
5
5
  from collections.abc import Iterable
6
6
  from typing import Any
7
- from pathlib import Path
7
+ from pathlib import Path, PurePosixPath
8
8
  import uuid
9
9
  import xml.etree.ElementTree as ET
10
10
  import zipfile
@@ -180,6 +180,33 @@ class Connection:
180
180
  return f"{self.from_port} -> {self.to_port}"
181
181
 
182
182
 
183
+ class ArchitectureWire:
184
+ """Dependency between two embedded FMUs, declared before the exchanged variables are known.
185
+
186
+ An architecture wire comes from an SSP connection carrying the `fmu_manipulation_toolbox.architecture-wire`
187
+ annotation. It is a hint for the user who defines the links: it is not a link, it takes no part in the
188
+ container build and it is not written in the JSON description.
189
+
190
+ Attributes:
191
+ start_fmu (str): Name of the embedded FMU at the start of the wire.
192
+ end_fmu (str): Name of the embedded FMU at the end of the wire.
193
+ orientation (str): `"directed"` (from start to end), `"bidirectional"` or `"undirected"`.
194
+ description (str | None): Free text (Markdown) attached to the wire.
195
+ """
196
+
197
+ ORIENTATIONS = ("directed", "bidirectional", "undirected")
198
+
199
+ def __init__(self, start_fmu: str, end_fmu: str, orientation: str, description: str | None = None):
200
+ self.start_fmu = start_fmu
201
+ self.end_fmu = end_fmu
202
+ self.orientation = orientation
203
+ self.description = description
204
+
205
+ def __str__(self):
206
+ arrow = {"directed": "->", "bidirectional": "<->"}.get(self.orientation, "-")
207
+ return f"{self.start_fmu} {arrow} {self.end_fmu}"
208
+
209
+
183
210
  class AssemblyNode:
184
211
  """Represents a node in the assembly tree, defining a container and its topology.
185
212
 
@@ -214,6 +241,11 @@ class AssemblyNode:
214
241
  start_values (dict[Port, str]): Mapping from port to its start value.
215
242
  drop_ports (list[Port]): List of output ports to explicitly ignore.
216
243
  links (list[Connection]): List of connections between embedded FMUs.
244
+ architecture_wires (list[ArchitectureWire]): Dependencies between embedded FMUs read from an SSP file,
245
+ kept as hints for the GUI; they are neither links nor part of the JSON description.
246
+ fmu_geometry (dict[str, tuple[float, float, float, float]]): Position of embedded FMUs read from an SSP
247
+ file: `(x1, y1, x2, y2)` of the `ElementGeometry` of their component (SSP coordinates, y upwards). A hint
248
+ for the GUI, not part of the JSON description.
217
249
  """
218
250
 
219
251
  def __init__(self, name: str, step_size: float = None, mt=False, profiling=False, sequential=False,
@@ -248,6 +280,8 @@ class AssemblyNode:
248
280
  self.start_values: dict[Port, str] = {}
249
281
  self.drop_ports: list[Port] = []
250
282
  self.links: list[Connection] = []
283
+ self.architecture_wires: list[ArchitectureWire] = []
284
+ self.fmu_geometry: dict[str, tuple[float, float, float, float]] = {}
251
285
 
252
286
  def add_sub_node(self, sub_node):
253
287
  """Add a child `AssemblyNode` to create a hierarchical (nested) container.
@@ -340,6 +374,17 @@ class AssemblyNode:
340
374
  self.links.append(Connection(Port(from_fmu_filename, from_port_name),
341
375
  Port(to_fmu_filename, to_port_name)))
342
376
 
377
+ def add_architecture_wire(self, start_fmu: str, end_fmu: str, orientation: str, description: str | None = None):
378
+ """Declare a dependency between two embedded FMUs, without naming variables (see `ArchitectureWire`).
379
+
380
+ Args:
381
+ start_fmu (str): Name of the embedded FMU at the start of the wire.
382
+ end_fmu (str): Name of the embedded FMU at the end of the wire.
383
+ orientation (str): `"directed"` (from start to end), `"bidirectional"` or `"undirected"`.
384
+ description (str | None): Free text (Markdown) attached to the wire.
385
+ """
386
+ self.architecture_wires.append(ArchitectureWire(start_fmu, end_fmu, orientation, description))
387
+
343
388
  def add_start_value(self, fmu_filename: str, port_name: str, value: str):
344
389
  """Set a start value for a port of an embedded FMU.
345
390
 
@@ -936,8 +981,8 @@ class Assembly:
936
981
 
937
982
  for file in zin.filelist:
938
983
  if file.filename.endswith(".fmu"):
939
- # FMU are all stored in extract_folder without hierarchy
940
- file.filename = str(Path(file.filename).name)
984
+ # FMUs keep their path relative to the archive root: two FMUs with the same file name in
985
+ # different directories do not overwrite each other.
941
986
  zin.extract(file, path=extract_folder)
942
987
  logger.debug(f"Extracted: {file.filename} (into {extract_folder})")
943
988
 
@@ -1008,7 +1053,7 @@ class Assembly:
1008
1053
 
1009
1054
 
1010
1055
  class SSDParser:
1011
- """Parser for SSD (System Structure Description) files of SSP 1.0 archives.
1056
+ """Parser for SSD (System Structure Description) files of SSP archives (SSP 1.0 and 2.0 share one namespace).
1012
1057
 
1013
1058
  Parses the XML structure of an `.ssd` file and builds the corresponding
1014
1059
  [AssemblyNode][fmu_manipulation_toolbox.assembly.AssemblyNode] tree, including
@@ -1017,16 +1062,25 @@ class SSDParser:
1017
1062
  Elements are recognized by their namespace (`SSD_NAMESPACE`), whatever the
1018
1063
  prefix used in the file (`ssd:`, another one, or a default namespace).
1019
1064
 
1065
+ Each component is embedded as `<component name>.fmu`, in the directory of its `source` file. A component
1066
+ without `source` (SSP 2.0 component without implementation) is ignored, with the connections attached to it.
1067
+
1068
+ A connection carrying an annotation of type `ARCHITECTURE_WIRE_TYPE` is an architecture wire (see
1069
+ `ArchitectureWire`), not a link.
1070
+
1020
1071
  Attributes:
1021
1072
  node_stack (list[AssemblyNode]): Stack of nodes used during XML parsing
1022
1073
  for tracking hierarchy.
1023
1074
  root (AssemblyNode | None): Root node after parsing is complete.
1024
1075
  fmu_filenames (dict[str, str]): Mapping from SSD component names to
1025
- the names of the embedded FMUs: the FMU filename, or an instance
1026
- name when several components share one source (see `instance_name`).
1076
+ the names of the embedded FMUs.
1077
+ ignored_components (set[str]): Names of the components ignored because they have no `source`.
1027
1078
  """
1028
1079
 
1029
1080
  SSD_NAMESPACE = "http://ssp-standard.org/SSP1/SystemStructureDescription"
1081
+ SSC_NAMESPACE = "http://ssp-standard.org/SSP1/SystemStructureCommon"
1082
+ ARCHITECTURE_WIRE_TYPE = "fmu_manipulation_toolbox.architecture-wire"
1083
+ ARCHITECTURE_WIRE_NAMESPACE = "urn:fmu_manipulation_toolbox:architecture-wire:1"
1030
1084
 
1031
1085
  def __init__(self, zin: zipfile.ZipFile, extract_folder_name: str, **kwargs):
1032
1086
  self.zin = zin
@@ -1034,9 +1088,17 @@ class SSDParser:
1034
1088
 
1035
1089
  self.node_stack: list[AssemblyNode] = []
1036
1090
  self.root = None
1037
- self.fmu_filenames: dict[str, str] = {} # Component name => FMU filename
1091
+ self.fmu_filenames: dict[str, str] = {} # Component name => FMU name
1092
+ self.ignored_components: set[str] = set()
1038
1093
  self.node_attrs = kwargs
1039
1094
 
1095
+ # Name of the embedded FMU of the component being read, for its ElementGeometry.
1096
+ self._component_fmu: str | None = None
1097
+ # Connection being read: its attributes, and its orientation once an architecture wire annotation is found.
1098
+ self._connection_attrs: dict[str, str] | None = None
1099
+ self._in_architecture_annotation = False
1100
+ self._wire_orientation: str | None = None
1101
+
1040
1102
  def parse(self, ssd_filename: str) -> AssemblyNode:
1041
1103
  """Parse an SSD file and return the root assembly node.
1042
1104
 
@@ -1062,6 +1124,8 @@ class SSDParser:
1062
1124
  f"root element is <{element.tag}>, expected "
1063
1125
  f"<SystemStructureDescription> in namespace '{self.SSD_NAMESPACE}'")
1064
1126
  root_checked = True
1127
+ if self._connection_attrs is not None:
1128
+ self._connection_child(event, element)
1065
1129
  if not element.tag.startswith(prefix):
1066
1130
  continue # other SSP namespaces (ssc:, ssv:...) and vendor annotations
1067
1131
  tag = element.tag[len(prefix):]
@@ -1082,20 +1146,10 @@ class SSDParser:
1082
1146
  def start_element(self, tag_name, attrs):
1083
1147
  """Handle the start of an SSD element (`tag_name` without namespace, e.g. `"Connection"`)."""
1084
1148
  if tag_name == 'Connection':
1085
- if 'startElement' in attrs:
1086
- if 'endElement' in attrs:
1087
- fmu_start = self.fmu_filenames[attrs['startElement']]
1088
- fmu_end = self.fmu_filenames[attrs['endElement']]
1089
- self.node_stack[-1].add_link(fmu_start, attrs['startConnector'],
1090
- fmu_end, attrs['endConnector'])
1091
- else:
1092
- fmu_start = self.fmu_filenames[attrs['startElement']]
1093
- self.node_stack[-1].add_output(fmu_start, attrs['startConnector'],
1094
- attrs['endConnector'])
1095
- else:
1096
- fmu_end = self.fmu_filenames[attrs['endElement']]
1097
- self.node_stack[-1].add_input(attrs['startConnector'],
1098
- fmu_end, attrs['endConnector'])
1149
+ # Decided on the end tag: an annotation (child element) may make it an architecture wire.
1150
+ self._connection_attrs = dict(attrs)
1151
+ self._in_architecture_annotation = False
1152
+ self._wire_orientation = None
1099
1153
 
1100
1154
  elif tag_name == 'System':
1101
1155
  logger.info(f"SSP System: {attrs['name']}")
@@ -1110,14 +1164,95 @@ class SSDParser:
1110
1164
  self.node_stack.append(node)
1111
1165
 
1112
1166
  elif tag_name == 'Component':
1113
- filename = f"{self.extract_folder_name}/{str(Path(attrs['source']).name)}"
1167
+ if 'source' not in attrs:
1168
+ logger.warning(f"Component '{attrs['name']}' has no source FMU. It is ignored, "
1169
+ f"with its connections.")
1170
+ self.ignored_components.add(attrs['name'])
1171
+ return
1172
+ source = self._source_path(attrs['source'])
1173
+ filename = f"{self.extract_folder_name}/{source}"
1114
1174
  node = self.node_stack[-1]
1115
- fmu_name = instance_name(filename, node.fmu_names_list) # components sharing a source: instances
1175
+ name = f"{self.extract_folder_name}/{source.parent / attrs['name']}.fmu"
1176
+ fmu_name = instance_name(name, node.fmu_names_list)
1116
1177
  self.fmu_filenames[attrs['name']] = fmu_name
1117
1178
  node.add_fmu(fmu_name, filename)
1179
+ self._component_fmu = fmu_name
1118
1180
  logger.debug(f"Component {attrs['name']} => {fmu_name}")
1119
1181
 
1182
+ elif tag_name == 'ElementGeometry' and self._component_fmu is not None:
1183
+ try:
1184
+ self.node_stack[-1].fmu_geometry[self._component_fmu] = \
1185
+ tuple(float(attrs[corner]) for corner in ('x1', 'y1', 'x2', 'y2'))
1186
+ except ValueError:
1187
+ logger.debug(f"Geometry of '{self._component_fmu}' ignored: invalid coordinates.")
1188
+
1120
1189
  def end_element(self, tag_name):
1121
1190
  """Handle the end of an SSD element (`tag_name` without namespace)."""
1122
1191
  if tag_name == 'System':
1123
1192
  self.node_stack.pop()
1193
+ elif tag_name == 'Component':
1194
+ self._component_fmu = None
1195
+ elif tag_name == 'Connection':
1196
+ attrs = self._connection_attrs
1197
+ self._connection_attrs = None
1198
+ if self._wire_orientation is None:
1199
+ self._add_connection(attrs)
1200
+ else:
1201
+ self._add_architecture_wire(attrs, self._wire_orientation)
1202
+
1203
+ def _connection_child(self, event: str, element: ET.Element):
1204
+ """Look for the architecture wire annotation among the descendants of the connection being read."""
1205
+ if element.tag == f"{{{self.SSC_NAMESPACE}}}Annotation":
1206
+ self._in_architecture_annotation = (event == "start" and
1207
+ element.get("type") == self.ARCHITECTURE_WIRE_TYPE)
1208
+ elif (self._in_architecture_annotation and event == "start" and
1209
+ element.tag == f"{{{self.ARCHITECTURE_WIRE_NAMESPACE}}}Wire"):
1210
+ orientation = element.get("orientation", "undirected")
1211
+ if orientation not in ArchitectureWire.ORIENTATIONS:
1212
+ logger.warning(f"Architecture wire with unknown orientation '{orientation}'. "
1213
+ f"It is read as 'undirected'.")
1214
+ orientation = "undirected"
1215
+ self._wire_orientation = orientation
1216
+
1217
+ def _add_connection(self, attrs: dict[str, str]):
1218
+ """Turn a connection into a link, an exposed input or an exposed output."""
1219
+ if attrs.get('startElement') in self.ignored_components or attrs.get('endElement') in self.ignored_components:
1220
+ logger.debug(f"Connection {attrs.get('startElement')}/{attrs['startConnector']} -> "
1221
+ f"{attrs.get('endElement')}/{attrs['endConnector']} ignored: it involves an ignored "
1222
+ f"component.")
1223
+ return
1224
+ if 'startElement' in attrs:
1225
+ if 'endElement' in attrs:
1226
+ fmu_start = self.fmu_filenames[attrs['startElement']]
1227
+ fmu_end = self.fmu_filenames[attrs['endElement']]
1228
+ self.node_stack[-1].add_link(fmu_start, attrs['startConnector'],
1229
+ fmu_end, attrs['endConnector'])
1230
+ else:
1231
+ fmu_start = self.fmu_filenames[attrs['startElement']]
1232
+ self.node_stack[-1].add_output(fmu_start, attrs['startConnector'],
1233
+ attrs['endConnector'])
1234
+ else:
1235
+ fmu_end = self.fmu_filenames[attrs['endElement']]
1236
+ self.node_stack[-1].add_input(attrs['startConnector'],
1237
+ fmu_end, attrs['endConnector'])
1238
+
1239
+ def _add_architecture_wire(self, attrs: dict[str, str], orientation: str):
1240
+ """Record an architecture wire between two components of the current system."""
1241
+ start, end = attrs.get('startElement'), attrs.get('endElement')
1242
+ if start is None or end is None:
1243
+ logger.warning(f"Architecture wire on connector '{attrs['startConnector']}' -> "
1244
+ f"'{attrs['endConnector']}' is ignored: it must join two components.")
1245
+ return
1246
+ if start in self.ignored_components or end in self.ignored_components:
1247
+ logger.debug(f"Architecture wire {start} -> {end} ignored: it involves an ignored component.")
1248
+ return
1249
+ self.node_stack[-1].add_architecture_wire(self.fmu_filenames[start], self.fmu_filenames[end],
1250
+ orientation, attrs.get('description'))
1251
+
1252
+ @staticmethod
1253
+ def _source_path(source: str) -> PurePosixPath:
1254
+ """Path of a component source inside the archive, refused if it leaves the archive."""
1255
+ path = PurePosixPath(source)
1256
+ if path.is_absolute() or ".." in path.parts:
1257
+ raise AssemblyError(f"Component source '{source}' must be a relative path inside the SSP archive.")
1258
+ return path