fmu-manipulation-toolbox 2.1.dev0__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.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/CHANGELOG.md +27 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/MANIFEST.in +3 -1
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/PKG-INFO +8 -1
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/README.md +7 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/_version.py +3 -3
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/fmutools.py +211 -26
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/headless.py +46 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/knowledge.py +7 -3
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/models.py +9 -46
- {fmu_manipulation_toolbox-2.1.dev0 → 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.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/checker.py +2 -11
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool.py +11 -1
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox/cli/fmutool_agent.py +285 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/help.py +10 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/model_description.py +58 -1
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/operations.py +85 -22
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/PKG-INFO +8 -1
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/SOURCES.txt +6 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/entry_points.txt +1 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/scm_file_list.json +16 -0
- fmu_manipulation_toolbox-2.1.dev1/fmu_manipulation_toolbox.egg-info/scm_version.json +8 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/mkdocs.yml +2 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/pyproject.toml +1 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/mcp_budget.py +7 -2
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli.py +11 -0
- fmu_manipulation_toolbox-2.1.dev1/tests/unit/test_agent_skills.py +242 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_fmutools.py +175 -5
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_contract.py +6 -4
- {fmu_manipulation_toolbox-2.1.dev0 → 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.1.dev0/fmu_manipulation_toolbox.egg-info/scm_version.json +0 -8
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/.git_archival.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/.gitattributes +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/.gitignore +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/CLAUDE.md +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/CONTRIBUTING.md +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/LICENSE.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/cmake/fmutool.cmake +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/cmake/gen_version.cmake +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/cmake/pgo.cmake +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/cmake/version.h.in +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/CMakeLists.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/build.bat +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/config.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/config.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/container.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/container.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/convert.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/datalog.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi2.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/fmi3.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/fmu.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/hash.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/library.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/library.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/logger.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/profile.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/solver.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/test_fmi.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/empty/container.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/container.txt.in +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/data/one_fmu/datalog.txt.in +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/stub_fmu.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_config.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_configure.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_datalog.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_locale.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_logger.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_main.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_malformed.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_thread.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/tests/test_threads_lifecycle.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/container/thread.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assembly.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/analysis.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/auth.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/bridge.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/paths.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/assistant/replay.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/datalog2pcap.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmucontainer.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmusplit.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/fmutool_mcp.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/cli/utils.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/compiler.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/arrays.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/builder.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/embedded.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/errors.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/layout.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/rules.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/txt.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/container/types.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/assembly_io.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/configuration_detail.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/container_detail.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/fmu_detail.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_assistant_demo.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/link_matching.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/stack.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/details/wire_detail.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/constants.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/node_info_dialog.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/scene.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/view.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/widget.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/graph/wire.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/mcp_bridge.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/model.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/panel.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/sync.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmucontainer/tree/widget.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmueditor/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/fmutool/__main__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/helper.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/log.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/gui/style.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/ls.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/remoting.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-checked.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/checkbox-unchecked.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/container.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/drop_fmu.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2FunctionTypes.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2Functions.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi2TypesPlatform.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3FunctionTypes.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3Functions.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi/fmi3PlatformTypes.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2ScalarVariable.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Type.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2Unit.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-2.0/fmi2VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Annotation.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3AttributeGroups.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3BuildDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3InterfaceType.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3LayeredStandardManifest.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3ModelDescription.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Terminal.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3TerminalsAndIcons.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Type.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Unit.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3Variable.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmi-3.0/fmi3VariableDependency.xsd +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmu_manipulation_toolbox.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmucontainer.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmueditor.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/fmutool.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/help.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon-round.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/icon_fmu.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/license.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/mask.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-checked.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-disabled.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked-hover.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/resources/radio-unchecked.png +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/split.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/terminals.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/textfiles.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox/version.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/dependency_links.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/requires.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/fmu_manipulation_toolbox.egg-info/top_level.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/overrides/main.html +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/CMakeLists.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/build.bat +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/client.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/communication.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/config.h.in +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/process.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/remoting/server.h +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/requirements.txt +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/setup.cfg +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/.coveragerc +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/__init__.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/archive.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assertions.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/assistant_bridge.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/_helpers/simulation.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/benchmarks/bench_manipulation.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/conftest.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_assistant_qt_bridge.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_architecture_wires.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_instances.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_open_file.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_reset_ports.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_ssp_geometry.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_fmucontainer_step_size.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_gui.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_gui_logging.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/gui/test_link_assistant_wire.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_array.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_assistant_stdio_server.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_cli_errors.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_compile_sources.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_enumeration.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_perf.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_reset.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_txt.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_container_xml.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_datalog.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_lsbus.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_me.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_operations_invariants.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_probe_fmu.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_remoting.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_split.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/integration/test_ssp.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/pytest.ini +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_errors.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_instances.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assembly_parsing.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_analysis.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_auth.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_budget.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_headless.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_assistant_server_runtime.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_loading.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_checker_semantic.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_compiler.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_container_internals.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_descriptor_cache.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_fmu_lifecycle.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_link_matching.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_description.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_model_exchange_sizes.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_conformity.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_dependencies.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_operations_errors.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_split_parsing.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_terminals.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_textfiles.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_assertions.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tests/unit/test_xml_roundtrip.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/bench_container.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/compare_traces.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/dist_inventory.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/make_carousel.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe10ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe20ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/Probe50ms.fmu +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/README.md +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/make_probe.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/probe.c +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/README.md +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S1.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S2.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S3.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4a.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4b.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4c.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S4d.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5j.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5r.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S5s.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6m.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/S6s.json +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/run_container.py +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/build_scenarios.m +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_scenarios.m +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/probe_simulink_api.m +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/probe_fmu/scenarios/simulink/run_scenarios.m +0 -0
- {fmu_manipulation_toolbox-2.1.dev0 → fmu_manipulation_toolbox-2.1.dev1}/tools/screenshots.py +0 -0
|
@@ -18,8 +18,35 @@ Not released yet. Changes since 2.0, with the same legend as 2.0.
|
|
|
18
18
|
`source` outside the archive is refused. SSP 2.0 files are read; a component without `source` (SSP 2.0) is
|
|
19
19
|
ignored with a warning, together with its connections.
|
|
20
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
|
+
|
|
21
40
|
## fmutool and the Python API
|
|
22
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`.
|
|
23
50
|
- 🟢 **ADDED** `-debug` option of `fmutool` and `fmutool-gui` (at launch): the `DEBUG` lines are logged, in the log
|
|
24
51
|
area for `fmutool-gui`, e.g. the command lines of the compiler and of the linker of `-compile-sources`.
|
|
25
52
|
|
|
@@ -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.1.
|
|
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
|
|
@@ -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
|
|
|
@@ -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.1.
|
|
22
|
-
__version_tuple__ = version_tuple = (2, 1, '
|
|
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'
|
|
@@ -16,6 +16,7 @@ Two design points are worth stating, because they shape the whole module:
|
|
|
16
16
|
the read-only tools here never call it.
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
|
+
import difflib
|
|
19
20
|
import logging
|
|
20
21
|
import re
|
|
21
22
|
from contextlib import contextmanager
|
|
@@ -23,9 +24,11 @@ from pathlib import Path
|
|
|
23
24
|
from typing import Any
|
|
24
25
|
|
|
25
26
|
from ..checker import get_checkers
|
|
27
|
+
from ..model_description import ModelDescription, ModelVariable, default_variability, matches_type
|
|
28
|
+
from ..terminals import Terminals
|
|
26
29
|
from ..operations import (
|
|
27
30
|
FMU, OperationKeepOnlyRegexp, OperationMergeTopLevel, OperationRemoveRegexp,
|
|
28
|
-
OperationRemoveSources, OperationRenameFromCSV, OperationSaveNamesToCSV,
|
|
31
|
+
OperationRemoveSources, OperationRename, OperationRenameFromCSV, OperationSaveNamesToCSV,
|
|
29
32
|
OperationStripTopLevel, OperationSummary, OperationTrimUntil,
|
|
30
33
|
)
|
|
31
34
|
|
|
@@ -47,6 +50,51 @@ OPERATIONS = {
|
|
|
47
50
|
#: Causalities an operation can be restricted to.
|
|
48
51
|
CAUSALITIES = ("input", "output", "parameter", "local")
|
|
49
52
|
|
|
53
|
+
#: Types a port filter accepts: the FMI 2.0 names (which also select their FMI 3.0 family) and the FMI 3.0 ones.
|
|
54
|
+
TYPES = tuple(dict.fromkeys(ModelDescription.FMI2_VARIABLE_TYPES + ModelDescription.FMI3_VARIABLE_TYPES))
|
|
55
|
+
|
|
56
|
+
#: Variabilities a port filter accepts.
|
|
57
|
+
VARIABILITIES = ModelDescription.VARIABILITIES
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def check_port_filters(causality: list[str] | None = None, types: list[str] | None = None,
|
|
61
|
+
variabilities: list[str] | None = None) -> None:
|
|
62
|
+
"""Refuse the unknown values of the port filters, listing the accepted ones.
|
|
63
|
+
|
|
64
|
+
Raises:
|
|
65
|
+
ValueError: If a value is not one of :data:`CAUSALITIES`, :data:`TYPES`
|
|
66
|
+
or :data:`VARIABILITIES`.
|
|
67
|
+
"""
|
|
68
|
+
for label, values, accepted in (("causality", causality, CAUSALITIES), ("type", types, TYPES),
|
|
69
|
+
("variability", variabilities, VARIABILITIES)):
|
|
70
|
+
unknown = set(values or ()) - set(accepted)
|
|
71
|
+
if unknown:
|
|
72
|
+
raise ValueError(f"Unknown {label} {sorted(unknown)}. Available: {list(accepted)}.")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def select_ports(ports: list[dict[str, Any]], fmi_version: int | None, causality: list[str] | None = None,
|
|
76
|
+
types: list[str] | None = None, variabilities: list[str] | None = None) -> list[dict[str, Any]]:
|
|
77
|
+
"""The ports of a description (`describe_fmu`, the bridges) that every filter set accepts.
|
|
78
|
+
|
|
79
|
+
Same rules as `FMU.apply_operation`: FMI 2.0 type names select their FMI
|
|
80
|
+
3.0 family, an undeclared variability is the default of the standard.
|
|
81
|
+
"""
|
|
82
|
+
# Any causality can be listed (`independent`, `calculatedParameter`...): only the other filters are checked.
|
|
83
|
+
check_port_filters(None, types, variabilities)
|
|
84
|
+
version = fmi_version or 2
|
|
85
|
+
selected = []
|
|
86
|
+
for port in ports:
|
|
87
|
+
port_causality = port.get("causality") or "local"
|
|
88
|
+
if causality and port_causality not in causality:
|
|
89
|
+
continue
|
|
90
|
+
if types and not matches_type(version, port.get("type"), types):
|
|
91
|
+
continue
|
|
92
|
+
if variabilities and (port.get("variability")
|
|
93
|
+
or default_variability(version, port_causality, port.get("type"))) not in variabilities:
|
|
94
|
+
continue
|
|
95
|
+
selected.append(port)
|
|
96
|
+
return selected
|
|
97
|
+
|
|
50
98
|
|
|
51
99
|
@contextmanager
|
|
52
100
|
def _captured_logs(level: int = logging.DEBUG):
|
|
@@ -124,6 +172,122 @@ def summarize_fmu(path: Path) -> dict[str, Any]:
|
|
|
124
172
|
return summary
|
|
125
173
|
|
|
126
174
|
|
|
175
|
+
#: Aliases listed by `describe_port`: an FMI 2.0 FMU may share one value reference between many variables.
|
|
176
|
+
MAX_ALIASES = 20
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def describe_port(path: Path, port: str) -> dict[str, Any]:
|
|
180
|
+
"""Describe one port of an FMU with everything its descriptor declares.
|
|
181
|
+
|
|
182
|
+
The port pages (`describe_fmu`) keep a few fields per port to stay small;
|
|
183
|
+
this is the full card of a single port.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
path: Path to an existing ``.fmu`` file.
|
|
187
|
+
port: Name of the port.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
A mapping with ``fmu``, ``fmi_version``, ``name``, ``type``,
|
|
191
|
+
``causality`` and ``variability`` (the defaults of the standard when not
|
|
192
|
+
declared), ``attributes`` (every attribute as declared, FMI 2.0
|
|
193
|
+
``<ScalarVariable>`` and type element merged, and the ``<Start>`` values
|
|
194
|
+
of FMI 3.0 ``String`` and ``Binary`` variables under ``start``), and
|
|
195
|
+
when they apply: ``dimensions`` (FMI 3.0 arrays), ``declared_type``
|
|
196
|
+
(name, attributes and enumeration items of the type definition, and
|
|
197
|
+
``inherited``: the attributes the port takes from it), ``aliases`` (the
|
|
198
|
+
first :data:`MAX_ALIASES`, with ``aliases_total`` beyond) and ``terminals``
|
|
199
|
+
(terminal name, kind and member name).
|
|
200
|
+
|
|
201
|
+
Raises:
|
|
202
|
+
ValueError: If the FMU has no such port; the message suggests close names.
|
|
203
|
+
"""
|
|
204
|
+
with FMU(str(path)) as fmu:
|
|
205
|
+
md = fmu.model_description
|
|
206
|
+
variables = {element.get("name"): element for element in md.variables()}
|
|
207
|
+
element = variables.get(port)
|
|
208
|
+
if element is None:
|
|
209
|
+
close = difflib.get_close_matches(port, list(variables), n=5)
|
|
210
|
+
hint = f" Close names: {close}." if close else ""
|
|
211
|
+
raise ValueError(f"'{path.name}' has no port '{port}'.{hint}")
|
|
212
|
+
variable = ModelVariable(element, md.fmi_version)
|
|
213
|
+
terminals = Terminals(fmu.tmp_directory)
|
|
214
|
+
|
|
215
|
+
attributes: dict[str, str] = {}
|
|
216
|
+
for attrs in variable.attrs_list:
|
|
217
|
+
for key, value in attrs.items():
|
|
218
|
+
attributes.setdefault(key, value)
|
|
219
|
+
|
|
220
|
+
card: dict[str, Any] = {
|
|
221
|
+
"fmu": path.name,
|
|
222
|
+
"fmi_version": md.fmi_version,
|
|
223
|
+
"name": port,
|
|
224
|
+
"type": variable.fmi_type,
|
|
225
|
+
"causality": variable.causality,
|
|
226
|
+
"variability": variable.variability,
|
|
227
|
+
"attributes": attributes,
|
|
228
|
+
}
|
|
229
|
+
if variable.dimensions:
|
|
230
|
+
card["dimensions"] = [{key: value} for key, value in variable.dimensions]
|
|
231
|
+
|
|
232
|
+
declared = _declared_type(md, variable)
|
|
233
|
+
if declared:
|
|
234
|
+
declared["inherited"] = {key: value for key, value in declared["attributes"].items()
|
|
235
|
+
if key not in attributes}
|
|
236
|
+
card["declared_type"] = declared
|
|
237
|
+
|
|
238
|
+
aliases = _aliases(md, variable, variables)
|
|
239
|
+
if aliases:
|
|
240
|
+
card["aliases"] = aliases[:MAX_ALIASES]
|
|
241
|
+
if len(aliases) > MAX_ALIASES:
|
|
242
|
+
card["aliases_total"] = len(aliases)
|
|
243
|
+
|
|
244
|
+
# `Terminals` lists the sub-terminals at the top level too: one pass covers them all.
|
|
245
|
+
memberships = [{"terminal": terminal.name, "kind": terminal.kind, "member": member}
|
|
246
|
+
for terminal in terminals
|
|
247
|
+
for member, name in terminal.members.items() if name == port]
|
|
248
|
+
if memberships:
|
|
249
|
+
card["terminals"] = memberships
|
|
250
|
+
return card
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _declared_type(md: ModelDescription, variable: ModelVariable) -> dict[str, Any] | None:
|
|
254
|
+
"""The type definition named by `declaredType`, with its enumeration items."""
|
|
255
|
+
name = variable.get("declaredType")
|
|
256
|
+
definitions = md.root.find("TypeDefinitions")
|
|
257
|
+
if not name or definitions is None:
|
|
258
|
+
return None
|
|
259
|
+
for definition in definitions:
|
|
260
|
+
if definition.get("name") != name:
|
|
261
|
+
continue
|
|
262
|
+
# FMI-2: <SimpleType name="..."><Real unit="..."/></SimpleType>; FMI-3: <Float64Type name="..." unit="..."/>.
|
|
263
|
+
typed = definition[0] if md.fmi_version == 2 and len(definition) else definition
|
|
264
|
+
attributes = {key: value for key, value in definition.attrib.items() if key != "name"}
|
|
265
|
+
if typed is not definition:
|
|
266
|
+
attributes.update(typed.attrib)
|
|
267
|
+
declared: dict[str, Any] = {"name": name, "attributes": attributes}
|
|
268
|
+
items = [dict(item.attrib) for item in typed.findall("Item")]
|
|
269
|
+
if items:
|
|
270
|
+
declared["items"] = items
|
|
271
|
+
return declared
|
|
272
|
+
return {"name": name, "attributes": {}, "error": "no such type definition"}
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
def _aliases(md: ModelDescription, variable: ModelVariable,
|
|
276
|
+
variables: dict[str, Any]) -> list[dict[str, str]]:
|
|
277
|
+
"""FMI-3: the `<Alias>` elements. FMI-2: the variables sharing the value reference and the type."""
|
|
278
|
+
if md.fmi_version == 3:
|
|
279
|
+
return [dict(alias.attrib) for alias in variable.element.findall("Alias")]
|
|
280
|
+
vr = variable.element.get("valueReference")
|
|
281
|
+
aliases = []
|
|
282
|
+
for name, element in variables.items():
|
|
283
|
+
if element is variable.element or element.get("valueReference") != vr:
|
|
284
|
+
continue
|
|
285
|
+
other = ModelVariable(element, md.fmi_version)
|
|
286
|
+
if other.fmi_type == variable.fmi_type:
|
|
287
|
+
aliases.append({"name": name, "causality": other.causality})
|
|
288
|
+
return aliases
|
|
289
|
+
|
|
290
|
+
|
|
127
291
|
#: Most groups of messages returned by `check_fmu` per list: an industrial FMU can produce thousands of errors,
|
|
128
292
|
#: which would fill the context window of the model.
|
|
129
293
|
MAX_MESSAGE_GROUPS = 50
|
|
@@ -202,7 +366,7 @@ def dump_ports_csv(fmu_path: Path, csv_path: Path) -> dict[str, Any]:
|
|
|
202
366
|
The file has one row per port, with columns ``name``, ``newName``,
|
|
203
367
|
``valueReference``, ``causality``, ``variability``, ``scalarType`` and
|
|
204
368
|
``startValue``, separated by semicolons. Editing the ``newName`` column
|
|
205
|
-
and feeding it back to :func:`
|
|
369
|
+
and feeding it back to :func:`rename_ports` is the intended
|
|
206
370
|
round-trip.
|
|
207
371
|
|
|
208
372
|
Args:
|
|
@@ -220,8 +384,13 @@ def dump_ports_csv(fmu_path: Path, csv_path: Path) -> dict[str, Any]:
|
|
|
220
384
|
return {"fmu": fmu_path.name, "csv": str(csv_path), "ports": max(len(rows) - 1, 0)}
|
|
221
385
|
|
|
222
386
|
|
|
223
|
-
|
|
224
|
-
|
|
387
|
+
#: Names of a renaming mapping absent from the FMU listed in the report of `rename_ports`; the total is always given.
|
|
388
|
+
MAX_UNKNOWN_NAMES = 20
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
def rename_ports(fmu_path: Path, output_path: Path, mapping: dict[str, str] | None = None,
|
|
392
|
+
csv_path: Path | None = None) -> dict[str, Any]:
|
|
393
|
+
"""Rename (or drop) the ports of an FMU, from a mapping or from a CSV file.
|
|
225
394
|
|
|
226
395
|
The CSV is the one produced by :func:`dump_ports_csv`: column 0 is the
|
|
227
396
|
current name, column 1 the new one. **An empty new name removes the
|
|
@@ -230,32 +399,52 @@ def rename_ports_from_csv(fmu_path: Path, csv_path: Path, output_path: Path) ->
|
|
|
230
399
|
|
|
231
400
|
Args:
|
|
232
401
|
fmu_path: FMU to read.
|
|
233
|
-
csv_path: CSV mapping file.
|
|
234
402
|
output_path: Destination FMU. The source is never modified.
|
|
403
|
+
mapping: Current name -> new name.
|
|
404
|
+
csv_path: CSV mapping file. Exactly one of `mapping` and `csv_path` is given.
|
|
235
405
|
|
|
236
406
|
Returns:
|
|
237
|
-
A mapping with ``fmu``, ``output``, ``renamed`` and ``removed
|
|
407
|
+
A mapping with ``fmu``, ``output``, ``renamed`` and ``removed`` (ports
|
|
408
|
+
actually renamed or removed), and when some names of the mapping are not
|
|
409
|
+
ports of the FMU: ``unknown`` (the first of them) and ``unknown_total``.
|
|
410
|
+
|
|
411
|
+
Raises:
|
|
412
|
+
ValueError: If neither or both of `mapping` and `csv_path` are given.
|
|
238
413
|
"""
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
414
|
+
if (mapping is None) == (csv_path is None):
|
|
415
|
+
raise ValueError("Give either `mapping` or `csv`, not both.")
|
|
416
|
+
if csv_path is not None:
|
|
417
|
+
operation: OperationRename = OperationRenameFromCSV(str(csv_path))
|
|
418
|
+
# `OperationRenameFromCSV` reads every row, header included: the CSV
|
|
419
|
+
# produced by `dump_ports_csv` starts with `name;newName`, which must not
|
|
420
|
+
# be taken for a port.
|
|
421
|
+
if operation.translations.get("name") == "newName":
|
|
422
|
+
del operation.translations["name"]
|
|
423
|
+
else:
|
|
424
|
+
operation = OperationRename(mapping)
|
|
247
425
|
|
|
248
426
|
with FMU(str(fmu_path)) as fmu:
|
|
249
427
|
fmu.apply_operation(operation)
|
|
250
428
|
fmu.repack(str(output_path))
|
|
251
429
|
|
|
252
|
-
|
|
253
|
-
|
|
430
|
+
translations = operation.translations
|
|
431
|
+
report: dict[str, Any] = {
|
|
432
|
+
"fmu": fmu_path.name, "output": str(output_path),
|
|
433
|
+
"renamed": sum(1 for old in operation.found if translations[old] and translations[old] != old),
|
|
434
|
+
"removed": sum(1 for old in operation.found if not translations[old]),
|
|
435
|
+
}
|
|
436
|
+
unknown = [old for old in translations if old not in operation.found]
|
|
437
|
+
if unknown:
|
|
438
|
+
report["unknown"] = unknown[:MAX_UNKNOWN_NAMES]
|
|
439
|
+
report["unknown_total"] = len(unknown)
|
|
440
|
+
return report
|
|
254
441
|
|
|
255
442
|
|
|
256
443
|
def apply_operation(fmu_path: Path, output_path: Path, operation: str,
|
|
257
444
|
argument: str | None = None,
|
|
258
|
-
causality: list[str] | None = None
|
|
445
|
+
causality: list[str] | None = None,
|
|
446
|
+
types: list[str] | None = None,
|
|
447
|
+
variabilities: list[str] | None = None) -> dict[str, Any]:
|
|
259
448
|
"""Apply one descriptor operation to an FMU and write the result.
|
|
260
449
|
|
|
261
450
|
Args:
|
|
@@ -265,6 +454,8 @@ def apply_operation(fmu_path: Path, output_path: Path, operation: str,
|
|
|
265
454
|
argument: Required by the parameterised operations (``trim_until``,
|
|
266
455
|
``remove_regexp``, ``keep_only_regexp``), rejected by the others.
|
|
267
456
|
causality: Restrict the operation to these causalities.
|
|
457
|
+
types: Restrict the operation to these types (see :func:`check_port_filters`).
|
|
458
|
+
variabilities: Restrict the operation to these variabilities.
|
|
268
459
|
|
|
269
460
|
Returns:
|
|
270
461
|
A mapping with ``fmu``, ``output`` and ``operation`` (what was done,
|
|
@@ -285,11 +476,7 @@ def apply_operation(fmu_path: Path, output_path: Path, operation: str,
|
|
|
285
476
|
if argument and not needs_argument:
|
|
286
477
|
raise ValueError(f"Operation '{operation}' does not take an `argument`.")
|
|
287
478
|
|
|
288
|
-
|
|
289
|
-
unknown = set(causality) - set(CAUSALITIES)
|
|
290
|
-
if unknown:
|
|
291
|
-
raise ValueError(f"Unknown causality {sorted(unknown)}. "
|
|
292
|
-
f"Available: {list(CAUSALITIES)}.")
|
|
479
|
+
check_port_filters(causality, types, variabilities)
|
|
293
480
|
|
|
294
481
|
# A malformed regular expression surfaces here, as a plain `re.error`:
|
|
295
482
|
# turn it into something the caller can act upon.
|
|
@@ -299,11 +486,9 @@ def apply_operation(fmu_path: Path, output_path: Path, operation: str,
|
|
|
299
486
|
raise ValueError(f"Cannot apply '{operation}': {exc}") from None
|
|
300
487
|
|
|
301
488
|
with FMU(str(fmu_path)) as fmu:
|
|
302
|
-
fmu.apply_operation(instance, causality or None
|
|
489
|
+
fmu.apply_operation(instance, causality or None, types=types or None,
|
|
490
|
+
variabilities=variabilities or None)
|
|
303
491
|
fmu.repack(str(output_path))
|
|
304
492
|
|
|
305
493
|
return {"fmu": fmu_path.name, "output": str(output_path),
|
|
306
494
|
"operation": repr(instance)}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
@@ -45,6 +45,9 @@ DEFAULT_OPTIONS: dict[str, Any] = {
|
|
|
45
45
|
#: Default name of the container being described.
|
|
46
46
|
DEFAULT_CONTAINER_NAME = "container.fmu"
|
|
47
47
|
|
|
48
|
+
#: Marker of the files written by `HeadlessAssemblyBridge.state` (the assembly state of `fmutool-agent`).
|
|
49
|
+
STATE_FORMAT = "fmutool-agent-state/1"
|
|
50
|
+
|
|
48
51
|
|
|
49
52
|
class _FmuDescriptor(OperationAbstract):
|
|
50
53
|
"""Reads an FMU descriptor and collects what the assistant needs.
|
|
@@ -165,6 +168,49 @@ class HeadlessAssemblyBridge:
|
|
|
165
168
|
self._start_values: dict[tuple[str, str], str] = {}
|
|
166
169
|
self._options: dict[str, Any] = dict(DEFAULT_OPTIONS)
|
|
167
170
|
|
|
171
|
+
# -- state -------------------------------------------------------------
|
|
172
|
+
|
|
173
|
+
def state(self) -> dict[str, Any]:
|
|
174
|
+
"""What the client asked for, as JSON values: `from_state` rebuilds the same bridge.
|
|
175
|
+
|
|
176
|
+
This is not the assembly description (`save_as_json`): it keeps the
|
|
177
|
+
names given to the FMUs and nothing derived from them, so that a tool
|
|
178
|
+
called in another process (`fmutool-agent`) finds the assembly as left.
|
|
179
|
+
"""
|
|
180
|
+
return {
|
|
181
|
+
"format": STATE_FORMAT,
|
|
182
|
+
"name": self._name,
|
|
183
|
+
"fmus": {name: str(path) for name, path in self._paths.items()},
|
|
184
|
+
"links": [list(link) for link in self._links],
|
|
185
|
+
"exposed_inputs": [list(item) for item in self._exposed_inputs],
|
|
186
|
+
"exposed_outputs": [list(item) for item in self._exposed_outputs],
|
|
187
|
+
"start_values": [[fmu, port, value] for (fmu, port), value in self._start_values.items()],
|
|
188
|
+
"options": dict(self._options),
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@classmethod
|
|
192
|
+
def from_state(cls, state: dict[str, Any]) -> "HeadlessAssemblyBridge":
|
|
193
|
+
"""The bridge saved by `state`. The FMUs are read again from their files.
|
|
194
|
+
|
|
195
|
+
Raises:
|
|
196
|
+
ValueError: If `state` was not produced by `state`.
|
|
197
|
+
FileNotFoundError: If an FMU of the assembly no longer exists.
|
|
198
|
+
"""
|
|
199
|
+
if not isinstance(state, dict) or state.get("format") != STATE_FORMAT:
|
|
200
|
+
raise ValueError(f"Not an assembly state (expected \"format\": \"{STATE_FORMAT}\").")
|
|
201
|
+
bridge = cls(state.get("name", DEFAULT_CONTAINER_NAME))
|
|
202
|
+
for name, path in state.get("fmus", {}).items():
|
|
203
|
+
description = describe_fmu(Path(path))
|
|
204
|
+
description["fmu"] = name
|
|
205
|
+
bridge._paths[name] = Path(path)
|
|
206
|
+
bridge._descriptions[name] = description
|
|
207
|
+
bridge._links = [tuple(link) for link in state.get("links", [])]
|
|
208
|
+
bridge._exposed_inputs = [tuple(item) for item in state.get("exposed_inputs", [])]
|
|
209
|
+
bridge._exposed_outputs = [tuple(item) for item in state.get("exposed_outputs", [])]
|
|
210
|
+
bridge._start_values = {(fmu, port): value for fmu, port, value in state.get("start_values", [])}
|
|
211
|
+
bridge._options.update(state.get("options", {}))
|
|
212
|
+
return bridge
|
|
213
|
+
|
|
168
214
|
# -- helpers -----------------------------------------------------------
|
|
169
215
|
|
|
170
216
|
def _description(self, fmu: str) -> dict[str, Any]:
|
|
@@ -84,10 +84,14 @@ Beyond assembling, single-FMU tools are also available. They read or rewrite
|
|
|
84
84
|
**one** `.fmu` file and never touch the assembly:
|
|
85
85
|
- `summarize_fmu(path)` — identity, capabilities, platforms, port counts.
|
|
86
86
|
- `check_fmu(path)` — FMI schema conformity and registered checkers.
|
|
87
|
-
- `
|
|
88
|
-
|
|
87
|
+
- `describe_port(fmu, port)` — everything declared about one port: min, max,
|
|
88
|
+
nominal, declared type, aliases, terminals.
|
|
89
|
+
- `rename_ports(fmu, output, mapping=...)` — renaming from a mapping, or from
|
|
90
|
+
a CSV written by `dump_ports_csv(fmu, path)` (bulk renaming). An **empty**
|
|
91
|
+
new name **removes** the port.
|
|
89
92
|
- `apply_operation(fmu, output, operation, ...)` — prefix stripping, trimming
|
|
90
|
-
and regexp filtering of port names
|
|
93
|
+
and regexp filtering of port names, restricted with `causality`, `type` and
|
|
94
|
+
`variability` if needed.
|
|
91
95
|
|
|
92
96
|
These rewrite the FMU interface, so they produce a **new** file and leave the
|
|
93
97
|
source untouched. Warn the user that anything already connected to the old
|
|
@@ -13,21 +13,13 @@ from typing import Any
|
|
|
13
13
|
|
|
14
14
|
from pydantic import BaseModel, ConfigDict, Field, SerializerFunctionWrapHandler, model_serializer
|
|
15
15
|
|
|
16
|
+
# Shared with the command line, which runs without Pydantic: defined in `tools`, re-exported here.
|
|
17
|
+
from .tools import DEFAULT_PORT_LIMIT, MAX_DESCRIPTION_LENGTH, MAX_PORT_LIMIT, format_start_value # noqa: F401
|
|
18
|
+
|
|
16
19
|
#: Value kinds accepted for a start value, before conversion to the FMI
|
|
17
20
|
#: textual representation.
|
|
18
21
|
StartValue = bool | int | float | str
|
|
19
22
|
|
|
20
|
-
#: Maximum number of ports returned by a single call, to keep the answer
|
|
21
|
-
#: readable and the context small on industrial FMUs.
|
|
22
|
-
DEFAULT_PORT_LIMIT = 50
|
|
23
|
-
|
|
24
|
-
#: Largest page of ports a client may ask for: about 31k characters (~9k tokens) of compact ports.
|
|
25
|
-
MAX_PORT_LIMIT = 200
|
|
26
|
-
|
|
27
|
-
#: Descriptions of the ports longer than this are cut (with `…`): they help to match ports by meaning, but some
|
|
28
|
-
#: generators write whole paragraphs, which would fill the context window of the model.
|
|
29
|
-
MAX_DESCRIPTION_LENGTH = 80
|
|
30
|
-
|
|
31
23
|
|
|
32
24
|
class ContainerOptions(BaseModel):
|
|
33
25
|
"""Container options to change; the others keep their value."""
|
|
@@ -55,18 +47,16 @@ class ContainerOptions(BaseModel):
|
|
|
55
47
|
)
|
|
56
48
|
auto_link: bool | None = Field(
|
|
57
49
|
default=None,
|
|
58
|
-
description="Connect the ports with the same name and type
|
|
59
|
-
"
|
|
50
|
+
description="Connect the ports with the same name and type (default: on); "
|
|
51
|
+
"links are for the others.",
|
|
60
52
|
)
|
|
61
53
|
auto_input: bool | None = Field(
|
|
62
54
|
default=None,
|
|
63
|
-
description="
|
|
64
|
-
"inputs. Enabled by default.",
|
|
55
|
+
description="Expose the unconnected inputs (default: on).",
|
|
65
56
|
)
|
|
66
57
|
auto_output: bool | None = Field(
|
|
67
58
|
default=None,
|
|
68
|
-
description="
|
|
69
|
-
"outputs. Enabled by default.",
|
|
59
|
+
description="Expose the unconnected outputs (default: on).",
|
|
70
60
|
)
|
|
71
61
|
auto_parameter: bool | None = Field(
|
|
72
62
|
default=None,
|
|
@@ -83,10 +73,8 @@ class ContainerOptions(BaseModel):
|
|
|
83
73
|
)
|
|
84
74
|
reset_ports: bool | None = Field(
|
|
85
75
|
default=None,
|
|
86
|
-
description="Add a `container.reset` input to each
|
|
87
|
-
"
|
|
88
|
-
"at the current time. Wire it with a link, or expose it as "
|
|
89
|
-
"`container.<fmu>.reset`.",
|
|
76
|
+
description="Add a `container.reset` input to each FMU: true resets and "
|
|
77
|
+
"initializes it again. Link it, or expose it as `container.<fmu>.reset`.",
|
|
90
78
|
)
|
|
91
79
|
|
|
92
80
|
def changes(self) -> dict[str, Any]:
|
|
@@ -117,23 +105,6 @@ def option_reference() -> list[dict[str, Any]]:
|
|
|
117
105
|
return reference
|
|
118
106
|
|
|
119
107
|
|
|
120
|
-
def format_start_value(value: StartValue) -> str:
|
|
121
|
-
"""Render ``value`` the way ``modelDescription.xml`` expects it.
|
|
122
|
-
|
|
123
|
-
Booleans are the trap here: ``str(True)`` yields ``"True"``, which FMI
|
|
124
|
-
does not accept.
|
|
125
|
-
|
|
126
|
-
Examples:
|
|
127
|
-
>>> format_start_value(True)
|
|
128
|
-
'true'
|
|
129
|
-
>>> format_start_value(0.01)
|
|
130
|
-
'0.01'
|
|
131
|
-
"""
|
|
132
|
-
if isinstance(value, bool):
|
|
133
|
-
return "true" if value else "false"
|
|
134
|
-
return str(value)
|
|
135
|
-
|
|
136
|
-
|
|
137
108
|
# ---------------------------------------------------------------------------
|
|
138
109
|
# FMU description
|
|
139
110
|
# ---------------------------------------------------------------------------
|
|
@@ -165,14 +136,6 @@ class Port(BaseModel):
|
|
|
165
136
|
"""
|
|
166
137
|
return {key: value for key, value in handler(self).items() if value is not None}
|
|
167
138
|
|
|
168
|
-
@classmethod
|
|
169
|
-
def from_description(cls, port: dict[str, Any]) -> "Port":
|
|
170
|
-
"""A port of a bridge description, its description cut to `MAX_DESCRIPTION_LENGTH` characters."""
|
|
171
|
-
description = port.get("description")
|
|
172
|
-
if description and len(description) > MAX_DESCRIPTION_LENGTH:
|
|
173
|
-
port = {**port, "description": description[:MAX_DESCRIPTION_LENGTH - 1].rstrip() + "…"}
|
|
174
|
-
return cls(**port)
|
|
175
|
-
|
|
176
139
|
|
|
177
140
|
class FmuPorts(BaseModel):
|
|
178
141
|
"""A page of ports, plus what it took to get there.
|