dynamic-systems-testing-framework 1.0.1__tar.gz → 1.1.0__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.
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/.gitignore +5 -1
- dynamic_systems_testing_framework-1.1.0/PKG-INFO +102 -0
- dynamic_systems_testing_framework-1.1.0/README.md +56 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/pyproject.toml +14 -4
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/edit_criteria.py +2 -2
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/edit_on_plot.py +3 -3
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/session.py +15 -4
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/app.py +2 -2
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/header.py +5 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/tree_card.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/situation.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/unscorable.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/__init__.py +109 -53
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/base.py +331 -78
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/json_driver.py +30 -9
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/dymola/backend.py +133 -13
- dynamic_systems_testing_framework-1.1.0/src/dstf/backends/dymola/interface_loader.py +404 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/dymola/persistent_backend.py +9 -5
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/fmpy/backend.py +90 -16
- dynamic_systems_testing_framework-1.1.0/src/dstf/backends/julia/backend.py +275 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/julia/persistent_backend.py +10 -25
- dynamic_systems_testing_framework-1.1.0/src/dstf/backends/locate.py +309 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/backend.py +99 -12
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/session_loader.py +7 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/persistent.py +309 -258
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/progress.py +29 -6
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/python/backend.py +40 -16
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/python/run_test.py +8 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/types.py +102 -25
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/__init__.py +16 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/cli/author_cmd.py +12 -21
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/baseline_cmds.py +303 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/cli/common.py +42 -35
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/diag_cmds.py +428 -0
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/main.py +85 -0
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/parser.py +2004 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/cli/run_cmds.py +120 -51
- dynamic_systems_testing_framework-1.1.0/src/dstf/cli/spec_cmds.py +244 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/__init__.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/algorithms.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/builtins.py +81 -4
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/comparator.py +60 -2
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/handles.py +3 -3
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/metric_tree.py +24 -20
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/mode_schema.py +62 -14
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/modes.py +181 -76
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/registry.py +77 -59
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/sides.py +18 -3
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/strict_keys.py +4 -3
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/summaries.py +2 -2
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/tree_eval.py +37 -5
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/tree_spec.py +17 -10
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/types.py +17 -7
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/validator.py +86 -44
- dynamic_systems_testing_framework-1.1.0/src/dstf/config.py +1058 -0
- dynamic_systems_testing_framework-1.1.0/src/dstf/config_shape.py +387 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/json_recognizer.py +85 -40
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/library_state.py +7 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/mo_parser.py +52 -13
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/patch_apply.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/patch_envelope.py +1 -1
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/recognizer.py +61 -15
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/scan_cache.py +3 -2
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/spec_parser.py +34 -55
- dynamic_systems_testing_framework-1.1.0/src/dstf/discovery/spec_shape.py +381 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/spec_update.py +37 -9
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/test_registry.py +46 -37
- dynamic_systems_testing_framework-1.1.0/src/dstf/json_types.py +107 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/pipeline.py +42 -27
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/plugins.py +16 -9
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/context_builder.py +5 -5
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/dashboard_render.py +165 -36
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/report_suite.py +7 -3
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/schema_export.py +89 -81
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/dashboard.html +5 -7
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/dashboard.js +7 -4
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/interactive.html +4 -4
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/accept.py +14 -8
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/reference_store.py +12 -7
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/roles.py +1 -1
- dynamic_systems_testing_framework-1.0.1/PKG-INFO +0 -266
- dynamic_systems_testing_framework-1.0.1/README.md +0 -226
- dynamic_systems_testing_framework-1.0.1/src/dstf/backends/dymola/interface_loader.py +0 -241
- dynamic_systems_testing_framework-1.0.1/src/dstf/backends/julia/backend.py +0 -156
- dynamic_systems_testing_framework-1.0.1/src/dstf/cli/__init__.py +0 -12
- dynamic_systems_testing_framework-1.0.1/src/dstf/cli/baseline_cmds.py +0 -341
- dynamic_systems_testing_framework-1.0.1/src/dstf/cli/diag_cmds.py +0 -350
- dynamic_systems_testing_framework-1.0.1/src/dstf/cli/main.py +0 -561
- dynamic_systems_testing_framework-1.0.1/src/dstf/cli/spec_cmds.py +0 -123
- dynamic_systems_testing_framework-1.0.1/src/dstf/config.py +0 -815
- dynamic_systems_testing_framework-1.0.1/src/dstf/discovery/spec_shape.py +0 -122
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/LICENSE +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/__main__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/accept.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/edit_family.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/edit_tree.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/builtin/enqueue.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/capabilities.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/errors.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/family_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/forms.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/layout.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/live_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/live_runs.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/needle.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/picker_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/queue_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/actions.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/drawer_controls.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/family_fold.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/figure_hook.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/grips.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/live_view.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/picker.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/placing.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/plot_card.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/queue_panel.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/rail.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/shell.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/stats_card.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/strip.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/style.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/suite.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/suite_grid.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/suite_grid.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/tab_theme.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/tabstate.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/test_list.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/test_page.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/variables_drawer.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/shell/widgets.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/spec_document.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/spec_preview.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/suite_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/tree_move.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/tree_pointer.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/tree_text.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/typed_number.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/typed_number.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/authoring/variable_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/live_mat.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/mat_reader.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/proc_kill.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/proc_output.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/result_files.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/result_variables.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/common/statistics.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/cross_backend.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/dymola/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/dymola/log_parser.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/fmpy/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/julia/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/julia/run_persistent.jl +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/julia/run_test.jl +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/init_xml.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/log_parser.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/mos_generator.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/openmodelica/persistent_backend.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/pool.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/python/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/backends/run_metadata.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/cli/review.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/geometry.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/seeds.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/comparison/snap.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/plots.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/discovery/unit_tests.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/assemble.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/decimate.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/families.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/palette.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/plotly.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/figures/view.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/console_report.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/junit_report.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/overlay_loader.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/stats_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/status.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/axes.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/filters.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/report.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/templates/vendor/plotly.min.js +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/theme.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/tree_rows.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/reporting/verdicts.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/__init__.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/baseline.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/batch_manifest.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/ref_index.py +0 -0
- {dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/src/dstf/storage/run_stats.py +0 -0
{dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/.gitignore
RENAMED
|
@@ -6,8 +6,9 @@ dist/
|
|
|
6
6
|
build/
|
|
7
7
|
*.egg
|
|
8
8
|
|
|
9
|
-
# Virtual environments
|
|
9
|
+
# Virtual environments (.venv-example/: the one docs/guides/first-run.md makes)
|
|
10
10
|
.venv/
|
|
11
|
+
.venv-example/
|
|
11
12
|
venv/
|
|
12
13
|
.env
|
|
13
14
|
|
|
@@ -46,6 +47,9 @@ testing_output/
|
|
|
46
47
|
# Generated reports (dashboard.html, interactive plots, comparison_data.json)
|
|
47
48
|
reports/
|
|
48
49
|
|
|
50
|
+
# The documentation site, built (sphinx-build docs docs/_build/html)
|
|
51
|
+
docs/_build/
|
|
52
|
+
|
|
49
53
|
# Reference-FMUs binaries (fetched by scripts/fetch_reference_fmus.py)
|
|
50
54
|
examples/fmu/reference-fmus-binaries/
|
|
51
55
|
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: dynamic-systems-testing-framework
|
|
3
|
+
Version: 1.1.0
|
|
4
|
+
Summary: Dynamic Systems Testing Framework — regression & unit testing for time-dependent system behavior, with plug-in backends: Modelica (Dymola, OpenModelica), FMU (FMPy), Julia (ModelingToolkit) and Python to start
|
|
5
|
+
Project-URL: Homepage, https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework
|
|
6
|
+
Project-URL: Repository, https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework
|
|
7
|
+
Project-URL: Documentation, https://dstf.readthedocs.io/
|
|
8
|
+
Project-URL: Issues, https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/CHANGELOG.md
|
|
10
|
+
Author: Scott Greenwood
|
|
11
|
+
License-Expression: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: dymola,fmi,fmu,julia,modelica,modelingtoolkit,openmodelica,regression-testing,simulation,testing
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering
|
|
21
|
+
Classifier: Topic :: Software Development :: Testing
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: jinja2>=3.1
|
|
24
|
+
Requires-Dist: numpy>=1.20
|
|
25
|
+
Requires-Dist: psutil>=5.9
|
|
26
|
+
Provides-Extra: author
|
|
27
|
+
Requires-Dist: nicegui>=3.16; extra == 'author'
|
|
28
|
+
Requires-Dist: regex>=2026.9.10; extra == 'author'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: mypy>=1.10; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.16; extra == 'dev'
|
|
35
|
+
Requires-Dist: scipy>=1.10; extra == 'dev'
|
|
36
|
+
Requires-Dist: types-regex>=2026.9.10; extra == 'dev'
|
|
37
|
+
Provides-Extra: docs
|
|
38
|
+
Requires-Dist: furo>=2024.8.6; extra == 'docs'
|
|
39
|
+
Requires-Dist: myst-parser>=4.0; extra == 'docs'
|
|
40
|
+
Requires-Dist: sphinx>=8.1; extra == 'docs'
|
|
41
|
+
Provides-Extra: fmpy
|
|
42
|
+
Requires-Dist: fmpy>=0.3; extra == 'fmpy'
|
|
43
|
+
Provides-Extra: om
|
|
44
|
+
Requires-Dist: ompython>=3.5; extra == 'om'
|
|
45
|
+
Description-Content-Type: text/markdown
|
|
46
|
+
|
|
47
|
+
# Dynamic Systems Testing Framework (DSTF)
|
|
48
|
+
|
|
49
|
+
[](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/actions/workflows/quality.yml)
|
|
50
|
+
|
|
51
|
+
DSTF is regression and unit testing for the behaviour of time-dependent
|
|
52
|
+
systems: Modelica libraries, FMUs, Julia models, or anything Python can
|
|
53
|
+
compute. It finds a library's tests, simulates them with a backend — Dymola,
|
|
54
|
+
OpenModelica, FMPy, Julia or Python, or one a plug-in adds — and scores each
|
|
55
|
+
result against a stored baseline by the criteria you write. It reports a
|
|
56
|
+
verdict per test on the command line, as JUnit XML for CI, and as a dashboard
|
|
57
|
+
and a page per test in the browser.
|
|
58
|
+
|
|
59
|
+
DSTF is in beta: the command line and the testing.json keys may still change
|
|
60
|
+
between minor versions; the changelog says when.
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```console
|
|
65
|
+
$ uv tool install dynamic-systems-testing-framework
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
or `pipx install dynamic-systems-testing-framework`. The command is `dstf`.
|
|
69
|
+
The `author` extra adds `dstf author`, a browser tool for writing criteria
|
|
70
|
+
beside the plots they score; `fmpy` and `om` add what the FMPy and
|
|
71
|
+
OpenModelica backends drive.
|
|
72
|
+
|
|
73
|
+
## A first run
|
|
74
|
+
|
|
75
|
+
The Python example library needs no simulator. From a clone of this
|
|
76
|
+
repository, in a Python environment with numpy and scipy:
|
|
77
|
+
|
|
78
|
+
```console
|
|
79
|
+
$ git clone https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework.git
|
|
80
|
+
$ cd DynamicSystemsTestingFramework
|
|
81
|
+
$ python3 -m pip install numpy scipy
|
|
82
|
+
$ dstf --config examples/python/PythonTestingLib/Resources/ReferenceResults/testing.json run
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
It runs three tests, compares each with its stored baseline, prints a verdict
|
|
86
|
+
per test and opens the dashboard:
|
|
87
|
+
|
|
88
|
+

|
|
89
|
+
|
|
90
|
+
## Documentation
|
|
91
|
+
|
|
92
|
+
<https://dstf.readthedocs.io/> — a first run, setting up `testing.json` for
|
|
93
|
+
your library, adding tests, reading results, baselines, criteria, CI, a page
|
|
94
|
+
per simulator, writing a backend plug-in, and a reference of every command,
|
|
95
|
+
key and comparison mode.
|
|
96
|
+
|
|
97
|
+
## Changelog and licence
|
|
98
|
+
|
|
99
|
+
What changed in each version is in
|
|
100
|
+
[CHANGELOG.md](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/CHANGELOG.md).
|
|
101
|
+
DSTF is released under the MIT licence:
|
|
102
|
+
[LICENSE](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/LICENSE).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Dynamic Systems Testing Framework (DSTF)
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/actions/workflows/quality.yml)
|
|
4
|
+
|
|
5
|
+
DSTF is regression and unit testing for the behaviour of time-dependent
|
|
6
|
+
systems: Modelica libraries, FMUs, Julia models, or anything Python can
|
|
7
|
+
compute. It finds a library's tests, simulates them with a backend — Dymola,
|
|
8
|
+
OpenModelica, FMPy, Julia or Python, or one a plug-in adds — and scores each
|
|
9
|
+
result against a stored baseline by the criteria you write. It reports a
|
|
10
|
+
verdict per test on the command line, as JUnit XML for CI, and as a dashboard
|
|
11
|
+
and a page per test in the browser.
|
|
12
|
+
|
|
13
|
+
DSTF is in beta: the command line and the testing.json keys may still change
|
|
14
|
+
between minor versions; the changelog says when.
|
|
15
|
+
|
|
16
|
+
## Install
|
|
17
|
+
|
|
18
|
+
```console
|
|
19
|
+
$ uv tool install dynamic-systems-testing-framework
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
or `pipx install dynamic-systems-testing-framework`. The command is `dstf`.
|
|
23
|
+
The `author` extra adds `dstf author`, a browser tool for writing criteria
|
|
24
|
+
beside the plots they score; `fmpy` and `om` add what the FMPy and
|
|
25
|
+
OpenModelica backends drive.
|
|
26
|
+
|
|
27
|
+
## A first run
|
|
28
|
+
|
|
29
|
+
The Python example library needs no simulator. From a clone of this
|
|
30
|
+
repository, in a Python environment with numpy and scipy:
|
|
31
|
+
|
|
32
|
+
```console
|
|
33
|
+
$ git clone https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework.git
|
|
34
|
+
$ cd DynamicSystemsTestingFramework
|
|
35
|
+
$ python3 -m pip install numpy scipy
|
|
36
|
+
$ dstf --config examples/python/PythonTestingLib/Resources/ReferenceResults/testing.json run
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
It runs three tests, compares each with its stored baseline, prints a verdict
|
|
40
|
+
per test and opens the dashboard:
|
|
41
|
+
|
|
42
|
+

|
|
43
|
+
|
|
44
|
+
## Documentation
|
|
45
|
+
|
|
46
|
+
<https://dstf.readthedocs.io/> — a first run, setting up `testing.json` for
|
|
47
|
+
your library, adding tests, reading results, baselines, criteria, CI, a page
|
|
48
|
+
per simulator, writing a backend plug-in, and a reference of every command,
|
|
49
|
+
key and comparison mode.
|
|
50
|
+
|
|
51
|
+
## Changelog and licence
|
|
52
|
+
|
|
53
|
+
What changed in each version is in
|
|
54
|
+
[CHANGELOG.md](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/CHANGELOG.md).
|
|
55
|
+
DSTF is released under the MIT licence:
|
|
56
|
+
[LICENSE](https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/LICENSE).
|
{dynamic_systems_testing_framework-1.0.1 → dynamic_systems_testing_framework-1.1.0}/pyproject.toml
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "dynamic-systems-testing-framework"
|
|
3
|
-
version = "1.0
|
|
4
|
-
description = "Dynamic Systems Testing Framework — regression & unit testing for time-dependent system behavior
|
|
3
|
+
version = "1.1.0"
|
|
4
|
+
description = "Dynamic Systems Testing Framework — regression & unit testing for time-dependent system behavior, with plug-in backends: Modelica (Dymola, OpenModelica), FMU (FMPy), Julia (ModelingToolkit) and Python to start"
|
|
5
5
|
# What the package index shows: the README as the project page (its one image
|
|
6
6
|
# is an absolute URL for that), the license by its SPDX name with the file
|
|
7
7
|
# beside it, and where the source and the docs are.
|
|
@@ -14,6 +14,7 @@ keywords = [
|
|
|
14
14
|
"modelingtoolkit", "simulation", "regression-testing", "testing",
|
|
15
15
|
]
|
|
16
16
|
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
17
18
|
"Intended Audience :: Science/Research",
|
|
18
19
|
"Intended Audience :: Developers",
|
|
19
20
|
"Operating System :: OS Independent",
|
|
@@ -59,12 +60,18 @@ fmpy = ["fmpy>=0.3"]
|
|
|
59
60
|
# subprocess path instead.
|
|
60
61
|
# Install with: uv sync --extra om --locked --inexact
|
|
61
62
|
om = ["OMPython>=3.5"]
|
|
63
|
+
# The documentation site (docs/conf.py): Sphinx, Markdown pages through MyST,
|
|
64
|
+
# the Furo theme. Build it with:
|
|
65
|
+
# uv sync --extra docs --locked --inexact
|
|
66
|
+
# uv run sphinx-build -W --keep-going -b html docs docs/_build/html
|
|
67
|
+
docs = ["sphinx>=8.1", "myst-parser>=4.0", "furo>=2024.8.6"]
|
|
62
68
|
|
|
63
69
|
[project.urls]
|
|
64
70
|
Homepage = "https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework"
|
|
65
71
|
Repository = "https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework"
|
|
66
|
-
Documentation = "https://
|
|
72
|
+
Documentation = "https://dstf.readthedocs.io/"
|
|
67
73
|
Issues = "https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/issues"
|
|
74
|
+
Changelog = "https://github.com/ORNL-Modelica/DynamicSystemsTestingFramework/blob/main/CHANGELOG.md"
|
|
68
75
|
|
|
69
76
|
[project.scripts]
|
|
70
77
|
dstf = "dstf.cli:main_entry"
|
|
@@ -90,7 +97,7 @@ markers = [
|
|
|
90
97
|
"fmpy: requires fmpy package",
|
|
91
98
|
"ompython: requires OMPython package (persistent-worker OpenModelica)",
|
|
92
99
|
"reference_fmus: requires Reference-FMUs binaries at examples/fmu/reference-fmus-binaries",
|
|
93
|
-
"julia: requires Julia 1.
|
|
100
|
+
"julia: requires Julia 1.11+ with ModelingToolkit + OrdinaryDiffEq installed in examples/julia/JuliaMtkTestingLib",
|
|
94
101
|
"playwright: browser-driven reporter tests (requires playwright + chromium); until D97 this marker did not exist and -m 'not playwright' was a no-op filter",
|
|
95
102
|
]
|
|
96
103
|
filterwarnings = [
|
|
@@ -151,6 +158,9 @@ files = [
|
|
|
151
158
|
"src/dstf/plugins.py",
|
|
152
159
|
"src/dstf/storage",
|
|
153
160
|
"src/dstf/config.py",
|
|
161
|
+
"src/dstf/config_shape.py",
|
|
162
|
+
"src/dstf/json_types.py",
|
|
163
|
+
"src/dstf/backends/locate.py",
|
|
154
164
|
"src/dstf/pipeline.py",
|
|
155
165
|
"src/dstf/reporting/rows.py",
|
|
156
166
|
]
|
|
@@ -130,7 +130,7 @@ class EditCriteria:
|
|
|
130
130
|
sel = s.selection
|
|
131
131
|
model_id = next(iter(sel.tests)) if len(sel.tests) == 1 else None
|
|
132
132
|
if model_id is None or sel.leaf_path is None:
|
|
133
|
-
return "select one
|
|
133
|
+
return "select one criterion"
|
|
134
134
|
# A compared test whose tree the Session will not materialize: its
|
|
135
135
|
# leaves are on the plots, but every edit is refused — the Session's
|
|
136
136
|
# reason, as the editor's why-line, not the view's leaf as if
|
|
@@ -154,7 +154,7 @@ class EditCriteria:
|
|
|
154
154
|
# The panel is rebuilt after edits made elsewhere: Edit tree wrapping
|
|
155
155
|
# the selected leaf leaves the selection's path naming a combinator.
|
|
156
156
|
if leaf is None:
|
|
157
|
-
ui.label("this
|
|
157
|
+
ui.label("this criterion is not in the scored tree")
|
|
158
158
|
return
|
|
159
159
|
#: A folded row's members as they are read now: the act refuses
|
|
160
160
|
#: the edit if a path no longer holds that member (`act`).
|
|
@@ -151,9 +151,9 @@ def _leaf_at(s: SessionView, model_id: str, path: str) -> dict:
|
|
|
151
151
|
except (KeyError, IndexError, TypeError, ValueError):
|
|
152
152
|
node = None
|
|
153
153
|
if not isinstance(node, dict):
|
|
154
|
-
raise ValueError(f"{path} names no
|
|
154
|
+
raise ValueError(f"{path} names no criterion of {model_id}")
|
|
155
155
|
if "combinator" in node:
|
|
156
|
-
raise ValueError(f"{path} is a
|
|
156
|
+
raise ValueError(f"{path} is a group, not a criterion")
|
|
157
157
|
return node
|
|
158
158
|
|
|
159
159
|
|
|
@@ -463,7 +463,7 @@ def dragged(
|
|
|
463
463
|
paths = [p for p, _ in _leaf_paths(s, model_id, variable)]
|
|
464
464
|
path = _leaf_path_of(handle, paths)
|
|
465
465
|
if path is None:
|
|
466
|
-
raise ValueError(f"{handle} names no
|
|
466
|
+
raise ValueError(f"{handle} names no criterion on {variable} of {model_id}")
|
|
467
467
|
if view is None:
|
|
468
468
|
view = s.view(model_id, variable) # full resolution, not the figure
|
|
469
469
|
leaf = next((lv for lv in view.leaves if lv.path == path), None)
|
|
@@ -26,7 +26,7 @@ from ..backends import BackendUnavailableError, dataset_kind_for, select_backend
|
|
|
26
26
|
from ..backends.base import Backend
|
|
27
27
|
from ..backends.common.result_variables import tracked_results
|
|
28
28
|
from ..backends.pool import ItemState, QueueItem, Refused, StartingWorker
|
|
29
|
-
from ..backends.progress import recorded_backend
|
|
29
|
+
from ..backends.progress import recorded_backend, refuse_unregistered
|
|
30
30
|
from ..backends.types import (
|
|
31
31
|
DatasetType,
|
|
32
32
|
TestResult,
|
|
@@ -60,6 +60,7 @@ from ..discovery.spec_update import (
|
|
|
60
60
|
implicit_tree_op,
|
|
61
61
|
is_literal_variable,
|
|
62
62
|
needs_materialization,
|
|
63
|
+
not_stored_notes,
|
|
63
64
|
unknown_override_modes,
|
|
64
65
|
validate_entry_keys,
|
|
65
66
|
validate_entry_metric_tree,
|
|
@@ -375,6 +376,7 @@ def resolve_project(
|
|
|
375
376
|
assert config.work_dir is not None # resolved in __post_init__
|
|
376
377
|
recorded, warning = recorded_backend(config.work_dir)
|
|
377
378
|
if recorded and recorded != config.backend_name:
|
|
379
|
+
refuse_unregistered(recorded, config.work_dir)
|
|
378
380
|
config = Config(
|
|
379
381
|
config_file=config_path, backend_name=recorded, work_dir=work_dir
|
|
380
382
|
)
|
|
@@ -848,7 +850,7 @@ class Session:
|
|
|
848
850
|
def rescore(self, model_id: str) -> TestComparison:
|
|
849
851
|
"""Score ``model_id`` against the spec with pending ops applied. A
|
|
850
852
|
flat-override test first gets the same ``add /metrics`` op
|
|
851
|
-
``spec
|
|
853
|
+
``spec update`` prepends, so the document the tool edits and the one
|
|
852
854
|
it saves never differ in shape — but only when that tree scores
|
|
853
855
|
exactly what the flat path scored (Conventions #7); otherwise the
|
|
854
856
|
test is scored as loaded and nothing is staged. That op does not
|
|
@@ -1086,6 +1088,15 @@ class Session:
|
|
|
1086
1088
|
result = replace(result, variables=tracked_results(test, result))
|
|
1087
1089
|
return tracked_names(scored, result)
|
|
1088
1090
|
|
|
1091
|
+
def not_stored_notes(self, model_id: str) -> list[str]:
|
|
1092
|
+
"""A sentence per baseline the test's entry, as staged, names that
|
|
1093
|
+
this folder stores none of (:func:`~dstf.discovery.spec_update.
|
|
1094
|
+
not_stored_notes`): `stage` took it — a soft check of another
|
|
1095
|
+
folder — and the pending preview says it is not scored here, as
|
|
1096
|
+
``spec update`` prints it."""
|
|
1097
|
+
project = self._require_project()
|
|
1098
|
+
return not_stored_notes(self.spec.entry(model_id), model_id, project.store)
|
|
1099
|
+
|
|
1089
1100
|
def variable_texts(self, model_id: str) -> dict[str, VariableText]:
|
|
1090
1101
|
"""``{name: VariableText}`` for this test — both readings of every
|
|
1091
1102
|
variable its page can show, from the ONE scope builder the report
|
|
@@ -1790,7 +1801,7 @@ class Session:
|
|
|
1790
1801
|
return out
|
|
1791
1802
|
|
|
1792
1803
|
def save(self) -> None:
|
|
1793
|
-
"""Apply exactly the pending ops through ``spec
|
|
1804
|
+
"""Apply exactly the pending ops through ``spec update``'s
|
|
1794
1805
|
read-modify-write, then reload. Refuses when the file changed on
|
|
1795
1806
|
disk since it was loaded, and when the edits leave a criterion that
|
|
1796
1807
|
can never be scored (`UnscorableSaveError`: `stage` took it, for its
|
|
@@ -2265,7 +2276,7 @@ class Session:
|
|
|
2265
2276
|
# class it reads results through — and silenced: the tool's
|
|
2266
2277
|
# process never narrates a run to the console it was
|
|
2267
2278
|
# started from.
|
|
2268
|
-
backend = select_backend(project.config, persistent=True)
|
|
2279
|
+
backend = select_backend(project.config, persistent=True, to_run=True)
|
|
2269
2280
|
backend.quiet = True
|
|
2270
2281
|
self._pool = open_pool(
|
|
2271
2282
|
project.config,
|
|
@@ -18,7 +18,7 @@ def run_app(
|
|
|
18
18
|
*,
|
|
19
19
|
filter: str | None = None,
|
|
20
20
|
package: str | None = None,
|
|
21
|
-
port: int
|
|
21
|
+
port: int,
|
|
22
22
|
work_dir: Path | None = None,
|
|
23
23
|
backend: str | None = None,
|
|
24
24
|
show: bool = True,
|
|
@@ -46,7 +46,7 @@ def run_app(
|
|
|
46
46
|
ui.run(
|
|
47
47
|
shell.index,
|
|
48
48
|
host="127.0.0.1",
|
|
49
|
-
port=port
|
|
49
|
+
port=port,
|
|
50
50
|
show=show,
|
|
51
51
|
reload=False,
|
|
52
52
|
title="DSTF",
|
|
@@ -758,6 +758,11 @@ class PendingDrawer:
|
|
|
758
758
|
]
|
|
759
759
|
for text in dict.fromkeys(said):
|
|
760
760
|
ui.label(text).classes("text-xs dstf-mono").mark("drawer-gesture")
|
|
761
|
+
# A baseline the entry names that this folder does not store: staged
|
|
762
|
+
# all the same — a soft check of another folder — and said here, in
|
|
763
|
+
# the line `spec update` prints for it.
|
|
764
|
+
for text in session.not_stored_notes(model_id):
|
|
765
|
+
ui.label(text).classes("text-xs text-secondary").mark("drawer-not-stored")
|
|
761
766
|
# Never an empty box: edits that cancel out are not here at all, and
|
|
762
767
|
# neither is a tree written out and not edited (a `rescore`, a value
|
|
763
768
|
# typed and cleared on a flat test) — an entry put back as saved has
|
|
@@ -307,7 +307,7 @@ def leaf_readout(leaf: dict) -> str:
|
|
|
307
307
|
to — which ALREADY carries the score ("NRMSE 1.531e-01 vs tolerance
|
|
308
308
|
1.000e-02 → FAIL"), so the display beside it said the number twice (the
|
|
309
309
|
first screenshot) — else the display alone. A sentinel's criterion says
|
|
310
|
-
the reason itself ("scalar
|
|
310
|
+
the reason itself ("scalar criterion not scored — …"), so the error is not a
|
|
311
311
|
branch of its own. The trailing verdict is not stripped: `tube` and
|
|
312
312
|
`range` do not end with it ("… → FAIL (requires 0)"), so a strip would
|
|
313
313
|
read the string wrong for half the modes."""
|
|
@@ -9,7 +9,7 @@ anything the last scoring said).
|
|
|
9
9
|
There is no state for edits to the simulation settings (the owner's ruling
|
|
10
10
|
Q2 A drew one): ``/simulation`` is not stageable — `patch_apply`'s default
|
|
11
11
|
whitelist is ``/comparison``, ``/metrics`` and ``/plots``, and widening it
|
|
12
|
-
changes ``spec
|
|
12
|
+
changes ``spec update``, a seam another repository relies on. It waits for
|
|
13
13
|
a simulation-settings editor."""
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
@@ -137,5 +137,5 @@ def refuse_bounds(metric: str, params: Mapping[str, object]) -> None:
|
|
|
137
137
|
if lo == hi and metric in STRICT_BOUNDS:
|
|
138
138
|
raise Refused(
|
|
139
139
|
f"min_value {_num(lo)} equals max_value {_num(hi)}; "
|
|
140
|
-
f"a {metric}
|
|
140
|
+
f"a {metric} criterion needs min_value < max_value"
|
|
141
141
|
)
|
|
@@ -27,7 +27,11 @@ __all__ = [
|
|
|
27
27
|
"resolve_variable_patterns",
|
|
28
28
|
"get_backend",
|
|
29
29
|
"get_backend_class",
|
|
30
|
+
"backend_class",
|
|
31
|
+
"backend_family",
|
|
32
|
+
"backend_names",
|
|
30
33
|
"select_backend",
|
|
34
|
+
"source_types",
|
|
31
35
|
"dataset_kind_for",
|
|
32
36
|
]
|
|
33
37
|
|
|
@@ -117,12 +121,23 @@ def _validate_capabilities(cls: type[Backend], name: str) -> None:
|
|
|
117
121
|
|
|
118
122
|
|
|
119
123
|
def register(name: str):
|
|
120
|
-
"""
|
|
124
|
+
"""Register a backend class under a name: the class decorator a backend
|
|
125
|
+
plug-in is declared with.
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
The name is what ``testing.json``'s ``backend`` and ``backends`` say, and
|
|
128
|
+
what ``--backend`` takes. An entry named ``"<name> 2025"`` is this
|
|
129
|
+
backend's too.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
name: The backend's name.
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
The decorator, which returns the class unchanged.
|
|
136
|
+
|
|
137
|
+
Raises:
|
|
138
|
+
TypeError: At decoration, when the class declares a
|
|
139
|
+
:class:`~dstf.backends.types.Capability` without overriding the
|
|
140
|
+
method it needs.
|
|
126
141
|
"""
|
|
127
142
|
|
|
128
143
|
def decorator(cls: type[Backend]) -> type[Backend]:
|
|
@@ -150,55 +165,89 @@ def get_backend_class(config: Config) -> type[Backend]:
|
|
|
150
165
|
unavailable-backend ``RuntimeError`` an optional dependency's absence
|
|
151
166
|
signals (FmpyBackend.__init__ imports fmpy).
|
|
152
167
|
"""
|
|
153
|
-
|
|
154
|
-
if backend not in _REGISTRY:
|
|
155
|
-
_import_builtin_backend(backend)
|
|
156
|
-
cls = _REGISTRY.get(backend)
|
|
168
|
+
cls = backend_class(config.backend)
|
|
157
169
|
if cls is None:
|
|
158
170
|
available = ", ".join(sorted(_REGISTRY)) or "(none)"
|
|
159
171
|
raise ValueError(
|
|
160
|
-
f"Unsupported backend: {backend} "
|
|
172
|
+
f"Unsupported backend: {config.backend} "
|
|
161
173
|
f"(from '{config.backend_name}'). Available: {available}"
|
|
162
174
|
)
|
|
163
175
|
return cls
|
|
164
176
|
|
|
165
177
|
|
|
178
|
+
def backend_class(name: str) -> type[Backend] | None:
|
|
179
|
+
"""The backend registered under ``name`` — a built-in is imported on
|
|
180
|
+
first use — or None."""
|
|
181
|
+
if name not in _REGISTRY:
|
|
182
|
+
_import_builtin_backend(name)
|
|
183
|
+
return _REGISTRY.get(name)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def backend_names() -> list[str]:
|
|
187
|
+
"""Every backend there is a class for: the built-ins, then what a
|
|
188
|
+
plug-in or a caller registered, in registration order. The order
|
|
189
|
+
``dstf check`` lists them in, and the one a project that names no
|
|
190
|
+
backend is searched in (``Backend.source_types``)."""
|
|
191
|
+
return [*_BUILTINS, *(name for name in _REGISTRY if name not in _BUILTINS)]
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def source_types() -> list[str]:
|
|
195
|
+
"""Every ``source_type`` a project may say: the ones a registered
|
|
196
|
+
backend runs (``Backend.source_types``), in the backends' order — the
|
|
197
|
+
built-ins' ``modelica``, ``fmu``, ``julia``, ``python``, then a
|
|
198
|
+
plug-in's. ``Config`` refuses any other, and the published schema
|
|
199
|
+
lists these."""
|
|
200
|
+
found: dict[str, None] = {}
|
|
201
|
+
for name in backend_names():
|
|
202
|
+
cls = backend_class(name)
|
|
203
|
+
if cls is not None:
|
|
204
|
+
found.update(dict.fromkeys(sorted(cls.source_types)))
|
|
205
|
+
return list(found)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def backend_family(backend_name: str) -> str:
|
|
209
|
+
"""The backend a named entry is of: ``"Dymola 2025"`` is a ``"Dymola"``,
|
|
210
|
+
``"OpenModelica 1.23"`` an ``"OpenModelica"`` — the registered name it
|
|
211
|
+
starts with, the longest where two do. A name that starts with none is
|
|
212
|
+
its own (and no backend, as :func:`get_backend_class` then says)."""
|
|
213
|
+
for name in sorted(backend_names(), key=len, reverse=True):
|
|
214
|
+
if backend_name.startswith(name):
|
|
215
|
+
return name
|
|
216
|
+
return backend_name
|
|
217
|
+
|
|
218
|
+
|
|
166
219
|
class BackendUnavailableError(RuntimeError):
|
|
167
|
-
"""The
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
220
|
+
"""The project's backend cannot be built on this machine: no backend of
|
|
221
|
+
that name is registered, its program was not found, or what it needs is not
|
|
222
|
+
installed. ``str()`` says which, in words true wherever it is shown — the
|
|
223
|
+
command line and `dstf author`'s Queue alike.
|
|
224
|
+
|
|
225
|
+
``batch_runs``: only the variant whose workers stay alive is refused;
|
|
226
|
+
the backend's per-test script mode would run. A caller that offers that
|
|
227
|
+
mode says so in its own words (the CLI's ``--batch``).
|
|
175
228
|
"""
|
|
176
229
|
|
|
230
|
+
def __init__(self, message: str, *, batch_runs: bool = False):
|
|
231
|
+
super().__init__(message)
|
|
232
|
+
self.batch_runs = batch_runs
|
|
177
233
|
|
|
178
|
-
def select_backend(config, *, persistent: bool) -> Backend:
|
|
179
|
-
"""Instantiate the backend for *config*, persistent variant when asked.
|
|
180
234
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
dependency probe and instantiate it. When the probe raises
|
|
184
|
-
:class:`RuntimeError`, raise :class:`BackendUnavailableError` naming
|
|
185
|
-
both fixes (install the dep, or re-run with ``--batch``) — no silent
|
|
186
|
-
fallback.
|
|
235
|
+
def select_backend(config, *, persistent: bool, to_run: bool = False) -> Backend:
|
|
236
|
+
"""Build the backend a project runs with.
|
|
187
237
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
238
|
+
Args:
|
|
239
|
+
config: The project's configuration.
|
|
240
|
+
persistent: Build the variant that keeps the simulator open between
|
|
241
|
+
tests, where the backend has one; ``--batch`` is False.
|
|
242
|
+
to_run: The backend will simulate, not only read results: one that was
|
|
243
|
+
not found on this machine is refused.
|
|
194
244
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
``persistent_backend_cls`` + ``preflight`` on their backend classes.
|
|
245
|
+
Returns:
|
|
246
|
+
The backend.
|
|
198
247
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
248
|
+
Raises:
|
|
249
|
+
BackendUnavailableError: The backend is not registered, not found, or
|
|
250
|
+
cannot be used here; the message says why and what to do.
|
|
202
251
|
"""
|
|
203
252
|
try:
|
|
204
253
|
batch_cls = get_backend_class(config)
|
|
@@ -206,10 +255,17 @@ def select_backend(config, *, persistent: bool) -> Backend:
|
|
|
206
255
|
# An unregistered backend name is a configuration problem, not a
|
|
207
256
|
# bug; same class of failure as a missing executable.
|
|
208
257
|
raise BackendUnavailableError(str(exc)) from exc
|
|
258
|
+
if to_run:
|
|
259
|
+
try:
|
|
260
|
+
batch_cls.require_found(config)
|
|
261
|
+
except RuntimeError as exc:
|
|
262
|
+
raise BackendUnavailableError(str(exc)) from exc
|
|
209
263
|
if not persistent or Capability.PERSISTENT_WORKERS not in batch_cls.capabilities:
|
|
210
264
|
# Batch-only backend (FMPy, Python today). Persistent flag is a
|
|
211
265
|
# no-op rather than an error so a single CLI works across mixed
|
|
212
|
-
# backends in a multi-library config.
|
|
266
|
+
# backends in a multi-library config. A `--batch` WRITTEN for such
|
|
267
|
+
# a backend is another matter, and the CLI's to refuse
|
|
268
|
+
# (`cli.run_cmds._refuse_batch_without_workers`).
|
|
213
269
|
return _instantiate(batch_cls, config)
|
|
214
270
|
pcls = batch_cls.persistent_backend_cls()
|
|
215
271
|
if pcls is None:
|
|
@@ -220,12 +276,8 @@ def select_backend(config, *, persistent: bool) -> Backend:
|
|
|
220
276
|
pcls.preflight(config)
|
|
221
277
|
except RuntimeError as exc:
|
|
222
278
|
raise BackendUnavailableError(
|
|
223
|
-
f"Persistent-worker {config.backend} unavailable.\n"
|
|
224
|
-
|
|
225
|
-
f"{exc}\n"
|
|
226
|
-
f"\n"
|
|
227
|
-
f"Or re-run with `--batch` to use the per-test subprocess "
|
|
228
|
-
f"backend instead."
|
|
279
|
+
f"Persistent-worker {config.backend} unavailable.\n\n{exc}",
|
|
280
|
+
batch_runs=True,
|
|
229
281
|
) from exc
|
|
230
282
|
return _instantiate(pcls, config)
|
|
231
283
|
|
|
@@ -245,16 +297,20 @@ def _instantiate(cls: type[Backend], config) -> Backend:
|
|
|
245
297
|
raise BackendUnavailableError(str(exc)) from exc
|
|
246
298
|
|
|
247
299
|
|
|
300
|
+
#: The built-in backends and the module each registers itself from. Their
|
|
301
|
+
#: order is the order :func:`backend_names` lists them in.
|
|
302
|
+
_BUILTINS = {
|
|
303
|
+
"Dymola": ".dymola",
|
|
304
|
+
"OpenModelica": ".openmodelica",
|
|
305
|
+
"FMPy": ".fmpy",
|
|
306
|
+
"Julia": ".julia",
|
|
307
|
+
"Python": ".python",
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
|
|
248
311
|
def _import_builtin_backend(name: str) -> None:
|
|
249
312
|
"""Import a built-in backend module so it registers itself."""
|
|
250
|
-
|
|
251
|
-
"Dymola": ".dymola",
|
|
252
|
-
"FMPy": ".fmpy",
|
|
253
|
-
"OpenModelica": ".openmodelica",
|
|
254
|
-
"Julia": ".julia",
|
|
255
|
-
"Python": ".python",
|
|
256
|
-
}
|
|
257
|
-
module = builtins.get(name)
|
|
313
|
+
module = _BUILTINS.get(name)
|
|
258
314
|
if module:
|
|
259
315
|
import importlib
|
|
260
316
|
|