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.
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CHANGELOG.md +71 -4
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/MANIFEST.in +3 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/PKG-INFO +9 -2
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/README.md +7 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/library.c +43 -3
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.h +4 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/_version.py +3 -3
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assembly.py +158 -23
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/fmutools.py +211 -26
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/headless.py +46 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/knowledge.py +7 -3
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/models.py +9 -46
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/server.py +87 -142
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/assistant/tools.py +319 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/checker.py +2 -11
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool.py +18 -3
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/cli/fmutool_agent.py +285 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/utils.py +8 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__main__.py +49 -21
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/assembly_io.py +52 -4
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/wire_detail.py +45 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/constants.py +4 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/wire.py +40 -4
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/mcp_bridge.py +38 -13
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__main__.py +10 -4
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__main__.py +44 -14
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/helper.py +5 -352
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/gui/log.py +617 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/help.py +16 -3
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/model_description.py +58 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/operations.py +85 -22
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/PKG-INFO +9 -2
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +10 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/entry_points.txt +1 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/requires.txt +1 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/scm_file_list.json +23 -0
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox.egg-info/scm_version.json +8 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/mkdocs.yml +2 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/pyproject.toml +2 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.c +2 -1
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/mcp_budget.py +7 -2
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_assistant_qt_bridge.py +53 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_architecture_wires.py +165 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_open_file.py +76 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_fmucontainer_ssp_geometry.py +69 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_gui.py +88 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/gui/test_gui_logging.py +470 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli.py +11 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_compile_sources.py +19 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/integration/test_ssp.py +202 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_agent_skills.py +242 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_fmutools.py +175 -5
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_contract.py +6 -4
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_tools.py +76 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_fmutool_agent.py +286 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_operations_scope.py +209 -0
- fmu_manipulation_toolbox-2.1.dev1/tools/build_skill_zips.py +56 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/make_carousel.py +40 -2
- fmu_manipulation_toolbox-2.0b3/fmu_manipulation_toolbox.egg-info/scm_version.json +0 -8
- fmu_manipulation_toolbox-2.0b3/tests/gui/test_gui_logging.py +0 -240
- fmu_manipulation_toolbox-2.0b3/tests/integration/test_ssp.py +0 -87
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.git_archival.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.gitattributes +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/.gitignore +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CLAUDE.md +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/CONTRIBUTING.md +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/fmutool.cmake +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/gen_version.cmake +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/pgo.cmake +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/cmake/version.h.in +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/CMakeLists.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/build.bat +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/config.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/config.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/container.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/container.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi2.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi3.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/library.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/test_fmi.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/empty/container.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/container.txt.in +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/datalog.txt.in +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/stub_fmu.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_config.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_configure.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_datalog.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_locale.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_logger.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_main.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_malformed.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_thread.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_threads_lifecycle.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/analysis.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/auth.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/bridge.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/paths.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/replay.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/datalog2pcap.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmucontainer.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmusplit.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool_mcp.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/compiler.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/arrays.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/builder.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/embedded.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/errors.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/layout.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/rules.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/txt.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/types.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/configuration_detail.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/container_detail.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/fmu_detail.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant_demo.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_matching.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/stack.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node_info_dialog.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/scene.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/view.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/widget.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/model.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/panel.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/sync.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/widget.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/style.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/ls.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/remoting.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/container.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2FunctionTypes.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2Functions.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2TypesPlatform.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3FunctionTypes.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3Functions.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3PlatformTypes.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmucontainer.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmueditor.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmutool.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/help.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/license.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/mask.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked.png +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/split.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/terminals.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/textfiles.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/version.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/overrides/main.html +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/CMakeLists.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/build.bat +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/config.h.in +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.h +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/requirements.txt +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/setup.cfg +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/.coveragerc +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/archive.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assertions.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assistant_bridge.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/simulation.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/benchmarks/bench_manipulation.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/conftest.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_instances.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_reset_ports.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_step_size.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant_wire.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_array.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_assistant_stdio_server.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli_errors.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_enumeration.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_perf.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_reset.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_txt.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_xml.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_datalog.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_lsbus.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_me.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_operations_invariants.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_probe_fmu.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_remoting.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_split.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/pytest.ini +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_errors.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_instances.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_parsing.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_analysis.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_auth.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_budget.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_headless.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_runtime.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_loading.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_semantic.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_compiler.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_container_internals.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_descriptor_cache.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_lifecycle.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_link_matching.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_description.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_exchange_sizes.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_conformity.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_dependencies.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_errors.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_split_parsing.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_terminals.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_textfiles.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_assertions.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_roundtrip.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/bench_container.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/compare_traces.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/dist_inventory.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe10ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe20ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe50ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/README.md +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/make_probe.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/probe.c +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/README.md +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S1.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S2.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S3.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4a.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4b.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4c.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4d.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5j.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5r.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5s.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6m.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6s.json +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/run_container.py +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/build_scenarios.m +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_scenarios.m +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_simulink_api.m +0 -0
- {fmu_manipulation_toolbox-2.0b3 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/run_scenarios.m +0 -0
- {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
|
|
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
|
|
306
|
-
standard output; without it, nothing is written on the standard output (the tree view and the
|
|
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.
|
|
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:
|
|
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
|
-
|
|
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 =
|
|
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,
|
|
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(...)
|
|
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.
|
|
22
|
-
__version_tuple__ = version_tuple = (2,
|
|
21
|
+
__version__ = version = '2.1.dev1'
|
|
22
|
+
__version_tuple__ = version_tuple = (2, 1, 'dev1')
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
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
|
-
#
|
|
940
|
-
|
|
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
|
|
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
|
|
1026
|
-
|
|
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
|
|
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
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|