dynamic-systems-testing-framework 1.0.1__py3-none-any.whl
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.
- dstf/__init__.py +41 -0
- dstf/__main__.py +10 -0
- dstf/authoring/__init__.py +13 -0
- dstf/authoring/builtin/__init__.py +32 -0
- dstf/authoring/builtin/accept.py +205 -0
- dstf/authoring/builtin/edit_criteria.py +479 -0
- dstf/authoring/builtin/edit_family.py +228 -0
- dstf/authoring/builtin/edit_on_plot.py +1354 -0
- dstf/authoring/builtin/edit_tree.py +1399 -0
- dstf/authoring/builtin/enqueue.py +144 -0
- dstf/authoring/capabilities.py +463 -0
- dstf/authoring/errors.py +49 -0
- dstf/authoring/family_rows.py +526 -0
- dstf/authoring/forms.py +631 -0
- dstf/authoring/layout.py +104 -0
- dstf/authoring/live_rows.py +337 -0
- dstf/authoring/live_runs.py +385 -0
- dstf/authoring/needle.py +127 -0
- dstf/authoring/picker_rows.py +92 -0
- dstf/authoring/queue_rows.py +354 -0
- dstf/authoring/session.py +3016 -0
- dstf/authoring/shell/__init__.py +9 -0
- dstf/authoring/shell/actions.py +702 -0
- dstf/authoring/shell/app.py +53 -0
- dstf/authoring/shell/drawer_controls.py +190 -0
- dstf/authoring/shell/family_fold.py +468 -0
- dstf/authoring/shell/figure_hook.py +249 -0
- dstf/authoring/shell/grips.js +1000 -0
- dstf/authoring/shell/header.py +783 -0
- dstf/authoring/shell/live_view.py +93 -0
- dstf/authoring/shell/picker.py +267 -0
- dstf/authoring/shell/placing.py +122 -0
- dstf/authoring/shell/plot_card.py +1171 -0
- dstf/authoring/shell/queue_panel.py +433 -0
- dstf/authoring/shell/rail.py +593 -0
- dstf/authoring/shell/shell.py +528 -0
- dstf/authoring/shell/stats_card.py +501 -0
- dstf/authoring/shell/strip.py +204 -0
- dstf/authoring/shell/style.py +721 -0
- dstf/authoring/shell/suite.py +277 -0
- dstf/authoring/shell/suite_grid.js +414 -0
- dstf/authoring/shell/suite_grid.py +373 -0
- dstf/authoring/shell/tab_theme.py +110 -0
- dstf/authoring/shell/tabstate.py +146 -0
- dstf/authoring/shell/test_list.py +179 -0
- dstf/authoring/shell/test_page.py +1404 -0
- dstf/authoring/shell/tree_card.py +1171 -0
- dstf/authoring/shell/variables_drawer.py +589 -0
- dstf/authoring/shell/widgets.py +188 -0
- dstf/authoring/situation.py +287 -0
- dstf/authoring/spec_document.py +215 -0
- dstf/authoring/spec_preview.py +83 -0
- dstf/authoring/suite_rows.py +99 -0
- dstf/authoring/tree_move.py +516 -0
- dstf/authoring/tree_pointer.py +33 -0
- dstf/authoring/tree_text.py +61 -0
- dstf/authoring/typed_number.js +64 -0
- dstf/authoring/typed_number.py +76 -0
- dstf/authoring/unscorable.py +141 -0
- dstf/authoring/variable_rows.py +216 -0
- dstf/backends/__init__.py +283 -0
- dstf/backends/base.py +1117 -0
- dstf/backends/common/__init__.py +1 -0
- dstf/backends/common/json_driver.py +484 -0
- dstf/backends/common/live_mat.py +369 -0
- dstf/backends/common/mat_reader.py +632 -0
- dstf/backends/common/proc_kill.py +238 -0
- dstf/backends/common/proc_output.py +20 -0
- dstf/backends/common/result_files.py +109 -0
- dstf/backends/common/result_variables.py +329 -0
- dstf/backends/common/statistics.py +39 -0
- dstf/backends/cross_backend.py +193 -0
- dstf/backends/dymola/__init__.py +5 -0
- dstf/backends/dymola/backend.py +776 -0
- dstf/backends/dymola/interface_loader.py +241 -0
- dstf/backends/dymola/log_parser.py +396 -0
- dstf/backends/dymola/persistent_backend.py +949 -0
- dstf/backends/fmpy/__init__.py +11 -0
- dstf/backends/fmpy/backend.py +443 -0
- dstf/backends/julia/__init__.py +27 -0
- dstf/backends/julia/backend.py +156 -0
- dstf/backends/julia/persistent_backend.py +541 -0
- dstf/backends/julia/run_persistent.jl +167 -0
- dstf/backends/julia/run_test.jl +146 -0
- dstf/backends/openmodelica/__init__.py +21 -0
- dstf/backends/openmodelica/backend.py +368 -0
- dstf/backends/openmodelica/init_xml.py +76 -0
- dstf/backends/openmodelica/log_parser.py +119 -0
- dstf/backends/openmodelica/mos_generator.py +228 -0
- dstf/backends/openmodelica/persistent_backend.py +1045 -0
- dstf/backends/openmodelica/session_loader.py +63 -0
- dstf/backends/persistent.py +1811 -0
- dstf/backends/pool.py +602 -0
- dstf/backends/progress.py +395 -0
- dstf/backends/python/__init__.py +11 -0
- dstf/backends/python/backend.py +141 -0
- dstf/backends/python/run_test.py +141 -0
- dstf/backends/run_metadata.py +103 -0
- dstf/backends/types.py +310 -0
- dstf/cli/__init__.py +12 -0
- dstf/cli/author_cmd.py +61 -0
- dstf/cli/baseline_cmds.py +341 -0
- dstf/cli/common.py +231 -0
- dstf/cli/diag_cmds.py +350 -0
- dstf/cli/main.py +561 -0
- dstf/cli/review.py +398 -0
- dstf/cli/run_cmds.py +589 -0
- dstf/cli/spec_cmds.py +123 -0
- dstf/comparison/__init__.py +13 -0
- dstf/comparison/algorithms.py +2127 -0
- dstf/comparison/builtins.py +291 -0
- dstf/comparison/comparator.py +1189 -0
- dstf/comparison/geometry.py +164 -0
- dstf/comparison/handles.py +1194 -0
- dstf/comparison/metric_tree.py +332 -0
- dstf/comparison/mode_schema.py +176 -0
- dstf/comparison/modes.py +788 -0
- dstf/comparison/registry.py +230 -0
- dstf/comparison/seeds.py +281 -0
- dstf/comparison/sides.py +158 -0
- dstf/comparison/snap.py +62 -0
- dstf/comparison/strict_keys.py +246 -0
- dstf/comparison/summaries.py +354 -0
- dstf/comparison/tree_eval.py +868 -0
- dstf/comparison/tree_spec.py +678 -0
- dstf/comparison/types.py +194 -0
- dstf/comparison/validator.py +232 -0
- dstf/config.py +815 -0
- dstf/discovery/__init__.py +0 -0
- dstf/discovery/json_recognizer.py +702 -0
- dstf/discovery/library_state.py +248 -0
- dstf/discovery/mo_parser.py +794 -0
- dstf/discovery/patch_apply.py +308 -0
- dstf/discovery/patch_envelope.py +63 -0
- dstf/discovery/plots.py +318 -0
- dstf/discovery/recognizer.py +103 -0
- dstf/discovery/scan_cache.py +154 -0
- dstf/discovery/spec_parser.py +538 -0
- dstf/discovery/spec_shape.py +122 -0
- dstf/discovery/spec_update.py +493 -0
- dstf/discovery/test_registry.py +488 -0
- dstf/discovery/unit_tests.py +95 -0
- dstf/figures/__init__.py +14 -0
- dstf/figures/assemble.py +48 -0
- dstf/figures/decimate.py +150 -0
- dstf/figures/families.py +289 -0
- dstf/figures/palette.py +170 -0
- dstf/figures/plotly.py +1413 -0
- dstf/figures/view.py +233 -0
- dstf/pipeline.py +435 -0
- dstf/plugins.py +104 -0
- dstf/reporting/__init__.py +0 -0
- dstf/reporting/console_report.py +187 -0
- dstf/reporting/context_builder.py +979 -0
- dstf/reporting/dashboard_render.py +534 -0
- dstf/reporting/junit_report.py +192 -0
- dstf/reporting/overlay_loader.py +708 -0
- dstf/reporting/report_suite.py +1059 -0
- dstf/reporting/rows.py +458 -0
- dstf/reporting/schema_export.py +413 -0
- dstf/reporting/stats_rows.py +321 -0
- dstf/reporting/status.py +388 -0
- dstf/reporting/templates/axes.js +61 -0
- dstf/reporting/templates/dashboard.html +284 -0
- dstf/reporting/templates/dashboard.js +604 -0
- dstf/reporting/templates/filters.js +100 -0
- dstf/reporting/templates/interactive.html +420 -0
- dstf/reporting/templates/report.js +116 -0
- dstf/reporting/templates/vendor/plotly.min.js +8 -0
- dstf/reporting/theme.py +324 -0
- dstf/reporting/tree_rows.py +73 -0
- dstf/reporting/verdicts.py +124 -0
- dstf/storage/__init__.py +0 -0
- dstf/storage/accept.py +216 -0
- dstf/storage/baseline.py +43 -0
- dstf/storage/batch_manifest.py +204 -0
- dstf/storage/ref_index.py +295 -0
- dstf/storage/reference_store.py +661 -0
- dstf/storage/roles.py +576 -0
- dstf/storage/run_stats.py +85 -0
- dynamic_systems_testing_framework-1.0.1.dist-info/METADATA +266 -0
- dynamic_systems_testing_framework-1.0.1.dist-info/RECORD +185 -0
- dynamic_systems_testing_framework-1.0.1.dist-info/WHEEL +4 -0
- dynamic_systems_testing_framework-1.0.1.dist-info/entry_points.txt +2 -0
- dynamic_systems_testing_framework-1.0.1.dist-info/licenses/LICENSE +21 -0
dstf/cli/spec_cmds.py
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Commands that write or describe `test_spec.json`: add, spec-update,
|
|
2
|
+
export-schema."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .common import _build_config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def cmd_add(args: argparse.Namespace) -> int:
|
|
12
|
+
"""Add a test to test_spec.json."""
|
|
13
|
+
config = _build_config(args)
|
|
14
|
+
model_id = args.model_id
|
|
15
|
+
variables = args.variables or []
|
|
16
|
+
|
|
17
|
+
from ..discovery.spec_parser import add_to_test_spec
|
|
18
|
+
|
|
19
|
+
# Determine spec file location
|
|
20
|
+
spec_path = config.spec_path
|
|
21
|
+
|
|
22
|
+
added = add_to_test_spec(spec_path, model_id, variables)
|
|
23
|
+
if added:
|
|
24
|
+
var_desc = ", ".join(variables) if variables else "(simulate only)"
|
|
25
|
+
print(f"Added: {model_id}")
|
|
26
|
+
print(f" Variables: {var_desc}")
|
|
27
|
+
print(f" Spec file: {spec_path}")
|
|
28
|
+
return 0
|
|
29
|
+
else:
|
|
30
|
+
# Already exists — prompt to overwrite
|
|
31
|
+
try:
|
|
32
|
+
choice = (
|
|
33
|
+
input(f" {model_id} already exists in spec. Overwrite? [y/n] > ")
|
|
34
|
+
.strip()
|
|
35
|
+
.lower()
|
|
36
|
+
)
|
|
37
|
+
except (EOFError, KeyboardInterrupt):
|
|
38
|
+
print("\nAborted.")
|
|
39
|
+
return 1
|
|
40
|
+
if choice == "y":
|
|
41
|
+
add_to_test_spec(spec_path, model_id, variables, overwrite=True)
|
|
42
|
+
print(f"Updated: {model_id}")
|
|
43
|
+
return 0
|
|
44
|
+
else:
|
|
45
|
+
print("Skipped.")
|
|
46
|
+
return 0
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def cmd_spec_update(args: argparse.Namespace) -> int:
|
|
50
|
+
"""Update test_spec.json from an RFC 6902 patch envelope (6.4.3).
|
|
51
|
+
|
|
52
|
+
The envelope is the only accepted input shape: the multi-model form the
|
|
53
|
+
authoring tool exports, or the single-model form older files carry.
|
|
54
|
+
"""
|
|
55
|
+
import json as json_mod
|
|
56
|
+
|
|
57
|
+
config = _build_config(args)
|
|
58
|
+
spec_path = config.spec_path
|
|
59
|
+
|
|
60
|
+
json_file = Path(args.json_file)
|
|
61
|
+
if not json_file.exists():
|
|
62
|
+
print(f"File not found: {json_file}")
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
update_data = json_mod.loads(json_file.read_text(encoding="utf-8"))
|
|
67
|
+
except (json_mod.JSONDecodeError, OSError) as e:
|
|
68
|
+
print(f"Failed to read {json_file}: {e}")
|
|
69
|
+
return 1
|
|
70
|
+
|
|
71
|
+
from ..discovery.patch_apply import PatchError
|
|
72
|
+
from ..discovery.patch_envelope import parse_envelope
|
|
73
|
+
from ..discovery.spec_update import apply_validated_patches
|
|
74
|
+
|
|
75
|
+
groups = parse_envelope(update_data, label=str(json_file))
|
|
76
|
+
requested = [(g.model_id, g.ops) for g in groups]
|
|
77
|
+
if not requested:
|
|
78
|
+
print(f"Nothing to apply: {json_file} carries no patches")
|
|
79
|
+
return 0
|
|
80
|
+
try:
|
|
81
|
+
applied = apply_validated_patches(spec_path, requested, config)
|
|
82
|
+
except PatchError as e:
|
|
83
|
+
print(f"Patch failed: {e}")
|
|
84
|
+
return 1
|
|
85
|
+
_print_applied(applied, requested, spec_path)
|
|
86
|
+
return 0
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _print_applied(applied, requested, spec_path) -> None:
|
|
90
|
+
"""One block per model: the materialization note when the applied ops
|
|
91
|
+
outgrew the requested ones, then the requested ops."""
|
|
92
|
+
for (model_id, full), (_, ops) in zip(applied, requested):
|
|
93
|
+
if len(full) > len(ops):
|
|
94
|
+
# The implicit tree is an `and` of one leaf per criterion the
|
|
95
|
+
# flat path scored: counted as what every other surface calls
|
|
96
|
+
# them, and in the number's own noun (it read `(1 leaves)`).
|
|
97
|
+
n = len(full[0]["value"]["children"])
|
|
98
|
+
print(
|
|
99
|
+
f"Note: materialized implicit metrics tree for {model_id} "
|
|
100
|
+
f"({n} {'criterion' if n == 1 else 'criteria'}) — entry had no "
|
|
101
|
+
"'metrics' block"
|
|
102
|
+
)
|
|
103
|
+
print(f"Applied {len(ops)} op(s) to {model_id} → {spec_path}")
|
|
104
|
+
for op in ops:
|
|
105
|
+
print(f" {op.get('op'):<8} {op.get('path'):<60} {op.get('value', '')}")
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def cmd_export_schema(args: argparse.Namespace) -> int:
|
|
109
|
+
"""Emit a JSON-Schema document describing ``test_spec.json`` (6.4.5)."""
|
|
110
|
+
import json as json_mod
|
|
111
|
+
|
|
112
|
+
from ..reporting.schema_export import build_schema
|
|
113
|
+
|
|
114
|
+
schema = build_schema()
|
|
115
|
+
text = json_mod.dumps(schema, indent=2) + "\n"
|
|
116
|
+
out = getattr(args, "output", None)
|
|
117
|
+
if out:
|
|
118
|
+
# LF on every platform — the schema gets committed.
|
|
119
|
+
Path(out).write_text(text, encoding="utf-8", newline="\n")
|
|
120
|
+
print(f"Wrote schema to {out}")
|
|
121
|
+
else:
|
|
122
|
+
sys.stdout.write(text)
|
|
123
|
+
return 0
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Comparison layer: metrics, MetricTrees, and the registries behind both.
|
|
2
|
+
|
|
3
|
+
Importing this package registers the built-in metrics and combinators, so
|
|
4
|
+
``registry.metric(...)`` / ``registry.combinator(...)`` resolve before any
|
|
5
|
+
spec is parsed. Third-party metrics register the same way (see
|
|
6
|
+
docs/extensibility.md).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from .builtins import register_builtins
|
|
12
|
+
|
|
13
|
+
register_builtins()
|