statable 3.2.1__tar.gz → 3.2.2__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.
- {statable-3.2.1 → statable-3.2.2}/PKG-INFO +1 -1
- {statable-3.2.1 → statable-3.2.2}/codegen/__init__.py +1 -1
- {statable-3.2.1 → statable-3.2.2}/pyproject.toml +1 -1
- {statable-3.2.1 → statable-3.2.2}/statable/__init__.py +1 -1
- {statable-3.2.1 → statable-3.2.2}/statable/cli.py +1 -1
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/PKG-INFO +1 -1
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/SOURCES.txt +2 -1
- {statable-3.2.1 → statable-3.2.2}/statable_gui/main_window.py +2 -1
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_0_s1_packaging.py +9 -9
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_0_s2_public_api.py +4 -4
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_0_s3_cli.py +4 -4
- statable-3.2.2/tests/test_v3_2_s2_signals.py +144 -0
- {statable-3.2.1 → statable-3.2.2}/README.md +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/c_code_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/code_merger.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/code_templates.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/config.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/enum_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/event_queue_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/interrupt_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/naming_convention.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/osal_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/role_function_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/sample_data.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/state_actions_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/struct_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/timer_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/transition_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/type_mapper.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/change_actions.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/change_applier.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/clipboard_manager.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/data/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/data/action_definitions.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/data/keywords.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/data/prompt_templates.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/data/validation_rules.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/base_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/cell_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/custom_type_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/event_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/flag_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/interrupt_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/queue_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/role_function_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/state_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/timer_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/transition_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/items/variable_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/logger.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/models.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/prompt_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/response_parser.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/response_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/validation_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/validate/validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/codegen/variable_generator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/setup.cfg +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/__main__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/global_defs.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/mermaid_gen.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/model.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/parser.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/sample_data.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/shared/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/shared/condition_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/shared/literal_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/shared/role_function_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/state_machine.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable/xml_io.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/dependency_links.txt +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/entry_points.txt +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/requires.txt +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable.egg-info/top_level.txt +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/action_edit_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/code_generation_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/code_generation_settings_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/common_widgets.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/condition_builder_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/condition_edit_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/condition_template_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/config.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/dialogs.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/event_definition_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/event_delivery_settings_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/event_queue_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/global_defs.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/global_defs_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/i18n/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/interrupt_handler_edit_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/layer_settings_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/condition_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/literal_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/literal_management_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/role_function_edit_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/libcntrl/role_function_library.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/literal_definition_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/logger.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/matrix_table.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/new_project_templates.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/new_project_wizard.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/preference_keys.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/preferences.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/role_function_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/sample_data.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/state_actions_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/symbol_picker.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/traceball.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/__init__.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/actions_tab.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/code_widget.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/coverage_analyzer.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/draft.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/edit_dialogs.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/overview_tab.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/palette_widget.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/relations_edit_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/relations_tab.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/system_global_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/transition_actions_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/transitions_tab.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/validation_dialog.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/statable_gui/widgets.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_readme_consistency.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p1.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_10.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_2.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_5.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_6.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_7.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_8.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p12_9.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p2.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p3.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p4a.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_2_p4b.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_3_p1.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_4_p1_merge.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p1.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p10.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p11.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p2.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p3.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p4.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p5.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p6.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p8.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_5_p9.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_6_p1.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_6_p2.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_6_p3.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_7_p3.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_7_p4.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_7_p5_validation.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_8_p1_ai_prompt.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_8_p2_response_parser.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_8_p3_response_validator.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v2_8_p4_gui_integration.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_0_g1_shared.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_0_s4_docs.py +0 -0
- {statable-3.2.1 → statable-3.2.2}/tests/test_v3_2_s1_wizard.py +0 -0
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "statable"
|
|
9
|
-
version = "3.2.
|
|
9
|
+
version = "3.2.2"
|
|
10
10
|
description = "MISRA C:2012-aware state machine design and C code generation for embedded systems"
|
|
11
11
|
readme = "README.md"
|
|
12
12
|
requires-python = ">=3.10"
|
|
@@ -334,7 +334,8 @@ class MainWindow(QMainWindow):
|
|
|
334
334
|
|
|
335
335
|
open_btn = QAction(self.tr("Open"), self)
|
|
336
336
|
open_btn.setToolTip(self.tr("Open project"))
|
|
337
|
-
|
|
337
|
+
# [v3.2.2 fix] lambda: avoid passing triggered(bool) as filepath
|
|
338
|
+
open_btn.triggered.connect(lambda: self.open_project())
|
|
338
339
|
toolbar.addAction(open_btn)
|
|
339
340
|
|
|
340
341
|
save_btn = QAction(self.tr("Save"), self)
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Phase S-1 (v3.0) tests: packaging foundation.
|
|
4
4
|
|
|
5
5
|
Verifies:
|
|
6
|
-
- code/pyproject.toml exists and declares statable/3.2.
|
|
6
|
+
- code/pyproject.toml exists and declares statable/3.2.2
|
|
7
7
|
- statable-cli entry point is defined
|
|
8
8
|
- extras: gui / dev
|
|
9
|
-
- statable.__version__ == "3.2.
|
|
10
|
-
- codegen.__version__ == "3.2.
|
|
9
|
+
- statable.__version__ == "3.2.2"
|
|
10
|
+
- codegen.__version__ == "3.2.2"
|
|
11
11
|
"""
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
@@ -64,8 +64,8 @@ def main() -> int:
|
|
|
64
64
|
check("project.name == 'statable'",
|
|
65
65
|
project.get("name") == "statable",
|
|
66
66
|
f"got: {project.get('name')!r}")
|
|
67
|
-
check("project.version == '3.2.
|
|
68
|
-
project.get("version") == "3.2.
|
|
67
|
+
check("project.version == '3.2.2'",
|
|
68
|
+
project.get("version") == "3.2.2",
|
|
69
69
|
f"got: {project.get('version')!r}")
|
|
70
70
|
|
|
71
71
|
# --- T4: requires-python ---------------------------------------
|
|
@@ -101,16 +101,16 @@ def main() -> int:
|
|
|
101
101
|
# --- T8: runtime __version__ -----------------------------------
|
|
102
102
|
try:
|
|
103
103
|
import statable
|
|
104
|
-
check("statable.__version__ == '3.2.
|
|
105
|
-
getattr(statable, "__version__", None) == "3.2.
|
|
104
|
+
check("statable.__version__ == '3.2.2'",
|
|
105
|
+
getattr(statable, "__version__", None) == "3.2.2",
|
|
106
106
|
f"got: {getattr(statable, '__version__', None)!r}")
|
|
107
107
|
except Exception as e:
|
|
108
108
|
check("statable importable", False, repr(e))
|
|
109
109
|
|
|
110
110
|
try:
|
|
111
111
|
import codegen
|
|
112
|
-
check("codegen.__version__ == '3.2.
|
|
113
|
-
getattr(codegen, "__version__", None) == "3.2.
|
|
112
|
+
check("codegen.__version__ == '3.2.2'",
|
|
113
|
+
getattr(codegen, "__version__", None) == "3.2.2",
|
|
114
114
|
f"got: {getattr(codegen, '__version__', None)!r}")
|
|
115
115
|
except Exception as e:
|
|
116
116
|
check("codegen importable", False, repr(e))
|
|
@@ -47,8 +47,8 @@ def main() -> int:
|
|
|
47
47
|
_summary()
|
|
48
48
|
return 1
|
|
49
49
|
|
|
50
|
-
check("statable has __version__ == '3.2.
|
|
51
|
-
getattr(statable, "__version__", None) == "3.2.
|
|
50
|
+
check("statable has __version__ == '3.2.2'",
|
|
51
|
+
getattr(statable, "__version__", None) == "3.2.2",
|
|
52
52
|
f"got: {getattr(statable, '__version__', None)!r}")
|
|
53
53
|
check("'__version__' in statable.__all__",
|
|
54
54
|
"__version__" in statable.__all__,
|
|
@@ -69,8 +69,8 @@ def main() -> int:
|
|
|
69
69
|
_summary()
|
|
70
70
|
return 1
|
|
71
71
|
|
|
72
|
-
check("codegen has __version__ == '3.2.
|
|
73
|
-
getattr(codegen, "__version__", None) == "3.2.
|
|
72
|
+
check("codegen has __version__ == '3.2.2'",
|
|
73
|
+
getattr(codegen, "__version__", None) == "3.2.2",
|
|
74
74
|
f"got: {getattr(codegen, '__version__', None)!r}")
|
|
75
75
|
check("'validate' in codegen.__all__",
|
|
76
76
|
"validate" in codegen.__all__,
|
|
@@ -60,8 +60,8 @@ def main() -> int:
|
|
|
60
60
|
try:
|
|
61
61
|
from statable import cli
|
|
62
62
|
check("statable.cli importable", True)
|
|
63
|
-
check("CLI_VERSION == '3.2.
|
|
64
|
-
cli.CLI_VERSION == "3.2.
|
|
63
|
+
check("CLI_VERSION == '3.2.2'",
|
|
64
|
+
cli.CLI_VERSION == "3.2.2",
|
|
65
65
|
f"got: {cli.CLI_VERSION!r}")
|
|
66
66
|
except Exception as e:
|
|
67
67
|
check("statable.cli importable", False, repr(e))
|
|
@@ -91,8 +91,8 @@ def main() -> int:
|
|
|
91
91
|
# --- T3: version --------------------------------------------------
|
|
92
92
|
rc, out, _ = run_cli(["version"])
|
|
93
93
|
check("version: exit 0", rc == 0, f"rc={rc}")
|
|
94
|
-
check("version: prints 'statable-cli 3.2.
|
|
95
|
-
"statable-cli 3.2.
|
|
94
|
+
check("version: prints 'statable-cli 3.2.2'",
|
|
95
|
+
"statable-cli 3.2.2" in out,
|
|
96
96
|
f"out={out!r}")
|
|
97
97
|
|
|
98
98
|
# --- T4: validate on real XML (json) ------------------------------
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# tests/test_v3_2_s2_signals.py
|
|
2
|
+
"""Test Qt signal-slot safety (v3.2.2).
|
|
3
|
+
|
|
4
|
+
Regression test for the v3.2.0 bug where `open_project(filepath=None)`
|
|
5
|
+
received Qt's `triggered(bool)` argument, resulting in
|
|
6
|
+
`project_from_xml(False)` and a hang on `open(False, "rb")`.
|
|
7
|
+
|
|
8
|
+
Key insight: PySide6 auto-truncates args for slots with fixed signatures,
|
|
9
|
+
so most `triggered.connect(self.slot)` are safe. The bug only occurs
|
|
10
|
+
when the slot has an OPTIONAL parameter that receives the bool.
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
import re
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
|
|
20
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def main():
|
|
24
|
+
passed = 0
|
|
25
|
+
failed = 0
|
|
26
|
+
|
|
27
|
+
def check(name, cond):
|
|
28
|
+
nonlocal passed, failed
|
|
29
|
+
if cond:
|
|
30
|
+
passed += 1
|
|
31
|
+
print(f"[PASS] {name}")
|
|
32
|
+
else:
|
|
33
|
+
failed += 1
|
|
34
|
+
print(f"[FAIL] {name}")
|
|
35
|
+
|
|
36
|
+
# ================================================================
|
|
37
|
+
# T1: open_project normalizes bool arguments
|
|
38
|
+
# ================================================================
|
|
39
|
+
print("=" * 70)
|
|
40
|
+
print(" T1: open_project(bool) normalization")
|
|
41
|
+
print("=" * 70)
|
|
42
|
+
|
|
43
|
+
try:
|
|
44
|
+
from PySide6.QtWidgets import QApplication
|
|
45
|
+
app = QApplication.instance() or QApplication(sys.argv)
|
|
46
|
+
|
|
47
|
+
from statable_gui.main_window import MainWindow
|
|
48
|
+
|
|
49
|
+
win = MainWindow()
|
|
50
|
+
|
|
51
|
+
import statable_gui.main_window as mw_mod
|
|
52
|
+
original_pfx = mw_mod.project_from_xml
|
|
53
|
+
called_with = []
|
|
54
|
+
|
|
55
|
+
def fake_pfx(path):
|
|
56
|
+
called_with.append(path)
|
|
57
|
+
raise RuntimeError("TEST_STOP")
|
|
58
|
+
|
|
59
|
+
mw_mod.project_from_xml = fake_pfx
|
|
60
|
+
|
|
61
|
+
from PySide6.QtWidgets import QFileDialog
|
|
62
|
+
original_dialog = QFileDialog.getOpenFileName
|
|
63
|
+
QFileDialog.getOpenFileName = staticmethod(lambda *a, **k: ("", ""))
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
win.open_project(False)
|
|
67
|
+
check("open_project(False) does not hang", True)
|
|
68
|
+
except Exception as e:
|
|
69
|
+
check(f"open_project(False) raised: {e}", False)
|
|
70
|
+
|
|
71
|
+
check("project_from_xml not called with False",
|
|
72
|
+
False not in called_with)
|
|
73
|
+
|
|
74
|
+
called_with.clear()
|
|
75
|
+
try:
|
|
76
|
+
win.open_project(True)
|
|
77
|
+
check("open_project(True) does not hang", True)
|
|
78
|
+
except Exception as e:
|
|
79
|
+
check(f"open_project(True) raised: {e}", False)
|
|
80
|
+
check("project_from_xml not called with True",
|
|
81
|
+
True not in called_with)
|
|
82
|
+
|
|
83
|
+
mw_mod.project_from_xml = original_pfx
|
|
84
|
+
QFileDialog.getOpenFileName = original_dialog
|
|
85
|
+
|
|
86
|
+
except Exception as e:
|
|
87
|
+
import traceback
|
|
88
|
+
print(traceback.format_exc())
|
|
89
|
+
check(f"T1 setup failed: {e}", False)
|
|
90
|
+
|
|
91
|
+
# ================================================================
|
|
92
|
+
# T2: open_project is connected via lambda (the actual bug)
|
|
93
|
+
# ================================================================
|
|
94
|
+
print()
|
|
95
|
+
print("=" * 70)
|
|
96
|
+
print(" T2: open_project is lambda-wrapped")
|
|
97
|
+
print("=" * 70)
|
|
98
|
+
|
|
99
|
+
mw_path = Path(__file__).parent.parent / "statable_gui" / "main_window.py"
|
|
100
|
+
src = mw_path.read_text(encoding="utf-8")
|
|
101
|
+
|
|
102
|
+
# The bug: `triggered.connect(self.open_project)` without lambda
|
|
103
|
+
# would pass triggered(bool) as filepath.
|
|
104
|
+
# FIX: must use `triggered.connect(lambda: self.open_project())`
|
|
105
|
+
bug_pattern = re.compile(
|
|
106
|
+
r'triggered\.connect\(\s*self\.open_project\s*\)'
|
|
107
|
+
)
|
|
108
|
+
check("open_project not connected without lambda",
|
|
109
|
+
not bug_pattern.search(src))
|
|
110
|
+
|
|
111
|
+
fix_pattern = re.compile(
|
|
112
|
+
r'triggered\.connect\(\s*lambda\s*:\s*self\.open_project\(\)\s*\)'
|
|
113
|
+
)
|
|
114
|
+
check("open_project connected via lambda",
|
|
115
|
+
bool(fix_pattern.search(src)))
|
|
116
|
+
|
|
117
|
+
# ================================================================
|
|
118
|
+
# T3: open_project has bool guard in body
|
|
119
|
+
# ================================================================
|
|
120
|
+
print()
|
|
121
|
+
print("=" * 70)
|
|
122
|
+
print(" T3: open_project has bool normalization guard")
|
|
123
|
+
print("=" * 70)
|
|
124
|
+
|
|
125
|
+
check("open_project has isinstance(filepath, bool) guard",
|
|
126
|
+
"isinstance(filepath, bool)" in src)
|
|
127
|
+
|
|
128
|
+
# Verify that the signature accepts Optional[str]
|
|
129
|
+
check("open_project signature has filepath parameter",
|
|
130
|
+
re.search(r'def open_project\(self,\s*filepath', src) is not None)
|
|
131
|
+
|
|
132
|
+
# ================================================================
|
|
133
|
+
# Summary
|
|
134
|
+
# ================================================================
|
|
135
|
+
print()
|
|
136
|
+
print("=" * 70)
|
|
137
|
+
print(f" TOTAL: {passed + failed} PASSED: {passed} FAILED: {failed}")
|
|
138
|
+
print("=" * 70)
|
|
139
|
+
|
|
140
|
+
return 0 if failed == 0 else 1
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
if __name__ == "__main__":
|
|
144
|
+
sys.exit(main())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/coverage_analyzer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/relations_edit_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
{statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/system_global_dialog.py
RENAMED
|
File without changes
|
{statable-3.2.1 → statable-3.2.2}/statable_gui/transition_editor_direct/transition_actions_dialog.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|